/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.bluetooth;

import android.Manifest;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.content.ComponentName;
import android.content.Context;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;

Public API for controlling the Bluetooth Headset Service. This includes both Bluetooth Headset and Handsfree (v1.5) profiles.

BluetoothHeadset is a proxy object for controlling the Bluetooth Headset Service via IPC.

Use BluetoothAdapter.getProfileProxy to get the BluetoothHeadset proxy object. Use BluetoothAdapter.closeProfileProxy to close the service connection.

Android only supports one connected Bluetooth Headset at a time. Each method is protected with its appropriate permission.

/** * Public API for controlling the Bluetooth Headset Service. This includes both * Bluetooth Headset and Handsfree (v1.5) profiles. * * <p>BluetoothHeadset is a proxy object for controlling the Bluetooth Headset * Service via IPC. * * <p> Use {@link BluetoothAdapter#getProfileProxy} to get * the BluetoothHeadset proxy object. Use * {@link BluetoothAdapter#closeProfileProxy} to close the service connection. * * <p> Android only supports one connected Bluetooth Headset at a time. * Each method is protected with its appropriate permission. */
public final class BluetoothHeadset implements BluetoothProfile { private static final String TAG = "BluetoothHeadset"; private static final boolean DBG = true; private static final boolean VDBG = false;
Intent used to broadcast the change in connection state of the Headset profile.

This intent will have 3 extras:

BluetoothProfile.EXTRA_STATE or BluetoothProfile.EXTRA_PREVIOUS_STATE can be any of BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTING.

Requires BLUETOOTH.BLUETOOTH permission to receive.

/** * Intent used to broadcast the change in connection state of the Headset * profile. * * <p>This intent will have 3 extras: * <ul> * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li> * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> * </ul> * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING}, * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to * receive. */
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED";
Intent used to broadcast the change in the Audio Connection state of the A2DP profile.

This intent will have 3 extras:

BluetoothProfile.EXTRA_STATE or BluetoothProfile.EXTRA_PREVIOUS_STATE can be any of STATE_AUDIO_CONNECTED, STATE_AUDIO_DISCONNECTED,

Requires BLUETOOTH.BLUETOOTH permission to receive.

/** * Intent used to broadcast the change in the Audio Connection state of the * A2DP profile. * * <p>This intent will have 3 extras: * <ul> * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li> * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> * </ul> * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of * {@link #STATE_AUDIO_CONNECTED}, {@link #STATE_AUDIO_DISCONNECTED}, * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission * to receive. */
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_AUDIO_STATE_CHANGED = "android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED";
Intent used to broadcast the selection of a connected device as active.

This intent will have one extra:

Requires BLUETOOTH.BLUETOOTH permission to receive.

@hide
/** * Intent used to broadcast the selection of a connected device as active. * * <p>This intent will have one extra: * <ul> * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can * be null if no device is active. </li> * </ul> * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to * receive. * * @hide */
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_ACTIVE_DEVICE_CHANGED = "android.bluetooth.headset.profile.action.ACTIVE_DEVICE_CHANGED";
Intent used to broadcast that the headset has posted a vendor-specific event.

This intent will have 4 extras and 1 category.

The category is the Company ID of the vendor defining the vendor-specific command. BluetoothAssignedNumbers For example, for Plantronics specific events Category will be VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY.55

For example, an AT+XEVENT=foo,3 will get translated into

  • EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD = +XEVENT
  • EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE = AT_CMD_TYPE_SET
  • EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS = foo, 3

Requires BLUETOOTH.BLUETOOTH permission to receive.

/** * Intent used to broadcast that the headset has posted a * vendor-specific event. * * <p>This intent will have 4 extras and 1 category. * <ul> * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote Bluetooth Device * </li> * <li> {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD} - The vendor * specific command </li> * <li> {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE} - The AT * command type which can be one of {@link #AT_CMD_TYPE_READ}, * {@link #AT_CMD_TYPE_TEST}, or {@link #AT_CMD_TYPE_SET}, * {@link #AT_CMD_TYPE_BASIC},{@link #AT_CMD_TYPE_ACTION}. </li> * <li> {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS} - Command * arguments. </li> * </ul> * * <p> The category is the Company ID of the vendor defining the * vendor-specific command. {@link BluetoothAssignedNumbers} * * For example, for Plantronics specific events * Category will be {@link #VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY}.55 * * <p> For example, an AT+XEVENT=foo,3 will get translated into * <ul> * <li> EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD = +XEVENT </li> * <li> EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE = AT_CMD_TYPE_SET </li> * <li> EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS = foo, 3 </li> * </ul> * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission * to receive. */
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_VENDOR_SPECIFIC_HEADSET_EVENT = "android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT";
A String extra field in ACTION_VENDOR_SPECIFIC_HEADSET_EVENT intents that contains the name of the vendor-specific command.
/** * A String extra field in {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT} * intents that contains the name of the vendor-specific command. */
public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD = "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_CMD";
An int extra field in ACTION_VENDOR_SPECIFIC_HEADSET_EVENT intents that contains the AT command type of the vendor-specific command.
/** * An int extra field in {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT} * intents that contains the AT command type of the vendor-specific command. */
public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE = "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE";
AT command type READ used with EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE For example, AT+VGM?. There are no arguments for this command type.
/** * AT command type READ used with * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE} * For example, AT+VGM?. There are no arguments for this command type. */
public static final int AT_CMD_TYPE_READ = 0;
AT command type TEST used with EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE For example, AT+VGM=?. There are no arguments for this command type.
/** * AT command type TEST used with * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE} * For example, AT+VGM=?. There are no arguments for this command type. */
public static final int AT_CMD_TYPE_TEST = 1;
AT command type SET used with EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE For example, AT+VGM=.
/** * AT command type SET used with * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE} * For example, AT+VGM=<args>. */
public static final int AT_CMD_TYPE_SET = 2;
AT command type BASIC used with EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE For example, ATD. Single character commands and everything following the character are arguments.
/** * AT command type BASIC used with * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE} * For example, ATD. Single character commands and everything following the * character are arguments. */
public static final int AT_CMD_TYPE_BASIC = 3;
AT command type ACTION used with EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE For example, AT+CHUP. There are no arguments for action commands.
/** * AT command type ACTION used with * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE} * For example, AT+CHUP. There are no arguments for action commands. */
public static final int AT_CMD_TYPE_ACTION = 4;
A Parcelable String array extra field in ACTION_VENDOR_SPECIFIC_HEADSET_EVENT intents that contains the arguments to the vendor-specific command.
/** * A Parcelable String array extra field in * {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT} intents that contains * the arguments to the vendor-specific command. */
public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS = "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_ARGS";
The intent category to be used with ACTION_VENDOR_SPECIFIC_HEADSET_EVENT for the companyId
/** * The intent category to be used with {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT} * for the companyId */
public static final String VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY = "android.bluetooth.headset.intent.category.companyid";
A vendor-specific command for unsolicited result code.
/** * A vendor-specific command for unsolicited result code. */
public static final String VENDOR_RESULT_CODE_COMMAND_ANDROID = "+ANDROID";
A vendor-specific AT command
@hide
/** * A vendor-specific AT command * * @hide */
public static final String VENDOR_SPECIFIC_HEADSET_EVENT_XAPL = "+XAPL";
A vendor-specific AT command
@hide
/** * A vendor-specific AT command * * @hide */
public static final String VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV = "+IPHONEACCEV";
Battery level indicator associated with VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV
@hide
/** * Battery level indicator associated with * {@link #VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV} * * @hide */
public static final int VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV_BATTERY_LEVEL = 1;
A vendor-specific AT command
@hide
/** * A vendor-specific AT command * * @hide */
public static final String VENDOR_SPECIFIC_HEADSET_EVENT_XEVENT = "+XEVENT";
Battery level indicator associated with VENDOR_SPECIFIC_HEADSET_EVENT_XEVENT
@hide
/** * Battery level indicator associated with {@link #VENDOR_SPECIFIC_HEADSET_EVENT_XEVENT} * * @hide */
public static final String VENDOR_SPECIFIC_HEADSET_EVENT_XEVENT_BATTERY_LEVEL = "BATTERY";
Headset state when SCO audio is not connected. This state can be one of BluetoothProfile.EXTRA_STATE or BluetoothProfile.EXTRA_PREVIOUS_STATE of ACTION_AUDIO_STATE_CHANGED intent.
/** * Headset state when SCO audio is not connected. * This state can be one of * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of * {@link #ACTION_AUDIO_STATE_CHANGED} intent. */
public static final int STATE_AUDIO_DISCONNECTED = 10;
Headset state when SCO audio is connecting. This state can be one of BluetoothProfile.EXTRA_STATE or BluetoothProfile.EXTRA_PREVIOUS_STATE of ACTION_AUDIO_STATE_CHANGED intent.
/** * Headset state when SCO audio is connecting. * This state can be one of * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of * {@link #ACTION_AUDIO_STATE_CHANGED} intent. */
public static final int STATE_AUDIO_CONNECTING = 11; /** * Headset state when SCO audio is connected. * This state can be one of * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of * {@link #ACTION_AUDIO_STATE_CHANGED} intent. */
Intent used to broadcast the headset's indicator status

This intent will have 3 extras:

EXTRA_HF_INDICATORS_IND_ID is defined by Bluetooth SIG and each of the indicators are given an assigned number. Below shows the assigned number of Indicator added so far - Enhanced Safety - 1, Valid Values: 0 - Disabled, 1 - Enabled - Battery Level - 2, Valid Values: 0~100 - Remaining level of Battery

Requires BLUETOOTH.BLUETOOTH permission to receive.

@hide
/** * Intent used to broadcast the headset's indicator status * * <p>This intent will have 3 extras: * <ul> * <li> {@link #EXTRA_HF_INDICATORS_IND_ID} - The Assigned number of headset Indicator which * is supported by the headset ( as indicated by AT+BIND command in the SLC * sequence) or whose value is changed (indicated by AT+BIEV command) </li> * <li> {@link #EXTRA_HF_INDICATORS_IND_VALUE} - Updated value of headset indicator. </li> * <li> {@link BluetoothDevice#EXTRA_DEVICE} - Remote device. </li> * </ul> * <p>{@link #EXTRA_HF_INDICATORS_IND_ID} is defined by Bluetooth SIG and each of the indicators * are given an assigned number. Below shows the assigned number of Indicator added so far * - Enhanced Safety - 1, Valid Values: 0 - Disabled, 1 - Enabled * - Battery Level - 2, Valid Values: 0~100 - Remaining level of Battery * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to receive. * * @hide */
public static final String ACTION_HF_INDICATORS_VALUE_CHANGED = "android.bluetooth.headset.action.HF_INDICATORS_VALUE_CHANGED";
A int extra field in ACTION_HF_INDICATORS_VALUE_CHANGED intents that contains the assigned number of the headset indicator as defined by Bluetooth SIG that is being sent. Value range is 0-65535 as defined in HFP 1.7
@hide
/** * A int extra field in {@link #ACTION_HF_INDICATORS_VALUE_CHANGED} * intents that contains the assigned number of the headset indicator as defined by * Bluetooth SIG that is being sent. Value range is 0-65535 as defined in HFP 1.7 * * @hide */
public static final String EXTRA_HF_INDICATORS_IND_ID = "android.bluetooth.headset.extra.HF_INDICATORS_IND_ID";
A int extra field in ACTION_HF_INDICATORS_VALUE_CHANGED intents that contains the value of the Headset indicator that is being sent.
@hide
/** * A int extra field in {@link #ACTION_HF_INDICATORS_VALUE_CHANGED} * intents that contains the value of the Headset indicator that is being sent. * * @hide */
public static final String EXTRA_HF_INDICATORS_IND_VALUE = "android.bluetooth.headset.extra.HF_INDICATORS_IND_VALUE"; public static final int STATE_AUDIO_CONNECTED = 12; private static final int MESSAGE_HEADSET_SERVICE_CONNECTED = 100; private static final int MESSAGE_HEADSET_SERVICE_DISCONNECTED = 101; private Context mContext; private ServiceListener mServiceListener; private volatile IBluetoothHeadset mService; private BluetoothAdapter mAdapter; private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { public void onBluetoothStateChange(boolean up) { if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); if (!up) { if (VDBG) Log.d(TAG, "Unbinding service..."); doUnbind(); } else { synchronized (mConnection) { try { if (mService == null) { if (VDBG) Log.d(TAG, "Binding service..."); doBind(); } } catch (Exception re) { Log.e(TAG, "", re); } } } } };
Create a BluetoothHeadset proxy object.
/** * Create a BluetoothHeadset proxy object. */
/*package*/ BluetoothHeadset(Context context, ServiceListener l) { mContext = context; mServiceListener = l; mAdapter = BluetoothAdapter.getDefaultAdapter(); IBluetoothManager mgr = mAdapter.getBluetoothManager(); if (mgr != null) { try { mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); } catch (RemoteException e) { Log.e(TAG, "", e); } } doBind(); } boolean doBind() { try { return mAdapter.getBluetoothManager().bindBluetoothProfileService( BluetoothProfile.HEADSET, mConnection); } catch (RemoteException e) { Log.e(TAG, "Unable to bind HeadsetService", e); } return false; } void doUnbind() { synchronized (mConnection) { if (mService != null) { try { mAdapter.getBluetoothManager().unbindBluetoothProfileService( BluetoothProfile.HEADSET, mConnection); } catch (RemoteException e) { Log.e(TAG, "Unable to unbind HeadsetService", e); } } } }
Close the connection to the backing service. Other public functions of BluetoothHeadset will return default error results once close() has been called. Multiple invocations of close() are ok.
/** * Close the connection to the backing service. * Other public functions of BluetoothHeadset will return default error * results once close() has been called. Multiple invocations of close() * are ok. */
/*package*/ void close() { if (VDBG) log("close()"); IBluetoothManager mgr = mAdapter.getBluetoothManager(); if (mgr != null) { try { mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); } catch (Exception e) { Log.e(TAG, "", e); } } mServiceListener = null; doUnbind(); }
Initiate connection to a profile of the remote bluetooth device.

