Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b8fe6943 authored by Patty's avatar Patty Committed by Automerger Merge Worker
Browse files

Parse audio config codec capability for LE devices am: ae425ca6

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

Change-Id: I7cab6bd9cc4bc2fbf6201c88b1f890a88a7c3bd2
parents b1e1f7b7 ae425ca6
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -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);
+129 −0
Original line number Diff line number Diff line
/*
 * 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);
        }
    }
}
+8 −8
Original line number Diff line number Diff line
@@ -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,7 +2282,9 @@ android_media_AudioSystem_getHwOffloadEncodingFormatsSupportedForA2DP(
        return (jint)AUDIO_JAVA_BAD_VALUE;
    }
    std::vector<audio_format_t> encodingFormats;
    status_t status = AudioSystem::getHwOffloadEncodingFormatsSupportedForA2DP(
    status_t status =
            AudioSystem::getHwOffloadFormatsSupportedForBluetoothMedia(static_cast<audio_devices_t>(
                                                                               deviceType),
                                                                       &encodingFormats);
    if (status != NO_ERROR) {
        ALOGE("%s: error %d", __FUNCTION__, 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",
+59 −0
Original line number Diff line number Diff line
/*
 * 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();

    }
}
+40 −13
Original line number Diff line number Diff line
@@ -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;
        }

        if (deviceType == AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) {
            for (Integer format : formatsList) {
                int btSourceCodec = AudioSystem.audioFormatToBluetoothSourceCodec(format);
            if (btSourceCodec
                    != BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID) {
                codecConfigList.add(new BluetoothCodecConfig(btSourceCodec));
                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
Loading