diff options
5 files changed, 142 insertions, 5 deletions
diff --git a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java index 121dc49320..7df5de50bc 100644 --- a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java @@ -26,6 +26,8 @@ import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothLeAudio; +import android.bluetooth.BluetoothLeAudioCodecConfig; +import android.bluetooth.BluetoothLeAudioCodecStatus; import android.bluetooth.BluetoothLeAudioContentMetadata; import android.bluetooth.BluetoothLeBroadcastMetadata; import android.bluetooth.BluetoothProfile; @@ -1695,6 +1697,52 @@ public class LeAudioService extends ProfileService { } /** + * Gets the current codec status (configuration and capability). + * + * @param device the remote Bluetooth device. + * @return the current codec status + * @hide + */ + public BluetoothLeAudioCodecStatus getCodecStatus(BluetoothDevice device) { + if (DBG) { + Log.d(TAG, "getCodecStatus(" + device + ")"); + } + + return null; + } + + /** + * Sets the codec configuration preference. + * + * @param device the remote Bluetooth device. + * @param codecConfig the codec configuration preference + * @hide + */ + public void setCodecConfigPreference(BluetoothDevice device, + BluetoothLeAudioCodecConfig codecConfig) { + if (DBG) { + Log.d(TAG, "setCodecConfigPreference(" + device + "): " + + Objects.toString(codecConfig)); + } + if (device == null) { + Log.e(TAG, "setCodecConfigPreference: Invalid device"); + return; + } + if (codecConfig == null) { + Log.e(TAG, "setCodecConfigPreference: Codec config can't be null"); + return; + } + BluetoothLeAudioCodecStatus codecStatus = getCodecStatus(device); + if (codecStatus == null) { + Log.e(TAG, "setCodecConfigPreference: Codec status is null"); + return; + } + + // TODO: pass the information to bt stack + } + + + /** * Binder object: must be a static class or memory leak may occur */ @VisibleForTesting @@ -2057,6 +2105,34 @@ public class LeAudioService extends ProfileService { receiver.propagateException(e); } } + + @Override + public void getCodecStatus(BluetoothDevice device, + AttributionSource source, SynchronousResultReceiver receiver) { + try { + LeAudioService service = getService(source); + BluetoothLeAudioCodecStatus codecStatus = null; + if (service != null) { + enforceBluetoothPrivilegedPermission(service); + codecStatus = service.getCodecStatus(device); + } + receiver.send(codecStatus); + } catch (RuntimeException e) { + receiver.propagateException(e); + } + } + + @Override + public void setCodecConfigPreference(BluetoothDevice device, + BluetoothLeAudioCodecConfig codecConfig, AttributionSource source) { + LeAudioService service = getService(source); + if (service == null) { + return; + } + + enforceBluetoothPrivilegedPermission(service); + service.setCodecConfigPreference(device, codecConfig); + } } @Override diff --git a/framework/java/android/bluetooth/BluetoothLeAudio.java b/framework/java/android/bluetooth/BluetoothLeAudio.java index 2db1d1afe5..23e9a039f4 100644 --- a/framework/java/android/bluetooth/BluetoothLeAudio.java +++ b/framework/java/android/bluetooth/BluetoothLeAudio.java @@ -966,9 +966,22 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { Log.d(TAG, "getCodecStatus(" + device + ")"); } + final IBluetoothLeAudio service = getService(); final BluetoothLeAudioCodecStatus defaultValue = null; - // TODO: Add the implementation to get codec status + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (mAdapter.isEnabled() && isValidDevice(device)) { + try { + final SynchronousResultReceiver<BluetoothLeAudioCodecStatus> recv = + new SynchronousResultReceiver(); + service.getCodecStatus(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } + } return defaultValue; } @@ -994,8 +1007,18 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { throw new IllegalArgumentException("codecConfig cannot be null"); } - // TODO: Add the implementation to set config preference - return; + final IBluetoothLeAudio service = getService(); + + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (mAdapter.isEnabled() && isValidDevice(device)) { + try { + service.setCodecConfigPreference(device, codecConfig, mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } + } } } diff --git a/framework/java/android/bluetooth/BluetoothLeAudioCodecStatus.java b/framework/java/android/bluetooth/BluetoothLeAudioCodecStatus.java index dea0642041..399ffa743c 100644 --- a/framework/java/android/bluetooth/BluetoothLeAudioCodecStatus.java +++ b/framework/java/android/bluetooth/BluetoothLeAudioCodecStatus.java @@ -109,8 +109,15 @@ public final class BluetoothLeAudioCodecStatus implements Parcelable { * @return {@code true} if the codec config matches, {@code false} otherwise */ public boolean isCodecConfigSelectable(@Nullable BluetoothLeAudioCodecConfig codecConfig) { - // TODO: Add the implementation to check the config is selectable - return true; + if (codecConfig == null) { + return false; + } + for (BluetoothLeAudioCodecConfig selectableConfig : mCodecsSelectableCapabilities) { + if (codecConfig.equals(selectableConfig)) { + return true; + } + } + return false; } /** @@ -171,6 +178,8 @@ public final class BluetoothLeAudioCodecStatus implements Parcelable { /** * Returns the current codec configuration. + * + * @return The current codec config. */ public @Nullable BluetoothLeAudioCodecConfig getCodecConfig() { return mCodecConfig; @@ -178,6 +187,8 @@ public final class BluetoothLeAudioCodecStatus implements Parcelable { /** * Returns the codecs local capabilities. + * + * @return The list of codec config that supported by the local system. */ public @NonNull List<BluetoothLeAudioCodecConfig> getCodecLocalCapabilities() { return (mCodecsLocalCapabilities == null) @@ -186,6 +197,9 @@ public final class BluetoothLeAudioCodecStatus implements Parcelable { /** * Returns the codecs selectable capabilities. + * + * @return The list of codec config that supported by both of the local system and + * remote devices. */ public @NonNull List<BluetoothLeAudioCodecConfig> getCodecSelectableCapabilities() { return (mCodecsSelectableCapabilities == null) diff --git a/system/binder/android/bluetooth/BluetoothLeAudioCodecConfig.aidl b/system/binder/android/bluetooth/BluetoothLeAudioCodecConfig.aidl new file mode 100644 index 0000000000..e32217eff7 --- /dev/null +++ b/system/binder/android/bluetooth/BluetoothLeAudioCodecConfig.aidl @@ -0,0 +1,19 @@ +/* + * Copyright 2022 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; + +parcelable BluetoothLeAudioCodecConfig; diff --git a/system/binder/android/bluetooth/IBluetoothLeAudio.aidl b/system/binder/android/bluetooth/IBluetoothLeAudio.aidl index 22a90a0758..c588802fee 100644 --- a/system/binder/android/bluetooth/IBluetoothLeAudio.aidl +++ b/system/binder/android/bluetooth/IBluetoothLeAudio.aidl @@ -18,6 +18,7 @@ package android.bluetooth; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothLeAudioCodecConfig; import android.bluetooth.BluetoothLeAudioContentMetadata; import android.bluetooth.IBluetoothLeBroadcastCallback; import android.content.AttributionSource; @@ -51,6 +52,10 @@ oneway interface IBluetoothLeAudio { void getConnectionPolicy(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") void getConnectedGroupLeadDevice(int groupId, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") + void getCodecStatus(in BluetoothDevice device, in AttributionSource source, in SynchronousResultReceiver receiver); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") + void setCodecConfigPreference(in BluetoothDevice device, in BluetoothLeAudioCodecConfig codecConfig, in AttributionSource source); /* Same value as bluetooth::groups::kGroupUnknown */ const int LE_AUDIO_GROUP_ID_INVALID = -1; |