1 /* 2 * Copyright (C) 2017 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 package com.android.settings.bluetooth; 17 18 import static com.google.common.truth.Truth.assertThat; 19 20 import static org.mockito.ArgumentMatchers.any; 21 import static org.mockito.Mockito.doReturn; 22 import static org.mockito.Mockito.never; 23 import static org.mockito.Mockito.verify; 24 import static org.mockito.Mockito.when; 25 26 import android.bluetooth.BluetoothAdapter; 27 import android.bluetooth.BluetoothDevice; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.graphics.drawable.Drawable; 31 import android.util.Pair; 32 33 import androidx.preference.Preference; 34 35 import com.android.settings.SettingsActivity; 36 import com.android.settings.connecteddevice.DevicePreferenceCallback; 37 import com.android.settings.testutils.shadow.ShadowBluetoothAdapter; 38 import com.android.settingslib.bluetooth.CachedBluetoothDevice; 39 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; 40 import com.android.settingslib.bluetooth.LocalBluetoothManager; 41 42 import org.junit.Before; 43 import org.junit.Test; 44 import org.junit.runner.RunWith; 45 import org.mockito.ArgumentCaptor; 46 import org.mockito.Mock; 47 import org.mockito.MockitoAnnotations; 48 import org.robolectric.RobolectricTestRunner; 49 import org.robolectric.RuntimeEnvironment; 50 import org.robolectric.annotation.Config; 51 import org.robolectric.shadow.api.Shadow; 52 53 import java.util.ArrayList; 54 import java.util.List; 55 56 @RunWith(RobolectricTestRunner.class) 57 @Config(shadows = {ShadowBluetoothAdapter.class}) 58 public class BluetoothDeviceUpdaterTest { 59 60 private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C"; 61 private static final String SUB_MAC_ADDRESS = "05:52:C7:0B:D8:3C"; 62 private static final String TEST_NAME = "test_name"; 63 64 @Mock 65 private DevicePreferenceCallback mDevicePreferenceCallback; 66 @Mock 67 private CachedBluetoothDevice mCachedBluetoothDevice; 68 @Mock 69 private CachedBluetoothDevice mSubCachedBluetoothDevice; 70 @Mock 71 private BluetoothDevice mBluetoothDevice; 72 @Mock 73 private BluetoothDevice mSubBluetoothDevice; 74 @Mock 75 private SettingsActivity mSettingsActivity; 76 @Mock 77 private LocalBluetoothManager mLocalManager; 78 @Mock 79 private CachedBluetoothDeviceManager mCachedDeviceManager; 80 @Mock 81 private Drawable mDrawable; 82 83 private Context mContext; 84 private TestBluetoothDeviceUpdater mBluetoothDeviceUpdater; 85 private BluetoothDevicePreference mPreference; 86 private ShadowBluetoothAdapter mShadowBluetoothAdapter; 87 private List<CachedBluetoothDevice> mCachedDevices = new ArrayList<>(); 88 89 @Before setUp()90 public void setUp() { 91 MockitoAnnotations.initMocks(this); 92 93 Pair<Drawable, String> pairs = new Pair<>(mDrawable, "fake_device"); 94 mContext = RuntimeEnvironment.application; 95 mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter()); 96 mCachedDevices.add(mCachedBluetoothDevice); 97 when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); 98 when(mSubCachedBluetoothDevice.getDevice()).thenReturn(mSubBluetoothDevice); 99 when(mLocalManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager); 100 when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(mCachedDevices); 101 when(mCachedBluetoothDevice.getAddress()).thenReturn(MAC_ADDRESS); 102 when(mSubBluetoothDevice.getAddress()).thenReturn(SUB_MAC_ADDRESS); 103 when(mCachedBluetoothDevice.getDrawableWithDescription()).thenReturn(pairs); 104 105 mPreference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice, 106 /* showDeviceWithoutNames= */ false, 107 BluetoothDevicePreference.SortType.TYPE_DEFAULT); 108 mBluetoothDeviceUpdater = new TestBluetoothDeviceUpdater(mContext, 109 mDevicePreferenceCallback, mLocalManager, /* metricsCategory= */ 0); 110 mBluetoothDeviceUpdater.setPrefContext(mContext); 111 } 112 113 @Test testAddPreference_deviceExist_doNothing()114 public void testAddPreference_deviceExist_doNothing() { 115 mBluetoothDeviceUpdater.mPreferenceMap.put(mBluetoothDevice, mPreference); 116 117 mBluetoothDeviceUpdater.addPreference(mCachedBluetoothDevice); 118 119 verify(mDevicePreferenceCallback, never()).onDeviceAdded(any(Preference.class)); 120 } 121 122 @Test testAddPreference_deviceNotExist_addPreference()123 public void testAddPreference_deviceNotExist_addPreference() { 124 mBluetoothDeviceUpdater.addPreference(mCachedBluetoothDevice); 125 126 final Preference preference = mBluetoothDeviceUpdater.mPreferenceMap.get(mBluetoothDevice); 127 assertThat(preference).isNotNull(); 128 verify(mDevicePreferenceCallback).onDeviceAdded(preference); 129 } 130 131 @Test testRemovePreference_deviceExist_removePreference()132 public void testRemovePreference_deviceExist_removePreference() { 133 mBluetoothDeviceUpdater.mPreferenceMap.put(mBluetoothDevice, mPreference); 134 135 mBluetoothDeviceUpdater.removePreference(mCachedBluetoothDevice); 136 137 verify(mDevicePreferenceCallback).onDeviceRemoved(mPreference); 138 assertThat(mBluetoothDeviceUpdater.mPreferenceMap.containsKey(mBluetoothDevice)).isFalse(); 139 } 140 141 @Test testOnDeviceDeleted_deviceExists_removePreference()142 public void testOnDeviceDeleted_deviceExists_removePreference() { 143 mBluetoothDeviceUpdater.mPreferenceMap.put(mBluetoothDevice, mPreference); 144 145 mBluetoothDeviceUpdater.onDeviceDeleted(mCachedBluetoothDevice); 146 147 verify(mDevicePreferenceCallback).onDeviceRemoved(mPreference); 148 assertThat(mBluetoothDeviceUpdater.mPreferenceMap.containsKey(mBluetoothDevice)).isFalse(); 149 } 150 151 @Test testRemovePreference_deviceNotExist_doNothing()152 public void testRemovePreference_deviceNotExist_doNothing() { 153 mBluetoothDeviceUpdater.removePreference(mCachedBluetoothDevice); 154 155 verify(mDevicePreferenceCallback, never()).onDeviceRemoved(any(Preference.class)); 156 } 157 158 @Test testRemovePreference_subDeviceExist_removePreference()159 public void testRemovePreference_subDeviceExist_removePreference() { 160 when(mCachedBluetoothDevice.getSubDevice()).thenReturn(mSubCachedBluetoothDevice); 161 mBluetoothDeviceUpdater.mPreferenceMap.put(mSubBluetoothDevice, mPreference); 162 163 assertThat(mBluetoothDeviceUpdater.mPreferenceMap. 164 containsKey(mSubBluetoothDevice)).isTrue(); 165 mBluetoothDeviceUpdater.removePreference(mCachedBluetoothDevice); 166 167 verify(mDevicePreferenceCallback).onDeviceRemoved(mPreference); 168 assertThat(mBluetoothDeviceUpdater.mPreferenceMap. 169 containsKey(mSubBluetoothDevice)).isFalse(); 170 } 171 172 @Test testDeviceProfilesListener_click_startBluetoothDeviceDetailPage()173 public void testDeviceProfilesListener_click_startBluetoothDeviceDetailPage() { 174 mBluetoothDeviceUpdater = new TestBluetoothDeviceUpdater(mSettingsActivity, 175 mDevicePreferenceCallback, mLocalManager, /* metricsCategory= */ 0); 176 177 final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); 178 mBluetoothDeviceUpdater.mDeviceProfilesListener.onGearClick(mPreference); 179 180 verify(mSettingsActivity).startActivity(intentCaptor.capture()); 181 assertThat(intentCaptor.getValue().getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT)) 182 .isEqualTo(BluetoothDeviceDetailsFragment.class.getName()); 183 } 184 185 @Test isDeviceConnected_deviceConnected()186 public void isDeviceConnected_deviceConnected() { 187 doReturn(BluetoothDevice.BOND_BONDED).when(mBluetoothDevice).getBondState(); 188 doReturn(true).when(mBluetoothDevice).isConnected(); 189 190 assertThat(mBluetoothDeviceUpdater.isDeviceConnected(mCachedBluetoothDevice)).isTrue(); 191 } 192 193 @Test isDeviceConnected_deviceNotConnected()194 public void isDeviceConnected_deviceNotConnected() { 195 doReturn(BluetoothDevice.BOND_BONDED).when(mBluetoothDevice).getBondState(); 196 doReturn(false).when(mBluetoothDevice).isConnected(); 197 198 assertThat(mBluetoothDeviceUpdater.isDeviceConnected(mCachedBluetoothDevice)).isFalse(); 199 } 200 201 @Test registerCallback_localBluetoothManagerNull_shouldNotCrash()202 public void registerCallback_localBluetoothManagerNull_shouldNotCrash() { 203 mBluetoothDeviceUpdater.mLocalManager = null; 204 205 // Shouldn't crash 206 mBluetoothDeviceUpdater.registerCallback(); 207 } 208 209 @Test unregisterCallback_localBluetoothManagerNull_shouldNotCrash()210 public void unregisterCallback_localBluetoothManagerNull_shouldNotCrash() { 211 mBluetoothDeviceUpdater.mLocalManager = null; 212 213 // Shouldn't crash 214 mBluetoothDeviceUpdater.unregisterCallback(); 215 } 216 217 @Test forceUpdate_bluetoothDisabled_removeAllDevicesFromPreference()218 public void forceUpdate_bluetoothDisabled_removeAllDevicesFromPreference() { 219 mShadowBluetoothAdapter.setEnabled(false); 220 mBluetoothDeviceUpdater.mPreferenceMap.put(mBluetoothDevice, mPreference); 221 222 mBluetoothDeviceUpdater.forceUpdate(); 223 224 verify(mDevicePreferenceCallback).onDeviceRemoved(mPreference); 225 assertThat(mBluetoothDeviceUpdater.mPreferenceMap).isEmpty(); 226 } 227 228 @Test forceUpdate_bluetoothEnabled_addPreference()229 public void forceUpdate_bluetoothEnabled_addPreference() { 230 mShadowBluetoothAdapter.setEnabled(true); 231 mBluetoothDeviceUpdater.forceUpdate(); 232 233 verify(mDevicePreferenceCallback).onDeviceAdded(any(Preference.class)); 234 } 235 236 @Test onBluetoothStateChanged_bluetoothStateIsOn_forceUpdate()237 public void onBluetoothStateChanged_bluetoothStateIsOn_forceUpdate() { 238 mShadowBluetoothAdapter.setEnabled(true); 239 mBluetoothDeviceUpdater.onBluetoothStateChanged(BluetoothAdapter.STATE_ON); 240 241 verify(mDevicePreferenceCallback).onDeviceAdded(any(Preference.class)); 242 } 243 244 @Test onBluetoothStateChanged_bluetoothStateIsOff_removeAllDevicesFromPreference()245 public void onBluetoothStateChanged_bluetoothStateIsOff_removeAllDevicesFromPreference() { 246 mBluetoothDeviceUpdater.mPreferenceMap.put(mBluetoothDevice, mPreference); 247 248 mBluetoothDeviceUpdater.onBluetoothStateChanged(BluetoothAdapter.STATE_OFF); 249 250 verify(mDevicePreferenceCallback).onDeviceRemoved(mPreference); 251 assertThat(mBluetoothDeviceUpdater.mPreferenceMap.containsKey(mBluetoothDevice)).isFalse(); 252 } 253 254 @Test havePreference_refreshPreference()255 public void havePreference_refreshPreference() { 256 mBluetoothDeviceUpdater.mPreferenceMap.put(mBluetoothDevice, mPreference); 257 mPreference.setTitle("fake_name"); 258 259 when(mCachedBluetoothDevice.getName()).thenReturn(TEST_NAME); 260 mBluetoothDeviceUpdater.refreshPreference(); 261 262 assertThat(mPreference.getTitle()).isEqualTo(TEST_NAME); 263 } 264 265 public static class TestBluetoothDeviceUpdater extends BluetoothDeviceUpdater { TestBluetoothDeviceUpdater(Context context, DevicePreferenceCallback devicePreferenceCallback, LocalBluetoothManager localManager, int metricsCategory)266 public TestBluetoothDeviceUpdater(Context context, 267 DevicePreferenceCallback devicePreferenceCallback, 268 LocalBluetoothManager localManager, int metricsCategory) { 269 super(context, devicePreferenceCallback, localManager, metricsCategory); 270 } 271 272 @Override isFilterMatched(CachedBluetoothDevice cachedBluetoothDevice)273 public boolean isFilterMatched(CachedBluetoothDevice cachedBluetoothDevice) { 274 return true; 275 } 276 277 @Override getPreferenceKey()278 protected String getPreferenceKey() { 279 return "test_bt"; 280 } 281 } 282 } 283