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