diff options
| author | Md Shahriar Hossain Sajib <sajibonly@google.com> | 2022-10-13 15:21:15 +0800 |
|---|---|---|
| committer | David Duarte <licorne@google.com> | 2023-01-27 23:25:15 +0000 |
| commit | 47cbbc8c59b9c09de9be9df971ccb5b5d71c22ee (patch) | |
| tree | cb43fa62a36343c7c4aa8ff1214eb968ded4af4d /framework/java/android/bluetooth/BluetoothDevice.java | |
| parent | 5fcf3f55c331ae4c972ed770270618aa383573bd (diff) | |
Bluetooth Audio Policy APIs and HFP support integration
HFP android specific command protocol to implement android features.
Used this protocol to support the Audio Policy feature from the HFP
protocol. BluetoothDevice is the endpoint to invoke the feature and
later BLE Audio will also support it.
Cherry picked from wear OS
Dirty because of conflict + hide the API
Bug: 263323082
Bug: 235541516
Bug: 253059988
Test: atest BluetoothInstrumentationTests
Tag: #feature
Merged-In: I5fd6c7959a85104f2bb5e31809a0e250c2dd13d0
(cherry picked from commit cb85f8cb0da7680b9251bbbca7ce12e78008037d)
Change-Id: I5d2d8f4ab71c8ed4f2f2997a7e16fc6b863bc5ae
Diffstat (limited to 'framework/java/android/bluetooth/BluetoothDevice.java')
| -rw-r--r-- | framework/java/android/bluetooth/BluetoothDevice.java | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/framework/java/android/bluetooth/BluetoothDevice.java b/framework/java/android/bluetooth/BluetoothDevice.java index d6930c5efe..780a66014b 100644 --- a/framework/java/android/bluetooth/BluetoothDevice.java +++ b/framework/java/android/bluetooth/BluetoothDevice.java @@ -3228,6 +3228,148 @@ public final class BluetoothDevice implements Parcelable, Attributable { return METADATA_LE_AUDIO; } + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef( + prefix = { "REMOTE_STATUS_" }, + value = { + /** Remote support status of audio policy feature is unknown/unconfigured **/ + BluetoothAudioPolicy.FEATURE_UNCONFIGURED_BY_REMOTE, + /** Remote support status of audio policy feature is supported **/ + BluetoothAudioPolicy.FEATURE_SUPPORTED_BY_REMOTE, + /** Remote support status of audio policy feature is not supported **/ + BluetoothAudioPolicy.FEATURE_NOT_SUPPORTED_BY_REMOTE, + } + ) + + public @interface AudioPolicyRemoteSupport {} + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { + BluetoothStatusCodes.SUCCESS, + BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED, + BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED, + BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED, + BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION, + BluetoothStatusCodes.FEATURE_NOT_SUPPORTED, + BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED, + }) + public @interface AudioPolicyReturnValues{} + + /** + * Returns whether the audio policy feature is supported by the remote. + * This requires a vendor specific command, so the API returns + * {@link BluetoothAudioPolicy#FEATURE_UNCONFIGURED_BY_REMOTE} to indicate the remote + * device has not yet relayed this information. After the internal configuration, + * the support status will be set to either + * {@link BluetoothAudioPolicy#FEATURE_NOT_SUPPORTED_BY_REMOTE} or + * {@link BluetoothAudioPolicy#FEATURE_SUPPORTED_BY_REMOTE}. + * The rest of the APIs related to this feature in both {@link BluetoothDevice} + * and {@link BluetoothAudioPolicy} should be invoked only after getting a + * {@link BluetoothAudioPolicy#FEATURE_SUPPORTED_BY_REMOTE} response from this API. + * + * @return if call audio policy feature is supported or not + * + * @hide + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(allOf = { + android.Manifest.permission.BLUETOOTH_CONNECT, + android.Manifest.permission.BLUETOOTH_PRIVILEGED, + }) + public @AudioPolicyRemoteSupport int getAudioPolicyRemoteSupported() { + if (DBG) log("getAudioPolicyRemoteSupported()"); + final IBluetooth service = getService(); + final int defaultValue = BluetoothAudioPolicy.FEATURE_UNCONFIGURED_BY_REMOTE; + if (service == null || !isBluetoothEnabled()) { + Log.e(TAG, "BT not enabled. Cannot retrieve audio policy support status."); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else { + try { + final SynchronousResultReceiver<Integer> recv = SynchronousResultReceiver.get(); + service.getAudioPolicyRemoteSupported(this, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } catch (RemoteException e) { + Log.e(TAG, "", e); + throw e.rethrowFromSystemServer(); + } + } + return defaultValue; + } + + /** + * Sets call audio preferences and sends them to the remote device. + * + * @param policies call audio policy preferences + * @return whether audio policy was set successfully or not + * + * @hide + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(allOf = { + android.Manifest.permission.BLUETOOTH_CONNECT, + android.Manifest.permission.BLUETOOTH_PRIVILEGED, + }) + public @AudioPolicyReturnValues int setAudioPolicy(@NonNull BluetoothAudioPolicy policies) { + if (DBG) log("setAudioPolicy"); + final IBluetooth service = getService(); + final int defaultValue = BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; + if (service == null || !isBluetoothEnabled()) { + Log.e(TAG, "Bluetooth is not enabled. Cannot set Audio Policy."); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else { + try { + final SynchronousResultReceiver<Integer> recv = SynchronousResultReceiver.get(); + service.setAudioPolicy(this, policies, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } + } + return defaultValue; + } + + /** + * Gets the call audio preferences for the remote device. + * <p>Note that the caller should check if the feature is supported by + * invoking {@link BluetoothDevice#getAudioPolicyRemoteSupported} first. + * <p>This API will return null if + * 1. The bleutooth service is not started yet, + * 2. It is invoked for a device which is not bonded, or + * 3. The used transport, for example, HFP Client profile is not enabled or + * connected yet. + * + * @return call audio policy as {@link BluetoothAudioPolicy} object + * + * @hide + */ + @RequiresBluetoothConnectPermission + @RequiresPermission(allOf = { + android.Manifest.permission.BLUETOOTH_CONNECT, + android.Manifest.permission.BLUETOOTH_PRIVILEGED, + }) + public @Nullable BluetoothAudioPolicy getAudioPolicy() { + if (DBG) log("getAudioPolicy"); + final IBluetooth service = getService(); + if (service == null || !isBluetoothEnabled()) { + Log.e(TAG, "Bluetooth is not enabled. Cannot get Audio Policy."); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else { + try { + final SynchronousResultReceiver<BluetoothAudioPolicy> + recv = SynchronousResultReceiver.get(); + service.getAudioPolicy(this, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } + } + return null; + } + /** * Enable or disable audio low latency for this {@link BluetoothDevice}. * |
