Move common audio AIDL types to audio.media.audio.common

The following types are being moved from 'android.media':
 - AudioChannelLayout
 - AudioFormatDescription
 - AudioFormatType
 - PcmType

AudioChannelLayout replaces legacy-based AudioChannelMask type.
AudioFormatDescription replaces legacy-based AudioFormat type.
Updated conversion functions.

Bug: 188932434
Test: atest AidlConversionUnitTests
Test: atest SoundHw2CompatTest
Test: atest SoundTriggerMiddlewareImplTest
Change-Id: Id002177f6b7f651389b59b0f476e6e2d28be4592
diff --git a/core/java/android/hardware/soundtrigger/ConversionUtil.java b/core/java/android/hardware/soundtrigger/ConversionUtil.java
index 644385c..35a974b 100644
--- a/core/java/android/hardware/soundtrigger/ConversionUtil.java
+++ b/core/java/android/hardware/soundtrigger/ConversionUtil.java
@@ -198,7 +198,8 @@
             int modelHandle, int captureSession, RecognitionEvent aidlEvent) {
         // The API recognition event doesn't allow for a null audio format, even though it doesn't
         // always make sense. We thus replace it with a default.
-        AudioFormat audioFormat = aidl2apiAudioFormatWithDefault(aidlEvent.audioConfig);
+        AudioFormat audioFormat = aidl2apiAudioFormatWithDefault(
+                aidlEvent.audioConfig, true /*isInput*/);
         return new SoundTrigger.GenericRecognitionEvent(
                 aidlEvent.status,
                 modelHandle, aidlEvent.captureAvailable, captureSession,
@@ -216,7 +217,8 @@
         }
         // The API recognition event doesn't allow for a null audio format, even though it doesn't
         // always make sense. We thus replace it with a default.
-        AudioFormat audioFormat = aidl2apiAudioFormatWithDefault(aidlEvent.common.audioConfig);
+        AudioFormat audioFormat = aidl2apiAudioFormatWithDefault(
+                aidlEvent.common.audioConfig, true /*isInput*/);
         return new SoundTrigger.KeyphraseRecognitionEvent(aidlEvent.common.status, modelHandle,
                 aidlEvent.common.captureAvailable,
                 captureSession, aidlEvent.common.captureDelayMs,
@@ -226,9 +228,10 @@
     }
 
     // In case of a null input returns a non-null valid output.
-    public static AudioFormat aidl2apiAudioFormatWithDefault(@Nullable AudioConfig audioConfig) {
+    public static AudioFormat aidl2apiAudioFormatWithDefault(
+            @Nullable AudioConfig audioConfig, boolean isInput) {
         if (audioConfig != null) {
-            return AidlConversion.aidl2api_AudioConfig_AudioFormat(audioConfig);
+            return AidlConversion.aidl2api_AudioConfig_AudioFormat(audioConfig, isInput);
         }
         return new AudioFormat.Builder().build();
     }
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index f46aadf..4f76aad 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -162,6 +162,7 @@
                 "android_util_CharsetUtils.cpp",
                 "android_util_MemoryIntArray.cpp",
                 "android_util_Process.cpp",
+                "android_media_audio_common_AidlConversion.cpp",
                 "android_media_AudioDeviceAttributes.cpp",
                 "android_media_AudioEffectDescriptor.cpp",
                 "android_media_AudioRecord.cpp",
@@ -241,6 +242,7 @@
             ],
 
             shared_libs: [
+                "android.media.audio.common.types-V1-cpp",
                 "audioclient-types-aidl-cpp",
                 "audioflinger-aidl-cpp",
                 "av-types-aidl-cpp",
@@ -284,6 +286,7 @@
                 "libmediametrics",
                 "libmeminfo",
                 "libaudioclient",
+                "libaudioclient_aidl_conversion",
                 "libaudiofoundation",
                 "libaudiopolicy",
                 "libusbhost",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index aa9995d..09d5cb1 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -98,6 +98,7 @@
 extern int register_android_media_AudioVolumeGroupChangeHandler(JNIEnv *env);
 extern int register_android_media_MicrophoneInfo(JNIEnv *env);
 extern int register_android_media_ToneGenerator(JNIEnv *env);
+extern int register_android_media_audio_common_AidlConversion(JNIEnv* env);
 extern int register_android_media_midi(JNIEnv *env);
 
 namespace android {
@@ -1616,6 +1617,7 @@
         REG_JNI(register_android_media_MicrophoneInfo),
         REG_JNI(register_android_media_RemoteDisplay),
         REG_JNI(register_android_media_ToneGenerator),
+        REG_JNI(register_android_media_audio_common_AidlConversion),
         REG_JNI(register_android_media_midi),
 
         REG_JNI(register_android_opengl_classes),
diff --git a/core/jni/android_media_audio_common_AidlConversion.cpp b/core/jni/android_media_audio_common_AidlConversion.cpp
new file mode 100644
index 0000000..6dcaf76
--- /dev/null
+++ b/core/jni/android_media_audio_common_AidlConversion.cpp
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "AidlConversion"
+
+#include <android_os_Parcel.h>
+#include <binder/Parcel.h>
+#include <jni.h>
+#include <log/log.h>
+#include <media/AidlConversion.h>
+#include <system/audio.h>
+
+#include "core_jni_helpers.h"
+
+namespace {
+
+using namespace android;
+
+#define PACKAGE "android/media/audio/common"
+#define CLASSNAME PACKAGE "/AidlConversion"
+
+template <typename AidlType, typename ConvFunc>
+int aidl2legacy(JNIEnv* env, jobject clazz, jobject jParcel, const ConvFunc& conv,
+                int fallbackValue) {
+    if (Parcel* parcel = parcelForJavaObject(env, jParcel); parcel != nullptr) {
+        AidlType aidl{};
+        if (status_t status = aidl.readFromParcel(parcel); status == OK) {
+            auto legacy = conv(aidl);
+            if (legacy.ok()) {
+                return legacy.value();
+            }
+        } else {
+            ALOGE("aidl2legacy: Failed to read from parcel: %d", status);
+        }
+    } else {
+        ALOGE("aidl2legacy: Failed to retrieve the native parcel from Java parcel");
+    }
+    return fallbackValue;
+}
+
+template <typename LegacyType, typename ConvFunc>
+jobject legacy2aidl(JNIEnv* env, jobject clazz, LegacyType legacy, const ConvFunc& conv) {
+    auto aidl = conv(legacy);
+    if (!aidl.ok()) {
+        return 0;
+    }
+    if (jobject jParcel = createJavaParcelObject(env); jParcel != 0) {
+        if (Parcel* parcel = parcelForJavaObject(env, jParcel); parcel != nullptr) {
+            if (status_t status = aidl.value().writeToParcel(parcel); status == OK) {
+                parcel->setDataPosition(0);
+                return jParcel;
+            }
+        } else {
+            ALOGE("legacy2aidl: Failed to retrieve the native parcel from Java parcel");
+        }
+        env->DeleteLocalRef(jParcel);
+    } else {
+        ALOGE("legacy2aidl: Failed to create Java parcel");
+    }
+    return 0;
+}
+
+int aidl2legacy_AudioChannelLayout_Parcel_audio_channel_mask_t(JNIEnv* env, jobject clazz,
+                                                               jobject jParcel, jboolean isInput) {
+    return aidl2legacy<media::audio::common::AudioChannelLayout>(
+            env, clazz, jParcel,
+            [isInput](const media::audio::common::AudioChannelLayout& l) {
+                return aidl2legacy_AudioChannelLayout_audio_channel_mask_t(l, isInput);
+            },
+            AUDIO_CHANNEL_INVALID);
+}
+
+jobject legacy2aidl_audio_channel_mask_t_AudioChannelLayout_Parcel(
+        JNIEnv* env, jobject clazz, int /*audio_channel_mask_t*/ legacy, jboolean isInput) {
+    return legacy2aidl<audio_channel_mask_t>(
+            env, clazz, static_cast<audio_channel_mask_t>(legacy),
+            [isInput](audio_channel_mask_t m) {
+                return legacy2aidl_audio_channel_mask_t_AudioChannelLayout(m, isInput);
+            });
+}
+
+int aidl2legacy_AudioFormatDescription_Parcel_audio_format_t(JNIEnv* env, jobject clazz,
+                                                             jobject jParcel) {
+    return aidl2legacy<
+            media::audio::common::
+                    AudioFormatDescription>(env, clazz, jParcel,
+                                            aidl2legacy_AudioFormatDescription_audio_format_t,
+                                            AUDIO_FORMAT_INVALID);
+}
+
+jobject legacy2aidl_audio_format_t_AudioFormatDescription_Parcel(JNIEnv* env, jobject clazz,
+                                                                 int /*audio_format_t*/ legacy) {
+    return legacy2aidl<audio_format_t>(env, clazz, static_cast<audio_format_t>(legacy),
+                                       legacy2aidl_audio_format_t_AudioFormatDescription);
+}
+
+const JNINativeMethod gMethods[] = {
+        {"aidl2legacy_AudioChannelLayout_Parcel_audio_channel_mask_t", "(Landroid/os/Parcel;Z)I",
+         reinterpret_cast<void*>(aidl2legacy_AudioChannelLayout_Parcel_audio_channel_mask_t)},
+        {"legacy2aidl_audio_channel_mask_t_AudioChannelLayout_Parcel", "(IZ)Landroid/os/Parcel;",
+         reinterpret_cast<void*>(legacy2aidl_audio_channel_mask_t_AudioChannelLayout_Parcel)},
+        {"aidl2legacy_AudioFormatDescription_Parcel_audio_format_t", "(Landroid/os/Parcel;)I",
+         reinterpret_cast<void*>(aidl2legacy_AudioFormatDescription_Parcel_audio_format_t)},
+        {"legacy2aidl_audio_format_t_AudioFormatDescription_Parcel", "(I)Landroid/os/Parcel;",
+         reinterpret_cast<void*>(legacy2aidl_audio_format_t_AudioFormatDescription_Parcel)},
+};
+
+} // namespace
+
+int register_android_media_audio_common_AidlConversion(JNIEnv* env) {
+    return RegisterMethodsOrDie(env, CLASSNAME, gMethods, NELEM(gMethods));
+}
diff --git a/media/Android.bp b/media/Android.bp
index cf4a0b1..82d6160 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -35,6 +35,7 @@
         "aidl/android/media/soundtrigger_middleware/SoundTriggerModuleDescriptor.aidl",
     ],
     imports: [
+        "android.media.audio.common.types",
         "android.media.soundtrigger.types",
         "media_permission-aidl",
     ],
@@ -45,20 +46,29 @@
     vendor_available: true,
     host_supported: true,
     double_loadable: true,
-    flags: ["-Werror", "-Weverything", ],
+    flags: [
+        "-Werror",
+        "-Weverything",
+    ],
     local_include_dir: "aidl",
     srcs: [
-        "aidl/android/media/audio/common/AudioChannelMask.aidl",
+        "aidl/android/media/audio/common/AudioChannelLayout.aidl",
         "aidl/android/media/audio/common/AudioConfig.aidl",
-        "aidl/android/media/audio/common/AudioFormat.aidl",
+        "aidl/android/media/audio/common/AudioFormatDescription.aidl",
+        "aidl/android/media/audio/common/AudioFormatType.aidl",
         "aidl/android/media/audio/common/AudioOffloadInfo.aidl",
         "aidl/android/media/audio/common/AudioStreamType.aidl",
         "aidl/android/media/audio/common/AudioUsage.aidl",
+        "aidl/android/media/audio/common/PcmType.aidl",
     ],
     stability: "vintf",
     backend: {
         cpp: {
-            enabled: true,
+            min_sdk_version: "29",
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.media",
+            ],
         },
         java: {
             sdk_version: "module_current",
@@ -74,7 +84,10 @@
 aidl_interface {
     name: "android.media.soundtrigger.types",
     vendor_available: true,
-    flags: ["-Werror", "-Weverything", ],
+    flags: [
+        "-Werror",
+        "-Weverything",
+    ],
     local_include_dir: "aidl",
     srcs: [
         "aidl/android/media/soundtrigger/AudioCapabilities.aidl",
diff --git a/media/aidl/android/media/audio/common/AudioChannelLayout.aidl b/media/aidl/android/media/audio/common/AudioChannelLayout.aidl
new file mode 100644
index 0000000..4f34372
--- /dev/null
+++ b/media/aidl/android/media/audio/common/AudioChannelLayout.aidl
@@ -0,0 +1,278 @@
+/*
+ * 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.media.audio.common;
+
+/**
+ * This structure describes a layout of a multi-channel stream.
+ * There are two possible ways for representing a layout:
+ *
+ * - indexed mask, which tells what channels of an audio frame are used, but
+ *   doesn't label them in any way, thus a correspondence between channels in
+ *   the same position of frames originating from different streams must be
+ *   established externally;
+ *
+ * - layout mask, which gives a label to each channel, thus allowing to
+ *   match channels between streams of different layouts.
+ *
+ * Both representations are agnostic of the direction of audio transfer. Also,
+ * by construction, the number of bits set to '1' in the mask indicates the
+ * number of channels in the audio frame. A channel mask per se only defines the
+ * presence or absence of a channel, not the order. Please see 'INTERLEAVE_*'
+ * constants for the platform convention of order.
+ *
+ * The structure also defines a "voice mask" which is a special case of
+ * layout mask, intended for processing voice audio from telecommunication
+ * use cases.
+ *
+ * {@hide}
+ */
+@JavaDerive(equals = true, toString = true)
+@VintfStability
+union AudioChannelLayout {
+    /**
+     * This variant is used for representing the "null" ("none") value
+     * for the channel layout. The field value must always be '0'.
+     */
+    int none = 0;
+    /**
+     * This variant is used for indicating an "invalid" layout for use by the
+     * framework only. HAL implementations must not accept or emit
+     * AudioChannelLayout values for this variant. The field value must always
+     * be '0'.
+     */
+    int invalid = 0;
+    /**
+     * This variant is used for representing indexed masks. The mask indicates
+     * what channels are used. For example, the mask that specifies to use only
+     * channels 1 and 3 when interacting with a multi-channel device is defined
+     * as a combination of the 1st and the 3rd bits and thus is equal to 5. See
+     * also the 'INDEX_MASK_*' constants. The 'indexMask' field must have at
+     * least one bit set.
+     */
+    int indexMask;
+    /**
+     * This variant is used for representing layout masks.
+     * It is recommended to use one of 'LAYOUT_*' values. The 'layoutMask' field
+     * must have at least one bit set.
+     */
+    int layoutMask;
+    /**
+     * This variant is used for processing of voice audio input and output.
+     * It is recommended to use one of 'VOICE_*' values. The 'voiceMask' field
+     * must have at least one bit set.
+     */
+    int voiceMask;
+
+    /**
+     * 'INDEX_MASK_*' constants define how many channels are used.
+     * The mask constants below are 'canonical' masks. Each 'INDEX_MASK_N'
+     * constant declares that all N channels are used and arranges
+     * them starting from the LSB.
+     */
+    const int INDEX_MASK_1 = (1 << 1) - 1;
+    const int INDEX_MASK_2 = (1 << 2) - 1;
+    const int INDEX_MASK_3 = (1 << 3) - 1;
+    const int INDEX_MASK_4 = (1 << 4) - 1;
+    const int INDEX_MASK_5 = (1 << 5) - 1;
+    const int INDEX_MASK_6 = (1 << 6) - 1;
+    const int INDEX_MASK_7 = (1 << 7) - 1;
+    const int INDEX_MASK_8 = (1 << 8) - 1;
+    const int INDEX_MASK_9 = (1 << 9) - 1;
+    const int INDEX_MASK_10 = (1 << 10) - 1;
+    const int INDEX_MASK_11 = (1 << 11) - 1;
+    const int INDEX_MASK_12 = (1 << 12) - 1;
+    const int INDEX_MASK_13 = (1 << 13) - 1;
+    const int INDEX_MASK_14 = (1 << 14) - 1;
+    const int INDEX_MASK_15 = (1 << 15) - 1;
+    const int INDEX_MASK_16 = (1 << 16) - 1;
+    const int INDEX_MASK_17 = (1 << 17) - 1;
+    const int INDEX_MASK_18 = (1 << 18) - 1;
+    const int INDEX_MASK_19 = (1 << 19) - 1;
+    const int INDEX_MASK_20 = (1 << 20) - 1;
+    const int INDEX_MASK_21 = (1 << 21) - 1;
+    const int INDEX_MASK_22 = (1 << 22) - 1;
+    const int INDEX_MASK_23 = (1 << 23) - 1;
+    const int INDEX_MASK_24 = (1 << 24) - 1;
+
+    /**
+     * 'LAYOUT_*' constants define channel layouts recognized by
+     * the audio system. The order of the channels in the frame is assumed
+     * to be from the LSB to MSB for all the bits set to '1'.
+     */
+    const int LAYOUT_MONO = CHANNEL_FRONT_LEFT;
+    const int LAYOUT_STEREO =
+            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT;
+    const int LAYOUT_2POINT1 =
+            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_LOW_FREQUENCY;
+    const int LAYOUT_TRI =
+            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_FRONT_CENTER;
+    const int LAYOUT_TRI_BACK =
+            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_BACK_CENTER;
+    const int LAYOUT_3POINT1 =
+            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_FRONT_CENTER |
+            CHANNEL_LOW_FREQUENCY;
+    const int LAYOUT_2POINT0POINT2 =
+            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
+            CHANNEL_TOP_SIDE_LEFT | CHANNEL_TOP_SIDE_RIGHT;
+    const int LAYOUT_2POINT1POINT2 =
+            LAYOUT_2POINT0POINT2 | CHANNEL_LOW_FREQUENCY;
+    const int LAYOUT_3POINT0POINT2 =
+            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
+            CHANNEL_FRONT_CENTER |
+            CHANNEL_TOP_SIDE_LEFT | CHANNEL_TOP_SIDE_RIGHT;
+    const int LAYOUT_3POINT1POINT2 =
+            LAYOUT_3POINT0POINT2 | CHANNEL_LOW_FREQUENCY;
+    const int LAYOUT_QUAD =
+            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
+            CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT;
+    const int LAYOUT_QUAD_SIDE =
+            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
+            CHANNEL_SIDE_LEFT | CHANNEL_SIDE_RIGHT;
+    const int LAYOUT_SURROUND =
+            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
+            CHANNEL_FRONT_CENTER | CHANNEL_BACK_CENTER;
+    const int LAYOUT_PENTA = LAYOUT_QUAD | CHANNEL_FRONT_CENTER;
+    const int LAYOUT_5POINT1 =
+            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
+            CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY |
+            CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT;
+    const int LAYOUT_5POINT1_SIDE =
+            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
+            CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY |
+            CHANNEL_SIDE_LEFT | CHANNEL_SIDE_RIGHT;
+    const int LAYOUT_5POINT1POINT2 = LAYOUT_5POINT1 |
+            CHANNEL_TOP_SIDE_LEFT | CHANNEL_TOP_SIDE_RIGHT;
+    const int LAYOUT_5POINT1POINT4 = LAYOUT_5POINT1 |
+            CHANNEL_TOP_FRONT_LEFT | CHANNEL_TOP_FRONT_RIGHT |
+            CHANNEL_TOP_BACK_LEFT | CHANNEL_TOP_BACK_RIGHT;
+    const int LAYOUT_6POINT1 =
+            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
+            CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY |
+            CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT | CHANNEL_BACK_CENTER;
+    const int LAYOUT_7POINT1 = LAYOUT_5POINT1 |
+            CHANNEL_SIDE_LEFT | CHANNEL_SIDE_RIGHT;
+    const int LAYOUT_7POINT1POINT2 = LAYOUT_7POINT1 |
+            CHANNEL_TOP_SIDE_LEFT | CHANNEL_TOP_SIDE_RIGHT;
+    const int LAYOUT_7POINT1POINT4 = LAYOUT_7POINT1 |
+            CHANNEL_TOP_FRONT_LEFT | CHANNEL_TOP_FRONT_RIGHT |
+            CHANNEL_TOP_BACK_LEFT | CHANNEL_TOP_BACK_RIGHT;
+    const int LAYOUT_9POINT1POINT4 = LAYOUT_7POINT1POINT4 |
+            CHANNEL_FRONT_WIDE_LEFT | CHANNEL_FRONT_WIDE_RIGHT;
+    const int LAYOUT_9POINT1POINT6 = LAYOUT_9POINT1POINT4 |
+            CHANNEL_TOP_SIDE_LEFT | CHANNEL_TOP_SIDE_RIGHT;
+    const int LAYOUT_13POINT_360RA =
+            CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
+            CHANNEL_FRONT_CENTER |
+            CHANNEL_SIDE_LEFT | CHANNEL_SIDE_RIGHT |
+            CHANNEL_TOP_FRONT_LEFT | CHANNEL_TOP_FRONT_RIGHT |
+            CHANNEL_TOP_FRONT_CENTER |
+            CHANNEL_TOP_BACK_LEFT | CHANNEL_TOP_BACK_RIGHT |
+            CHANNEL_BOTTOM_FRONT_LEFT | CHANNEL_BOTTOM_FRONT_RIGHT |
+            CHANNEL_BOTTOM_FRONT_CENTER;
+    const int LAYOUT_22POINT2 = LAYOUT_7POINT1POINT4 |
+            CHANNEL_FRONT_LEFT_OF_CENTER | CHANNEL_FRONT_RIGHT_OF_CENTER |
+            CHANNEL_BACK_CENTER | CHANNEL_TOP_CENTER |
+            CHANNEL_TOP_FRONT_CENTER | CHANNEL_TOP_BACK_CENTER |
+            CHANNEL_TOP_SIDE_LEFT | CHANNEL_TOP_SIDE_RIGHT |
+            CHANNEL_BOTTOM_FRONT_LEFT | CHANNEL_BOTTOM_FRONT_RIGHT |
+            CHANNEL_BOTTOM_FRONT_CENTER |
+            CHANNEL_LOW_FREQUENCY_2;
+    const int LAYOUT_MONO_HAPTIC_A =
+            LAYOUT_MONO | CHANNEL_HAPTIC_A;
+    const int LAYOUT_STEREO_HAPTIC_A =
+            LAYOUT_STEREO | CHANNEL_HAPTIC_A;
+    const int LAYOUT_HAPTIC_AB =
+            CHANNEL_HAPTIC_A | CHANNEL_HAPTIC_B;
+    const int LAYOUT_MONO_HAPTIC_AB =
+            LAYOUT_MONO | LAYOUT_HAPTIC_AB;
+    const int LAYOUT_STEREO_HAPTIC_AB =
+            LAYOUT_STEREO | LAYOUT_HAPTIC_AB;
+    const int LAYOUT_FRONT_BACK =
+            CHANNEL_FRONT_CENTER | CHANNEL_BACK_CENTER;
+
+    /**
+     * Expresses the convention when stereo audio samples are stored interleaved
+     * in an array.  This should improve readability by allowing code to use
+     * symbolic indices instead of hard-coded [0] and [1].
+     *
+     * For multi-channel beyond stereo, the platform convention is that channels
+     * are interleaved in order from least significant channel mask bit to most
+     * significant channel mask bit, with unused bits skipped. Any exceptions
+     * to this convention will be noted at the appropriate API.
+     */
+    const int INTERLEAVE_LEFT = 0;
+    const int INTERLEAVE_RIGHT = 1;
+
+    /**
+     * 'CHANNEL_*' constants are used to build 'LAYOUT_*' masks. Each constant
+     * must have exactly one bit set. The values do not match
+     * 'android.media.AudioFormat.CHANNEL_OUT_*' constants from the SDK
+     * for better efficiency in masks processing.
+     */
+    const int CHANNEL_FRONT_LEFT = 1 << 0;
+    const int CHANNEL_FRONT_RIGHT = 1 << 1;
+    const int CHANNEL_FRONT_CENTER = 1 << 2;
+    const int CHANNEL_LOW_FREQUENCY = 1 << 3;
+    const int CHANNEL_BACK_LEFT = 1 << 4;
+    const int CHANNEL_BACK_RIGHT = 1 << 5;
+    const int CHANNEL_FRONT_LEFT_OF_CENTER = 1 << 6;
+    const int CHANNEL_FRONT_RIGHT_OF_CENTER = 1 << 7;
+    const int CHANNEL_BACK_CENTER = 1 << 8;
+    const int CHANNEL_SIDE_LEFT = 1 << 9;
+    const int CHANNEL_SIDE_RIGHT = 1 << 10;
+    const int CHANNEL_TOP_CENTER = 1 << 11;
+    const int CHANNEL_TOP_FRONT_LEFT = 1 << 12;
+    const int CHANNEL_TOP_FRONT_CENTER = 1 << 13;
+    const int CHANNEL_TOP_FRONT_RIGHT = 1 << 14;
+    const int CHANNEL_TOP_BACK_LEFT = 1 << 15;
+    const int CHANNEL_TOP_BACK_CENTER = 1 << 16;
+    const int CHANNEL_TOP_BACK_RIGHT = 1 << 17;
+    const int CHANNEL_TOP_SIDE_LEFT = 1 << 18;
+    const int CHANNEL_TOP_SIDE_RIGHT = 1 << 19;
+    const int CHANNEL_BOTTOM_FRONT_LEFT = 1 << 20;
+    const int CHANNEL_BOTTOM_FRONT_CENTER = 1 << 21;
+    const int CHANNEL_BOTTOM_FRONT_RIGHT = 1 << 22;
+    const int CHANNEL_LOW_FREQUENCY_2 = 1 << 23;
+    const int CHANNEL_FRONT_WIDE_LEFT = 1 << 24;
+    const int CHANNEL_FRONT_WIDE_RIGHT = 1 << 25;
+    /**
+     * Haptic channels are not part of multichannel standards, however they
+     * enhance user experience when playing so they are packed together with the
+     * channels of the program. To avoid collision with positional channels the
+     * values for haptic channels start at the MSB of an integer (after the sign
+     * bit) and move down to LSB.
+     */
+    const int CHANNEL_HAPTIC_B = 1 << 29;
+    const int CHANNEL_HAPTIC_A = 1 << 30;
+
+    /**
+     * 'VOICE_*' constants define layouts for voice audio. The order of the
+     * channels in the frame is assumed to be from the LSB to MSB for all the
+     * bits set to '1'.
+     */
+    const int VOICE_UPLINK_MONO = CHANNEL_VOICE_UPLINK;
+    const int VOICE_DNLINK_MONO = CHANNEL_VOICE_DNLINK;
+    const int VOICE_CALL_MONO = CHANNEL_VOICE_UPLINK | CHANNEL_VOICE_DNLINK;
+
+    /**
+     * 'CHANNEL_VOICE_*' constants are used to build 'VOICE_*' masks. Each
+     * constant must have exactly one bit set. Use the same values as
+     * 'android.media.AudioFormat.CHANNEL_IN_VOICE_*' constants from the SDK.
+     */
+    const int CHANNEL_VOICE_UPLINK = 0x4000;
+    const int CHANNEL_VOICE_DNLINK = 0x8000;
+}
diff --git a/media/aidl/android/media/audio/common/AudioChannelMask.aidl b/media/aidl/android/media/audio/common/AudioChannelMask.aidl
deleted file mode 100644
index 17be8dd..0000000
--- a/media/aidl/android/media/audio/common/AudioChannelMask.aidl
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
- // This file has been semi-automatically generated using hidl2aidl from its counterpart in
- // hardware/interfaces/audio/common/5.0/types.hal
-
-package android.media.audio.common;
-
-/**
- * A channel mask per se only defines the presence or absence of a channel, not
- * the order.
- *
- * The channel order convention is that channels are interleaved in order from
- * least significant channel mask bit to most significant channel mask bit,
- * with unused bits skipped. For example for stereo, LEFT would be first,
- * followed by RIGHT.
- * Any exceptions to this convention are noted at the appropriate API.
- *
- * AudioChannelMask is an opaque type and its internal layout should not be
- * assumed as it may change in the future.  Instead, always use functions
- * to examine it.
- *
- * These are the current representations:
- *
- *   REPRESENTATION_POSITION
- *     is a channel mask representation for position assignment.  Each low-order
- *     bit corresponds to the spatial position of a transducer (output), or
- *     interpretation of channel (input).  The user of a channel mask needs to
- *     know the context of whether it is for output or input.  The constants
- *     OUT_* or IN_* apply to the bits portion.  It is not permitted for no bits
- *     to be set.
- *
- *   REPRESENTATION_INDEX
- *     is a channel mask representation for index assignment.  Each low-order
- *     bit corresponds to a selected channel.  There is no platform
- *     interpretation of the various bits.  There is no concept of output or
- *     input.  It is not permitted for no bits to be set.
- *
- * All other representations are reserved for future use.
- *
- * Warning: current representation distinguishes between input and output, but
- * this will not the be case in future revisions of the platform. Wherever there
- * is an ambiguity between input and output that is currently resolved by
- * checking the channel mask, the implementer should look for ways to fix it
- * with additional information outside of the mask.
- *
- * TODO: this should be replaced with strings or other mechanisms that are easy to extend, in line
- *     with the audio HAL conventions.
- * {@hide}
- */
-@VintfStability
-@Backing(type="int")
-enum AudioChannelMask {
-    /**
-     * must be 0 for compatibility
-     */
-    REPRESENTATION_POSITION = 0,
-    /**
-     * 1 is reserved for future use
-     */
-    REPRESENTATION_INDEX = 2,
-    /**
-     * 3 is reserved for future use
-     *
-     *
-     * These can be a complete value of AudioChannelMask
-     */
-    NONE = 0x0,
-    INVALID = 0xC0000000,
-    /**
-     * These can be the bits portion of an AudioChannelMask
-     * with representation REPRESENTATION_POSITION.
-     *
-     *
-     * output channels
-     */
-    OUT_FRONT_LEFT = 0x1,
-    OUT_FRONT_RIGHT = 0x2,
-    OUT_FRONT_CENTER = 0x4,
-    OUT_LOW_FREQUENCY = 0x8,
-    OUT_BACK_LEFT = 0x10,
-    OUT_BACK_RIGHT = 0x20,
-    OUT_FRONT_LEFT_OF_CENTER = 0x40,
-    OUT_FRONT_RIGHT_OF_CENTER = 0x80,
-    OUT_BACK_CENTER = 0x100,
-    OUT_SIDE_LEFT = 0x200,
-    OUT_SIDE_RIGHT = 0x400,
-    OUT_TOP_CENTER = 0x800,
-    OUT_TOP_FRONT_LEFT = 0x1000,
-    OUT_TOP_FRONT_CENTER = 0x2000,
-    OUT_TOP_FRONT_RIGHT = 0x4000,
-    OUT_TOP_BACK_LEFT = 0x8000,
-    OUT_TOP_BACK_CENTER = 0x10000,
-    OUT_TOP_BACK_RIGHT = 0x20000,
-    OUT_TOP_SIDE_LEFT = 0x40000,
-    OUT_TOP_SIDE_RIGHT = 0x80000,
-    /**
-     * Haptic channel characteristics are specific to a device and
-     * only used to play device specific resources (eg: ringtones).
-     * The HAL can freely map A and B to haptic controllers, the
-     * framework shall not interpret those values and forward them
-     * from the device audio assets.
-     */
-    OUT_HAPTIC_A = 0x20000000,
-    OUT_HAPTIC_B = 0x10000000,
-
-    OUT_MONO = OUT_FRONT_LEFT,
-    OUT_STEREO = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT),
-    OUT_2POINT1 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_LOW_FREQUENCY),
-    OUT_2POINT0POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT),
-    OUT_2POINT1POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT | OUT_LOW_FREQUENCY),
-    OUT_3POINT0POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_FRONT_CENTER | OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT),
-    OUT_3POINT1POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_FRONT_CENTER | OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT | OUT_LOW_FREQUENCY),
-    OUT_QUAD = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_BACK_LEFT | OUT_BACK_RIGHT),
-    OUT_QUAD_BACK = OUT_QUAD,
-    /**
-     * like OUT_QUAD_BACK with *_SIDE_* instead of *_BACK_*
-     */
-    OUT_QUAD_SIDE = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_SIDE_LEFT | OUT_SIDE_RIGHT),
-    OUT_SURROUND = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_FRONT_CENTER | OUT_BACK_CENTER),
-    OUT_PENTA = (OUT_QUAD | OUT_FRONT_CENTER),
-    OUT_5POINT1 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_FRONT_CENTER | OUT_LOW_FREQUENCY | OUT_BACK_LEFT | OUT_BACK_RIGHT),
-    OUT_5POINT1_BACK = OUT_5POINT1,
-    /**
-     * like OUT_5POINT1_BACK with *_SIDE_* instead of *_BACK_*
-     */
-    OUT_5POINT1_SIDE = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_FRONT_CENTER | OUT_LOW_FREQUENCY | OUT_SIDE_LEFT | OUT_SIDE_RIGHT),
-    OUT_5POINT1POINT2 = (OUT_5POINT1 | OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT),
-    OUT_5POINT1POINT4 = (OUT_5POINT1 | OUT_TOP_FRONT_LEFT | OUT_TOP_FRONT_RIGHT | OUT_TOP_BACK_LEFT | OUT_TOP_BACK_RIGHT),
-    OUT_6POINT1 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_FRONT_CENTER | OUT_LOW_FREQUENCY | OUT_BACK_LEFT | OUT_BACK_RIGHT | OUT_BACK_CENTER),
-    /**
-     * matches the correct AudioFormat.CHANNEL_OUT_7POINT1_SURROUND
-     */
-    OUT_7POINT1 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_FRONT_CENTER | OUT_LOW_FREQUENCY | OUT_BACK_LEFT | OUT_BACK_RIGHT | OUT_SIDE_LEFT | OUT_SIDE_RIGHT),
-    OUT_7POINT1POINT2 = (OUT_7POINT1 | OUT_TOP_SIDE_LEFT | OUT_TOP_SIDE_RIGHT),
-    OUT_7POINT1POINT4 = (OUT_7POINT1 | OUT_TOP_FRONT_LEFT | OUT_TOP_FRONT_RIGHT | OUT_TOP_BACK_LEFT | OUT_TOP_BACK_RIGHT),
-    OUT_MONO_HAPTIC_A = (OUT_FRONT_LEFT | OUT_HAPTIC_A),
-    OUT_STEREO_HAPTIC_A = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_HAPTIC_A),
-    OUT_HAPTIC_AB = (OUT_HAPTIC_A | OUT_HAPTIC_B),
-    OUT_MONO_HAPTIC_AB = (OUT_FRONT_LEFT | OUT_HAPTIC_A | OUT_HAPTIC_B),
-    OUT_STEREO_HAPTIC_AB = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_HAPTIC_A | OUT_HAPTIC_B),
-
-    /**
-     * These are bits only, not complete values
-     *
-     *
-     * input channels
-     */
-    IN_LEFT = 0x4,
-    IN_RIGHT = 0x8,
-    IN_FRONT = 0x10,
-    IN_BACK = 0x20,
-    IN_LEFT_PROCESSED = 0x40,
-    IN_RIGHT_PROCESSED = 0x80,
-    IN_FRONT_PROCESSED = 0x100,
-    IN_BACK_PROCESSED = 0x200,
-    IN_PRESSURE = 0x400,
-    IN_X_AXIS = 0x800,
-    IN_Y_AXIS = 0x1000,
-    IN_Z_AXIS = 0x2000,
-    IN_BACK_LEFT = 0x10000,
-    IN_BACK_RIGHT = 0x20000,
-    IN_CENTER = 0x40000,
-    IN_LOW_FREQUENCY = 0x100000,
-    IN_TOP_LEFT = 0x200000,
-    IN_TOP_RIGHT = 0x400000,
-    IN_VOICE_UPLINK = 0x4000,
-    IN_VOICE_DNLINK = 0x8000,
-// TODO(ytai): Aliases not currently supported in AIDL - can inline the values.
-//    IN_MONO = IN_FRONT,
-//    IN_STEREO = (IN_LEFT | IN_RIGHT),
-//    IN_FRONT_BACK = (IN_FRONT | IN_BACK),
-//    IN_6 = (IN_LEFT | IN_RIGHT | IN_FRONT | IN_BACK | IN_LEFT_PROCESSED | IN_RIGHT_PROCESSED),
-//    IN_2POINT0POINT2 = (IN_LEFT | IN_RIGHT | IN_TOP_LEFT | IN_TOP_RIGHT),
-//    IN_2POINT1POINT2 = (IN_LEFT | IN_RIGHT | IN_TOP_LEFT | IN_TOP_RIGHT | IN_LOW_FREQUENCY),
-//    IN_3POINT0POINT2 = (IN_LEFT | IN_CENTER | IN_RIGHT | IN_TOP_LEFT | IN_TOP_RIGHT),
-//    IN_3POINT1POINT2 = (IN_LEFT | IN_CENTER | IN_RIGHT | IN_TOP_LEFT | IN_TOP_RIGHT | IN_LOW_FREQUENCY),
-//    IN_5POINT1 = (IN_LEFT | IN_CENTER | IN_RIGHT | IN_BACK_LEFT | IN_BACK_RIGHT | IN_LOW_FREQUENCY),
-//    IN_VOICE_UPLINK_MONO = (IN_VOICE_UPLINK | IN_MONO),
-//    IN_VOICE_DNLINK_MONO = (IN_VOICE_DNLINK | IN_MONO),
-//    IN_VOICE_CALL_MONO = (IN_VOICE_UPLINK_MONO | IN_VOICE_DNLINK_MONO),
-//    COUNT_MAX = 30,
-//    INDEX_HDR = REPRESENTATION_INDEX << COUNT_MAX,
-//    INDEX_MASK_1 = INDEX_HDR | ((1 << 1) - 1),
-//    INDEX_MASK_2 = INDEX_HDR | ((1 << 2) - 1),
-//    INDEX_MASK_3 = INDEX_HDR | ((1 << 3) - 1),
-//    INDEX_MASK_4 = INDEX_HDR | ((1 << 4) - 1),
-//    INDEX_MASK_5 = INDEX_HDR | ((1 << 5) - 1),
-//    INDEX_MASK_6 = INDEX_HDR | ((1 << 6) - 1),
-//    INDEX_MASK_7 = INDEX_HDR | ((1 << 7) - 1),
-//    INDEX_MASK_8 = INDEX_HDR | ((1 << 8) - 1),
-//    INDEX_MASK_9 = INDEX_HDR | ((1 << 9) - 1),
-//    INDEX_MASK_10 = INDEX_HDR | ((1 << 10) - 1),
-//    INDEX_MASK_11 = INDEX_HDR | ((1 << 11) - 1),
-//    INDEX_MASK_12 = INDEX_HDR | ((1 << 12) - 1),
-//    INDEX_MASK_13 = INDEX_HDR | ((1 << 13) - 1),
-//    INDEX_MASK_14 = INDEX_HDR | ((1 << 14) - 1),
-//    INDEX_MASK_15 = INDEX_HDR | ((1 << 15) - 1),
-//    INDEX_MASK_16 = INDEX_HDR | ((1 << 16) - 1),
-//    INDEX_MASK_17 = INDEX_HDR | ((1 << 17) - 1),
-//    INDEX_MASK_18 = INDEX_HDR | ((1 << 18) - 1),
-//    INDEX_MASK_19 = INDEX_HDR | ((1 << 19) - 1),
-//    INDEX_MASK_20 = INDEX_HDR | ((1 << 20) - 1),
-//    INDEX_MASK_21 = INDEX_HDR | ((1 << 21) - 1),
-//    INDEX_MASK_22 = INDEX_HDR | ((1 << 22) - 1),
-//    INDEX_MASK_23 = INDEX_HDR | ((1 << 23) - 1),
-//    INDEX_MASK_24 = INDEX_HDR | ((1 << 24) - 1),
-}
diff --git a/media/aidl/android/media/audio/common/AudioConfig.aidl b/media/aidl/android/media/audio/common/AudioConfig.aidl
index d128561..4a264d8 100644
--- a/media/aidl/android/media/audio/common/AudioConfig.aidl
+++ b/media/aidl/android/media/audio/common/AudioConfig.aidl
@@ -14,12 +14,10 @@
  * limitations under the License.
  */
 
