1 /* 2 * Copyright (C) 2023 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.settings.bluetooth; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.mockito.ArgumentMatchers.anyInt; 22 import static org.mockito.Mockito.doNothing; 23 import static org.mockito.Mockito.doReturn; 24 import static org.mockito.Mockito.mock; 25 import static org.mockito.Mockito.spy; 26 import static org.mockito.Mockito.verify; 27 import static org.mockito.Mockito.when; 28 29 import android.bluetooth.BluetoothAdapter; 30 import android.bluetooth.BluetoothDevice; 31 import android.bluetooth.BluetoothProfile; 32 import android.content.Context; 33 import android.content.res.Resources; 34 import android.graphics.drawable.Drawable; 35 import android.util.Pair; 36 37 import androidx.test.core.app.ApplicationProvider; 38 39 import com.android.settings.testutils.shadow.ShadowBluetoothAdapter; 40 import com.android.settingslib.bluetooth.CachedBluetoothDevice; 41 import com.android.settingslib.bluetooth.LocalBluetoothManager; 42 43 import org.junit.Before; 44 import org.junit.Rule; 45 import org.junit.Test; 46 import org.junit.runner.RunWith; 47 import org.mockito.Answers; 48 import org.mockito.Mock; 49 import org.mockito.junit.MockitoJUnit; 50 import org.mockito.junit.MockitoRule; 51 import org.robolectric.RobolectricTestRunner; 52 import org.robolectric.annotation.Config; 53 import org.robolectric.shadow.api.Shadow; 54 55 /** Tests for {@link BluetoothDevicePairingDetailBase}. */ 56 @RunWith(RobolectricTestRunner.class) 57 @Config(shadows = { 58 ShadowBluetoothAdapter.class, 59 com.android.settings.testutils.shadow.ShadowFragment.class, 60 }) 61 public class BluetoothDevicePairingDetailBaseTest { 62 63 @Rule 64 public final MockitoRule mockito = MockitoJUnit.rule(); 65 66 public static final String KEY_DEVICE_LIST_GROUP = "test_key"; 67 68 private static final String TEST_DEVICE_ADDRESS = "00:A1:A1:A1:A1:A1"; 69 private static final String TEST_DEVICE_ADDRESS_B = "00:B1:B1:B1:B1:B1"; 70 private final Context mContext = ApplicationProvider.getApplicationContext(); 71 72 @Mock 73 private Resources mResource; 74 @Mock(answer = Answers.RETURNS_DEEP_STUBS) 75 private LocalBluetoothManager mLocalManager; 76 @Mock 77 private CachedBluetoothDevice mCachedBluetoothDevice; 78 @Mock 79 private Drawable mDrawable; 80 private BluetoothAdapter mBluetoothAdapter; 81 private ShadowBluetoothAdapter mShadowBluetoothAdapter; 82 private BluetoothProgressCategory mAvailableDevicesCategory; 83 private BluetoothDevice mBluetoothDevice; 84 private TestBluetoothDevicePairingDetailBase mFragment; 85 86 @Before setUp()87 public void setUp() { 88 mAvailableDevicesCategory = spy(new BluetoothProgressCategory(mContext)); 89 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 90 mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter()); 91 when(mCachedBluetoothDevice.getAddress()).thenReturn(TEST_DEVICE_ADDRESS); 92 final Pair<Drawable, String> pairs = new Pair<>(mDrawable, "fake_device"); 93 when(mCachedBluetoothDevice.getDrawableWithDescription()).thenReturn(pairs); 94 mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS); 95 96 mFragment = spy(new TestBluetoothDevicePairingDetailBase()); 97 when(mFragment.findPreference(KEY_DEVICE_LIST_GROUP)).thenReturn(mAvailableDevicesCategory); 98 doReturn(mContext).when(mFragment).getContext(); 99 doReturn(mResource).when(mFragment).getResources(); 100 mFragment.mDeviceListGroup = mAvailableDevicesCategory; 101 mFragment.mLocalManager = mLocalManager; 102 mFragment.mBluetoothAdapter = mBluetoothAdapter; 103 mFragment.initPreferencesFromPreferenceScreen(); 104 105 } 106 107 @Test startScanning_startScanAndRemoveDevices()108 public void startScanning_startScanAndRemoveDevices() { 109 mFragment.enableScanning(); 110 111 verify(mFragment).startScanning(); 112 verify(mAvailableDevicesCategory).removeAll(); 113 } 114 115 @Test updateContent_stateOn()116 public void updateContent_stateOn() { 117 mFragment.updateContent(BluetoothAdapter.STATE_ON); 118 119 assertThat(mBluetoothAdapter.isEnabled()).isTrue(); 120 verify(mFragment).enableScanning(); 121 } 122 123 @Test updateContent_stateOff_finish()124 public void updateContent_stateOff_finish() { 125 mFragment.updateContent(BluetoothAdapter.STATE_OFF); 126 127 verify(mFragment).finish(); 128 } 129 130 @Test updateBluetooth_bluetoothOff_turnOnBluetooth()131 public void updateBluetooth_bluetoothOff_turnOnBluetooth() { 132 mShadowBluetoothAdapter.setEnabled(false); 133 134 mFragment.updateBluetooth(); 135 136 assertThat(mBluetoothAdapter.isEnabled()).isTrue(); 137 } 138 139 @Test updateBluetooth_bluetoothOn_updateState()140 public void updateBluetooth_bluetoothOn_updateState() { 141 mShadowBluetoothAdapter.setEnabled(true); 142 doNothing().when(mFragment).updateContent(anyInt()); 143 144 mFragment.updateBluetooth(); 145 146 verify(mFragment).updateContent(anyInt()); 147 } 148 149 @Test onBluetoothStateChanged_whenTurnedOnBTShowToast()150 public void onBluetoothStateChanged_whenTurnedOnBTShowToast() { 151 doNothing().when(mFragment).updateContent(anyInt()); 152 153 mFragment.onBluetoothStateChanged(BluetoothAdapter.STATE_ON); 154 155 verify(mFragment).showBluetoothTurnedOnToast(); 156 } 157 158 @Test onProfileConnectionStateChanged_deviceInSelectedListAndConnected_finish()159 public void onProfileConnectionStateChanged_deviceInSelectedListAndConnected_finish() { 160 final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_B); 161 mFragment.mSelectedList.add(mBluetoothDevice); 162 mFragment.mSelectedList.add(device); 163 164 when(mCachedBluetoothDevice.isConnected()).thenReturn(true); 165 when(mCachedBluetoothDevice.getDevice()).thenReturn(device); 166 167 mFragment.onProfileConnectionStateChanged(mCachedBluetoothDevice, 168 BluetoothProfile.A2DP, BluetoothAdapter.STATE_CONNECTED); 169 170 verify(mFragment).finish(); 171 } 172 173 @Test onProfileConnectionStateChanged_deviceNotInSelectedList_doNothing()174 public void onProfileConnectionStateChanged_deviceNotInSelectedList_doNothing() { 175 final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_B); 176 mFragment.mSelectedList.add(device); 177 178 when(mCachedBluetoothDevice.isConnected()).thenReturn(true); 179 when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); 180 181 mFragment.onProfileConnectionStateChanged(mCachedBluetoothDevice, 182 BluetoothProfile.A2DP, BluetoothAdapter.STATE_CONNECTED); 183 184 // not crash 185 } 186 187 @Test onProfileConnectionStateChanged_deviceDisconnected_doNothing()188 public void onProfileConnectionStateChanged_deviceDisconnected_doNothing() { 189 final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_B); 190 mFragment.mSelectedList.add(mBluetoothDevice); 191 mFragment.mSelectedList.add(device); 192 193 when(mCachedBluetoothDevice.isConnected()).thenReturn(false); 194 when(mCachedBluetoothDevice.getDevice()).thenReturn(device); 195 196 mFragment.onProfileConnectionStateChanged(mCachedBluetoothDevice, 197 BluetoothProfile.A2DP, BluetoothAdapter.STATE_DISCONNECTED); 198 199 // not crash 200 } 201 202 @Test onProfileConnectionStateChanged_deviceInPreferenceMapAndConnected_removed()203 public void onProfileConnectionStateChanged_deviceInPreferenceMapAndConnected_removed() { 204 final BluetoothDevicePreference preference = 205 new BluetoothDevicePreference(mContext, mCachedBluetoothDevice, 206 true, BluetoothDevicePreference.SortType.TYPE_FIFO); 207 final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS); 208 mFragment.getDevicePreferenceMap().put(mCachedBluetoothDevice, preference); 209 210 when(mCachedBluetoothDevice.isConnected()).thenReturn(true); 211 when(mCachedBluetoothDevice.getDevice()).thenReturn(device); 212 213 mFragment.onProfileConnectionStateChanged(mCachedBluetoothDevice, 214 BluetoothProfile.A2DP, BluetoothAdapter.STATE_CONNECTED); 215 216 assertThat(mFragment.getDevicePreferenceMap().size()).isEqualTo(0); 217 } 218 219 @Test onProfileConnectionStateChanged_deviceNotInPreferenceMap_doNothing()220 public void onProfileConnectionStateChanged_deviceNotInPreferenceMap_doNothing() { 221 final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class); 222 final BluetoothDevicePreference preference = 223 new BluetoothDevicePreference(mContext, mCachedBluetoothDevice, 224 true, BluetoothDevicePreference.SortType.TYPE_FIFO); 225 final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS); 226 final BluetoothDevice device2 = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_B); 227 mFragment.getDevicePreferenceMap().put(mCachedBluetoothDevice, preference); 228 229 when(mCachedBluetoothDevice.isConnected()).thenReturn(true); 230 when(mCachedBluetoothDevice.getDevice()).thenReturn(device); 231 when(cachedDevice.isConnected()).thenReturn(true); 232 when(cachedDevice.getDevice()).thenReturn(device2); 233 when(cachedDevice.getAddress()).thenReturn(TEST_DEVICE_ADDRESS_B); 234 when(cachedDevice.getIdentityAddress()).thenReturn(TEST_DEVICE_ADDRESS_B); 235 236 mFragment.onProfileConnectionStateChanged(cachedDevice, BluetoothProfile.A2DP, 237 BluetoothAdapter.STATE_CONNECTED); 238 239 // not crash 240 } 241 242 private static class TestBluetoothDevicePairingDetailBase extends 243 BluetoothDevicePairingDetailBase { 244 TestBluetoothDevicePairingDetailBase()245 TestBluetoothDevicePairingDetailBase() { 246 super(); 247 } 248 249 @Override getMetricsCategory()250 public int getMetricsCategory() { 251 return 0; 252 } 253 254 @Override getDeviceListKey()255 public String getDeviceListKey() { 256 return KEY_DEVICE_LIST_GROUP; 257 } 258 259 @Override getPreferenceScreenResId()260 protected int getPreferenceScreenResId() { 261 return 0; 262 } 263 264 @Override getLogTag()265 protected String getLogTag() { 266 return "test_tag"; 267 } 268 } 269 } 270