Currently, the system supports only 1 connection to the headset/handsfree profile. The API will automatically disconnect connected devices before connecting.

This API returns false in scenarios like the profile on the device is already connected or Bluetooth is not turned on. When this API returns true, it is guaranteed that connection state intent for the profile will be broadcasted with the state. Users can get the connection state of the profile from this intent.

Requires BLUETOOTH_ADMIN.BLUETOOTH_ADMIN permission.

Params:
  • device – Remote Bluetooth Device
Returns:false on immediate error, true otherwise
@hide
/** * Initiate connection to a profile of the remote bluetooth device. * * <p> Currently, the system supports only 1 connection to the * headset/handsfree profile. The API will automatically disconnect connected * devices before connecting. * * <p> This API returns false in scenarios like the profile on the * device is already connected or Bluetooth is not turned on. * When this API returns true, it is guaranteed that * connection state intent for the profile will be broadcasted with * the state. Users can get the connection state of the profile * from this intent. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} * permission. * * @param device Remote Bluetooth Device * @return false on immediate error, true otherwise * @hide */
@SystemApi @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); final IBluetoothHeadset service = mService; if (service != null && isEnabled() && isValidDevice(device)) { try { return service.connect(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return false; } } if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; }
Initiate disconnection from a profile

This API will return false in scenarios like the profile on the Bluetooth device is not in connected state etc. When this API returns, true, it is guaranteed that the connection state change intent will be broadcasted with the state. Users can get the disconnection state of the profile from this intent.