- // This file has been semi-automatically generated using hidl2aidl from its counterpart in
- // hardware/interfaces/audio/common/5.0/types.hal
-
 package android.media.audio.common;
 
-import android.media.audio.common.AudioFormat;
+import android.media.audio.common.AudioChannelLayout;
+import android.media.audio.common.AudioFormatDescription;
 import android.media.audio.common.AudioOffloadInfo;
 
 /**
@@ -31,8 +29,8 @@
 @VintfStability
 parcelable AudioConfig {
     int sampleRateHz;
-    int channelMask;
-    AudioFormat format = AudioFormat.INVALID;
+    AudioChannelLayout channelMask;
+    AudioFormatDescription format;
     AudioOffloadInfo offloadInfo;
     long frameCount;
 }
diff --git a/media/aidl/android/media/audio/common/AudioFormat.aidl b/media/aidl/android/media/audio/common/AudioFormat.aidl
deleted file mode 100644
index 73fbca2..0000000
--- a/media/aidl/android/media/audio/common/AudioFormat.aidl
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
- // This file has been semi-automatically generated using hidl2aidl from its counterpart in
- // hardware/interfaces/audio/common/5.0/types.hal
-
-package android.media.audio.common;
-
-/**
- * Audio format  is a 32-bit word that consists of:
- *   main format field (upper 8 bits)
- *   sub format field (lower 24 bits).
- *
- * The main format indicates the main codec type. The sub format field indicates
- * options and parameters for each format. The sub format is mainly used for
- * record to indicate for instance the requested bitrate or profile.  It can
- * also be used for certain formats to give informations not present in the
- * encoded audio stream (e.g. octet alignement for AMR).
- *
- * {@hide}
- */
-@VintfStability
-@Backing(type="int")
-enum AudioFormat {
-   INVALID = 0xFFFFFFFF,
-   DEFAULT = 0,
-   PCM = 0x00000000,
-   MP3 = 0x01000000,
-   AMR_NB = 0x02000000,
-   AMR_WB = 0x03000000,
-   AAC = 0x04000000,
-   /**
-    * Deprecated, Use AAC_HE_V1
-    */
-   HE_AAC_V1 = 0x05000000,
-   /**
-    * Deprecated, Use AAC_HE_V2
-    */
-   HE_AAC_V2 = 0x06000000,
-   VORBIS = 0x07000000,
-   OPUS = 0x08000000,
-   AC3 = 0x09000000,
-   E_AC3 = 0x0A000000,
-   DTS = 0x0B000000,
-   DTS_HD = 0x0C000000,
-   /**
-    * IEC61937 is encoded audio wrapped in 16-bit PCM.
-    */
-   IEC61937 = 0x0D000000,
-   DOLBY_TRUEHD = 0x0E000000,
-   EVRC = 0x10000000,
-   EVRCB = 0x11000000,
-   EVRCWB = 0x12000000,
-   EVRCNW = 0x13000000,
-   AAC_ADIF = 0x14000000,
-   WMA = 0x15000000,
-   WMA_PRO = 0x16000000,
-   AMR_WB_PLUS = 0x17000000,
-   MP2 = 0x18000000,
-   QCELP = 0x19000000,
-   DSD = 0x1A000000,
-   FLAC = 0x1B000000,
-   ALAC = 0x1C000000,
-   APE = 0x1D000000,
-   AAC_ADTS = 0x1E000000,
-   SBC = 0x1F000000,
-   APTX = 0x20000000,
-   APTX_HD = 0x21000000,
-   AC4 = 0x22000000,
-   LDAC = 0x23000000,
-   /**
-    * Dolby Metadata-enhanced Audio Transmission
-    */
-   MAT = 0x24000000,
-   AAC_LATM = 0x25000000,
-   CELT = 0x26000000,
-   APTX_ADAPTIVE = 0x27000000,
-   LHDC = 0x28000000,
-   LHDC_LL = 0x29000000,
-   APTX_TWSP = 0x2A000000,
-   /**
-    * Deprecated
-    */
-   MAIN_MASK = 0xFF000000,
-   SUB_MASK = 0x00FFFFFF,
-   /**
-    * Subformats
-    */
-   PCM_SUB_16_BIT = 0x1,
-   PCM_SUB_8_BIT = 0x2,
-   PCM_SUB_32_BIT = 0x3,
-   PCM_SUB_8_24_BIT = 0x4,
-   PCM_SUB_FLOAT = 0x5,
-   PCM_SUB_24_BIT_PACKED = 0x6,
-   MP3_SUB_NONE = 0x0,
-   AMR_SUB_NONE = 0x0,
-   AAC_SUB_MAIN = 0x1,
-   AAC_SUB_LC = 0x2,
-   AAC_SUB_SSR = 0x4,
-   AAC_SUB_LTP = 0x8,
-   AAC_SUB_HE_V1 = 0x10,
-   AAC_SUB_SCALABLE = 0x20,
-   AAC_SUB_ERLC = 0x40,
-   AAC_SUB_LD = 0x80,
-   AAC_SUB_HE_V2 = 0x100,
-   AAC_SUB_ELD = 0x200,
-   AAC_SUB_XHE = 0x300,
-   VORBIS_SUB_NONE = 0x0,
-   E_AC3_SUB_JOC = 0x1,
-   MAT_SUB_1_0 = 0x1,
-   MAT_SUB_2_0 = 0x2,
-   MAT_SUB_2_1 = 0x3,
-// TODO(ytai): Aliases not currently supported in AIDL - can inline the values.
-//   /**
-//    * Aliases
-//    *
-//    *
-//    * note != AudioFormat.ENCODING_PCM_16BIT
-//    */
-//   PCM_16_BIT = (PCM | PCM_SUB_16_BIT),
-//   /**
-//    * note != AudioFormat.ENCODING_PCM_8BIT
-//    */
-//   PCM_8_BIT = (PCM | PCM_SUB_8_BIT),
-//   PCM_32_BIT = (PCM | PCM_SUB_32_BIT),
-//   PCM_8_24_BIT = (PCM | PCM_SUB_8_24_BIT),
-//   PCM_FLOAT = (PCM | PCM_SUB_FLOAT),
-//   PCM_24_BIT_PACKED = (PCM | PCM_SUB_24_BIT_PACKED),
-//   AAC_MAIN = (AAC | AAC_SUB_MAIN),
-//   AAC_LC = (AAC | AAC_SUB_LC),
-//   AAC_SSR = (AAC | AAC_SUB_SSR),
-//   AAC_LTP = (AAC | AAC_SUB_LTP),
-//   AAC_HE_V1 = (AAC | AAC_SUB_HE_V1),
-//   AAC_SCALABLE = (AAC | AAC_SUB_SCALABLE),
-//   AAC_ERLC = (AAC | AAC_SUB_ERLC),
-//   AAC_LD = (AAC | AAC_SUB_LD),
-//   AAC_HE_V2 = (AAC | AAC_SUB_HE_V2),
-//   AAC_ELD = (AAC | AAC_SUB_ELD),
-//   AAC_XHE = (AAC | AAC_SUB_XHE),
-//   AAC_ADTS_MAIN = (AAC_ADTS | AAC_SUB_MAIN),
-//   AAC_ADTS_LC = (AAC_ADTS | AAC_SUB_LC),
-//   AAC_ADTS_SSR = (AAC_ADTS | AAC_SUB_SSR),
-//   AAC_ADTS_LTP = (AAC_ADTS | AAC_SUB_LTP),
-//   AAC_ADTS_HE_V1 = (AAC_ADTS | AAC_SUB_HE_V1),
-//   AAC_ADTS_SCALABLE = (AAC_ADTS | AAC_SUB_SCALABLE),
-//   AAC_ADTS_ERLC = (AAC_ADTS | AAC_SUB_ERLC),
-//   AAC_ADTS_LD = (AAC_ADTS | AAC_SUB_LD),
-//   AAC_ADTS_HE_V2 = (AAC_ADTS | AAC_SUB_HE_V2),
-//   AAC_ADTS_ELD = (AAC_ADTS | AAC_SUB_ELD),
-//   AAC_ADTS_XHE = (AAC_ADTS | AAC_SUB_XHE),
-//   E_AC3_JOC = (E_AC3 | E_AC3_SUB_JOC),
-//   MAT_1_0 = (MAT | MAT_SUB_1_0),
-//   MAT_2_0 = (MAT | MAT_SUB_2_0),
-//   MAT_2_1 = (MAT | MAT_SUB_2_1),
-//   AAC_LATM_LC = (AAC_LATM | AAC_SUB_LC),
-//   AAC_LATM_HE_V1 = (AAC_LATM | AAC_SUB_HE_V1),
-//   AAC_LATM_HE_V2 = (AAC_LATM | AAC_SUB_HE_V2),
-}
diff --git a/media/aidl/android/media/audio/common/AudioFormatDescription.aidl b/media/aidl/android/media/audio/common/AudioFormatDescription.aidl
new file mode 100644
index 0000000..2aea8dd
--- /dev/null
+++ b/media/aidl/android/media/audio/common/AudioFormatDescription.aidl
@@ -0,0 +1,86 @@
+/*
+ * 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.media.audio.common;
+
+import android.media.audio.common.AudioFormatType;
+import android.media.audio.common.PcmType;
+
+/**
+ * An extensible type for specifying audio formats. All formats are largely
+ * divided into two classes: PCM and non-PCM (bitstreams). Bitstreams can
+ * be encapsulated into PCM streams.
+ *
+ * The type defined in a way to make each format uniquely identifiable, so
+ * that if the framework and the HAL construct a value for the same type
+ * (e.g. PCM 16 bit), they will produce identical parcelables which will have
+ * identical hashes. This makes possible deduplicating type descriptions
+ * by the framework when they are received from different HAL modules without
+ * relying on having some centralized registry of enumeration values.
+ *
+ * {@hide}
+ */
+@JavaDerive(equals = true, toString = true)
+@VintfStability
+parcelable AudioFormatDescription {
+    /**
+     * The type of the audio format. See the 'AudioFormatType' for the
+     * list of supported values.
+     */
+    AudioFormatType type = AudioFormatType.DEFAULT;
+    /**
+     * The type of the PCM stream or the transport stream for PCM
+     * encapsulations.  See 'PcmType' for the list of supported values.
+     */
+    PcmType pcm = PcmType.DEFAULT;
+    /**
+     * Optional encoding specification. Must be left empty when:
+     *
+     *  - 'type == DEFAULT && pcm == DEFAULT' -- that means "default" type;
+     *  - 'type == PCM' -- that means a regular PCM stream (not an encapsulation
+     *    of an encoded bitstream).
+     *
+     * For PCM encapsulations of encoded bitstreams (e.g. an encapsulation
+     * according to IEC-61937 standard), the value of the 'pcm' field must
+     * be set accordingly, as an example, PCM_INT_16_BIT must be used for
+     * IEC-61937. Note that 'type == NON_PCM' in this case.
+     *
+     * Encoding names mostly follow IANA standards for media types (MIME), and
+     * frameworks/av/media/libstagefright/foundation/MediaDefs.cpp with the
+     * latter having priority.  Since there are still many audio types not found
+     * in any of these lists, the following rules are applied:
+     *
+     *   - If there is a direct MIME type for the encoding, the MIME type name
+     *     is used as is, e.g. "audio/eac3" for the EAC-3 format.
+     *   - If the encoding is a "subformat" of a MIME-registered format,
+     *     the latter is augmented with a suffix, e.g. "audio/eac3-joc" for the
+     *     JOC extension of EAC-3.
+     *   - If it's a proprietary format, a "vnd." prefix is added, similar to
+     *     IANA rules, e.g. "audio/vnd.dolby.truehd".
+     *   - Otherwise, "x-" prefix is added, e.g. "audio/x-iec61937".
+     *   - All MIME types not found in the IANA formats list have an associated
+     *     comment.
+     *
+     * For PCM encapsulations with a known bitstream format, the latter
+     * is added to the encapsulation encoding as a suffix, after a "+" char.
+     * For example, an IEC61937 encapsulation of AC3 has the following
+     * representation:
+     *   type = NON_PCM,
+     *   pcm = PcmType.INT_16_BIT,
+     *   encoding = "audio/x-iec61937+audio/ac3"
+     */
+    @utf8InCpp String encoding;
+}
diff --git a/media/aidl/android/media/audio/common/AudioFormatType.aidl b/media/aidl/android/media/audio/common/AudioFormatType.aidl
new file mode 100644
index 0000000..1759401
--- /dev/null
+++ b/media/aidl/android/media/audio/common/AudioFormatType.aidl
@@ -0,0 +1,49 @@
+/*
+ * 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.media.audio.common;
+
+/**
+ * The type of the audio format. Only used as part of 'AudioFormatDescription'
+ * structure.
+ */
+@VintfStability
+@Backing(type="byte")
+enum AudioFormatType {
+    /**
+     * "Default" type is used when the client does not care about the actual
+     * format. All fields of 'AudioFormatDescription' must have default / empty
+     * / null values.
+     */
+    DEFAULT = 0,
+    /**
+     * When the 'encoding' field of 'AudioFormatDescription' is not empty, it
+     * specifies the codec used for bitstream (non-PCM) data. It is also used
+     * in the case when the bitstream data is encapsulated into a PCM stream,
+     * see the documentation for 'AudioFormatDescription'.
+     */
+    NON_PCM = DEFAULT,
+    /**
+     * PCM type. The 'pcm' field of 'AudioFormatDescription' is used to specify
+     * the actual sample size and representation.
+     */
+    PCM = 1,
+    /**
+     * Value reserved for system use only. HALs must never return this value to
+     * the system or accept it from the system.
+     */
+    SYS_RESERVED_INVALID = -1,
+}
diff --git a/media/aidl/android/media/audio/common/AudioOffloadInfo.aidl b/media/aidl/android/media/audio/common/AudioOffloadInfo.aidl
index 7be5e6a..b6b5487 100644
--- a/media/aidl/android/media/audio/common/AudioOffloadInfo.aidl
+++ b/media/aidl/android/media/audio/common/AudioOffloadInfo.aidl
@@ -14,12 +14,10 @@
  * limitations under the License.
  */
 
