summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2021-12-02 12:45:30 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2021-12-02 12:45:30 +0000
commit792db6a75e388704139f996ff6a556340fde39ac (patch)
treecd156a2a9244d0979b610d683e3b735b1d56f74c
parent06299b95e47cce00e3c93945d0fba2b52b7a3c6f (diff)
parent4669421b4c7956f01de447aba54fa8062a2445c8 (diff)
Merge "Parse audio config codec capability for LE devices"
-rw-r--r--core/api/current.txt14
-rw-r--r--core/java/android/bluetooth/BluetoothLeAudioCodecConfig.java129
-rw-r--r--core/jni/android_media_AudioSystem.cpp17
-rw-r--r--core/tests/bluetoothtests/src/android/bluetooth/BluetoothLeAudioCodecConfigTest.java59
-rw-r--r--media/java/android/media/AudioManager.java53
-rw-r--r--media/java/android/media/AudioSystem.java42
6 files changed, 288 insertions, 26 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index ea69d212af73..f5f3bb091f28 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -9561,6 +9561,20 @@ package android.bluetooth {
field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED = "android.bluetooth.action.LE_AUDIO_CONNECTION_STATE_CHANGED";
}
+ public final class BluetoothLeAudioCodecConfig {
+ method @NonNull public String getCodecName();
+ method public int getCodecType();
+ method public static int getMaxCodecType();
+ field public static final int SOURCE_CODEC_TYPE_INVALID = 1000000; // 0xf4240
+ field public static final int SOURCE_CODEC_TYPE_LC3 = 0; // 0x0
+ }
+
+ public static final class BluetoothLeAudioCodecConfig.Builder {
+ ctor public BluetoothLeAudioCodecConfig.Builder();
+ method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig build();
+ method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig.Builder setCodecType(int);
+ }
+
public final class BluetoothManager {
method public android.bluetooth.BluetoothAdapter getAdapter();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(int);
diff --git a/core/java/android/bluetooth/BluetoothLeAudioCodecConfig.java b/core/java/android/bluetooth/BluetoothLeAudioCodecConfig.java
new file mode 100644
index 000000000000..dcaf4b682f44
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothLeAudioCodecConfig.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2021 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.annotation.IntDef;
+import android.annotation.NonNull;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Represents the codec configuration for a Bluetooth LE Audio source device.
+ * <p>Contains the source codec type.
+ * <p>The source codec type values are the same as those supported by the
+ * device hardware.
+ *
+ * {@see BluetoothLeAudioCodecConfig}
+ */
+public final class BluetoothLeAudioCodecConfig {
+ // Add an entry for each source codec here.
+
+ /** @hide */
+ @IntDef(prefix = "SOURCE_CODEC_TYPE_", value = {
+ SOURCE_CODEC_TYPE_LC3,
+ SOURCE_CODEC_TYPE_INVALID
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SourceCodecType {};
+
+ public static final int SOURCE_CODEC_TYPE_LC3 = 0;
+ public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000;
+
+ /**
+ * Represents the count of valid source codec types. Can be accessed via
+ * {@link #getMaxCodecType}.
+ */
+ private static final int SOURCE_CODEC_TYPE_MAX = 1;
+
+ private final @SourceCodecType int mCodecType;
+
+ /**
+ * Creates a new BluetoothLeAudioCodecConfig.
+ *
+ * @param codecType the source codec type
+ */
+ private BluetoothLeAudioCodecConfig(@SourceCodecType int codecType) {
+ mCodecType = codecType;
+ }
+
+ @Override
+ public String toString() {
+ return "{codecName:" + getCodecName() + "}";
+ }
+
+ /**
+ * Gets the codec type.
+ *
+ * @return the codec type
+ */
+ public @SourceCodecType int getCodecType() {
+ return mCodecType;
+ }
+
+ /**
+ * Returns the valid codec types count.
+ */
+ public static int getMaxCodecType() {
+ return SOURCE_CODEC_TYPE_MAX;
+ }
+
+ /**
+ * Gets the codec name.
+ *
+ * @return the codec name
+ */
+ public @NonNull String getCodecName() {
+ switch (mCodecType) {
+ case SOURCE_CODEC_TYPE_LC3:
+ return "LC3";
+ case SOURCE_CODEC_TYPE_INVALID:
+ return "INVALID CODEC";
+ default:
+ break;
+ }
+ return "UNKNOWN CODEC(" + mCodecType + ")";
+ }
+
+ /**
+ * Builder for {@link BluetoothLeAudioCodecConfig}.
+ * <p> By default, the codec type will be set to
+ * {@link BluetoothLeAudioCodecConfig#SOURCE_CODEC_TYPE_INVALID}
+ */
+ public static final class Builder {
+ private int mCodecType = BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_INVALID;
+
+ /**
+ * Set codec type for Bluetooth codec config.
+ *
+ * @param codecType of this codec
+ * @return the same Builder instance
+ */
+ public @NonNull Builder setCodecType(@SourceCodecType int codecType) {
+ mCodecType = codecType;
+ return this;
+ }
+
+ /**
+ * Build {@link BluetoothLeAudioCodecConfig}.
+ * @return new BluetoothLeAudioCodecConfig built
+ */
+ public @NonNull BluetoothLeAudioCodecConfig build() {
+ return new BluetoothLeAudioCodecConfig(mCodecType);
+ }
+ }
+}
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 268871bb16c5..8b45907b64f2 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -2284,10 +2284,8 @@ android_media_AudioSystem_getMicrophones(JNIEnv *env, jobject thiz, jobject jMic
return jStatus;
}
-static jint
-android_media_AudioSystem_getHwOffloadEncodingFormatsSupportedForA2DP(
- JNIEnv *env, jobject thiz, jobject jEncodingFormatList)
-{
+static jint android_media_AudioSystem_getHwOffloadFormatsSupportedForBluetoothMedia(
+ JNIEnv *env, jobject thiz, jint deviceType, jobject jEncodingFormatList) {
ALOGV("%s", __FUNCTION__);
jint jStatus = AUDIO_JAVA_SUCCESS;
if (!env->IsInstanceOf(jEncodingFormatList, gArrayListClass)) {
@@ -2295,8 +2293,10 @@ android_media_AudioSystem_getHwOffloadEncodingFormatsSupportedForA2DP(
return (jint)AUDIO_JAVA_BAD_VALUE;
}
std::vector<audio_format_t> encodingFormats;
- status_t status = AudioSystem::getHwOffloadEncodingFormatsSupportedForA2DP(
- &encodingFormats);
+ status_t status =
+ AudioSystem::getHwOffloadFormatsSupportedForBluetoothMedia(static_cast<audio_devices_t>(
+ deviceType),
+ &encodingFormats);
if (status != NO_ERROR) {
ALOGE("%s: error %d", __FUNCTION__, status);
jStatus = nativeToJavaStatus(status);
@@ -2875,8 +2875,8 @@ static const JNINativeMethod gMethods[] =
{"setA11yServicesUids", "([I)I", (void *)android_media_AudioSystem_setA11yServicesUids},
{"isHapticPlaybackSupported", "()Z",
(void *)android_media_AudioSystem_isHapticPlaybackSupported},
- {"getHwOffloadEncodingFormatsSupportedForA2DP", "(Ljava/util/ArrayList;)I",
- (void *)android_media_AudioSystem_getHwOffloadEncodingFormatsSupportedForA2DP},
+ {"getHwOffloadFormatsSupportedForBluetoothMedia", "(ILjava/util/ArrayList;)I",
+ (void *)android_media_AudioSystem_getHwOffloadFormatsSupportedForBluetoothMedia},
{"setSupportedSystemUsages", "([I)I",
(void *)android_media_AudioSystem_setSupportedSystemUsages},
{"setAllowedCapturePolicy", "(II)I",
@@ -2919,7 +2919,6 @@ static const JNINativeMethod gMethods[] =
"[Landroid/media/AudioDeviceAttributes;)Z",
(void *)android_media_AudioSystem_canBeSpatialized}};
-
static const JNINativeMethod gEventHandlerMethods[] = {
{"native_setup",
"(Ljava/lang/Object;)V",
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothLeAudioCodecConfigTest.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothLeAudioCodecConfigTest.java
new file mode 100644
index 000000000000..6471492c9663
--- /dev/null
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothLeAudioCodecConfigTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 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.test.suitebuilder.annotation.SmallTest;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit test cases for {@link BluetoothLeAudioCodecConfig}.
+ */
+public class BluetoothLeAudioCodecConfigTest extends TestCase {
+ private int[] mCodecTypeArray = new int[] {
+ BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_LC3,
+ BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_INVALID,
+ };
+
+ @SmallTest
+ public void testBluetoothLeAudioCodecConfig_valid_get_methods() {
+
+ for (int codecIdx = 0; codecIdx < mCodecTypeArray.length; codecIdx++) {
+ int codecType = mCodecTypeArray[codecIdx];
+
+ BluetoothLeAudioCodecConfig leAudioCodecConfig =
+ buildBluetoothLeAudioCodecConfig(codecType);
+
+ if (codecType == BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_LC3) {
+ assertEquals("LC3", leAudioCodecConfig.getCodecName());
+ }
+ if (codecType == BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_INVALID) {
+ assertEquals("INVALID CODEC", leAudioCodecConfig.getCodecName());
+ }
+
+ assertEquals(1, leAudioCodecConfig.getMaxCodecType());
+ assertEquals(codecType, leAudioCodecConfig.getCodecType());
+ }
+ }
+
+ private BluetoothLeAudioCodecConfig buildBluetoothLeAudioCodecConfig(int sourceCodecType) {
+ return new BluetoothLeAudioCodecConfig.Builder()
+ .setCodecType(sourceCodecType)
+ .build();
+
+ }
+}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 337b45c4c531..faae9a5bd4c9 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -33,6 +33,7 @@ import android.app.PendingIntent;
import android.app.compat.CompatChanges;
import android.bluetooth.BluetoothCodecConfig;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothLeAudioCodecConfig;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.compat.annotation.UnsupportedAppUsage;
@@ -6768,30 +6769,56 @@ public class AudioManager {
/**
* Returns a list of audio formats that corresponds to encoding formats
- * supported on offload path for A2DP playback.
+ * supported on offload path for A2DP and LE audio playback.
*
+ * @param deviceType Indicates the target device type {@link AudioSystem.DeviceType}
* @return a list of {@link BluetoothCodecConfig} objects containing encoding formats
- * supported for offload A2DP playback
+ * supported for offload A2DP playback or a list of {@link BluetoothLeAudioCodecConfig}
+ * objects containing encoding formats supported for offload LE Audio playback
* @hide
*/
- public List<BluetoothCodecConfig> getHwOffloadEncodingFormatsSupportedForA2DP() {
+ public List<?> getHwOffloadFormatsSupportedForBluetoothMedia(
+ @AudioSystem.DeviceType int deviceType) {
ArrayList<Integer> formatsList = new ArrayList<Integer>();
- ArrayList<BluetoothCodecConfig> codecConfigList = new ArrayList<BluetoothCodecConfig>();
+ ArrayList<BluetoothCodecConfig> a2dpCodecConfigList = new ArrayList<BluetoothCodecConfig>();
+ ArrayList<BluetoothLeAudioCodecConfig> leAudioCodecConfigList =
+ new ArrayList<BluetoothLeAudioCodecConfig>();
- int status = AudioSystem.getHwOffloadEncodingFormatsSupportedForA2DP(formatsList);
+ if (deviceType != AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP
+ && deviceType != AudioSystem.DEVICE_OUT_BLE_HEADSET) {
+ throw new IllegalArgumentException(
+ "Illegal devicetype for the getHwOffloadFormatsSupportedForBluetoothMedia");
+ }
+
+ int status = AudioSystem.getHwOffloadFormatsSupportedForBluetoothMedia(deviceType,
+ formatsList);
if (status != AudioManager.SUCCESS) {
- Log.e(TAG, "getHwOffloadEncodingFormatsSupportedForA2DP failed:" + status);
- return codecConfigList;
+ Log.e(TAG, "getHwOffloadFormatsSupportedForBluetoothMedia for deviceType "
+ + deviceType + " failed:" + status);
+ return a2dpCodecConfigList;
}
- for (Integer format : formatsList) {
- int btSourceCodec = AudioSystem.audioFormatToBluetoothSourceCodec(format);
- if (btSourceCodec
- != BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID) {
- codecConfigList.add(new BluetoothCodecConfig(btSourceCodec));
+ if (deviceType == AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) {
+ for (Integer format : formatsList) {
+ int btSourceCodec = AudioSystem.audioFormatToBluetoothSourceCodec(format);
+ if (btSourceCodec != BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID) {
+ a2dpCodecConfigList.add(new BluetoothCodecConfig(btSourceCodec));
+ }
+ }
+ return a2dpCodecConfigList;
+ } else if (deviceType == AudioSystem.DEVICE_OUT_BLE_HEADSET) {
+ for (Integer format : formatsList) {
+ int btLeAudioCodec = AudioSystem.audioFormatToBluetoothLeAudioSourceCodec(format);
+ if (btLeAudioCodec != BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_INVALID) {
+ leAudioCodecConfigList.add(new BluetoothLeAudioCodecConfig.Builder()
+ .setCodecType(btLeAudioCodec)
+ .build());
+ }
}
+ return leAudioCodecConfigList;
}
- return codecConfigList;
+ Log.e(TAG, "Input deviceType " + deviceType + " doesn't support.");
+ return a2dpCodecConfigList;
}
// Since we need to calculate the changes since THE LAST NOTIFICATION, and not since the
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 16cb5f437414..cc37c38e96c1 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -22,6 +22,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.TestApi;
import android.bluetooth.BluetoothCodecConfig;
+import android.bluetooth.BluetoothLeAudioCodecConfig;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -236,6 +237,9 @@ public class AudioSystem
public static final int AUDIO_FORMAT_APTX_HD = 0x21000000;
/** @hide */
public static final int AUDIO_FORMAT_LDAC = 0x23000000;
+ /** @hide */
+ public static final int AUDIO_FORMAT_LC3 = 0x2B000000;
+
/** @hide */
@IntDef(flag = false, prefix = "AUDIO_FORMAT_", value = {
@@ -245,11 +249,26 @@ public class AudioSystem
AUDIO_FORMAT_SBC,
AUDIO_FORMAT_APTX,
AUDIO_FORMAT_APTX_HD,
- AUDIO_FORMAT_LDAC }
+ AUDIO_FORMAT_LDAC}
)
@Retention(RetentionPolicy.SOURCE)
public @interface AudioFormatNativeEnumForBtCodec {}
+ /** @hide */
+ @IntDef(flag = false, prefix = "AUDIO_FORMAT_", value = {
+ AUDIO_FORMAT_LC3}
+ )
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AudioFormatNativeEnumForBtLeAudioCodec {}
+
+ /** @hide */
+ @IntDef(flag = false, prefix = "DEVICE_", value = {
+ DEVICE_OUT_BLUETOOTH_A2DP,
+ DEVICE_OUT_BLE_HEADSET}
+ )
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DeviceType {}
+
/**
* @hide
* Convert audio format enum values to Bluetooth codec values
@@ -271,6 +290,21 @@ public class AudioSystem
/**
* @hide
+ * Convert audio format enum values to Bluetooth LE audio codec values
+ */
+ public static int audioFormatToBluetoothLeAudioSourceCodec(
+ @AudioFormatNativeEnumForBtLeAudioCodec int audioFormat) {
+ switch (audioFormat) {
+ case AUDIO_FORMAT_LC3: return BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_LC3;
+ default:
+ Log.e(TAG, "Unknown audio format 0x" + Integer.toHexString(audioFormat)
+ + " for conversion to BT LE audio codec");
+ return BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_INVALID;
+ }
+ }
+
+ /**
+ * @hide
* Convert a Bluetooth codec to an audio format enum
* @param btCodec the codec to convert.
* @return the audio format, or {@link #AUDIO_FORMAT_DEFAULT} if unknown
@@ -1761,10 +1795,10 @@ public class AudioSystem
/**
* @hide
- * Returns a list of audio formats (codec) supported on the A2DP offload path.
+ * Returns a list of audio formats (codec) supported on the A2DP and LE audio offload path.
*/
- public static native int getHwOffloadEncodingFormatsSupportedForA2DP(
- ArrayList<Integer> formatList);
+ public static native int getHwOffloadFormatsSupportedForBluetoothMedia(
+ @DeviceType int deviceType, ArrayList<Integer> formatList);
/** @hide */
public static native int setSurroundFormatEnabled(int audioFormat, boolean enabled);