diff options
| -rw-r--r-- | core/api/current.txt | 1 | ||||
| -rw-r--r-- | core/jni/android_media_AudioSystem.cpp | 12 | ||||
| -rw-r--r-- | media/java/android/media/AudioDeviceInfo.java | 14 | ||||
| -rw-r--r-- | media/java/android/media/AudioDevicePort.java | 42 |
4 files changed, 64 insertions, 5 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 4a2c998d9ebb..a03f8c5c167f 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -21557,6 +21557,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(); diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 8eaa7aa99a2d..3d9a19e129a8 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -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 = diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java index 2da8eecedc4d..b41f40f412d2 100644 --- a/media/java/android/media/AudioDeviceInfo.java +++ b/media/java/android/media/AudioDeviceInfo.java @@ -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; @@ -548,6 +549,19 @@ public final class AudioDeviceInfo { } /** + * @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. * <code>ENCODING_PCM_FLOAT</code> indicates the device supports more diff --git a/media/java/android/media/AudioDevicePort.java b/media/java/android/media/AudioDevicePort.java index ab5c54b5cd7e..f5913c763b82 100644 --- a/media/java/android/media/AudioDevicePort.java +++ b/media/java/android/media/AudioDevicePort.java @@ -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. */ |