- // This file has been semi-automatically generated using hidl2aidl from its counterpart in
- // hardware/interfaces/audio/common/5.0/types.hal
-
 package android.media.audio.common;
 
-import android.media.audio.common.AudioFormat;
+import android.media.audio.common.AudioChannelLayout;
+import android.media.audio.common.AudioFormatDescription;
 import android.media.audio.common.AudioStreamType;
 import android.media.audio.common.AudioUsage;
 
@@ -32,8 +30,8 @@
 @VintfStability
 parcelable AudioOffloadInfo {
     int sampleRateHz;
-    int channelMask;
-    AudioFormat format = AudioFormat.INVALID;
+    AudioChannelLayout channelMask;
+    AudioFormatDescription format;
     AudioStreamType streamType = AudioStreamType.INVALID;
     int bitRatePerSecond;
     long durationMicroseconds;
@@ -43,4 +41,3 @@
     int bufferSize;
     AudioUsage usage = AudioUsage.INVALID;
 }
-
diff --git a/media/aidl/android/media/audio/common/PcmType.aidl b/media/aidl/android/media/audio/common/PcmType.aidl
new file mode 100644
index 0000000..db77769
--- /dev/null
+++ b/media/aidl/android/media/audio/common/PcmType.aidl
@@ -0,0 +1,54 @@
+/*
+ * 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.media.audio.common;
+
+/**
+ * The type of the encoding used for representing PCM samples. Only used as
+ * part of 'AudioFormatDescription' structure.
+ */
+@VintfStability
+@Backing(type="byte")
+enum PcmType {
+    /**
+     * "Default" value used when the type 'AudioFormatDescription' is "default".
+     */
+    DEFAULT = 0,
+    /**
+     * Unsigned 8-bit integer.
+     */
+    UINT_8_BIT = DEFAULT,
+    /**
+     * Signed 16-bit integer.
+     */
+    INT_16_BIT = 1,
+    /**
+     * Signed 32-bit integer.
+     */
+    INT_32_BIT = 2,
+    /**
+     * Q8.24 fixed point format.
+     */
+    FIXED_Q_8_24 = 3,
+    /**
+     * IEEE 754 32-bit floating point format.
+     */
+    FLOAT_32_BIT = 4,
+    /**
+     * Signed 24-bit integer.
+     */
+    INT_24_BIT = 5,
+}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioChannelLayout.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioChannelLayout.aidl
new file mode 100644
index 0000000..6845ac1
--- /dev/null
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioChannelLayout.aidl
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media.audio.common;
+/* @hide */
+@JavaDerive(equals=true, toString=true) @VintfStability
+union AudioChannelLayout {
+  int none = 0;
+  int invalid = 0;
+  int indexMask;
+  int layoutMask;
+  int voiceMask;
+  const int INDEX_MASK_1 = 1;
+  const int INDEX_MASK_2 = 3;
+  const int INDEX_MASK_3 = 7;
+  const int INDEX_MASK_4 = 15;
+  const int INDEX_MASK_5 = 31;
+  const int INDEX_MASK_6 = 63;
+  const int INDEX_MASK_7 = 127;
+  const int INDEX_MASK_8 = 255;
+  const int INDEX_MASK_9 = 511;
+  const int INDEX_MASK_10 = 1023;
+  const int INDEX_MASK_11 = 2047;
+  const int INDEX_MASK_12 = 4095;
+  const int INDEX_MASK_13 = 8191;
+  const int INDEX_MASK_14 = 16383;
+  const int INDEX_MASK_15 = 32767;
+  const int INDEX_MASK_16 = 65535;
+  const int INDEX_MASK_17 = 131071;
+  const int INDEX_MASK_18 = 262143;
+  const int INDEX_MASK_19 = 524287;
+  const int INDEX_MASK_20 = 1048575;
+  const int INDEX_MASK_21 = 2097151;
+  const int INDEX_MASK_22 = 4194303;
+  const int INDEX_MASK_23 = 8388607;
+  const int INDEX_MASK_24 = 16777215;
+  const int LAYOUT_MONO = 1;
+  const int LAYOUT_STEREO = 3;
+  const int LAYOUT_2POINT1 = 11;
+  const int LAYOUT_TRI = 7;
+  const int LAYOUT_TRI_BACK = 259;
+  const int LAYOUT_3POINT1 = 15;
+  const int LAYOUT_2POINT0POINT2 = 786435;
+  const int LAYOUT_2POINT1POINT2 = 786443;
+  const int LAYOUT_3POINT0POINT2 = 786439;
+  const int LAYOUT_3POINT1POINT2 = 786447;
+  const int LAYOUT_QUAD = 51;
+  const int LAYOUT_QUAD_SIDE = 1539;
+  const int LAYOUT_SURROUND = 263;
+  const int LAYOUT_PENTA = 55;
+  const int LAYOUT_5POINT1 = 63;
+  const int LAYOUT_5POINT1_SIDE = 1551;
+  const int LAYOUT_5POINT1POINT2 = 786495;
+  const int LAYOUT_5POINT1POINT4 = 184383;
+  const int LAYOUT_6POINT1 = 319;
+  const int LAYOUT_7POINT1 = 1599;
+  const int LAYOUT_7POINT1POINT2 = 788031;
+  const int LAYOUT_7POINT1POINT4 = 185919;
+  const int LAYOUT_9POINT1POINT4 = 50517567;
+  const int LAYOUT_9POINT1POINT6 = 51303999;
+  const int LAYOUT_13POINT_360RA = 7534087;
+  const int LAYOUT_22POINT2 = 16777215;
+  const int LAYOUT_MONO_HAPTIC_A = 1073741825;
+  const int LAYOUT_STEREO_HAPTIC_A = 1073741827;
+  const int LAYOUT_HAPTIC_AB = 1610612736;
+  const int LAYOUT_MONO_HAPTIC_AB = 1610612737;
+  const int LAYOUT_STEREO_HAPTIC_AB = 1610612739;
+  const int LAYOUT_FRONT_BACK = 260;
+  const int INTERLEAVE_LEFT = 0;
+  const int INTERLEAVE_RIGHT = 1;
+  const int CHANNEL_FRONT_LEFT = 1;
+  const int CHANNEL_FRONT_RIGHT = 2;
+  const int CHANNEL_FRONT_CENTER = 4;
+  const int CHANNEL_LOW_FREQUENCY = 8;
+  const int CHANNEL_BACK_LEFT = 16;
+  const int CHANNEL_BACK_RIGHT = 32;
+  const int CHANNEL_FRONT_LEFT_OF_CENTER = 64;
+  const int CHANNEL_FRONT_RIGHT_OF_CENTER = 128;
+  const int CHANNEL_BACK_CENTER = 256;
+  const int CHANNEL_SIDE_LEFT = 512;
+  const int CHANNEL_SIDE_RIGHT = 1024;
+  const int CHANNEL_TOP_CENTER = 2048;
+  const int CHANNEL_TOP_FRONT_LEFT = 4096;
+  const int CHANNEL_TOP_FRONT_CENTER = 8192;
+  const int CHANNEL_TOP_FRONT_RIGHT = 16384;
+  const int CHANNEL_TOP_BACK_LEFT = 32768;
+  const int CHANNEL_TOP_BACK_CENTER = 65536;
+  const int CHANNEL_TOP_BACK_RIGHT = 131072;
+  const int CHANNEL_TOP_SIDE_LEFT = 262144;
+  const int CHANNEL_TOP_SIDE_RIGHT = 524288;
+  const int CHANNEL_BOTTOM_FRONT_LEFT = 1048576;
+  const int CHANNEL_BOTTOM_FRONT_CENTER = 2097152;
+  const int CHANNEL_BOTTOM_FRONT_RIGHT = 4194304;
+  const int CHANNEL_LOW_FREQUENCY_2 = 8388608;
+  const int CHANNEL_FRONT_WIDE_LEFT = 16777216;
+  const int CHANNEL_FRONT_WIDE_RIGHT = 33554432;
+  const int CHANNEL_HAPTIC_B = 536870912;
+  const int CHANNEL_HAPTIC_A = 1073741824;
+  const int VOICE_UPLINK_MONO = 16384;
+  const int VOICE_DNLINK_MONO = 32768;
+  const int VOICE_CALL_MONO = 49152;
+  const int CHANNEL_VOICE_UPLINK = 16384;
+  const int CHANNEL_VOICE_DNLINK = 32768;
+}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioChannelMask.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioChannelMask.aidl
deleted file mode 100644
index c3af3bf..0000000
--- a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioChannelMask.aidl
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */// This file has been semi-automatically generated using hidl2aidl from its counterpart in
-// hardware/interfaces/audio/common/5.0/types.hal
-///////////////////////////////////////////////////////////////////////////////
-// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
-///////////////////////////////////////////////////////////////////////////////
-
-// This file is a snapshot of an AIDL file. Do not edit it manually. There are
-// two cases:
-// 1). this is a frozen version file - do not edit this in any case.
-// 2). this is a 'current' file. If you make a backwards compatible change to
-//     the interface (from the latest frozen version), the build system will
-//     prompt you to update this file with `m <name>-update-api`.
-//
-// You must not make a backward incompatible change to any AIDL file built
-// with the aidl_interface module type with versions property set. The module
-// type is used to build AIDL files in a way that they can be used across
-// independently updatable components of the system. If a device is shipped
-// with such a backward incompatible change, it has a high risk of breaking
-// later when a module using the interface is updated, e.g., Mainline modules.
-
-package android.media.audio.common;
-/* @hide */
-@Backing(type="int") @VintfStability
-enum AudioChannelMask {
-  REPRESENTATION_POSITION = 0,
-  REPRESENTATION_INDEX = 2,
-  NONE = 0,
-  INVALID = -1073741824,
-  OUT_FRONT_LEFT = 1,
-  OUT_FRONT_RIGHT = 2,
-  OUT_FRONT_CENTER = 4,
-  OUT_LOW_FREQUENCY = 8,
-  OUT_BACK_LEFT = 16,
-  OUT_BACK_RIGHT = 32,
-  OUT_FRONT_LEFT_OF_CENTER = 64,
-  OUT_FRONT_RIGHT_OF_CENTER = 128,
-  OUT_BACK_CENTER = 256,
-  OUT_SIDE_LEFT = 512,
-  OUT_SIDE_RIGHT = 1024,
-  OUT_TOP_CENTER = 2048,
-  OUT_TOP_FRONT_LEFT = 4096,
-  OUT_TOP_FRONT_CENTER = 8192,
-  OUT_TOP_FRONT_RIGHT = 16384,
-  OUT_TOP_BACK_LEFT = 32768,
-  OUT_TOP_BACK_CENTER = 65536,
-  OUT_TOP_BACK_RIGHT = 131072,
-  OUT_TOP_SIDE_LEFT = 262144,
-  OUT_TOP_SIDE_RIGHT = 524288,
-  OUT_HAPTIC_A = 536870912,
-  OUT_HAPTIC_B = 268435456,
-  OUT_MONO = 1,
-  OUT_STEREO = 3,
-  OUT_2POINT1 = 11,
-  OUT_2POINT0POINT2 = 786435,
-  OUT_2POINT1POINT2 = 786443,
-  OUT_3POINT0POINT2 = 786439,
-  OUT_3POINT1POINT2 = 786447,
-  OUT_QUAD = 51,
-  OUT_QUAD_BACK = 51,
-  OUT_QUAD_SIDE = 1539,
-  OUT_SURROUND = 263,
-  OUT_PENTA = 55,
-  OUT_5POINT1 = 63,
-  OUT_5POINT1_BACK = 63,
-  OUT_5POINT1_SIDE = 1551,
-  OUT_5POINT1POINT2 = 786495,
-  OUT_5POINT1POINT4 = 184383,
-  OUT_6POINT1 = 319,
-  OUT_7POINT1 = 1599,
-  OUT_7POINT1POINT2 = 788031,
-  OUT_7POINT1POINT4 = 185919,
-  OUT_MONO_HAPTIC_A = 536870913,
-  OUT_STEREO_HAPTIC_A = 536870915,
-  OUT_HAPTIC_AB = 805306368,
-  OUT_MONO_HAPTIC_AB = 805306369,
-  OUT_STEREO_HAPTIC_AB = 805306371,
-  IN_LEFT = 4,
-  IN_RIGHT = 8,
-  IN_FRONT = 16,
-  IN_BACK = 32,
-  IN_LEFT_PROCESSED = 64,
-  IN_RIGHT_PROCESSED = 128,
-  IN_FRONT_PROCESSED = 256,
-  IN_BACK_PROCESSED = 512,
-  IN_PRESSURE = 1024,
-  IN_X_AXIS = 2048,
-  IN_Y_AXIS = 4096,
-  IN_Z_AXIS = 8192,
-  IN_BACK_LEFT = 65536,
-  IN_BACK_RIGHT = 131072,
-  IN_CENTER = 262144,
-  IN_LOW_FREQUENCY = 1048576,
-  IN_TOP_LEFT = 2097152,
-  IN_TOP_RIGHT = 4194304,
-  IN_VOICE_UPLINK = 16384,
-  IN_VOICE_DNLINK = 32768,
-}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioConfig.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioConfig.aidl
index c11eb76..5fdeb4c 100644
--- a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioConfig.aidl
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioConfig.aidl
@@ -12,8 +12,7 @@
  * 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.
