Loading framework/java/android/bluetooth/BluetoothAdapter.java +9 −8 Original line number Diff line number Diff line Loading @@ -2249,17 +2249,17 @@ public final class BluetoothAdapter { /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(value = { BluetoothStatusCodes.SUCCESS, BluetoothStatusCodes.FEATURE_SUPPORTED, BluetoothStatusCodes.ERROR_UNKNOWN, BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED, BluetoothStatusCodes.ERROR_FEATURE_NOT_SUPPORTED, BluetoothStatusCodes.FEATURE_NOT_SUPPORTED, }) public @interface LeFeatureReturnValues {} /** * Returns {@link BluetoothStatusCodes#SUCCESS} if the LE audio feature is * supported, returns {@link BluetoothStatusCodes#ERROR_FEATURE_NOT_SUPPORTED} if * the feature is not supported or an error code. * Returns {@link BluetoothStatusCodes#FEATURE_SUPPORTED} if the LE audio feature is * supported, {@link BluetoothStatusCodes#FEATURE_NOT_SUPPORTED} if the feature is not * supported, or an error code. * * @return whether the LE audio is supported */ Loading @@ -2282,9 +2282,10 @@ public final class BluetoothAdapter { } /** * Returns {@link BluetoothStatusCodes#SUCCESS} if LE Periodic Advertising Sync Transfer Sender * feature is supported, returns {@link BluetoothStatusCodes#ERROR_FEATURE_NOT_SUPPORTED} if the * feature is not supported or an error code * Returns {@link BluetoothStatusCodes#FEATURE_SUPPORTED} if LE Periodic Advertising Sync * Transfer Sender feature is supported, * {@link BluetoothStatusCodes#FEATURE_NOT_SUPPORTED} if the feature is not supported, or * an error code * * @return whether the chipset supports the LE Periodic Advertising Sync Transfer Sender feature */ Loading framework/java/android/bluetooth/BluetoothHeadset.java +104 −66 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.bluetooth; import static android.bluetooth.BluetoothUtils.getSyncTimeout; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; Loading @@ -44,6 +45,8 @@ import android.util.Log; import com.android.modules.utils.SynchronousResultReceiver; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeoutException; Loading Loading @@ -895,17 +898,36 @@ public final class BluetoothHeadset implements BluetoothProfile { com.android.internal.R.bool.config_bluetooth_sco_off_call); } /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(value = { BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTING, BluetoothHeadset.STATE_AUDIO_CONNECTED, BluetoothStatusCodes.ERROR_TIMEOUT }) public @interface GetAudioStateReturnValues {} /** * Get the current audio state of the Headset. * Note: This is an internal function and shouldn't be exposed * * @param device is the Bluetooth device for which the audio state is being queried * @return the audio state of the device or an error code * @throws IllegalArgumentException if the device is null * * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @SystemApi @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getAudioState(BluetoothDevice device) { @RequiresPermission(allOf = { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) public @GetAudioStateReturnValues int getAudioState(@NonNull BluetoothDevice device) { if (VDBG) log("getAudioState"); if (device == null) { throw new IllegalArgumentException("device cannot be null"); } final IBluetoothHeadset service = mService; final int defaultValue = BluetoothHeadset.STATE_AUDIO_DISCONNECTED; if (service == null) { Loading @@ -916,8 +938,12 @@ public final class BluetoothHeadset implements BluetoothProfile { final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver(); service.getAudioState(device, mAttributionSource, recv); return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); } catch (RemoteException | TimeoutException e) { } catch (RemoteException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); throw e.rethrowFromSystemServer(); } catch (TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); return BluetoothStatusCodes.ERROR_TIMEOUT; } } return defaultValue; Loading Loading @@ -1005,103 +1031,112 @@ public final class BluetoothHeadset implements BluetoothProfile { } } /** * Check if at least one headset's SCO audio is connected or connecting * * @return true if at least one device's SCO audio is connected or connecting, false otherwise * or on error * @hide */ @RequiresLegacyBluetoothPermission @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isAudioOn() { if (VDBG) log("isAudioOn()"); final IBluetoothHeadset service = mService; final boolean defaultValue = false; if (service == null) { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); } else if (isEnabled()) { try { final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver(); service.isAudioOn(mAttributionSource, recv); return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); } catch (RemoteException | TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } return defaultValue; } /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(value = { BluetoothStatusCodes.SUCCESS, BluetoothStatusCodes.ERROR_UNKNOWN, BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND, BluetoothStatusCodes.ERROR_TIMEOUT, BluetoothStatusCodes.ERROR_AUDIO_DEVICE_ALREADY_CONNECTED, BluetoothStatusCodes.ERROR_NO_ACTIVE_DEVICES, BluetoothStatusCodes.ERROR_NOT_ACTIVE_DEVICE, BluetoothStatusCodes.ERROR_AUDIO_ROUTE_BLOCKED, BluetoothStatusCodes.ERROR_CALL_ACTIVE, BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED }) public @interface ConnectAudioReturnValues {} /** * 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 * Initiates a connection of SCO audio to the current active HFP device. The active HFP device * can be identified with {@link BluetoothAdapter#getActiveDevices(int)}. * <p> * If this function returns {@link BluetoothStatusCodes#SUCCESS}, the intent * {@link #ACTION_AUDIO_STATE_CHANGED} will be broadcasted twice. First with {@link #EXTRA_STATE} * set to {@link #STATE_AUDIO_CONNECTING}. This will be followed by a broadcast with * {@link #EXTRA_STATE} set to either {@link #STATE_AUDIO_CONNECTED} if the audio connection is * established or {@link #STATE_AUDIO_DISCONNECTED} if there was a failure in establishing the * audio connection. * * @return false if there was some error such as there is no active headset * @return whether the connection was successfully initiated or an error code on failure * @hide */ @UnsupportedAppUsage @SystemApi @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean connectAudio() { @RequiresPermission(allOf = { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) public @ConnectAudioReturnValues int connectAudio() { if (VDBG) log("connectAudio()"); final IBluetoothHeadset service = mService; final boolean defaultValue = false; final int defaultValue = BluetoothStatusCodes.ERROR_UNKNOWN; if (service == null) { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); } else if (isEnabled()) { try { final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver(); final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver(); service.connectAudio(mAttributionSource, recv); return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); } catch (RemoteException | TimeoutException e) { } catch (RemoteException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); throw e.rethrowFromSystemServer(); } catch (TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); return BluetoothStatusCodes.ERROR_TIMEOUT; } } return defaultValue; } /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(value = { BluetoothStatusCodes.SUCCESS, BluetoothStatusCodes.ERROR_UNKNOWN, BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND, BluetoothStatusCodes.ERROR_TIMEOUT, BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED, BluetoothStatusCodes.ERROR_AUDIO_DEVICE_ALREADY_DISCONNECTED }) public @interface DisconnectAudioReturnValues {} /** * Initiates a disconnection of HFP SCO audio. * Tear down voice recognition or virtual voice call if any. * Initiates a disconnection of HFP SCO audio from actively connected devices. It also tears * down voice recognition or virtual voice call, if any exists. * * <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> If this function returns {@link BluetoothStatusCodes#SUCCESS}, the intent * {@link #ACTION_AUDIO_STATE_CHANGED} 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 * @return whether the disconnection was initiated successfully or an error code on failure * @hide */ @UnsupportedAppUsage @SystemApi @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disconnectAudio() { @RequiresPermission(allOf = { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) public @DisconnectAudioReturnValues int disconnectAudio() { if (VDBG) log("disconnectAudio()"); final IBluetoothHeadset service = mService; final boolean defaultValue = false; final int defaultValue = BluetoothStatusCodes.ERROR_UNKNOWN; if (service == null) { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); } else if (isEnabled()) { try { final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver(); final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver(); service.disconnectAudio(mAttributionSource, recv); return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); } catch (RemoteException | TimeoutException e) { } catch (RemoteException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); throw e.rethrowFromSystemServer(); } catch (TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); return BluetoothStatusCodes.ERROR_TIMEOUT; } } return defaultValue; Loading Loading @@ -1386,7 +1421,10 @@ public final class BluetoothHeadset implements BluetoothProfile { @SystemApi @RequiresLegacyBluetoothPermission @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) @RequiresPermission(allOf = { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) public boolean isInbandRingingEnabled() { if (DBG) log("isInbandRingingEnabled()"); final IBluetoothHeadset service = mService; Loading framework/java/android/bluetooth/BluetoothStatusCodes.java +84 −15 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ import android.annotation.SystemApi; /** * A class with constants representing possible return values for Bluetooth APIs. General return * values occupy the range 0 to 99. Profile-specific return values occupy the range 100-999. * values occupy the range 0 to 199. Profile-specific return values occupy the range 200-999. * API-specific return values start at 1000. The exception to this is the "UNKNOWN" error code which * occupies the max integer value. */ Loading @@ -29,28 +29,28 @@ public final class BluetoothStatusCodes { private BluetoothStatusCodes() {} /** * Indicates that the API call was successful * Indicates that the API call was successful. */ public static final int SUCCESS = 0; /** * Error code indicating that Bluetooth is not enabled * Error code indicating that Bluetooth is not enabled. */ public static final int ERROR_BLUETOOTH_NOT_ENABLED = 1; /** * Error code indicating that the API call was initiated by neither the system nor the active * user * user. */ public static final int ERROR_BLUETOOTH_NOT_ALLOWED = 2; /** * Error code indicating that the Bluetooth Device specified is not bonded * Error code indicating that the Bluetooth Device specified is not bonded. */ public static final int ERROR_DEVICE_NOT_BONDED = 3; /** * Error code indicating that the Bluetooth Device specified is not connected, but is bonded * Error code indicating that the Bluetooth Device specified is not connected, but is bonded. * * @hide */ Loading @@ -58,7 +58,7 @@ public final class BluetoothStatusCodes { /** * Error code indicating that the caller does not have the * {@link android.Manifest.permission#BLUETOOTH_ADVERTISE} permission * {@link android.Manifest.permission#BLUETOOTH_ADVERTISE} permission. * * @hide */ Loading @@ -66,13 +66,13 @@ public final class BluetoothStatusCodes { /** * Error code indicating that the caller does not have the * {@link android.Manifest.permission#BLUETOOTH_CONNECT} permission * {@link android.Manifest.permission#BLUETOOTH_CONNECT} permission. */ public static final int ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION = 6; /** * Error code indicating that the caller does not have the * {@link android.Manifest.permission#BLUETOOTH_SCAN} permission * {@link android.Manifest.permission#BLUETOOTH_SCAN} permission. * * @hide */ Loading @@ -80,30 +80,67 @@ public final class BluetoothStatusCodes { /** * Error code indicating that the caller does not have the * {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} permission * {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} permission. */ public static final int ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION = 8; /** * Error code indicating that the profile service is not bound. You can bind a profile service * by calling {@link BluetoothAdapter#getProfileProxy} * by calling {@link BluetoothAdapter#getProfileProxy}. */ public static final int ERROR_PROFILE_SERVICE_NOT_BOUND = 9; /** * Error code indicating that the feature is not supported. * Indicates that the feature is supported. */ public static final int ERROR_FEATURE_NOT_SUPPORTED = 10; public static final int FEATURE_SUPPORTED = 10; /** * Indicates that the feature is not supported. */ public static final int FEATURE_NOT_SUPPORTED = 11; /** * Error code indicating that the device is not the active device for this profile. * * @hide */ @SystemApi public static final int ERROR_NOT_ACTIVE_DEVICE = 12; /** * Error code indicating that there are no active devices for the profile. * * @hide */ @SystemApi public static final int ERROR_NO_ACTIVE_DEVICES = 13; /** * Indicates that the Bluetooth profile is not connected to this device. * * @hide */ @SystemApi public static final int ERROR_PROFILE_NOT_CONNECTED = 14; /** * Error code indicating that the requested operation timed out. * * @hide */ @SystemApi public static final int ERROR_TIMEOUT = 15; /** * A GATT writeCharacteristic request is not permitted on the remote device. */ public static final int ERROR_GATT_WRITE_NOT_ALLOWED = 101; public static final int ERROR_GATT_WRITE_NOT_ALLOWED = 200; /** * A GATT writeCharacteristic request is issued to a busy remote device. */ public static final int ERROR_GATT_WRITE_REQUEST_BUSY = 102; public static final int ERROR_GATT_WRITE_REQUEST_BUSY = 201; /** * If another application has already requested {@link OobData} then another fetch will be Loading Loading @@ -285,6 +322,38 @@ public final class BluetoothStatusCodes { */ public static final int ERROR_LE_AUDIO_BROADCAST_SOURCE_DISABLE_ENCRYPTION_FAILED = 1115; /** * Indicates that there is already one device for which SCO audio is connected or connecting. * * @hide */ @SystemApi public static final int ERROR_AUDIO_DEVICE_ALREADY_CONNECTED = 1116; /** * Indicates that SCO audio was already not connected for this device. * * @hide */ @SystemApi public static final int ERROR_AUDIO_DEVICE_ALREADY_DISCONNECTED = 1117; /** * Indicates that there audio route is currently blocked by the system. * * @hide */ @SystemApi public static final int ERROR_AUDIO_ROUTE_BLOCKED = 1118; /** * Indicates that there is an active call preventing this operation from succeeding. * * @hide */ @SystemApi public static final int ERROR_CALL_ACTIVE = 1119; /** * Indicates that an unknown error has occurred has occurred. */ Loading Loading
framework/java/android/bluetooth/BluetoothAdapter.java +9 −8 Original line number Diff line number Diff line Loading @@ -2249,17 +2249,17 @@ public final class BluetoothAdapter { /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(value = { BluetoothStatusCodes.SUCCESS, BluetoothStatusCodes.FEATURE_SUPPORTED, BluetoothStatusCodes.ERROR_UNKNOWN, BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED, BluetoothStatusCodes.ERROR_FEATURE_NOT_SUPPORTED, BluetoothStatusCodes.FEATURE_NOT_SUPPORTED, }) public @interface LeFeatureReturnValues {} /** * Returns {@link BluetoothStatusCodes#SUCCESS} if the LE audio feature is * supported, returns {@link BluetoothStatusCodes#ERROR_FEATURE_NOT_SUPPORTED} if * the feature is not supported or an error code. * Returns {@link BluetoothStatusCodes#FEATURE_SUPPORTED} if the LE audio feature is * supported, {@link BluetoothStatusCodes#FEATURE_NOT_SUPPORTED} if the feature is not * supported, or an error code. * * @return whether the LE audio is supported */ Loading @@ -2282,9 +2282,10 @@ public final class BluetoothAdapter { } /** * Returns {@link BluetoothStatusCodes#SUCCESS} if LE Periodic Advertising Sync Transfer Sender * feature is supported, returns {@link BluetoothStatusCodes#ERROR_FEATURE_NOT_SUPPORTED} if the * feature is not supported or an error code * Returns {@link BluetoothStatusCodes#FEATURE_SUPPORTED} if LE Periodic Advertising Sync * Transfer Sender feature is supported, * {@link BluetoothStatusCodes#FEATURE_NOT_SUPPORTED} if the feature is not supported, or * an error code * * @return whether the chipset supports the LE Periodic Advertising Sync Transfer Sender feature */ Loading
framework/java/android/bluetooth/BluetoothHeadset.java +104 −66 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.bluetooth; import static android.bluetooth.BluetoothUtils.getSyncTimeout; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; Loading @@ -44,6 +45,8 @@ import android.util.Log; import com.android.modules.utils.SynchronousResultReceiver; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeoutException; Loading Loading @@ -895,17 +898,36 @@ public final class BluetoothHeadset implements BluetoothProfile { com.android.internal.R.bool.config_bluetooth_sco_off_call); } /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(value = { BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTING, BluetoothHeadset.STATE_AUDIO_CONNECTED, BluetoothStatusCodes.ERROR_TIMEOUT }) public @interface GetAudioStateReturnValues {} /** * Get the current audio state of the Headset. * Note: This is an internal function and shouldn't be exposed * * @param device is the Bluetooth device for which the audio state is being queried * @return the audio state of the device or an error code * @throws IllegalArgumentException if the device is null * * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @SystemApi @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getAudioState(BluetoothDevice device) { @RequiresPermission(allOf = { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) public @GetAudioStateReturnValues int getAudioState(@NonNull BluetoothDevice device) { if (VDBG) log("getAudioState"); if (device == null) { throw new IllegalArgumentException("device cannot be null"); } final IBluetoothHeadset service = mService; final int defaultValue = BluetoothHeadset.STATE_AUDIO_DISCONNECTED; if (service == null) { Loading @@ -916,8 +938,12 @@ public final class BluetoothHeadset implements BluetoothProfile { final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver(); service.getAudioState(device, mAttributionSource, recv); return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); } catch (RemoteException | TimeoutException e) { } catch (RemoteException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); throw e.rethrowFromSystemServer(); } catch (TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); return BluetoothStatusCodes.ERROR_TIMEOUT; } } return defaultValue; Loading Loading @@ -1005,103 +1031,112 @@ public final class BluetoothHeadset implements BluetoothProfile { } } /** * Check if at least one headset's SCO audio is connected or connecting * * @return true if at least one device's SCO audio is connected or connecting, false otherwise * or on error * @hide */ @RequiresLegacyBluetoothPermission @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isAudioOn() { if (VDBG) log("isAudioOn()"); final IBluetoothHeadset service = mService; final boolean defaultValue = false; if (service == null) { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); } else if (isEnabled()) { try { final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver(); service.isAudioOn(mAttributionSource, recv); return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); } catch (RemoteException | TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } return defaultValue; } /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(value = { BluetoothStatusCodes.SUCCESS, BluetoothStatusCodes.ERROR_UNKNOWN, BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND, BluetoothStatusCodes.ERROR_TIMEOUT, BluetoothStatusCodes.ERROR_AUDIO_DEVICE_ALREADY_CONNECTED, BluetoothStatusCodes.ERROR_NO_ACTIVE_DEVICES, BluetoothStatusCodes.ERROR_NOT_ACTIVE_DEVICE, BluetoothStatusCodes.ERROR_AUDIO_ROUTE_BLOCKED, BluetoothStatusCodes.ERROR_CALL_ACTIVE, BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED }) public @interface ConnectAudioReturnValues {} /** * 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 * Initiates a connection of SCO audio to the current active HFP device. The active HFP device * can be identified with {@link BluetoothAdapter#getActiveDevices(int)}. * <p> * If this function returns {@link BluetoothStatusCodes#SUCCESS}, the intent * {@link #ACTION_AUDIO_STATE_CHANGED} will be broadcasted twice. First with {@link #EXTRA_STATE} * set to {@link #STATE_AUDIO_CONNECTING}. This will be followed by a broadcast with * {@link #EXTRA_STATE} set to either {@link #STATE_AUDIO_CONNECTED} if the audio connection is * established or {@link #STATE_AUDIO_DISCONNECTED} if there was a failure in establishing the * audio connection. * * @return false if there was some error such as there is no active headset * @return whether the connection was successfully initiated or an error code on failure * @hide */ @UnsupportedAppUsage @SystemApi @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean connectAudio() { @RequiresPermission(allOf = { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) public @ConnectAudioReturnValues int connectAudio() { if (VDBG) log("connectAudio()"); final IBluetoothHeadset service = mService; final boolean defaultValue = false; final int defaultValue = BluetoothStatusCodes.ERROR_UNKNOWN; if (service == null) { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); } else if (isEnabled()) { try { final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver(); final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver(); service.connectAudio(mAttributionSource, recv); return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); } catch (RemoteException | TimeoutException e) { } catch (RemoteException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); throw e.rethrowFromSystemServer(); } catch (TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); return BluetoothStatusCodes.ERROR_TIMEOUT; } } return defaultValue; } /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(value = { BluetoothStatusCodes.SUCCESS, BluetoothStatusCodes.ERROR_UNKNOWN, BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND, BluetoothStatusCodes.ERROR_TIMEOUT, BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED, BluetoothStatusCodes.ERROR_AUDIO_DEVICE_ALREADY_DISCONNECTED }) public @interface DisconnectAudioReturnValues {} /** * Initiates a disconnection of HFP SCO audio. * Tear down voice recognition or virtual voice call if any. * Initiates a disconnection of HFP SCO audio from actively connected devices. It also tears * down voice recognition or virtual voice call, if any exists. * * <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> If this function returns {@link BluetoothStatusCodes#SUCCESS}, the intent * {@link #ACTION_AUDIO_STATE_CHANGED} 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 * @return whether the disconnection was initiated successfully or an error code on failure * @hide */ @UnsupportedAppUsage @SystemApi @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disconnectAudio() { @RequiresPermission(allOf = { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) public @DisconnectAudioReturnValues int disconnectAudio() { if (VDBG) log("disconnectAudio()"); final IBluetoothHeadset service = mService; final boolean defaultValue = false; final int defaultValue = BluetoothStatusCodes.ERROR_UNKNOWN; if (service == null) { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); } else if (isEnabled()) { try { final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver(); final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver(); service.disconnectAudio(mAttributionSource, recv); return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); } catch (RemoteException | TimeoutException e) { } catch (RemoteException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); throw e.rethrowFromSystemServer(); } catch (TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); return BluetoothStatusCodes.ERROR_TIMEOUT; } } return defaultValue; Loading Loading @@ -1386,7 +1421,10 @@ public final class BluetoothHeadset implements BluetoothProfile { @SystemApi @RequiresLegacyBluetoothPermission @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) @RequiresPermission(allOf = { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) public boolean isInbandRingingEnabled() { if (DBG) log("isInbandRingingEnabled()"); final IBluetoothHeadset service = mService; Loading
framework/java/android/bluetooth/BluetoothStatusCodes.java +84 −15 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ import android.annotation.SystemApi; /** * A class with constants representing possible return values for Bluetooth APIs. General return * values occupy the range 0 to 99. Profile-specific return values occupy the range 100-999. * values occupy the range 0 to 199. Profile-specific return values occupy the range 200-999. * API-specific return values start at 1000. The exception to this is the "UNKNOWN" error code which * occupies the max integer value. */ Loading @@ -29,28 +29,28 @@ public final class BluetoothStatusCodes { private BluetoothStatusCodes() {} /** * Indicates that the API call was successful * Indicates that the API call was successful. */ public static final int SUCCESS = 0; /** * Error code indicating that Bluetooth is not enabled * Error code indicating that Bluetooth is not enabled. */ public static final int ERROR_BLUETOOTH_NOT_ENABLED = 1; /** * Error code indicating that the API call was initiated by neither the system nor the active * user * user. */ public static final int ERROR_BLUETOOTH_NOT_ALLOWED = 2; /** * Error code indicating that the Bluetooth Device specified is not bonded * Error code indicating that the Bluetooth Device specified is not bonded. */ public static final int ERROR_DEVICE_NOT_BONDED = 3; /** * Error code indicating that the Bluetooth Device specified is not connected, but is bonded * Error code indicating that the Bluetooth Device specified is not connected, but is bonded. * * @hide */ Loading @@ -58,7 +58,7 @@ public final class BluetoothStatusCodes { /** * Error code indicating that the caller does not have the * {@link android.Manifest.permission#BLUETOOTH_ADVERTISE} permission * {@link android.Manifest.permission#BLUETOOTH_ADVERTISE} permission. * * @hide */ Loading @@ -66,13 +66,13 @@ public final class BluetoothStatusCodes { /** * Error code indicating that the caller does not have the * {@link android.Manifest.permission#BLUETOOTH_CONNECT} permission * {@link android.Manifest.permission#BLUETOOTH_CONNECT} permission. */ public static final int ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION = 6; /** * Error code indicating that the caller does not have the * {@link android.Manifest.permission#BLUETOOTH_SCAN} permission * {@link android.Manifest.permission#BLUETOOTH_SCAN} permission. * * @hide */ Loading @@ -80,30 +80,67 @@ public final class BluetoothStatusCodes { /** * Error code indicating that the caller does not have the * {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} permission * {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} permission. */ public static final int ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION = 8; /** * Error code indicating that the profile service is not bound. You can bind a profile service * by calling {@link BluetoothAdapter#getProfileProxy} * by calling {@link BluetoothAdapter#getProfileProxy}. */ public static final int ERROR_PROFILE_SERVICE_NOT_BOUND = 9; /** * Error code indicating that the feature is not supported. * Indicates that the feature is supported. */ public static final int ERROR_FEATURE_NOT_SUPPORTED = 10; public static final int FEATURE_SUPPORTED = 10; /** * Indicates that the feature is not supported. */ public static final int FEATURE_NOT_SUPPORTED = 11; /** * Error code indicating that the device is not the active device for this profile. * * @hide */ @SystemApi public static final int ERROR_NOT_ACTIVE_DEVICE = 12; /** * Error code indicating that there are no active devices for the profile. * * @hide */ @SystemApi public static final int ERROR_NO_ACTIVE_DEVICES = 13; /** * Indicates that the Bluetooth profile is not connected to this device. * * @hide */ @SystemApi public static final int ERROR_PROFILE_NOT_CONNECTED = 14; /** * Error code indicating that the requested operation timed out. * * @hide */ @SystemApi public static final int ERROR_TIMEOUT = 15; /** * A GATT writeCharacteristic request is not permitted on the remote device. */ public static final int ERROR_GATT_WRITE_NOT_ALLOWED = 101; public static final int ERROR_GATT_WRITE_NOT_ALLOWED = 200; /** * A GATT writeCharacteristic request is issued to a busy remote device. */ public static final int ERROR_GATT_WRITE_REQUEST_BUSY = 102; public static final int ERROR_GATT_WRITE_REQUEST_BUSY = 201; /** * If another application has already requested {@link OobData} then another fetch will be Loading Loading @@ -285,6 +322,38 @@ public final class BluetoothStatusCodes { */ public static final int ERROR_LE_AUDIO_BROADCAST_SOURCE_DISABLE_ENCRYPTION_FAILED = 1115; /** * Indicates that there is already one device for which SCO audio is connected or connecting. * * @hide */ @SystemApi public static final int ERROR_AUDIO_DEVICE_ALREADY_CONNECTED = 1116; /** * Indicates that SCO audio was already not connected for this device. * * @hide */ @SystemApi public static final int ERROR_AUDIO_DEVICE_ALREADY_DISCONNECTED = 1117; /** * Indicates that there audio route is currently blocked by the system. * * @hide */ @SystemApi public static final int ERROR_AUDIO_ROUTE_BLOCKED = 1118; /** * Indicates that there is an active call preventing this operation from succeeding. * * @hide */ @SystemApi public static final int ERROR_CALL_ACTIVE = 1119; /** * Indicates that an unknown error has occurred has occurred. */ Loading