1 /* 2 * Copyright 2018 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.bluetooth.btservice; 17 18 import static android.Manifest.permission.BLUETOOTH_CONNECT; 19 import static org.mockito.Mockito.*; 20 21 import android.bluetooth.BluetoothDevice; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.os.Bundle; 25 import android.os.HandlerThread; 26 import android.os.Message; 27 import android.os.ParcelUuid; 28 import android.os.UserHandle; 29 30 import androidx.test.InstrumentationRegistry; 31 import androidx.test.filters.MediumTest; 32 import androidx.test.runner.AndroidJUnit4; 33 34 import com.android.bluetooth.TestUtils; 35 36 import org.junit.After; 37 import org.junit.Assert; 38 import org.junit.Before; 39 import org.junit.Test; 40 import org.junit.runner.RunWith; 41 import org.mockito.ArgumentCaptor; 42 import org.mockito.Mock; 43 import org.mockito.MockitoAnnotations; 44 45 @MediumTest 46 @RunWith(AndroidJUnit4.class) 47 public class BondStateMachineTest { 48 private static final int TEST_BOND_REASON = 0; 49 private static final byte[] TEST_BT_ADDR_BYTES = {00, 11, 22, 33, 44, 55}; 50 private static final byte[] TEST_BT_ADDR_BYTES_2 = {00, 11, 22, 33, 44, 66}; 51 private static final ParcelUuid[] TEST_UUIDS = 52 {ParcelUuid.fromString("0000111E-0000-1000-8000-00805F9B34FB")}; 53 54 private static final int BOND_NONE = BluetoothDevice.BOND_NONE; 55 private static final int BOND_BONDING = BluetoothDevice.BOND_BONDING; 56 private static final int BOND_BONDED = BluetoothDevice.BOND_BONDED; 57 58 private AdapterProperties mAdapterProperties; 59 private BluetoothDevice mDevice; 60 private Context mTargetContext; 61 private RemoteDevices mRemoteDevices; 62 private BondStateMachine mBondStateMachine; 63 private HandlerThread mHandlerThread; 64 private RemoteDevices.DeviceProperties mDeviceProperties; 65 private int mVerifyCount = 0; 66 67 @Mock private AdapterService mAdapterService; 68 69 @Before setUp()70 public void setUp() throws Exception { 71 mTargetContext = InstrumentationRegistry.getTargetContext(); 72 MockitoAnnotations.initMocks(this); 73 TestUtils.setAdapterService(mAdapterService); 74 mHandlerThread = new HandlerThread("BondStateMachineTestHandlerThread"); 75 mHandlerThread.start(); 76 77 mRemoteDevices = new RemoteDevices(mAdapterService, mHandlerThread.getLooper()); 78 mRemoteDevices.reset(); 79 when(mAdapterService.getResources()).thenReturn( 80 mTargetContext.getResources()); 81 mAdapterProperties = new AdapterProperties(mAdapterService); 82 mAdapterProperties.init(mRemoteDevices); 83 mBondStateMachine = BondStateMachine.make(mAdapterService, mAdapterProperties, 84 mRemoteDevices); 85 } 86 87 @After tearDown()88 public void tearDown() throws Exception { 89 mHandlerThread.quit(); 90 TestUtils.clearAdapterService(mAdapterService); 91 } 92 93 @Test testCreateBondAfterRemoveBond()94 public void testCreateBondAfterRemoveBond() { 95 // Set up two devices already bonded. 96 mRemoteDevices.reset(); 97 RemoteDevices.DeviceProperties deviceProperties1, deviceProperties2; 98 deviceProperties1 = mRemoteDevices.addDeviceProperties(TEST_BT_ADDR_BYTES); 99 deviceProperties2 = mRemoteDevices.addDeviceProperties(TEST_BT_ADDR_BYTES_2); 100 BluetoothDevice device1, device2; 101 device1 = mRemoteDevices.getDevice(TEST_BT_ADDR_BYTES); 102 device2 = mRemoteDevices.getDevice(TEST_BT_ADDR_BYTES_2); 103 deviceProperties1.mBondState = BOND_BONDED; 104 deviceProperties2.mBondState = BOND_BONDED; 105 106 doReturn(true).when(mAdapterService).removeBondNative(any(byte[].class)); 107 doReturn(true).when(mAdapterService).createBondNative(any(byte[].class), anyInt()); 108 109 // The removeBond() request for a bonded device should invoke the removeBondNative() call. 110 Message removeBondMsg1 = mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND); 111 removeBondMsg1.obj = device1; 112 mBondStateMachine.sendMessage(removeBondMsg1); 113 TestUtils.waitForLooperToFinishScheduledTask(mBondStateMachine.getHandler().getLooper()); 114 Message removeBondMsg2 = mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND); 115 removeBondMsg2.obj = device2; 116 mBondStateMachine.sendMessage(removeBondMsg2); 117 TestUtils.waitForLooperToFinishScheduledTask(mBondStateMachine.getHandler().getLooper()); 118 119 verify(mAdapterService, times(1)).removeBondNative(eq(TEST_BT_ADDR_BYTES)); 120 verify(mAdapterService, times(1)).removeBondNative(eq(TEST_BT_ADDR_BYTES_2)); 121 122 mBondStateMachine.bondStateChangeCallback(AbstractionLayer.BT_STATUS_SUCCESS, 123 TEST_BT_ADDR_BYTES, BOND_NONE); 124 TestUtils.waitForLooperToFinishScheduledTask(mBondStateMachine.getHandler().getLooper()); 125 mBondStateMachine.bondStateChangeCallback(AbstractionLayer.BT_STATUS_SUCCESS, 126 TEST_BT_ADDR_BYTES_2, BOND_NONE); 127 TestUtils.waitForLooperToFinishScheduledTask(mBondStateMachine.getHandler().getLooper()); 128 129 // Try to pair these two devices again, createBondNative() should be invoked. 130 Message createBondMsg1 = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND); 131 createBondMsg1.obj = device1; 132 mBondStateMachine.sendMessage(createBondMsg1); 133 Message createBondMsg2 = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND); 134 createBondMsg2.obj = device2; 135 mBondStateMachine.sendMessage(createBondMsg2); 136 TestUtils.waitForLooperToFinishScheduledTask(mBondStateMachine.getHandler().getLooper()); 137 138 verify(mAdapterService, times(1)).createBondNative(eq(TEST_BT_ADDR_BYTES), anyInt()); 139 verify(mAdapterService, times(1)).createBondNative(eq(TEST_BT_ADDR_BYTES_2), anyInt()); 140 } 141 142 @Test testSendIntent()143 public void testSendIntent() { 144 int badBondState = 42; 145 mVerifyCount = 0; 146 147 // Reset mRemoteDevices for the test. 148 mRemoteDevices.reset(); 149 mDeviceProperties = mRemoteDevices.addDeviceProperties(TEST_BT_ADDR_BYTES); 150 mDevice = mDeviceProperties.getDevice(); 151 Assert.assertNotNull(mDevice); 152 153 /* Classic / Dualmode test cases*/ 154 // Uuid not available, mPendingBondedDevice is empty. 155 testSendIntentNoPendingDevice(BOND_NONE, BOND_NONE, BOND_NONE, 156 false, BOND_NONE, BOND_NONE); 157 testSendIntentNoPendingDevice(BOND_NONE, BOND_BONDING, BOND_BONDING, 158 true, BOND_NONE, BOND_BONDING); 159 testSendIntentNoPendingDevice(BOND_NONE, BOND_BONDED, BOND_BONDED, 160 true, BOND_NONE, BOND_BONDING); 161 testSendIntentNoPendingDevice(BOND_NONE, badBondState, BOND_NONE, 162 false, BOND_NONE, BOND_NONE); 163 testSendIntentNoPendingDevice(BOND_BONDING, BOND_NONE, BOND_NONE, 164 true, BOND_BONDING, BOND_NONE); 165 testSendIntentNoPendingDevice(BOND_BONDING, BOND_BONDING, BOND_BONDING, 166 false, BOND_NONE, BOND_NONE); 167 testSendIntentNoPendingDevice(BOND_BONDING, BOND_BONDED, BOND_BONDED, 168 false, BOND_NONE, BOND_NONE); 169 testSendIntentNoPendingDevice(BOND_BONDING, badBondState, BOND_BONDING, 170 false, BOND_NONE, BOND_NONE); 171 testSendIntentNoPendingDevice(BOND_BONDED, BOND_NONE, BOND_NONE, 172 true, BOND_BONDED, BOND_NONE); 173 testSendIntentNoPendingDevice(BOND_BONDED, BOND_BONDING, BOND_BONDING, 174 true, BOND_BONDED, BOND_BONDING); 175 testSendIntentNoPendingDevice(BOND_BONDED, BOND_BONDED, BOND_BONDED, 176 false, BOND_NONE, BOND_NONE); 177 testSendIntentNoPendingDevice(BOND_BONDED, badBondState, BOND_BONDED, 178 false, BOND_NONE, BOND_NONE); 179 180 // Uuid not available, mPendingBondedDevice contains a remote device. 181 testSendIntentPendingDevice(BOND_NONE, BOND_NONE, BOND_NONE, 182 false, BOND_NONE, BOND_NONE); 183 testSendIntentPendingDevice(BOND_NONE, BOND_BONDING, BOND_NONE, 184 false, BOND_NONE, BOND_NONE); 185 testSendIntentPendingDevice(BOND_NONE, BOND_BONDED, BOND_NONE, 186 false, BOND_NONE, BOND_NONE); 187 testSendIntentPendingDevice(BOND_NONE, badBondState, BOND_NONE, 188 false, BOND_NONE, BOND_NONE); 189 testSendIntentPendingDevice(BOND_BONDING, BOND_NONE, BOND_BONDING, 190 false, BOND_NONE, BOND_NONE); 191 testSendIntentPendingDevice(BOND_BONDING, BOND_BONDING, BOND_BONDING, 192 false, BOND_NONE, BOND_NONE); 193 testSendIntentPendingDevice(BOND_BONDING, BOND_BONDED, BOND_BONDING, 194 false, BOND_NONE, BOND_NONE); 195 testSendIntentPendingDevice(BOND_BONDING, badBondState, BOND_BONDING, 196 false, BOND_NONE, BOND_NONE); 197 testSendIntentPendingDevice(BOND_BONDED, BOND_NONE, BOND_NONE, 198 true, BOND_BONDING, BOND_NONE); 199 testSendIntentPendingDevice(BOND_BONDED, BOND_BONDING, BOND_BONDING, 200 false, BOND_NONE, BOND_NONE); 201 testSendIntentPendingDevice(BOND_BONDED, BOND_BONDED, BOND_BONDED, 202 false, BOND_NONE, BOND_NONE); 203 testSendIntentPendingDevice(BOND_BONDED, badBondState, BOND_BONDED, 204 false, BOND_NONE, BOND_NONE); 205 206 // Uuid available, mPendingBondedDevice is empty. 207 testSendIntentNoPendingDeviceWithUuid(BOND_NONE, BOND_NONE, BOND_NONE, 208 false, BOND_NONE, BOND_NONE); 209 testSendIntentNoPendingDeviceWithUuid(BOND_NONE, BOND_BONDING, BOND_BONDING, 210 true, BOND_NONE, BOND_BONDING); 211 testSendIntentNoPendingDeviceWithUuid(BOND_NONE, BOND_BONDED, BOND_BONDED, 212 true, BOND_NONE, BOND_BONDED); 213 testSendIntentNoPendingDeviceWithUuid(BOND_NONE, badBondState, BOND_NONE, 214 false, BOND_NONE, BOND_NONE); 215 testSendIntentNoPendingDeviceWithUuid(BOND_BONDING, BOND_NONE, BOND_NONE, 216 true, BOND_BONDING, BOND_NONE); 217 testSendIntentNoPendingDeviceWithUuid(BOND_BONDING, BOND_BONDING, BOND_BONDING, 218 false, BOND_NONE, BOND_NONE); 219 testSendIntentNoPendingDeviceWithUuid(BOND_BONDING, BOND_BONDED, BOND_BONDED, 220 true, BOND_BONDING, BOND_BONDED); 221 testSendIntentNoPendingDeviceWithUuid(BOND_BONDING, badBondState, BOND_BONDING, 222 false, BOND_NONE, BOND_NONE); 223 testSendIntentNoPendingDeviceWithUuid(BOND_BONDED, BOND_NONE, BOND_NONE, 224 true, BOND_BONDED, BOND_NONE); 225 testSendIntentNoPendingDeviceWithUuid(BOND_BONDED, BOND_BONDING, BOND_BONDING, 226 true, BOND_BONDED, BOND_BONDING); 227 testSendIntentNoPendingDeviceWithUuid(BOND_BONDED, BOND_BONDED, BOND_BONDED, 228 false, BOND_NONE, BOND_NONE); 229 testSendIntentNoPendingDeviceWithUuid(BOND_BONDED, badBondState, BOND_BONDED, 230 false, BOND_NONE, BOND_NONE); 231 232 // Uuid available, mPendingBondedDevice contains a remote device. 233 testSendIntentPendingDeviceWithUuid(BOND_NONE, BOND_NONE, BOND_NONE, 234 false, BOND_NONE, BOND_NONE); 235 testSendIntentPendingDeviceWithUuid(BOND_NONE, BOND_BONDING, BOND_NONE, 236 false, BOND_NONE, BOND_NONE); 237 testSendIntentPendingDeviceWithUuid(BOND_NONE, BOND_BONDED, BOND_NONE, 238 false, BOND_NONE, BOND_NONE); 239 testSendIntentPendingDeviceWithUuid(BOND_NONE, badBondState, BOND_NONE, 240 false, BOND_NONE, BOND_NONE); 241 testSendIntentPendingDeviceWithUuid(BOND_BONDING, BOND_NONE, BOND_BONDING, 242 false, BOND_NONE, BOND_NONE); 243 testSendIntentPendingDeviceWithUuid(BOND_BONDING, BOND_BONDING, BOND_BONDING, 244 false, BOND_NONE, BOND_NONE); 245 testSendIntentPendingDeviceWithUuid(BOND_BONDING, BOND_BONDED, BOND_BONDING, 246 false, BOND_NONE, BOND_NONE); 247 testSendIntentPendingDeviceWithUuid(BOND_BONDING, badBondState, BOND_BONDING, 248 false, BOND_NONE, BOND_NONE); 249 testSendIntentPendingDeviceWithUuid(BOND_BONDED, BOND_NONE, BOND_NONE, 250 true, BOND_BONDING, BOND_NONE); 251 testSendIntentPendingDeviceWithUuid(BOND_BONDED, BOND_BONDING, BOND_BONDING, 252 false, BOND_NONE, BOND_NONE); 253 testSendIntentPendingDeviceWithUuid(BOND_BONDED, BOND_BONDED, BOND_BONDED, 254 true, BOND_BONDING, BOND_BONDED); 255 testSendIntentPendingDeviceWithUuid(BOND_BONDED, badBondState, BOND_BONDED, 256 false, BOND_NONE, BOND_NONE); 257 258 /* Low energy test cases */ 259 testSendIntentBle(BOND_NONE, BOND_NONE, BOND_NONE); 260 testSendIntentBle(BOND_NONE, BOND_BONDING, BOND_BONDING); 261 testSendIntentBle(BOND_NONE, BOND_BONDED, BOND_BONDED); 262 testSendIntentBle(BOND_BONDING, BOND_NONE, BOND_NONE); 263 testSendIntentBle(BOND_BONDING, BOND_BONDING, BOND_BONDING); 264 testSendIntentBle(BOND_BONDING, BOND_BONDED, BOND_BONDED); 265 testSendIntentBle(BOND_BONDED, BOND_NONE, BOND_NONE); 266 testSendIntentBle(BOND_BONDED, BOND_BONDING, BOND_BONDING); 267 testSendIntentBle(BOND_BONDED, BOND_BONDED, BOND_BONDED); 268 } 269 testSendIntentCase(int oldState, int newState, int expectedNewState, boolean shouldBroadcast, int broadcastOldState, int broadcastNewState)270 private void testSendIntentCase(int oldState, int newState, int expectedNewState, 271 boolean shouldBroadcast, int broadcastOldState, int broadcastNewState) { 272 ArgumentCaptor<Intent> intentArgument = ArgumentCaptor.forClass(Intent.class); 273 274 // Setup old state before start test. 275 mDeviceProperties.mBondState = oldState; 276 277 try { 278 mBondStateMachine.sendIntent(mDevice, newState, TEST_BOND_REASON); 279 } catch (IllegalArgumentException e) { 280 // Do nothing. 281 } 282 Assert.assertEquals(expectedNewState, mDeviceProperties.getBondState()); 283 284 // Check for bond state Intent status. 285 if (shouldBroadcast) { 286 verify(mAdapterService, times(++mVerifyCount)).sendBroadcastAsUser( 287 intentArgument.capture(), eq(UserHandle.ALL), 288 eq(BLUETOOTH_CONNECT), any(Bundle.class)); 289 verifyBondStateChangeIntent(broadcastOldState, broadcastNewState, 290 intentArgument.getValue()); 291 } else { 292 verify(mAdapterService, times(mVerifyCount)).sendBroadcastAsUser(any(Intent.class), 293 any(UserHandle.class), anyString(), any(Bundle.class)); 294 } 295 } 296 testSendIntentNoPendingDeviceWithUuid(int oldState, int newState, int expectedNewState, boolean shouldBroadcast, int broadcastOldState, int broadcastNewState)297 private void testSendIntentNoPendingDeviceWithUuid(int oldState, int newState, 298 int expectedNewState, boolean shouldBroadcast, int broadcastOldState, 299 int broadcastNewState) { 300 // Add dummy UUID for the device. 301 mDeviceProperties.mUuids = TEST_UUIDS; 302 testSendIntentNoPendingDevice(oldState, newState, expectedNewState, shouldBroadcast, 303 broadcastOldState, broadcastNewState); 304 } 305 testSendIntentPendingDeviceWithUuid(int oldState, int newState, int expectedNewState, boolean shouldBroadcast, int broadcastOldState, int broadcastNewState)306 private void testSendIntentPendingDeviceWithUuid(int oldState, int newState, 307 int expectedNewState, boolean shouldBroadcast, int broadcastOldState, 308 int broadcastNewState) { 309 // Add dummy UUID for the device. 310 mDeviceProperties.mUuids = TEST_UUIDS; 311 testSendIntentPendingDevice(oldState, newState, expectedNewState, shouldBroadcast, 312 broadcastOldState, broadcastNewState); 313 } 314 testSendIntentPendingDevice(int oldState, int newState, int expectedNewState, boolean shouldBroadcast, int broadcastOldState, int broadcastNewState)315 private void testSendIntentPendingDevice(int oldState, int newState, int expectedNewState, 316 boolean shouldBroadcast, int broadcastOldState, int broadcastNewState) { 317 // Test for classic remote device. 318 mDeviceProperties.mDeviceType = BluetoothDevice.DEVICE_TYPE_CLASSIC; 319 mBondStateMachine.mPendingBondedDevices.clear(); 320 mBondStateMachine.mPendingBondedDevices.add(mDevice); 321 testSendIntentCase(oldState, newState, expectedNewState, shouldBroadcast, 322 broadcastOldState, broadcastNewState); 323 324 // Test for dual-mode remote device. 325 mDeviceProperties.mDeviceType = BluetoothDevice.DEVICE_TYPE_DUAL; 326 mBondStateMachine.mPendingBondedDevices.clear(); 327 mBondStateMachine.mPendingBondedDevices.add(mDevice); 328 testSendIntentCase(oldState, newState, expectedNewState, shouldBroadcast, 329 broadcastOldState, broadcastNewState); 330 } 331 testSendIntentNoPendingDevice(int oldState, int newState, int expectedNewState, boolean shouldBroadcast, int broadcastOldState, int broadcastNewState)332 private void testSendIntentNoPendingDevice(int oldState, int newState, int expectedNewState, 333 boolean shouldBroadcast, int broadcastOldState, int broadcastNewState) { 334 // Test for classic remote device. 335 mDeviceProperties.mDeviceType = BluetoothDevice.DEVICE_TYPE_CLASSIC; 336 mBondStateMachine.mPendingBondedDevices.clear(); 337 testSendIntentCase(oldState, newState, expectedNewState, shouldBroadcast, 338 broadcastOldState, broadcastNewState); 339 340 // Test for dual-mode remote device. 341 mDeviceProperties.mDeviceType = BluetoothDevice.DEVICE_TYPE_DUAL; 342 mBondStateMachine.mPendingBondedDevices.clear(); 343 testSendIntentCase(oldState, newState, expectedNewState, shouldBroadcast, 344 broadcastOldState, broadcastNewState); 345 } 346 testSendIntentBle(int oldState, int newState, int expectedNewState)347 private void testSendIntentBle(int oldState, int newState, int expectedNewState) { 348 // Test for low energy remote device. 349 mDeviceProperties.mDeviceType = BluetoothDevice.DEVICE_TYPE_LE; 350 mBondStateMachine.mPendingBondedDevices.clear(); 351 testSendIntentCase(oldState, newState, newState, (oldState != newState), 352 oldState, newState); 353 } 354 verifyBondStateChangeIntent(int oldState, int newState, Intent intent)355 private void verifyBondStateChangeIntent(int oldState, int newState, Intent intent) { 356 Assert.assertNotNull(intent); 357 Assert.assertEquals(BluetoothDevice.ACTION_BOND_STATE_CHANGED, intent.getAction()); 358 Assert.assertEquals(mDevice, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); 359 Assert.assertEquals(newState, intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1)); 360 Assert.assertEquals(oldState, intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, 361 -1)); 362 if (newState == BOND_NONE) { 363 Assert.assertEquals(TEST_BOND_REASON, intent.getIntExtra(BluetoothDevice.EXTRA_REASON, 364 -1)); 365 } else { 366 Assert.assertEquals(-1, intent.getIntExtra(BluetoothDevice.EXTRA_REASON, -1)); 367 } 368 } 369 } 370