- */// This file has been semi-automatically generated using hidl2aidl from its counterpart in
-// hardware/interfaces/audio/common/5.0/types.hal
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
@@ -37,8 +36,8 @@
 @JavaDerive(equals=true, toString=true) @VintfStability
 parcelable AudioConfig {
   int sampleRateHz;
-  int channelMask;
-  android.media.audio.common.AudioFormat format = android.media.audio.common.AudioFormat.INVALID;
+  android.media.audio.common.AudioChannelLayout channelMask;
+  android.media.audio.common.AudioFormatDescription format;
   android.media.audio.common.AudioOffloadInfo offloadInfo;
   long frameCount;
 }
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioFormat.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioFormat.aidl
deleted file mode 100644
index b7c8659..0000000
--- a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioFormat.aidl
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */// This file has been semi-automatically generated using hidl2aidl from its counterpart in
-// hardware/interfaces/audio/common/5.0/types.hal
-///////////////////////////////////////////////////////////////////////////////
-// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
-///////////////////////////////////////////////////////////////////////////////
-
-// This file is a snapshot of an AIDL file. Do not edit it manually. There are
-// two cases:
-// 1). this is a frozen version file - do not edit this in any case.
-// 2). this is a 'current' file. If you make a backwards compatible change to
-//     the interface (from the latest frozen version), the build system will
-//     prompt you to update this file with `m <name>-update-api`.
-//
-// You must not make a backward incompatible change to any AIDL file built
-// with the aidl_interface module type with versions property set. The module
-// type is used to build AIDL files in a way that they can be used across
-// independently updatable components of the system. If a device is shipped
-// with such a backward incompatible change, it has a high risk of breaking
-// later when a module using the interface is updated, e.g., Mainline modules.
-
-package android.media.audio.common;
-/* @hide */
-@Backing(type="int") @VintfStability
-enum AudioFormat {
-  INVALID = -1,
-  DEFAULT = 0,
-  PCM = 0,
-  MP3 = 16777216,
-  AMR_NB = 33554432,
-  AMR_WB = 50331648,
-  AAC = 67108864,
-  HE_AAC_V1 = 83886080,
-  HE_AAC_V2 = 100663296,
-  VORBIS = 117440512,
-  OPUS = 134217728,
-  AC3 = 150994944,
-  E_AC3 = 167772160,
-  DTS = 184549376,
-  DTS_HD = 201326592,
-  IEC61937 = 218103808,
-  DOLBY_TRUEHD = 234881024,
-  EVRC = 268435456,
-  EVRCB = 285212672,
-  EVRCWB = 301989888,
-  EVRCNW = 318767104,
-  AAC_ADIF = 335544320,
-  WMA = 352321536,
-  WMA_PRO = 369098752,
-  AMR_WB_PLUS = 385875968,
-  MP2 = 402653184,
-  QCELP = 419430400,
-  DSD = 436207616,
-  FLAC = 452984832,
-  ALAC = 469762048,
-  APE = 486539264,
-  AAC_ADTS = 503316480,
-  SBC = 520093696,
-  APTX = 536870912,
-  APTX_HD = 553648128,
-  AC4 = 570425344,
-  LDAC = 587202560,
-  MAT = 603979776,
-  AAC_LATM = 620756992,
-  CELT = 637534208,
-  APTX_ADAPTIVE = 654311424,
-  LHDC = 671088640,
-  LHDC_LL = 687865856,
-  APTX_TWSP = 704643072,
-  MAIN_MASK = -16777216,
-  SUB_MASK = 16777215,
-  PCM_SUB_16_BIT = 1,
-  PCM_SUB_8_BIT = 2,
-  PCM_SUB_32_BIT = 3,
-  PCM_SUB_8_24_BIT = 4,
-  PCM_SUB_FLOAT = 5,
-  PCM_SUB_24_BIT_PACKED = 6,
-  MP3_SUB_NONE = 0,
-  AMR_SUB_NONE = 0,
-  AAC_SUB_MAIN = 1,
-  AAC_SUB_LC = 2,
-  AAC_SUB_SSR = 4,
-  AAC_SUB_LTP = 8,
-  AAC_SUB_HE_V1 = 16,
-  AAC_SUB_SCALABLE = 32,
-  AAC_SUB_ERLC = 64,
-  AAC_SUB_LD = 128,
-  AAC_SUB_HE_V2 = 256,
-  AAC_SUB_ELD = 512,
-  AAC_SUB_XHE = 768,
-  VORBIS_SUB_NONE = 0,
-  E_AC3_SUB_JOC = 1,
-  MAT_SUB_1_0 = 1,
-  MAT_SUB_2_0 = 2,
-  MAT_SUB_2_1 = 3,
-}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioFormatDescription.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioFormatDescription.aidl
new file mode 100644
index 0000000..58c75eb
--- /dev/null
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioFormatDescription.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media.audio.common;
+/* @hide */
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable AudioFormatDescription {
+  android.media.audio.common.AudioFormatType type = android.media.audio.common.AudioFormatType.DEFAULT;
+  android.media.audio.common.PcmType pcm = android.media.audio.common.PcmType.DEFAULT;
+  @utf8InCpp String encoding;
+}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioFormatType.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioFormatType.aidl
new file mode 100644
index 0000000..b94c850
--- /dev/null
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioFormatType.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media.audio.common;
+@Backing(type="byte") @VintfStability
+enum AudioFormatType {
+  DEFAULT = 0,
+  NON_PCM = 0,
+  PCM = 1,
+  SYS_RESERVED_INVALID = -1,
+}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioOffloadInfo.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioOffloadInfo.aidl
index b5d889e..9404a4b 100644
--- a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioOffloadInfo.aidl
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioOffloadInfo.aidl
@@ -12,8 +12,7 @@
  * 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.
