BluetoothA2dp.java revision 41d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.bluetooth;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.annotation.SdkConstant;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.annotation.SdkConstant.SdkConstantType;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
2341d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganeshimport android.os.ParcelUuid;
2462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganeshimport android.os.RemoteException;
2562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganeshimport android.os.ServiceManager;
2662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganeshimport android.server.BluetoothA2dpService;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
29bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellyimport java.util.Collections;
3062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganeshimport java.util.Arrays;
3162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganeshimport java.util.HashMap;
32bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellyimport java.util.HashSet;
3362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganeshimport java.util.Set;
3462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
3762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * This class provides the public APIs to control the Bluetooth A2DP
3862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * profile.
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh *<p>BluetoothA2dp is a proxy object for controlling the Bluetooth A2DP
4162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
4262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * the BluetoothA2dp proxy object.
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * <p> Android only supports one connected Bluetooth A2dp device at a time.
4562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Each method is protected with its appropriate permission.
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
4762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganeshpublic final class BluetoothA2dp implements BluetoothProfile {
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "BluetoothA2dp";
49f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2The Android Open Source Project    private static final boolean DBG = false;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
5262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * Intent used to broadcast the change in connection state of the A2DP
5362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * profile.
5462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
5562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * <p>This intent will have 3 extras:
5662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #EXTRA_STATE} - The current state of the profile.
5762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile
5862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link BluetoothDevice#EXTRA_DEVICE} - The remote device.
5962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
6062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
6162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
6262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
6362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
6462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
6562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     */
6662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
6762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public static final String ACTION_CONNECTION_STATE_CHANGED =
6862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        "android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED";
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
7162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * Intent used to broadcast the change in the Playing state of the A2DP
7262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * profile.
7362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
7462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * <p>This intent will have 3 extras:
7562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #EXTRA_STATE} - The current state of the profile.
7662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile
7762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link BluetoothDevice#EXTRA_DEVICE} - The remote device.
7862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
7962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
8062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #STATE_PLAYING}, {@link #STATE_NOT_PLAYING},
8162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
8262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
8562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public static final String ACTION_PLAYING_STATE_CHANGED =
8662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        "android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED";
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
8962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * A2DP sink device is streaming music. This state can be one of
9062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
9162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #ACTION_PLAYING_STATE_CHANGED} intent.
9262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     */
9362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public static final int STATE_PLAYING   =  10;
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
9662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * A2DP sink device is NOT streaming music. This state can be one of
9762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
9862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #ACTION_PLAYING_STATE_CHANGED} intent.
9962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     */
10062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public static final int STATE_NOT_PLAYING   =  11;
101bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly
10262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    private ServiceListener mServiceListener;
10362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    private IBluetoothA2dp mService;
10462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    private BluetoothAdapter mAdapter;
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a BluetoothA2dp proxy object for interacting with the local
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Bluetooth A2DP service.
10962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /*package*/ BluetoothA2dp(Context mContext, ServiceListener l) {
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IBinder b = ServiceManager.getService(BluetoothA2dpService.BLUETOOTH_A2DP_SERVICE);
11362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        mServiceListener = l;
11462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        mAdapter = BluetoothAdapter.getDefaultAdapter();
115081f58abb7ceb702fdb0b65ff0e0ff70dd265a30Michael Chan        if (b != null) {
116081f58abb7ceb702fdb0b65ff0e0ff70dd265a30Michael Chan            mService = IBluetoothA2dp.Stub.asInterface(b);
11762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            if (mServiceListener != null) {
11862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                mServiceListener.onServiceConnected(BluetoothProfile.A2DP, this);
11962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
120081f58abb7ceb702fdb0b65ff0e0ff70dd265a30Michael Chan        } else {
121081f58abb7ceb702fdb0b65ff0e0ff70dd265a30Michael Chan            Log.w(TAG, "Bluetooth A2DP service not available!");
122081f58abb7ceb702fdb0b65ff0e0ff70dd265a30Michael Chan
123081f58abb7ceb702fdb0b65ff0e0ff70dd265a30Michael Chan            // Instead of throwing an exception which prevents people from going
124081f58abb7ceb702fdb0b65ff0e0ff70dd265a30Michael Chan            // into Wireless settings in the emulator. Let it crash later when it is actually used.
125081f58abb7ceb702fdb0b65ff0e0ff70dd265a30Michael Chan            mService = null;
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
13062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@inheritDoc}
13162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @hide
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public boolean connect(BluetoothDevice device) {
13462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (DBG) log("connect(" + device + ")");
13562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled() &&
13662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            isValidDevice(device)) {
13762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            try {
13862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.connect(device);
13962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
14062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
14162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return false;
14262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
14562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        return false;
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
14962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@inheritDoc}
15062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @hide
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public boolean disconnect(BluetoothDevice device) {
15362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (DBG) log("disconnect(" + device + ")");
15462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled() &&
15562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            isValidDevice(device)) {
15662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            try {
15762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.disconnect(device);
15862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
15962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
16062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return false;
16162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
16462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        return false;
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
16862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@inheritDoc}
169f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan     */
17062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public Set<BluetoothDevice> getConnectedDevices() {
17162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (DBG) log("getConnectedDevices()");
17262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled()) {
17362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            try {
17462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return toDeviceSet(mService.getConnectedDevices());
17562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
17662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
17762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return toDeviceSet(new BluetoothDevice[0]);
17862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
179f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan        }
18062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
18162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        return toDeviceSet(new BluetoothDevice[0]);
182f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan    }
183f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan
18462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
18562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@inheritDoc}
186f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan     */
18762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public Set<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
18862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (DBG) log("getDevicesMatchingStates()");
18962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled()) {
19062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            try {
19162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return toDeviceSet(mService.getDevicesMatchingConnectionStates(states));
19262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
19362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
19462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return toDeviceSet(new BluetoothDevice[0]);
19562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
196f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan        }
19762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
19862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        return toDeviceSet(new BluetoothDevice[0]);
199f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan    }
200f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan
20162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
20262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@inheritDoc}
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
20462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public int getConnectionState(BluetoothDevice device) {
20562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (DBG) log("getState(" + device + ")");
20662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled()
20762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            && isValidDevice(device)) {
20862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            try {
20962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.getConnectionState(device);
21062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
21162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
21262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return BluetoothProfile.STATE_DISCONNECTED;
21362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
21462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        }
21562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
21662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        return BluetoothProfile.STATE_DISCONNECTED;
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
22062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@inheritDoc}
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
22362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public boolean setPriority(BluetoothDevice device, int priority) {
22462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (DBG) log("setPriority(" + device + ", " + priority + ")");
22562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled()
22662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            && isValidDevice(device)) {
22762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            if (priority != BluetoothProfile.PRIORITY_OFF &&
22862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                priority != BluetoothProfile.PRIORITY_ON) {
22962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh              return false;
23062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
23162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            try {
23262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.setPriority(device, priority);
23362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
23462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
23562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return false;
23662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
23962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        return false;
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
24262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
24362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@inheritDoc}
244b16c4f7dd92dabf0cc27438a5d3d9ebd203a38b3Jaikumar Ganesh     * @hide
245b16c4f7dd92dabf0cc27438a5d3d9ebd203a38b3Jaikumar Ganesh     */
24662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public int getPriority(BluetoothDevice device) {
24762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (DBG) log("getPriority(" + device + ")");
24862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled()
24962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            && isValidDevice(device)) {
25062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            try {
25162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.getPriority(device);
25262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
25362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
25462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return BluetoothProfile.PRIORITY_OFF;
25562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
256b16c4f7dd92dabf0cc27438a5d3d9ebd203a38b3Jaikumar Ganesh        }
25762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
25862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        return BluetoothProfile.PRIORITY_OFF;
259b16c4f7dd92dabf0cc27438a5d3d9ebd203a38b3Jaikumar Ganesh    }
260b16c4f7dd92dabf0cc27438a5d3d9ebd203a38b3Jaikumar Ganesh
26162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
26262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * Check if A2DP profile is streaming music.
26362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
26462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
26562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
26662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @param device BluetoothDevice device
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
26862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public boolean isA2dpPlaying(BluetoothDevice device) {
26962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled()
27062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            && isValidDevice(device)) {
27162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            try {
27262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.isA2dpPlaying(device);
27362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
27462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
27562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return false;
27662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
27862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
27962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        return false;
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
28362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * Initiate suspend from an A2DP sink.
28462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
28562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * <p> This API will return false in scenarios like the A2DP
28662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * device is not in connected state etc. When this API returns,
28762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * true, it is guaranteed that {@link #ACTION_SINK_STATE_CHANGED}
28862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * intent will be broadcasted with the state. Users can get the
28962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * state of the A2DP device from this intent.
29062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
29162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
29262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
29362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @param device Remote A2DP sink
29462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @return false on immediate error,
29562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *               true otherwise
29662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @hide
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
29862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public boolean suspendSink(BluetoothDevice device) {
29962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled()
30062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            && isValidDevice(device)) {
30162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            try {
30262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.suspendSink(device);
30362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
30462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
30562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return false;
30662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
30862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
30962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        return false;
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
31362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * Initiate resume from a suspended A2DP sink.
31462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
31562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * <p> This API will return false in scenarios like the A2DP
31662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * device is not in suspended state etc. When this API returns,
31762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * true, it is guaranteed that {@link #ACTION_SINK_STATE_CHANGED}
31862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * intent will be broadcasted with the state. Users can get the
31962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * state of the A2DP device from this intent.
32062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
32162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
32262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
32362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @param device Remote A2DP sink
32462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @return false on immediate error,
32562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *               true otherwise
32662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @hide
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
32862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public boolean resumeSink(BluetoothDevice device) {
32962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled()
33062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            && isValidDevice(device)) {
33162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            try {
33262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.resumeSink(device);
33362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
33462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
33562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return false;
33662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
33862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
33962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        return false;
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
34241d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh    /**
34341d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh     * This function checks if the remote device is an AVCRP
34441d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh     * target and thus whether we should send volume keys
34541d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh     * changes or not.
34641d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh     * @hide
34741d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh     */
34841d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh    public boolean shouldSendVolumeKeys(BluetoothDevice device) {
34941d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh        if (isEnabled() && isValidDevice(device)) {
35041d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh            ParcelUuid[] uuids = device.getUuids();
35141d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh            if (uuids == null) return false;
35241d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh
35341d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh            for (ParcelUuid uuid: uuids) {
35441d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh                if (BluetoothUuid.isAvrcpTarget(uuid)) {
35541d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh                    return true;
35641d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh                }
35741d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh            }
35841d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh        }
35941d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh        return false;
36041d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh    }
36141d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh
36262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     /**
36362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * Helper for converting a state to a string.
36462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * For debug use only - strings are not internationalized.
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static String stateToString(int state) {
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (state) {
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case STATE_DISCONNECTED:
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "disconnected";
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case STATE_CONNECTING:
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "connecting";
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case STATE_CONNECTED:
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "connected";
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case STATE_DISCONNECTING:
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "disconnecting";
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case STATE_PLAYING:
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "playing";
38062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        case STATE_NOT_PLAYING:
38162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh          return "not playing";
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        default:
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "<unknown state " + state + ">";
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
386f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2The Android Open Source Project
38762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    private boolean isEnabled() {
38862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh       if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
38962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh       return false;
39062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    }
39162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
39262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    private boolean isValidDevice(BluetoothDevice device) {
39362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh       if (device == null) return false;
39462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
39562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh       if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
39662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh       return false;
39762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    }
39862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
39962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    private Set<BluetoothDevice> toDeviceSet(BluetoothDevice[] devices) {
40062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh       return Collections.unmodifiableSet(
40162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh          new HashSet<BluetoothDevice>(Arrays.asList(devices)));
40262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    }
40362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
404f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2The Android Open Source Project    private static void log(String msg) {
40562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh      Log.d(TAG, msg);
406f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2The Android Open Source Project    }
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
408