blob: e9311e08f2eadbefca1365125a1b203cdb61df75 [file] [log] [blame]
Eric Rowe13438b022010-08-30 16:14:08 -07001/*
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.bluetooth.BluetoothHeadset.ServiceListener;
20import android.content.BroadcastReceiver;
21import android.content.Context;
22import android.content.Intent;
23import android.content.IntentFilter;
24import android.os.Environment;
25import android.util.Log;
26
27import junit.framework.Assert;
28
29import java.io.BufferedWriter;
30import java.io.File;
31import java.io.FileWriter;
32import java.io.IOException;
33
34public class BluetoothTestUtils extends Assert {
35
36 /**
37 * Timeout for {@link BluetoothAdapter#disable()} in ms.
38 */
39 private static final int DISABLE_TIMEOUT = 5000;
40
41 /**
42 * Timeout for {@link BluetoothAdapter#enable()} in ms.
43 */
44 private static final int ENABLE_TIMEOUT = 20000;
45
46 /**
47 * Timeout for {@link BluetoothAdapter#setScanMode(int)} in ms.
48 */
49 private static final int SET_SCAN_MODE_TIMEOUT = 5000;
50
51 /**
52 * Timeout for {@link BluetoothAdapter#startDiscovery()} in ms.
53 */
54 private static final int START_DISCOVERY_TIMEOUT = 5000;
55
56 /**
57 * Timeout for {@link BluetoothAdapter#cancelDiscovery()} in ms.
58 */
59 private static final int CANCEL_DISCOVERY_TIMEOUT = 5000;
60
61 /**
62 * Timeout for {@link BluetoothDevice#createBond()} in ms.
63 */
64 private static final int PAIR_TIMEOUT = 20000;
65
66 /**
67 * Timeout for {@link BluetoothDevice#removeBond()} in ms.
68 */
69 private static final int UNPAIR_TIMEOUT = 20000;
70
71 /**
72 * Timeout for {@link BluetoothA2dp#connectSink(BluetoothDevice)} in ms.
73 */
74 private static final int CONNECT_A2DP_TIMEOUT = 20000;
75
76 /**
77 * Timeout for {@link BluetoothA2dp#disconnectSink(BluetoothDevice)} in ms.
78 */
79 private static final int DISCONNECT_A2DP_TIMEOUT = 20000;
80
81 /**
82 * Timeout for {@link BluetoothHeadset#connectHeadset(BluetoothDevice)} in ms.
83 */
84 private static final int CONNECT_HEADSET_TIMEOUT = 20000;
85
86 /**
87 * Timeout for {@link BluetoothHeadset#disconnectHeadset(BluetoothDevice)} in ms.
88 */
89 private static final int DISCONNECT_HEADSET_TIMEOUT = 20000;
90
91 private static final int DISCOVERY_STARTED_FLAG = 1;
92 private static final int DISCOVERY_FINISHED_FLAG = 1 << 1;
93 private static final int SCAN_MODE_NONE_FLAG = 1 << 2;
94 private static final int SCAN_MODE_CONNECTABLE_FLAG = 1 << 3;
95 private static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE_FLAG = 1 << 4;
96 private static final int STATE_OFF_FLAG = 1 << 5;
97 private static final int STATE_TURNING_ON_FLAG = 1 << 6;
98 private static final int STATE_ON_FLAG = 1 << 7;
99 private static final int STATE_TURNING_OFF_FLAG = 1 << 8;
100 private static final int PAIR_STATE_FLAG = 1 << 9;
101 private static final int PROFILE_A2DP_FLAG = 1 << 10;
102 private static final int PROFILE_HEADSET_FLAG = 1 << 11;
103
104 private static final int PAIR_STATE_BONDED = 1;
105 private static final int PAIR_STATE_BONDING = 1 << 1;
106 private static final int PAIR_STATE_NONE = 1 << 2;
107
108 private static final int A2DP_STATE_DISCONNECTED = 1;
109 private static final int A2DP_STATE_CONNECTING = 1 << 1;
110 private static final int A2DP_STATE_CONNECTED = 1 << 2;
111 private static final int A2DP_STATE_DISCONNECTING = 1 << 3;
112 private static final int A2DP_STATE_PLAYING = 1 << 4;
113
114 private static final int HEADSET_STATE_DISCONNECTED = 1;
115 private static final int HEADSET_STATE_CONNECTING = 1 << 1;
116 private static final int HEADSET_STATE_CONNECTED = 1 << 2;
117
118 /**
119 * Time between polls in ms.
120 */
121 private static final int POLL_TIME = 100;
122
123 private Context mContext;
124
125 private BufferedWriter mOutputWriter;
126
127 private BluetoothA2dp mA2dp;
128
129 private BluetoothHeadset mHeadset;
130
131 private String mOutputFile;
132 private String mTag;
133 private class HeadsetServiceListener implements ServiceListener {
134 private boolean mConnected = false;
135
136 @Override
137 public void onServiceConnected() {
138 synchronized (this) {
139 mConnected = true;
140 }
141 }
142
143 @Override
144 public void onServiceDisconnected() {
145 synchronized (this) {
146 mConnected = false;
147 }
148 }
149
150 public boolean isConnected() {
151 synchronized (this) {
152 return mConnected;
153 }
154 }
155 }
156
157 private HeadsetServiceListener mHeadsetServiceListener = new HeadsetServiceListener();
158
159 private class BluetoothReceiver extends BroadcastReceiver {
160 private int mFiredFlags = 0;
161 private int mPairFiredFlags = 0;
162 private int mA2dpFiredFlags = 0;
163 private int mHeadsetFiredFlags = 0;
164
165 @Override
166 public void onReceive(Context context, Intent intent) {
167 synchronized (this) {
168 if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(intent.getAction())) {
169 mFiredFlags |= DISCOVERY_STARTED_FLAG;
170 } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(intent.getAction())) {
171 mFiredFlags |= DISCOVERY_FINISHED_FLAG;
172 } else if (BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(intent.getAction())) {
173 int mode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE,
174 BluetoothAdapter.ERROR);
175 assertNotSame(mode, BluetoothAdapter.ERROR);
176 switch (mode) {
177 case BluetoothAdapter.SCAN_MODE_NONE:
178 mFiredFlags |= SCAN_MODE_NONE_FLAG;
179 break;
180 case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
181 mFiredFlags |= SCAN_MODE_CONNECTABLE_FLAG;
182 break;
183 case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
184 mFiredFlags |= SCAN_MODE_CONNECTABLE_DISCOVERABLE_FLAG;
185 break;
186 }
187 } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
188 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
189 BluetoothAdapter.ERROR);
190 assertNotSame(state, BluetoothAdapter.ERROR);
191 switch (state) {
192 case BluetoothAdapter.STATE_OFF:
193 mFiredFlags |= STATE_OFF_FLAG;
194 break;
195 case BluetoothAdapter.STATE_TURNING_ON:
196 mFiredFlags |= STATE_TURNING_ON_FLAG;
197 break;
198 case BluetoothAdapter.STATE_ON:
199 mFiredFlags |= STATE_ON_FLAG;
200 break;
201 case BluetoothAdapter.STATE_TURNING_OFF:
202 mFiredFlags |= STATE_TURNING_OFF_FLAG;
203 break;
204 }
205 } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(intent.getAction())) {
206 mFiredFlags |= PAIR_STATE_FLAG;
207 int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1);
208 assertNotSame(state, -1);
209 switch (state) {
210 case BluetoothDevice.BOND_BONDED:
211 mPairFiredFlags |= PAIR_STATE_BONDED;
212 break;
213 case BluetoothDevice.BOND_BONDING:
214 mPairFiredFlags |= PAIR_STATE_BONDING;
215 break;
216 case BluetoothDevice.BOND_NONE:
217 mPairFiredFlags |= PAIR_STATE_NONE;
218 break;
219 }
220 } else if (BluetoothA2dp.ACTION_SINK_STATE_CHANGED.equals(intent.getAction())) {
221 mFiredFlags |= PROFILE_A2DP_FLAG;
222 int state = intent.getIntExtra(BluetoothA2dp.EXTRA_SINK_STATE, -1);
223 assertNotSame(state, -1);
224 switch (state) {
225 case BluetoothA2dp.STATE_DISCONNECTED:
226 mA2dpFiredFlags |= A2DP_STATE_DISCONNECTED;
227 break;
228 case BluetoothA2dp.STATE_CONNECTING:
229 mA2dpFiredFlags |= A2DP_STATE_CONNECTING;
230 break;
231 case BluetoothA2dp.STATE_CONNECTED:
232 mA2dpFiredFlags |= A2DP_STATE_CONNECTED;
233 break;
234 case BluetoothA2dp.STATE_DISCONNECTING:
235 mA2dpFiredFlags |= A2DP_STATE_DISCONNECTING;
236 break;
237 case BluetoothA2dp.STATE_PLAYING:
238 mA2dpFiredFlags |= A2DP_STATE_PLAYING;
239 break;
240 }
241 } else if (BluetoothHeadset.ACTION_STATE_CHANGED.equals(intent.getAction())) {
242 mFiredFlags |= PROFILE_HEADSET_FLAG;
243 int state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE,
244 BluetoothHeadset.STATE_ERROR);
245 assertNotSame(state, BluetoothHeadset.STATE_ERROR);
246 switch (state) {
247 case BluetoothHeadset.STATE_DISCONNECTED:
248 mHeadsetFiredFlags |= HEADSET_STATE_DISCONNECTED;
249 break;
250 case BluetoothHeadset.STATE_CONNECTING:
251 mHeadsetFiredFlags |= HEADSET_STATE_CONNECTING;
252 break;
253 case BluetoothHeadset.STATE_CONNECTED:
254 mHeadsetFiredFlags |= HEADSET_STATE_CONNECTED;
255 break;
256 }
257 }
258 }
259 }
260
261 public int getFiredFlags() {
262 synchronized (this) {
263 return mFiredFlags;
264 }
265 }
266
267 public int getPairFiredFlags() {
268 synchronized (this) {
269 return mPairFiredFlags;
270 }
271 }
272
273 public int getA2dpFiredFlags() {
274 synchronized (this) {
275 return mA2dpFiredFlags;
276 }
277 }
278
279 public int getHeadsetFiredFlags() {
280 synchronized (this) {
281 return mHeadsetFiredFlags;
282 }
283 }
284
285 public void resetFiredFlags() {
286 synchronized (this) {
287 mFiredFlags = 0;
288 mPairFiredFlags = 0;
289 mA2dpFiredFlags = 0;
290 mHeadsetFiredFlags = 0;
291 }
292 }
293 }
294
295 private BluetoothReceiver mReceiver = new BluetoothReceiver();
296
297 public BluetoothTestUtils(Context context, String tag) {
298 this(context, tag, null);
299 }
300
301 public BluetoothTestUtils(Context context, String tag, String outputFile) {
302 mContext = context;
303 mTag = tag;
304 mOutputFile = outputFile;
305
306 if (mOutputFile == null) {
307 mOutputWriter = null;
308 } else {
309 try {
310 mOutputWriter = new BufferedWriter(new FileWriter(new File(
311 Environment.getExternalStorageDirectory(), mOutputFile), true));
312 } catch (IOException e) {
313 Log.w(mTag, "Test output file could not be opened", e);
314 mOutputWriter = null;
315 }
316 }
317
318 IntentFilter filter = new IntentFilter();
319 filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
320 filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
321 filter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
322 filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
323 mContext.registerReceiver(mReceiver, filter);
324 }
325
326 public void close() {
327 mContext.unregisterReceiver(mReceiver);
328
329 if (mOutputWriter != null) {
330 try {
331 mOutputWriter.close();
332 } catch (IOException e) {
333 Log.w(mTag, "Test output file could not be closed", e);
334 }
335 }
336 }
337
338 public void enable(BluetoothAdapter adapter) {
339 int mask = STATE_TURNING_ON_FLAG | STATE_ON_FLAG | SCAN_MODE_CONNECTABLE_FLAG;
340 mReceiver.resetFiredFlags();
341
342 int state = adapter.getState();
343 switch (state) {
344 case BluetoothAdapter.STATE_ON:
345 assertTrue(adapter.isEnabled());
346 return;
347 case BluetoothAdapter.STATE_OFF:
348 case BluetoothAdapter.STATE_TURNING_OFF:
349 assertFalse(adapter.isEnabled());
350 assertTrue(adapter.enable());
351 break;
352 case BluetoothAdapter.STATE_TURNING_ON:
353 assertFalse(adapter.isEnabled());
354 mask = 0; // Don't check for received intents since we might have missed them.
355 break;
356 default:
357 fail("enable() invalid state: state=" + state);
358 }
359
360 long s = System.currentTimeMillis();
361 while (System.currentTimeMillis() - s < ENABLE_TIMEOUT) {
362 state = adapter.getState();
363 if (state == BluetoothAdapter.STATE_ON) {
364 assertTrue(adapter.isEnabled());
365 if ((mReceiver.getFiredFlags() & mask) == mask) {
366 mReceiver.resetFiredFlags();
367 writeOutput(String.format("enable() completed in %d ms",
368 (System.currentTimeMillis() - s)));
369 return;
370 }
371 } else {
372 assertFalse(adapter.isEnabled());
373 assertEquals(BluetoothAdapter.STATE_TURNING_ON, state);
374 }
375 sleep(POLL_TIME);
376 }
377
378 int firedFlags = mReceiver.getFiredFlags();
379 mReceiver.resetFiredFlags();
380 fail(String.format("enable() timeout: state=%d (expected %d), flags=0x%x (expected 0x%x)",
381 state, BluetoothAdapter.STATE_ON, firedFlags, mask));
382 }
383
384 public void disable(BluetoothAdapter adapter) {
385 int mask = STATE_TURNING_OFF_FLAG | STATE_OFF_FLAG | SCAN_MODE_NONE_FLAG;
386 mReceiver.resetFiredFlags();
387
388 int state = adapter.getState();
389 switch (state) {
390 case BluetoothAdapter.STATE_OFF:
391 assertFalse(adapter.isEnabled());
392 return;
393 case BluetoothAdapter.STATE_ON:
394 assertTrue(adapter.isEnabled());
395 assertTrue(adapter.disable());
396 break;
397 case BluetoothAdapter.STATE_TURNING_ON:
398 assertFalse(adapter.isEnabled());
399 assertTrue(adapter.disable());
400 break;
401 case BluetoothAdapter.STATE_TURNING_OFF:
402 assertFalse(adapter.isEnabled());
403 mask = 0; // Don't check for received intents since we might have missed them.
404 break;
405 default:
406 fail("disable() invalid state: state=" + state);
407 }
408
409 long s = System.currentTimeMillis();
410 while (System.currentTimeMillis() - s < DISABLE_TIMEOUT) {
411 state = adapter.getState();
412 if (state == BluetoothAdapter.STATE_OFF) {
413 assertFalse(adapter.isEnabled());
414 if ((mReceiver.getFiredFlags() & mask) == mask) {
415 mReceiver.resetFiredFlags();
416 writeOutput(String.format("disable() completed in %d ms",
417 (System.currentTimeMillis() - s)));
418 return;
419 }
420 } else {
421 assertFalse(adapter.isEnabled());
422 assertEquals(BluetoothAdapter.STATE_TURNING_OFF, state);
423 }
424 sleep(POLL_TIME);
425 }
426
427 int firedFlags = mReceiver.getFiredFlags();
428 mReceiver.resetFiredFlags();
429 fail(String.format("disable() timeout: state=%d (expected %d), flags=0x%x (expected 0x%x)",
430 state, BluetoothAdapter.STATE_OFF, firedFlags, mask));
431 }
432
433 public void discoverable(BluetoothAdapter adapter) {
434 int mask = SCAN_MODE_CONNECTABLE_DISCOVERABLE_FLAG;
435 mReceiver.resetFiredFlags();
436
437 if (!adapter.isEnabled()) {
438 fail("discoverable() bluetooth not enabled");
439 }
440
441 int scanMode = adapter.getScanMode();
442 if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
443 return;
444 }
445
446 assertEquals(scanMode, BluetoothAdapter.SCAN_MODE_CONNECTABLE);
447 assertTrue(adapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE));
448
449 long s = System.currentTimeMillis();
450 while (System.currentTimeMillis() - s < SET_SCAN_MODE_TIMEOUT) {
451 scanMode = adapter.getScanMode();
452 if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
453 if ((mReceiver.getFiredFlags() & mask) == mask) {
454 mReceiver.resetFiredFlags();
455 writeOutput(String.format("discoverable() completed in %d ms",
456 (System.currentTimeMillis() - s)));
457 return;
458 }
459 } else {
460 assertEquals(scanMode, BluetoothAdapter.SCAN_MODE_CONNECTABLE);
461 }
462 sleep(POLL_TIME);
463 }
464
465 int firedFlags = mReceiver.getFiredFlags();
466 mReceiver.resetFiredFlags();
467 fail(String.format("discoverable() timeout: scanMode=%d (expected %d), flags=0x%x "
468 + "(expected 0x%x)", scanMode, BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE,
469 firedFlags, mask));
470 }
471
472 public void undiscoverable(BluetoothAdapter adapter) {
473 int mask = SCAN_MODE_CONNECTABLE_FLAG;
474 mReceiver.resetFiredFlags();
475
476 if (!adapter.isEnabled()) {
477 fail("undiscoverable() bluetooth not enabled");
478 }
479
480 int scanMode = adapter.getScanMode();
481 if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE) {
482 return;
483 }
484
485 assertEquals(scanMode, BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
486 assertTrue(adapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE));
487
488 long s = System.currentTimeMillis();
489 while (System.currentTimeMillis() - s < SET_SCAN_MODE_TIMEOUT) {
490 scanMode = adapter.getScanMode();
491 if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE) {
492 if ((mReceiver.getFiredFlags() & mask) == mask) {
493 mReceiver.resetFiredFlags();
494 writeOutput(String.format("undiscoverable() completed in %d ms",
495 (System.currentTimeMillis() - s)));
496 return;
497 }
498 } else {
499 assertEquals(scanMode, BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
500 }
501 sleep(POLL_TIME);
502 }
503
504 int firedFlags = mReceiver.getFiredFlags();
505 mReceiver.resetFiredFlags();
506 fail(String.format("undiscoverable() timeout: scanMode=%d (expected %d), flags=0x%x "
507 + "(expected 0x%x)", scanMode, BluetoothAdapter.SCAN_MODE_CONNECTABLE, firedFlags,
508 mask));
509 }
510
511 public void startScan(BluetoothAdapter adapter) {
512 int mask = DISCOVERY_STARTED_FLAG;
513 mReceiver.resetFiredFlags();
514
515 if (!adapter.isEnabled()) {
516 fail("startScan() bluetooth not enabled");
517 }
518
519 if (adapter.isDiscovering()) {
520 return;
521 }
522
523 assertTrue(adapter.startDiscovery());
524
525 long s = System.currentTimeMillis();
526 while (System.currentTimeMillis() - s < START_DISCOVERY_TIMEOUT) {
527 if (adapter.isDiscovering() && ((mReceiver.getFiredFlags() & mask) == mask)) {
528 mReceiver.resetFiredFlags();
529 writeOutput(String.format("startScan() completed in %d ms",
530 (System.currentTimeMillis() - s)));
531 return;
532 }
533 sleep(POLL_TIME);
534 }
535
536 int firedFlags = mReceiver.getFiredFlags();
537 mReceiver.resetFiredFlags();
538 fail(String.format("startScan() timeout: isDiscovering=%b, flags=0x%x (expected 0x%x)",
539 adapter.isDiscovering(), firedFlags, mask));
540 }
541
542 public void stopScan(BluetoothAdapter adapter) {
543 int mask = DISCOVERY_FINISHED_FLAG;
544 mReceiver.resetFiredFlags();
545
546 if (!adapter.isEnabled()) {
547 fail("stopScan() bluetooth not enabled");
548 }
549
550 if (!adapter.isDiscovering()) {
551 return;
552 }
553
554 // TODO: put assertTrue() around cancelDiscovery() once it starts returning true.
555 adapter.cancelDiscovery();
556
557 long s = System.currentTimeMillis();
558 while (System.currentTimeMillis() - s < CANCEL_DISCOVERY_TIMEOUT) {
559 if (!adapter.isDiscovering() && ((mReceiver.getFiredFlags() & mask) == mask)) {
560 mReceiver.resetFiredFlags();
561 writeOutput(String.format("stopScan() completed in %d ms",
562 (System.currentTimeMillis() - s)));
563 return;
564 }
565 sleep(POLL_TIME);
566 }
567
568 int firedFlags = mReceiver.getFiredFlags();
569 mReceiver.resetFiredFlags();
570 fail(String.format("stopScan() timeout: isDiscovering=%b, flags=0x%x (expected 0x%x)",
571 adapter.isDiscovering(), firedFlags, mask));
572
573 }
574
575 public void pair(BluetoothAdapter adapter, BluetoothDevice device) {
576 int mask = PAIR_STATE_FLAG;
577 int pairMask = PAIR_STATE_BONDING | PAIR_STATE_BONDED;
578 mReceiver.resetFiredFlags();
579
580 if (!adapter.isEnabled()) {
581 fail("pair() bluetooth not enabled");
582 }
583
584 int state = device.getBondState();
585 switch (state) {
586 case BluetoothDevice.BOND_BONDED:
587 assertTrue(adapter.getBondedDevices().contains(device));
588 return;
589 case BluetoothDevice.BOND_BONDING:
590 // Don't check for received intents since we might have missed them.
591 mask = pairMask = 0;
592 break;
593 case BluetoothDevice.BOND_NONE:
594 assertFalse(adapter.getBondedDevices().contains(device));
595 assertTrue(device.createBond());
596 break;
597 default:
598 fail("pair() invalide state: state=" + state);
599 }
600
601 long s = System.currentTimeMillis();
602 while (System.currentTimeMillis() - s < PAIR_TIMEOUT) {
603 state = device.getBondState();
604 if (state == BluetoothDevice.BOND_BONDED) {
605 assertTrue(adapter.getBondedDevices().contains(device));
606 if ((mReceiver.getFiredFlags() & mask) == mask
607 && (mReceiver.getPairFiredFlags() & pairMask) == pairMask) {
608 writeOutput(String.format("pair() completed in %d ms: device=%s",
609 (System.currentTimeMillis() - s), device));
610 return;
611 }
612 }
613 sleep(POLL_TIME);
614 }
615
616 int firedFlags = mReceiver.getFiredFlags();
617 int pairFiredFlags = mReceiver.getPairFiredFlags();
618 mReceiver.resetFiredFlags();
619 fail(String.format("pair() timeout: state=%d (expected %d), flags=0x%x (expected 0x%x), "
620 + "pairFlags=0x%x (expected 0x%x)", state, BluetoothDevice.BOND_BONDED, firedFlags,
621 mask, pairFiredFlags, pairMask));
622 }
623
624 public void unpair(BluetoothAdapter adapter, BluetoothDevice device) {
625 int mask = PAIR_STATE_FLAG;
626 int pairMask = PAIR_STATE_NONE;
627 mReceiver.resetFiredFlags();
628
629 if (!adapter.isEnabled()) {
630 fail("unpair() bluetooth not enabled");
631 }
632
633 int state = device.getBondState();
634 switch (state) {
635 case BluetoothDevice.BOND_BONDED:
636 assertTrue(adapter.getBondedDevices().contains(device));
637 assertTrue(device.removeBond());
638 break;
639 case BluetoothDevice.BOND_BONDING:
640 assertTrue(device.removeBond());
641 break;
642 case BluetoothDevice.BOND_NONE:
643 assertFalse(adapter.getBondedDevices().contains(device));
644 return;
645 default:
646 fail("unpair() invalid state: state=" + state);
647 }
648
649 assertTrue(device.removeBond());
650
651 long s = System.currentTimeMillis();
652 while (System.currentTimeMillis() - s < UNPAIR_TIMEOUT) {
653 if (device.getBondState() == BluetoothDevice.BOND_NONE) {
654 assertFalse(adapter.getBondedDevices().contains(device));
655 if ((mReceiver.getFiredFlags() & mask) == mask
656 && (mReceiver.getPairFiredFlags() & pairMask) == pairMask) {
657 writeOutput(String.format("unpair() completed in %d ms: device=%s",
658 (System.currentTimeMillis() - s), device));
659 return;
660 }
661 }
662 }
663
664 int firedFlags = mReceiver.getFiredFlags();
665 int pairFiredFlags = mReceiver.getPairFiredFlags();
666 mReceiver.resetFiredFlags();
667 fail(String.format("unpair() timeout: state=%d (expected %d), flags=0x%x (expected 0x%x), "
668 + "pairFlags=0x%x (expected 0x%x)", state, BluetoothDevice.BOND_BONDED, firedFlags,
669 mask, pairFiredFlags, pairMask));
670 }
671
672 public void connectA2dp(BluetoothAdapter adapter, BluetoothDevice device) {
673 int mask = PROFILE_A2DP_FLAG;
674 int a2dpMask1 = A2DP_STATE_CONNECTING | A2DP_STATE_CONNECTED | A2DP_STATE_PLAYING;
675 int a2dpMask2 = a2dpMask1 ^ A2DP_STATE_CONNECTED;
676 int a2dpMask3 = a2dpMask1 ^ A2DP_STATE_PLAYING;
677 mReceiver.resetFiredFlags();
678
679 if (!adapter.isEnabled()) {
680 fail("connectA2dp() bluetooth not enabled");
681 }
682
683 if (!adapter.getBondedDevices().contains(device)) {
684 fail("connectA2dp() device not paired: device=" + device);
685 }
686
687 int state = mA2dp.getSinkState(device);
688 switch (state) {
689 case BluetoothA2dp.STATE_CONNECTED:
690 case BluetoothA2dp.STATE_PLAYING:
691 assertTrue(mA2dp.isSinkConnected(device));
692 return;
693 case BluetoothA2dp.STATE_DISCONNECTING:
694 case BluetoothA2dp.STATE_DISCONNECTED:
695 assertFalse(mA2dp.isSinkConnected(device));
696 assertTrue(mA2dp.connectSink(device));
697 break;
698 case BluetoothA2dp.STATE_CONNECTING:
699 assertFalse(mA2dp.isSinkConnected(device));
700 // Don't check for received intents since we might have missed them.
701 mask = a2dpMask1 = a2dpMask2 = a2dpMask3 = 0;
702 break;
703 default:
704 fail("connectA2dp() invalid state: state=" + state);
705 }
706
707 long s = System.currentTimeMillis();
708 while (System.currentTimeMillis() - s < CONNECT_A2DP_TIMEOUT) {
709 state = mA2dp.getSinkState(device);
710 if (state == BluetoothA2dp.STATE_CONNECTED || state == BluetoothA2dp.STATE_PLAYING) {
711 assertTrue(mA2dp.isSinkConnected(device));
712 // Check whether STATE_CONNECTING and (STATE_CONNECTED or STATE_PLAYING) intents
713 // have fired if we are checking if intents should be fired.
714 int firedFlags = mReceiver.getFiredFlags();
715 int a2dpFiredFlags = mReceiver.getA2dpFiredFlags();
716 if ((mReceiver.getFiredFlags() & mask) == mask
717 && ((a2dpFiredFlags & a2dpMask1) == a2dpMask1
718 || (a2dpFiredFlags & a2dpMask2) == a2dpMask2
719 || (a2dpFiredFlags & a2dpMask3) == a2dpMask3)) {
720 mReceiver.resetFiredFlags();
721 writeOutput(String.format("connectA2dp() completed in %d ms: device=%s",
722 (System.currentTimeMillis() - s), device));
723 return;
724 }
725 }
726 sleep(POLL_TIME);
727 }
728
729 int firedFlags = mReceiver.getFiredFlags();
730 int a2dpFiredFlags = mReceiver.getA2dpFiredFlags();
731 mReceiver.resetFiredFlags();
732 fail(String.format("connectA2dp() timeout: state=%d (expected %d or %d), "
733 + "flags=0x%x (expected 0x%x), a2dpFlags=0x%x (expected 0x%x or 0x%x or 0x%x)",
734 state, BluetoothHeadset.STATE_CONNECTED, BluetoothA2dp.STATE_PLAYING, firedFlags,
735 mask, a2dpFiredFlags, a2dpMask1, a2dpMask2, a2dpMask3));
736 }
737
738 public void disconnectA2dp(BluetoothAdapter adapter, BluetoothDevice device) {
739 int mask = PROFILE_A2DP_FLAG;
740 int a2dpMask = A2DP_STATE_DISCONNECTING | A2DP_STATE_DISCONNECTED;
741 mReceiver.resetFiredFlags();
742
743 if (!adapter.isEnabled()) {
744 fail("disconnectA2dp() bluetooth not enabled");
745 }
746
747 if (!adapter.getBondedDevices().contains(device)) {
748 fail("disconnectA2dp() device not paired: device=" + device);
749 }
750
751 int state = mA2dp.getSinkState(device);
752 switch (state) {
753 case BluetoothA2dp.STATE_DISCONNECTED:
754 assertFalse(mA2dp.isSinkConnected(device));
755 return;
756 case BluetoothA2dp.STATE_CONNECTED:
757 case BluetoothA2dp.STATE_PLAYING:
758 assertTrue(mA2dp.isSinkConnected(device));
759 assertTrue(mA2dp.disconnectSink(device));
760 break;
761 case BluetoothA2dp.STATE_CONNECTING:
762 assertFalse(mA2dp.isSinkConnected(device));
763 assertTrue(mA2dp.disconnectSink(device));
764 break;
765 case BluetoothA2dp.STATE_DISCONNECTING:
766 assertFalse(mA2dp.isSinkConnected(device));
767 // Don't check for received intents since we might have missed them.
768 mask = a2dpMask = 0;
769 break;
770 default:
771 fail("disconnectA2dp() invalid state: state=" + state);
772 }
773
774 long s = System.currentTimeMillis();
775 while (System.currentTimeMillis() - s < DISCONNECT_A2DP_TIMEOUT) {
776 state = mA2dp.getSinkState(device);
777 if (state == BluetoothA2dp.STATE_DISCONNECTED) {
778 assertFalse(mA2dp.isSinkConnected(device));
779 if ((mReceiver.getFiredFlags() & mask) == mask
780 && (mReceiver.getA2dpFiredFlags() & a2dpMask) == a2dpMask) {
781 mReceiver.resetFiredFlags();
782 writeOutput(String.format("disconnectA2dp() completed in %d ms: device=%s",
783 (System.currentTimeMillis() - s), device));
784 return;
785 }
786 }
787 sleep(POLL_TIME);
788 }
789
790 int firedFlags = mReceiver.getFiredFlags();
791 int a2dpFiredFlags = mReceiver.getA2dpFiredFlags();
792 mReceiver.resetFiredFlags();
793 fail(String.format("disconnectA2dp() timeout: state=%d (expected %d), "
794 + "flags=0x%x (expected 0x%x), a2dpFlags=0x%x (expected 0x%x)", state,
795 BluetoothA2dp.STATE_DISCONNECTED, firedFlags, mask, a2dpFiredFlags, a2dpMask));
796 }
797
798 public void connectHeadset(BluetoothAdapter adapter, BluetoothDevice device) {
799 int mask = PROFILE_HEADSET_FLAG;
800 int headsetMask = HEADSET_STATE_CONNECTING | HEADSET_STATE_CONNECTED;
801 mReceiver.resetFiredFlags();
802
803 if (!adapter.isEnabled()) {
804 fail("connectHeadset() bluetooth not enabled");
805 }
806
807 if (!adapter.getBondedDevices().contains(device)) {
808 fail("connectHeadset() device not paired: device=" + device);
809 }
810
811 while (!mHeadsetServiceListener.isConnected()) {
812 sleep(POLL_TIME);
813 }
814
815 int state = mHeadset.getState(device);
816 switch (state) {
817 case BluetoothHeadset.STATE_CONNECTED:
818 assertTrue(mHeadset.isConnected(device));
819 return;
820 case BluetoothHeadset.STATE_DISCONNECTED:
821 assertFalse(mHeadset.isConnected(device));
822 mHeadset.connectHeadset(device);
823 break;
824 case BluetoothHeadset.STATE_CONNECTING:
825 assertFalse(mHeadset.isConnected(device));
826 // Don't check for received intents since we might have missed them.
827 mask = headsetMask = 0;
828 break;
829 case BluetoothHeadset.STATE_ERROR:
830 fail("connectHeadset() error state");
831 break;
832 default:
833 fail("connectHeadset() invalid state: state=" + state);
834 }
835
836 long s = System.currentTimeMillis();
837 while (System.currentTimeMillis() - s < CONNECT_HEADSET_TIMEOUT) {
838 state = mHeadset.getState(device);
839 if (state == BluetoothHeadset.STATE_CONNECTED) {
840 assertTrue(mHeadset.isConnected(device));
841 if ((mReceiver.getFiredFlags() & mask) == mask
842 && (mReceiver.getHeadsetFiredFlags() & headsetMask) == headsetMask) {
843 mReceiver.resetFiredFlags();
844 writeOutput(String.format("connectHeadset() completed in %d ms: device=%s",
845 (System.currentTimeMillis() - s), device));
846 return;
847 }
848 }
849 sleep(POLL_TIME);
850 }
851
852 int firedFlags = mReceiver.getFiredFlags();
853 int headsetFiredFlags = mReceiver.getHeadsetFiredFlags();
854 mReceiver.resetFiredFlags();
855 fail(String.format("connectHeadset() timeout: state=%d (expected %d), "
856 + "flags=0x%x (expected 0x%x), headsetFlags=0x%s (expected 0x%x)", state,
857 BluetoothHeadset.STATE_CONNECTED, firedFlags, mask, headsetFiredFlags,
858 headsetMask));
859 }
860
861 public void disconnectHeadset(BluetoothAdapter adapter, BluetoothDevice device) {
862 int mask = PROFILE_HEADSET_FLAG;
863 int headsetMask = HEADSET_STATE_DISCONNECTED;
864 mReceiver.resetFiredFlags();
865
866 if (!adapter.isEnabled()) {
867 fail("disconnectHeadset() bluetooth not enabled");
868 }
869
870 if (!adapter.getBondedDevices().contains(device)) {
871 fail("disconnectHeadset() device not paired: device=" + device);
872 }
873
874 while (!mHeadsetServiceListener.isConnected()) {
875 sleep(POLL_TIME);
876 }
877
878 int state = mHeadset.getState(device);
879 switch (state) {
880 case BluetoothHeadset.STATE_CONNECTED:
881 mHeadset.disconnectHeadset(device);
882 break;
883 case BluetoothHeadset.STATE_CONNECTING:
884 mHeadset.disconnectHeadset(device);
885 break;
886 case BluetoothHeadset.STATE_DISCONNECTED:
887 return;
888 case BluetoothHeadset.STATE_ERROR:
889 fail("disconnectHeadset() error state");
890 break;
891 default:
892 fail("disconnectHeadset() invalid state: state=" + state);
893 }
894
895 long s = System.currentTimeMillis();
896 while (System.currentTimeMillis() - s < DISCONNECT_HEADSET_TIMEOUT) {
897 state = mHeadset.getState(device);
898 if (state == BluetoothHeadset.STATE_DISCONNECTED) {
899 assertFalse(mHeadset.isConnected(device));
900 if ((mReceiver.getFiredFlags() & mask) == mask
901 && (mReceiver.getHeadsetFiredFlags() & headsetMask) == headsetMask) {
902 mReceiver.resetFiredFlags();
903 writeOutput(String.format("disconnectHeadset() completed in %d ms: device=%s",
904 (System.currentTimeMillis() - s), device));
905 return;
906 }
907 }
908 sleep(POLL_TIME);
909 }
910
911 int firedFlags = mReceiver.getFiredFlags();
912 int headsetFiredFlags = mReceiver.getHeadsetFiredFlags();
913 mReceiver.resetFiredFlags();
914 fail(String.format("disconnectHeadset() timeout: state=%d (expected %d), "
915 + "flags=0x%x (expected 0x%x), headsetFlags=0x%s (expected 0x%x)", state,
916 BluetoothHeadset.STATE_DISCONNECTED, firedFlags, mask, headsetFiredFlags,
917 headsetMask));
918 }
919
920 public void writeOutput(String s) {
921 Log.i(mTag, s);
922 if (mOutputWriter == null) {
923 return;
924 }
925 try {
926 mOutputWriter.write(s + "\n");
927 mOutputWriter.flush();
928 } catch (IOException e) {
929 Log.w(mTag, "Could not write to output file", e);
930 }
931 }
932
933 private void sleep(long time) {
934 try {
935 Thread.sleep(time);
936 } catch (InterruptedException e) {
937 }
938 }
939}