- */// This file has been semi-automatically generated using hidl2aidl from its counterpart in
-// hardware/interfaces/audio/common/5.0/types.hal
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
@@ -37,8 +36,8 @@
 @JavaDerive(equals=true, toString=true) @VintfStability
 parcelable AudioOffloadInfo {
   int sampleRateHz;
-  int channelMask;
-  android.media.audio.common.AudioFormat format = android.media.audio.common.AudioFormat.INVALID;
+  android.media.audio.common.AudioChannelLayout channelMask;
+  android.media.audio.common.AudioFormatDescription format;
   android.media.audio.common.AudioStreamType streamType = android.media.audio.common.AudioStreamType.INVALID;
   int bitRatePerSecond;
   long durationMicroseconds;
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/PcmType.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/PcmType.aidl
new file mode 100644
index 0000000..42c4679
--- /dev/null
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/PcmType.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media.audio.common;
+@Backing(type="byte") @VintfStability
+enum PcmType {
+  DEFAULT = 0,
+  UINT_8_BIT = 0,
+  INT_16_BIT = 1,
+  INT_32_BIT = 2,
+  FIXED_Q_8_24 = 3,
+  FLOAT_32_BIT = 4,
+  INT_24_BIT = 5,
+}
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index a8199c4..5cdb898 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -495,6 +495,12 @@
     public static final int CHANNEL_OUT_FRONT_WIDE_LEFT = 0x4000000;
     /** Front wide right output channel (see FWR in channel diagram) */
     public static final int CHANNEL_OUT_FRONT_WIDE_RIGHT = 0x8000000;
+    /** @hide
+     * Haptic channels can be used by internal framework code. Use the same values as in native.
+     */
+    public static final int CHANNEL_OUT_HAPTIC_B = 0x10000000;
+    /** @hide */
+    public static final int CHANNEL_OUT_HAPTIC_A = 0x20000000;
 
     public static final int CHANNEL_OUT_MONO = CHANNEL_OUT_FRONT_LEFT;
     public static final int CHANNEL_OUT_STEREO = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT);
diff --git a/media/java/android/media/audio/common/AidlConversion.java b/media/java/android/media/audio/common/AidlConversion.java
index e14e048..3b58934 100644
--- a/media/java/android/media/audio/common/AidlConversion.java
+++ b/media/java/android/media/audio/common/AidlConversion.java
@@ -18,6 +18,10 @@
 
 import android.annotation.NonNull;
 import android.media.AudioFormat;
+import android.media.MediaFormat;
+import android.os.Parcel;
+
+import com.android.internal.annotations.VisibleForTesting;
 
 /**
  * This class provides utility functions for converting between
@@ -39,23 +43,69 @@
  *
  * @hide
  */