If the disconnection is initiated by a remote device, the state will transition from BluetoothProfile.STATE_CONNECTED to BluetoothProfile.STATE_DISCONNECTED. If the disconnect is initiated by the host (local) device the state will transition from BluetoothProfile.STATE_CONNECTED to state BluetoothProfile.STATE_DISCONNECTING to state BluetoothProfile.STATE_DISCONNECTED. The transition to BluetoothProfile.STATE_DISCONNECTING can be used to distinguish between the two scenarios.

Requires BLUETOOTH_ADMIN.BLUETOOTH_ADMIN permission.

Params:
  • device – Remote Bluetooth Device
Returns:false on immediate error, true otherwise
@hide
/** * Initiate disconnection from a profile * * <p> This API will return false in scenarios like the profile on the * Bluetooth device is not in connected state etc. When this API returns, * true, it is guaranteed that the connection state change * intent will be broadcasted with the state. Users can get the * disconnection state of the profile from this intent. * * <p> If the disconnection is initiated by a remote device, the state * will transition from {@link #STATE_CONNECTED} to * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the * host (local) device the state will transition from * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to * state {@link #STATE_DISCONNECTED}. The transition to * {@link #STATE_DISCONNECTING} can be used to distinguish between the * two scenarios. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} * permission. * * @param device Remote Bluetooth Device * @return false on immediate error, true otherwise * @hide */
@SystemApi @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); final IBluetoothHeadset service = mService; if (service != null && isEnabled() && isValidDevice(device)) { try { return service.disconnect(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return false; } } if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public List<BluetoothDevice> getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); final IBluetoothHeadset service = mService; if (service != null && isEnabled()) { try { return service.getConnectedDevices(); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { if (VDBG) log("getDevicesMatchingStates()"); final IBluetoothHeadset service = mService; if (service != null && isEnabled()) { try { return service.getDevicesMatchingConnectionStates(states); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public int getConnectionState(BluetoothDevice device) { if (VDBG) log("getConnectionState(" + device + ")"); final IBluetoothHeadset service = mService; if (service != null && isEnabled() && isValidDevice(device)) { try { return service.getConnectionState(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return BluetoothProfile.STATE_DISCONNECTED; } } if (service == null) Log.w(TAG, "Proxy not attached to service"); return BluetoothProfile.STATE_DISCONNECTED; }
Set priority of the profile

The device should already be paired. Priority can be one of BluetoothProfile.PRIORITY_ON or BluetoothProfile.PRIORITY_OFF,

Requires BLUETOOTH_ADMIN.BLUETOOTH_ADMIN permission.

Params:
  • device – Paired bluetooth device
  • priority –
Returns:true if priority is set, false on error
@hide
/** * Set priority of the profile * * <p> The device should already be paired. * Priority can be one of {@link BluetoothProfile#PRIORITY_ON} or * {@link BluetoothProfile#PRIORITY_OFF}, * * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} * permission. * * @param device Paired bluetooth device * @param priority * @return true if priority is set, false on error * @hide */
@SystemApi @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setPriority(BluetoothDevice device, int priority) { if (DBG) log("setPriority(" + device + ", " + priority + ")"); final IBluetoothHeadset service = mService; if (service != null && isEnabled() && isValidDevice(device)) { if (priority != BluetoothProfile.PRIORITY_OFF && priority != BluetoothProfile.PRIORITY_ON) { return false; } try { return service.setPriority(device, priority); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return false; } } if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; }
Get the priority of the profile.

The priority can be any of: BluetoothProfile.PRIORITY_AUTO_CONNECT, BluetoothProfile.PRIORITY_OFF, BluetoothProfile.PRIORITY_ON, BluetoothProfile.PRIORITY_UNDEFINED

Requires BLUETOOTH.BLUETOOTH permission.

Params:
  • device – Bluetooth device
Returns:priority of the device
@hide
/** * Get the priority of the profile. * * <p> The priority can be any of: * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF}, * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED} * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param device Bluetooth device * @return priority of the device * @hide */
public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); final IBluetoothHeadset service = mService; if (service != null && isEnabled() && isValidDevice(device)) { try { return service.getPriority(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return PRIORITY_OFF; } } if (service == null) Log.w(TAG, "Proxy not attached to service"); return PRIORITY_OFF; }
Start Bluetooth voice recognition. This methods sends the voice recognition AT command to the headset and establishes the audio connection.

Users can listen to ACTION_AUDIO_STATE_CHANGED. If this function returns true, this intent will be broadcasted with BluetoothProfile.EXTRA_STATE set to STATE_AUDIO_CONNECTING.

BluetoothProfile.EXTRA_STATE will transition from STATE_AUDIO_CONNECTING to STATE_AUDIO_CONNECTED when audio connection is established and to STATE_AUDIO_DISCONNECTED in case of failure to establish the audio connection.

Requires BLUETOOTH.BLUETOOTH permission.

Params:
  • device – Bluetooth headset
Returns:false if there is no headset connected, or the connected headset doesn't support voice recognition, or voice recognition is already started, or audio channel is occupied, or on error, true otherwise
/** * Start Bluetooth voice recognition. This methods sends the voice * recognition AT command to the headset and establishes the * audio connection. * * <p> Users can listen to {@link #ACTION_AUDIO_STATE_CHANGED}. * If this function returns true, this intent will be broadcasted with * {@link #EXTRA_STATE} set to {@link #STATE_AUDIO_CONNECTING}. * * <p> {@link #EXTRA_STATE} will transition from * {@link #STATE_AUDIO_CONNECTING} to {@link #STATE_AUDIO_CONNECTED} when * audio connection is established and to {@link #STATE_AUDIO_DISCONNECTED} * in case of failure to establish the audio connection. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param device Bluetooth headset * @return false if there is no headset connected, or the connected headset doesn't support * voice recognition, or voice recognition is already started, or audio channel is occupied, * or on error, true otherwise */
public boolean startVoiceRecognition(BluetoothDevice device) { if (DBG) log("startVoiceRecognition()"); final IBluetoothHeadset service = mService; if (service != null && isEnabled() && isValidDevice(device)) { try { return service.startVoiceRecognition(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; }
Stop Bluetooth Voice Recognition mode, and shut down the Bluetooth audio path.

Users can listen to ACTION_AUDIO_STATE_CHANGED. If this function returns true, this intent will be broadcasted with BluetoothProfile.EXTRA_STATE set to STATE_AUDIO_DISCONNECTED.

Requires BLUETOOTH.BLUETOOTH permission.

Params:
  • device – Bluetooth headset
Returns:false if there is no headset connected, or voice recognition has not started, or voice recognition has ended on this headset, or on error, true otherwise
/** * Stop Bluetooth Voice Recognition mode, and shut down the * Bluetooth audio path. * * <p> Users can listen to {@link #ACTION_AUDIO_STATE_CHANGED}. * If this function returns true, this intent will be broadcasted with * {@link #EXTRA_STATE} set to {@link #STATE_AUDIO_DISCONNECTED}. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param device Bluetooth headset * @return false if there is no headset connected, or voice recognition has not started, * or voice recognition has ended on this headset, or on error, true otherwise */
public boolean stopVoiceRecognition(BluetoothDevice device) { if (DBG) log("stopVoiceRecognition()"); final IBluetoothHeadset service = mService; if (service != null && isEnabled() && isValidDevice(device)) { try { return service.stopVoiceRecognition(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; }
Check if Bluetooth SCO audio is connected.

Requires BLUETOOTH.BLUETOOTH permission.

Params:
  • device – Bluetooth headset
Returns:true if SCO is connected, false otherwise or on error
/** * Check if Bluetooth SCO audio is connected. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param device Bluetooth headset * @return true if SCO is connected, false otherwise or on error */
public boolean isAudioConnected(BluetoothDevice device) { if (VDBG) log("isAudioConnected()"); final IBluetoothHeadset service = mService; if (service != null && isEnabled() && isValidDevice(device)) { try { return service.isAudioConnected(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; }
Indicates if current platform supports voice dialing over bluetooth SCO.
Returns:true if voice dialing over bluetooth is supported, false otherwise.
@hide
/** * Indicates if current platform supports voice dialing over bluetooth SCO. * * @return true if voice dialing over bluetooth is supported, false otherwise. * @hide */
public static boolean isBluetoothVoiceDialingEnabled(Context context) { return context.getResources().getBoolean( com.android.internal.R.bool.config_bluetooth_sco_off_call); }
Get the current audio state of the Headset. Note: This is an internal function and shouldn't be exposed
@hide
/** * Get the current audio state of the Headset. * Note: This is an internal function and shouldn't be exposed * * @hide */
public int getAudioState(BluetoothDevice device) { if (VDBG) log("getAudioState"); final IBluetoothHeadset service = mService; if (service != null && !isDisabled()) { try { return service.getAudioState(device); } catch (RemoteException e) { Log.e(TAG, e.toString()); } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } return BluetoothHeadset.STATE_AUDIO_DISCONNECTED; }
Sets whether audio routing is allowed. When set to false, the AG will not route any audio to the HF unless explicitly told to. This method should be used in cases where the SCO channel is shared between multiple profiles and must be delegated by a source knowledgeable Note: This is an internal function and shouldn't be exposed
Params:
  • allowed – true if the profile can reroute audio, false otherwise.
@hide
/** * Sets whether audio routing is allowed. When set to {@code false}, the AG will not route any * audio to the HF unless explicitly told to. * This method should be used in cases where the SCO channel is shared between multiple profiles * and must be delegated by a source knowledgeable * Note: This is an internal function and shouldn't be exposed * * @param allowed {@code true} if the profile can reroute audio, {@code false} otherwise. * @hide */
public void setAudioRouteAllowed(boolean allowed) { if (VDBG) log("setAudioRouteAllowed"); final IBluetoothHeadset service = mService; if (service != null && isEnabled()) { try { service.setAudioRouteAllowed(allowed); } catch (RemoteException e) { Log.e(TAG, e.toString()); } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } }
Returns whether audio routing is allowed. see setAudioRouteAllowed(boolean). Note: This is an internal function and shouldn't be exposed
@hide
/** * Returns whether audio routing is allowed. see {@link #setAudioRouteAllowed(boolean)}. * Note: This is an internal function and shouldn't be exposed * * @hide */
public boolean getAudioRouteAllowed() { if (VDBG) log("getAudioRouteAllowed"); final IBluetoothHeadset service = mService; if (service != null && isEnabled()) { try { return service.getAudioRouteAllowed(); } catch (RemoteException e) { Log.e(TAG, e.toString()); } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } return false; }
Force SCO audio to be opened regardless any other restrictions
Params:
  • forced – Whether or not SCO audio connection should be forced: True to force SCO audio False to use SCO audio in normal manner
@hide
/** * Force SCO audio to be opened regardless any other restrictions * * @param forced Whether or not SCO audio connection should be forced: True to force SCO audio * False to use SCO audio in normal manner * @hide */
public void setForceScoAudio(boolean forced) { if (VDBG) log("setForceScoAudio " + String.valueOf(forced)); final IBluetoothHeadset service = mService; if (service != null && isEnabled()) { try { service.setForceScoAudio(forced); } catch (RemoteException e) { Log.e(TAG, e.toString()); } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } }
Check if at least one headset's SCO audio is connected or connecting

Requires BLUETOOTH.BLUETOOTH permission.

Returns:true if at least one device's SCO audio is connected or connecting, false otherwise or on error
@hide
/** * Check if at least one headset's SCO audio is connected or connecting * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @return true if at least one device's SCO audio is connected or connecting, false otherwise * or on error * @hide */
public boolean isAudioOn() { if (VDBG) log("isAudioOn()"); final IBluetoothHeadset service = mService; if (service != null && isEnabled()) { try { return service.isAudioOn(); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; }
Initiates a connection of headset audio to the current active device

Users can listen to ACTION_AUDIO_STATE_CHANGED. If this function returns true, this intent will be broadcasted with BluetoothProfile.EXTRA_STATE set to STATE_AUDIO_CONNECTING.

BluetoothProfile.EXTRA_STATE will transition from STATE_AUDIO_CONNECTING to STATE_AUDIO_CONNECTED when audio connection is established and to STATE_AUDIO_DISCONNECTED in case of failure to establish the audio connection. Note that this intent will not be sent if isAudioOn() is true before calling this method

Returns:false if there was some error such as there is no active headset
@hide
/** * Initiates a connection of headset audio to the current active device * * <p> Users can listen to {@link #ACTION_AUDIO_STATE_CHANGED}. * If this function returns true, this intent will be broadcasted with * {@link #EXTRA_STATE} set to {@link #STATE_AUDIO_CONNECTING}. * * <p> {@link #EXTRA_STATE} will transition from * {@link #STATE_AUDIO_CONNECTING} to {@link #STATE_AUDIO_CONNECTED} when * audio connection is established and to {@link #STATE_AUDIO_DISCONNECTED} * in case of failure to establish the audio connection. * * Note that this intent will not be sent if {@link BluetoothHeadset#isAudioOn()} is true * before calling this method * * @return false if there was some error such as there is no active headset * @hide */
public boolean connectAudio() { final IBluetoothHeadset service = mService; if (service != null && isEnabled()) { try { return service.connectAudio(); } catch (RemoteException e) { Log.e(TAG, e.toString()); } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } return false; }
Initiates a disconnection of HFP SCO audio. Tear down voice recognition or virtual voice call if any.

Users can listen to ACTION_AUDIO_STATE_CHANGED. If this function returns true, this intent will be broadcasted with BluetoothProfile.EXTRA_STATE set to STATE_AUDIO_DISCONNECTED.

Returns:false if audio is not connected, or on error, true otherwise
@hide
/** * Initiates a disconnection of HFP SCO audio. * Tear down voice recognition or virtual voice call if any. * * <p> Users can listen to {@link #ACTION_AUDIO_STATE_CHANGED}. * If this function returns true, this intent will be broadcasted with * {@link #EXTRA_STATE} set to {@link #STATE_AUDIO_DISCONNECTED}. * * @return false if audio is not connected, or on error, true otherwise * @hide */
public boolean disconnectAudio() { final IBluetoothHeadset service = mService; if (service != null && isEnabled()) { try { return service.disconnectAudio(); } catch (RemoteException e) { Log.e(TAG, e.toString()); } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } return false; }
Initiates a SCO channel connection as a virtual voice call to the current active device Active handsfree device will be notified of incoming call and connected call.

Users can listen to ACTION_AUDIO_STATE_CHANGED. If this function returns true, this intent will be broadcasted with BluetoothProfile.EXTRA_STATE set to STATE_AUDIO_CONNECTING.

BluetoothProfile.EXTRA_STATE will transition from STATE_AUDIO_CONNECTING to STATE_AUDIO_CONNECTED when audio connection is established and to STATE_AUDIO_DISCONNECTED in case of failure to establish the audio connection.

Returns:true if successful, false if one of the following case applies - SCO audio is not idle (connecting or connected) - virtual call has already started - there is no active device - a Telecom managed call is going on - binder is dead or Bluetooth is disabled or other error
@hide
/** * Initiates a SCO channel connection as a virtual voice call to the current active device * Active handsfree device will be notified of incoming call and connected call. * * <p> Users can listen to {@link #ACTION_AUDIO_STATE_CHANGED}. * If this function returns true, this intent will be broadcasted with * {@link #EXTRA_STATE} set to {@link #STATE_AUDIO_CONNECTING}. * * <p> {@link #EXTRA_STATE} will transition from * {@link #STATE_AUDIO_CONNECTING} to {@link #STATE_AUDIO_CONNECTED} when * audio connection is established and to {@link #STATE_AUDIO_DISCONNECTED} * in case of failure to establish the audio connection. * * @return true if successful, false if one of the following case applies * - SCO audio is not idle (connecting or connected) * - virtual call has already started * - there is no active device * - a Telecom managed call is going on * - binder is dead or Bluetooth is disabled or other error * @hide */
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) public boolean startScoUsingVirtualVoiceCall() { if (DBG) log("startScoUsingVirtualVoiceCall()"); final IBluetoothHeadset service = mService; if (service != null && isEnabled()) { try { return service.startScoUsingVirtualVoiceCall(); } catch (RemoteException e) { Log.e(TAG, e.toString()); } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } return false; }
Terminates an ongoing SCO connection and the associated virtual call.

Users can listen to ACTION_AUDIO_STATE_CHANGED. If this function returns true, this intent will be broadcasted with BluetoothProfile.EXTRA_STATE set to STATE_AUDIO_DISCONNECTED.

Returns:true if successful, false if one of the following case applies - virtual voice call is not started or has ended - binder is dead or Bluetooth is disabled or other error
@hide
/** * Terminates an ongoing SCO connection and the associated virtual call. * * <p> Users can listen to {@link #ACTION_AUDIO_STATE_CHANGED}. * If this function returns true, this intent will be broadcasted with * {@link #EXTRA_STATE} set to {@link #STATE_AUDIO_DISCONNECTED}. * * @return true if successful, false if one of the following case applies * - virtual voice call is not started or has ended * - binder is dead or Bluetooth is disabled or other error * @hide */
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) public boolean stopScoUsingVirtualVoiceCall() { if (DBG) log("stopScoUsingVirtualVoiceCall()"); final IBluetoothHeadset service = mService; if (service != null && isEnabled()) { try { return service.stopScoUsingVirtualVoiceCall(); } catch (RemoteException e) { Log.e(TAG, e.toString()); } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } return false; }
Notify Headset of phone state change. This is a backdoor for phone app to call BluetoothHeadset since there is currently not a good way to get precise call state change outside of phone app.
@hide
/** * Notify Headset of phone state change. * This is a backdoor for phone app to call BluetoothHeadset since * there is currently not a good way to get precise call state change outside * of phone app. * * @hide */
public void phoneStateChanged(int numActive, int numHeld, int callState, String number, int type) { final IBluetoothHeadset service = mService; if (service != null && isEnabled()) { try { service.phoneStateChanged(numActive, numHeld, callState, number, type); } catch (RemoteException e) { Log.e(TAG, e.toString()); } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } }
Send Headset of CLCC response
@hide
/** * Send Headset of CLCC response * * @hide */
public void clccResponse(int index, int direction, int status, int mode, boolean mpty, String number, int type) { final IBluetoothHeadset service = mService; if (service != null && isEnabled()) { try { service.clccResponse(index, direction, status, mode, mpty, number, type); } catch (RemoteException e) { Log.e(TAG, e.toString()); } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } }
Sends a vendor-specific unsolicited result code to the headset.

The actual string to be sent is command + ": " + arg. For example, if command is VENDOR_RESULT_CODE_COMMAND_ANDROID and arg is "0", the string "+ANDROID: 0" will be sent.

Currently only VENDOR_RESULT_CODE_COMMAND_ANDROID is allowed as command.

Requires BLUETOOTH.BLUETOOTH permission.

Params:
  • device – Bluetooth headset.
  • command – A vendor-specific command.
  • arg – The argument that will be attached to the command.
Throws:
Returns:false if there is no headset connected, or if the command is not an allowed vendor-specific unsolicited result code, or on error. true otherwise.
/** * Sends a vendor-specific unsolicited result code to the headset. * * <p>The actual string to be sent is <code>command + ": " + arg</code>. For example, if {@code * command} is {@link #VENDOR_RESULT_CODE_COMMAND_ANDROID} and {@code arg} is {@code "0"}, the * string <code>"+ANDROID: 0"</code> will be sent. * * <p>Currently only {@link #VENDOR_RESULT_CODE_COMMAND_ANDROID} is allowed as {@code command}. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param device Bluetooth headset. * @param command A vendor-specific command. * @param arg The argument that will be attached to the command. * @return {@code false} if there is no headset connected, or if the command is not an allowed * vendor-specific unsolicited result code, or on error. {@code true} otherwise. * @throws IllegalArgumentException if {@code command} is {@code null}. */
public boolean sendVendorSpecificResultCode(BluetoothDevice device, String command, String arg) { if (DBG) { log("sendVendorSpecificResultCode()"); } if (command == null) { throw new IllegalArgumentException("command is null"); } final IBluetoothHeadset service = mService; if (service != null && isEnabled() && isValidDevice(device)) { try { return service.sendVendorSpecificResultCode(device, command, arg); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (service == null) { Log.w(TAG, "Proxy not attached to service"); } return false; }
Select a connected device as active. The active device selection is per profile. An active device's purpose is profile-specific. For example, in HFP and HSP profiles, it is the device used for phone call audio. If a remote device is not connected, it cannot be selected as active.

This API returns false in scenarios like the profile on the device is not connected or Bluetooth is not turned on. When this API returns true, it is guaranteed that the ACTION_ACTIVE_DEVICE_CHANGED intent will be broadcasted with the active device.

Requires BLUETOOTH_ADMIN.BLUETOOTH_ADMIN permission.

Params:
  • device – Remote Bluetooth Device, could be null if phone call audio should not be streamed to a headset
Returns:false on immediate error, true otherwise
@hide
/** * Select a connected device as active. * * The active device selection is per profile. An active device's * purpose is profile-specific. For example, in HFP and HSP profiles, * it is the device used for phone call audio. If a remote device is not * connected, it cannot be selected as active. * * <p> This API returns false in scenarios like the profile on the * device is not connected or Bluetooth is not turned on. * When this API returns true, it is guaranteed that the * {@link #ACTION_ACTIVE_DEVICE_CHANGED} intent will be broadcasted * with the active device. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} * permission. * * @param device Remote Bluetooth Device, could be null if phone call audio should not be * streamed to a headset * @return false on immediate error, true otherwise * @hide */
@RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setActiveDevice(@Nullable BluetoothDevice device) { if (DBG) { Log.d(TAG, "setActiveDevice: " + device); } final IBluetoothHeadset service = mService; if (service != null && isEnabled() && (device == null || isValidDevice(device))) { try { return service.setActiveDevice(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (service == null) { Log.w(TAG, "Proxy not attached to service"); } return false; }
Get the connected device that is active.

Requires BLUETOOTH.BLUETOOTH permission.

Returns:the connected device that is active or null if no device is active.
@hide
/** * Get the connected device that is active. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} * permission. * * @return the connected device that is active or null if no device * is active. * @hide */
@RequiresPermission(android.Manifest.permission.BLUETOOTH) public BluetoothDevice getActiveDevice() { if (VDBG) { Log.d(TAG, "getActiveDevice"); } final IBluetoothHeadset service = mService; if (service != null && isEnabled()) { try { return service.getActiveDevice(); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (service == null) { Log.w(TAG, "Proxy not attached to service"); } return null; }
Check if in-band ringing is currently enabled. In-band ringing could be disabled during an active connection.
Returns:true if in-band ringing is enabled, false if in-band ringing is disabled
@hide
/** * Check if in-band ringing is currently enabled. In-band ringing could be disabled during an * active connection. * * @return true if in-band ringing is enabled, false if in-band ringing is disabled * @hide */
@RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean isInbandRingingEnabled() { if (DBG) { log("isInbandRingingEnabled()"); } final IBluetoothHeadset service = mService; if (service != null && isEnabled()) { try { return service.isInbandRingingEnabled(); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (service == null) { Log.w(TAG, "Proxy not attached to service"); } return false; }
Check if in-band ringing is supported for this platform.
Returns:true if in-band ringing is supported, false if in-band ringing is not supported
@hide
/** * Check if in-band ringing is supported for this platform. * * @return true if in-band ringing is supported, false if in-band ringing is not supported * @hide */
public static boolean isInbandRingingSupported(Context context) { return context.getResources().getBoolean( com.android.internal.R.bool.config_bluetooth_hfp_inband_ringing_support); } private final IBluetoothProfileServiceConnection mConnection = new IBluetoothProfileServiceConnection.Stub() { @Override public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) Log.d(TAG, "Proxy object connected"); mService = IBluetoothHeadset.Stub.asInterface(Binder.allowBlocking(service)); mHandler.sendMessage(mHandler.obtainMessage( MESSAGE_HEADSET_SERVICE_CONNECTED)); } @Override public void onServiceDisconnected(ComponentName className) { if (DBG) Log.d(TAG, "Proxy object disconnected"); mService = null; mHandler.sendMessage(mHandler.obtainMessage( MESSAGE_HEADSET_SERVICE_DISCONNECTED)); } }; private boolean isEnabled() { return mAdapter.getState() == BluetoothAdapter.STATE_ON; } private boolean isDisabled() { return mAdapter.getState() == BluetoothAdapter.STATE_OFF; } private static boolean isValidDevice(BluetoothDevice device) { return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress()); } private static void log(String msg) { Log.d(TAG, msg); } private final Handler mHandler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { switch (msg.what) { case MESSAGE_HEADSET_SERVICE_CONNECTED: { if (mServiceListener != null) { mServiceListener.onServiceConnected(BluetoothProfile.HEADSET, BluetoothHeadset.this); } break; } case MESSAGE_HEADSET_SERVICE_DISCONNECTED: { if (mServiceListener != null) { mServiceListener.onServiceDisconnected(BluetoothProfile.HEADSET); } break; } } } }; }