• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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