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