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