+@VisibleForTesting
 public class AidlConversion {
-    /** Convert from legacy audio_channel_mask_t to AIDL AudioChannelMask. */
-    public static int legacy2aidl_audio_channel_mask_t_AudioChannelMask(
-            int /*audio_channel_mask_t*/ legacy) {
-        // Relies on the fact that AudioChannelMask was converted from
-        // the HIDL definition which uses the same constant values as system/audio.h
-        return legacy;
+    /** Convert from AIDL AudioChannelLayout to legacy audio_channel_mask_t. */
+    @VisibleForTesting
+    public static int /*audio_channel_mask_t*/ aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+            @NonNull AudioChannelLayout aidl, boolean isInput) {
+        Parcel out = Parcel.obtain();
+        aidl.writeToParcel(out, 0);
+        out.setDataPosition(0);
+        try {
+            return aidl2legacy_AudioChannelLayout_Parcel_audio_channel_mask_t(out, isInput);
+        } finally {
+            out.recycle();
+        }
     }
 
-    /** Convert from legacy audio_format_t to AIDL AudioFormat. */
-    public static int legacy2aidl_audio_format_t_AudioFormat(int /*audio_format_t*/ legacy) {
-        // Relies on the fact that AudioFormat was converted from
-        // the HIDL definition which uses the same constant values as system/audio.h
-        return legacy;
+    /** Convert from legacy audio_channel_mask_t to AIDL AudioChannelLayout. */
+    @VisibleForTesting
+    public static AudioChannelLayout legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+            int /*audio_channel_mask_t*/ legacy, boolean isInput) {
+        Parcel in = legacy2aidl_audio_channel_mask_t_AudioChannelLayout_Parcel(legacy, isInput);
+        if (in != null) {
+            try {
+                return AudioChannelLayout.CREATOR.createFromParcel(in);
+            } finally {
+                in.recycle();
+            }
+        }
+        throw new IllegalArgumentException("Invalid legacy audio "
+                + (isInput ? "input" : "output") + " channel mask: " + legacy);
+    }
+
+    /** Convert from AIDL AudioFormatDescription to legacy audio_format_t. */
+    @VisibleForTesting
+    public static int /*audio_format_t*/ aidl2legacy_AudioFormatDescription_audio_format_t(
+            @NonNull AudioFormatDescription aidl) {
+        Parcel out = Parcel.obtain();
+        aidl.writeToParcel(out, 0);
+        out.setDataPosition(0);
+        try {
+            return aidl2legacy_AudioFormatDescription_Parcel_audio_format_t(out);
+        } finally {
+            out.recycle();
+        }
+    }
+
+    /** Convert from legacy audio_format_t to AIDL AudioFormatDescription. */
+    @VisibleForTesting
+    public static @NonNull AudioFormatDescription legacy2aidl_audio_format_t_AudioFormatDescription(
+            int /*audio_format_t*/ legacy) {
+        Parcel in = legacy2aidl_audio_format_t_AudioFormatDescription_Parcel(legacy);
+        if (in != null) {
+            try {
+                return AudioFormatDescription.CREATOR.createFromParcel(in);
+            } finally {
+                in.recycle();
+            }
+        }
+        throw new IllegalArgumentException("Invalid legacy audio format: " + legacy);
     }
 
     /** Convert from legacy audio_stream_type_t to AIDL AudioStreamType. */
+    @VisibleForTesting
     public static int legacy2aidl_audio_stream_type_t_AudioStreamType(
             int /*audio_stream_type_t*/ legacy) {
         // Relies on the fact that AudioStreamType was converted from
@@ -64,113 +114,280 @@
     }
 
     /** Convert from legacy audio_usage_t to AIDL AudioUsage. */
+    @VisibleForTesting
     public static int legacy2aidl_audio_usage_t_AudioUsage(int /*audio_usage_t*/ legacy) {
         // Relies on the fact that AudioUsage was converted from
         // the HIDL definition which uses the same constant values as system/audio.h
         return legacy;
     }
 
-    /** Convert from AIDL AudioChannelMask to SDK AudioFormat.CHANNEL_IN_*. */
-    public static int aidl2api_AudioChannelMask_AudioFormatChannelInMask(int aidlMask) {
-        // We're assuming AudioFormat.CHANNEL_IN_* constants are kept in sync with
-        // android.media.audio.common.AudioChannelMask.
-        return aidlMask;
+    /** Convert from AIDL AudioChannelLayout to SDK AudioFormat.CHANNEL_*. */
+    @VisibleForTesting
+    public static int aidl2api_AudioChannelLayout_AudioFormatChannelMask(
+            @NonNull AudioChannelLayout aidlMask, boolean isInput) {
+        switch (aidlMask.getTag()) {
+            case AudioChannelLayout.none:
+                return isInput ? AudioFormat.CHANNEL_IN_DEFAULT : AudioFormat.CHANNEL_OUT_DEFAULT;
+            case AudioChannelLayout.invalid:
+                return AudioFormat.CHANNEL_INVALID;
+            case AudioChannelLayout.indexMask:
+                // Note that for a proper building of SDK AudioFormat one must
+                // call either 'setChannelMask' or 'setChannelIndexMask' depending
+                // on the variant of AudioChannelLayout. The integer representations
+                // of positional and indexed channel masks are indistinguishable in
+                // the SDK.
+                return aidlMask.getIndexMask();
+            case AudioChannelLayout.layoutMask:
+                if (isInput) {
+                    switch (aidlMask.getLayoutMask()) {
+                        case AudioChannelLayout.LAYOUT_MONO:
+                            return AudioFormat.CHANNEL_IN_MONO;
+                        case AudioChannelLayout.LAYOUT_STEREO:
+                            return AudioFormat.CHANNEL_IN_STEREO;
+                        case AudioChannelLayout.LAYOUT_FRONT_BACK:
+                            return AudioFormat.CHANNEL_IN_FRONT_BACK;
+                        default:
+                            return AudioFormat.CHANNEL_INVALID;
+                    }
+                } else {
+                    switch (aidlMask.getLayoutMask()) {
+                        case AudioChannelLayout.LAYOUT_MONO:
+                            return AudioFormat.CHANNEL_OUT_MONO;
+                        case AudioChannelLayout.LAYOUT_STEREO:
+                            return AudioFormat.CHANNEL_OUT_STEREO;
+                        case AudioChannelLayout.LAYOUT_2POINT1:
+                            return AudioFormat.CHANNEL_OUT_FRONT_LEFT
+                                    | AudioFormat.CHANNEL_OUT_FRONT_RIGHT
+                                    | AudioFormat.CHANNEL_OUT_LOW_FREQUENCY;
+                        case AudioChannelLayout.LAYOUT_TRI:
+                            return AudioFormat.CHANNEL_OUT_FRONT_LEFT
+                                    | AudioFormat.CHANNEL_OUT_FRONT_RIGHT
+                                    | AudioFormat.CHANNEL_OUT_FRONT_CENTER;
+                        case AudioChannelLayout.LAYOUT_TRI_BACK:
+                            return AudioFormat.CHANNEL_OUT_FRONT_LEFT
+                                    | AudioFormat.CHANNEL_OUT_FRONT_RIGHT
+                                    | AudioFormat.CHANNEL_OUT_BACK_CENTER;
+                        case AudioChannelLayout.LAYOUT_3POINT1:
+                            return AudioFormat.CHANNEL_OUT_FRONT_LEFT
+                                    | AudioFormat.CHANNEL_OUT_FRONT_RIGHT
+                                    | AudioFormat.CHANNEL_OUT_FRONT_CENTER
+                                    | AudioFormat.CHANNEL_OUT_LOW_FREQUENCY;
+                        case AudioChannelLayout.LAYOUT_2POINT0POINT2:
+                            return AudioFormat.CHANNEL_OUT_FRONT_LEFT
+                                    | AudioFormat.CHANNEL_OUT_FRONT_RIGHT
+                                    | AudioFormat.CHANNEL_OUT_TOP_SIDE_LEFT
+                                    | AudioFormat.CHANNEL_OUT_TOP_SIDE_RIGHT;
+                        case AudioChannelLayout.LAYOUT_2POINT1POINT2:
+                            return AudioFormat.CHANNEL_OUT_FRONT_LEFT
+                                    | AudioFormat.CHANNEL_OUT_FRONT_RIGHT
+                                    | AudioFormat.CHANNEL_OUT_TOP_SIDE_LEFT
+                                    | AudioFormat.CHANNEL_OUT_TOP_SIDE_RIGHT
+                                    | AudioFormat.CHANNEL_OUT_LOW_FREQUENCY;
+                        case AudioChannelLayout.LAYOUT_3POINT0POINT2:
+                            return AudioFormat.CHANNEL_OUT_FRONT_LEFT
+                                    | AudioFormat.CHANNEL_OUT_FRONT_RIGHT
+                                    | AudioFormat.CHANNEL_OUT_FRONT_CENTER
+                                    | AudioFormat.CHANNEL_OUT_TOP_SIDE_LEFT
+                                    | AudioFormat.CHANNEL_OUT_TOP_SIDE_RIGHT;
+                        case AudioChannelLayout.LAYOUT_3POINT1POINT2:
+                            return AudioFormat.CHANNEL_OUT_FRONT_LEFT
+                                    | AudioFormat.CHANNEL_OUT_FRONT_RIGHT
+                                    | AudioFormat.CHANNEL_OUT_FRONT_CENTER
+                                    | AudioFormat.CHANNEL_OUT_TOP_SIDE_LEFT
+                                    | AudioFormat.CHANNEL_OUT_TOP_SIDE_RIGHT
+                                    | AudioFormat.CHANNEL_OUT_LOW_FREQUENCY;
+                        case AudioChannelLayout.LAYOUT_QUAD:
+                            return AudioFormat.CHANNEL_OUT_QUAD;
+                        case AudioChannelLayout.LAYOUT_QUAD_SIDE:
+                            return AudioFormat.CHANNEL_OUT_QUAD_SIDE;
+                        case AudioChannelLayout.LAYOUT_SURROUND:
+                            return AudioFormat.CHANNEL_OUT_SURROUND;
+                        case AudioChannelLayout.LAYOUT_PENTA:
+                            return AudioFormat.CHANNEL_OUT_QUAD
+                                    | AudioFormat.CHANNEL_OUT_FRONT_CENTER;
+                        case AudioChannelLayout.LAYOUT_5POINT1:
+                            return AudioFormat.CHANNEL_OUT_5POINT1;
+                        case AudioChannelLayout.LAYOUT_5POINT1_SIDE:
+                            return AudioFormat.CHANNEL_OUT_5POINT1_SIDE;
+                        case AudioChannelLayout.LAYOUT_5POINT1POINT2:
+                            return AudioFormat.CHANNEL_OUT_5POINT1POINT2;
+                        case AudioChannelLayout.LAYOUT_5POINT1POINT4:
+                            return AudioFormat.CHANNEL_OUT_5POINT1POINT4;
+                        case AudioChannelLayout.LAYOUT_6POINT1:
+                            return AudioFormat.CHANNEL_OUT_FRONT_LEFT
+                                    | AudioFormat.CHANNEL_OUT_FRONT_RIGHT
+                                    | AudioFormat.CHANNEL_OUT_FRONT_CENTER
+                                    | AudioFormat.CHANNEL_OUT_LOW_FREQUENCY
+                                    | AudioFormat.CHANNEL_OUT_BACK_LEFT
+                                    | AudioFormat.CHANNEL_OUT_BACK_RIGHT
+                                    | AudioFormat.CHANNEL_OUT_BACK_CENTER;
+                        case AudioChannelLayout.LAYOUT_7POINT1:
+                            return AudioFormat.CHANNEL_OUT_7POINT1_SURROUND;
+                        case AudioChannelLayout.LAYOUT_7POINT1POINT2:
+                            return AudioFormat.CHANNEL_OUT_7POINT1POINT2;
+                        case AudioChannelLayout.LAYOUT_7POINT1POINT4:
+                            return AudioFormat.CHANNEL_OUT_7POINT1POINT4;
+                        case AudioChannelLayout.LAYOUT_9POINT1POINT4:
+                            return AudioFormat.CHANNEL_OUT_9POINT1POINT4;
+                        case AudioChannelLayout.LAYOUT_9POINT1POINT6:
+                            return AudioFormat.CHANNEL_OUT_9POINT1POINT6;
+                        case AudioChannelLayout.LAYOUT_13POINT_360RA:
+                            return AudioFormat.CHANNEL_OUT_13POINT_360RA;
+                        case AudioChannelLayout.LAYOUT_22POINT2:
+                            return AudioFormat.CHANNEL_OUT_22POINT2;
+                        case AudioChannelLayout.LAYOUT_MONO_HAPTIC_A:
+                            return AudioFormat.CHANNEL_OUT_MONO
+                                    | AudioFormat.CHANNEL_OUT_HAPTIC_A;
+                        case AudioChannelLayout.LAYOUT_STEREO_HAPTIC_A:
+                            return AudioFormat.CHANNEL_OUT_STEREO
+                                    | AudioFormat.CHANNEL_OUT_HAPTIC_A;
+                        case AudioChannelLayout.LAYOUT_HAPTIC_AB:
+                            return AudioFormat.CHANNEL_OUT_HAPTIC_A
+                                    | AudioFormat.CHANNEL_OUT_HAPTIC_B;
+                        case AudioChannelLayout.LAYOUT_MONO_HAPTIC_AB:
+                            return AudioFormat.CHANNEL_OUT_MONO
+                                    | AudioFormat.CHANNEL_OUT_HAPTIC_A
+                                    | AudioFormat.CHANNEL_OUT_HAPTIC_B;
+                        case AudioChannelLayout.LAYOUT_STEREO_HAPTIC_AB:
+                            return AudioFormat.CHANNEL_OUT_STEREO
+                                    | AudioFormat.CHANNEL_OUT_HAPTIC_A
+                                    | AudioFormat.CHANNEL_OUT_HAPTIC_B;
+                        case AudioChannelLayout.LAYOUT_FRONT_BACK:
+                            return AudioFormat.CHANNEL_OUT_FRONT_CENTER
+                                    | AudioFormat.CHANNEL_OUT_BACK_CENTER;
+                        default:
+                            return AudioFormat.CHANNEL_INVALID;
+                    }
+                }
+            case AudioChannelLayout.voiceMask:
+                if (isInput) {
+                    switch (aidlMask.getVoiceMask()) {
+                        // AudioFormat input masks match legacy native masks directly,
+                        // thus we add AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO here.
+                        case AudioChannelLayout.VOICE_UPLINK_MONO:
+                            return AudioFormat.CHANNEL_IN_VOICE_UPLINK
+                                    | AudioFormat.CHANNEL_IN_MONO;
+                        case AudioChannelLayout.VOICE_DNLINK_MONO:
+                            return AudioFormat.CHANNEL_IN_VOICE_DNLINK
+                                    | AudioFormat.CHANNEL_IN_MONO;
+                        case AudioChannelLayout.VOICE_CALL_MONO:
+                            return AudioFormat.CHANNEL_IN_VOICE_UPLINK
+                                    | AudioFormat.CHANNEL_IN_VOICE_DNLINK
+                                    | AudioFormat.CHANNEL_IN_MONO;
+                    }
+                }
+                return AudioFormat.CHANNEL_INVALID;
+            default:
+                return AudioFormat.CHANNEL_INVALID;
+        }
     }
 
     /** Convert from AIDL AudioConfig to SDK AudioFormat. */
+    @VisibleForTesting
     public static @NonNull AudioFormat aidl2api_AudioConfig_AudioFormat(
-            @NonNull AudioConfig audioConfig) {
+            @NonNull AudioConfig audioConfig, boolean isInput) {
         AudioFormat.Builder apiBuilder = new AudioFormat.Builder();
         apiBuilder.setSampleRate(audioConfig.sampleRateHz);
-        apiBuilder.setChannelMask(aidl2api_AudioChannelMask_AudioFormatChannelInMask(
-                        audioConfig.channelMask));
+        if (audioConfig.channelMask.getTag() != AudioChannelLayout.indexMask) {
+            apiBuilder.setChannelMask(aidl2api_AudioChannelLayout_AudioFormatChannelMask(
+                            audioConfig.channelMask, isInput));
+        } else {
+            apiBuilder.setChannelIndexMask(aidl2api_AudioChannelLayout_AudioFormatChannelMask(
+                            audioConfig.channelMask, isInput));
+        }
         apiBuilder.setEncoding(aidl2api_AudioFormat_AudioFormatEncoding(audioConfig.format));
         return apiBuilder.build();
     }
 
     /** Convert from AIDL AudioFormat to SDK AudioFormat.ENCODING_*. */
-    public static int aidl2api_AudioFormat_AudioFormatEncoding(int aidlFormat) {
-        switch (aidlFormat) {
-            case android.media.audio.common.AudioFormat.PCM
-                    | android.media.audio.common.AudioFormat.PCM_SUB_16_BIT:
-                return AudioFormat.ENCODING_PCM_16BIT;
-
-            case android.media.audio.common.AudioFormat.PCM
-                    | android.media.audio.common.AudioFormat.PCM_SUB_8_BIT:
-                return AudioFormat.ENCODING_PCM_8BIT;
-
-            case android.media.audio.common.AudioFormat.PCM
-                    | android.media.audio.common.AudioFormat.PCM_SUB_FLOAT:
-            case android.media.audio.common.AudioFormat.PCM
-                    | android.media.audio.common.AudioFormat.PCM_SUB_8_24_BIT:
-            case android.media.audio.common.AudioFormat.PCM
-                    | android.media.audio.common.AudioFormat.PCM_SUB_24_BIT_PACKED:
-            case android.media.audio.common.AudioFormat.PCM
-                    | android.media.audio.common.AudioFormat.PCM_SUB_32_BIT:
-                return AudioFormat.ENCODING_PCM_FLOAT;
-
-            case android.media.audio.common.AudioFormat.AC3:
-                return AudioFormat.ENCODING_AC3;
-
-            case android.media.audio.common.AudioFormat.E_AC3:
-                return AudioFormat.ENCODING_E_AC3;
-
-            case android.media.audio.common.AudioFormat.DTS:
-                return AudioFormat.ENCODING_DTS;
-
-            case android.media.audio.common.AudioFormat.DTS_HD:
-                return AudioFormat.ENCODING_DTS_HD;
-
-            case android.media.audio.common.AudioFormat.MP3:
-                return AudioFormat.ENCODING_MP3;
-
-            case android.media.audio.common.AudioFormat.AAC
-                    | android.media.audio.common.AudioFormat.AAC_SUB_LC:
-                return AudioFormat.ENCODING_AAC_LC;
-
-            case android.media.audio.common.AudioFormat.AAC
-                    | android.media.audio.common.AudioFormat.AAC_SUB_HE_V1:
-                return AudioFormat.ENCODING_AAC_HE_V1;
-
-            case android.media.audio.common.AudioFormat.AAC
-                    | android.media.audio.common.AudioFormat.AAC_SUB_HE_V2:
-                return AudioFormat.ENCODING_AAC_HE_V2;
-
-            case android.media.audio.common.AudioFormat.IEC61937:
-                return AudioFormat.ENCODING_IEC61937;
-
-            case android.media.audio.common.AudioFormat.DOLBY_TRUEHD:
-                return AudioFormat.ENCODING_DOLBY_TRUEHD;
-
-            case android.media.audio.common.AudioFormat.AAC
-                    | android.media.audio.common.AudioFormat.AAC_SUB_ELD:
-                return AudioFormat.ENCODING_AAC_ELD;
-
-            case android.media.audio.common.AudioFormat.AAC
-                    | android.media.audio.common.AudioFormat.AAC_SUB_XHE:
-                return AudioFormat.ENCODING_AAC_XHE;
-
-            case android.media.audio.common.AudioFormat.AC4:
-                return AudioFormat.ENCODING_AC4;
-
-            case android.media.audio.common.AudioFormat.E_AC3
-                    | android.media.audio.common.AudioFormat.E_AC3_SUB_JOC:
-                return AudioFormat.ENCODING_E_AC3_JOC;
-
-            case android.media.audio.common.AudioFormat.MAT:
-            case android.media.audio.common.AudioFormat.MAT
-                    | android.media.audio.common.AudioFormat.MAT_SUB_1_0:
-            case android.media.audio.common.AudioFormat.MAT
-                    | android.media.audio.common.AudioFormat.MAT_SUB_2_0:
-            case android.media.audio.common.AudioFormat.MAT
-                    | android.media.audio.common.AudioFormat.MAT_SUB_2_1:
-                return AudioFormat.ENCODING_DOLBY_MAT;
-
-            case android.media.audio.common.AudioFormat.DEFAULT:
-                return AudioFormat.ENCODING_DEFAULT;
-
+    @VisibleForTesting
+    public static int aidl2api_AudioFormat_AudioFormatEncoding(
+            @NonNull AudioFormatDescription aidlFormat) {
+        switch (aidlFormat.type) {
+            case AudioFormatType.PCM:
+                switch (aidlFormat.pcm) {
+                    case PcmType.UINT_8_BIT:
+                        return AudioFormat.ENCODING_PCM_8BIT;
+                    case PcmType.INT_16_BIT:
+                        return AudioFormat.ENCODING_PCM_16BIT;
+                    case PcmType.INT_32_BIT:
+                        return AudioFormat.ENCODING_PCM_32BIT;
+                    case PcmType.FIXED_Q_8_24:
+                    case PcmType.FLOAT_32_BIT:
+                        return AudioFormat.ENCODING_PCM_FLOAT;
+                    case PcmType.INT_24_BIT:
+                        return AudioFormat.ENCODING_PCM_24BIT_PACKED;
+                    default:
+                        return AudioFormat.ENCODING_INVALID;
+                }
+            case AudioFormatType.NON_PCM: // same as DEFAULT
+                if (aidlFormat.encoding != null && !aidlFormat.encoding.isEmpty()) {
+                    if (MediaFormat.MIMETYPE_AUDIO_AC3.equals(aidlFormat.encoding)) {
+                        return AudioFormat.ENCODING_AC3;
+                    } else if (MediaFormat.MIMETYPE_AUDIO_EAC3.equals(aidlFormat.encoding)) {
+                        return AudioFormat.ENCODING_E_AC3;
+                    } else if (MediaFormat.MIMETYPE_AUDIO_DTS.equals(aidlFormat.encoding)) {
+                        return AudioFormat.ENCODING_DTS;
+                    } else if (MediaFormat.MIMETYPE_AUDIO_DTS_HD.equals(aidlFormat.encoding)) {
+                        return AudioFormat.ENCODING_DTS_HD;
+                    } else if (MediaFormat.MIMETYPE_AUDIO_MPEG.equals(aidlFormat.encoding)) {
+                        return AudioFormat.ENCODING_MP3;
+                    } else if (MediaFormat.MIMETYPE_AUDIO_AAC_LC.equals(aidlFormat.encoding)) {
+                        return AudioFormat.ENCODING_AAC_LC;
+                    } else if (MediaFormat.MIMETYPE_AUDIO_AAC_HE_V1.equals(aidlFormat.encoding)) {
+                        return AudioFormat.ENCODING_AAC_HE_V1;
+                    } else if (MediaFormat.MIMETYPE_AUDIO_AAC_HE_V2.equals(aidlFormat.encoding)) {
+                        return AudioFormat.ENCODING_AAC_HE_V2;
+                    } else if (MediaFormat.MIMETYPE_AUDIO_IEC61937.equals(aidlFormat.encoding)
+                            && aidlFormat.pcm == PcmType.INT_16_BIT) {
+                        return AudioFormat.ENCODING_IEC61937;
+                    } else if (MediaFormat.MIMETYPE_AUDIO_DOLBY_TRUEHD.equals(
+                                    aidlFormat.encoding)) {
+                        return AudioFormat.ENCODING_DOLBY_TRUEHD;
+                    } else if (MediaFormat.MIMETYPE_AUDIO_AAC_ELD.equals(aidlFormat.encoding)) {
+                        return AudioFormat.ENCODING_AAC_ELD;
+                    } else if (MediaFormat.MIMETYPE_AUDIO_AAC_XHE.equals(aidlFormat.encoding)) {
+                        return AudioFormat.ENCODING_AAC_XHE;
+                    } else if (MediaFormat.MIMETYPE_AUDIO_AC4.equals(aidlFormat.encoding)) {
+                        return AudioFormat.ENCODING_AC4;
+                    } else if (MediaFormat.MIMETYPE_AUDIO_EAC3_JOC.equals(aidlFormat.encoding)) {
+                        return AudioFormat.ENCODING_E_AC3_JOC;
+                    } else if (MediaFormat.MIMETYPE_AUDIO_DOLBY_MAT.equals(aidlFormat.encoding)
+                            || aidlFormat.encoding.startsWith(
+                                    MediaFormat.MIMETYPE_AUDIO_DOLBY_MAT + ".")) {
+                        return AudioFormat.ENCODING_DOLBY_MAT;
+                    } else if (MediaFormat.MIMETYPE_AUDIO_OPUS.equals(aidlFormat.encoding)) {
+                        return AudioFormat.ENCODING_OPUS;
+                    } else if (MediaFormat.MIMETYPE_AUDIO_MPEGH_BL_L3.equals(aidlFormat.encoding)) {
+                        return AudioFormat.ENCODING_MPEGH_BL_L3;
+                    } else if (MediaFormat.MIMETYPE_AUDIO_MPEGH_BL_L4.equals(aidlFormat.encoding)) {
+                        return AudioFormat.ENCODING_MPEGH_BL_L4;
+                    } else if (MediaFormat.MIMETYPE_AUDIO_MPEGH_LC_L3.equals(aidlFormat.encoding)) {
+                        return AudioFormat.ENCODING_MPEGH_LC_L3;
+                    } else if (MediaFormat.MIMETYPE_AUDIO_MPEGH_LC_L4.equals(aidlFormat.encoding)) {
+                        return AudioFormat.ENCODING_MPEGH_LC_L4;
+                    } else if (MediaFormat.MIMETYPE_AUDIO_DTS_UHD.equals(aidlFormat.encoding)) {
+                        return AudioFormat.ENCODING_DTS_UHD;
+                    } else if (MediaFormat.MIMETYPE_AUDIO_DRA.equals(aidlFormat.encoding)) {
+                        return AudioFormat.ENCODING_DRA;
+                    } else {
+                        return AudioFormat.ENCODING_INVALID;
+                    }
+                } else {
+                    return AudioFormat.ENCODING_DEFAULT;
+                }
+            case AudioFormatType.SYS_RESERVED_INVALID:
             default:
                 return AudioFormat.ENCODING_INVALID;
         }
     }
+
+    private static native int aidl2legacy_AudioChannelLayout_Parcel_audio_channel_mask_t(
+            Parcel aidl, boolean isInput);
+    private static native Parcel legacy2aidl_audio_channel_mask_t_AudioChannelLayout_Parcel(
+            int legacy, boolean isInput);
+    private static native int aidl2legacy_AudioFormatDescription_Parcel_audio_format_t(
+            Parcel aidl);
+    private static native Parcel legacy2aidl_audio_format_t_AudioFormatDescription_Parcel(
+            int legacy);
 }
diff --git a/media/tests/aidltests/Android.bp b/media/tests/aidltests/Android.bp
new file mode 100644
index 0000000..c3d5fa2
--- /dev/null
+++ b/media/tests/aidltests/Android.bp
@@ -0,0 +1,40 @@
+//
+// 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 {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+    name: "AidlConversionUnitTests",
+    srcs: ["src/**/*.java"],
+    static_libs: [
+        "androidx.test.rules",
+        "platform-test-annotations",
+    ],
+    libs: [
+        "framework",
+    ],
+    sdk_version: "current",
+    platform_apis: true,
+    test_suites: ["device-tests"],
+    certificate: "platform",
+}
diff --git a/media/tests/aidltests/AndroidManifest.xml b/media/tests/aidltests/AndroidManifest.xml
new file mode 100644
index 0000000..ffa895a
--- /dev/null
+++ b/media/tests/aidltests/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="android.media.audio.common">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.media.audio.common"
+        android:label="Unit tests for AIDL conversion utilities" />
+</manifest>
diff --git a/media/tests/aidltests/AndroidTest.xml b/media/tests/aidltests/AndroidTest.xml
new file mode 100644
index 0000000..fb27a3c
--- /dev/null
+++ b/media/tests/aidltests/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs AIDL Unit Tests">
+    <!--Test app needs to be installed when we change its settings below-->
+    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+        <option name="test-file-name" value="AidlConversionUnitTests.apk"/>
+        <option name="cleanup-apks" value="true"/>
+    </target_preparer>
+
+    <option name="test-suite-tag" value="apct"/>
+    <option name="test-tag" value="AidlConversionUnitTests"/>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="android.media.audio.common"/>
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner"/>
+    </test>
+</configuration>
diff --git a/media/tests/aidltests/src/com/android/media/AidlConversionUnitTests.java b/media/tests/aidltests/src/com/android/media/AidlConversionUnitTests.java
new file mode 100644
index 0000000..c9e79e6
--- /dev/null
+++ b/media/tests/aidltests/src/com/android/media/AidlConversionUnitTests.java
@@ -0,0 +1,282 @@
+/*
+ * 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.media.audio.common;
+
+import android.media.AudioFormat;
+import android.media.AudioSystem;
+import android.media.MediaFormat;
+import android.platform.test.annotations.Presubmit;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Unit tests for AidlConversion utilities.
+ *
+ * Run with "atest AidlConversionUnitTests".
+ */
+@Presubmit
+@RunWith(JUnit4.class)
+public final class AidlConversionUnitTests {
+
+    private static final String TAG = "AidlConvTests";
+
+    @Test
+    public void testAudioChannelConversionApiDefault() {
+        final AudioChannelLayout aidl = new AudioChannelLayout();
+        final int api = AidlConversion.aidl2api_AudioChannelLayout_AudioFormatChannelMask(
+                aidl, false /*isInput*/);
+        assertEquals(AudioFormat.CHANNEL_OUT_DEFAULT, api);
+        final int apiInput = AidlConversion.aidl2api_AudioChannelLayout_AudioFormatChannelMask(
+                aidl, true /*isInput*/);
+        assertEquals(AudioFormat.CHANNEL_IN_DEFAULT, apiInput);
+    }
+
+    @Test
+    public void testAudioChannelConversionApiOutput() {
+        final AudioChannelLayout aidl = AudioChannelLayout.layoutMask(
+                AudioChannelLayout.LAYOUT_MONO);
+        final int api = AidlConversion.aidl2api_AudioChannelLayout_AudioFormatChannelMask(
+                aidl, false /*isInput*/);
+        assertEquals(AudioFormat.CHANNEL_OUT_MONO, api);
+    }
+
+    @Test
+    public void testAudioChannelConversionApiInput() {
+        final AudioChannelLayout aidl = AudioChannelLayout.layoutMask(
+                AudioChannelLayout.LAYOUT_MONO);
+        final int api = AidlConversion.aidl2api_AudioChannelLayout_AudioFormatChannelMask(
+                aidl, true /*isInput*/);
+        assertEquals(AudioFormat.CHANNEL_IN_MONO, api);
+    }
+
+    @Test
+    public void testAudioChannelConversionApiIndex() {
+        final AudioChannelLayout aidl = AudioChannelLayout.indexMask(
+                AudioChannelLayout.INDEX_MASK_1);
+        final int api = AidlConversion.aidl2api_AudioChannelLayout_AudioFormatChannelMask(
+                aidl, false /*isInput*/);
+        assertEquals(1, api);
+        final int apiInput = AidlConversion.aidl2api_AudioChannelLayout_AudioFormatChannelMask(
+                aidl, true /*isInput*/);
+        assertEquals(1, apiInput);
+    }
+
+    @Test
+    public void testAudioChannelConversionApiVoice() {
+        final AudioChannelLayout aidl = AudioChannelLayout.voiceMask(
+                AudioChannelLayout.VOICE_UPLINK_MONO);
+        final int api = AidlConversion.aidl2api_AudioChannelLayout_AudioFormatChannelMask(
+                aidl, true /*isInput*/);
+        assertEquals(AudioFormat.CHANNEL_IN_VOICE_UPLINK | AudioFormat.CHANNEL_IN_MONO, api);
+    }
+
+    @Test
+    public void testAudioConfigConfersionApiIndex() {
+        final AudioConfig aidl = new AudioConfig();
+        aidl.sampleRateHz = 8000;
+        aidl.channelMask = AudioChannelLayout.indexMask(AudioChannelLayout.INDEX_MASK_1);
+        aidl.format = createPcm16FormatAidl();
+        // Other fields in AudioConfig are irrelevant.
+        final AudioFormat api = AidlConversion.aidl2api_AudioConfig_AudioFormat(
+                aidl, false /*isInput*/);
+        final AudioFormat apiInput = AidlConversion.aidl2api_AudioConfig_AudioFormat(
+                aidl, true /*isInput*/);
+        assertEquals(api, apiInput);
+        assertEquals(8000, api.getSampleRate());
+        assertEquals(1, api.getChannelIndexMask());
+        assertEquals(AudioFormat.ENCODING_PCM_16BIT, api.getEncoding());
+    }
+
+    @Test
+    public void testAudioConfigConfersionApiLayout() {
+        final AudioConfig aidl = new AudioConfig();
+        aidl.sampleRateHz = 8000;
+        aidl.channelMask = AudioChannelLayout.layoutMask(AudioChannelLayout.LAYOUT_MONO);
+        aidl.format = createPcm16FormatAidl();
+        // Other fields in AudioConfig are irrelevant.
+        final AudioFormat api = AidlConversion.aidl2api_AudioConfig_AudioFormat(
+                aidl, false /*isInput*/);
+        assertEquals(8000, api.getSampleRate());
+        assertEquals(AudioFormat.CHANNEL_OUT_MONO, api.getChannelMask());
+        assertEquals(AudioFormat.ENCODING_PCM_16BIT, api.getEncoding());
+        final AudioFormat apiInput = AidlConversion.aidl2api_AudioConfig_AudioFormat(
+                aidl, true /*isInput*/);
+        assertEquals(8000, apiInput.getSampleRate());
+        assertEquals(AudioFormat.CHANNEL_IN_MONO, apiInput.getChannelMask());
+        assertEquals(AudioFormat.ENCODING_PCM_16BIT, apiInput.getEncoding());
+    }
+
+    @Test
+    public void testAudioFormatConversionApiDefault() {
+        final AudioFormatDescription aidl = new AudioFormatDescription();
+        final int api = AidlConversion.aidl2api_AudioFormat_AudioFormatEncoding(aidl);
+        assertEquals(AudioFormat.ENCODING_DEFAULT, api);
+    }
+
+    @Test
+    public void testAudioFormatConversionApiPcm16() {
+        final AudioFormatDescription aidl = createPcm16FormatAidl();
+        final int api = AidlConversion.aidl2api_AudioFormat_AudioFormatEncoding(aidl);
+        assertEquals(AudioFormat.ENCODING_PCM_16BIT, api);
+    }
+
+    @Test
+    public void testAudioFormatConversionApiAacLc() {
+        final AudioFormatDescription aidl = new AudioFormatDescription();
+        aidl.type = AudioFormatType.NON_PCM;
+        aidl.encoding = MediaFormat.MIMETYPE_AUDIO_AAC_LC;
+        final int api = AidlConversion.aidl2api_AudioFormat_AudioFormatEncoding(aidl);
+        assertEquals(AudioFormat.ENCODING_AAC_LC, api);
+    }
+
+    @Test
+    public void testAudioChannelConversionLegacyDefault() {
+        final int legacy = 0; /*AUDIO_CHANNEL_NONE*/
+        final AudioChannelLayout aidl =
+                AidlConversion.legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+                        legacy, false /*isInput*/);
+        final AudioChannelLayout aidlInput =
+                AidlConversion.legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+                        legacy, true /*isInput*/);
+        assertEquals(aidl, aidlInput);
+        assertEquals(AudioChannelLayout.none, aidl.getTag());
+        final int legacyBack =
+                AidlConversion.aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+                        aidl, false /*isInput*/);
+        final int legacyBackInput =
+                AidlConversion.aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+                        aidl, true /*isInput*/);
+        assertEquals(legacy, legacyBack);
+        assertEquals(legacy, legacyBackInput);
+    }
+
+    @Test
+    public void testAudioChannelConversionLegacyOutput() {
+        final int legacy = 1; /*AUDIO_CHANNEL_OUT_MONO*/
+        final AudioChannelLayout aidl =
+                AidlConversion.legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+                        legacy, false /*isInput*/);
+        assertEquals(AudioChannelLayout.layoutMask, aidl.getTag());
+        assertEquals(AudioChannelLayout.LAYOUT_MONO, aidl.getLayoutMask());
+        final int legacyBack =
+                AidlConversion.aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+                        aidl, false /*isInput*/);
+        assertEquals(legacy, legacyBack);
+    }
+
+    @Test
+    public void testAudioChannelConversionLegacyInput() {
+        final int legacy = 0x10; /*AUDIO_CHANNEL_IN_MONO*/
+        final AudioChannelLayout aidl =
+                AidlConversion.legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+                        legacy, true /*isInput*/);
+        assertEquals(AudioChannelLayout.layoutMask, aidl.getTag());
+        assertEquals(AudioChannelLayout.LAYOUT_MONO, aidl.getLayoutMask());
+        final int legacyBack =
+                AidlConversion.aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+                        aidl, true /*isInput*/);
+        assertEquals(legacy, legacyBack);
+    }
+
+    @Test
+    public void testAudioChannelConversionLegacyIndex() {
+        final int legacy = 0x80000001; /*AUDIO_CHANNEL_INDEX_MASK_1*/
+        final AudioChannelLayout aidl =
+                AidlConversion.legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+                        legacy, false /*isInput*/);
+        final AudioChannelLayout aidlInput =
+                AidlConversion.legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+                        legacy, true /*isInput*/);
+        assertEquals(aidl, aidlInput);
+        assertEquals(AudioChannelLayout.indexMask, aidl.getTag());
+        assertEquals(AudioChannelLayout.INDEX_MASK_1, aidl.getIndexMask());
+        final int legacyBack =
+                AidlConversion.aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+                        aidl, false /*isInput*/);
+        final int legacyBackInput =
+                AidlConversion.aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+                        aidl, true /*isInput*/);
+        assertEquals(legacy, legacyBack);
+        assertEquals(legacy, legacyBackInput);
+    }
+
+    @Test
+    public void testAudioChannelConversionLegacyVoice() {
+        final int legacy = 0x4010; /*AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO*/
+        final AudioChannelLayout aidl =
+                AidlConversion.legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+                        legacy, true /*isInput*/);
+        assertEquals(AudioChannelLayout.voiceMask, aidl.getTag());
+        assertEquals(AudioChannelLayout.VOICE_UPLINK_MONO, aidl.getVoiceMask());
+        final int legacyBack =
+                AidlConversion.aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+                        aidl, true /*isInput*/);
+        assertEquals(legacy, legacyBack);
+    }
+
+    @Test
+    public void testAudioFormatConversionLegacyDefault() {
+        final int legacy = AudioSystem.AUDIO_FORMAT_DEFAULT;
+        final AudioFormatDescription aidl =
+                AidlConversion.legacy2aidl_audio_format_t_AudioFormatDescription(legacy);
+        assertEquals(AudioFormatType.DEFAULT, aidl.type);
+        assertNotNull(aidl.encoding);
+        assertTrue(aidl.encoding.isEmpty());
+        final int legacyBack =
+                AidlConversion.aidl2legacy_AudioFormatDescription_audio_format_t(aidl);
+        assertEquals(legacy, legacyBack);
+    }
+
+    @Test
+    public void testAudioFormatConversionLegacyPcm16() {
+        final int legacy = 1; /*AUDIO_FORMAT_PCM_16_BIT*/
+        final AudioFormatDescription aidl =
+                AidlConversion.legacy2aidl_audio_format_t_AudioFormatDescription(legacy);
+        assertEquals(AudioFormatType.PCM, aidl.type);
+        assertEquals(PcmType.INT_16_BIT, aidl.pcm);
+        final int legacyBack =
+                AidlConversion.aidl2legacy_AudioFormatDescription_audio_format_t(aidl);
+        assertEquals(legacy, legacyBack);
+    }
+
+    @Test
+    public void testAudioFormatConversionLegacyAac() {
+        final int legacy = AudioSystem.AUDIO_FORMAT_AAC;
+        final AudioFormatDescription aidl =
+                AidlConversion.legacy2aidl_audio_format_t_AudioFormatDescription(legacy);
+        assertEquals(AudioFormatType.NON_PCM, aidl.type);
+        assertNotNull(aidl.encoding);
+        assertFalse(aidl.encoding.isEmpty());
+        final int legacyBack =
+                AidlConversion.aidl2legacy_AudioFormatDescription_audio_format_t(aidl);
+        assertEquals(legacy, legacyBack);
+    }
+
+    private AudioFormatDescription createPcm16FormatAidl() {
+        final AudioFormatDescription aidl = new AudioFormatDescription();
+        aidl.type = AudioFormatType.PCM;
+        aidl.pcm = PcmType.INT_16_BIT;
+        return aidl;
+    }
+}
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/ConversionUtil.java b/services/core/java/com/android/server/soundtrigger_middleware/ConversionUtil.java
index 8597e31..c170603 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/ConversionUtil.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/ConversionUtil.java
@@ -304,7 +304,7 @@
         aidlEvent.captureDelayMs = hidlEvent.captureDelayMs;
         aidlEvent.capturePreambleMs = hidlEvent.capturePreambleMs;
         aidlEvent.triggerInData = hidlEvent.triggerInData;
