Skip to content
Snippets Groups Projects
Commit bb4c7541 authored by Srinivas Patibandla's avatar Srinivas Patibandla Committed by Android (Google) Code Review
Browse files

Merge "[Hide DCK Device] Hide DCK BluetoothDevice from QS SysUI" into main

parents e2a2de37 6e3328ed
No related branches found
No related tags found
No related merge requests found
......@@ -43,4 +43,11 @@ flag {
namespace: "pixel_cross_device_control"
description: "Gates whether to enable LE audio private broadcast sharing via QR code"
bug: "308368124"
}
\ No newline at end of file
}
flag {
name: "enable_hide_exclusively_managed_bluetooth_device"
namespace: "dck_framework"
description: "Hide exclusively managed Bluetooth devices in BT settings menu."
bug: "324475542"
}
......@@ -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
......@@ -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
......@@ -45,6 +47,7 @@ internal abstract class DeviceItemFactory {
internal class ActiveMediaDeviceItemFactory : DeviceItemFactory() {
override fun isFilterMatched(
context: Context,
cachedDevice: CachedBluetoothDevice,
audioManager: AudioManager?
): Boolean {
......@@ -71,6 +74,7 @@ internal class ActiveMediaDeviceItemFactory : DeviceItemFactory() {
internal class AvailableMediaDeviceItemFactory : DeviceItemFactory() {
override fun isFilterMatched(
context: Context,
cachedDevice: CachedBluetoothDevice,
audioManager: AudioManager?
): Boolean {
......@@ -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 {
......@@ -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 {
......
......@@ -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)
......
......@@ -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
......@@ -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
......@@ -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)
......@@ -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"
}
}
......@@ -279,6 +279,7 @@ class DeviceItemInteractorTest : SysuiTestCase() {
): DeviceItemFactory {
return object : DeviceItemFactory() {
override fun isFilterMatched(
context: Context,
cachedDevice: CachedBluetoothDevice,
audioManager: AudioManager?
) = isFilterMatchFunc(cachedDevice)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment