1 /*
2  * Copyright (C) 2010 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 
17 package android.bluetooth;
18 
19 import android.content.Context;
20 import android.test.InstrumentationTestCase;
21 
22 /**
23  * Stress test suite for Bluetooth related functions.
24  *
25  * Includes tests for enabling/disabling bluetooth, enabling/disabling discoverable mode,
26  * starting/stopping scans, connecting/disconnecting to HFP, A2DP, HID, PAN profiles, and verifying
27  * that remote connections/disconnections occur for the PAN profile.
28  * <p>
29  * This test suite uses {@link android.bluetooth.BluetoothTestRunner} to for parameters such as the
30  * number of iterations and the addresses of remote Bluetooth devices.
31  */
32 public class BluetoothStressTest extends InstrumentationTestCase {
33     private static final String TAG = "BluetoothStressTest";
34     private static final String OUTPUT_FILE = "BluetoothStressTestOutput.txt";
35     /** The amount of time to sleep between issuing start/stop SCO in ms. */
36     private static final long SCO_SLEEP_TIME = 2 * 1000;
37 
38     private BluetoothAdapter mAdapter;
39     private BluetoothTestUtils mTestUtils;
40 
41     @Override
setUp()42     protected void setUp() throws Exception {
43         super.setUp();
44 
45         Context context = getInstrumentation().getTargetContext();
46         mAdapter = BluetoothAdapter.getDefaultAdapter();
47         mTestUtils = new BluetoothTestUtils(context, TAG, OUTPUT_FILE);
48 
49         // Start all tests in a disabled state.
50         if (mAdapter.isEnabled()) {
51             mTestUtils.disable(mAdapter);
52         }
53     }
54 
55     @Override
tearDown()56     protected void tearDown() throws Exception {
57         super.tearDown();
58         mTestUtils.close();
59     }
60 
61     /**
62      * Stress test for enabling and disabling Bluetooth.
63      */
testEnable()64     public void testEnable() {
65         int iterations = BluetoothTestRunner.sEnableIterations;
66         if (iterations == 0) {
67             return;
68         }
69 
70         for (int i = 0; i < iterations; i++) {
71             mTestUtils.writeOutput("enable iteration " + (i + 1) + " of " + iterations);
72             mTestUtils.enable(mAdapter);
73             mTestUtils.disable(mAdapter);
74         }
75     }
76 
77     /**
78      * Stress test for putting the device in and taking the device out of discoverable mode.
79      */
testDiscoverable()80     public void testDiscoverable() {
81         int iterations = BluetoothTestRunner.sDiscoverableIterations;
82         if (iterations == 0) {
83             return;
84         }
85 
86         mTestUtils.enable(mAdapter);
87         mTestUtils.undiscoverable(mAdapter);
88 
89         for (int i = 0; i < iterations; i++) {
90             mTestUtils.writeOutput("discoverable iteration " + (i + 1) + " of " + iterations);
91             mTestUtils.discoverable(mAdapter);
92             mTestUtils.undiscoverable(mAdapter);
93         }
94     }
95 
96     /**
97      * Stress test for starting and stopping Bluetooth scans.
98      */
testScan()99     public void testScan() {
100         int iterations = BluetoothTestRunner.sScanIterations;
101         if (iterations == 0) {
102             return;
103         }
104 
105         mTestUtils.enable(mAdapter);
106         mTestUtils.stopScan(mAdapter);
107 
108         for (int i = 0; i < iterations; i++) {
109             mTestUtils.writeOutput("scan iteration " + (i + 1) + " of " + iterations);
110             mTestUtils.startScan(mAdapter);
111             mTestUtils.stopScan(mAdapter);
112         }
113     }
114 
115     /**
116      * Stress test for enabling and disabling the PAN NAP profile.
117      */
testEnablePan()118     public void testEnablePan() {
119         int iterations = BluetoothTestRunner.sEnablePanIterations;
120         if (iterations == 0) {
121             return;
122         }
123 
124         mTestUtils.enable(mAdapter);
125         mTestUtils.disablePan(mAdapter);
126 
127         for (int i = 0; i < iterations; i++) {
128             mTestUtils.writeOutput("testEnablePan iteration " + (i + 1) + " of "
129                     + iterations);
130             mTestUtils.enablePan(mAdapter);
131             mTestUtils.disablePan(mAdapter);
132         }
133     }
134 
135     /**
136      * Stress test for pairing and unpairing with a remote device.
137      * <p>
138      * In this test, the local device initiates pairing with a remote device, and then unpairs with
139      * the device after the pairing has successfully completed.
140      */
testPair()141     public void testPair() {
142         int iterations = BluetoothTestRunner.sPairIterations;
143         if (iterations == 0) {
144             return;
145         }
146 
147         BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
148         mTestUtils.enable(mAdapter);
149         mTestUtils.unpair(mAdapter, device);
150 
151         for (int i = 0; i < iterations; i++) {
152             mTestUtils.writeOutput("pair iteration " + (i + 1) + " of " + iterations);
153             mTestUtils.pair(mAdapter, device, BluetoothTestRunner.sDevicePairPasskey,
154                     BluetoothTestRunner.sDevicePairPin);
155             mTestUtils.unpair(mAdapter, device);
156         }
157     }
158 
159     /**
160      * Stress test for accepting a pairing request and unpairing with a remote device.
161      * <p>
162      * In this test, the local device waits for a pairing request from a remote device.  It accepts
163      * the request and then unpairs after the paring has successfully completed.
164      */
testAcceptPair()165     public void testAcceptPair() {
166         int iterations = BluetoothTestRunner.sPairIterations;
167         if (iterations == 0) {
168             return;
169         }
170         BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
171         mTestUtils.enable(mAdapter);
172         mTestUtils.unpair(mAdapter, device);
173 
174         for (int i = 0; i < iterations; i++) {
175             mTestUtils.writeOutput("acceptPair iteration " + (i + 1) + " of " + iterations);
176             mTestUtils.acceptPair(mAdapter, device, BluetoothTestRunner.sDevicePairPasskey,
177                     BluetoothTestRunner.sDevicePairPin);
178             mTestUtils.unpair(mAdapter, device);
179         }
180     }
181 
182     /**
183      * Stress test for connecting and disconnecting with an A2DP source.
184      * <p>
185      * In this test, the local device plays the role of an A2DP sink, and initiates connections and
186      * disconnections with an A2DP source.
187      */
testConnectA2dp()188     public void testConnectA2dp() {
189         int iterations = BluetoothTestRunner.sConnectA2dpIterations;
190         if (iterations == 0) {
191             return;
192         }
193 
194         BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
195         mTestUtils.enable(mAdapter);
196         mTestUtils.unpair(mAdapter, device);
197         mTestUtils.pair(mAdapter, device, BluetoothTestRunner.sDevicePairPasskey,
198                 BluetoothTestRunner.sDevicePairPin);
199         mTestUtils.disconnectProfile(mAdapter, device, BluetoothProfile.A2DP, null);
200 
201         for (int i = 0; i < iterations; i++) {
202             mTestUtils.writeOutput("connectA2dp iteration " + (i + 1) + " of " + iterations);
203             mTestUtils.connectProfile(mAdapter, device, BluetoothProfile.A2DP,
204                     String.format("connectA2dp(device=%s)", device));
205             mTestUtils.disconnectProfile(mAdapter, device, BluetoothProfile.A2DP,
206                     String.format("disconnectA2dp(device=%s)", device));
207         }
208 
209         mTestUtils.unpair(mAdapter, device);
210     }
211 
212     /**
213      * Stress test for connecting and disconnecting the HFP with a hands free device.
214      * <p>
215      * In this test, the local device plays the role of an HFP audio gateway, and initiates
216      * connections and disconnections with a hands free device.
217      */
testConnectHeadset()218     public void testConnectHeadset() {
219         int iterations = BluetoothTestRunner.sConnectHeadsetIterations;
220         if (iterations == 0) {
221             return;
222         }
223 
224         BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
225         mTestUtils.enable(mAdapter);
226         mTestUtils.unpair(mAdapter, device);
227         mTestUtils.pair(mAdapter, device, BluetoothTestRunner.sDevicePairPasskey,
228                 BluetoothTestRunner.sDevicePairPin);
229         mTestUtils.disconnectProfile(mAdapter, device, BluetoothProfile.HEADSET, null);
230 
231         for (int i = 0; i < iterations; i++) {
232             mTestUtils.writeOutput("connectHeadset iteration " + (i + 1) + " of " + iterations);
233             mTestUtils.connectProfile(mAdapter, device, BluetoothProfile.HEADSET,
234                     String.format("connectHeadset(device=%s)", device));
235             mTestUtils.disconnectProfile(mAdapter, device, BluetoothProfile.HEADSET,
236                     String.format("disconnectHeadset(device=%s)", device));
237         }
238 
239         mTestUtils.unpair(mAdapter, device);
240     }
241 
242     /**
243      * Stress test for connecting and disconnecting with a HID device.
244      * <p>
245      * In this test, the local device plays the role of a HID host, and initiates connections and
246      * disconnections with a HID device.
247      */
testConnectInput()248     public void testConnectInput() {
249         int iterations = BluetoothTestRunner.sConnectInputIterations;
250         if (iterations == 0) {
251             return;
252         }
253 
254         BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
255         mTestUtils.enable(mAdapter);
256         mTestUtils.unpair(mAdapter, device);
257         mTestUtils.pair(mAdapter, device, BluetoothTestRunner.sDevicePairPasskey,
258                 BluetoothTestRunner.sDevicePairPin);
259         mTestUtils.disconnectProfile(mAdapter, device, BluetoothProfile.HID_HOST, null);
260 
261         for (int i = 0; i < iterations; i++) {
262             mTestUtils.writeOutput("connectInput iteration " + (i + 1) + " of " + iterations);
263             mTestUtils.connectProfile(mAdapter, device, BluetoothProfile.HID_HOST,
264                     String.format("connectInput(device=%s)", device));
265             mTestUtils.disconnectProfile(mAdapter, device, BluetoothProfile.HID_HOST,
266                     String.format("disconnectInput(device=%s)", device));
267         }
268 
269         mTestUtils.unpair(mAdapter, device);
270     }
271 
272     /**
273      * Stress test for connecting and disconnecting with a PAN NAP.
274      * <p>
275      * In this test, the local device plays the role of a PANU, and initiates connections and
276      * disconnections with a NAP.
277      */
testConnectPan()278     public void testConnectPan() {
279         int iterations = BluetoothTestRunner.sConnectPanIterations;
280         if (iterations == 0) {
281             return;
282         }
283 
284         BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
285         mTestUtils.enable(mAdapter);
286         mTestUtils.unpair(mAdapter, device);
287         mTestUtils.pair(mAdapter, device, BluetoothTestRunner.sDevicePairPasskey,
288                 BluetoothTestRunner.sDevicePairPin);
289 
290         for (int i = 0; i < iterations; i++) {
291             mTestUtils.writeOutput("connectPan iteration " + (i + 1) + " of " + iterations);
292             mTestUtils.connectPan(mAdapter, device);
293             mTestUtils.disconnectPan(mAdapter, device);
294         }
295 
296         mTestUtils.unpair(mAdapter, device);
297     }
298 
299     /**
300      * Stress test for verifying a PANU connecting and disconnecting with the device.
301      * <p>
302      * In this test, the local device plays the role of a NAP which a remote PANU connects and
303      * disconnects from.
304      */
testIncomingPanConnection()305     public void testIncomingPanConnection() {
306         int iterations = BluetoothTestRunner.sConnectPanIterations;
307         if (iterations == 0) {
308             return;
309         }
310 
311         BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
312         mTestUtils.enable(mAdapter);
313         mTestUtils.disablePan(mAdapter);
314         mTestUtils.enablePan(mAdapter);
315         mTestUtils.unpair(mAdapter, device);
316         mTestUtils.acceptPair(mAdapter, device, BluetoothTestRunner.sDevicePairPasskey,
317                 BluetoothTestRunner.sDevicePairPin);
318 
319         for (int i = 0; i < iterations; i++) {
320             mTestUtils.writeOutput("incomingPanConnection iteration " + (i + 1) + " of "
321                     + iterations);
322             mTestUtils.incomingPanConnection(mAdapter, device);
323             mTestUtils.incomingPanDisconnection(mAdapter, device);
324         }
325 
326         mTestUtils.unpair(mAdapter, device);
327         mTestUtils.disablePan(mAdapter);
328     }
329 
330     /**
331      * Stress test for verifying that AudioManager can open and close SCO connections.
332      * <p>
333      * In this test, a HSP connection is opened with an external headset and the SCO connection is
334      * repeatibly opened and closed.
335      */
testStartStopSco()336     public void testStartStopSco() {
337         int iterations = BluetoothTestRunner.sStartStopScoIterations;
338         if (iterations == 0) {
339             return;
340         }
341 
342         BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
343         mTestUtils.enable(mAdapter);
344         mTestUtils.unpair(mAdapter, device);
345         mTestUtils.pair(mAdapter, device, BluetoothTestRunner.sDevicePairPasskey,
346                 BluetoothTestRunner.sDevicePairPin);
347         mTestUtils.disconnectProfile(mAdapter, device, BluetoothProfile.HEADSET, null);
348         mTestUtils.connectProfile(mAdapter, device, BluetoothProfile.HEADSET, null);
349         mTestUtils.stopSco(mAdapter, device);
350 
351         for (int i = 0; i < iterations; i++) {
352             mTestUtils.writeOutput("startStopSco iteration " + (i + 1) + " of " + iterations);
353             mTestUtils.startSco(mAdapter, device);
354             sleep(SCO_SLEEP_TIME);
355             mTestUtils.stopSco(mAdapter, device);
356             sleep(SCO_SLEEP_TIME);
357         }
358 
359         mTestUtils.disconnectProfile(mAdapter, device, BluetoothProfile.HEADSET, null);
360         mTestUtils.unpair(mAdapter, device);
361     }
362 
sleep(long time)363     private void sleep(long time) {
364         try {
365             Thread.sleep(time);
366         } catch (InterruptedException e) {
367         }
368     }
369 }
370