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

Commit 8dd599a6 authored by Trevor Knight's avatar Trevor Knight
Browse files

Add speakerChannelMask to AudioDevicePort and use it for new API

This CL adds a speakerChannelMask field to AudioDevicePort and uses it for AudioDeviceInfo.getSpeakerChannelMask(). This field represents the physical output speaker layout of the device, powered by a new AIDL field in AudioPortDeviceExt.aidl

The field is set by convertAudioPortFromNative.

Bug: 337522902
Test: m
Flag: android.media.audio.speaker_layout_api
Change-Id: I5a4a99d27538d192069b98bc0f921b88b0463e05
parent 3a74114a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -21521,6 +21521,7 @@ package android.media {
    method public int getId();
    method public CharSequence getProductName();
    method @NonNull public int[] getSampleRates();
    method @FlaggedApi("android.media.audio.speaker_layout_api") public int getSpeakerLayoutChannelMask();
    method public int getType();
    method public boolean isSink();
    method public boolean isSource();
+9 −3
Original line number Diff line number Diff line
@@ -109,6 +109,7 @@ static struct {
    // Valid only if an AudioDevicePort
    jfieldID    mType;
    jfieldID    mAddress;
    jfieldID mSpeakerLayoutChannelMask;
    // other fields unused by JNI
} gAudioPortFields;

@@ -1084,6 +1085,8 @@ static jint convertAudioPortConfigToNativeWithDevicePort(JNIEnv *env,
    strncpy(nAudioPortConfig->ext.device.address,
            nDeviceAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN - 1);
    env->ReleaseStringUTFChars(jDeviceAddress, nDeviceAddress);
    nAudioPortConfig->ext.device.speaker_layout_channel_mask = outChannelMaskToNative(
            env->GetIntField(jAudioDevicePort, gAudioPortFields.mSpeakerLayoutChannelMask));
    env->DeleteLocalRef(jDeviceAddress);
    env->DeleteLocalRef(jAudioDevicePort);
    return jStatus;
@@ -1541,10 +1544,12 @@ static jint convertAudioPortFromNative(JNIEnv *env, ScopedLocalRef<jobject> *jAu
                                                           .encapsulation_metadata_types));
        ALOGV("convertAudioPortFromNative is a device %08x", nAudioPort->ext.device.type);
        ScopedLocalRef<jstring> jAddress(env, env->NewStringUTF(nAudioPort->ext.device.address));
        int speakerLayoutChannelMask = outChannelMaskFromNative(
                nAudioPort->active_config.ext.device.speaker_layout_channel_mask);
        jAudioPort->reset(env->NewObject(gAudioDevicePortClass, gAudioDevicePortCstor,
                                         jHandle.get(), jDeviceName.get(), jAudioProfiles.get(),
                                         jGains.get(), nAudioPort->ext.device.type, jAddress.get(),
                                         jEncapsulationModes.get(),
                                         speakerLayoutChannelMask, jEncapsulationModes.get(),
                                         jEncapsulationMetadataTypes.get(),
                                         jAudioDescriptors.get()));
    } else if (nAudioPort->type == AUDIO_PORT_TYPE_MIX) {
@@ -3705,14 +3710,15 @@ int register_android_media_AudioSystem(JNIEnv *env)
    gAudioDevicePortCstor =
            GetMethodIDOrDie(env, audioDevicePortClass, "<init>",
                             "(Landroid/media/AudioHandle;Ljava/lang/String;Ljava/util/List;"
                             "[Landroid/media/AudioGain;ILjava/lang/String;[I[I"
                             "[Landroid/media/AudioGain;ILjava/lang/String;I[I[I"
                             "Ljava/util/List;)V");

    // When access AudioPort as AudioDevicePort
    gAudioPortFields.mType = GetFieldIDOrDie(env, audioDevicePortClass, "mType", "I");
    gAudioPortFields.mAddress = GetFieldIDOrDie(env, audioDevicePortClass, "mAddress",
            "Ljava/lang/String;");

    gAudioPortFields.mSpeakerLayoutChannelMask =
            GetFieldIDOrDie(env, audioDevicePortClass, "mSpeakerLayoutChannelMask", "I");
    jclass audioMixPortClass = FindClassOrDie(env, "android/media/AudioMixPort");
    gAudioMixPortClass = MakeGlobalRefOrDie(env, audioMixPortClass);
    gAudioMixPortCstor =
+14 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.media;

import static android.media.audio.Flags.FLAG_ENABLE_MULTICHANNEL_GROUP_DEVICE;
import static android.media.audio.Flags.FLAG_SPEAKER_LAYOUT_API;

import android.Manifest;
import android.annotation.FlaggedApi;
@@ -547,6 +548,19 @@ public final class AudioDeviceInfo {
        return counts;
    }

    /**
     * @return A ChannelMask representing the physical output speaker layout of the device.
     *
     * The layout channel mask only indicates which speaker channels are present, the
     * physical layout of the speakers should be informed by a standard for multi-channel
     * sound playback systems, such as ITU-R BS.2051.
     * @see AudioFormat
     */
    @FlaggedApi(FLAG_SPEAKER_LAYOUT_API)
    public int getSpeakerLayoutChannelMask() {
        return mPort.speakerLayoutChannelMask();
    }

    /**
     * @return An array of audio encodings (e.g. {@link AudioFormat#ENCODING_PCM_16BIT},
     * {@link AudioFormat#ENCODING_PCM_FLOAT}) supported by the audio device.
+40 −2
Original line number Diff line number Diff line
@@ -60,8 +60,27 @@ public class AudioDevicePort extends AudioPort {
                /* encapsulationMetadataTypes= */ null);
    }

    /** @hide */
    // TODO: b/316864909 - Remove this method once there's a way to fake audio device ports further
    // down the stack.
    @VisibleForTesting
    public static AudioDevicePort createForTesting(int speakerLayoutChannelMask) {
        return new AudioDevicePort(
                new AudioHandle(/* id= */ 0),
                /* name= */ "testAudioDevicePort",
                /* profiles= */ null,
                /* gains= */ null,
                /* type= */ AudioManager.DEVICE_OUT_SPEAKER,
                /* address= */ "testAddress",
                /* speakerLayoutChannelMask= */ speakerLayoutChannelMask,
                /* encapsulationModes= */ null,
                /* encapsulationMetadataTypes= */ null,
                /* descriptors= */ null);
    }

    private final int mType;
    private final String mAddress;
    private final int mSpeakerLayoutChannelMask;
    private final int[] mEncapsulationModes;
    private final int[] mEncapsulationMetadataTypes;

