1185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe/*
2185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe * Copyright (C) 2010 The Android Open Source Project
3185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe *
4185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe * Licensed under the Apache License, Version 2.0 (the "License");
5185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe * you may not use this file except in compliance with the License.
6185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe * You may obtain a copy of the License at
7185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe *
8185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe *      http://www.apache.org/licenses/LICENSE-2.0
9185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe *
10185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe * Unless required by applicable law or agreed to in writing, software
11185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe * distributed under the License is distributed on an "AS IS" BASIS,
12185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe * See the License for the specific language governing permissions and
14185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe * limitations under the License.
15185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe */
16185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
17185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowepackage android.bluetooth;
18185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
1974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganeshimport android.bluetooth.BluetoothPan;
2074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganeshimport android.bluetooth.BluetoothProfile;
21185a0b04c611a287cbd866d27b0ceff77f12d97bEric Roweimport android.content.BroadcastReceiver;
22185a0b04c611a287cbd866d27b0ceff77f12d97bEric Roweimport android.content.Context;
23185a0b04c611a287cbd866d27b0ceff77f12d97bEric Roweimport android.content.Intent;
24185a0b04c611a287cbd866d27b0ceff77f12d97bEric Roweimport android.content.IntentFilter;
25835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Roweimport android.media.AudioManager;
26185a0b04c611a287cbd866d27b0ceff77f12d97bEric Roweimport android.os.Environment;
27185a0b04c611a287cbd866d27b0ceff77f12d97bEric Roweimport android.util.Log;
28185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
29185a0b04c611a287cbd866d27b0ceff77f12d97bEric Roweimport junit.framework.Assert;
30185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
31185a0b04c611a287cbd866d27b0ceff77f12d97bEric Roweimport java.io.BufferedWriter;
32185a0b04c611a287cbd866d27b0ceff77f12d97bEric Roweimport java.io.File;
33185a0b04c611a287cbd866d27b0ceff77f12d97bEric Roweimport java.io.FileWriter;
34185a0b04c611a287cbd866d27b0ceff77f12d97bEric Roweimport java.io.IOException;
35826af6266c79d76b81fe850b9cd3d351597e4adbEric Roweimport java.util.ArrayList;
36826af6266c79d76b81fe850b9cd3d351597e4adbEric Roweimport java.util.List;
37185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
38185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowepublic class BluetoothTestUtils extends Assert {
39185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
402b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe    /** Timeout for enable/disable in ms. */
41207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe    private static final int ENABLE_DISABLE_TIMEOUT = 20000;
422b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe    /** Timeout for discoverable/undiscoverable in ms. */
43207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe    private static final int DISCOVERABLE_UNDISCOVERABLE_TIMEOUT = 5000;
442b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe    /** Timeout for starting/stopping a scan in ms. */
45207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe    private static final int START_STOP_SCAN_TIMEOUT = 5000;
462b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe    /** Timeout for pair/unpair in ms. */
47207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe    private static final int PAIR_UNPAIR_TIMEOUT = 20000;
482b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe    /** Timeout for connecting/disconnecting a profile in ms. */
49207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe    private static final int CONNECT_DISCONNECT_PROFILE_TIMEOUT = 20000;
502b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe    /** Timeout to start or stop a SCO channel in ms. */
51835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe    private static final int START_STOP_SCO_TIMEOUT = 10000;
522b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe    /** Timeout to connect a profile proxy in ms. */
532b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe    private static final int CONNECT_PROXY_TIMEOUT = 5000;
542b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe    /** Time between polls in ms. */
55185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe    private static final int POLL_TIME = 100;
56185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
57826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    private abstract class FlagReceiver extends BroadcastReceiver {
58826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private int mExpectedFlags = 0;
59826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private int mFiredFlags = 0;
60826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private long mCompletedTime = -1;
61185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
62826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        public FlagReceiver(int expectedFlags) {
63826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            mExpectedFlags = expectedFlags;
64826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
65185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
66826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        public int getFiredFlags() {
67826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            synchronized (this) {
68826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                return mFiredFlags;
69826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            }
70826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
71185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
72826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        public long getCompletedTime() {
73826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            synchronized (this) {
74826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                return mCompletedTime;
75826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            }
76826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
77826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
78826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        protected void setFiredFlag(int flag) {
79826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            synchronized (this) {
80826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                mFiredFlags |= flag;
815d0ed7b952667a1506585683c9eb5fe5ed7f0af2Eric Rowe                if ((mFiredFlags & mExpectedFlags) == mExpectedFlags) {
82826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    mCompletedTime = System.currentTimeMillis();
83826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                }
84826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            }
85826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
86826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    }
87826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
88826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    private class BluetoothReceiver extends FlagReceiver {
89826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private static final int DISCOVERY_STARTED_FLAG = 1;
90826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private static final int DISCOVERY_FINISHED_FLAG = 1 << 1;
91826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private static final int SCAN_MODE_NONE_FLAG = 1 << 2;
92826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private static final int SCAN_MODE_CONNECTABLE_FLAG = 1 << 3;
93826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE_FLAG = 1 << 4;
94826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private static final int STATE_OFF_FLAG = 1 << 5;
95826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private static final int STATE_TURNING_ON_FLAG = 1 << 6;
96826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private static final int STATE_ON_FLAG = 1 << 7;
97826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private static final int STATE_TURNING_OFF_FLAG = 1 << 8;
98826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
99826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        public BluetoothReceiver(int expectedFlags) {
100826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            super(expectedFlags);
101826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
102185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
103185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        @Override
104185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        public void onReceive(Context context, Intent intent) {
105826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(intent.getAction())) {
106826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                setFiredFlag(DISCOVERY_STARTED_FLAG);
107826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(intent.getAction())) {
108826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                setFiredFlag(DISCOVERY_FINISHED_FLAG);
109826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            } else if (BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(intent.getAction())) {
110826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                int mode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE, -1);
111826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                assertNotSame(-1, mode);
112826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                switch (mode) {
113826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    case BluetoothAdapter.SCAN_MODE_NONE:
114826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        setFiredFlag(SCAN_MODE_NONE_FLAG);
115826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        break;
116826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
117826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        setFiredFlag(SCAN_MODE_CONNECTABLE_FLAG);
118826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        break;
119826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
120826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        setFiredFlag(SCAN_MODE_CONNECTABLE_DISCOVERABLE_FLAG);
121826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        break;
122826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                }
123826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
124826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
125826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                assertNotSame(-1, state);
126826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                switch (state) {
127826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    case BluetoothAdapter.STATE_OFF:
128826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        setFiredFlag(STATE_OFF_FLAG);
129826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        break;
130826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    case BluetoothAdapter.STATE_TURNING_ON:
131826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        setFiredFlag(STATE_TURNING_ON_FLAG);
132826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        break;
133826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    case BluetoothAdapter.STATE_ON:
134826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        setFiredFlag(STATE_ON_FLAG);
135826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        break;
136826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    case BluetoothAdapter.STATE_TURNING_OFF:
137826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        setFiredFlag(STATE_TURNING_OFF_FLAG);
138826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        break;
139185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                }
140185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            }
141185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        }
142826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    }
143185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
144826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    private class PairReceiver extends FlagReceiver {
145826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private static final int STATE_BONDED_FLAG = 1;
146826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private static final int STATE_BONDING_FLAG = 1 << 1;
147826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private static final int STATE_NONE_FLAG = 1 << 2;
148826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
149826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private BluetoothDevice mDevice;
150826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private int mPasskey;
151826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private byte[] mPin;
152826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
153826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        public PairReceiver(BluetoothDevice device, int passkey, byte[] pin, int expectedFlags) {
154826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            super(expectedFlags);
155826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
156826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            mDevice = device;
157826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            mPasskey = passkey;
158826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            mPin = pin;
159826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
160826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
161826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        @Override
162826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        public void onReceive(Context context, Intent intent) {
163826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            if (!mDevice.equals(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE))) {
164826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                return;
165826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            }
166826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
167826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(intent.getAction())) {
168826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                int varient = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, -1);
169826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                assertNotSame(-1, varient);
170b49aa60829ab8fadec2f4c0661271100691d8225Eric Rowe                switch (varient) {
171826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    case BluetoothDevice.PAIRING_VARIANT_PIN:
172826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        mDevice.setPin(mPin);
173826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        break;
174826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    case BluetoothDevice.PAIRING_VARIANT_PASSKEY:
175826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        mDevice.setPasskey(mPasskey);
176826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        break;
177826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION:
178826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    case BluetoothDevice.PAIRING_VARIANT_CONSENT:
179826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        mDevice.setPairingConfirmation(true);
180826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        break;
181826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT:
182826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        mDevice.setRemoteOutOfBandData();
183826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        break;
184826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                }
185826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(intent.getAction())) {
186826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1);
187826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                assertNotSame(-1, state);
188826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                switch (state) {
189826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    case BluetoothDevice.BOND_NONE:
190826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        setFiredFlag(STATE_NONE_FLAG);
191826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        break;
192826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    case BluetoothDevice.BOND_BONDING:
193826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        setFiredFlag(STATE_BONDING_FLAG);
194826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        break;
195826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    case BluetoothDevice.BOND_BONDED:
196826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        setFiredFlag(STATE_BONDED_FLAG);
197826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        break;
198826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                }
199826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            }
200826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
201826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    }
202826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
203826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    private class ConnectProfileReceiver extends FlagReceiver {
204826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private static final int STATE_DISCONNECTED_FLAG = 1;
205826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private static final int STATE_CONNECTING_FLAG = 1 << 1;
206826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private static final int STATE_CONNECTED_FLAG = 1 << 2;
207826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private static final int STATE_DISCONNECTING_FLAG = 1 << 3;
208826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
209826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private BluetoothDevice mDevice;
210826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private int mProfile;
211826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        private String mConnectionAction;
212826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
213826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        public ConnectProfileReceiver(BluetoothDevice device, int profile, int expectedFlags) {
214826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            super(expectedFlags);
215826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
216826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            mDevice = device;
217826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            mProfile = profile;
218826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
219b49aa60829ab8fadec2f4c0661271100691d8225Eric Rowe            switch (mProfile) {
220826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                case BluetoothProfile.A2DP:
221826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    mConnectionAction = BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED;
222826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    break;
223826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                case BluetoothProfile.HEADSET:
224826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    mConnectionAction = BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED;
225826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    break;
2264ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                case BluetoothProfile.INPUT_DEVICE:
2274ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                    mConnectionAction = BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED;
2284ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                    break;
2292b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                case BluetoothProfile.PAN:
2302b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                    mConnectionAction = BluetoothPan.ACTION_CONNECTION_STATE_CHANGED;
2312b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                    break;
232826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                default:
233826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    mConnectionAction = null;
234826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            }
235826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
236826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
237826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        @Override
238826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        public void onReceive(Context context, Intent intent) {
239826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            if (mConnectionAction != null && mConnectionAction.equals(intent.getAction())) {
240826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                if (!mDevice.equals(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE))) {
241826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    return;
242826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                }
243826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
244826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
245826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                assertNotSame(-1, state);
246826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                switch (state) {
247826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    case BluetoothProfile.STATE_DISCONNECTED:
248826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        setFiredFlag(STATE_DISCONNECTED_FLAG);
249826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        break;
250826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    case BluetoothProfile.STATE_CONNECTING:
251826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        setFiredFlag(STATE_CONNECTING_FLAG);
252826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        break;
253826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    case BluetoothProfile.STATE_CONNECTED:
254826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        setFiredFlag(STATE_CONNECTED_FLAG);
255826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        break;
256826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    case BluetoothProfile.STATE_DISCONNECTING:
257826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        setFiredFlag(STATE_DISCONNECTING_FLAG);
258826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        break;
259826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                }
260826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            }
261826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
262826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    }
263826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
2642b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe    private class ConnectPanReceiver extends ConnectProfileReceiver {
2657e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        private int mRole;
2667e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
2677e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        public ConnectPanReceiver(BluetoothDevice device, int role, int expectedFlags) {
2682b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            super(device, BluetoothProfile.PAN, expectedFlags);
2697e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
2707e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe            mRole = role;
2717e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        }
2727e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
2737e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        @Override
2747e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        public void onReceive(Context context, Intent intent) {
2752b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            if (mRole != intent.getIntExtra(BluetoothPan.EXTRA_LOCAL_ROLE, -1)) {
2767e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                return;
2777e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe            }
2787e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
2792b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            super.onReceive(context, intent);
2807e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        }
2817e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    }
2827e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
283835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe    private class StartStopScoReceiver extends FlagReceiver {
284835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        private static final int STATE_CONNECTED_FLAG = 1;
285835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        private static final int STATE_DISCONNECTED_FLAG = 1 << 1;
286835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe
287835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        public StartStopScoReceiver(int expectedFlags) {
288835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe            super(expectedFlags);
289835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        }
290835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe
291835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        @Override
292835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        public void onReceive(Context context, Intent intent) {
2937af75afb2c8608dbe73509036eefd3281d646a5fEric Rowe            if (AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED.equals(intent.getAction())) {
294835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe                int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,
295835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe                        AudioManager.SCO_AUDIO_STATE_ERROR);
296835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe                assertNotSame(AudioManager.SCO_AUDIO_STATE_ERROR, state);
297835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe                switch(state) {
298835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe                    case AudioManager.SCO_AUDIO_STATE_CONNECTED:
299835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe                        setFiredFlag(STATE_CONNECTED_FLAG);
300835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe                        break;
301835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe                    case AudioManager.SCO_AUDIO_STATE_DISCONNECTED:
302835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe                        setFiredFlag(STATE_DISCONNECTED_FLAG);
303835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe                        break;
304835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe                }
305835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe            }
306835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        }
307835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe    }
308835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe
309826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    private BluetoothProfile.ServiceListener mServiceListener =
310826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            new BluetoothProfile.ServiceListener() {
3112b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe        @Override
312826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        public void onServiceConnected(int profile, BluetoothProfile proxy) {
313185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            synchronized (this) {
314826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                switch (profile) {
315826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    case BluetoothProfile.A2DP:
316826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        mA2dp = (BluetoothA2dp) proxy;
317826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        break;
318826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    case BluetoothProfile.HEADSET:
319826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        mHeadset = (BluetoothHeadset) proxy;
320826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        break;
3214ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                    case BluetoothProfile.INPUT_DEVICE:
3224ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                        mInput = (BluetoothInputDevice) proxy;
3234ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                        break;
32474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                    case BluetoothProfile.PAN:
32574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                        mPan = (BluetoothPan) proxy;
32674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                        break;
327826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                }
328185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            }
329185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        }
330185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
3312b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe        @Override
332826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        public void onServiceDisconnected(int profile) {
333185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            synchronized (this) {
334826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                switch (profile) {
335826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    case BluetoothProfile.A2DP:
336826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        mA2dp = null;
337826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        break;
338826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    case BluetoothProfile.HEADSET:
339826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        mHeadset = null;
340826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        break;
3414ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                    case BluetoothProfile.INPUT_DEVICE:
3424ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                        mInput = null;
3434ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                        break;
34474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                    case BluetoothProfile.PAN:
34574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                        mPan = null;
34674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                        break;
347826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                }
348185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            }
349185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        }
350826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    };
351826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
352826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    private List<BroadcastReceiver> mReceivers = new ArrayList<BroadcastReceiver>();
353826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
354826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    private BufferedWriter mOutputWriter;
355826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    private String mTag;
356826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    private String mOutputFile;
357185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
358826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    private Context mContext;
3592b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe    private BluetoothA2dp mA2dp = null;
3602b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe    private BluetoothHeadset mHeadset = null;
3612b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe    private BluetoothInputDevice mInput = null;
3622b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe    private BluetoothPan mPan = null;
363185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
3647e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    /**
3657e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * Creates a utility instance for testing Bluetooth.
3667e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     *
3677e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param context The context of the application using the utility.
3687e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param tag The log tag of the application using the utility.
3697e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     */
370185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe    public BluetoothTestUtils(Context context, String tag) {
371185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        this(context, tag, null);
372185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe    }
373185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
3747e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    /**
3757e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * Creates a utility instance for testing Bluetooth.
3767e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     *
3777e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param context The context of the application using the utility.
3787e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param tag The log tag of the application using the utility.
3797e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param outputFile The path to an output file if the utility is to write results to a
3807e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     *        separate file.
3817e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     */
382185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe    public BluetoothTestUtils(Context context, String tag, String outputFile) {
383185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        mContext = context;
384185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        mTag = tag;
385185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        mOutputFile = outputFile;
386185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
387185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        if (mOutputFile == null) {
388185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            mOutputWriter = null;
389185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        } else {
390185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            try {
391185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                mOutputWriter = new BufferedWriter(new FileWriter(new File(
392185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                        Environment.getExternalStorageDirectory(), mOutputFile), true));
393185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            } catch (IOException e) {
394185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                Log.w(mTag, "Test output file could not be opened", e);
395185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                mOutputWriter = null;
396185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            }
397185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        }
398185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe    }
399185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
4007e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    /**
4017e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * Closes the utility instance and unregisters any BroadcastReceivers.
4027e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     */
403185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe    public void close() {
404826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        while (!mReceivers.isEmpty()) {
405826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            mContext.unregisterReceiver(mReceivers.remove(0));
406826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
407185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
408185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        if (mOutputWriter != null) {
409185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            try {
410185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                mOutputWriter.close();
411185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            } catch (IOException e) {
412185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                Log.w(mTag, "Test output file could not be closed", e);
413185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            }
414185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        }
415185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe    }
416185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
4177e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    /**
4187e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * Enables Bluetooth and checks to make sure that Bluetooth was turned on and that the correct
4197e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * actions were broadcast.
4207e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     *
4217e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param adapter The BT adapter.
4227e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     */
423185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe    public void enable(BluetoothAdapter adapter) {
424826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        int mask = (BluetoothReceiver.STATE_TURNING_ON_FLAG | BluetoothReceiver.STATE_ON_FLAG
425826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                | BluetoothReceiver.SCAN_MODE_CONNECTABLE_FLAG);
426826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        long start = -1;
427826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        BluetoothReceiver receiver = getBluetoothReceiver(mask);
428185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
429185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        int state = adapter.getState();
430185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        switch (state) {
431185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            case BluetoothAdapter.STATE_ON:
432185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                assertTrue(adapter.isEnabled());
433826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                removeReceiver(receiver);
434185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                return;
435826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            case BluetoothAdapter.STATE_TURNING_ON:
436826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                assertFalse(adapter.isEnabled());
437826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                mask = 0; // Don't check for received intents since we might have missed them.
438826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                break;
439185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            case BluetoothAdapter.STATE_OFF:
440185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                assertFalse(adapter.isEnabled());
441826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                start = System.currentTimeMillis();
442185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                assertTrue(adapter.enable());
443185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                break;
444b49aa60829ab8fadec2f4c0661271100691d8225Eric Rowe            case BluetoothAdapter.STATE_TURNING_OFF:
445b49aa60829ab8fadec2f4c0661271100691d8225Eric Rowe                start = System.currentTimeMillis();
446b49aa60829ab8fadec2f4c0661271100691d8225Eric Rowe                assertTrue(adapter.enable());
447b49aa60829ab8fadec2f4c0661271100691d8225Eric Rowe                break;
448185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            default:
449826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                removeReceiver(receiver);
450826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                fail(String.format("enable() invalid state: state=%d", state));
451185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        }
452185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
453185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        long s = System.currentTimeMillis();
454207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe        while (System.currentTimeMillis() - s < ENABLE_DISABLE_TIMEOUT) {
455185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            state = adapter.getState();
456207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe            if (state == BluetoothAdapter.STATE_ON
457207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                    && (receiver.getFiredFlags() & mask) == mask) {
458185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                assertTrue(adapter.isEnabled());
459207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                long finish = receiver.getCompletedTime();
460207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                if (start != -1 && finish != -1) {
461207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                    writeOutput(String.format("enable() completed in %d ms", (finish - start)));
462207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                } else {
463207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                    writeOutput("enable() completed");
464185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                }
465207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                removeReceiver(receiver);
466207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                return;
467185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            }
468185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            sleep(POLL_TIME);
469185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        }
470185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
471826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        int firedFlags = receiver.getFiredFlags();
472826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        removeReceiver(receiver);
473185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        fail(String.format("enable() timeout: state=%d (expected %d), flags=0x%x (expected 0x%x)",
474185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                state, BluetoothAdapter.STATE_ON, firedFlags, mask));
475185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe    }
476185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
4777e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    /**
4787e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * Disables Bluetooth and checks to make sure that Bluetooth was turned off and that the correct
4797e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * actions were broadcast.
4807e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     *
4817e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param adapter The BT adapter.
4827e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     */
483185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe    public void disable(BluetoothAdapter adapter) {
484826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        int mask = (BluetoothReceiver.STATE_TURNING_OFF_FLAG | BluetoothReceiver.STATE_OFF_FLAG
485826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                | BluetoothReceiver.SCAN_MODE_NONE_FLAG);
486826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        long start = -1;
487826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        BluetoothReceiver receiver = getBluetoothReceiver(mask);
488185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
489185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        int state = adapter.getState();
490185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        switch (state) {
491185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            case BluetoothAdapter.STATE_OFF:
492185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                assertFalse(adapter.isEnabled());
493826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                removeReceiver(receiver);
494185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                return;
495185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            case BluetoothAdapter.STATE_TURNING_ON:
496185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                assertFalse(adapter.isEnabled());
497826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                start = System.currentTimeMillis();
498826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                break;
499826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            case BluetoothAdapter.STATE_ON:
500826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                assertTrue(adapter.isEnabled());
501826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                start = System.currentTimeMillis();
502185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                assertTrue(adapter.disable());
503185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                break;
504185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            case BluetoothAdapter.STATE_TURNING_OFF:
505185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                assertFalse(adapter.isEnabled());
506185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                mask = 0; // Don't check for received intents since we might have missed them.
507185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                break;
508185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            default:
509826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                removeReceiver(receiver);
510826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                fail(String.format("disable() invalid state: state=%d", state));
511185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        }
512185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
513185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        long s = System.currentTimeMillis();
514207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe        while (System.currentTimeMillis() - s < ENABLE_DISABLE_TIMEOUT) {
515185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            state = adapter.getState();
516207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe            if (state == BluetoothAdapter.STATE_OFF
517207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                    && (receiver.getFiredFlags() & mask) == mask) {
518185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                assertFalse(adapter.isEnabled());
519207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                long finish = receiver.getCompletedTime();
520207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                if (start != -1 && finish != -1) {
521207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                    writeOutput(String.format("disable() completed in %d ms", (finish - start)));
522207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                } else {
523207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                    writeOutput("disable() completed");
524185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                }
525207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                removeReceiver(receiver);
526207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                return;
527185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            }
528185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            sleep(POLL_TIME);
529185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        }
530185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
531826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        int firedFlags = receiver.getFiredFlags();
532826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        removeReceiver(receiver);
533185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        fail(String.format("disable() timeout: state=%d (expected %d), flags=0x%x (expected 0x%x)",
534185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                state, BluetoothAdapter.STATE_OFF, firedFlags, mask));
535185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe    }
536185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
5377e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    /**
5387e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * Puts the local device into discoverable mode and checks to make sure that the local device
5397e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * is in discoverable mode and that the correct actions were broadcast.
5407e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     *
5417e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param adapter The BT adapter.
5427e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     */
543185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe    public void discoverable(BluetoothAdapter adapter) {
544826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        int mask = BluetoothReceiver.SCAN_MODE_CONNECTABLE_DISCOVERABLE_FLAG;
545185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
546185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        if (!adapter.isEnabled()) {
547185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            fail("discoverable() bluetooth not enabled");
548185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        }
549185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
550185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        int scanMode = adapter.getScanMode();
551185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
552185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            return;
553185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        }
554185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
555826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        BluetoothReceiver receiver = getBluetoothReceiver(mask);
556826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
557826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        assertEquals(BluetoothAdapter.SCAN_MODE_CONNECTABLE, scanMode);
558826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        long start = System.currentTimeMillis();
559185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        assertTrue(adapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE));
560185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
561207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe        while (System.currentTimeMillis() - start < DISCOVERABLE_UNDISCOVERABLE_TIMEOUT) {
562185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            scanMode = adapter.getScanMode();
563207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe            if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE
564207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                    && (receiver.getFiredFlags() & mask) == mask) {
565207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                writeOutput(String.format("discoverable() completed in %d ms",
566207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                        (receiver.getCompletedTime() - start)));
567207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                removeReceiver(receiver);
568207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                return;
569185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            }
570185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            sleep(POLL_TIME);
571185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        }
572185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
573826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        int firedFlags = receiver.getFiredFlags();
574826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        removeReceiver(receiver);
575185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        fail(String.format("discoverable() timeout: scanMode=%d (expected %d), flags=0x%x "
576185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                + "(expected 0x%x)", scanMode, BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE,
577185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                firedFlags, mask));
578185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe    }
579185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
5807e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    /**
5817e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * Puts the local device into connectable only mode and checks to make sure that the local
5827e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * device is in in connectable mode and that the correct actions were broadcast.
5837e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     *
5847e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param adapter The BT adapter.
5857e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     */
586185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe    public void undiscoverable(BluetoothAdapter adapter) {
587826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        int mask = BluetoothReceiver.SCAN_MODE_CONNECTABLE_FLAG;
588185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
589185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        if (!adapter.isEnabled()) {
590185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            fail("undiscoverable() bluetooth not enabled");
591185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        }
592185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
593185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        int scanMode = adapter.getScanMode();
594185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE) {
595185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            return;
596185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        }
597185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
598826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        BluetoothReceiver receiver = getBluetoothReceiver(mask);
599826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
600826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        assertEquals(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, scanMode);
601826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        long start = System.currentTimeMillis();
602185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        assertTrue(adapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE));
603185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
604207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe        while (System.currentTimeMillis() - start < DISCOVERABLE_UNDISCOVERABLE_TIMEOUT) {
605185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            scanMode = adapter.getScanMode();
606207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe            if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE
607207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                    && (receiver.getFiredFlags() & mask) == mask) {
608207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                writeOutput(String.format("undiscoverable() completed in %d ms",
609207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                        (receiver.getCompletedTime() - start)));
610207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                removeReceiver(receiver);
611207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                return;
612185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            }
613185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            sleep(POLL_TIME);
614185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        }
615185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
616826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        int firedFlags = receiver.getFiredFlags();
617826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        removeReceiver(receiver);
618185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        fail(String.format("undiscoverable() timeout: scanMode=%d (expected %d), flags=0x%x "
619185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                + "(expected 0x%x)", scanMode, BluetoothAdapter.SCAN_MODE_CONNECTABLE, firedFlags,
620185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                mask));
621185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe    }
622185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
6237e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    /**
6247e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * Starts a scan for remote devices and checks to make sure that the local device is scanning
6257e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * and that the correct actions were broadcast.
6267e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     *
6277e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param adapter The BT adapter.
6287e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     */
629185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe    public void startScan(BluetoothAdapter adapter) {
630826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        int mask = BluetoothReceiver.DISCOVERY_STARTED_FLAG;
631185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
632185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        if (!adapter.isEnabled()) {
633185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            fail("startScan() bluetooth not enabled");
634185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        }
635185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
636185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        if (adapter.isDiscovering()) {
637185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            return;
638185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        }
639185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
640826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        BluetoothReceiver receiver = getBluetoothReceiver(mask);
641826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
642826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        long start = System.currentTimeMillis();
643185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        assertTrue(adapter.startDiscovery());
644185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
645207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe        while (System.currentTimeMillis() - start < START_STOP_SCAN_TIMEOUT) {
646826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            if (adapter.isDiscovering() && ((receiver.getFiredFlags() & mask) == mask)) {
647185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                writeOutput(String.format("startScan() completed in %d ms",
648826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        (receiver.getCompletedTime() - start)));
649826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                removeReceiver(receiver);
650185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                return;
651185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            }
652185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            sleep(POLL_TIME);
653185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        }
654185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
655826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        int firedFlags = receiver.getFiredFlags();
656826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        removeReceiver(receiver);
657185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        fail(String.format("startScan() timeout: isDiscovering=%b, flags=0x%x (expected 0x%x)",
658185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                adapter.isDiscovering(), firedFlags, mask));
659185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe    }
660185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
6617e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    /**
6627e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * Stops a scan for remote devices and checks to make sure that the local device is not scanning
6637e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * and that the correct actions were broadcast.
6647e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     *
6657e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param adapter The BT adapter.
6667e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     */
667185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe    public void stopScan(BluetoothAdapter adapter) {
668826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        int mask = BluetoothReceiver.DISCOVERY_FINISHED_FLAG;
669185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
670185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        if (!adapter.isEnabled()) {
671185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            fail("stopScan() bluetooth not enabled");
672185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        }
673185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
674185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        if (!adapter.isDiscovering()) {
675185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            return;
676185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        }
677185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
678826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        BluetoothReceiver receiver = getBluetoothReceiver(mask);
679826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
680826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        long start = System.currentTimeMillis();
681efc1d16374955f04d713c770ab47d90d190afe83Albert Mojir        assertTrue(adapter.cancelDiscovery());
682185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
683207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe        while (System.currentTimeMillis() - start < START_STOP_SCAN_TIMEOUT) {
684826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            if (!adapter.isDiscovering() && ((receiver.getFiredFlags() & mask) == mask)) {
685185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                writeOutput(String.format("stopScan() completed in %d ms",
686826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                        (receiver.getCompletedTime() - start)));
687826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                removeReceiver(receiver);
688185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                return;
689185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            }
690185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            sleep(POLL_TIME);
691185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        }
692185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
693826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        int firedFlags = receiver.getFiredFlags();
694826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        removeReceiver(receiver);
695185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        fail(String.format("stopScan() timeout: isDiscovering=%b, flags=0x%x (expected 0x%x)",
696185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe                adapter.isDiscovering(), firedFlags, mask));
697185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
698185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe    }
699185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
7007e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    /**
7017e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * Enables PAN tethering on the local device and checks to make sure that tethering is enabled.
7027e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     *
7037e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param adapter The BT adapter.
7047e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     */
7057e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    public void enablePan(BluetoothAdapter adapter) {
70674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        if (mPan == null) mPan = (BluetoothPan) connectProxy(adapter, BluetoothProfile.PAN);
70774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        assertNotNull(mPan);
7087e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
7097e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        long start = System.currentTimeMillis();
71074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        mPan.setBluetoothTethering(true);
7117e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        long stop = System.currentTimeMillis();
71274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        assertTrue(mPan.isTetheringOn());
7137e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
7147e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        writeOutput(String.format("enablePan() completed in %d ms", (stop - start)));
7157e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    }
7167e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
7177e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    /**
7187e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * Disables PAN tethering on the local device and checks to make sure that tethering is
7197e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * disabled.
7207e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     *
7217e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param adapter The BT adapter.
7227e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     */
7237e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    public void disablePan(BluetoothAdapter adapter) {
72474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        if (mPan == null) mPan = (BluetoothPan) connectProxy(adapter, BluetoothProfile.PAN);
72574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        assertNotNull(mPan);
7267e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
7277e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        long start = System.currentTimeMillis();
72874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        mPan.setBluetoothTethering(false);
7297e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        long stop = System.currentTimeMillis();
73074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        assertFalse(mPan.isTetheringOn());
7317e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
7327e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        writeOutput(String.format("disablePan() completed in %d ms", (stop - start)));
7337e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    }
7347e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
7357e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    /**
7367e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * Initiates a pairing with a remote device and checks to make sure that the devices are paired
7377e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * and that the correct actions were broadcast.
7387e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     *
7397e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param adapter The BT adapter.
7407e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param device The remote device.
7417e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param passkey The pairing passkey if pairing requires a passkey. Any value if not.
7427e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param pin The pairing pin if pairing requires a pin. Any value if not.
7437e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     */
744826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    public void pair(BluetoothAdapter adapter, BluetoothDevice device, int passkey, byte[] pin) {
74523c067692be74c4fcd50cea48f9d469ba5288213Eric Rowe        pairOrAcceptPair(adapter, device, passkey, pin, true);
74623c067692be74c4fcd50cea48f9d469ba5288213Eric Rowe    }
74723c067692be74c4fcd50cea48f9d469ba5288213Eric Rowe
7487e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    /**
7497e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * Accepts a pairing with a remote device and checks to make sure that the devices are paired
7507e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * and that the correct actions were broadcast.
7517e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     *
7527e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param adapter The BT adapter.
7537e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param device The remote device.
7547e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param passkey The pairing passkey if pairing requires a passkey. Any value if not.
7557e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param pin The pairing pin if pairing requires a pin. Any value if not.
7567e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     */
75723c067692be74c4fcd50cea48f9d469ba5288213Eric Rowe    public void acceptPair(BluetoothAdapter adapter, BluetoothDevice device, int passkey,
75823c067692be74c4fcd50cea48f9d469ba5288213Eric Rowe            byte[] pin) {
75923c067692be74c4fcd50cea48f9d469ba5288213Eric Rowe        pairOrAcceptPair(adapter, device, passkey, pin, false);
76023c067692be74c4fcd50cea48f9d469ba5288213Eric Rowe    }
76123c067692be74c4fcd50cea48f9d469ba5288213Eric Rowe
7627e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    /**
7637e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * Helper method used by {@link #pair(BluetoothAdapter, BluetoothDevice, int, byte[])} and
7647e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * {@link #acceptPair(BluetoothAdapter, BluetoothDevice, int, byte[])} to either pair or accept
7657e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * a pairing request.
7667e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     *
7677e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param adapter The BT adapter.
7687e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param device The remote device.
7697e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param passkey The pairing passkey if pairing requires a passkey. Any value if not.
7707e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param pin The pairing pin if pairing requires a pin. Any value if not.
7717e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param shouldPair Whether to pair or accept the pair.
7727e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     */
77323c067692be74c4fcd50cea48f9d469ba5288213Eric Rowe    private void pairOrAcceptPair(BluetoothAdapter adapter, BluetoothDevice device, int passkey,
7747e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe            byte[] pin, boolean shouldPair) {
775826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        int mask = PairReceiver.STATE_BONDING_FLAG | PairReceiver.STATE_BONDED_FLAG;
776826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        long start = -1;
7772b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe        String methodName;
7782b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe        if (shouldPair) {
7792b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            methodName = String.format("pair(device=%s)", device);
7802b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe        } else {
7812b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            methodName = String.format("acceptPair(device=%s)", device);
7822b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe        }
783826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
784826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        if (!adapter.isEnabled()) {
7852b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            fail(String.format("%s bluetooth not enabled", methodName));
786826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
787826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
788826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        PairReceiver receiver = getPairReceiver(device, passkey, pin, mask);
789826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
790826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        int state = device.getBondState();
791826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        switch (state) {
792826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            case BluetoothDevice.BOND_NONE:
793826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                assertFalse(adapter.getBondedDevices().contains(device));
794826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                start = System.currentTimeMillis();
7957e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                if (shouldPair) {
79623c067692be74c4fcd50cea48f9d469ba5288213Eric Rowe                    assertTrue(device.createBond());
79723c067692be74c4fcd50cea48f9d469ba5288213Eric Rowe                }
798826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                break;
799826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            case BluetoothDevice.BOND_BONDING:
800826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                mask = 0; // Don't check for received intents since we might have missed them.
801826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                break;
802826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            case BluetoothDevice.BOND_BONDED:
803826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                assertTrue(adapter.getBondedDevices().contains(device));
804826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                return;
805826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            default:
806826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                removeReceiver(receiver);
8072b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                fail(String.format("%s invalid state: state=%d", methodName, state));
808826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
809826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
810826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        long s = System.currentTimeMillis();
811207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe        while (System.currentTimeMillis() - s < PAIR_UNPAIR_TIMEOUT) {
812826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            state = device.getBondState();
813207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe            if (state == BluetoothDevice.BOND_BONDED && (receiver.getFiredFlags() & mask) == mask) {
814826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                assertTrue(adapter.getBondedDevices().contains(device));
815207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                long finish = receiver.getCompletedTime();
816207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                if (start != -1 && finish != -1) {
8172b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                    writeOutput(String.format("%s completed in %d ms", methodName,
8182b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                            (finish - start)));
819207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                } else {
8202b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                    writeOutput(String.format("%s completed", methodName));
821826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                }
822207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                removeReceiver(receiver);
823207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                return;
824826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            }
825826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            sleep(POLL_TIME);
826826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
827826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
828826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        int firedFlags = receiver.getFiredFlags();
829826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        removeReceiver(receiver);
8302b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe        fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%x)",
8312b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                methodName, state, BluetoothDevice.BOND_BONDED, firedFlags, mask));
832826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    }
833826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
8347e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    /**
8357e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * Deletes a pairing with a remote device and checks to make sure that the devices are unpaired
8367e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * and that the correct actions were broadcast.
8377e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     *
8387e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param adapter The BT adapter.
8397e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param device The remote device.
8407e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     */
841826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    public void unpair(BluetoothAdapter adapter, BluetoothDevice device) {
842826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        int mask = PairReceiver.STATE_NONE_FLAG;
843826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        long start = -1;
8442b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe        String methodName = String.format("unpair(device=%s)", device);
845826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
846826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        if (!adapter.isEnabled()) {
8472b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            fail(String.format("%s bluetooth not enabled", methodName));
848826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
849826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
850826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        PairReceiver receiver = getPairReceiver(device, 0, null, mask);
851826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
852826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        int state = device.getBondState();
853826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        switch (state) {
854826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            case BluetoothDevice.BOND_NONE:
855826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                assertFalse(adapter.getBondedDevices().contains(device));
856826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                removeReceiver(receiver);
857826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                return;
858826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            case BluetoothDevice.BOND_BONDING:
859826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                start = System.currentTimeMillis();
860826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                assertTrue(device.removeBond());
861826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                break;
862826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            case BluetoothDevice.BOND_BONDED:
863826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                assertTrue(adapter.getBondedDevices().contains(device));
864826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                start = System.currentTimeMillis();
865826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                assertTrue(device.removeBond());
866826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                break;
867826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            default:
868826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                removeReceiver(receiver);
8692b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                fail(String.format("%s invalid state: state=%d", methodName, state));
870826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
871826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
872826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        long s = System.currentTimeMillis();
873207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe        while (System.currentTimeMillis() - s < PAIR_UNPAIR_TIMEOUT) {
874207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe            if (device.getBondState() == BluetoothDevice.BOND_NONE
875207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                    && (receiver.getFiredFlags() & mask) == mask) {
876826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                assertFalse(adapter.getBondedDevices().contains(device));
877207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                long finish = receiver.getCompletedTime();
878207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                if (start != -1 && finish != -1) {
8792b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                    writeOutput(String.format("%s completed in %d ms", methodName,
8802b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                            (finish - start)));
881207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                } else {
8822b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                    writeOutput(String.format("%s completed", methodName));
883826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                }
884207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                removeReceiver(receiver);
885207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                return;
886826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            }
887826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
888826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
889826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        int firedFlags = receiver.getFiredFlags();
890826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        removeReceiver(receiver);
8912b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe        fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%x)",
8922b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                methodName, state, BluetoothDevice.BOND_BONDED, firedFlags, mask));
893826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    }
894826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
8957e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    /**
8967e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * Connects a profile from the local device to a remote device and checks to make sure that the
8977e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * profile is connected and that the correct actions were broadcast.
8987e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     *
8997e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param adapter The BT adapter.
9007e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param device The remote device.
9012b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe     * @param profile The profile to connect. One of {@link BluetoothProfile#A2DP},
9022b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe     * {@link BluetoothProfile#HEADSET}, or {@link BluetoothProfile#INPUT_DEVICE}.
9032b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe     * @param methodName The method name to printed in the logs.  If null, will be
9042b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe     * "connectProfile(profile=&lt;profile&gt;, device=&lt;device&gt;)"
9057e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     */
9062b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe    public void connectProfile(BluetoothAdapter adapter, BluetoothDevice device, int profile,
9072b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            String methodName) {
9082b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe        if (methodName == null) {
9092b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            methodName = String.format("connectProfile(profile=%d, device=%s)", profile, device);
9102b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe        }
911826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        int mask = (ConnectProfileReceiver.STATE_CONNECTING_FLAG
912826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                | ConnectProfileReceiver.STATE_CONNECTED_FLAG);
913826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        long start = -1;
914826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
915826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        if (!adapter.isEnabled()) {
9162b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            fail(String.format("%s bluetooth not enabled", methodName));
917826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
918826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
919826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        if (!adapter.getBondedDevices().contains(device)) {
9202b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            fail(String.format("%s device not paired", methodName));
921826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
922826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
923826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        BluetoothProfile proxy = connectProxy(adapter, profile);
9242b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe        assertNotNull(proxy);
925826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
926826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        ConnectProfileReceiver receiver = getConnectProfileReceiver(device, profile, mask);
927826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
928826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        int state = proxy.getConnectionState(device);
929826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        switch (state) {
930826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            case BluetoothProfile.STATE_CONNECTED:
931826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                removeReceiver(receiver);
932826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                return;
933826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            case BluetoothProfile.STATE_CONNECTING:
934826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                mask = 0; // Don't check for received intents since we might have missed them.
935826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                break;
936826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            case BluetoothProfile.STATE_DISCONNECTED:
937826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            case BluetoothProfile.STATE_DISCONNECTING:
938826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                start = System.currentTimeMillis();
939f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh                if (profile == BluetoothProfile.A2DP) {
940f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh                    assertTrue(((BluetoothA2dp)proxy).connect(device));
941f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh                } else if (profile == BluetoothProfile.HEADSET) {
942f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh                    assertTrue(((BluetoothHeadset)proxy).connect(device));
943f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh                } else if (profile == BluetoothProfile.INPUT_DEVICE) {
944f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh                    assertTrue(((BluetoothInputDevice)proxy).connect(device));
945f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh                }
946826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                break;
947826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            default:
948826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                removeReceiver(receiver);
9492b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                fail(String.format("%s invalid state: state=%d", methodName, state));
950826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
951826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
952826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        long s = System.currentTimeMillis();
953207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe        while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
954826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            state = proxy.getConnectionState(device);
955207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe            if (state == BluetoothProfile.STATE_CONNECTED
956207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                    && (receiver.getFiredFlags() & mask) == mask) {
957207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                long finish = receiver.getCompletedTime();
958207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                if (start != -1 && finish != -1) {
9592b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                    writeOutput(String.format("%s completed in %d ms", methodName,
9602b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                            (finish - start)));
961207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                } else {
9622b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                    writeOutput(String.format("%s completed", methodName));
963826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                }
964207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                removeReceiver(receiver);
965207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                return;
966826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            }
967826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            sleep(POLL_TIME);
968826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
969826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
970826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        int firedFlags = receiver.getFiredFlags();
971826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        removeReceiver(receiver);
9722b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe        fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%x)",
9732b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                methodName, state, BluetoothProfile.STATE_CONNECTED, firedFlags, mask));
974826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    }
975826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
9767e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    /**
9777e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * Disconnects a profile between the local device and a remote device and checks to make sure
9787e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * that the profile is disconnected and that the correct actions were broadcast.
9797e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     *
9807e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param adapter The BT adapter.
9817e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param device The remote device.
9822b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe     * @param profile The profile to disconnect. One of {@link BluetoothProfile#A2DP},
9832b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe     * {@link BluetoothProfile#HEADSET}, or {@link BluetoothProfile#INPUT_DEVICE}.
9842b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe     * @param methodName The method name to printed in the logs.  If null, will be
9852b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe     * "connectProfile(profile=&lt;profile&gt;, device=&lt;device&gt;)"
9867e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     */
9872b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe    public void disconnectProfile(BluetoothAdapter adapter, BluetoothDevice device, int profile,
9882b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            String methodName) {
9892b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe        if (methodName == null) {
9902b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            methodName = String.format("disconnectProfile(profile=%d, device=%s)", profile, device);
9912b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe        }
992826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        int mask = (ConnectProfileReceiver.STATE_DISCONNECTING_FLAG
993826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                | ConnectProfileReceiver.STATE_DISCONNECTED_FLAG);
994826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        long start = -1;
995826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
996826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        if (!adapter.isEnabled()) {
9972b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            fail(String.format("%s bluetooth not enabled", methodName));
998826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
999826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
1000826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        if (!adapter.getBondedDevices().contains(device)) {
10012b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            fail(String.format("%s device not paired", methodName));
1002826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
1003826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
1004826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        BluetoothProfile proxy = connectProxy(adapter, profile);
10052b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe        assertNotNull(proxy);
1006826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
1007826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        ConnectProfileReceiver receiver = getConnectProfileReceiver(device, profile, mask);
1008826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
1009826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        int state = proxy.getConnectionState(device);
1010826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        switch (state) {
1011826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            case BluetoothProfile.STATE_CONNECTED:
1012826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            case BluetoothProfile.STATE_CONNECTING:
1013826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                start = System.currentTimeMillis();
1014f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh                if (profile == BluetoothProfile.A2DP) {
1015f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh                    assertTrue(((BluetoothA2dp)proxy).disconnect(device));
1016f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh                } else if (profile == BluetoothProfile.HEADSET) {
1017f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh                    assertTrue(((BluetoothHeadset)proxy).disconnect(device));
1018f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh                } else if (profile == BluetoothProfile.INPUT_DEVICE) {
1019f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh                    assertTrue(((BluetoothInputDevice)proxy).disconnect(device));
1020f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh                }
1021826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                break;
1022826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            case BluetoothProfile.STATE_DISCONNECTED:
1023826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                removeReceiver(receiver);
1024826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                return;
1025826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            case BluetoothProfile.STATE_DISCONNECTING:
1026826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                mask = 0; // Don't check for received intents since we might have missed them.
1027826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                break;
1028826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            default:
1029826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                removeReceiver(receiver);
10302b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                fail(String.format("%s invalid state: state=%d", methodName, state));
1031826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
1032826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
1033826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        long s = System.currentTimeMillis();
1034207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe        while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
1035826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            state = proxy.getConnectionState(device);
1036207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe            if (state == BluetoothProfile.STATE_DISCONNECTED
1037207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                    && (receiver.getFiredFlags() & mask) == mask) {
1038207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                long finish = receiver.getCompletedTime();
1039207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                if (start != -1 && finish != -1) {
10402b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                    writeOutput(String.format("%s completed in %d ms", methodName,
10412b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                            (finish - start)));
1042207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                } else {
10432b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                    writeOutput(String.format("%s completed", methodName));
1044826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                }
1045207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                removeReceiver(receiver);
1046207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                return;
1047826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            }
1048826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            sleep(POLL_TIME);
1049826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
1050826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
1051826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        int firedFlags = receiver.getFiredFlags();
1052826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        removeReceiver(receiver);
10532b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe        fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%x)",
10542b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                methodName, state, BluetoothProfile.STATE_DISCONNECTED, firedFlags, mask));
1055826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    }
1056826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
10577e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    /**
10587e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * Connects the PANU to a remote NAP and checks to make sure that the PANU is connected and that
10597e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * the correct actions were broadcast.
10607e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     *
10617e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param adapter The BT adapter.
10627e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param device The remote device.
10637e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     */
10647e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    public void connectPan(BluetoothAdapter adapter, BluetoothDevice device) {
10657e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        connectPanOrIncomingPanConnection(adapter, device, true);
10667e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    }
10677e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
10687e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    /**
10697e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * Checks that a remote PANU connects to the local NAP correctly and that the correct actions
10707e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * were broadcast.
10717e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     *
10727e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param adapter The BT adapter.
10737e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param device The remote device.
10747e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     */
10757e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    public void incomingPanConnection(BluetoothAdapter adapter, BluetoothDevice device) {
10767e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        connectPanOrIncomingPanConnection(adapter, device, false);
10777e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    }
10787e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
10797e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    /**
10807e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * Helper method used by {@link #connectPan(BluetoothAdapter, BluetoothDevice)} and
10817e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * {@link #incomingPanConnection(BluetoothAdapter, BluetoothDevice)} to either connect to a
10827e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * remote NAP or verify that a remote device connected to the local NAP.
10837e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     *
10847e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param adapter The BT adapter.
10857e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param device The remote device.
10867e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param connect If the method should initiate the connection (is PANU)
10877e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     */
10887e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    private void connectPanOrIncomingPanConnection(BluetoothAdapter adapter, BluetoothDevice device,
10897e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe            boolean connect) {
10907e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        long start = -1;
10917e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        int mask, role;
10927e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        String methodName;
10937e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
10947e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        if (connect) {
10952b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            methodName = String.format("connectPan(device=%s)", device);
10962b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            mask = (ConnectProfileReceiver.STATE_CONNECTED_FLAG |
10972b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                    ConnectProfileReceiver.STATE_CONNECTING_FLAG);
10987e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe            role = BluetoothPan.LOCAL_PANU_ROLE;
10997e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        } else {
11002b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            methodName = String.format("incomingPanConnection(device=%s)", device);
11012b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            mask = ConnectProfileReceiver.STATE_CONNECTED_FLAG;
11027e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe            role = BluetoothPan.LOCAL_NAP_ROLE;
11037e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        }
11047e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
11057e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        if (!adapter.isEnabled()) {
11062b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            fail(String.format("%s bluetooth not enabled", methodName));
11077e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        }
11087e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
11097e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        if (!adapter.getBondedDevices().contains(device)) {
11102b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            fail(String.format("%s device not paired", methodName));
11117e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        }
11127e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
11132b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe        mPan = (BluetoothPan) connectProxy(adapter, BluetoothProfile.PAN);
111474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        assertNotNull(mPan);
11157e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        ConnectPanReceiver receiver = getConnectPanReceiver(device, role, mask);
11167e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
111774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        int state = mPan.getConnectionState(device);
11187e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        switch (state) {
11197e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe            case BluetoothPan.STATE_CONNECTED:
11207e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                removeReceiver(receiver);
11217e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                return;
11227e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe            case BluetoothPan.STATE_CONNECTING:
11237e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                mask = 0; // Don't check for received intents since we might have missed them.
11247e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                break;
11257e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe            case BluetoothPan.STATE_DISCONNECTED:
11267e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe            case BluetoothPan.STATE_DISCONNECTING:
11277e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                start = System.currentTimeMillis();
11287e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                if (role == BluetoothPan.LOCAL_PANU_ROLE) {
11297e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                    Log.i("BT", "connect to pan");
113074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                    assertTrue(mPan.connect(device));
11317e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                }
11327e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                break;
11337e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe            default:
11347e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                removeReceiver(receiver);
11352b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                fail(String.format("%s invalid state: state=%d", methodName, state));
11367e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        }
11377e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
11387e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        long s = System.currentTimeMillis();
11397e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
114074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            state = mPan.getConnectionState(device);
11417e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe            if (state == BluetoothPan.STATE_CONNECTED
11427e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                    && (receiver.getFiredFlags() & mask) == mask) {
11437e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                long finish = receiver.getCompletedTime();
11447e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                if (start != -1 && finish != -1) {
11452b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                    writeOutput(String.format("%s completed in %d ms", methodName,
11462b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                            (finish - start)));
11477e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                } else {
11482b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                    writeOutput(String.format("%s completed", methodName));
11497e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                }
11507e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                removeReceiver(receiver);
11517e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                return;
11527e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe            }
11537e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe            sleep(POLL_TIME);
11547e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        }
11557e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
11567e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        int firedFlags = receiver.getFiredFlags();
11577e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        removeReceiver(receiver);
11582b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe        fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%s)",
11592b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                methodName, state, BluetoothPan.STATE_CONNECTED, firedFlags, mask));
11607e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    }
11617e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
11627e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    /**
11637e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * Disconnects the PANU from a remote NAP and checks to make sure that the PANU is disconnected
11647e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * and that the correct actions were broadcast.
11657e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     *
11667e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param adapter The BT adapter.
11677e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param device The remote device.
11687e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     */
11697e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    public void disconnectPan(BluetoothAdapter adapter, BluetoothDevice device) {
11707e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        disconnectFromRemoteOrVerifyConnectNap(adapter, device, true);
11717e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    }
11727e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
11737e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    /**
11747e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * Checks that a remote PANU disconnects from the local NAP correctly and that the correct
11757e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * actions were broadcast.
11767e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     *
11777e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param adapter The BT adapter.
11787e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param device The remote device.
11797e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     */
11807e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    public void incomingPanDisconnection(BluetoothAdapter adapter, BluetoothDevice device) {
11817e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        disconnectFromRemoteOrVerifyConnectNap(adapter, device, false);
11827e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    }
11837e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
11847e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    /**
11857e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * Helper method used by {@link #disconnectPan(BluetoothAdapter, BluetoothDevice)} and
11867e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * {@link #incomingPanDisconnection(BluetoothAdapter, BluetoothDevice)} to either disconnect
11877e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * from a remote NAP or verify that a remote device disconnected from the local NAP.
11887e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     *
11897e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param adapter The BT adapter.
11907e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param device The remote device.
11917e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param disconnect Whether the method should connect or verify.
11927e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     */
11937e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    private void disconnectFromRemoteOrVerifyConnectNap(BluetoothAdapter adapter,
11947e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe            BluetoothDevice device, boolean disconnect) {
11957e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        long start = -1;
11967e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        int mask, role;
11977e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        String methodName;
11987e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
11997e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        if (disconnect) {
12002b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            methodName = String.format("disconnectPan(device=%s)", device);
12012b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            mask = (ConnectProfileReceiver.STATE_DISCONNECTED_FLAG |
12022b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                    ConnectProfileReceiver.STATE_DISCONNECTING_FLAG);
12037e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe            role = BluetoothPan.LOCAL_PANU_ROLE;
12047e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        } else {
12052b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            methodName = String.format("incomingPanDisconnection(device=%s)", device);
12062b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            mask = ConnectProfileReceiver.STATE_DISCONNECTED_FLAG;
12077e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe            role = BluetoothPan.LOCAL_NAP_ROLE;
12087e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        }
12097e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
12107e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        if (!adapter.isEnabled()) {
12112b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            fail(String.format("%s bluetooth not enabled", methodName));
12127e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        }
12137e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
12147e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        if (!adapter.getBondedDevices().contains(device)) {
12152b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            fail(String.format("%s device not paired", methodName));
12167e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        }
12177e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
12182b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe        mPan = (BluetoothPan) connectProxy(adapter, BluetoothProfile.PAN);
121974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        assertNotNull(mPan);
12207e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        ConnectPanReceiver receiver = getConnectPanReceiver(device, role, mask);
12217e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
122274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        int state = mPan.getConnectionState(device);
12237e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        switch (state) {
122474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            case BluetoothPan.STATE_CONNECTED:
122574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            case BluetoothPan.STATE_CONNECTING:
12267e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                start = System.currentTimeMillis();
12277e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                if (role == BluetoothPan.LOCAL_PANU_ROLE) {
122874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                    assertTrue(mPan.disconnect(device));
12297e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                }
12307e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                break;
123174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            case BluetoothPan.STATE_DISCONNECTED:
12327e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                removeReceiver(receiver);
12337e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                return;
123474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            case BluetoothPan.STATE_DISCONNECTING:
12357e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                mask = 0; // Don't check for received intents since we might have missed them.
12367e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                break;
12377e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe            default:
12387e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                removeReceiver(receiver);
12392b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                fail(String.format("%s invalid state: state=%d", methodName, state));
12407e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        }
12417e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
12427e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        long s = System.currentTimeMillis();
12437e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
124474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            state = mPan.getConnectionState(device);
12457e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe            if (state == BluetoothInputDevice.STATE_DISCONNECTED
12467e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                    && (receiver.getFiredFlags() & mask) == mask) {
12477e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                long finish = receiver.getCompletedTime();
12487e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                if (start != -1 && finish != -1) {
12492b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                    writeOutput(String.format("%s completed in %d ms", methodName,
12502b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                            (finish - start)));
12517e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                } else {
12522b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                    writeOutput(String.format("%s completed", methodName));
12537e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                }
12547e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                removeReceiver(receiver);
12557e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe                return;
12567e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe            }
12577e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe            sleep(POLL_TIME);
12587e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        }
12597e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
12607e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        int firedFlags = receiver.getFiredFlags();
12617e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        removeReceiver(receiver);
12622b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe        fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%s)",
12632b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                methodName, state, BluetoothInputDevice.STATE_DISCONNECTED, firedFlags, mask));
12647e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    }
12657e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
12667e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    /**
1267835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe     * Opens a SCO channel using {@link android.media.AudioManager#startBluetoothSco()} and checks
1268835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe     * to make sure that the channel is opened and that the correct actions were broadcast.
1269835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe     *
1270835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe     * @param adapter The BT adapter.
1271835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe     * @param device The remote device.
1272835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe     */
1273835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe    public void startSco(BluetoothAdapter adapter, BluetoothDevice device) {
1274835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        startStopSco(adapter, device, true);
1275835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe    }
1276835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe
1277835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe    /**
1278835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe     * Closes a SCO channel using {@link android.media.AudioManager#stopBluetoothSco()} and checks
1279835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe     *  to make sure that the channel is closed and that the correct actions were broadcast.
1280835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe     *
1281835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe     * @param adapter The BT adapter.
1282835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe     * @param device The remote device.
1283835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe     */
1284835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe    public void stopSco(BluetoothAdapter adapter, BluetoothDevice device) {
1285835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        startStopSco(adapter, device, false);
1286835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe    }
1287835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe    /**
1288835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe     * Helper method for {@link #startSco(BluetoothAdapter, BluetoothDevice)} and
1289835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe     * {@link #stopSco(BluetoothAdapter, BluetoothDevice)}.
1290835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe     *
1291835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe     * @param adapter The BT adapter.
1292835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe     * @param device The remote device.
1293835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe     * @param isStart Whether the SCO channel should be opened.
1294835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe     */
1295835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe    private void startStopSco(BluetoothAdapter adapter, BluetoothDevice device, boolean isStart) {
1296835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        long start = -1;
1297835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        int mask;
1298835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        String methodName;
1299835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe
1300835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        if (isStart) {
13012b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            methodName = String.format("startSco(device=%s)", device);
1302835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe            mask = StartStopScoReceiver.STATE_CONNECTED_FLAG;
1303835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        } else {
13042b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            methodName = String.format("stopSco(device=%s)", device);
1305835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe            mask = StartStopScoReceiver.STATE_DISCONNECTED_FLAG;
1306835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        }
1307835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe
1308835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        if (!adapter.isEnabled()) {
13092b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            fail(String.format("%s bluetooth not enabled", methodName));
1310835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        }
1311835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe
1312835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        if (!adapter.getBondedDevices().contains(device)) {
13132b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            fail(String.format("%s device not paired", methodName));
1314835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        }
1315835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe
1316835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        AudioManager manager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
1317835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        assertNotNull(manager);
1318835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe
1319835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        if (!manager.isBluetoothScoAvailableOffCall()) {
13202b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            fail(String.format("%s device does not support SCO", methodName));
1321835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        }
1322835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe
1323835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        boolean isScoOn = manager.isBluetoothScoOn();
1324835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        if (isStart == isScoOn) {
1325835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe            return;
1326835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        }
1327835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe
1328835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        StartStopScoReceiver receiver = getStartStopScoReceiver(mask);
1329835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        start = System.currentTimeMillis();
1330835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        if (isStart) {
1331835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe            manager.startBluetoothSco();
1332835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        } else {
1333835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe            manager.stopBluetoothSco();
1334835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        }
1335835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe
1336835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        long s = System.currentTimeMillis();
1337835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        while (System.currentTimeMillis() - s < START_STOP_SCO_TIMEOUT) {
1338835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe            isScoOn = manager.isBluetoothScoOn();
13392b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            if (isStart == isScoOn && (receiver.getFiredFlags() & mask) == mask) {
1340835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe                long finish = receiver.getCompletedTime();
1341835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe                if (start != -1 && finish != -1) {
1342835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe                    writeOutput(String.format("%s completed in %d ms", methodName,
1343835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe                            (finish - start)));
1344835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe                } else {
1345835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe                    writeOutput(String.format("%s completed", methodName));
1346835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe                }
1347835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe                removeReceiver(receiver);
1348835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe                return;
1349835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe            }
1350835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe            sleep(POLL_TIME);
1351835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        }
1352835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe
1353835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        int firedFlags = receiver.getFiredFlags();
1354835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        removeReceiver(receiver);
13552b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe        fail(String.format("%s timeout: on=%b (expected %b), flags=0x%x (expected 0x%x)",
1356835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe                methodName, isScoOn, isStart, firedFlags, mask));
1357835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe    }
1358835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe
1359835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe    /**
13607e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * Writes a string to the logcat and a file if a file has been specified in the constructor.
13617e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     *
13627e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     * @param s The string to be written.
13637e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe     */
1364185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe    public void writeOutput(String s) {
1365185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        Log.i(mTag, s);
1366185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        if (mOutputWriter == null) {
1367185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            return;
1368185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        }
1369185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        try {
1370185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            mOutputWriter.write(s + "\n");
1371185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            mOutputWriter.flush();
1372185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        } catch (IOException e) {
1373185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            Log.w(mTag, "Could not write to output file", e);
1374185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        }
1375185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe    }
1376185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe
1377207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe    private void addReceiver(BroadcastReceiver receiver, String[] actions) {
1378826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        IntentFilter filter = new IntentFilter();
1379207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe        for (String action: actions) {
1380207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe            filter.addAction(action);
1381207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe        }
1382826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        mContext.registerReceiver(receiver, filter);
1383826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        mReceivers.add(receiver);
1384207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe    }
1385207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe
1386207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe    private BluetoothReceiver getBluetoothReceiver(int expectedFlags) {
1387207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe        String[] actions = {
1388207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                BluetoothAdapter.ACTION_DISCOVERY_FINISHED,
1389207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                BluetoothAdapter.ACTION_DISCOVERY_STARTED,
1390207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                BluetoothAdapter.ACTION_SCAN_MODE_CHANGED,
1391207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                BluetoothAdapter.ACTION_STATE_CHANGED};
1392207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe        BluetoothReceiver receiver = new BluetoothReceiver(expectedFlags);
1393207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe        addReceiver(receiver, actions);
1394826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        return receiver;
1395826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    }
1396826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
1397826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    private PairReceiver getPairReceiver(BluetoothDevice device, int passkey, byte[] pin,
1398826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            int expectedFlags) {
1399207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe        String[] actions = {
1400207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                BluetoothDevice.ACTION_PAIRING_REQUEST,
1401207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                BluetoothDevice.ACTION_BOND_STATE_CHANGED};
1402826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        PairReceiver receiver = new PairReceiver(device, passkey, pin, expectedFlags);
1403207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe        addReceiver(receiver, actions);
1404826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        return receiver;
1405826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    }
1406826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
1407826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    private ConnectProfileReceiver getConnectProfileReceiver(BluetoothDevice device, int profile,
1408826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            int expectedFlags) {
1409207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe        String[] actions = {
1410207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe                BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED,
14114ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED,
14124ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED};
1413826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        ConnectProfileReceiver receiver = new ConnectProfileReceiver(device, profile,
1414826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                expectedFlags);
1415207c0a58012d5ce102760f33b5918d8b38c2af6bEric Rowe        addReceiver(receiver, actions);
1416826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        return receiver;
1417826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    }
1418826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
14197e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    private ConnectPanReceiver getConnectPanReceiver(BluetoothDevice device, int role,
14207e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe            int expectedFlags) {
142174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        String[] actions = {BluetoothPan.ACTION_CONNECTION_STATE_CHANGED};
14227e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        ConnectPanReceiver receiver = new ConnectPanReceiver(device, role, expectedFlags);
14237e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        addReceiver(receiver, actions);
14247e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe        return receiver;
14257e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe    }
14267e4d0c0982cb28a86bf3d45c3b316ec7eab1e017Eric Rowe
1427835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe    private StartStopScoReceiver getStartStopScoReceiver(int expectedFlags) {
1428fca8e9d919443449807f87203609e53a64368f6bEric Rowe        String[] actions = {AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED};
1429835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        StartStopScoReceiver receiver = new StartStopScoReceiver(expectedFlags);
1430835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        addReceiver(receiver, actions);
1431835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe        return receiver;
1432835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe    }
1433835d8ee61ecddcd3fdc0aadf500d05b914ca375fEric Rowe
1434826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    private void removeReceiver(BroadcastReceiver receiver) {
1435826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        mContext.unregisterReceiver(receiver);
1436826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        mReceivers.remove(receiver);
1437826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    }
1438826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
1439826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    private BluetoothProfile connectProxy(BluetoothAdapter adapter, int profile) {
14402b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe        switch (profile) {
14412b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            case BluetoothProfile.A2DP:
14422b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                if (mA2dp != null) {
14432b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                    return mA2dp;
14442b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                }
14452b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                break;
14462b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            case BluetoothProfile.HEADSET:
14472b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                if (mHeadset != null) {
14482b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                    return mHeadset;
14492b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                }
14502b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                break;
14512b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            case BluetoothProfile.INPUT_DEVICE:
14522b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                if (mInput != null) {
14532b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                    return mInput;
14542b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                }
14552b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                break;
14562b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            case BluetoothProfile.PAN:
14572b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                if (mPan != null) {
14582b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                    return mPan;
14592b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                }
14602b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                break;
14612b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe            default:
14622b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe                return null;
14632b1fb45fabcb6f6e6edfd1a7a8e394928a27afe8Eric Rowe        }
1464826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        adapter.getProfileProxy(mContext, mServiceListener, profile);
1465826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        long s = System.currentTimeMillis();
1466826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        switch (profile) {
1467826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            case BluetoothProfile.A2DP:
14684ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                while (mA2dp == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
1469826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    sleep(POLL_TIME);
1470826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                }
1471826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                return mA2dp;
1472826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            case BluetoothProfile.HEADSET:
14734ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                while (mHeadset == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
1474826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                    sleep(POLL_TIME);
1475826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                }
1476826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                return mHeadset;
14774ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            case BluetoothProfile.INPUT_DEVICE:
14784ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                while (mInput == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
14794ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                    sleep(POLL_TIME);
14804ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                }
14814ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return mInput;
148274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            case BluetoothProfile.PAN:
148374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                while (mPan == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
148474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                    sleep(POLL_TIME);
148574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                }
148674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                return mPan;
1487826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe            default:
1488826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe                return null;
1489826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe        }
1490826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe    }
1491826af6266c79d76b81fe850b9cd3d351597e4adbEric Rowe
1492185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe    private void sleep(long time) {
1493185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        try {
1494185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe            Thread.sleep(time);
1495185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        } catch (InterruptedException e) {
1496185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe        }
1497185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe    }
1498185a0b04c611a287cbd866d27b0ceff77f12d97bEric Rowe}
1499