Parse audio config codec capability for LE devices am: ae425ca614

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1881112

Change-Id: I7cab6bd9cc4bc2fbf6201c88b1f890a88a7c3bd2
This commit is contained in:
Patty 2021-12-08 03:54:09 +00:00 committed by Automerger Merge Worker
commit b8fe694317
6 changed files with 288 additions and 25 deletions

View File

@ -9520,6 +9520,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);

View File

@ -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);
}
}
}

View File

@ -2273,10 +2273,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)) {
@ -2284,8 +2282,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);
@ -2810,8 +2810,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",

View File

@ -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();
}
}

View File

@ -32,6 +32,7 @@ import android.app.NotificationManager;
import android.app.PendingIntent;
import android.bluetooth.BluetoothCodecConfig;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeAudioCodecConfig;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
@ -6790,30 +6791,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

View File

@ -21,6 +21,7 @@ import android.annotation.NonNull;
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;
@ -229,6 +230,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 = {
@ -238,11 +242,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
@ -262,6 +281,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
@ -1754,10 +1788,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);