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 19005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pellyimport android.annotation.SdkConstant; 20005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pellyimport android.annotation.SdkConstant.SdkConstantType; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ComponentName; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 23e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franzimport android.os.Handler; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder; 25e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franzimport android.os.Looper; 26e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franzimport android.os.Message; 2703cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar 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 * Public API for controlling the Bluetooth Headset Service. This includes both 3562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Bluetooth Headset and Handsfree (v1.5) profiles. 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * <p>BluetoothHeadset is a proxy object for controlling the Bluetooth Headset 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Service via IPC. 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * <p> Use {@link BluetoothAdapter#getProfileProxy} to get 4162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * the BluetoothHeadset proxy object. Use 4262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@link BluetoothAdapter#closeProfileProxy} to close the service connection. 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * <p> Android only supports one connected Bluetooth Headset at a time. 4562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Each method is protected with its appropriate permission. 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganeshpublic final class BluetoothHeadset implements BluetoothProfile { 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "BluetoothHeadset"; 490f42037eb7b5118015c2caca635538324ccf0ccffredc private static final boolean DBG = true; 50563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie private static final boolean VDBG = false; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh /** 5362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Intent used to broadcast the change in connection state of the Headset 5462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * profile. 5562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 5662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * <p>This intent will have 3 extras: 57c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <ul> 58c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> 59c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li> 60c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> 61c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * </ul> 620706fed52075f7f2b25101a40287519ac18d3184Jaikumar Ganesh * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of 6362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING}, 6462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}. 6562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 66c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to 67c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * receive. 6862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh */ 69005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 7062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh public static final String ACTION_CONNECTION_STATE_CHANGED = 7162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh "android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED"; 7262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh 73005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly /** 7462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Intent used to broadcast the change in the Audio Connection state of the 7562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * A2DP profile. 7662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 7762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * <p>This intent will have 3 extras: 78c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <ul> 79c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> 80c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li> 81c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> 82c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * </ul> 830706fed52075f7f2b25101a40287519ac18d3184Jaikumar Ganesh * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of 8462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@link #STATE_AUDIO_CONNECTED}, {@link #STATE_AUDIO_DISCONNECTED}, 8562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 86c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission 87c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * to receive. 88005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly */ 89005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 90005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly public static final String ACTION_AUDIO_STATE_CHANGED = 9162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh "android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED"; 9262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh 93c24dbdb57b30f9e8fa6b0c5b48372017b5ae46b0Jaikumar Ganesh 94005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly /** 95e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * Intent used to broadcast that the headset has posted a 96e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * vendor-specific event. 97e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * 98e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * <p>This intent will have 4 extras and 1 category. 99c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <ul> 100c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote Bluetooth Device 101c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * </li> 102c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <li> {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD} - The vendor 103c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * specific command </li> 104c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <li> {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE} - The AT 105c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * command type which can be one of {@link #AT_CMD_TYPE_READ}, 106c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * {@link #AT_CMD_TYPE_TEST}, or {@link #AT_CMD_TYPE_SET}, 1070706fed52075f7f2b25101a40287519ac18d3184Jaikumar Ganesh * {@link #AT_CMD_TYPE_BASIC},{@link #AT_CMD_TYPE_ACTION}. </li> 108c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <li> {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS} - Command 109c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * arguments. </li> 110c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * </ul> 111e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * 1120706fed52075f7f2b25101a40287519ac18d3184Jaikumar Ganesh *<p> The category is the Company ID of the vendor defining the 113e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * vendor-specific command. {@link BluetoothAssignedNumbers} 114e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * 115e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * For example, for Plantronics specific events 116e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * Category will be {@link #VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY}.55 117e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * 118e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * <p> For example, an AT+XEVENT=foo,3 will get translated into 119c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <ul> 120c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <li> EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD = +XEVENT </li> 121c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <li> EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE = AT_CMD_TYPE_SET </li> 1220706fed52075f7f2b25101a40287519ac18d3184Jaikumar Ganesh * <li> EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS = foo, 3 </li> 123c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * </ul> 124c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission 125c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * to receive. 126a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek */ 127a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 128a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek public static final String ACTION_VENDOR_SPECIFIC_HEADSET_EVENT = 129a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek "android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT"; 130a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek 131a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek /** 132a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek * A String extra field in {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT} 133a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek * intents that contains the name of the vendor-specific command. 134a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek */ 135a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD = 136a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_CMD"; 137a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek 138a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek /** 139a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek * An int extra field in {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT} 140e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * intents that contains the AT command type of the vendor-specific command. 141e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh */ 142e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE = 143e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE"; 144e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh 145e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh /** 146e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * AT command type READ used with 147e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE} 148e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * For example, AT+VGM?. There are no arguments for this command type. 149e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh */ 150e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh public static final int AT_CMD_TYPE_READ = 0; 151e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh 152e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh /** 153e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * AT command type TEST used with 154e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE} 155e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * For example, AT+VGM=?. There are no arguments for this command type. 156e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh */ 157e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh public static final int AT_CMD_TYPE_TEST = 1; 158e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh 159e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh /** 160e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * AT command type SET used with 161e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE} 162e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * For example, AT+VGM=<args>. 163e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh */ 164e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh public static final int AT_CMD_TYPE_SET = 2; 165e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh 166e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh /** 167e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * AT command type BASIC used with 168e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE} 169e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * For example, ATD. Single character commands and everything following the 170e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * character are arguments. 171e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh */ 172e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh public static final int AT_CMD_TYPE_BASIC = 3; 173e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh 174e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh /** 175e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * AT command type ACTION used with 176e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE} 177e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * For example, AT+CHUP. There are no arguments for action commands. 178a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek */ 179e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh public static final int AT_CMD_TYPE_ACTION = 4; 180a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek 181a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek /** 182a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek * A Parcelable String array extra field in 183a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek * {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT} intents that contains 184a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek * the arguments to the vendor-specific command. 185a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek */ 186a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS = 187a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_ARGS"; 188a4733941839abd672b1e37edd7f61c8932d4aa48Herb Jellinek 189e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh /** 190e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * The intent category to be used with {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT} 191e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh * for the companyId 192e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh */ 193e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh public static final String VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY = 194e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh "android.bluetooth.headset.intent.category.companyid"; 195e775b3daab9766bce9ec2d01fe7d652c4a782b6bJaikumar Ganesh 19630d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh /** 197922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee * A vendor-specific command for unsolicited result code. 198922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee */ 199922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee public static final String VENDOR_RESULT_CODE_COMMAND_ANDROID = "+ANDROID"; 200922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee 201922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee /** 202c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * Headset state when SCO audio is not connected. 20362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * This state can be one of 20462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of 20562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@link #ACTION_AUDIO_STATE_CHANGED} intent. 206005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly */ 207b0a1d01b4c044a0779cfe006e204bac468459802Jaikumar Ganesh public static final int STATE_AUDIO_DISCONNECTED = 10; 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 210c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * Headset state when SCO audio is connecting. 21162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * This state can be one of 21262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of 21362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@link #ACTION_AUDIO_STATE_CHANGED} intent. 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 215b0a1d01b4c044a0779cfe006e204bac468459802Jaikumar Ganesh public static final int STATE_AUDIO_CONNECTING = 11; 21662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh 21730d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh /** 218c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * Headset state when SCO audio is connected. 21930d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh * This state can be one of 22030d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of 22130d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh * {@link #ACTION_AUDIO_STATE_CHANGED} intent. 22230d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh */ 223b0a1d01b4c044a0779cfe006e204bac468459802Jaikumar Ganesh public static final int STATE_AUDIO_CONNECTED = 12; 224b0a1d01b4c044a0779cfe006e204bac468459802Jaikumar Ganesh 225e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz private static final int MESSAGE_HEADSET_SERVICE_CONNECTED = 100; 226e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz private static final int MESSAGE_HEADSET_SERVICE_DISCONNECTED = 101; 22762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh 22862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh private Context mContext; 22962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh private ServiceListener mServiceListener; 23062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh private IBluetoothHeadset mService; 231bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie private BluetoothAdapter mAdapter; 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2330f42037eb7b5118015c2caca635538324ccf0ccffredc final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = 2340f42037eb7b5118015c2caca635538324ccf0ccffredc new IBluetoothStateChangeCallback.Stub() { 2350f42037eb7b5118015c2caca635538324ccf0ccffredc public void onBluetoothStateChange(boolean up) { 2360f42037eb7b5118015c2caca635538324ccf0ccffredc if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); 2370f42037eb7b5118015c2caca635538324ccf0ccffredc if (!up) { 238563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) Log.d(TAG,"Unbinding service..."); 239e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz doUnbind(); 2400f42037eb7b5118015c2caca635538324ccf0ccffredc } else { 2410f42037eb7b5118015c2caca635538324ccf0ccffredc synchronized (mConnection) { 2420f42037eb7b5118015c2caca635538324ccf0ccffredc try { 2430f42037eb7b5118015c2caca635538324ccf0ccffredc if (mService == null) { 244563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) Log.d(TAG,"Binding service..."); 245221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn doBind(); 2460f42037eb7b5118015c2caca635538324ccf0ccffredc } 2470f42037eb7b5118015c2caca635538324ccf0ccffredc } catch (Exception re) { 2480f42037eb7b5118015c2caca635538324ccf0ccffredc Log.e(TAG,"",re); 2490f42037eb7b5118015c2caca635538324ccf0ccffredc } 2500f42037eb7b5118015c2caca635538324ccf0ccffredc } 2510f42037eb7b5118015c2caca635538324ccf0ccffredc } 2520f42037eb7b5118015c2caca635538324ccf0ccffredc } 2530f42037eb7b5118015c2caca635538324ccf0ccffredc }; 2540f42037eb7b5118015c2caca635538324ccf0ccffredc 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a BluetoothHeadset proxy object. 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 25862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh /*package*/ BluetoothHeadset(Context context, ServiceListener l) { 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mServiceListener = l; 26162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh mAdapter = BluetoothAdapter.getDefaultAdapter(); 2620f42037eb7b5118015c2caca635538324ccf0ccffredc 2630f42037eb7b5118015c2caca635538324ccf0ccffredc IBluetoothManager mgr = mAdapter.getBluetoothManager(); 2640f42037eb7b5118015c2caca635538324ccf0ccffredc if (mgr != null) { 2650f42037eb7b5118015c2caca635538324ccf0ccffredc try { 2660f42037eb7b5118015c2caca635538324ccf0ccffredc mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); 2670f42037eb7b5118015c2caca635538324ccf0ccffredc } catch (RemoteException e) { 2680f42037eb7b5118015c2caca635538324ccf0ccffredc Log.e(TAG,"",e); 2690f42037eb7b5118015c2caca635538324ccf0ccffredc } 2700f42037eb7b5118015c2caca635538324ccf0ccffredc } 2710f42037eb7b5118015c2caca635538324ccf0ccffredc 272221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn doBind(); 273221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn } 274221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn 275221ea892dcc661bd07d6f36ff012edca2c48aed4Dianne Hackborn boolean doBind() { 276e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz try { 277e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz return mAdapter.getBluetoothManager().bindBluetoothProfileService( 278e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz BluetoothProfile.HEADSET, mConnection); 279e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } catch (RemoteException e) { 280e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz Log.e(TAG, "Unable to bind HeadsetService", e); 281e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 282e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz return false; 283e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 284e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 285e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz void doUnbind() { 286e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz synchronized (mConnection) { 287e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (mService != null) { 288e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz try { 289e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mAdapter.getBluetoothManager().unbindBluetoothProfileService( 290e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz BluetoothProfile.HEADSET, mConnection); 291e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } catch (RemoteException e) { 292e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz Log.e(TAG,"Unable to unbind HeadsetService", e); 293e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 294e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Close the connection to the backing service. 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Other public functions of BluetoothHeadset will return default error 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * results once close() has been called. Multiple invocations of close() 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * are ok. 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 30413450df2b9264ef2220418f308037c19cec739a9Matthew Xie /*package*/ void close() { 305563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) log("close()"); 3060f42037eb7b5118015c2caca635538324ccf0ccffredc 3070f42037eb7b5118015c2caca635538324ccf0ccffredc IBluetoothManager mgr = mAdapter.getBluetoothManager(); 3080f42037eb7b5118015c2caca635538324ccf0ccffredc if (mgr != null) { 3090f42037eb7b5118015c2caca635538324ccf0ccffredc try { 3100f42037eb7b5118015c2caca635538324ccf0ccffredc mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); 3110f42037eb7b5118015c2caca635538324ccf0ccffredc } catch (Exception e) { 3120f42037eb7b5118015c2caca635538324ccf0ccffredc Log.e(TAG,"",e); 3130f42037eb7b5118015c2caca635538324ccf0ccffredc } 3140f42037eb7b5118015c2caca635538324ccf0ccffredc } 315c88b6bdcfada95447269b41d388fd7028dba574bBenjamin Franz mServiceListener = null; 316e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz doUnbind(); 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 320f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * Initiate connection to a profile of the remote bluetooth device. 321f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 322f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * <p> Currently, the system supports only 1 connection to the 323f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * headset/handsfree profile. The API will automatically disconnect connected 324f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * devices before connecting. 325f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 326f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * <p> This API returns false in scenarios like the profile on the 327f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * device is already connected or Bluetooth is not turned on. 328f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * When this API returns true, it is guaranteed that 329f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * connection state intent for the profile will be broadcasted with 330f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * the state. Users can get the connection state of the profile 331f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * from this intent. 332f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 333f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 334f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * permission. 335f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 336f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * @param device Remote Bluetooth Device 337f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * @return false on immediate error, 338f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * true otherwise 33962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * @hide 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 34162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh public boolean connect(BluetoothDevice device) { 34262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (DBG) log("connect(" + device + ")"); 34362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService != null && isEnabled() && 34462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh isValidDevice(device)) { 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 34662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return mService.connect(device); 34762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } catch (RemoteException e) { 34862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh Log.e(TAG, Log.getStackTraceString(new Throwable())); 34962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 35062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService == null) Log.w(TAG, "Proxy not attached to service"); 35362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 357f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * Initiate disconnection from a profile 358f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 359f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * <p> This API will return false in scenarios like the profile on the 360f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * Bluetooth device is not in connected state etc. When this API returns, 361f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * true, it is guaranteed that the connection state change 362f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * intent will be broadcasted with the state. Users can get the 363f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * disconnection state of the profile from this intent. 364f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 365f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * <p> If the disconnection is initiated by a remote device, the state 366f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * will transition from {@link #STATE_CONNECTED} to 367f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the 368f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * host (local) device the state will transition from 369f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to 370f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * state {@link #STATE_DISCONNECTED}. The transition to 371f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * {@link #STATE_DISCONNECTING} can be used to distinguish between the 372f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * two scenarios. 373f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 374f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 375f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * permission. 376f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 377f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * @param device Remote Bluetooth Device 378f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * @return false on immediate error, 379f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * true otherwise 38062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * @hide 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 38262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh public boolean disconnect(BluetoothDevice device) { 38362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (DBG) log("disconnect(" + device + ")"); 38462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService != null && isEnabled() && 38562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh isValidDevice(device)) { 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 38762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return mService.disconnect(device); 38862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } catch (RemoteException e) { 38962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh Log.e(TAG, Log.getStackTraceString(new Throwable())); 39062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 39162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 39362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService == null) Log.w(TAG, "Proxy not attached to service"); 39462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 39862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@inheritDoc} 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 40003cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh public List<BluetoothDevice> getConnectedDevices() { 401563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) log("getConnectedDevices()"); 40262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService != null && isEnabled()) { 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 40403cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh return mService.getConnectedDevices(); 40562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } catch (RemoteException e) { 40662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh Log.e(TAG, Log.getStackTraceString(new Throwable())); 40703cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh return new ArrayList<BluetoothDevice>(); 40862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 41062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService == null) Log.w(TAG, "Proxy not attached to service"); 41103cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh return new ArrayList<BluetoothDevice>(); 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 41562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@inheritDoc} 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 41703cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 418563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) log("getDevicesMatchingStates()"); 41962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService != null && isEnabled()) { 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 42103cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh return mService.getDevicesMatchingConnectionStates(states); 42262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } catch (RemoteException e) { 42362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh Log.e(TAG, Log.getStackTraceString(new Throwable())); 42403cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh return new ArrayList<BluetoothDevice>(); 42562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 42762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService == null) Log.w(TAG, "Proxy not attached to service"); 42803cd78cf5e51c3adb78d2e3d314838dcf3e36b26Jaikumar Ganesh return new ArrayList<BluetoothDevice>(); 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 43262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * {@inheritDoc} 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 43462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh public int getConnectionState(BluetoothDevice device) { 435563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) log("getConnectionState(" + device + ")"); 43662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService != null && isEnabled() && 43762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh isValidDevice(device)) { 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 43962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return mService.getConnectionState(device); 44062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } catch (RemoteException e) { 44162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh Log.e(TAG, Log.getStackTraceString(new Throwable())); 44262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return BluetoothProfile.STATE_DISCONNECTED; 44362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 44562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService == null) Log.w(TAG, "Proxy not attached to service"); 44662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return BluetoothProfile.STATE_DISCONNECTED; 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 450f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * Set priority of the profile 451f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 452f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * <p> The device should already be paired. 453f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * Priority can be one of {@link #PRIORITY_ON} or 454f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * {@link #PRIORITY_OFF}, 455f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 456f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 457f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * permission. 458f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 459f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * @param device Paired bluetooth device 460f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * @param priority 461f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * @return true if priority is set, false on error 46262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * @hide 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 46462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh public boolean setPriority(BluetoothDevice device, int priority) { 46562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (DBG) log("setPriority(" + device + ", " + priority + ")"); 46662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService != null && isEnabled() && 46762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh isValidDevice(device)) { 46862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (priority != BluetoothProfile.PRIORITY_OFF && 4696f6c54519a9b15379bb79e195655b6bd4fc5967aGanesh Ganapathi Batta priority != BluetoothProfile.PRIORITY_ON) { 47062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 47162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 47362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return mService.setPriority(device, priority); 47462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } catch (RemoteException e) { 47562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh Log.e(TAG, Log.getStackTraceString(new Throwable())); 47662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 47762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 47962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService == null) Log.w(TAG, "Proxy not attached to service"); 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 484f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * Get the priority of the profile. 485f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 486f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * <p> The priority can be any of: 487f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF}, 488f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED} 489f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 490f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 491f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * 492f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * @param device Bluetooth device 493f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh * @return priority of the device 49462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * @hide 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 49662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh public int getPriority(BluetoothDevice device) { 497563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) log("getPriority(" + device + ")"); 49862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService != null && isEnabled() && 49962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh isValidDevice(device)) { 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 50162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return mService.getPriority(device); 50262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } catch (RemoteException e) { 50362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh Log.e(TAG, Log.getStackTraceString(new Throwable())); 50462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return PRIORITY_OFF; 50562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 50762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService == null) Log.w(TAG, "Proxy not attached to service"); 50862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return PRIORITY_OFF; 50962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 51062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh 51162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh /** 51262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Start Bluetooth voice recognition. This methods sends the voice 51362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * recognition AT command to the headset and establishes the 51462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * audio connection. 51562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 51662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * <p> Users can listen to {@link #ACTION_AUDIO_STATE_CHANGED}. 517b0a1d01b4c044a0779cfe006e204bac468459802Jaikumar Ganesh * If this function returns true, this intent will be broadcasted with 518b0a1d01b4c044a0779cfe006e204bac468459802Jaikumar Ganesh * {@link #EXTRA_STATE} set to {@link #STATE_AUDIO_CONNECTING}. 519b0a1d01b4c044a0779cfe006e204bac468459802Jaikumar Ganesh * 520b0a1d01b4c044a0779cfe006e204bac468459802Jaikumar Ganesh * <p> {@link #EXTRA_STATE} will transition from 521b0a1d01b4c044a0779cfe006e204bac468459802Jaikumar Ganesh * {@link #STATE_AUDIO_CONNECTING} to {@link #STATE_AUDIO_CONNECTED} when 522b0a1d01b4c044a0779cfe006e204bac468459802Jaikumar Ganesh * audio connection is established and to {@link #STATE_AUDIO_DISCONNECTED} 523b0a1d01b4c044a0779cfe006e204bac468459802Jaikumar Ganesh * in case of failure to establish the audio connection. 52462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 525b0a1d01b4c044a0779cfe006e204bac468459802Jaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 52662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 52762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * @param device Bluetooth headset 52862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * @return false if there is no headset connected of if the 52962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * connected headset doesn't support voice recognition 53062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * or on error, true otherwise 53162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh */ 53262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh public boolean startVoiceRecognition(BluetoothDevice device) { 53362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (DBG) log("startVoiceRecognition()"); 53462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService != null && isEnabled() && 53562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh isValidDevice(device)) { 53662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh try { 53762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return mService.startVoiceRecognition(device); 53862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } catch (RemoteException e) { 53962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh Log.e(TAG, Log.getStackTraceString(new Throwable())); 54062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 54162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 54262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService == null) Log.w(TAG, "Proxy not attached to service"); 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 54762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Stop Bluetooth Voice Recognition mode, and shut down the 54862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Bluetooth audio path. 54962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 550c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 55162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 55262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * @param device Bluetooth headset 55362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * @return false if there is no headset connected 55462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * or on error, true otherwise 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 55662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh public boolean stopVoiceRecognition(BluetoothDevice device) { 55762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (DBG) log("stopVoiceRecognition()"); 55862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService != null && isEnabled() && 55962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh isValidDevice(device)) { 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 56162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return mService.stopVoiceRecognition(device); 56262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } catch (RemoteException e) { 56362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh Log.e(TAG, Log.getStackTraceString(new Throwable())); 56462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 56662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService == null) Log.w(TAG, "Proxy not attached to service"); 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 57162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Check if Bluetooth SCO audio is connected. 57262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 573c8fa4ff838a0c3d2c67db65540fa751e5abe27edJaikumar Ganesh * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 57462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 57562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * @param device Bluetooth headset 57662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * @return true if SCO is connected, 57762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * false otherwise or on error 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 57962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh public boolean isAudioConnected(BluetoothDevice device) { 580563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) log("isAudioConnected()"); 58162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService != null && isEnabled() && 58262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh isValidDevice(device)) { 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 58462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return mService.isAudioConnected(device); 58562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } catch (RemoteException e) { 58662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh Log.e(TAG, Log.getStackTraceString(new Throwable())); 58762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 5886c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly } 58962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService == null) Log.w(TAG, "Proxy not attached to service"); 59062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 5916c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly } 5926c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly 5936c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly /** 5946c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly * Get battery usage hint for Bluetooth Headset service. 5956c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly * This is a monotonically increasing integer. Wraps to 0 at 5966c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly * Integer.MAX_INT, and at boot. 5976c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly * Current implementation returns the number of AT commands handled since 5986c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly * boot. This is a good indicator for spammy headset/handsfree units that 5996c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly * can keep the device awake by polling for cellular status updates. As a 6006c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly * rule of thumb, each AT command prevents the CPU from sleeping for 500 ms 60162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 60262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * @param device the bluetooth headset. 6036c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly * @return monotonically increasing battery usage hint, or a negative error 6046c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly * code on error 6056c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly * @hide 6066c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly */ 60762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh public int getBatteryUsageHint(BluetoothDevice device) { 608563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) log("getBatteryUsageHint()"); 60962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService != null && isEnabled() && 61062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh isValidDevice(device)) { 6116c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly try { 61262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return mService.getBatteryUsageHint(device); 61362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } catch (RemoteException e) { 61462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh Log.e(TAG, Log.getStackTraceString(new Throwable())); 61562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 61762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService == null) Log.w(TAG, "Proxy not attached to service"); 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 62062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh 621d726b35ebd8660022dcea706ee6d3ca51886b04eEric Laurent /** 622d726b35ebd8660022dcea706ee6d3ca51886b04eEric Laurent * Indicates if current platform supports voice dialing over bluetooth SCO. 62362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 624d726b35ebd8660022dcea706ee6d3ca51886b04eEric Laurent * @return true if voice dialing over bluetooth is supported, false otherwise. 625d726b35ebd8660022dcea706ee6d3ca51886b04eEric Laurent * @hide 626d726b35ebd8660022dcea706ee6d3ca51886b04eEric Laurent */ 627d726b35ebd8660022dcea706ee6d3ca51886b04eEric Laurent public static boolean isBluetoothVoiceDialingEnabled(Context context) { 628d726b35ebd8660022dcea706ee6d3ca51886b04eEric Laurent return context.getResources().getBoolean( 629d726b35ebd8660022dcea706ee6d3ca51886b04eEric Laurent com.android.internal.R.bool.config_bluetooth_sco_off_call); 630d726b35ebd8660022dcea706ee6d3ca51886b04eEric Laurent } 631d726b35ebd8660022dcea706ee6d3ca51886b04eEric Laurent 6329b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh /** 6339b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh * Accept the incoming connection. 63462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * Note: This is an internal function and shouldn't be exposed 63562c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 6369b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh * @hide 6379b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh */ 6389b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh public boolean acceptIncomingConnect(BluetoothDevice device) { 6399b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (DBG) log("acceptIncomingConnect"); 64062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mService != null && isEnabled()) { 6419b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh try { 6429b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return mService.acceptIncomingConnect(device); 6439b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } catch (RemoteException e) {Log.e(TAG, e.toString());} 6449b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } else { 6459b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh Log.w(TAG, "Proxy not attached to service"); 6469b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 6479b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 6489b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 6499b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 6509b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 6519b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh /** 652a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie * Reject the incoming connection. 653a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie * @hide 654a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie */ 655a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie public boolean rejectIncomingConnect(BluetoothDevice device) { 656a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (DBG) log("rejectIncomingConnect"); 657a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (mService != null) { 658a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie try { 659a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return mService.rejectIncomingConnect(device); 660a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } catch (RemoteException e) {Log.e(TAG, e.toString());} 661a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } else { 662a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie Log.w(TAG, "Proxy not attached to service"); 663a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 664a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 665a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie return false; 666a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie } 667a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie 668a0c680393f2dd03a937c598b2cb9abf98a58152cMatthew Xie /** 6693e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * Get the current audio state of the Headset. 6709b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh * Note: This is an internal function and shouldn't be exposed 67162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 6729b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh * @hide 6739b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh */ 6743e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie public int getAudioState(BluetoothDevice device) { 675563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) log("getAudioState"); 6763e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie if (mService != null && !isDisabled()) { 6779b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh try { 6783e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie return mService.getAudioState(device); 6799b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } catch (RemoteException e) {Log.e(TAG, e.toString());} 6809b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } else { 6819b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh Log.w(TAG, "Proxy not attached to service"); 6829b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 6839b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 6843e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie return BluetoothHeadset.STATE_AUDIO_DISCONNECTED; 6859b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 6869b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh 6879b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh /** 6883e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * Check if Bluetooth SCO audio is connected. 6893e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * 6903e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 69162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 6923e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * @return true if SCO is connected, 6933e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * false otherwise or on error 6949b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh * @hide 6959b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh */ 6963e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie public boolean isAudioOn() { 697563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie if (VDBG) log("isAudioOn()"); 6983e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie if (mService != null && isEnabled()) { 6999b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh try { 7003e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie return mService.isAudioOn(); 7013e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie } catch (RemoteException e) { 7023e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie Log.e(TAG, Log.getStackTraceString(new Throwable())); 7033e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie } 7049b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 7053e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie if (mService == null) Log.w(TAG, "Proxy not attached to service"); 7069b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh return false; 7073e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie 7089b637e5985f9a86f39d70335c0390ade3716592aJaikumar Ganesh } 70962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh 71062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh /** 7113e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * Initiates a connection of headset audio. 7123e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * It setup SCO channel with remote connected headset device. 71362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * 7143e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * @return true if successful 7153e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * false if there was some error such as 7163e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * there is no connected headset 71762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh * @hide 71862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh */ 7193e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie public boolean connectAudio() { 7203e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie if (mService != null && isEnabled()) { 72162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh try { 7223e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie return mService.connectAudio(); 7233e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie } catch (RemoteException e) { 7243e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie Log.e(TAG, e.toString()); 7253e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie } 72662c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } else { 72762c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh Log.w(TAG, "Proxy not attached to service"); 72862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 72962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 73062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 73162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 73262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh 73330d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh /** 7343e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * Initiates a disconnection of headset audio. 7353e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * It tears down the SCO channel from remote headset device. 73630d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh * 7373e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * @return true if successful 7383e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * false if there was some error such as 7393e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * there is no connected SCO channel 74030d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh * @hide 74130d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh */ 7423e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie public boolean disconnectAudio() { 7433e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie if (mService != null && isEnabled()) { 74430d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh try { 7453e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie return mService.disconnectAudio(); 7463e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie } catch (RemoteException e) { 7473e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie Log.e(TAG, e.toString()); 7483e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie } 74930d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh } else { 75030d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh Log.w(TAG, "Proxy not attached to service"); 75130d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 75230d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh } 7533e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie return false; 75430d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh } 75530d181690e48b26cdfae3b144d23f1e16c75da37Jaikumar Ganesh 756f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh /** 757dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh * Initiates a SCO channel connection with the headset (if connected). 758dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh * Also initiates a virtual voice call for Handsfree devices as many devices 759dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh * do not accept SCO audio without a call. 760dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh * This API allows the handsfree device to be used for routing non-cellular 761dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh * call audio. 762f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh * 763f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh * @param device Remote Bluetooth Device 764f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh * @return true if successful, false if there was some error. 765f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh * @hide 766f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh */ 767dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh public boolean startScoUsingVirtualVoiceCall(BluetoothDevice device) { 768dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh if (DBG) log("startScoUsingVirtualVoiceCall()"); 769f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh if (mService != null && isEnabled() && isValidDevice(device)) { 770f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh try { 771dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh return mService.startScoUsingVirtualVoiceCall(device); 772f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh } catch (RemoteException e) { 773f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh Log.e(TAG, e.toString()); 774f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh } 775f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh } else { 776f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh Log.w(TAG, "Proxy not attached to service"); 777f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 778f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh } 779f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh return false; 780f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh } 781f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh 782f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh /** 783dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh * Terminates an ongoing SCO connection and the associated virtual 784dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh * call. 785f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh * 786f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh * @param device Remote Bluetooth Device 787f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh * @return true if successful, false if there was some error. 788f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh * @hide 789f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh */ 790dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh public boolean stopScoUsingVirtualVoiceCall(BluetoothDevice device) { 791dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh if (DBG) log("stopScoUsingVirtualVoiceCall()"); 792f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh if (mService != null && isEnabled() && isValidDevice(device)) { 793f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh try { 794dde68c64fd8e97a592633ec4c09283ec928e5697Jaikumar Ganesh return mService.stopScoUsingVirtualVoiceCall(device); 795f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh } catch (RemoteException e) { 796f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh Log.e(TAG, e.toString()); 797f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh } 798f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh } else { 799f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh Log.w(TAG, "Proxy not attached to service"); 800f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 801f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh } 802f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh return false; 803f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh } 804f2e6b13620f3ebbb94166834abaaabcc08a403b7Jaikumar Ganesh 8053e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie /** 8063e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * Notify Headset of phone state change. 8073e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * This is a backdoor for phone app to call BluetoothHeadset since 8083e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * there is currently not a good way to get precise call state change outside 8093e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * of phone app. 8103e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * 8113e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * @hide 8123e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie */ 8133e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie public void phoneStateChanged(int numActive, int numHeld, int callState, String number, 8143e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie int type) { 8153e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie if (mService != null && isEnabled()) { 8163e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie try { 8173e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie mService.phoneStateChanged(numActive, numHeld, callState, number, type); 8183e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie } catch (RemoteException e) { 8193e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie Log.e(TAG, e.toString()); 8203e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie } 8213e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie } else { 8223e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie Log.w(TAG, "Proxy not attached to service"); 8233e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 8243e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie } 8253e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie } 8263e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie 8273e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie /** 8283e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * Send Headset of CLCC response 8293e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * 8303e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie * @hide 8313e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie */ 8323e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie public void clccResponse(int index, int direction, int status, int mode, boolean mpty, 8333e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie String number, int type) { 8343e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie if (mService != null && isEnabled()) { 8353e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie try { 8363e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie mService.clccResponse(index, direction, status, mode, mpty, number, type); 8373e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie } catch (RemoteException e) { 8383e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie Log.e(TAG, e.toString()); 8393e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie } 8403e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie } else { 8413e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie Log.w(TAG, "Proxy not attached to service"); 8423e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 8433e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie } 8443e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie } 8453e8c82edb1feafc796aa52efafedc13f794c4dcdMatthew Xie 846922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee /** 847922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee * Sends a vendor-specific unsolicited result code to the headset. 848922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee * 849922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee * <p>The actual string to be sent is <code>command + ": " + arg</code>. 850b240578f0333f5b35472cb11d6d7b5bb1da431ccYing Wang * For example, if {@code command} is {@link #VENDOR_RESULT_CODE_COMMAND_ANDROID} and {@code arg} 851922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee * is {@code "0"}, the string <code>"+ANDROID: 0"</code> will be sent. 852922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee * 853b240578f0333f5b35472cb11d6d7b5bb1da431ccYing Wang * <p>Currently only {@link #VENDOR_RESULT_CODE_COMMAND_ANDROID} is allowed as {@code command}. 854922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee * 855922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 856922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee * 857922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee * @param device Bluetooth headset. 858922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee * @param command A vendor-specific command. 859922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee * @param arg The argument that will be attached to the command. 860922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee * @return {@code false} if there is no headset connected, or if the command is not an allowed 861922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee * vendor-specific unsolicited result code, or on error. {@code true} otherwise. 862922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee * @throws IllegalArgumentException if {@code command} is {@code null}. 863922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee */ 864922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee public boolean sendVendorSpecificResultCode(BluetoothDevice device, String command, 865922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee String arg) { 866922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee if (DBG) { 867922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee log("sendVendorSpecificResultCode()"); 868922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee } 869922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee if (command == null) { 870922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee throw new IllegalArgumentException("command is null"); 871922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee } 872922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee if (mService != null && isEnabled() && 873922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee isValidDevice(device)) { 874922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee try { 875922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee return mService.sendVendorSpecificResultCode(device, command, arg); 876922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee } catch (RemoteException e) { 877922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee Log.e(TAG, Log.getStackTraceString(new Throwable())); 878922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee } 879922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee } 880922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee if (mService == null) { 881922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee Log.w(TAG, "Proxy not attached to service"); 882922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee } 883922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee return false; 884922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee } 885922d41b6ef202eac65991d27c43d74c828256f0dEdward Jee 886177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth /** 887177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth * enable WBS codec setting. 888177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth * 889177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth * @return true if successful 890177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth * false if there was some error such as 891177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth * there is no connected headset 892177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth * @hide 893177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth */ 894177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth public boolean enableWBS() { 895177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth if (mService != null && isEnabled()) { 896177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth try { 897177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth return mService.enableWBS(); 898177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth } catch (RemoteException e) { 899177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth Log.e(TAG, e.toString()); 900177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth } 901177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth } else { 902177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth Log.w(TAG, "Proxy not attached to service"); 903177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 904177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth } 905177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth return false; 906177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth } 907177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth 908177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth /** 909177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth * disable WBS codec settting. It set NBS codec. 910177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth * 911177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth * @return true if successful 912177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth * false if there was some error such as 913177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth * there is no connected headset 914177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth * @hide 915177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth */ 916177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth public boolean disableWBS() { 917177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth if (mService != null && isEnabled()) { 918177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth try { 919177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth return mService.disableWBS(); 920177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth } catch (RemoteException e) { 921177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth Log.e(TAG, e.toString()); 922177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth } 923177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth } else { 924177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth Log.w(TAG, "Proxy not attached to service"); 925177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 926177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth } 927177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth return false; 928177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth } 929177d078d90f9659cfc7f091d1fdeb5712b357123Mudumba Ananth 930e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz private final IBluetoothProfileServiceConnection mConnection 931e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz = new IBluetoothProfileServiceConnection.Stub() { 932e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz @Override 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onServiceConnected(ComponentName className, IBinder service) { 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) Log.d(TAG, "Proxy object connected"); 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mService = IBluetoothHeadset.Stub.asInterface(service); 936e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mHandler.sendMessage(mHandler.obtainMessage( 937e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz MESSAGE_HEADSET_SERVICE_CONNECTED)); 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 939e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz @Override 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onServiceDisconnected(ComponentName className) { 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) Log.d(TAG, "Proxy object disconnected"); 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mService = null; 943e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mHandler.sendMessage(mHandler.obtainMessage( 944e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz MESSAGE_HEADSET_SERVICE_DISCONNECTED)); 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 947f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2The Android Open Source Project 94862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh private boolean isEnabled() { 94962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; 95062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 95162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 95262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh 9536f7a9736602ba1f1dc5a16542aa947861a520ec5Jaikumar Ganesh private boolean isDisabled() { 9546f7a9736602ba1f1dc5a16542aa947861a520ec5Jaikumar Ganesh if (mAdapter.getState() == BluetoothAdapter.STATE_OFF) return true; 9556f7a9736602ba1f1dc5a16542aa947861a520ec5Jaikumar Ganesh return false; 9566f7a9736602ba1f1dc5a16542aa947861a520ec5Jaikumar Ganesh } 9576f7a9736602ba1f1dc5a16542aa947861a520ec5Jaikumar Ganesh 95862c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh private boolean isValidDevice(BluetoothDevice device) { 95962c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (device == null) return false; 96062c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh 96162c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; 96262c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh return false; 96362c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh } 96462c37efc9e894809b29a004c142a8e0a6b374db7Jaikumar Ganesh 965f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2The Android Open Source Project private static void log(String msg) { 966f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2The Android Open Source Project Log.d(TAG, msg); 967f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2The Android Open Source Project } 968e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz 969e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz private final Handler mHandler = new Handler(Looper.getMainLooper()) { 970e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz @Override 971e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz public void handleMessage(Message msg) { 972e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz switch (msg.what) { 973e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz case MESSAGE_HEADSET_SERVICE_CONNECTED: { 974e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (mServiceListener != null) { 975e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mServiceListener.onServiceConnected(BluetoothProfile.HEADSET, 976e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz BluetoothHeadset.this); 977e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 978e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz break; 979e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 980e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz case MESSAGE_HEADSET_SERVICE_DISCONNECTED: { 981e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz if (mServiceListener != null) { 982e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz mServiceListener.onServiceDisconnected(BluetoothProfile.HEADSET); 983e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 984e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz break; 985e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 986e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 987e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz } 988e8b98925d08f720c4d22b626d0650de536840a9aBenjamin Franz }; 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 990