BluetoothA2dp.java revision 2d2d8c28545c687dbb105006ef4554eac8480313
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;
213e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xieimport android.content.ComponentName;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
233e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xieimport android.content.Intent;
243e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xieimport android.content.ServiceConnection;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
2641d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganeshimport android.os.ParcelUuid;
2762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganeshimport android.os.RemoteException;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3003cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganeshimport java.util.ArrayList;
3103cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganeshimport java.util.List;
3262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
3562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * This class provides the public APIs to control the Bluetooth A2DP
3662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * profile.
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
3862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh *<p>BluetoothA2dp is a proxy object for controlling the Bluetooth A2DP
3962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
4062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * the BluetoothA2dp proxy object.
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * <p> Android only supports one connected Bluetooth A2dp device at a time.
4362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Each method is protected with its appropriate permission.
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
4562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganeshpublic final class BluetoothA2dp implements BluetoothProfile {
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "BluetoothA2dp";
473e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie    private static final boolean DBG = true;
48563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie    private static final boolean VDBG = false;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
5162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * Intent used to broadcast the change in connection state of the A2DP
5262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * profile.
5362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
5462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * <p>This intent will have 3 extras:
55c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * <ul>
56c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *   <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
57c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *   <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
58c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *   <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
59c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * </ul>
6062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
610706fed52075f7f2b25101a40287519ac18d3184Jaikumar Ganesh     * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
6262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
6362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
6462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
65c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
66c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * receive.
6762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     */
6862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
6962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public static final String ACTION_CONNECTION_STATE_CHANGED =
7062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        "android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED";
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
7362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * Intent used to broadcast the change in the Playing state of the A2DP
7462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * profile.
7562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
7662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * <p>This intent will have 3 extras:
77c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * <ul>
78c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *   <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
79c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     *   <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li>
800706fed52075f7f2b25101a40287519ac18d3184Jaikumar Ganesh     *   <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
81c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * </ul>
8262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
830706fed52075f7f2b25101a40287519ac18d3184Jaikumar Ganesh     * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
8462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #STATE_PLAYING}, {@link #STATE_NOT_PLAYING},
8562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
86c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
87c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * receive.
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
9062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public static final String ACTION_PLAYING_STATE_CHANGED =
9162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        "android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED";
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
933b76a4b2b62e9539e2629dc569d7e9a934e65dfbHemant Gupta    /** @hide */
943b76a4b2b62e9539e2629dc569d7e9a934e65dfbHemant Gupta    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
953b76a4b2b62e9539e2629dc569d7e9a934e65dfbHemant Gupta    public static final String ACTION_AVRCP_CONNECTION_STATE_CHANGED =
963b76a4b2b62e9539e2629dc569d7e9a934e65dfbHemant Gupta        "android.bluetooth.a2dp.profile.action.AVRCP_CONNECTION_STATE_CHANGED";
973b76a4b2b62e9539e2629dc569d7e9a934e65dfbHemant Gupta
9862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
9962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * A2DP sink device is streaming music. This state can be one of
10062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
10162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #ACTION_PLAYING_STATE_CHANGED} intent.
10262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     */
10362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public static final int STATE_PLAYING   =  10;
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
10662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * A2DP sink device is NOT streaming music. This state can be one of
10762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
10862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@link #ACTION_PLAYING_STATE_CHANGED} intent.
10962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     */
11062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public static final int STATE_NOT_PLAYING   =  11;
111bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly
1123e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie    private Context mContext;
11362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    private ServiceListener mServiceListener;
11462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    private IBluetoothA2dp mService;
11562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    private BluetoothAdapter mAdapter;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1170f42037eb7b5118015c2caca635538324ccf0ccffredc    final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
1180f42037eb7b5118015c2caca635538324ccf0ccffredc            new IBluetoothStateChangeCallback.Stub() {
1190f42037eb7b5118015c2caca635538324ccf0ccffredc                public void onBluetoothStateChange(boolean up) {
1200f42037eb7b5118015c2caca635538324ccf0ccffredc                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
1210f42037eb7b5118015c2caca635538324ccf0ccffredc                    if (!up) {
122563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie                        if (VDBG) Log.d(TAG,"Unbinding service...");
1230f42037eb7b5118015c2caca635538324ccf0ccffredc                        synchronized (mConnection) {
1240f42037eb7b5118015c2caca635538324ccf0ccffredc                            try {
1250f42037eb7b5118015c2caca635538324ccf0ccffredc                                mService = null;
1260f42037eb7b5118015c2caca635538324ccf0ccffredc                                mContext.unbindService(mConnection);
1270f42037eb7b5118015c2caca635538324ccf0ccffredc                            } catch (Exception re) {
1280f42037eb7b5118015c2caca635538324ccf0ccffredc                                Log.e(TAG,"",re);
1290f42037eb7b5118015c2caca635538324ccf0ccffredc                            }
1300f42037eb7b5118015c2caca635538324ccf0ccffredc                        }
1310f42037eb7b5118015c2caca635538324ccf0ccffredc                    } else {
1320f42037eb7b5118015c2caca635538324ccf0ccffredc                        synchronized (mConnection) {
1330f42037eb7b5118015c2caca635538324ccf0ccffredc                            try {
1340f42037eb7b5118015c2caca635538324ccf0ccffredc                                if (mService == null) {
135563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie                                    if (VDBG) Log.d(TAG,"Binding service...");
136221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn                                    doBind();
1370f42037eb7b5118015c2caca635538324ccf0ccffredc                                }
1380f42037eb7b5118015c2caca635538324ccf0ccffredc                            } catch (Exception re) {
1390f42037eb7b5118015c2caca635538324ccf0ccffredc                                Log.e(TAG,"",re);
1400f42037eb7b5118015c2caca635538324ccf0ccffredc                            }
1410f42037eb7b5118015c2caca635538324ccf0ccffredc                        }
1420f42037eb7b5118015c2caca635538324ccf0ccffredc                    }
1430f42037eb7b5118015c2caca635538324ccf0ccffredc                }
1440f42037eb7b5118015c2caca635538324ccf0ccffredc        };
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a BluetoothA2dp proxy object for interacting with the local
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Bluetooth A2DP service.
14862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1503e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie    /*package*/ BluetoothA2dp(Context context, ServiceListener l) {
1513e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        mContext = context;
15262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        mServiceListener = l;
15362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        mAdapter = BluetoothAdapter.getDefaultAdapter();
1540f42037eb7b5118015c2caca635538324ccf0ccffredc        IBluetoothManager mgr = mAdapter.getBluetoothManager();
1550f42037eb7b5118015c2caca635538324ccf0ccffredc        if (mgr != null) {
1560f42037eb7b5118015c2caca635538324ccf0ccffredc            try {
1570f42037eb7b5118015c2caca635538324ccf0ccffredc                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
1580f42037eb7b5118015c2caca635538324ccf0ccffredc            } catch (RemoteException e) {
1590f42037eb7b5118015c2caca635538324ccf0ccffredc                Log.e(TAG,"",e);
1600f42037eb7b5118015c2caca635538324ccf0ccffredc            }
1610f42037eb7b5118015c2caca635538324ccf0ccffredc        }
1620f42037eb7b5118015c2caca635538324ccf0ccffredc
163221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn        doBind();
164221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn    }
165221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn
166221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn    boolean doBind() {
167221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn        Intent intent = new Intent(IBluetoothA2dp.class.getName());
168221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
169221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn        intent.setComponent(comp);
170466ce96da8ca7ea8c97e716b02a7d55007179aa1Dianne Hackborn        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
171466ce96da8ca7ea8c97e716b02a7d55007179aa1Dianne Hackborn                android.os.Process.myUserHandle())) {
172221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn            Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent);
173221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn            return false;
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
175221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn        return true;
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1789bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh    /*package*/ void close() {
1799bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh        mServiceListener = null;
1800f42037eb7b5118015c2caca635538324ccf0ccffredc        IBluetoothManager mgr = mAdapter.getBluetoothManager();
1810f42037eb7b5118015c2caca635538324ccf0ccffredc        if (mgr != null) {
1820f42037eb7b5118015c2caca635538324ccf0ccffredc            try {
1830f42037eb7b5118015c2caca635538324ccf0ccffredc                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
1840f42037eb7b5118015c2caca635538324ccf0ccffredc            } catch (Exception e) {
1850f42037eb7b5118015c2caca635538324ccf0ccffredc                Log.e(TAG,"",e);
1860f42037eb7b5118015c2caca635538324ccf0ccffredc            }
1870f42037eb7b5118015c2caca635538324ccf0ccffredc        }
1880f42037eb7b5118015c2caca635538324ccf0ccffredc
1890f42037eb7b5118015c2caca635538324ccf0ccffredc        synchronized (mConnection) {
1900f42037eb7b5118015c2caca635538324ccf0ccffredc            if (mService != null) {
1910f42037eb7b5118015c2caca635538324ccf0ccffredc                try {
1920f42037eb7b5118015c2caca635538324ccf0ccffredc                    mService = null;
1930f42037eb7b5118015c2caca635538324ccf0ccffredc                    mContext.unbindService(mConnection);
1940f42037eb7b5118015c2caca635538324ccf0ccffredc                } catch (Exception re) {
1950f42037eb7b5118015c2caca635538324ccf0ccffredc                    Log.e(TAG,"",re);
1960f42037eb7b5118015c2caca635538324ccf0ccffredc                }
1970f42037eb7b5118015c2caca635538324ccf0ccffredc            }
1980f42037eb7b5118015c2caca635538324ccf0ccffredc        }
1999bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh    }
2009bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh
2010f42037eb7b5118015c2caca635538324ccf0ccffredc    public void finalize() {
2022d2d8c28545c687dbb105006ef4554eac8480313Mathias Jeppsson        // The empty finalize needs to be kept or the
2032d2d8c28545c687dbb105006ef4554eac8480313Mathias Jeppsson        // cts signature tests would fail.
2040f42037eb7b5118015c2caca635538324ccf0ccffredc    }
20562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
206f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Initiate connection to a profile of the remote bluetooth device.
207f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
208f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> Currently, the system supports only 1 connection to the
209f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * A2DP profile. The API will automatically disconnect connected
210f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * devices before connecting.
211f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
212f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> This API returns false in scenarios like the profile on the
213f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * device is already connected or Bluetooth is not turned on.
214f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * When this API returns true, it is guaranteed that
215f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * connection state intent for the profile will be broadcasted with
216f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * the state. Users can get the connection state of the profile
217f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * from this intent.
218f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
219f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
220f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * permission.
221f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
222f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param device Remote Bluetooth Device
223f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @return false on immediate error,
224f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *               true otherwise
22562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @hide
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
22762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public boolean connect(BluetoothDevice device) {
22862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (DBG) log("connect(" + device + ")");
22962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled() &&
23062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            isValidDevice(device)) {
23162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            try {
23262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.connect(device);
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    /**
243f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Initiate disconnection from a profile
244f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
245f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> This API will return false in scenarios like the profile on the
246f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Bluetooth device is not in connected state etc. When this API returns,
247f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * true, it is guaranteed that the connection state change
248f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * intent will be broadcasted with the state. Users can get the
249f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * disconnection state of the profile from this intent.
250f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
251f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> If the disconnection is initiated by a remote device, the state
252f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * will transition from {@link #STATE_CONNECTED} to
253f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
254f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * host (local) device the state will transition from
255f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
256f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * state {@link #STATE_DISCONNECTED}. The transition to
257f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #STATE_DISCONNECTING} can be used to distinguish between the
258f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * two scenarios.
259f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
260f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
261f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * permission.
262f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
263f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param device Remote Bluetooth Device
264f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @return false on immediate error,
265f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *               true otherwise
26662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @hide
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
26862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public boolean disconnect(BluetoothDevice device) {
26962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (DBG) log("disconnect(" + device + ")");
27062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled() &&
27162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            isValidDevice(device)) {
27262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            try {
27362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.disconnect(device);
27462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
27562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
27662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return false;
27762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
27962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
28062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        return false;
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
28362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
28462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@inheritDoc}
285f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan     */
28603cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh    public List<BluetoothDevice> getConnectedDevices() {
287563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("getConnectedDevices()");
28862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled()) {
28962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            try {
29003cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh                return mService.getConnectedDevices();
29162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
29262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
29303cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh                return new ArrayList<BluetoothDevice>();
29462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
295f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan        }
29662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
29703cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh        return new ArrayList<BluetoothDevice>();
298f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan    }
299f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan
30062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
30162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@inheritDoc}
302f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan     */
30303cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
304563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("getDevicesMatchingStates()");
30562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled()) {
30662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            try {
30703cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh                return mService.getDevicesMatchingConnectionStates(states);
30862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
30962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
31003cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh                return new ArrayList<BluetoothDevice>();
31162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
312f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan        }
31362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
31403cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh        return new ArrayList<BluetoothDevice>();
315f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan    }
316f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57Zhu Lan
31762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
31862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * {@inheritDoc}
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
32062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public int getConnectionState(BluetoothDevice device) {
321563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("getState(" + device + ")");
32262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled()
32362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            && isValidDevice(device)) {
32462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            try {
32562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.getConnectionState(device);
32662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
32762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
32862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return BluetoothProfile.STATE_DISCONNECTED;
32962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
33062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        }
33162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
33262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        return BluetoothProfile.STATE_DISCONNECTED;
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
33562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
336f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Set priority of the profile
337f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
338f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> The device should already be paired.
3390f42037eb7b5118015c2caca635538324ccf0ccffredc     *  Priority can be one of {@link #PRIORITY_ON} orgetBluetoothManager
340f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #PRIORITY_OFF},
341f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
342f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
343f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * permission.
344f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
345f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param device Paired bluetooth device
346f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param priority
347f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @return true if priority is set, false on error
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
35062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public boolean setPriority(BluetoothDevice device, int priority) {
35162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (DBG) log("setPriority(" + device + ", " + priority + ")");
35262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled()
35362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            && isValidDevice(device)) {
35462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            if (priority != BluetoothProfile.PRIORITY_OFF &&
3556f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta                priority != BluetoothProfile.PRIORITY_ON){
35662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh              return false;
35762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
35862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            try {
35962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.setPriority(device, priority);
36062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
36162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
36262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return false;
36362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
36562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
36662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        return false;
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
36962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
370f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Get the priority of the profile.
371f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
372f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> The priority can be any of:
373f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
374f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
375f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
376f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
377f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
378f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param device Bluetooth device
379f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @return priority of the device
380b16c4f7dd92dabf0cc27438a5d3d9ebd203a38b3Jaikumar Ganesh     * @hide
381b16c4f7dd92dabf0cc27438a5d3d9ebd203a38b3Jaikumar Ganesh     */
38262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public int getPriority(BluetoothDevice device) {
383563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("getPriority(" + device + ")");
38462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled()
38562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            && isValidDevice(device)) {
38662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            try {
38762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.getPriority(device);
38862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
38962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
39062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return BluetoothProfile.PRIORITY_OFF;
39162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
392b16c4f7dd92dabf0cc27438a5d3d9ebd203a38b3Jaikumar Ganesh        }
39362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
39462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        return BluetoothProfile.PRIORITY_OFF;
395b16c4f7dd92dabf0cc27438a5d3d9ebd203a38b3Jaikumar Ganesh    }
396b16c4f7dd92dabf0cc27438a5d3d9ebd203a38b3Jaikumar Ganesh
39762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    /**
3985a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     * Checks if Avrcp device supports the absolute volume feature.
3995a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     *
4005a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     * @return true if device supports absolute volume
4015a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     * @hide
4025a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     */
4035a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du    public boolean isAvrcpAbsoluteVolumeSupported() {
4045a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du        if (DBG) Log.d(TAG, "isAvrcpAbsoluteVolumeSupported");
4055a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du        if (mService != null && isEnabled()) {
4065a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du            try {
4075a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du                return mService.isAvrcpAbsoluteVolumeSupported();
4085a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du            } catch (RemoteException e) {
4095a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du                Log.e(TAG, "Error talking to BT service in isAvrcpAbsoluteVolumeSupported()", e);
4105a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du                return false;
4115a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du            }
4125a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du        }
4135a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du        if (mService == null) Log.w(TAG, "Proxy not attached to service");
4145a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du        return false;
4155a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du    }
4165a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du
4175a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du    /**
4185a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     * Tells remote device to adjust volume. Only if absolute volume is supported.
4195a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     *
4205a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     * @param direction 1 to increase volume, or -1 to decrease volume
4215a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     * @hide
4225a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     */
4235a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du    public void adjustAvrcpAbsoluteVolume(int direction) {
4245a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du        if (DBG) Log.d(TAG, "adjustAvrcpAbsoluteVolume");
4255a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du        if (mService != null && isEnabled()) {
4265a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du            try {
4275a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du                mService.adjustAvrcpAbsoluteVolume(direction);
4285a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du                return;
4295a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du            } catch (RemoteException e) {
4305a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du                Log.e(TAG, "Error talking to BT service in adjustAvrcpAbsoluteVolume()", e);
4315a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du                return;
4325a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du            }
4335a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du        }
4345a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du        if (mService == null) Log.w(TAG, "Proxy not attached to service");
4355a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du    }
4365a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du
4375a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du    /**
4385a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     * Tells remote device to set an absolute volume. Only if absolute volume is supported
4395a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     *
4405a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     * @param volume Absolute volume to be set on AVRCP side
4415a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     * @hide
4425a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du     */
4435a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du    public void setAvrcpAbsoluteVolume(int volume) {
4445a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du        if (DBG) Log.d(TAG, "setAvrcpAbsoluteVolume");
4455a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du        if (mService != null && isEnabled()) {
4465a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du            try {
4475a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du                mService.setAvrcpAbsoluteVolume(volume);
4485a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du                return;
4495a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du            } catch (RemoteException e) {
4505a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du                Log.e(TAG, "Error talking to BT service in setAvrcpAbsoluteVolume()", e);
4515a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du                return;
4525a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du            }
4535a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du        }
4545a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du        if (mService == null) Log.w(TAG, "Proxy not attached to service");
4555a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du    }
4565a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du
4575a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du    /**
45862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * Check if A2DP profile is streaming music.
45962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
460c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
46162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
46262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * @param device BluetoothDevice device
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
46462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    public boolean isA2dpPlaying(BluetoothDevice device) {
46562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService != null && isEnabled()
46662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            && isValidDevice(device)) {
46762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            try {
46862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return mService.isA2dpPlaying(device);
46962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            } catch (RemoteException e) {
47062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
47162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh                return false;
47262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh            }
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
47462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
47562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        return false;
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
47941d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh     * This function checks if the remote device is an AVCRP
48041d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh     * target and thus whether we should send volume keys
48141d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh     * changes or not.
48241d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh     * @hide
48341d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh     */
48441d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh    public boolean shouldSendVolumeKeys(BluetoothDevice device) {
48541d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh        if (isEnabled() && isValidDevice(device)) {
48641d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh            ParcelUuid[] uuids = device.getUuids();
48741d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh            if (uuids == null) return false;
48841d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh
48941d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh            for (ParcelUuid uuid: uuids) {
49041d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh                if (BluetoothUuid.isAvrcpTarget(uuid)) {
49141d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh                    return true;
49241d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh                }
49341d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh            }
49441d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh        }
49541d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh        return false;
49641d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh    }
49741d5c805d96aef0aaa9a2aaa86ccc4b77ca75e11Jaikumar Ganesh
498a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie    /**
49962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     * Helper for converting a state to a string.
50062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh     *
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * For debug use only - strings are not internationalized.
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static String stateToString(int state) {
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (state) {
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case STATE_DISCONNECTED:
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "disconnected";
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case STATE_CONNECTING:
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "connecting";
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case STATE_CONNECTED:
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "connected";
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case STATE_DISCONNECTING:
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "disconnecting";
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case STATE_PLAYING:
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "playing";
51662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh        case STATE_NOT_PLAYING:
51762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh          return "not playing";
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        default:
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "<unknown state " + state + ">";
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
522f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2The Android Open Source Project
5239b6939939901cb82bc6fca93aad3810a4936dfc6Matthew Xie    private final ServiceConnection mConnection = new ServiceConnection() {
5243e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        public void onServiceConnected(ComponentName className, IBinder service) {
5253e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            if (DBG) Log.d(TAG, "Proxy object connected");
5263e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            mService = IBluetoothA2dp.Stub.asInterface(service);
5273e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie
5283e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            if (mServiceListener != null) {
5293e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie                mServiceListener.onServiceConnected(BluetoothProfile.A2DP, BluetoothA2dp.this);
5303e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            }
5313e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        }
5323e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        public void onServiceDisconnected(ComponentName className) {
5333e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            if (DBG) Log.d(TAG, "Proxy object disconnected");
5343e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            mService = null;
5353e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            if (mServiceListener != null) {
5363e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie                mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP);
5373e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie            }
5383e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie        }
5393e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie    };
5403e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie
54162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    private boolean isEnabled() {
54262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh       if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
54362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh       return false;
54462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    }
54562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
54662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    private boolean isValidDevice(BluetoothDevice device) {
54762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh       if (device == null) return false;
54862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
54962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh       if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
55062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh       return false;
55162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh    }
55262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh
553f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2The Android Open Source Project    private static void log(String msg) {
55462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh      Log.d(TAG, msg);
555f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2The Android Open Source Project    }
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
557