From a7d6d462462f1e83cac532cae4a95e95ec29c2d6 Mon Sep 17 00:00:00 2001 From: chelseahao Date: Tue, 19 Nov 2024 16:24:39 +0800 Subject: [PATCH] Part 1 of `use bluetooth` toggle catalyst migration. Test: atest Bug: 372774767 Flag: com.android.settings.flags.catalyst Test: atest Change-Id: Ic4be881ead92c6d56412ea3210bc5890e7f1695b --- .../BluetoothMainSwitchPreference.kt | 99 +++++++++++++++++++ .../BluetoothDashboardScreenTest.kt | 2 + .../BluetoothMainSwitchPreferenceTest.kt | 80 +++++++++++++++ 3 files changed, 181 insertions(+) create mode 100644 src/com/android/settings/connecteddevice/BluetoothMainSwitchPreference.kt create mode 100644 tests/robotests/src/com/android/settings/connecteddevice/BluetoothMainSwitchPreferenceTest.kt diff --git a/src/com/android/settings/connecteddevice/BluetoothMainSwitchPreference.kt b/src/com/android/settings/connecteddevice/BluetoothMainSwitchPreference.kt new file mode 100644 index 00000000000..bf806531135 --- /dev/null +++ b/src/com/android/settings/connecteddevice/BluetoothMainSwitchPreference.kt @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.connecteddevice + +import android.bluetooth.BluetoothAdapter +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import com.android.settings.R +import com.android.settings.widget.MainSwitchBarMetadata +import com.android.settingslib.datastore.KeyValueStore +import com.android.settingslib.datastore.NoOpKeyedObservable +import com.android.settingslib.metadata.PreferenceLifecycleContext +import com.android.settingslib.metadata.PreferenceLifecycleProvider +import com.android.settingslib.metadata.ReadWritePermit + +class BluetoothMainSwitchPreference(private val bluetoothAdapter: BluetoothAdapter?) : + MainSwitchBarMetadata, PreferenceLifecycleProvider { + + private lateinit var broadcastReceiver: BroadcastReceiver + + override val key + get() = "use_bluetooth" + + override val title + get() = R.string.bluetooth_main_switch_title + + override fun getReadPermit(context: Context, myUid: Int, callingUid: Int) = + ReadWritePermit.ALLOW + + override fun getWritePermit(context: Context, value: Boolean?, myUid: Int, callingUid: Int) = + ReadWritePermit.ALLOW + + override fun storage(context: Context) = BluetoothStateStore(bluetoothAdapter) + + override fun onStart(context: PreferenceLifecycleContext) { + broadcastReceiver = + object : BroadcastReceiver() { + override fun onReceive(receiverContext: Context, intent: Intent) { + context.notifyPreferenceChange(key) + } + } + context.registerReceiver( + broadcastReceiver, + IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED), + Context.RECEIVER_EXPORTED_UNAUDITED + ) + } + + override fun onStop(context: PreferenceLifecycleContext) { + if (::broadcastReceiver.isInitialized) { + context.unregisterReceiver(broadcastReceiver) + } + } + + override fun isEnabled(context: Context): Boolean { + return bluetoothAdapter?.state.let { + it == BluetoothAdapter.STATE_ON || it == BluetoothAdapter.STATE_OFF + } + } + + @Suppress("UNCHECKED_CAST") + class BluetoothStateStore(private val bluetoothAdapter: BluetoothAdapter?) : + NoOpKeyedObservable(), KeyValueStore { + + override fun contains(key: String) = true + + override fun getValue(key: String, valueType: Class): T? { + return (bluetoothAdapter?.state.let { + it == BluetoothAdapter.STATE_ON || it == BluetoothAdapter.STATE_TURNING_ON + }) as T + } + + override fun setValue(key: String, valueType: Class, value: T?) { + if (value is Boolean) { + if (value) { + bluetoothAdapter?.enable() + } else { + bluetoothAdapter?.disable() + } + } + } + } +} diff --git a/tests/robotests/src/com/android/settings/connecteddevice/BluetoothDashboardScreenTest.kt b/tests/robotests/src/com/android/settings/connecteddevice/BluetoothDashboardScreenTest.kt index 16db8413fa7..9b6e2296bf4 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/BluetoothDashboardScreenTest.kt +++ b/tests/robotests/src/com/android/settings/connecteddevice/BluetoothDashboardScreenTest.kt @@ -39,6 +39,8 @@ class BluetoothDashboardScreenTest : CatalystScreenTestCase() { assertThat(preferenceScreenCreator.key).isEqualTo(BluetoothDashboardScreen.KEY) } + override fun migration() {} + override fun launchFragment( fragmentClass: Class, action: (PreferenceFragmentCompat) -> Unit, diff --git a/tests/robotests/src/com/android/settings/connecteddevice/BluetoothMainSwitchPreferenceTest.kt b/tests/robotests/src/com/android/settings/connecteddevice/BluetoothMainSwitchPreferenceTest.kt new file mode 100644 index 00000000000..03039ac8b4c --- /dev/null +++ b/tests/robotests/src/com/android/settings/connecteddevice/BluetoothMainSwitchPreferenceTest.kt @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.connecteddevice + +import android.bluetooth.BluetoothAdapter +import android.content.Context +import android.platform.test.flag.junit.SetFlagsRule +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.kotlin.spy +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever +import org.robolectric.RuntimeEnvironment + +@RunWith(AndroidJUnit4::class) +class BluetoothMainSwitchPreferenceTest { + @get:Rule + val setFlagsRule = SetFlagsRule() + private val context: Context = ApplicationProvider.getApplicationContext() + private lateinit var bluetoothAdapter: BluetoothAdapter + private lateinit var bluetoothMainSwitchPreference: BluetoothMainSwitchPreference + + @Before + fun setUp() { + bluetoothAdapter = spy( + BluetoothAdapter.getDefaultAdapter() + ) + whenever(bluetoothAdapter.state).thenReturn(BluetoothAdapter.STATE_ON) + bluetoothMainSwitchPreference = BluetoothMainSwitchPreference(bluetoothAdapter) + } + + @Test + fun isEnabled_bluetoothOn_returnTrue() { + assertThat(bluetoothMainSwitchPreference.isEnabled(context)).isTrue() + } + + @Test + fun isEnabled_bluetoothTurningOn_returnFalse() { + whenever(bluetoothAdapter.state).thenReturn(BluetoothAdapter.STATE_TURNING_ON) + + assertThat(bluetoothMainSwitchPreference.isEnabled(context)).isFalse() + } + + @Test + fun storageSetOff_turnOff() { + bluetoothMainSwitchPreference.storage(context).setValue( + bluetoothMainSwitchPreference.key, Boolean::class.javaObjectType, false + ) + + verify(bluetoothAdapter).disable() + } + + @Test + fun storageSetOn_turnOn() { + bluetoothMainSwitchPreference.storage(context).setValue( + bluetoothMainSwitchPreference.key, Boolean::class.javaObjectType, true + ) + + verify(bluetoothAdapter).enable() + } +} \ No newline at end of file