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