-        aidlEvent.audioConfig = hidl2aidlAudioConfig(hidlEvent.audioConfig);
+        aidlEvent.audioConfig = hidl2aidlAudioConfig(hidlEvent.audioConfig, true /*isInput*/);
         aidlEvent.data = new byte[hidlEvent.data.size()];
         for (int i = 0; i < aidlEvent.data.length; ++i) {
             aidlEvent.data[i] = hidlEvent.data.get(i);
@@ -349,12 +349,15 @@
 
     static @NonNull
     AudioConfig hidl2aidlAudioConfig(
-            @NonNull android.hardware.audio.common.V2_0.AudioConfig hidlConfig) {
+            @NonNull android.hardware.audio.common.V2_0.AudioConfig hidlConfig, boolean isInput) {
         AudioConfig aidlConfig = new AudioConfig();
         aidlConfig.sampleRateHz = hidlConfig.sampleRateHz;
-        aidlConfig.channelMask = AidlConversion.legacy2aidl_audio_channel_mask_t_AudioChannelMask(
-                hidlConfig.channelMask);
-        aidlConfig.format = AidlConversion.legacy2aidl_audio_format_t_AudioFormat(
+        // Relies on the fact that HIDL AudioChannelMask uses the same constant values as
+        // system/audio.h.
+        aidlConfig.channelMask = AidlConversion.legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+                hidlConfig.channelMask, isInput);
+        // Relies on the fact that HIDL AudioFormat uses the same constant values as system/audio.h.
+        aidlConfig.format = AidlConversion.legacy2aidl_audio_format_t_AudioFormatDescription(
                 hidlConfig.format);
         aidlConfig.offloadInfo = hidl2aidlOffloadInfo(hidlConfig.offloadInfo);
         aidlConfig.frameCount = hidlConfig.frameCount;
@@ -366,9 +369,13 @@
             @NonNull android.hardware.audio.common.V2_0.AudioOffloadInfo hidlInfo) {
         AudioOffloadInfo aidlInfo = new AudioOffloadInfo();
         aidlInfo.sampleRateHz = hidlInfo.sampleRateHz;
-        aidlInfo.channelMask = AidlConversion.legacy2aidl_audio_channel_mask_t_AudioChannelMask(
-                hidlInfo.channelMask);
-        aidlInfo.format = AidlConversion.legacy2aidl_audio_format_t_AudioFormat(hidlInfo.format);
+        // Relies on the fact that HIDL AudioChannelMask uses the same constant values as
+        // system/audio.h.
+        aidlInfo.channelMask = AidlConversion.legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+                hidlInfo.channelMask, false /*isInput*/);
+        // Relies on the fact that HIDL AudioFormat uses the same constant values as system/audio.h.
+        aidlInfo.format = AidlConversion.legacy2aidl_audio_format_t_AudioFormatDescription(
+                hidlInfo.format);
         aidlInfo.streamType = AidlConversion.legacy2aidl_audio_stream_type_t_AudioStreamType(
                 hidlInfo.streamType);
         aidlInfo.bitRatePerSecond = hidlInfo.bitRatePerSecond;
diff --git a/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/TestUtil.java b/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/TestUtil.java
index 4eca298..6ed9dde 100644
--- a/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/TestUtil.java
+++ b/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/TestUtil.java
@@ -23,9 +23,12 @@
 import android.annotation.NonNull;
 import android.hardware.soundtrigger.V2_1.ISoundTriggerHw;
 import android.hardware.soundtrigger.V2_4.ISoundTriggerHwCallback;
-import android.media.audio.common.AudioChannelMask;
+import android.media.AudioFormat;
+import android.media.MediaFormat;
+import android.media.audio.common.AudioChannelLayout;
 import android.media.audio.common.AudioConfig;
-import android.media.audio.common.AudioFormat;
+import android.media.audio.common.AudioFormatDescription;
+import android.media.audio.common.AudioFormatType;
 import android.media.soundtrigger.AudioCapabilities;
 import android.media.soundtrigger.ConfidenceLevel;
 import android.media.soundtrigger.Phrase;
@@ -53,6 +56,8 @@
  * corresponding objects generated by the system under test.
  */
 class TestUtil {
+    private static final int AUDIO_FORMAT_MP3 = 0x01000000;  // matches native
+
     static SoundModel createGenericSoundModel() {
         return createSoundModel(SoundModelType.GENERIC);
     }
@@ -310,8 +315,8 @@
         halEvent.capturePreambleMs = 345;
         halEvent.triggerInData = true;
         halEvent.audioConfig.sampleRateHz = 456;
-        halEvent.audioConfig.channelMask = AudioChannelMask.IN_LEFT;
-        halEvent.audioConfig.format = AudioFormat.MP3;
+        halEvent.audioConfig.channelMask = AudioFormat.CHANNEL_IN_MONO;  // matches native
+        halEvent.audioConfig.format = AUDIO_FORMAT_MP3;
         // hwEvent.audioConfig.offloadInfo is irrelevant.
         halEvent.data.add((byte) 31);
         halEvent.data.add((byte) 32);
@@ -319,6 +324,13 @@
         return halEvent;
     }
 
+    static AudioFormatDescription createAudioFormatMp3() {
+        AudioFormatDescription format = new AudioFormatDescription();
+        format.type = AudioFormatType.NON_PCM;
+        format.encoding = MediaFormat.MIMETYPE_AUDIO_MPEG;  // MP3
+        return format;
+    }
+
     static RecognitionEvent createRecognitionEvent(@RecognitionStatus int status) {
         RecognitionEvent event = new RecognitionEvent();
         event.status = status;
@@ -329,8 +341,9 @@
         event.triggerInData = true;
         event.audioConfig = new AudioConfig();
         event.audioConfig.sampleRateHz = 456;
-        event.audioConfig.channelMask = AudioChannelMask.IN_LEFT;
-        event.audioConfig.format = AudioFormat.MP3;
+        event.audioConfig.channelMask = AudioChannelLayout.layoutMask(
+                AudioChannelLayout.LAYOUT_MONO);
+        event.audioConfig.format = createAudioFormatMp3();
         //event.audioConfig.offloadInfo is irrelevant.
         event.data = new byte[]{31, 32, 33};
         return event;
@@ -355,8 +368,9 @@
         assertEquals(345, event.capturePreambleMs);
         assertTrue(event.triggerInData);
         assertEquals(456, event.audioConfig.sampleRateHz);
-        assertEquals(AudioChannelMask.IN_LEFT, event.audioConfig.channelMask);
-        assertEquals(AudioFormat.MP3, event.audioConfig.format);
+        assertEquals(AudioChannelLayout.layoutMask(AudioChannelLayout.LAYOUT_MONO),
+                event.audioConfig.channelMask);
+        assertEquals(createAudioFormatMp3(), event.audioConfig.format);
         assertArrayEquals(new byte[]{31, 32, 33}, event.data);
     }