1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.bluetooth.qsdialog 18 19 import android.bluetooth.BluetoothDevice 20 import android.graphics.drawable.Drawable 21 import android.media.AudioManager 22 import android.platform.test.annotations.DisableFlags 23 import android.platform.test.annotations.EnableFlags 24 import android.testing.TestableLooper 25 import android.util.Pair 26 import androidx.test.ext.junit.runners.AndroidJUnit4 27 import androidx.test.filters.SmallTest 28 import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession 29 import com.android.dx.mockito.inline.extended.StaticMockitoSession 30 import com.android.settingslib.bluetooth.BluetoothUtils 31 import com.android.settingslib.bluetooth.CachedBluetoothDevice 32 import com.android.settingslib.bluetooth.LocalBluetoothManager 33 import com.android.settingslib.flags.Flags 34 import com.android.systemui.SysuiTestCase 35 import com.android.systemui.res.R 36 import com.google.common.truth.Truth.assertThat 37 import org.junit.After 38 import org.junit.Before 39 import org.junit.Rule 40 import org.junit.Test 41 import org.junit.runner.RunWith 42 import org.mockito.Mock 43 import org.mockito.Mockito.`when` 44 import org.mockito.junit.MockitoJUnit 45 import org.mockito.junit.MockitoRule 46 import org.mockito.kotlin.any 47 48 @SmallTest 49 @RunWith(AndroidJUnit4::class) 50 @TestableLooper.RunWithLooper(setAsMainLooper = true) 51 class DeviceItemFactoryTest : SysuiTestCase() { 52 @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule() 53 54 private lateinit var mockitoSession: StaticMockitoSession 55 @Mock private lateinit var cachedDevice: CachedBluetoothDevice 56 @Mock private lateinit var bluetoothDevice: BluetoothDevice 57 @Mock private lateinit var localBluetoothManager: LocalBluetoothManager 58 @Mock private lateinit var drawable: Drawable 59 60 private val availableMediaDeviceItemFactory = AvailableMediaDeviceItemFactory() 61 private val connectedDeviceItemFactory = ConnectedDeviceItemFactory() 62 private val savedDeviceItemFactory = SavedDeviceItemFactory() 63 64 private val audioManager = context.getSystemService(AudioManager::class.java)!! 65 66 @Before setupnull67 fun setup() { 68 mockitoSession = 69 mockitoSession().initMocks(this).mockStatic(BluetoothUtils::class.java).startMocking() 70 } 71 72 @After tearDownnull73 fun tearDown() { 74 mockitoSession.finishMocking() 75 } 76 77 @Test testAvailableMediaDeviceItemFactory_createFromCachedDevicenull78 fun testAvailableMediaDeviceItemFactory_createFromCachedDevice() { 79 `when`(cachedDevice.name).thenReturn(DEVICE_NAME) 80 `when`(cachedDevice.connectionSummary).thenReturn(CONNECTION_SUMMARY) 81 `when`(cachedDevice.drawableWithDescription).thenReturn(Pair.create(drawable, "")) 82 val deviceItem = availableMediaDeviceItemFactory.create(context, cachedDevice) 83 84 assertDeviceItem(deviceItem, DeviceItemType.AVAILABLE_MEDIA_BLUETOOTH_DEVICE) 85 } 86 87 @Test testConnectedDeviceItemFactory_createFromCachedDevicenull88 fun testConnectedDeviceItemFactory_createFromCachedDevice() { 89 `when`(cachedDevice.name).thenReturn(DEVICE_NAME) 90 `when`(cachedDevice.connectionSummary).thenReturn(CONNECTION_SUMMARY) 91 `when`(cachedDevice.drawableWithDescription).thenReturn(Pair.create(drawable, "")) 92 val deviceItem = connectedDeviceItemFactory.create(context, cachedDevice) 93 94 assertDeviceItem(deviceItem, DeviceItemType.CONNECTED_BLUETOOTH_DEVICE) 95 } 96 97 @Test testSavedDeviceItemFactory_createFromCachedDevicenull98 fun testSavedDeviceItemFactory_createFromCachedDevice() { 99 `when`(cachedDevice.name).thenReturn(DEVICE_NAME) 100 `when`(cachedDevice.connectionSummary).thenReturn(CONNECTION_SUMMARY) 101 `when`(cachedDevice.drawableWithDescription).thenReturn(Pair.create(drawable, "")) 102 val deviceItem = savedDeviceItemFactory.create(context, cachedDevice) 103 104 assertDeviceItem(deviceItem, DeviceItemType.SAVED_BLUETOOTH_DEVICE) 105 assertThat(deviceItem.background).isNotNull() 106 } 107 108 @Test testAvailableAudioSharingMediaDeviceItemFactory_createFromCachedDevicenull109 fun testAvailableAudioSharingMediaDeviceItemFactory_createFromCachedDevice() { 110 `when`(cachedDevice.name).thenReturn(DEVICE_NAME) 111 `when`(cachedDevice.drawableWithDescription).thenReturn(Pair.create(drawable, "")) 112 val deviceItem = 113 AvailableAudioSharingMediaDeviceItemFactory(localBluetoothManager) 114 .create(context, cachedDevice) 115 116 assertThat(deviceItem).isNotNull() 117 assertThat(deviceItem.type) 118 .isEqualTo(DeviceItemType.AVAILABLE_AUDIO_SHARING_MEDIA_BLUETOOTH_DEVICE) 119 assertThat(deviceItem.cachedBluetoothDevice).isEqualTo(cachedDevice) 120 assertThat(deviceItem.deviceName).isEqualTo(DEVICE_NAME) 121 assertThat(deviceItem.isActive).isFalse() 122 assertThat(deviceItem.connectionSummary) 123 .isEqualTo( 124 context.getString( 125 R.string.quick_settings_bluetooth_device_audio_sharing_or_switch_active 126 ) 127 ) 128 } 129 130 @Test testAvailableAudioSharingMediaDeviceItemFactory_isFilterMatched_flagOff_returnsFalsenull131 fun testAvailableAudioSharingMediaDeviceItemFactory_isFilterMatched_flagOff_returnsFalse() { 132 assertThat( 133 AvailableAudioSharingMediaDeviceItemFactory(localBluetoothManager) 134 .isFilterMatched(context, cachedDevice, audioManager, false) 135 ) 136 .isFalse() 137 } 138 139 @Test testAvailableAudioSharingMediaDeviceItemFactory_isFilterMatched_isActiveDevice_falsenull140 fun testAvailableAudioSharingMediaDeviceItemFactory_isFilterMatched_isActiveDevice_false() { 141 `when`(BluetoothUtils.isActiveMediaDevice(any())).thenReturn(true) 142 143 assertThat( 144 AvailableAudioSharingMediaDeviceItemFactory(localBluetoothManager) 145 .isFilterMatched(context, cachedDevice, audioManager, true) 146 ) 147 .isFalse() 148 } 149 150 @Test testAvailableAudioSharingMediaDeviceItemFactory_isFilterMatched_isNotAvailable_falsenull151 fun testAvailableAudioSharingMediaDeviceItemFactory_isFilterMatched_isNotAvailable_false() { 152 `when`(BluetoothUtils.isActiveMediaDevice(any())).thenReturn(false) 153 `when`(BluetoothUtils.isAvailableMediaBluetoothDevice(any(), any())).thenReturn(true) 154 `when`(BluetoothUtils.isAvailableAudioSharingMediaBluetoothDevice(any(), any())) 155 .thenReturn(false) 156 157 assertThat( 158 AvailableAudioSharingMediaDeviceItemFactory(localBluetoothManager) 159 .isFilterMatched(context, cachedDevice, audioManager, true) 160 ) 161 .isFalse() 162 } 163 164 @Test testAvailableAudioSharingMediaDeviceItemFactory_isFilterMatched_returnsTruenull165 fun testAvailableAudioSharingMediaDeviceItemFactory_isFilterMatched_returnsTrue() { 166 `when`(BluetoothUtils.isActiveMediaDevice(any())).thenReturn(false) 167 `when`(BluetoothUtils.isAvailableMediaBluetoothDevice(any(), any())).thenReturn(true) 168 `when`(BluetoothUtils.isAvailableAudioSharingMediaBluetoothDevice(any(), any())) 169 .thenReturn(true) 170 171 assertThat( 172 AvailableAudioSharingMediaDeviceItemFactory(localBluetoothManager) 173 .isFilterMatched(context, cachedDevice, audioManager, true) 174 ) 175 .isTrue() 176 } 177 178 @Test 179 @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) testSavedFactory_isFilterMatched_bondedAndNotConnected_returnsTruenull180 fun testSavedFactory_isFilterMatched_bondedAndNotConnected_returnsTrue() { 181 `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) 182 `when`(cachedDevice.isConnected).thenReturn(false) 183 184 assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) 185 .isTrue() 186 } 187 188 @Test 189 @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) testSavedFactory_isFilterMatched_connected_returnsFalsenull190 fun testSavedFactory_isFilterMatched_connected_returnsFalse() { 191 `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) 192 `when`(cachedDevice.isConnected).thenReturn(true) 193 194 assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) 195 .isFalse() 196 } 197 198 @Test 199 @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) testSavedFactory_isFilterMatched_notBonded_returnsFalsenull200 fun testSavedFactory_isFilterMatched_notBonded_returnsFalse() { 201 `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_NONE) 202 203 assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) 204 .isFalse() 205 } 206 207 @Test 208 @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) testSavedFactory_isFilterMatched_exclusivelyManaged_returnsFalsenull209 fun testSavedFactory_isFilterMatched_exclusivelyManaged_returnsFalse() { 210 `when`(cachedDevice.device).thenReturn(bluetoothDevice) 211 `when`(BluetoothUtils.isExclusivelyManagedBluetoothDevice(any(), any())).thenReturn(true) 212 213 assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) 214 .isFalse() 215 } 216 217 @Test 218 @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) testSavedFactory_isFilterMatched_notExclusiveManaged_returnsTruenull219 fun testSavedFactory_isFilterMatched_notExclusiveManaged_returnsTrue() { 220 `when`(cachedDevice.device).thenReturn(bluetoothDevice) 221 `when`(BluetoothUtils.isExclusivelyManagedBluetoothDevice(any(), any())).thenReturn(false) 222 `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) 223 `when`(cachedDevice.isConnected).thenReturn(false) 224 225 assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) 226 .isTrue() 227 } 228 229 @Test 230 @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) testSavedFactory_isFilterMatched_notExclusivelyManaged_connected_returnsFalsenull231 fun testSavedFactory_isFilterMatched_notExclusivelyManaged_connected_returnsFalse() { 232 `when`(cachedDevice.device).thenReturn(bluetoothDevice) 233 `when`(BluetoothUtils.isExclusivelyManagedBluetoothDevice(any(), any())).thenReturn(false) 234 `when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED) 235 `when`(cachedDevice.isConnected).thenReturn(true) 236 237 assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) 238 .isFalse() 239 } 240 241 @Test 242 @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) testConnectedFactory_isFilterMatched_bondedAndConnected_returnsTruenull243 fun testConnectedFactory_isFilterMatched_bondedAndConnected_returnsTrue() { 244 `when`(BluetoothUtils.isConnectedBluetoothDevice(any(), any())).thenReturn(true) 245 246 assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) 247 .isTrue() 248 } 249 250 @Test 251 @DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) testConnectedFactory_isFilterMatched_notConnected_returnsFalsenull252 fun testConnectedFactory_isFilterMatched_notConnected_returnsFalse() { 253 assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) 254 .isFalse() 255 } 256 257 @Test 258 @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) testConnectedFactory_isFilterMatched_exclusivelyManaged_returnsFalsenull259 fun testConnectedFactory_isFilterMatched_exclusivelyManaged_returnsFalse() { 260 `when`(cachedDevice.device).thenReturn(bluetoothDevice) 261 `when`(BluetoothUtils.isExclusivelyManagedBluetoothDevice(any(), any())).thenReturn(true) 262 263 assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) 264 .isFalse() 265 } 266 267 @Test 268 @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) testConnectedFactory_isFilterMatched_noExclusiveManager_returnsTruenull269 fun testConnectedFactory_isFilterMatched_noExclusiveManager_returnsTrue() { 270 `when`(cachedDevice.device).thenReturn(bluetoothDevice) 271 `when`(BluetoothUtils.isExclusivelyManagedBluetoothDevice(any(), any())).thenReturn(false) 272 `when`(BluetoothUtils.isConnectedBluetoothDevice(any(), any())).thenReturn(true) 273 274 assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) 275 .isTrue() 276 } 277 278 @Test 279 @EnableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE) testConnectedFactory_isFilterMatched_notExclusivelyManaged_notConnected_returnsFalsenull280 fun testConnectedFactory_isFilterMatched_notExclusivelyManaged_notConnected_returnsFalse() { 281 `when`(cachedDevice.device).thenReturn(bluetoothDevice) 282 `when`(BluetoothUtils.isExclusivelyManagedBluetoothDevice(any(), any())).thenReturn(false) 283 `when`(BluetoothUtils.isConnectedBluetoothDevice(any(), any())).thenReturn(false) 284 285 assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager)) 286 .isFalse() 287 } 288 assertDeviceItemnull289 private fun assertDeviceItem(deviceItem: DeviceItem?, deviceItemType: DeviceItemType) { 290 assertThat(deviceItem).isNotNull() 291 assertThat(deviceItem!!.type).isEqualTo(deviceItemType) 292 assertThat(deviceItem.cachedBluetoothDevice).isEqualTo(cachedDevice) 293 assertThat(deviceItem.deviceName).isEqualTo(DEVICE_NAME) 294 assertThat(deviceItem.connectionSummary).isEqualTo(CONNECTION_SUMMARY) 295 } 296 297 companion object { 298 const val DEVICE_NAME = "DeviceName" 299 const val CONNECTION_SUMMARY = "ConnectionSummary" 300 } 301 } 302