BluetoothA2dp.java revision 44a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0f
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
192d49752ee050ab7f1cd848933f6c62a73707e2d9Tor Norbyeimport android.Manifest;
202d49752ee050ab7f1cd848933f6c62a73707e2d9Tor Norbyeimport android.annotation.RequiresPermission;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.annotation.SdkConstant;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.annotation.SdkConstant.SdkConstantType;
233e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xieimport android.content.ComponentName;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
253e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xieimport android.content.Intent;
263e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xieimport android.content.ServiceConnection;
274197cb60bc74629fe4c04ab10cb3b1c9a7427d24RoboErikimport android.media.AudioManager;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
2941d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganeshimport android.os.ParcelUuid;
3062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganeshimport android.os.RemoteException;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
33d7d16b9f372116da1658f589df213aed33c2ded6Calvin Onimport com.android.internal.annotations.GuardedBy;
34d7d16b9f372116da1658f589df213aed33c2ded6Calvin On
3503cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganeshimport java.util.ArrayList;
3603cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganeshimport java.util.List;
37d7d16b9f372116da1658f589df213aed33c2ded6Calvin Onimport java.util.concurrent.locks.ReentrantReadWriteLock;
3862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
4162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * This class provides the public APIs to control the Bluetooth A2DP
4262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * profile.
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh *<p>BluetoothA2dp is a proxy object for controlling the Bluetooth A2DP
4562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
4662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * the BluetoothA2dp proxy object.
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * <p> Android only supports one connected Bluetooth A2dp device at a time.
4962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Each method is protected with its appropriate permission.
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
5162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganeshpublic final class BluetoothA2dp implements BluetoothProfile {
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "BluetoothA2dp";
533e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie    private static final boolean DBG = true;
54563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie    private static final boolean VDBG = false;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
5762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * Intent used to broadcast the change in connection state of the A2DP
5862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * profile.
5962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
6062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * <p>This intent will have 3 extras:
61c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * <ul>
62c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *   <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
63c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *   <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
64c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *   <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
65c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * </ul>
6662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
670706fed52075f7f2b25101a40287519ac18d3184Jaikumar Ganesh     * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
6862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
6962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
7062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
71c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
72c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * receive.
7362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     */
7462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
7562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public static final String ACTION_CONNECTION_STATE_CHANGED =
7662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        "android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED";
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
7962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * Intent used to broadcast the change in the Playing state of the A2DP
8062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * profile.
8162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
8262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * <p>This intent will have 3 extras:
83c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * <ul>
84c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *   <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
85c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *   <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li>
860706fed52075f7f2b25101a40287519ac18d3184Jaikumar Ganesh     *   <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
87c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * </ul>
8862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
890706fed52075f7f2b25101a40287519ac18d3184Jaikumar Ganesh     * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
9062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #STATE_PLAYING}, {@link #STATE_NOT_PLAYING},
9162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
92c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
93c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * receive.
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
9662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public static final String ACTION_PLAYING_STATE_CHANGED =
9762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        "android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED";
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
993b76a4b2b62e9539e2629dc569d7e9a934e65dfbHemant Gupta    /** @hide */
1003b76a4b2b62e9539e2629dc569d7e9a934e65dfbHemant Gupta    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
1013b76a4b2b62e9539e2629dc569d7e9a934e65dfbHemant Gupta    public static final String ACTION_AVRCP_CONNECTION_STATE_CHANGED =
1023b76a4b2b62e9539e2629dc569d7e9a934e65dfbHemant Gupta        "android.bluetooth.a2dp.profile.action.AVRCP_CONNECTION_STATE_CHANGED";
1033b76a4b2b62e9539e2629dc569d7e9a934e65dfbHemant Gupta
10462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
10544a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     * Intent used to broadcast the change in the Audio Codec state of the
10644a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     * A2DP Source profile.
10744a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     *
10844a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     * <p>This intent will have 3 extras:
10944a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     * <ul>
11044a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     *   <li> {@link #EXTRA_CODEC_CONFIG} - The current codec configuration. </li>
11144a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     *   <li> {@link #EXTRA_PREVIOUS_CODEC_CONFIG} - The previous codec configuration. </li>
11244a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     *   <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device if the device is currently
11344a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     *   connected, otherwise it is not included.</li>
11444a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     * </ul>
11544a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     *
11644a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
11744a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     * receive.
11844a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     *
11944a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     * @hide
12044a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     */
12144a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
12244a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov    public static final String ACTION_CODEC_CONFIG_CHANGED =
12344a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov        "android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED";
12444a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov
12544a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov    /**
12662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * A2DP sink device is streaming music. This state can be one of
12762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
12862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #ACTION_PLAYING_STATE_CHANGED} intent.
12962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     */
13062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public static final int STATE_PLAYING   =  10;
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
13362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * A2DP sink device is NOT streaming music. This state can be one of
13462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
13562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #ACTION_PLAYING_STATE_CHANGED} intent.
13662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     */
13762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public static final int STATE_NOT_PLAYING   =  11;
138bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly
1393e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie    private Context mContext;
14062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    private ServiceListener mServiceListener;
141d7d16b9f372116da1658f589df213aed33c2ded6Calvin On    private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
142d7d16b9f372116da1658f589df213aed33c2ded6Calvin On    @GuardedBy("mServiceLock") private IBluetoothA2dp mService;
14362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    private BluetoothAdapter mAdapter;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1450f42037eb7b5118015c2caca635538324ccf0ccffredc    final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
1460f42037eb7b5118015c2caca635538324ccf0ccffredc            new IBluetoothStateChangeCallback.Stub() {
1470f42037eb7b5118015c2caca635538324ccf0ccffredc                public void onBluetoothStateChange(boolean up) {
1480f42037eb7b5118015c2caca635538324ccf0ccffredc                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
1490f42037eb7b5118015c2caca635538324ccf0ccffredc                    if (!up) {
150d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                        if (VDBG) Log.d(TAG, "Unbinding service...");
151d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                        try {
152d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                            mServiceLock.writeLock().lock();
153d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                            mService = null;
154d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                            mContext.unbindService(mConnection);
155d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                        } catch (Exception re) {
156d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                            Log.e(TAG, "", re);
157d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                        } finally {
158d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                            mServiceLock.writeLock().unlock();
1590f42037eb7b5118015c2caca635538324ccf0ccffredc                        }
1600f42037eb7b5118015c2caca635538324ccf0ccffredc                    } else {
161d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                        try {
162d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                            mServiceLock.readLock().lock();
163d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                            if (mService == null) {
164d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                                if (VDBG) Log.d(TAG,"Binding service...");
165d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                                doBind();
1660f42037eb7b5118015c2caca635538324ccf0ccffredc                            }
167d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                        } catch (Exception re) {
168d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                            Log.e(TAG,"",re);
169d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                        } finally {
170d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                            mServiceLock.readLock().unlock();
1710f42037eb7b5118015c2caca635538324ccf0ccffredc                        }
1720f42037eb7b5118015c2caca635538324ccf0ccffredc                    }
1730f42037eb7b5118015c2caca635538324ccf0ccffredc                }
1740f42037eb7b5118015c2caca635538324ccf0ccffredc        };
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a BluetoothA2dp proxy object for interacting with the local
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Bluetooth A2DP service.
17862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1803e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie    /*package*/ BluetoothA2dp(Context context, ServiceListener l) {
1813e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        mContext = context;
18262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        mServiceListener = l;
18362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        mAdapter = BluetoothAdapter.getDefaultAdapter();
1840f42037eb7b5118015c2caca635538324ccf0ccffredc        IBluetoothManager mgr = mAdapter.getBluetoothManager();
1850f42037eb7b5118015c2caca635538324ccf0ccffredc        if (mgr != null) {
1860f42037eb7b5118015c2caca635538324ccf0ccffredc            try {
1870f42037eb7b5118015c2caca635538324ccf0ccffredc                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
1880f42037eb7b5118015c2caca635538324ccf0ccffredc            } catch (RemoteException e) {
1890f42037eb7b5118015c2caca635538324ccf0ccffredc                Log.e(TAG,"",e);
1900f42037eb7b5118015c2caca635538324ccf0ccffredc            }
1910f42037eb7b5118015c2caca635538324ccf0ccffredc        }
1920f42037eb7b5118015c2caca635538324ccf0ccffredc
193221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn        doBind();
194221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn    }
195221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn
196221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn    boolean doBind() {
197221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn        Intent intent = new Intent(IBluetoothA2dp.class.getName());
198221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
199221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn        intent.setComponent(comp);
200466ce96da8ca7ea8c97e716b02a7d55007179aa1Dianne Hackborn        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
201466ce96da8ca7ea8c97e716b02a7d55007179aa1Dianne Hackborn                android.os.Process.myUserHandle())) {
202221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn            Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent);
203221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn            return false;
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
205221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn        return true;
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2089bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh    /*package*/ void close() {
2099bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh        mServiceListener = null;
2100f42037eb7b5118015c2caca635538324ccf0ccffredc        IBluetoothManager mgr = mAdapter.getBluetoothManager();
2110f42037eb7b5118015c2caca635538324ccf0ccffredc        if (mgr != null) {
2120f42037eb7b5118015c2caca635538324ccf0ccffredc            try {
2130f42037eb7b5118015c2caca635538324ccf0ccffredc                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
2140f42037eb7b5118015c2caca635538324ccf0ccffredc            } catch (Exception e) {
2150f42037eb7b5118015c2caca635538324ccf0ccffredc                Log.e(TAG,"",e);
2160f42037eb7b5118015c2caca635538324ccf0ccffredc            }
2170f42037eb7b5118015c2caca635538324ccf0ccffredc        }
2180f42037eb7b5118015c2caca635538324ccf0ccffredc
219d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        try {
220d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            mServiceLock.writeLock().lock();
2210f42037eb7b5118015c2caca635538324ccf0ccffredc            if (mService != null) {
222d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                mService = null;
223d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                mContext.unbindService(mConnection);
2240f42037eb7b5118015c2caca635538324ccf0ccffredc            }
225d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        } catch (Exception re) {
226d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            Log.e(TAG, "", re);
227d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        } finally {
228d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            mServiceLock.writeLock().unlock();
2290f42037eb7b5118015c2caca635538324ccf0ccffredc        }
2309bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh    }
2319bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh
2320f42037eb7b5118015c2caca635538324ccf0ccffredc    public void finalize() {
2332d2d8c28545c687dbb105006ef4554eac8480313Mathias Jeppsson        // The empty finalize needs to be kept or the
2342d2d8c28545c687dbb105006ef4554eac8480313Mathias Jeppsson        // cts signature tests would fail.
2350f42037eb7b5118015c2caca635538324ccf0ccffredc    }
23662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
237f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Initiate connection to a profile of the remote bluetooth device.
238f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
239f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> Currently, the system supports only 1 connection to the
240f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * A2DP profile. The API will automatically disconnect connected
241f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * devices before connecting.
242f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
243f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> This API returns false in scenarios like the profile on the
244f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * device is already connected or Bluetooth is not turned on.
245f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * When this API returns true, it is guaranteed that
246f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * connection state intent for the profile will be broadcasted with
247f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * the state. Users can get the connection state of the profile
248f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * from this intent.
249f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
250f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
251f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * permission.
252f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
253f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param device Remote Bluetooth Device
254f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @return false on immediate error,
255f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *               true otherwise
25662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @hide
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
25862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public boolean connect(BluetoothDevice device) {
25962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (DBG) log("connect(" + device + ")");
260d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        try {
261d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            mServiceLock.readLock().lock();
262d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            if (mService != null && isEnabled() &&
263d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                isValidDevice(device)) {
26462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.connect(device);
26562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
266d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            if (mService == null) Log.w(TAG, "Proxy not attached to service");
267d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            return false;
268d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        } catch (RemoteException e) {
269d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
270d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            return false;
271d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        } finally {
272d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            mServiceLock.readLock().unlock();
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
27662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
277f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Initiate disconnection from a profile
278f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
279f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> This API will return false in scenarios like the profile on the
280f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Bluetooth device is not in connected state etc. When this API returns,
281f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * true, it is guaranteed that the connection state change
282f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * intent will be broadcasted with the state. Users can get the
283f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * disconnection state of the profile from this intent.
284f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
285f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> If the disconnection is initiated by a remote device, the state
286f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * will transition from {@link #STATE_CONNECTED} to
287f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
288f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * host (local) device the state will transition from
289f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
290f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * state {@link #STATE_DISCONNECTED}. The transition to
291f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #STATE_DISCONNECTING} can be used to distinguish between the
292f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * two scenarios.
293f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
294f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
295f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * permission.
296f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
297f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param device Remote Bluetooth Device
298f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @return false on immediate error,
299f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *               true otherwise
30062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @hide
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
30262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public boolean disconnect(BluetoothDevice device) {
30362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (DBG) log("disconnect(" + device + ")");
304d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        try {
305d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            mServiceLock.readLock().lock();
306d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            if (mService != null && isEnabled() &&
307d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                isValidDevice(device)) {
30862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.disconnect(device);
30962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
310d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            if (mService == null) Log.w(TAG, "Proxy not attached to service");
311d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            return false;
312d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        } catch (RemoteException e) {
313d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
314d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            return false;
315d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        } finally {
316d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            mServiceLock.readLock().unlock();
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
32062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
32162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@inheritDoc}
322f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan     */
32303cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh    public List<BluetoothDevice> getConnectedDevices() {
324563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("getConnectedDevices()");
325d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        try {
326d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            mServiceLock.readLock().lock();
327d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            if (mService != null && isEnabled()) {
32803cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh                return mService.getConnectedDevices();
32962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
330d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            if (mService == null) Log.w(TAG, "Proxy not attached to service");
331d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            return new ArrayList<BluetoothDevice>();
332d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        } catch (RemoteException e) {
333d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
334d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            return new ArrayList<BluetoothDevice>();
335d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        } finally {
336d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            mServiceLock.readLock().unlock();
337f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan        }
338f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan    }
339f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan
34062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
34162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@inheritDoc}
342f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan     */
34303cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
344563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("getDevicesMatchingStates()");
345d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        try {
346d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            mServiceLock.readLock().lock();
347d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            if (mService != null && isEnabled()) {
34803cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh                return mService.getDevicesMatchingConnectionStates(states);
34962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
350d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            if (mService == null) Log.w(TAG, "Proxy not attached to service");
351d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            return new ArrayList<BluetoothDevice>();
352d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        } catch (RemoteException e) {
353d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
354d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            return new ArrayList<BluetoothDevice>();
355d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        } finally {
356d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            mServiceLock.readLock().unlock();
357f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan        }
358f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan    }
359f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan
36062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
36162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@inheritDoc}
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
36362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public int getConnectionState(BluetoothDevice device) {
364563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("getState(" + device + ")");
365d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        try {
366d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            mServiceLock.readLock().lock();
367d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            if (mService != null && isEnabled()
368d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                && isValidDevice(device)) {
36962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.getConnectionState(device);
37062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
371d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            if (mService == null) Log.w(TAG, "Proxy not attached to service");
372d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            return BluetoothProfile.STATE_DISCONNECTED;
373d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        } catch (RemoteException e) {
374d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
375d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            return BluetoothProfile.STATE_DISCONNECTED;
376d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        } finally {
377d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            mServiceLock.readLock().unlock();
37862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        }
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
38162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
382f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Set priority of the profile
383f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
384f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> The device should already be paired.
3850f42037eb7b5118015c2caca635538324ccf0ccffredc     *  Priority can be one of {@link #PRIORITY_ON} orgetBluetoothManager
386f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #PRIORITY_OFF},
387f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
388f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
389f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * permission.
390f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
391f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param device Paired bluetooth device
392f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param priority
393f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @return true if priority is set, false on error
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
39662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public boolean setPriority(BluetoothDevice device, int priority) {
39762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (DBG) log("setPriority(" + device + ", " + priority + ")");
398d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        try {
399d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            mServiceLock.readLock().lock();
400d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            if (mService != null && isEnabled()
401d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                && isValidDevice(device)) {
402d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                if (priority != BluetoothProfile.PRIORITY_OFF &&
403d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                    priority != BluetoothProfile.PRIORITY_ON) {
404d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                    return false;
405d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                }
40662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.setPriority(device, priority);
40762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
408d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            if (mService == null) Log.w(TAG, "Proxy not attached to service");
409d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            return false;
410d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        } catch (RemoteException e) {
411d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
412d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            return false;
413d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        } finally {
414d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            mServiceLock.readLock().unlock();
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
41862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
419f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Get the priority of the profile.
420f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
421f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> The priority can be any of:
422f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
423f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
424f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
425f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
426f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
427f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param device Bluetooth device
428f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @return priority of the device
429b16c4f7dd92dabf0cc27438a5d3d9ebd203a38b3Jaikumar Ganesh     * @hide
430b16c4f7dd92dabf0cc27438a5d3d9ebd203a38b3Jaikumar Ganesh     */
4312d49752ee050ab7f1cd848933f6c62a73707e2d9Tor Norbye    @RequiresPermission(Manifest.permission.BLUETOOTH)
43262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public int getPriority(BluetoothDevice device) {
433563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("getPriority(" + device + ")");
434d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        try {
435d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            mServiceLock.readLock().lock();
436d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            if (mService != null && isEnabled()
437d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                && isValidDevice(device)) {
43862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.getPriority(device);
43962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
440d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            if (mService == null) Log.w(TAG, "Proxy not attached to service");
441d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            return BluetoothProfile.PRIORITY_OFF;
442d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        } catch (RemoteException e) {
443d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
444d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            return BluetoothProfile.PRIORITY_OFF;
445d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        } finally {
446d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            mServiceLock.readLock().unlock();
447b16c4f7dd92dabf0cc27438a5d3d9ebd203a38b3Jaikumar Ganesh        }
448b16c4f7dd92dabf0cc27438a5d3d9ebd203a38b3Jaikumar Ganesh    }
449b16c4f7dd92dabf0cc27438a5d3d9ebd203a38b3Jaikumar Ganesh
45062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
4515a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     * Checks if Avrcp device supports the absolute volume feature.
4525a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     *
4535a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     * @return true if device supports absolute volume
4545a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     * @hide
4555a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     */
4565a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du    public boolean isAvrcpAbsoluteVolumeSupported() {
4575a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du        if (DBG) Log.d(TAG, "isAvrcpAbsoluteVolumeSupported");
458d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        try {
459d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            mServiceLock.readLock().lock();
460d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            if (mService != null && isEnabled()) {
4615a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du                return mService.isAvrcpAbsoluteVolumeSupported();
4625a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du            }
463d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            if (mService == null) Log.w(TAG, "Proxy not attached to service");
464d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            return false;
465d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        } catch (RemoteException e) {
466d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            Log.e(TAG, "Error talking to BT service in isAvrcpAbsoluteVolumeSupported()", e);
467d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            return false;
468d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        } finally {
469d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            mServiceLock.readLock().unlock();
4705a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du        }
4715a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du    }
4725a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du
4735a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du    /**
4744197cb60bc74629fe4c04ab10cb3b1c9a7427d24RoboErik     * Tells remote device to adjust volume. Only if absolute volume is
4754197cb60bc74629fe4c04ab10cb3b1c9a7427d24RoboErik     * supported. Uses the following values:
4764197cb60bc74629fe4c04ab10cb3b1c9a7427d24RoboErik     * <ul>
4774197cb60bc74629fe4c04ab10cb3b1c9a7427d24RoboErik     * <li>{@link AudioManager#ADJUST_LOWER}</li>
4784197cb60bc74629fe4c04ab10cb3b1c9a7427d24RoboErik     * <li>{@link AudioManager#ADJUST_RAISE}</li>
4794197cb60bc74629fe4c04ab10cb3b1c9a7427d24RoboErik     * <li>{@link AudioManager#ADJUST_MUTE}</li>
4804197cb60bc74629fe4c04ab10cb3b1c9a7427d24RoboErik     * <li>{@link AudioManager#ADJUST_UNMUTE}</li>
4814197cb60bc74629fe4c04ab10cb3b1c9a7427d24RoboErik     * </ul>
4825a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     *
4834197cb60bc74629fe4c04ab10cb3b1c9a7427d24RoboErik     * @param direction One of the supported adjust values.
4845a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     * @hide
4855a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     */
4865a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du    public void adjustAvrcpAbsoluteVolume(int direction) {
4875a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du        if (DBG) Log.d(TAG, "adjustAvrcpAbsoluteVolume");
488d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        try {
489d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            mServiceLock.readLock().lock();
490d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            if (mService != null && isEnabled()) {
4915a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du                mService.adjustAvrcpAbsoluteVolume(direction);
4925a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du            }
493d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            if (mService == null) Log.w(TAG, "Proxy not attached to service");
494d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        } catch (RemoteException e) {
495d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            Log.e(TAG, "Error talking to BT service in adjustAvrcpAbsoluteVolume()", e);
496d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        } finally {
497d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            mServiceLock.readLock().unlock();
4985a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du        }
4995a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du    }
5005a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du
5015a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du    /**
5025a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     * Tells remote device to set an absolute volume. Only if absolute volume is supported
5035a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     *
5045a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     * @param volume Absolute volume to be set on AVRCP side
5055a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     * @hide
5065a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     */
5075a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du    public void setAvrcpAbsoluteVolume(int volume) {
5085a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du        if (DBG) Log.d(TAG, "setAvrcpAbsoluteVolume");
509d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        try {
510d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            mServiceLock.readLock().lock();
511d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            if (mService != null && isEnabled()) {
5125a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du                mService.setAvrcpAbsoluteVolume(volume);
5135a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du            }
514d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            if (mService == null) Log.w(TAG, "Proxy not attached to service");
515d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        } catch (RemoteException e) {
516d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            Log.e(TAG, "Error talking to BT service in setAvrcpAbsoluteVolume()", e);
517d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        } finally {
518d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            mServiceLock.readLock().unlock();
5195a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du        }
5205a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du    }
5215a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du
5225a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du    /**
52362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * Check if A2DP profile is streaming music.
52462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
525c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
52662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
52762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @param device BluetoothDevice device
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
52962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public boolean isA2dpPlaying(BluetoothDevice device) {
530d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        try {
531d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            mServiceLock.readLock().lock();
532d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            if (mService != null && isEnabled()
533d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                && isValidDevice(device)) {
53462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.isA2dpPlaying(device);
53562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
536d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            if (mService == null) Log.w(TAG, "Proxy not attached to service");
537d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            return false;
538d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        } catch (RemoteException e) {
539d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
540d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            return false;
541d7d16b9f372116da1658f589df213aed33c2ded6Calvin On        } finally {
542d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            mServiceLock.readLock().unlock();
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
54741d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh     * This function checks if the remote device is an AVCRP
54841d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh     * target and thus whether we should send volume keys
54941d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh     * changes or not.
55041d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh     * @hide
55141d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh     */
55241d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh    public boolean shouldSendVolumeKeys(BluetoothDevice device) {
55341d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh        if (isEnabled() && isValidDevice(device)) {
55441d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh            ParcelUuid[] uuids = device.getUuids();
55541d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh            if (uuids == null) return false;
55641d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh
55741d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh            for (ParcelUuid uuid: uuids) {
55841d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh                if (BluetoothUuid.isAvrcpTarget(uuid)) {
55941d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh                    return true;
56041d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh                }
56141d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh            }
56241d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh        }
56341d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh        return false;
56441d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh    }
56541d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh
566a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    /**
56744a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     * Gets the current codec configuration.
56844a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     *
56944a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     * @return the current codec configuration
57044a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     * @hide
57144a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     */
57244a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov    public BluetoothCodecConfig getCodecConfig() {
57344a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov        if (DBG) Log.d(TAG, "getCodecConfig");
57444a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov        try {
57544a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov            mServiceLock.readLock().lock();
57644a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov            if (mService != null && isEnabled()) {
57744a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov                return mService.getCodecConfig();
57844a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov            }
57944a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov            if (mService == null) {
58044a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov                Log.w(TAG, "Proxy not attached to service");
58144a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov            }
58244a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov            return null;
58344a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov        } catch (RemoteException e) {
58444a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov            Log.e(TAG, "Error talking to BT service in getCodecConfig()", e);
58544a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov            return null;
58644a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov        } finally {
58744a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov            mServiceLock.readLock().unlock();
58844a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov        }
58944a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov    }
59044a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov
59144a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov    /**
59244a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     * Sets the codec configuration preference.
59344a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     *
59444a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     * @param codecConfig the codec configuration preference
59544a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     * @hide
59644a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov     */
59744a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov    public void setCodecConfigPreference(BluetoothCodecConfig codecConfig) {
59844a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov        if (DBG) Log.d(TAG, "setCodecConfigPreference");
59944a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov        try {
60044a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov            mServiceLock.readLock().lock();
60144a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov            if (mService != null && isEnabled()) {
60244a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov                mService.setCodecConfigPreference(codecConfig);
60344a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov            }
60444a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov            if (mService == null) Log.w(TAG, "Proxy not attached to service");
60544a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov            return;
60644a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov        } catch (RemoteException e) {
60744a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov            Log.e(TAG, "Error talking to BT service in setCodecConfigPreference()", e);
60844a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov            return;
60944a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov        } finally {
61044a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov            mServiceLock.readLock().unlock();
61144a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov        }
61244a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov    }
61344a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov
61444a4ef0aa93ebb2912f36d65af42ffbb1bcdbc0fPavlin Radoslavov    /**
61562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * Helper for converting a state to a string.
61662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * For debug use only - strings are not internationalized.
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static String stateToString(int state) {
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (state) {
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case STATE_DISCONNECTED:
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "disconnected";
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case STATE_CONNECTING:
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "connecting";
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case STATE_CONNECTED:
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "connected";
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case STATE_DISCONNECTING:
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "disconnecting";
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case STATE_PLAYING:
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "playing";
63262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        case STATE_NOT_PLAYING:
63362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh          return "not playing";
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        default:
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "<unknown state " + state + ">";
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
638f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2The Android Open Source Project
6399b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie    private final ServiceConnection mConnection = new ServiceConnection() {
6403e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        public void onServiceConnected(ComponentName className, IBinder service) {
6413e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            if (DBG) Log.d(TAG, "Proxy object connected");
642d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            try {
643d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                mServiceLock.writeLock().lock();
644d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                mService = IBluetoothA2dp.Stub.asInterface(service);
645d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            } finally {
646d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                mServiceLock.writeLock().unlock();
647d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            }
6483e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie
6493e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            if (mServiceListener != null) {
6503e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie                mServiceListener.onServiceConnected(BluetoothProfile.A2DP, BluetoothA2dp.this);
6513e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            }
6523e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        }
6533e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        public void onServiceDisconnected(ComponentName className) {
6543e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            if (DBG) Log.d(TAG, "Proxy object disconnected");
655d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            try {
656d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                mServiceLock.writeLock().lock();
657d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                mService = null;
658d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            } finally {
659d7d16b9f372116da1658f589df213aed33c2ded6Calvin On                mServiceLock.writeLock().unlock();
660d7d16b9f372116da1658f589df213aed33c2ded6Calvin On            }
6613e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            if (mServiceListener != null) {
6623e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie                mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP);
6633e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            }
6643e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        }
6653e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie    };
6663e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie
66762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    private boolean isEnabled() {
66862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh       if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
66962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh       return false;
67062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    }
67162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
67262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    private boolean isValidDevice(BluetoothDevice device) {
67362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh       if (device == null) return false;
67462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
67562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh       if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
67662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh       return false;
67762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    }
67862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
679f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2The Android Open Source Project    private static void log(String msg) {
68062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh      Log.d(TAG, msg);
681f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2The Android Open Source Project    }
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
683