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