@@ -76,12 +95,20 @@ public class AudioDevicePort extends AudioPort {
             deviceName, samplingRates, channelMasks, channelIndexMasks, formats, gains);
        mType = type;
        mAddress = address;
        mSpeakerLayoutChannelMask = AudioFormat.CHANNEL_INVALID;
        mEncapsulationModes = encapsulationModes;
        mEncapsulationMetadataTypes = encapsulationMetadataTypes;
    }

    AudioDevicePort(AudioHandle handle, String deviceName, List<AudioProfile> profiles,
            AudioGain[] gains, int type, String address, int[] encapsulationModes,
    AudioDevicePort(
            AudioHandle handle,
            String deviceName,
            List<AudioProfile> profiles,
            AudioGain[] gains,
            int type,
            String address,
            int speakerLayoutChannelMask,
            int[] encapsulationModes,
            @AudioTrack.EncapsulationMetadataType int[] encapsulationMetadataTypes,
            List<AudioDescriptor> descriptors) {
        super(handle,
@@ -89,6 +116,7 @@ public class AudioDevicePort extends AudioPort {
                deviceName, profiles, gains, descriptors);
        mType = type;
        mAddress = address;
        mSpeakerLayoutChannelMask = speakerLayoutChannelMask;
        mEncapsulationModes = encapsulationModes;
        mEncapsulationMetadataTypes = encapsulationMetadataTypes;
    }
@@ -119,6 +147,16 @@ public class AudioDevicePort extends AudioPort {
        return mAddress;
    }

    /** Get the channel mask representing the physical output speaker layout of the device.
     *
     * The layout channel mask only indicates which speaker channels are present, the
     * physical layout of the speakers should be informed by a standard for multi-channel
     * sound playback systems, such as ITU-R BS.2051.
    */
    public int speakerLayoutChannelMask() {
        return mSpeakerLayoutChannelMask;
    }

    /**
     * Get supported encapsulation modes.
     */