Loading packages/SettingsLib/aconfig/settingslib.aconfig +8 −1 Original line number Diff line number Diff line Loading @@ -44,3 +44,10 @@ flag { description: "Gates whether to enable LE audio private broadcast sharing via QR code" bug: "308368124" } flag { name: "enable_hide_exclusively_managed_bluetooth_device" namespace: "dck_framework" description: "Hide exclusively managed Bluetooth devices in BT settings menu." bug: "324475542" } packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/DeviceItemFactory.kt +22 −2 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.content.Context import android.media.AudioManager import com.android.settingslib.bluetooth.BluetoothUtils import com.android.settingslib.bluetooth.CachedBluetoothDevice import com.android.settingslib.flags.Flags import com.android.systemui.res.R private val backgroundOn = R.drawable.settingslib_switch_bar_bg_on Loading @@ -36,6 +37,7 @@ private val actionAccessibilityLabelDisconnect = /** Factories to create different types of Bluetooth device items from CachedBluetoothDevice. */ internal abstract class DeviceItemFactory { abstract fun isFilterMatched( context: Context, cachedDevice: CachedBluetoothDevice, audioManager: AudioManager? ): Boolean Loading @@ -45,6 +47,7 @@ internal abstract class DeviceItemFactory { internal class ActiveMediaDeviceItemFactory : DeviceItemFactory() { override fun isFilterMatched( context: Context, cachedDevice: CachedBluetoothDevice, audioManager: AudioManager? ): Boolean { Loading @@ -71,6 +74,7 @@ internal class ActiveMediaDeviceItemFactory : DeviceItemFactory() { internal class AvailableMediaDeviceItemFactory : DeviceItemFactory() { override fun isFilterMatched( context: Context, cachedDevice: CachedBluetoothDevice, audioManager: AudioManager? ): Boolean { Loading Loading @@ -99,10 +103,18 @@ internal class AvailableMediaDeviceItemFactory : DeviceItemFactory() { internal class ConnectedDeviceItemFactory : DeviceItemFactory() { override fun isFilterMatched( context: Context, cachedDevice: CachedBluetoothDevice, audioManager: AudioManager? ): Boolean { return BluetoothUtils.isConnectedBluetoothDevice(cachedDevice, audioManager) return if (Flags.enableHideExclusivelyManagedBluetoothDevice()) { !BluetoothUtils.isExclusivelyManagedBluetoothDevice( context, cachedDevice.getDevice() ) && BluetoothUtils.isConnectedBluetoothDevice(cachedDevice, audioManager) } else { BluetoothUtils.isConnectedBluetoothDevice(cachedDevice, audioManager) } } override fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem { Loading @@ -125,10 +137,18 @@ internal class ConnectedDeviceItemFactory : DeviceItemFactory() { internal class SavedDeviceItemFactory : DeviceItemFactory() { override fun isFilterMatched( context: Context, cachedDevice: CachedBluetoothDevice, audioManager: AudioManager? ): Boolean { return cachedDevice.bondState == BluetoothDevice.BOND_BONDED && !cachedDevice.isConnected return if (Flags.enableHideExclusivelyManagedBluetoothDevice()) { !BluetoothUtils.isExclusivelyManagedBluetoothDevice( context, cachedDevice.getDevice() ) && cachedDevice.bondState == BluetoothDevice.BOND_BONDED && !cachedDevice.isConnected } else { cachedDevice.bondState == BluetoothDevice.BOND_BONDED && !cachedDevice.isConnected } } override fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem { Loading packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/DeviceItemInteractor.kt +1 −1 Original line number Diff line number Diff line Loading @@ -133,7 +133,7 @@ constructor( bluetoothTileDialogRepository.cachedDevices .mapNotNull { cachedDevice -> deviceItemFactoryList .firstOrNull { it.isFilterMatched(cachedDevice, audioManager) } .firstOrNull { it.isFilterMatched(context, cachedDevice, audioManager) } ?.create(context, cachedDevice) } .sort(displayPriority, bluetoothAdapter?.mostRecentlyConnectedDevices) Loading packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/DeviceItemFactoryTest.kt +237 −1 Original line number Diff line number Diff line Loading @@ -16,10 +16,18 @@ package com.android.systemui.qs.tiles.dialog.bluetooth import android.bluetooth.BluetoothDevice import android.content.pm.PackageInfo import android.content.pm.PackageManager import android.media.AudioManager import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.testing.AndroidTestingRunner import android.testing.TestableLooper import androidx.test.filters.SmallTest import com.android.settingslib.bluetooth.BluetoothUtils import com.android.settingslib.bluetooth.CachedBluetoothDevice import com.android.settingslib.flags.Flags import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat import org.junit.Before Loading @@ -35,19 +43,26 @@ import org.mockito.junit.MockitoRule @RunWith(AndroidTestingRunner::class) @TestableLooper.RunWithLooper(setAsMainLooper = true) class DeviceItemFactoryTest : SysuiTestCase() { @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule() @Mock private lateinit var cachedDevice: CachedBluetoothDevice @Mock private lateinit var bluetoothDevice: BluetoothDevice @Mock private lateinit var packageManager: PackageManager private val availableMediaDeviceItemFactory = AvailableMediaDeviceItemFactory() private val connectedDeviceItemFactory = ConnectedDeviceItemFactory() private val savedDeviceItemFactory = SavedDeviceItemFactory() private val audioManager = context.getSystemService(AudioManager::class.java)!! @Before fun setup() { `when`(cachedDevice.name).thenReturn(DEVICE_NAME) `when`(cachedDevice.address).thenReturn(DEVICE_ADDRESS) `when`(cachedDevice.device).thenReturn(bluetoothDevice) `when`(cachedDevice.connectionSummary).thenReturn(CONNECTION_SUMMARY) context.setMockPackageManager(packageManager) } @Test Loading @@ -72,6 +87,225 @@ class DeviceItemFactoryTest : SysuiTestCase() { assertThat(deviceItem.background).isNotNull() } @Test @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testSavedFactory_isFilterMatched_bondedAndNotConnected_returnsTrue() { `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(cachedDevice.isConnected).thenReturn(false) assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isTrue() } @Test @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testSavedFactory_isFilterMatched_connected_returnsFalse() { `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(cachedDevice.isConnected).thenReturn(true) assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isFalse() } @Test @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testSavedFactory_isFilterMatched_notBonded_returnsFalse() { `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_NONE) `when`(cachedDevice.isConnected).thenReturn(false) assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isFalse() } @Test @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testSavedFactory_isFilterMatched_exclusivelyManaged_returnsFalse() { val exclusiveManagerName = BluetoothUtils.getExclusiveManagers().firstOrNull() ?: FAKE_EXCLUSIVE_MANAGER_NAME `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)) .thenReturn(exclusiveManagerName.toByteArray()) `when`(packageManager.getPackageInfo(exclusiveManagerName, 0)).thenReturn(PackageInfo()) `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(cachedDevice.isConnected).thenReturn(false) assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isFalse() } @Test @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testSavedFactory_isFilterMatched_noExclusiveManager_returnsTrue() { `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(cachedDevice.isConnected).thenReturn(false) assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isTrue() } @Test @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testSavedFactory_isFilterMatched_notAllowedExclusiveManager_returnsTrue() { `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)) .thenReturn(FAKE_EXCLUSIVE_MANAGER_NAME.toByteArray()) `when`(packageManager.getPackageInfo(FAKE_EXCLUSIVE_MANAGER_NAME, 0)) .thenReturn(PackageInfo()) `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(cachedDevice.isConnected).thenReturn(false) assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isTrue() } @Test @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testSavedFactory_isFilterMatched_uninstalledExclusiveManager_returnsTrue() { val exclusiveManagerName = BluetoothUtils.getExclusiveManagers().firstOrNull() ?: FAKE_EXCLUSIVE_MANAGER_NAME `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)) .thenReturn(exclusiveManagerName.toByteArray()) `when`(packageManager.getPackageInfo(exclusiveManagerName, 0)) .thenThrow(PackageManager.NameNotFoundException("Test!")) `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(cachedDevice.isConnected).thenReturn(false) assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isTrue() } @Test @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testSavedFactory_isFilterMatched_notExclusivelyManaged_notBonded_returnsFalse() { `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_NONE) `when`(cachedDevice.isConnected).thenReturn(false) assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isFalse() } @Test @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testSavedFactory_isFilterMatched_notExclusivelyManaged_connected_returnsFalse() { `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(cachedDevice.isConnected).thenReturn(true) assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isFalse() } @Test @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testConnectedFactory_isFilterMatched_bondedAndConnected_returnsTrue() { `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(bluetoothDevice.isConnected).thenReturn(true) audioManager.setMode(AudioManager.MODE_NORMAL) assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isTrue() } @Test @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testConnectedFactory_isFilterMatched_notConnected_returnsFalse() { `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(bluetoothDevice.isConnected).thenReturn(false) audioManager.setMode(AudioManager.MODE_NORMAL) assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isFalse() } @Test @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testConnectedFactory_isFilterMatched_notBonded_returnsFalse() { `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_NONE) `when`(bluetoothDevice.isConnected).thenReturn(true) audioManager.setMode(AudioManager.MODE_NORMAL) assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isFalse() } @Test @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testConnectedFactory_isFilterMatched_exclusivelyManaged_returnsFalse() { val exclusiveManagerName = BluetoothUtils.getExclusiveManagers().firstOrNull() ?: FAKE_EXCLUSIVE_MANAGER_NAME `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)) .thenReturn(exclusiveManagerName.toByteArray()) `when`(packageManager.getPackageInfo(exclusiveManagerName, 0)).thenReturn(PackageInfo()) `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(bluetoothDevice.isConnected).thenReturn(true) audioManager.setMode(AudioManager.MODE_NORMAL) assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isFalse() } @Test @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testConnectedFactory_isFilterMatched_noExclusiveManager_returnsTrue() { `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(bluetoothDevice.isConnected).thenReturn(true) audioManager.setMode(AudioManager.MODE_NORMAL) assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isTrue() } @Test @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testConnectedFactory_isFilterMatched_notAllowedExclusiveManager_returnsTrue() { `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)) .thenReturn(FAKE_EXCLUSIVE_MANAGER_NAME.toByteArray()) `when`(packageManager.getPackageInfo(FAKE_EXCLUSIVE_MANAGER_NAME, 0)) .thenReturn(PackageInfo()) `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(bluetoothDevice.isConnected).thenReturn(true) audioManager.setMode(AudioManager.MODE_NORMAL) assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isTrue() } @Test @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testConnectedFactory_isFilterMatched_uninstalledExclusiveManager_returnsTrue() { val exclusiveManagerName = BluetoothUtils.getExclusiveManagers().firstOrNull() ?: FAKE_EXCLUSIVE_MANAGER_NAME `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)) .thenReturn(exclusiveManagerName.toByteArray()) `when`(packageManager.getPackageInfo(exclusiveManagerName, 0)) .thenThrow(PackageManager.NameNotFoundException("Test!")) `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(bluetoothDevice.isConnected).thenReturn(true) audioManager.setMode(AudioManager.MODE_NORMAL) assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isTrue() } @Test @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testConnectedFactory_isFilterMatched_notExclusivelyManaged_notBonded_returnsFalse() { `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_NONE) `when`(bluetoothDevice.isConnected).thenReturn(true) audioManager.setMode(AudioManager.MODE_NORMAL) assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isFalse() } @Test @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testConnectedFactory_isFilterMatched_notExclusivelyManaged_notConnected_returnsFalse() { `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(bluetoothDevice.isConnected).thenReturn(false) audioManager.setMode(AudioManager.MODE_NORMAL) assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isFalse() } private fun assertDeviceItem(deviceItem: DeviceItem?, deviceItemType: DeviceItemType) { assertThat(deviceItem).isNotNull() assertThat(deviceItem!!.type).isEqualTo(deviceItemType) Loading @@ -83,5 +317,7 @@ class DeviceItemFactoryTest : SysuiTestCase() { companion object { const val DEVICE_NAME = "DeviceName" const val CONNECTION_SUMMARY = "ConnectionSummary" private const val FAKE_EXCLUSIVE_MANAGER_NAME = "com.fake.name" private const val DEVICE_ADDRESS = "04:52:C7:0B:D8:3C" } } packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/DeviceItemInteractorTest.kt +1 −0 Original line number Diff line number Diff line Loading @@ -279,6 +279,7 @@ class DeviceItemInteractorTest : SysuiTestCase() { ): DeviceItemFactory { return object : DeviceItemFactory() { override fun isFilterMatched( context: Context, cachedDevice: CachedBluetoothDevice, audioManager: AudioManager? ) = isFilterMatchFunc(cachedDevice) Loading Loading
packages/SettingsLib/aconfig/settingslib.aconfig +8 −1 Original line number Diff line number Diff line Loading @@ -44,3 +44,10 @@ flag { description: "Gates whether to enable LE audio private broadcast sharing via QR code" bug: "308368124" } flag { name: "enable_hide_exclusively_managed_bluetooth_device" namespace: "dck_framework" description: "Hide exclusively managed Bluetooth devices in BT settings menu." bug: "324475542" }
packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/DeviceItemFactory.kt +22 −2 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.content.Context import android.media.AudioManager import com.android.settingslib.bluetooth.BluetoothUtils import com.android.settingslib.bluetooth.CachedBluetoothDevice import com.android.settingslib.flags.Flags import com.android.systemui.res.R private val backgroundOn = R.drawable.settingslib_switch_bar_bg_on Loading @@ -36,6 +37,7 @@ private val actionAccessibilityLabelDisconnect = /** Factories to create different types of Bluetooth device items from CachedBluetoothDevice. */ internal abstract class DeviceItemFactory { abstract fun isFilterMatched( context: Context, cachedDevice: CachedBluetoothDevice, audioManager: AudioManager? ): Boolean Loading @@ -45,6 +47,7 @@ internal abstract class DeviceItemFactory { internal class ActiveMediaDeviceItemFactory : DeviceItemFactory() { override fun isFilterMatched( context: Context, cachedDevice: CachedBluetoothDevice, audioManager: AudioManager? ): Boolean { Loading @@ -71,6 +74,7 @@ internal class ActiveMediaDeviceItemFactory : DeviceItemFactory() { internal class AvailableMediaDeviceItemFactory : DeviceItemFactory() { override fun isFilterMatched( context: Context, cachedDevice: CachedBluetoothDevice, audioManager: AudioManager? ): Boolean { Loading Loading @@ -99,10 +103,18 @@ internal class AvailableMediaDeviceItemFactory : DeviceItemFactory() { internal class ConnectedDeviceItemFactory : DeviceItemFactory() { override fun isFilterMatched( context: Context, cachedDevice: CachedBluetoothDevice, audioManager: AudioManager? ): Boolean { return BluetoothUtils.isConnectedBluetoothDevice(cachedDevice, audioManager) return if (Flags.enableHideExclusivelyManagedBluetoothDevice()) { !BluetoothUtils.isExclusivelyManagedBluetoothDevice( context, cachedDevice.getDevice() ) && BluetoothUtils.isConnectedBluetoothDevice(cachedDevice, audioManager) } else { BluetoothUtils.isConnectedBluetoothDevice(cachedDevice, audioManager) } } override fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem { Loading @@ -125,10 +137,18 @@ internal class ConnectedDeviceItemFactory : DeviceItemFactory() { internal class SavedDeviceItemFactory : DeviceItemFactory() { override fun isFilterMatched( context: Context, cachedDevice: CachedBluetoothDevice, audioManager: AudioManager? ): Boolean { return cachedDevice.bondState == BluetoothDevice.BOND_BONDED && !cachedDevice.isConnected return if (Flags.enableHideExclusivelyManagedBluetoothDevice()) { !BluetoothUtils.isExclusivelyManagedBluetoothDevice( context, cachedDevice.getDevice() ) && cachedDevice.bondState == BluetoothDevice.BOND_BONDED && !cachedDevice.isConnected } else { cachedDevice.bondState == BluetoothDevice.BOND_BONDED && !cachedDevice.isConnected } } override fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem { Loading
packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/DeviceItemInteractor.kt +1 −1 Original line number Diff line number Diff line Loading @@ -133,7 +133,7 @@ constructor( bluetoothTileDialogRepository.cachedDevices .mapNotNull { cachedDevice -> deviceItemFactoryList .firstOrNull { it.isFilterMatched(cachedDevice, audioManager) } .firstOrNull { it.isFilterMatched(context, cachedDevice, audioManager) } ?.create(context, cachedDevice) } .sort(displayPriority, bluetoothAdapter?.mostRecentlyConnectedDevices) Loading
packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/DeviceItemFactoryTest.kt +237 −1 Original line number Diff line number Diff line Loading @@ -16,10 +16,18 @@ package com.android.systemui.qs.tiles.dialog.bluetooth import android.bluetooth.BluetoothDevice import android.content.pm.PackageInfo import android.content.pm.PackageManager import android.media.AudioManager import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.testing.AndroidTestingRunner import android.testing.TestableLooper import androidx.test.filters.SmallTest import com.android.settingslib.bluetooth.BluetoothUtils import com.android.settingslib.bluetooth.CachedBluetoothDevice import com.android.settingslib.flags.Flags import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat import org.junit.Before Loading @@ -35,19 +43,26 @@ import org.mockito.junit.MockitoRule @RunWith(AndroidTestingRunner::class) @TestableLooper.RunWithLooper(setAsMainLooper = true) class DeviceItemFactoryTest : SysuiTestCase() { @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule() @Mock private lateinit var cachedDevice: CachedBluetoothDevice @Mock private lateinit var bluetoothDevice: BluetoothDevice @Mock private lateinit var packageManager: PackageManager private val availableMediaDeviceItemFactory = AvailableMediaDeviceItemFactory() private val connectedDeviceItemFactory = ConnectedDeviceItemFactory() private val savedDeviceItemFactory = SavedDeviceItemFactory() private val audioManager = context.getSystemService(AudioManager::class.java)!! @Before fun setup() { `when`(cachedDevice.name).thenReturn(DEVICE_NAME) `when`(cachedDevice.address).thenReturn(DEVICE_ADDRESS) `when`(cachedDevice.device).thenReturn(bluetoothDevice) `when`(cachedDevice.connectionSummary).thenReturn(CONNECTION_SUMMARY) context.setMockPackageManager(packageManager) } @Test Loading @@ -72,6 +87,225 @@ class DeviceItemFactoryTest : SysuiTestCase() { assertThat(deviceItem.background).isNotNull() } @Test @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testSavedFactory_isFilterMatched_bondedAndNotConnected_returnsTrue() { `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(cachedDevice.isConnected).thenReturn(false) assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isTrue() } @Test @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testSavedFactory_isFilterMatched_connected_returnsFalse() { `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(cachedDevice.isConnected).thenReturn(true) assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isFalse() } @Test @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testSavedFactory_isFilterMatched_notBonded_returnsFalse() { `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_NONE) `when`(cachedDevice.isConnected).thenReturn(false) assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isFalse() } @Test @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testSavedFactory_isFilterMatched_exclusivelyManaged_returnsFalse() { val exclusiveManagerName = BluetoothUtils.getExclusiveManagers().firstOrNull() ?: FAKE_EXCLUSIVE_MANAGER_NAME `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)) .thenReturn(exclusiveManagerName.toByteArray()) `when`(packageManager.getPackageInfo(exclusiveManagerName, 0)).thenReturn(PackageInfo()) `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(cachedDevice.isConnected).thenReturn(false) assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isFalse() } @Test @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testSavedFactory_isFilterMatched_noExclusiveManager_returnsTrue() { `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(cachedDevice.isConnected).thenReturn(false) assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isTrue() } @Test @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testSavedFactory_isFilterMatched_notAllowedExclusiveManager_returnsTrue() { `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)) .thenReturn(FAKE_EXCLUSIVE_MANAGER_NAME.toByteArray()) `when`(packageManager.getPackageInfo(FAKE_EXCLUSIVE_MANAGER_NAME, 0)) .thenReturn(PackageInfo()) `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(cachedDevice.isConnected).thenReturn(false) assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isTrue() } @Test @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testSavedFactory_isFilterMatched_uninstalledExclusiveManager_returnsTrue() { val exclusiveManagerName = BluetoothUtils.getExclusiveManagers().firstOrNull() ?: FAKE_EXCLUSIVE_MANAGER_NAME `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)) .thenReturn(exclusiveManagerName.toByteArray()) `when`(packageManager.getPackageInfo(exclusiveManagerName, 0)) .thenThrow(PackageManager.NameNotFoundException("Test!")) `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(cachedDevice.isConnected).thenReturn(false) assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isTrue() } @Test @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testSavedFactory_isFilterMatched_notExclusivelyManaged_notBonded_returnsFalse() { `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_NONE) `when`(cachedDevice.isConnected).thenReturn(false) assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isFalse() } @Test @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testSavedFactory_isFilterMatched_notExclusivelyManaged_connected_returnsFalse() { `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(cachedDevice.isConnected).thenReturn(true) assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isFalse() } @Test @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testConnectedFactory_isFilterMatched_bondedAndConnected_returnsTrue() { `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(bluetoothDevice.isConnected).thenReturn(true) audioManager.setMode(AudioManager.MODE_NORMAL) assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isTrue() } @Test @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testConnectedFactory_isFilterMatched_notConnected_returnsFalse() { `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(bluetoothDevice.isConnected).thenReturn(false) audioManager.setMode(AudioManager.MODE_NORMAL) assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isFalse() } @Test @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testConnectedFactory_isFilterMatched_notBonded_returnsFalse() { `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_NONE) `when`(bluetoothDevice.isConnected).thenReturn(true) audioManager.setMode(AudioManager.MODE_NORMAL) assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isFalse() } @Test @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testConnectedFactory_isFilterMatched_exclusivelyManaged_returnsFalse() { val exclusiveManagerName = BluetoothUtils.getExclusiveManagers().firstOrNull() ?: FAKE_EXCLUSIVE_MANAGER_NAME `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)) .thenReturn(exclusiveManagerName.toByteArray()) `when`(packageManager.getPackageInfo(exclusiveManagerName, 0)).thenReturn(PackageInfo()) `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(bluetoothDevice.isConnected).thenReturn(true) audioManager.setMode(AudioManager.MODE_NORMAL) assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isFalse() } @Test @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testConnectedFactory_isFilterMatched_noExclusiveManager_returnsTrue() { `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(bluetoothDevice.isConnected).thenReturn(true) audioManager.setMode(AudioManager.MODE_NORMAL) assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isTrue() } @Test @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testConnectedFactory_isFilterMatched_notAllowedExclusiveManager_returnsTrue() { `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)) .thenReturn(FAKE_EXCLUSIVE_MANAGER_NAME.toByteArray()) `when`(packageManager.getPackageInfo(FAKE_EXCLUSIVE_MANAGER_NAME, 0)) .thenReturn(PackageInfo()) `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(bluetoothDevice.isConnected).thenReturn(true) audioManager.setMode(AudioManager.MODE_NORMAL) assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isTrue() } @Test @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testConnectedFactory_isFilterMatched_uninstalledExclusiveManager_returnsTrue() { val exclusiveManagerName = BluetoothUtils.getExclusiveManagers().firstOrNull() ?: FAKE_EXCLUSIVE_MANAGER_NAME `when`(bluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)) .thenReturn(exclusiveManagerName.toByteArray()) `when`(packageManager.getPackageInfo(exclusiveManagerName, 0)) .thenThrow(PackageManager.NameNotFoundException("Test!")) `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(bluetoothDevice.isConnected).thenReturn(true) audioManager.setMode(AudioManager.MODE_NORMAL) assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isTrue() } @Test @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testConnectedFactory_isFilterMatched_notExclusivelyManaged_notBonded_returnsFalse() { `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_NONE) `when`(bluetoothDevice.isConnected).thenReturn(true) audioManager.setMode(AudioManager.MODE_NORMAL) assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isFalse() } @Test @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) fun testConnectedFactory_isFilterMatched_notExclusivelyManaged_notConnected_returnsFalse() { `when`(bluetoothDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) `when`(bluetoothDevice.isConnected).thenReturn(false) audioManager.setMode(AudioManager.MODE_NORMAL) assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) .isFalse() } private fun assertDeviceItem(deviceItem: DeviceItem?, deviceItemType: DeviceItemType) { assertThat(deviceItem).isNotNull() assertThat(deviceItem!!.type).isEqualTo(deviceItemType) Loading @@ -83,5 +317,7 @@ class DeviceItemFactoryTest : SysuiTestCase() { companion object { const val DEVICE_NAME = "DeviceName" const val CONNECTION_SUMMARY = "ConnectionSummary" private const val FAKE_EXCLUSIVE_MANAGER_NAME = "com.fake.name" private const val DEVICE_ADDRESS = "04:52:C7:0B:D8:3C" } }
packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/DeviceItemInteractorTest.kt +1 −0 Original line number Diff line number Diff line Loading @@ -279,6 +279,7 @@ class DeviceItemInteractorTest : SysuiTestCase() { ): DeviceItemFactory { return object : DeviceItemFactory() { override fun isFilterMatched( context: Context, cachedDevice: CachedBluetoothDevice, audioManager: AudioManager? ) = isFilterMatchFunc(cachedDevice) Loading