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