Merge changes from topic "aidlize-audioflinger"

* changes:
  Remove manual parceling from Interpolator and VolumeShaper
  Make use of AIDL unions.
  Convert AudioFlinger create* arguments to AIDL
  Small fixes to AidlConversion
  Correctly set offload info in AudioTrack
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..87a8f41
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,27 @@
+aidl_interface {
+    name: "av-types-aidl",
+    unstable: true,
+    host_supported: true,
+    vendor_available: true,
+    double_loadable: true,
+    local_include_dir: "aidl",
+    srcs: [
+        "aidl/android/media/InterpolatorConfig.aidl",
+        "aidl/android/media/InterpolatorType.aidl",
+        "aidl/android/media/VolumeShaperConfiguration.aidl",
+        "aidl/android/media/VolumeShaperConfigurationOptionFlag.aidl",
+        "aidl/android/media/VolumeShaperConfigurationType.aidl",
+        "aidl/android/media/VolumeShaperOperation.aidl",
+        "aidl/android/media/VolumeShaperOperationFlag.aidl",
+        "aidl/android/media/VolumeShaperState.aidl",
+    ],
+    backend: {
+        cpp: {
+            min_sdk_version: "29",
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.media",
+            ],
+        },
+    },
+}
diff --git a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl b/aidl/android/media/InterpolatorConfig.aidl
similarity index 66%
copy from media/libaudioclient/aidl/android/media/AudioSessionType.aidl
copy to aidl/android/media/InterpolatorConfig.aidl
index d305c29..ef7486e 100644
--- a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl
+++ b/aidl/android/media/InterpolatorConfig.aidl
@@ -13,13 +13,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.media;
 
-@Backing(type="int")
-enum AudioSessionType {
-    DEVICE = -2,
-    OUTPUT_STAGE = -1,
-    OUTPUT_MIX = 0,
-    ALLOCATE = 0,
-    NONE = 0,
+import android.media.InterpolatorType;
+
+/**
+ * {@hide}
+ */
+parcelable InterpolatorConfig {
+    InterpolatorType type;
+    /** For cubic interpolation, the boundary conditions in slope. */
+    float firstSlope;
+    float lastSlope;
+    /** A flattened list of <x, y> pairs, monotonically increasing in x. */
+    float[] xy;
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl b/aidl/android/media/InterpolatorType.aidl
similarity index 67%
copy from media/libaudioclient/aidl/android/media/AudioSessionType.aidl
copy to aidl/android/media/InterpolatorType.aidl
index d305c29..b722cad 100644
--- a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl
+++ b/aidl/android/media/InterpolatorType.aidl
@@ -15,11 +15,20 @@
  */
 package android.media;
 
+/**
+ * Polynomial spline interpolators.
+ *
+ * {@hide}
+ */
 @Backing(type="int")
-enum AudioSessionType {
-    DEVICE = -2,
-    OUTPUT_STAGE = -1,
-    OUTPUT_MIX = 0,
-    ALLOCATE = 0,
-    NONE = 0,
+enum InterpolatorType {
+    /** Not continuous. */
+    STEP,
+    /** C0. */
+    LINEAR,
+    /** C1. */
+    CUBIC,
+    /** C1 (to provide locally monotonic curves). */
+    CUBIC_MONOTONIC,
+    // CUBIC_C2, // TODO - requires global computation / cache
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl b/aidl/android/media/VolumeShaperConfiguration.aidl
similarity index 60%
copy from media/libaudioclient/aidl/android/media/AudioSessionType.aidl
copy to aidl/android/media/VolumeShaperConfiguration.aidl
index d305c29..6361851 100644
--- a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl
+++ b/aidl/android/media/VolumeShaperConfiguration.aidl
@@ -13,13 +13,21 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.media;
 
-@Backing(type="int")
-enum AudioSessionType {
-    DEVICE = -2,
-    OUTPUT_STAGE = -1,
-    OUTPUT_MIX = 0,
-    ALLOCATE = 0,
-    NONE = 0,
+import android.media.InterpolatorConfig;
+import android.media.VolumeShaperConfigurationOptionFlag;
+import android.media.VolumeShaperConfigurationType;
+
+/**
+ * {@hide}
+ */
+parcelable VolumeShaperConfiguration {
+    VolumeShaperConfigurationType type;
+    int id;
+    /** Bitmask, indexed by VolumeShaperConfigurationOptionFlag. */
+    int optionFlags;
+    double durationMs;
+    InterpolatorConfig interpolatorConfig;
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl b/aidl/android/media/VolumeShaperConfigurationOptionFlag.aidl
similarity index 84%
copy from media/libaudioclient/aidl/android/media/AudioSessionType.aidl
copy to aidl/android/media/VolumeShaperConfigurationOptionFlag.aidl
index d305c29..f583cee 100644
--- a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl
+++ b/aidl/android/media/VolumeShaperConfigurationOptionFlag.aidl
@@ -16,10 +16,7 @@
 package android.media;
 
 @Backing(type="int")
-enum AudioSessionType {
-    DEVICE = -2,
-    OUTPUT_STAGE = -1,
-    OUTPUT_MIX = 0,
-    ALLOCATE = 0,
-    NONE = 0,
+enum VolumeShaperConfigurationOptionFlag {
+    VOLUME_IN_DBFS,
+    CLOCK_TIME,
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl b/aidl/android/media/VolumeShaperConfigurationType.aidl
similarity index 84%
copy from media/libaudioclient/aidl/android/media/AudioSessionType.aidl
copy to aidl/android/media/VolumeShaperConfigurationType.aidl
index d305c29..aa6334e 100644
--- a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl
+++ b/aidl/android/media/VolumeShaperConfigurationType.aidl
@@ -16,10 +16,7 @@
 package android.media;
 
 @Backing(type="int")
-enum AudioSessionType {
-    DEVICE = -2,
-    OUTPUT_STAGE = -1,
-    OUTPUT_MIX = 0,
-    ALLOCATE = 0,
-    NONE = 0,
+enum VolumeShaperConfigurationType {
+    ID,
+    SCALE,
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl b/aidl/android/media/VolumeShaperOperation.aidl
similarity index 67%
copy from media/libaudioclient/aidl/android/media/AudioSessionType.aidl
copy to aidl/android/media/VolumeShaperOperation.aidl
index d305c29..dd9a0e7 100644
--- a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl
+++ b/aidl/android/media/VolumeShaperOperation.aidl
@@ -13,13 +13,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.media;
 
-@Backing(type="int")
-enum AudioSessionType {
-    DEVICE = -2,
-    OUTPUT_STAGE = -1,
-    OUTPUT_MIX = 0,
-    ALLOCATE = 0,
-    NONE = 0,
+/**
+ * {@hide}
+ */
+parcelable VolumeShaperOperation {
+    /** Operations to do. Bitmask of VolumeShaperOperationFlag. */
+    int flags;
+    /** If >= 0 the id to remove in a replace operation. */
+    int replaceId;
+    /** Position in the curve to set if a valid number (not nan). */
+    float xOffset;
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl b/aidl/android/media/VolumeShaperOperationFlag.aidl
similarity index 79%
copy from media/libaudioclient/aidl/android/media/AudioSessionType.aidl
copy to aidl/android/media/VolumeShaperOperationFlag.aidl
index d305c29..8fe5275 100644
--- a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl
+++ b/aidl/android/media/VolumeShaperOperationFlag.aidl
@@ -16,10 +16,11 @@
 package android.media;
 
 @Backing(type="int")
-enum AudioSessionType {
-    DEVICE = -2,
-    OUTPUT_STAGE = -1,
-    OUTPUT_MIX = 0,
-    ALLOCATE = 0,
-    NONE = 0,
+enum VolumeShaperOperationFlag {
+    /** The absence of this flag indicates "play". */
+    REVERSE,
+    TERMINATE,
+    JOIN,
+    DELAY,
+    CREATE_IF_NECESSARY,
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl b/aidl/android/media/VolumeShaperState.aidl
similarity index 72%
copy from media/libaudioclient/aidl/android/media/AudioSessionType.aidl
copy to aidl/android/media/VolumeShaperState.aidl
index d305c29..4085e2b 100644
--- a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl
+++ b/aidl/android/media/VolumeShaperState.aidl
@@ -13,13 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.media;
 
-@Backing(type="int")
-enum AudioSessionType {
-    DEVICE = -2,
-    OUTPUT_STAGE = -1,
-    OUTPUT_MIX = 0,
-    ALLOCATE = 0,
-    NONE = 0,
+/**
+ * {@hide}
+ */
+parcelable VolumeShaperState {
+    /** Linear volume in the range MIN_LINEAR_VOLUME to MAX_LINEAR_VOLUME. */
+    float volume;
+    /** Position on curve expressed from MIN_CURVE_TIME to MAX_CURVE_TIME. */
+    float xOffset;
 }
diff --git a/include/media/Interpolator.h b/include/media/Interpolator.h
index 703cf77..2004acb 100644
--- a/include/media/Interpolator.h
+++ b/include/media/Interpolator.h
@@ -21,6 +21,7 @@
 #include <sstream>
 #include <unordered_map>
 
+#include <android/media/InterpolatorConfig.h>
 #include <binder/Parcel.h>
 #include <utils/RefBase.h>
 
@@ -39,17 +40,10 @@
 class Interpolator : public std::map<S, T> {
 public:
     // Polynomial spline interpolators
-    // Extend only at the end of enum, as this must match order in VolumeShapers.java.
-    enum InterpolatorType : int32_t {
-        INTERPOLATOR_TYPE_STEP,   // Not continuous
-        INTERPOLATOR_TYPE_LINEAR, // C0
-        INTERPOLATOR_TYPE_CUBIC,  // C1
-        INTERPOLATOR_TYPE_CUBIC_MONOTONIC, // C1 (to provide locally monotonic curves)
-        // INTERPOLATOR_TYPE_CUBIC_C2, // TODO - requires global computation / cache
-    };
+    using InterpolatorType  = media::InterpolatorType;
 
     explicit Interpolator(
-            InterpolatorType interpolatorType = INTERPOLATOR_TYPE_LINEAR,
+            InterpolatorType interpolatorType = InterpolatorType::LINEAR,
             bool cache = true)
         : mCache(cache)
         , mFirstSlope(0)
@@ -82,13 +76,13 @@
 
         // now that we have two adjacent points:
         switch (mInterpolatorType) {
-        case INTERPOLATOR_TYPE_STEP:
+        case InterpolatorType::STEP:
             return high->first == x ? high->second : low->second;
-        case INTERPOLATOR_TYPE_LINEAR:
+        case InterpolatorType::LINEAR:
             return ((high->first - x) * low->second + (x - low->first) * high->second)
                     / (high->first - low->first);
-        case INTERPOLATOR_TYPE_CUBIC:
-        case INTERPOLATOR_TYPE_CUBIC_MONOTONIC:
+        case InterpolatorType::CUBIC:
+        case InterpolatorType::CUBIC_MONOTONIC:
         default: {
             // See https://en.wikipedia.org/wiki/Cubic_Hermite_spline
 
@@ -116,7 +110,7 @@
             // non catmullRom (finite difference) with regular cubic;
             // the choices here minimize computation.
             bool monotonic, catmullRom;
-            if (mInterpolatorType == INTERPOLATOR_TYPE_CUBIC_MONOTONIC) {
+            if (mInterpolatorType == InterpolatorType::CUBIC_MONOTONIC) {
                 monotonic = true;
                 catmullRom = false;
             } else {
@@ -202,11 +196,11 @@
 
     status_t setInterpolatorType(InterpolatorType interpolatorType) {
         switch (interpolatorType) {
-        case INTERPOLATOR_TYPE_STEP:   // Not continuous
-        case INTERPOLATOR_TYPE_LINEAR: // C0
-        case INTERPOLATOR_TYPE_CUBIC:  // C1
-        case INTERPOLATOR_TYPE_CUBIC_MONOTONIC: // C1 + other constraints
-        // case INTERPOLATOR_TYPE_CUBIC_C2:
+        case InterpolatorType::STEP:   // Not continuous
+        case InterpolatorType::LINEAR: // C0
+        case InterpolatorType::CUBIC:  // C1
+        case InterpolatorType::CUBIC_MONOTONIC: // C1 + other constraints
+        // case InterpolatorType::CUBIC_C2:
             mInterpolatorType = interpolatorType;
             return NO_ERROR;
         default:
@@ -235,49 +229,50 @@
         mMemo.clear();
     }
 
+    // TODO(ytai): remove this method once it is not used.
     status_t writeToParcel(Parcel *parcel) const {
-        if (parcel == nullptr) {
-            return BAD_VALUE;
-        }
-        status_t res = parcel->writeInt32(mInterpolatorType)
-                ?: parcel->writeFloat(mFirstSlope)
-                ?: parcel->writeFloat(mLastSlope)
-                ?: parcel->writeUint32((uint32_t)this->size()); // silent truncation
-        if (res != NO_ERROR) {
-            return res;
-        }
-        for (const auto &pt : *this) {
-            res = parcel->writeFloat(pt.first)
-                    ?: parcel->writeFloat(pt.second);
-            if (res != NO_ERROR) {
-                return res;
-            }
-        }
-        return NO_ERROR;
+        media::InterpolatorConfig config;
+        writeToConfig(&config);
+        return config.writeToParcel(parcel);
     }
 
+    void writeToConfig(media::InterpolatorConfig *config) const {
+        config->type = mInterpolatorType;
+        config->firstSlope = mFirstSlope;
+        config->lastSlope = mLastSlope;
+        for (const auto &pt : *this) {
+            config->xy.push_back(pt.first);
+            config->xy.push_back(pt.second);
+        }
+    }
+
+    // TODO(ytai): remove this method once it is not used.
     status_t readFromParcel(const Parcel &parcel) {
-        this->clear();
-        int32_t type;
-        uint32_t size;
-        status_t res = parcel.readInt32(&type)
-                        ?: parcel.readFloat(&mFirstSlope)
-                        ?: parcel.readFloat(&mLastSlope)
-                        ?: parcel.readUint32(&size)
-                        ?: setInterpolatorType((InterpolatorType)type);
+        media::InterpolatorConfig config;
+        status_t res = config.readFromParcel(&parcel);
         if (res != NO_ERROR) {
             return res;
         }
+        return readFromConfig(config);
+    }
+
+    status_t readFromConfig(const media::InterpolatorConfig &config) {
+        this->clear();
+        setInterpolatorType(config.type);
+        if ((config.xy.size() & 1) != 0) {
+            // xy size must be even.
+            return BAD_VALUE;
+        }
+        uint32_t size = config.xy.size() / 2;
+        mFirstSlope = config.firstSlope;
+        mLastSlope = config.lastSlope;
+
         // Note: We don't need to check size is within some bounds as
         // the Parcel read will fail if size is incorrectly specified too large.
         float lastx;
         for (uint32_t i = 0; i < size; ++i) {
-            float x, y;
-            res = parcel.readFloat(&x)
-                    ?: parcel.readFloat(&y);
-            if (res != NO_ERROR) {
-                return res;
-            }
+            float x = config.xy[i * 2];
+            float y = config.xy[i * 2 + 1];
             if ((i > 0 && !(x > lastx)) /* handle nan */
                     || y != y /* handle nan */) {
                 // This is a std::map object which imposes sorted order
diff --git a/include/media/VolumeShaper.h b/include/media/VolumeShaper.h
index fe519bb..f8ead2f 100644
--- a/include/media/VolumeShaper.h
+++ b/include/media/VolumeShaper.h
@@ -22,6 +22,11 @@
 #include <math.h>
 #include <sstream>
 
+#include <android/media/VolumeShaperConfiguration.h>
+#include <android/media/VolumeShaperConfigurationOptionFlag.h>
+#include <android/media/VolumeShaperOperation.h>
+#include <android/media/VolumeShaperOperationFlag.h>
+#include <android/media/VolumeShaperState.h>
 #include <binder/Parcel.h>
 #include <media/Interpolator.h>
 #include <utils/Mutex.h>
@@ -284,30 +289,38 @@
             clampVolume();
         }
 
-        // The parcel layout must match VolumeShaper.java
         status_t writeToParcel(Parcel *parcel) const override {
-            if (parcel == nullptr) return BAD_VALUE;
-            return parcel->writeInt32((int32_t)mType)
-                    ?: parcel->writeInt32(mId)
-                    ?: mType == TYPE_ID
-                        ? NO_ERROR
-                        : parcel->writeInt32((int32_t)mOptionFlags)
-                            ?: parcel->writeDouble(mDurationMs)
-                            ?: Interpolator<S, T>::writeToParcel(parcel);
+            VolumeShaperConfiguration parcelable;
+            writeToParcelable(&parcelable);
+            return parcelable.writeToParcel(parcel);
         }
 
-        status_t readFromParcel(const Parcel *parcel) override {
-            int32_t type, optionFlags;
-            return parcel->readInt32(&type)
-                    ?: setType((Type)type)
-                    ?: parcel->readInt32(&mId)
-                    ?: mType == TYPE_ID
-                        ? NO_ERROR
-                        : parcel->readInt32(&optionFlags)
-                            ?: setOptionFlags((OptionFlag)optionFlags)
-                            ?: parcel->readDouble(&mDurationMs)
-                            ?: Interpolator<S, T>::readFromParcel(*parcel)
-                            ?: checkCurve();
+        void writeToParcelable(VolumeShaperConfiguration *parcelable) const {
+            parcelable->id = getId();
+            parcelable->type = getTypeAsAidl();
+            parcelable->optionFlags = 0;
+            if (mType != TYPE_ID) {
+                parcelable->optionFlags = getOptionFlagsAsAidl();
+                parcelable->durationMs = getDurationMs();
+                Interpolator<S, T>::writeToConfig(&parcelable->interpolatorConfig);
+            }
+        }
+
+        status_t readFromParcel(const Parcel* parcel) override {
+            VolumeShaperConfiguration data;
+            return data.readFromParcel(parcel)
+                   ?: readFromParcelable(data);
+        }
+
+        status_t readFromParcelable(const VolumeShaperConfiguration& parcelable) {
+            setId(parcelable.id);
+            return setTypeFromAidl(parcelable.type)
+                   ?: mType == TYPE_ID
+                      ? NO_ERROR
+                      : setOptionFlagsFromAidl(parcelable.optionFlags)
+                        ?: setDurationMs(parcelable.durationMs)
+                           ?: Interpolator<S, T>::readFromConfig(parcelable.interpolatorConfig)
+                              ?: checkCurve();
         }
 
         // Returns a string for debug printing.
@@ -329,6 +342,51 @@
         int32_t mId;             // A valid id is >= 0.
         OptionFlag mOptionFlags; // option flags for the configuration.
         double mDurationMs;      // duration, must be > 0; default is 1000 ms.
+
+        int32_t getOptionFlagsAsAidl() const {
+            int32_t result = 0;
+            if (getOptionFlags() & OPTION_FLAG_VOLUME_IN_DBFS) {
+                result |=
+                        1 << static_cast<int>(VolumeShaperConfigurationOptionFlag::VOLUME_IN_DBFS);
+            }
+            if (getOptionFlags() & OPTION_FLAG_CLOCK_TIME) {
+                result |= 1 << static_cast<int>(VolumeShaperConfigurationOptionFlag::CLOCK_TIME);
+            }
+            return result;
+        }
+
+        status_t setOptionFlagsFromAidl(int32_t aidl) {
+            std::underlying_type_t<OptionFlag> options = 0;
+            if (aidl & (1 << static_cast<int>(VolumeShaperConfigurationOptionFlag::VOLUME_IN_DBFS))) {
+                options |= OPTION_FLAG_VOLUME_IN_DBFS;
+            }
+            if (aidl & (1 << static_cast<int>(VolumeShaperConfigurationOptionFlag::CLOCK_TIME))) {
+                options |= OPTION_FLAG_CLOCK_TIME;
+            }
+            return setOptionFlags(static_cast<OptionFlag>(options));
+        }
+
+        status_t setTypeFromAidl(VolumeShaperConfigurationType aidl) {
+            switch (aidl) {
+                case VolumeShaperConfigurationType::ID:
+                    return setType(TYPE_ID);
+                case VolumeShaperConfigurationType::SCALE:
+                    return setType(TYPE_SCALE);
+                default:
+                    return BAD_VALUE;
+            }
+        }
+
+        VolumeShaperConfigurationType getTypeAsAidl() const {
+            switch (getType()) {
+                case TYPE_ID:
+                    return VolumeShaperConfigurationType::ID;
+                case TYPE_SCALE:
+                    return VolumeShaperConfigurationType::SCALE;
+                default:
+                    LOG_ALWAYS_FATAL("Shouldn't get here");
+            }
+        }
     }; // Configuration
 
     /* VolumeShaper::Operation expresses an operation to perform on the
@@ -420,19 +478,29 @@
             return NO_ERROR;
         }
 
-        status_t writeToParcel(Parcel *parcel) const override {
+        status_t writeToParcel(Parcel* parcel) const override {
             if (parcel == nullptr) return BAD_VALUE;
-            return parcel->writeInt32((int32_t)mFlags)
-                    ?: parcel->writeInt32(mReplaceId)
-                    ?: parcel->writeFloat(mXOffset);
+            VolumeShaperOperation op;
+            writeToParcelable(&op);
+            return op.writeToParcel(parcel);
         }
 
-        status_t readFromParcel(const Parcel *parcel) override {
-            int32_t flags;
-            return parcel->readInt32(&flags)
-                    ?: parcel->readInt32(&mReplaceId)
-                    ?: parcel->readFloat(&mXOffset)
-                    ?: setFlags((Flag)flags);
+        void writeToParcelable(VolumeShaperOperation* op) const {
+            op->flags = getFlagsAsAidl();
+            op->replaceId = mReplaceId;
+            op->xOffset = mXOffset;
+        }
+
+        status_t readFromParcel(const Parcel* parcel) override {
+            VolumeShaperOperation op;
+            return op.readFromParcel(parcel)
+                   ?: readFromParcelable(op);
+        }
+
+        status_t readFromParcelable(const VolumeShaperOperation& op) {
+            mReplaceId = op.replaceId;
+            mXOffset = op.xOffset;
+            return setFlagsFromAidl(op.flags);
         }
 
         std::string toString() const {
@@ -445,6 +513,48 @@
         }
 
     private:
+        status_t setFlagsFromAidl(int32_t aidl) {
+            std::underlying_type_t<Flag> flags = 0;
+            if (aidl & (1 << static_cast<int>(VolumeShaperOperationFlag::REVERSE))) {
+                flags |= FLAG_REVERSE;
+            }
+            if (aidl & (1 << static_cast<int>(VolumeShaperOperationFlag::TERMINATE))) {
+                flags |= FLAG_TERMINATE;
+            }
+            if (aidl & (1 << static_cast<int>(VolumeShaperOperationFlag::JOIN))) {
+                flags |= FLAG_JOIN;
+            }
+            if (aidl & (1 << static_cast<int>(VolumeShaperOperationFlag::DELAY))) {
+                flags |= FLAG_DELAY;
+            }
+            if (aidl & (1 << static_cast<int>(VolumeShaperOperationFlag::CREATE_IF_NECESSARY))) {
+                flags |= FLAG_CREATE_IF_NECESSARY;
+            }
+            return setFlags(static_cast<Flag>(flags));
+        }
+
+        int32_t getFlagsAsAidl() const {
+            int32_t aidl = 0;
+            std::underlying_type_t<Flag> flags = getFlags();
+            if (flags & FLAG_REVERSE) {
+                aidl |= (1 << static_cast<int>(VolumeShaperOperationFlag::REVERSE));
+            }
+            if (flags & FLAG_TERMINATE) {
+                aidl |= (1 << static_cast<int>(VolumeShaperOperationFlag::TERMINATE));
+            }
+            if (flags & FLAG_JOIN) {
+                aidl |= (1 << static_cast<int>(VolumeShaperOperationFlag::JOIN));
+            }
+            if (flags & FLAG_DELAY) {
+                aidl |= (1 << static_cast<int>(VolumeShaperOperationFlag::DELAY));
+            }
+            if (flags & FLAG_CREATE_IF_NECESSARY) {
+                aidl |= (1 << static_cast<int>(VolumeShaperOperationFlag::CREATE_IF_NECESSARY));
+            }
+            return aidl;
+        }
+
+    private:
         Flag mFlags;        // operation to do
         int32_t mReplaceId; // if >= 0 the id to remove in a replace operation.
         S mXOffset;         // position in the curve to set if a valid number (not nan)
@@ -483,15 +593,28 @@
             mXOffset = xOffset;
         }
 
-        status_t writeToParcel(Parcel *parcel) const override {
+        status_t writeToParcel(Parcel* parcel) const override {
             if (parcel == nullptr) return BAD_VALUE;
-            return parcel->writeFloat(mVolume)
-                    ?: parcel->writeFloat(mXOffset);
+            VolumeShaperState state;
+            writeToParcelable(&state);
+            return state.writeToParcel(parcel);
         }
 
-        status_t readFromParcel(const Parcel *parcel) override {
-            return parcel->readFloat(&mVolume)
-                     ?: parcel->readFloat(&mXOffset);
+        void writeToParcelable(VolumeShaperState* parcelable) const {
+            parcelable->volume = mVolume;
+            parcelable->xOffset = mXOffset;
+        }
+
+        status_t readFromParcel(const Parcel* parcel) override {
+            VolumeShaperState state;
+            return state.readFromParcel(parcel)
+                   ?: readFromParcelable(state);
+        }
+
+        status_t readFromParcelable(const VolumeShaperState& parcelable) {
+            mVolume = parcelable.volume;
+            mXOffset = parcelable.xOffset;
+            return OK;
         }
 
         std::string toString() const {
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index 95a6a4a..d362d8f 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#include <limits>
-
 #define LOG_TAG "AidlConversion"
 //#define LOG_NDEBUG 0
 #include <system/audio.h>
@@ -23,12 +21,7 @@
 
 #include "media/AidlConversion.h"
 
-#define VALUE_OR_RETURN(result)                          \
-    ({                                                   \
-        auto _tmp = (result);                            \
-        if (!_tmp.ok()) return unexpected(_tmp.error()); \
-        _tmp.value();                                    \
-    })
+#include <media/ShmemCompat.h>
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // Utilities
@@ -118,27 +111,30 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
+// Utilities for working with AIDL unions.
+// UNION_GET(obj, fieldname) returns a ConversionResult<T> containing either the strongly-typed
+//   value of the respective field, or BAD_VALUE if the union is not set to the requested field.
+// UNION_SET(obj, fieldname, value) sets the requested field to the given value.
 
-template<typename To, typename From>
-ConversionResult<To> convertIntegral(From from) {
-    // Special handling is required for signed / vs. unsigned comparisons, since otherwise we may
-    // have the signed converted to unsigned and produce wrong results.
-    if (std::is_signed_v<From> && !std::is_signed_v<To>) {
-        if (from < 0 || from > std::numeric_limits<To>::max()) {
-            return unexpected(BAD_VALUE);
-        }
-    } else if (std::is_signed_v<To> && !std::is_signed_v<From>) {
-        if (from > std::numeric_limits<To>::max()) {
-            return unexpected(BAD_VALUE);
-        }
-    } else {
-        if (from < std::numeric_limits<To>::min() || from > std::numeric_limits<To>::max()) {
-            return unexpected(BAD_VALUE);
-        }
+template<typename T, typename T::Tag tag>
+using UnionFieldType = std::decay_t<decltype(std::declval<T>().template get<tag>())>;
+
+template<typename T, typename T::Tag tag>
+ConversionResult<UnionFieldType<T, tag>> unionGetField(const T& u) {
+    if (u.getTag() != tag) {
+        return unexpected(BAD_VALUE);
     }
-    return static_cast<To>(from);
+    return u.template get<tag>();
 }
 
+#define UNION_GET(u, field) \
+    unionGetField<std::decay_t<decltype(u)>, std::decay_t<decltype(u)>::Tag::field>(u)
+
+#define UNION_SET(u, field, value) \
+    (u).set<std::decay_t<decltype(u)>::Tag::field>(value)
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
 template<typename To, typename From>
 ConversionResult<To> convertReinterpret(From from) {
     static_assert(sizeof(From) == sizeof(To));
@@ -210,6 +206,90 @@
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // Converters
 
+status_t aidl2legacy_string(std::string_view aidl, char* dest, size_t maxSize) {
+    if (aidl.size() > maxSize - 1) {
+        return BAD_VALUE;
+    }
+    aidl.copy(dest, aidl.size());
+    dest[aidl.size()] = '\0';
+    return OK;
+}
+
+ConversionResult<std::string> legacy2aidl_string(const char* legacy, size_t maxSize) {
+    if (legacy == nullptr) {
+        return unexpected(BAD_VALUE);
+    }
+    if (strnlen(legacy, maxSize) == maxSize) {
+        // No null-terminator.
+        return unexpected(BAD_VALUE);
+    }
+    return std::string(legacy);
+}
+
+ConversionResult<audio_module_handle_t> aidl2legacy_int32_t_audio_module_handle_t(int32_t aidl) {
+    return convertReinterpret<audio_module_handle_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_module_handle_t_int32_t(audio_module_handle_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_io_handle_t> aidl2legacy_int32_t_audio_io_handle_t(int32_t aidl) {
+    return convertReinterpret<audio_io_handle_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_io_handle_t_int32_t(audio_io_handle_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_port_handle_t> aidl2legacy_int32_t_audio_port_handle_t(int32_t aidl) {
+    return convertReinterpret<audio_port_handle_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_port_handle_t_int32_t(audio_port_handle_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_patch_handle_t> aidl2legacy_int32_t_audio_patch_handle_t(int32_t aidl) {
+    return convertReinterpret<audio_patch_handle_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_patch_handle_t_int32_t(audio_patch_handle_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_unique_id_t> aidl2legacy_int32_t_audio_unique_id_t(int32_t aidl) {
+    return convertReinterpret<audio_unique_id_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_unique_id_t_int32_t(audio_unique_id_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<pid_t> aidl2legacy_int32_t_pid_t(int32_t aidl) {
+    return convertReinterpret<pid_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_pid_t_int32_t(pid_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<uid_t> aidl2legacy_int32_t_uid_t(int32_t aidl) {
+    return convertReinterpret<uid_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_uid_t_int32_t(uid_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<String16> aidl2legacy_string_view_String16(std::string_view aidl) {
+    return String16(aidl.data(), aidl.size());
+}
+
+ConversionResult<std::string> legacy2aidl_String16_string(const String16& legacy) {
+    return std::string(String8(legacy).c_str());
+}
+
 // The legacy enum is unnamed. Thus, we use int.
 ConversionResult<int> aidl2legacy_AudioPortConfigType(media::AudioPortConfigType aidl) {
     switch (aidl) {
@@ -642,14 +722,13 @@
 }
 
 ConversionResult<audio_output_flags_t> aidl2legacy_audio_output_flags_mask(int32_t aidl) {
-    using LegacyMask = std::underlying_type_t<audio_output_flags_t>;
-
-    LegacyMask converted = VALUE_OR_RETURN(
-            (convertBitmask<LegacyMask, int32_t, audio_output_flags_t, media::AudioOutputFlags>(
-                    aidl, aidl2legacy_AudioOutputFlags_audio_output_flags_t,
-                    index2enum_index<media::AudioOutputFlags>,
-                    enumToMask_bitmask<LegacyMask, audio_output_flags_t>)));
-    return convertReinterpret<audio_output_flags_t>(converted);
+    return convertBitmask<audio_output_flags_t,
+                          int32_t,
+                          audio_output_flags_t,
+                          media::AudioOutputFlags>(
+            aidl, aidl2legacy_AudioOutputFlags_audio_output_flags_t,
+            index2enum_index<media::AudioOutputFlags>,
+            enumToMask_bitmask<audio_output_flags_t, audio_output_flags_t>);
 }
 
 ConversionResult<int32_t> legacy2aidl_audio_output_flags_mask(audio_output_flags_t legacy) {
@@ -665,27 +744,18 @@
 ConversionResult<audio_io_flags> aidl2legacy_AudioIoFlags_audio_io_flags(
         const media::AudioIoFlags& aidl, media::AudioPortRole role, media::AudioPortType type) {
     audio_io_flags legacy;
-    // Our way of representing a union in AIDL is to have multiple vectors and require that at most
-    // one of the them has size 1 and the rest are empty.
-    size_t totalSize = aidl.input.size() + aidl.output.size();
-    if (totalSize > 1) {
-        return unexpected(BAD_VALUE);
-    }
-
     Direction dir = VALUE_OR_RETURN(direction(role, type));
     switch (dir) {
-        case Direction::INPUT:
-            if (aidl.input.empty()) {
-                return unexpected(BAD_VALUE);
-            }
-            legacy.input = VALUE_OR_RETURN(aidl2legacy_audio_input_flags_mask(aidl.input[0]));
+        case Direction::INPUT: {
+            legacy.input = VALUE_OR_RETURN(
+                    aidl2legacy_audio_input_flags_mask(VALUE_OR_RETURN(UNION_GET(aidl, input))));
+        }
             break;
 
-        case Direction::OUTPUT:
-            if (aidl.output.empty()) {
-                return unexpected(BAD_VALUE);
-            }
-            legacy.output = VALUE_OR_RETURN(aidl2legacy_audio_output_flags_mask(aidl.output[0]));
+        case Direction::OUTPUT: {
+            legacy.output = VALUE_OR_RETURN(
+                    aidl2legacy_audio_output_flags_mask(VALUE_OR_RETURN(UNION_GET(aidl, output))));
+        }
             break;
     }
 
@@ -699,11 +769,12 @@
     Direction dir = VALUE_OR_RETURN(direction(role, type));
     switch (dir) {
         case Direction::INPUT:
-            aidl.input.push_back(VALUE_OR_RETURN(legacy2aidl_audio_input_flags_mask(legacy.input)));
+            UNION_SET(aidl, input,
+                      VALUE_OR_RETURN(legacy2aidl_audio_input_flags_mask(legacy.input)));
             break;
         case Direction::OUTPUT:
-            aidl.output.push_back(
-                    VALUE_OR_RETURN(legacy2aidl_audio_output_flags_mask(legacy.output)));
+            UNION_SET(aidl, output,
+                      VALUE_OR_RETURN(legacy2aidl_audio_output_flags_mask(legacy.output)));
             break;
     }
     return aidl;
@@ -712,26 +783,19 @@
 ConversionResult<audio_port_config_device_ext> aidl2legacy_AudioPortConfigDeviceExt(
         const media::AudioPortConfigDeviceExt& aidl) {
     audio_port_config_device_ext legacy;
-    legacy.hw_module = VALUE_OR_RETURN(convertReinterpret<audio_module_handle_t>(aidl.hwModule));
+    legacy.hw_module = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_module_handle_t(aidl.hwModule));
     legacy.type = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_devices_t(aidl.type));
-    if (aidl.address.size() > AUDIO_DEVICE_MAX_ADDRESS_LEN - 1) {
-        return unexpected(BAD_VALUE);
-    }
-    std::strcpy(legacy.address, aidl.address.c_str());
+    RETURN_IF_ERROR(aidl2legacy_string(aidl.address, legacy.address, AUDIO_DEVICE_MAX_ADDRESS_LEN));
     return legacy;
 }
 
 ConversionResult<media::AudioPortConfigDeviceExt> legacy2aidl_AudioPortConfigDeviceExt(
         const audio_port_config_device_ext& legacy) {
     media::AudioPortConfigDeviceExt aidl;
-    aidl.hwModule = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.hw_module));
+    aidl.hwModule = VALUE_OR_RETURN(legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
     aidl.type = VALUE_OR_RETURN(legacy2aidl_audio_devices_t_int32_t(legacy.type));
-
-    if (strnlen(legacy.address, AUDIO_DEVICE_MAX_ADDRESS_LEN) == AUDIO_DEVICE_MAX_ADDRESS_LEN) {
-        // No null-terminator.
-        return unexpected(BAD_VALUE);
-    }
-    aidl.address = legacy.address;
+    aidl.address = VALUE_OR_RETURN(
+            legacy2aidl_string(legacy.address, AUDIO_DEVICE_MAX_ADDRESS_LEN));
     return aidl;
 }
 
@@ -818,6 +882,9 @@
 ConversionResult<audio_source_t> aidl2legacy_AudioSourceType_audio_source_t(
         media::AudioSourceType aidl) {
     switch (aidl) {
+        case media::AudioSourceType::INVALID:
+            // This value does not have an enum
+            return AUDIO_SOURCE_INVALID;
         case media::AudioSourceType::DEFAULT:
             return AUDIO_SOURCE_DEFAULT;
         case media::AudioSourceType::MIC:
@@ -854,6 +921,8 @@
 ConversionResult<media::AudioSourceType> legacy2aidl_audio_source_t_AudioSourceType(
         audio_source_t legacy) {
     switch (legacy) {
+        case AUDIO_SOURCE_INVALID:
+            return media::AudioSourceType::INVALID;
         case AUDIO_SOURCE_DEFAULT:
             return media::AudioSourceType::DEFAULT;
         case AUDIO_SOURCE_MIC:
@@ -887,32 +956,12 @@
     }
 }
 
-ConversionResult<audio_session_t> aidl2legacy_AudioSessionType_audio_session_t(
-        media::AudioSessionType aidl) {
-    switch (aidl) {
-        case media::AudioSessionType::DEVICE:
-            return AUDIO_SESSION_DEVICE;
-        case media::AudioSessionType::OUTPUT_STAGE:
-            return AUDIO_SESSION_OUTPUT_STAGE;
-        case media::AudioSessionType::OUTPUT_MIX:
-            return AUDIO_SESSION_OUTPUT_MIX;
-        default:
-            return unexpected(BAD_VALUE);
-    }
+ConversionResult<audio_session_t> aidl2legacy_int32_t_audio_session_t(int32_t aidl) {
+    return convertReinterpret<audio_session_t>(aidl);
 }
 
-ConversionResult<media::AudioSessionType> legacy2aidl_audio_session_t_AudioSessionType(
-        audio_session_t legacy) {
-    switch (legacy) {
-        case AUDIO_SESSION_DEVICE:
-            return media::AudioSessionType::DEVICE;
-        case AUDIO_SESSION_OUTPUT_STAGE:
-            return media::AudioSessionType::OUTPUT_STAGE;
-        case AUDIO_SESSION_OUTPUT_MIX:
-            return media::AudioSessionType::OUTPUT_MIX;
-        default:
-            return unexpected(BAD_VALUE);
-    }
+ConversionResult<int32_t> legacy2aidl_audio_session_t_int32_t(audio_session_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
 }
 
 // This type is unnamed in the original definition, thus we name it here.
@@ -922,36 +971,22 @@
         const media::AudioPortConfigMixExtUseCase& aidl, media::AudioPortRole role) {
     audio_port_config_mix_ext_usecase legacy;
 
-    // Our way of representing a union in AIDL is to have multiple vectors and require that exactly
-    // one of the them has size 1 and the rest are empty.
-    size_t totalSize = aidl.stream.size() + aidl.source.size();
-    if (totalSize > 1) {
-        return unexpected(BAD_VALUE);
-    }
-
     switch (role) {
         case media::AudioPortRole::NONE:
-            if (totalSize != 0) {
-                return unexpected(BAD_VALUE);
-            }
+            // Just verify that the union is empty.
+            VALUE_OR_RETURN(UNION_GET(aidl, nothing));
             break;
 
         case media::AudioPortRole::SOURCE:
             // This is not a bug. A SOURCE role corresponds to the stream field.
-            if (aidl.stream.empty()) {
-                return unexpected(BAD_VALUE);
-            }
-            legacy.stream = VALUE_OR_RETURN(
-                    aidl2legacy_AudioStreamType_audio_stream_type_t(aidl.stream[0]));
+            legacy.stream = VALUE_OR_RETURN(aidl2legacy_AudioStreamType_audio_stream_type_t(
+                    VALUE_OR_RETURN(UNION_GET(aidl, stream))));
             break;
 
         case media::AudioPortRole::SINK:
             // This is not a bug. A SINK role corresponds to the source field.
-            if (aidl.source.empty()) {
-                return unexpected(BAD_VALUE);
-            }
-            legacy.source =
-                    VALUE_OR_RETURN(aidl2legacy_AudioSourceType_audio_source_t(aidl.source[0]));
+            legacy.source = VALUE_OR_RETURN(aidl2legacy_AudioSourceType_audio_source_t(
+                    VALUE_OR_RETURN(UNION_GET(aidl, source))));
             break;
 
         default:
@@ -966,17 +1001,17 @@
 
     switch (role) {
         case AUDIO_PORT_ROLE_NONE:
+            UNION_SET(aidl, nothing, false);
             break;
         case AUDIO_PORT_ROLE_SOURCE:
             // This is not a bug. A SOURCE role corresponds to the stream field.
-            aidl.stream.push_back(VALUE_OR_RETURN(
-                                          legacy2aidl_audio_stream_type_t_AudioStreamType(
-                                                  legacy.stream)));
+            UNION_SET(aidl, stream, VALUE_OR_RETURN(
+                    legacy2aidl_audio_stream_type_t_AudioStreamType(legacy.stream)));
             break;
         case AUDIO_PORT_ROLE_SINK:
             // This is not a bug. A SINK role corresponds to the source field.
-            aidl.source.push_back(
-                    VALUE_OR_RETURN(legacy2aidl_audio_source_t_AudioSourceType(legacy.source)));
+            UNION_SET(aidl, source,
+                      VALUE_OR_RETURN(legacy2aidl_audio_source_t_AudioSourceType(legacy.source)));
             break;
         default:
             LOG_ALWAYS_FATAL("Shouldn't get here");
@@ -987,8 +1022,8 @@
 ConversionResult<audio_port_config_mix_ext> aidl2legacy_AudioPortConfigMixExt(
         const media::AudioPortConfigMixExt& aidl, media::AudioPortRole role) {
     audio_port_config_mix_ext legacy;
-    legacy.hw_module = VALUE_OR_RETURN(convertReinterpret<audio_module_handle_t>(aidl.hwModule));
-    legacy.handle = VALUE_OR_RETURN(convertReinterpret<audio_io_handle_t>(aidl.handle));
+    legacy.hw_module = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_module_handle_t(aidl.hwModule));
+    legacy.handle = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_io_handle_t(aidl.handle));
     legacy.usecase = VALUE_OR_RETURN(aidl2legacy_AudioPortConfigMixExtUseCase(aidl.usecase, role));
     return legacy;
 }
@@ -996,8 +1031,8 @@
 ConversionResult<media::AudioPortConfigMixExt> legacy2aidl_AudioPortConfigMixExt(
         const audio_port_config_mix_ext& legacy, audio_port_role_t role) {
     media::AudioPortConfigMixExt aidl;
-    aidl.hwModule = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.hw_module));
-    aidl.handle = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.handle));
+    aidl.hwModule = VALUE_OR_RETURN(legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
+    aidl.handle = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(legacy.handle));
     aidl.usecase = VALUE_OR_RETURN(legacy2aidl_AudioPortConfigMixExtUseCase(legacy.usecase, role));
     return aidl;
 }
@@ -1005,14 +1040,14 @@
 ConversionResult<audio_port_config_session_ext> aidl2legacy_AudioPortConfigSessionExt(
         const media::AudioPortConfigSessionExt& aidl) {
     audio_port_config_session_ext legacy;
-    legacy.session = VALUE_OR_RETURN(aidl2legacy_AudioSessionType_audio_session_t(aidl.session));
+    legacy.session = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_session_t(aidl.session));
     return legacy;
 }
 
 ConversionResult<media::AudioPortConfigSessionExt> legacy2aidl_AudioPortConfigSessionExt(
         const audio_port_config_session_ext& legacy) {
     media::AudioPortConfigSessionExt aidl;
-    aidl.session = VALUE_OR_RETURN(legacy2aidl_audio_session_t_AudioSessionType(legacy.session));
+    aidl.session = VALUE_OR_RETURN(legacy2aidl_audio_session_t_int32_t(legacy.session));
     return aidl;
 }
 
@@ -1025,34 +1060,22 @@
     audio_port_config_ext legacy;
     // Our way of representing a union in AIDL is to have multiple vectors and require that at most
     // one of the them has size 1 and the rest are empty.
-    size_t totalSize = aidl.device.size() + aidl.mix.size() + aidl.session.size();
-    if (totalSize > 1) {
-        return unexpected(BAD_VALUE);
-    }
     switch (type) {
         case media::AudioPortType::NONE:
-            if (totalSize != 0) {
-                return unexpected(BAD_VALUE);
-            }
+            // Just verify that the union is empty.
+            VALUE_OR_RETURN(UNION_GET(aidl, nothing));
             break;
         case media::AudioPortType::DEVICE:
-            if (aidl.device.empty()) {
-                return unexpected(BAD_VALUE);
-            }
-            legacy.device = VALUE_OR_RETURN(aidl2legacy_AudioPortConfigDeviceExt(aidl.device[0]));
+            legacy.device = VALUE_OR_RETURN(
+                    aidl2legacy_AudioPortConfigDeviceExt(VALUE_OR_RETURN(UNION_GET(aidl, device))));
             break;
         case media::AudioPortType::MIX:
-            if (aidl.mix.empty()) {
-                return unexpected(BAD_VALUE);
-            }
-            legacy.mix = VALUE_OR_RETURN(aidl2legacy_AudioPortConfigMixExt(aidl.mix[0], role));
+            legacy.mix = VALUE_OR_RETURN(
+                    aidl2legacy_AudioPortConfigMixExt(VALUE_OR_RETURN(UNION_GET(aidl, mix)), role));
             break;
         case media::AudioPortType::SESSION:
-            if (aidl.session.empty()) {
-                return unexpected(BAD_VALUE);
-            }
-            legacy.session =
-                    VALUE_OR_RETURN(aidl2legacy_AudioPortConfigSessionExt(aidl.session[0]));
+            legacy.session = VALUE_OR_RETURN(aidl2legacy_AudioPortConfigSessionExt(
+                    VALUE_OR_RETURN(UNION_GET(aidl, session))));
             break;
         default:
             LOG_ALWAYS_FATAL("Shouldn't get here");
@@ -1066,18 +1089,19 @@
 
     switch (type) {
         case AUDIO_PORT_TYPE_NONE:
+            UNION_SET(aidl, nothing, false);
             break;
         case AUDIO_PORT_TYPE_DEVICE:
-            aidl.device.push_back(
-                    VALUE_OR_RETURN(legacy2aidl_AudioPortConfigDeviceExt(legacy.device)));
+            UNION_SET(aidl, device,
+                      VALUE_OR_RETURN(legacy2aidl_AudioPortConfigDeviceExt(legacy.device)));
             break;
         case AUDIO_PORT_TYPE_MIX:
-            aidl.mix.push_back(
-                    VALUE_OR_RETURN(legacy2aidl_AudioPortConfigMixExt(legacy.mix, role)));
+            UNION_SET(aidl, mix,
+                      VALUE_OR_RETURN(legacy2aidl_AudioPortConfigMixExt(legacy.mix, role)));
             break;
         case AUDIO_PORT_TYPE_SESSION:
-            aidl.session.push_back(
-                    VALUE_OR_RETURN(legacy2aidl_AudioPortConfigSessionExt(legacy.session)));
+            UNION_SET(aidl, session,
+                      VALUE_OR_RETURN(legacy2aidl_AudioPortConfigSessionExt(legacy.session)));
             break;
         default:
             LOG_ALWAYS_FATAL("Shouldn't get here");
@@ -1088,7 +1112,7 @@
 ConversionResult<audio_port_config> aidl2legacy_AudioPortConfig_audio_port_config(
         const media::AudioPortConfig& aidl) {
     audio_port_config legacy;
-    legacy.id = VALUE_OR_RETURN(convertReinterpret<audio_port_handle_t>(aidl.id));
+    legacy.id = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_port_handle_t(aidl.id));
     legacy.role = VALUE_OR_RETURN(aidl2legacy_AudioPortRole_audio_port_role_t(aidl.role));
     legacy.type = VALUE_OR_RETURN(aidl2legacy_AudioPortType_audio_port_type_t(aidl.type));
     legacy.config_mask = VALUE_OR_RETURN(aidl2legacy_int32_t_config_mask(aidl.configMask));
@@ -1117,7 +1141,7 @@
 ConversionResult<media::AudioPortConfig> legacy2aidl_audio_port_config_AudioPortConfig(
         const audio_port_config& legacy) {
     media::AudioPortConfig aidl;
-    aidl.id = VALUE_OR_RETURN(convertReinterpret<audio_port_handle_t>(legacy.id));
+    aidl.id = VALUE_OR_RETURN(legacy2aidl_audio_port_handle_t_int32_t(legacy.id));
     aidl.role = VALUE_OR_RETURN(legacy2aidl_audio_port_role_t_AudioPortRole(legacy.role));
     aidl.type = VALUE_OR_RETURN(legacy2aidl_audio_port_type_t_AudioPortType(legacy.type));
     aidl.configMask = VALUE_OR_RETURN(legacy2aidl_config_mask_int32_t(legacy.config_mask));
@@ -1147,7 +1171,7 @@
 ConversionResult<struct audio_patch> aidl2legacy_AudioPatch_audio_patch(
         const media::AudioPatch& aidl) {
     struct audio_patch legacy;
-    legacy.id = VALUE_OR_RETURN(convertReinterpret<audio_patch_handle_t>(aidl.id));
+    legacy.id = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_patch_handle_t(aidl.id));
     legacy.num_sinks = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.sinks.size()));
     if (legacy.num_sinks > AUDIO_PATCH_PORTS_MAX) {
         return unexpected(BAD_VALUE);
@@ -1170,7 +1194,7 @@
 ConversionResult<media::AudioPatch> legacy2aidl_audio_patch_AudioPatch(
         const struct audio_patch& legacy) {
     media::AudioPatch aidl;
-    aidl.id = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.id));
+    aidl.id = VALUE_OR_RETURN(legacy2aidl_audio_patch_handle_t_int32_t(legacy.id));
 
     if (legacy.num_sinks > AUDIO_PATCH_PORTS_MAX) {
         return unexpected(BAD_VALUE);
@@ -1192,7 +1216,7 @@
 ConversionResult<sp<AudioIoDescriptor>> aidl2legacy_AudioIoDescriptor_AudioIoDescriptor(
         const media::AudioIoDescriptor& aidl) {
     sp<AudioIoDescriptor> legacy(new AudioIoDescriptor());
-    legacy->mIoHandle = VALUE_OR_RETURN(convertReinterpret<audio_io_handle_t>(aidl.ioHandle));
+    legacy->mIoHandle = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_io_handle_t(aidl.ioHandle));
     legacy->mPatch = VALUE_OR_RETURN(aidl2legacy_AudioPatch_audio_patch(aidl.patch));
     legacy->mSamplingRate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.samplingRate));
     legacy->mFormat = VALUE_OR_RETURN(aidl2legacy_AudioFormat_audio_format_t(aidl.format));
@@ -1201,22 +1225,459 @@
     legacy->mFrameCount = VALUE_OR_RETURN(convertIntegral<size_t>(aidl.frameCount));
     legacy->mFrameCountHAL = VALUE_OR_RETURN(convertIntegral<size_t>(aidl.frameCountHAL));
     legacy->mLatency = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.latency));
-    legacy->mPortId = VALUE_OR_RETURN(convertReinterpret<audio_port_handle_t>(aidl.portId));
+    legacy->mPortId = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_port_handle_t(aidl.portId));
     return legacy;
 }
 
 ConversionResult<media::AudioIoDescriptor> legacy2aidl_AudioIoDescriptor_AudioIoDescriptor(
         const sp<AudioIoDescriptor>& legacy) {
     media::AudioIoDescriptor aidl;
-    aidl.ioHandle = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy->mIoHandle));
+    aidl.ioHandle = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(legacy->mIoHandle));
     aidl.patch = VALUE_OR_RETURN(legacy2aidl_audio_patch_AudioPatch(legacy->mPatch));
     aidl.samplingRate = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy->mSamplingRate));
     aidl.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormat(legacy->mFormat));
-    aidl.channelMask = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy->mChannelMask));
+    aidl.channelMask = VALUE_OR_RETURN(
+            legacy2aidl_audio_channel_mask_t_int32_t(legacy->mChannelMask));
     aidl.frameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(legacy->mFrameCount));
     aidl.frameCountHAL = VALUE_OR_RETURN(convertIntegral<int64_t>(legacy->mFrameCountHAL));
     aidl.latency = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy->mLatency));
-    aidl.portId = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy->mPortId));
+    aidl.portId = VALUE_OR_RETURN(legacy2aidl_audio_port_handle_t_int32_t(legacy->mPortId));
+    return aidl;
+}
+
+ConversionResult<AudioClient> aidl2legacy_AudioClient(const media::AudioClient& aidl) {
+    AudioClient legacy;
+    legacy.clientUid = VALUE_OR_RETURN(aidl2legacy_int32_t_uid_t(aidl.clientUid));
+    legacy.clientPid = VALUE_OR_RETURN(aidl2legacy_int32_t_pid_t(aidl.clientPid));
+    legacy.clientTid = VALUE_OR_RETURN(aidl2legacy_int32_t_pid_t(aidl.clientTid));
+    legacy.packageName = VALUE_OR_RETURN(aidl2legacy_string_view_String16(aidl.packageName));
+    return legacy;
+}
+
+ConversionResult<media::AudioClient> legacy2aidl_AudioClient(const AudioClient& legacy) {
+    media::AudioClient aidl;
+    aidl.clientUid = VALUE_OR_RETURN(legacy2aidl_uid_t_int32_t(legacy.clientUid));
+    aidl.clientPid = VALUE_OR_RETURN(legacy2aidl_pid_t_int32_t(legacy.clientPid));
+    aidl.clientTid = VALUE_OR_RETURN(legacy2aidl_pid_t_int32_t(legacy.clientTid));
+    aidl.packageName = VALUE_OR_RETURN(legacy2aidl_String16_string(legacy.packageName));
+    return aidl;
+}
+
+ConversionResult<audio_content_type_t>
+aidl2legacy_AudioContentType_audio_content_type_t(media::AudioContentType aidl) {
+    switch (aidl) {
+        case media::AudioContentType::UNKNOWN:
+            return AUDIO_CONTENT_TYPE_UNKNOWN;
+        case media::AudioContentType::SPEECH:
+            return AUDIO_CONTENT_TYPE_SPEECH;
+        case media::AudioContentType::MUSIC:
+            return AUDIO_CONTENT_TYPE_MUSIC;
+        case media::AudioContentType::MOVIE:
+            return AUDIO_CONTENT_TYPE_MOVIE;
+        case media::AudioContentType::SONIFICATION:
+            return AUDIO_CONTENT_TYPE_SONIFICATION;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<media::AudioContentType>
+legacy2aidl_audio_content_type_t_AudioContentType(audio_content_type_t legacy) {
+    switch (legacy) {
+        case AUDIO_CONTENT_TYPE_UNKNOWN:
+            return media::AudioContentType::UNKNOWN;
+        case AUDIO_CONTENT_TYPE_SPEECH:
+            return media::AudioContentType::SPEECH;
+        case AUDIO_CONTENT_TYPE_MUSIC:
+            return media::AudioContentType::MUSIC;
+        case AUDIO_CONTENT_TYPE_MOVIE:
+            return media::AudioContentType::MOVIE;
+        case AUDIO_CONTENT_TYPE_SONIFICATION:
+            return media::AudioContentType::SONIFICATION;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_usage_t>
+aidl2legacy_AudioUsage_audio_usage_t(media::AudioUsage aidl) {
+    switch (aidl) {
+        case media::AudioUsage::UNKNOWN:
+            return AUDIO_USAGE_UNKNOWN;
+        case media::AudioUsage::MEDIA:
+            return AUDIO_USAGE_MEDIA;
+        case media::AudioUsage::VOICE_COMMUNICATION:
+            return AUDIO_USAGE_VOICE_COMMUNICATION;
+        case media::AudioUsage::VOICE_COMMUNICATION_SIGNALLING:
+            return AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
+        case media::AudioUsage::ALARM:
+            return AUDIO_USAGE_ALARM;
+        case media::AudioUsage::NOTIFICATION:
+            return AUDIO_USAGE_NOTIFICATION;
+        case media::AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE:
+            return AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
+        case media::AudioUsage::NOTIFICATION_COMMUNICATION_REQUEST:
+            return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST;
+        case media::AudioUsage::NOTIFICATION_COMMUNICATION_INSTANT:
+            return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT;
+        case media::AudioUsage::NOTIFICATION_COMMUNICATION_DELAYED:
+            return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED;
+        case media::AudioUsage::NOTIFICATION_EVENT:
+            return AUDIO_USAGE_NOTIFICATION_EVENT;
+        case media::AudioUsage::ASSISTANCE_ACCESSIBILITY:
+            return AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
+        case media::AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE:
+            return AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE;
+        case media::AudioUsage::ASSISTANCE_SONIFICATION:
+            return AUDIO_USAGE_ASSISTANCE_SONIFICATION;
+        case media::AudioUsage::GAME:
+            return AUDIO_USAGE_GAME;
+        case media::AudioUsage::VIRTUAL_SOURCE:
+            return AUDIO_USAGE_VIRTUAL_SOURCE;
+        case media::AudioUsage::ASSISTANT:
+            return AUDIO_USAGE_ASSISTANT;
+        case media::AudioUsage::CALL_ASSISTANT:
+            return AUDIO_USAGE_CALL_ASSISTANT;
+        case media::AudioUsage::EMERGENCY:
+            return AUDIO_USAGE_EMERGENCY;
+        case media::AudioUsage::SAFETY:
+            return AUDIO_USAGE_SAFETY;
+        case media::AudioUsage::VEHICLE_STATUS:
+            return AUDIO_USAGE_VEHICLE_STATUS;
+        case media::AudioUsage::ANNOUNCEMENT:
+            return AUDIO_USAGE_ANNOUNCEMENT;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<media::AudioUsage>
+legacy2aidl_audio_usage_t_AudioUsage(audio_usage_t legacy) {
+    switch (legacy) {
+        case AUDIO_USAGE_UNKNOWN:
+            return media::AudioUsage::UNKNOWN;
+        case AUDIO_USAGE_MEDIA:
+            return media::AudioUsage::MEDIA;
+        case AUDIO_USAGE_VOICE_COMMUNICATION:
+            return media::AudioUsage::VOICE_COMMUNICATION;
+        case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
+            return media::AudioUsage::VOICE_COMMUNICATION_SIGNALLING;
+        case AUDIO_USAGE_ALARM:
+            return media::AudioUsage::ALARM;
+        case AUDIO_USAGE_NOTIFICATION:
+            return media::AudioUsage::NOTIFICATION;
+        case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
+            return media::AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE;
+        case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
+            return media::AudioUsage::NOTIFICATION_COMMUNICATION_REQUEST;
+        case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
+            return media::AudioUsage::NOTIFICATION_COMMUNICATION_INSTANT;
+        case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
+            return media::AudioUsage::NOTIFICATION_COMMUNICATION_DELAYED;
+        case AUDIO_USAGE_NOTIFICATION_EVENT:
+            return media::AudioUsage::NOTIFICATION_EVENT;
+        case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
+            return media::AudioUsage::ASSISTANCE_ACCESSIBILITY;
+        case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
+            return media::AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE;
+        case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
+            return media::AudioUsage::ASSISTANCE_SONIFICATION;
+        case AUDIO_USAGE_GAME:
+            return media::AudioUsage::GAME;
+        case AUDIO_USAGE_VIRTUAL_SOURCE:
+            return media::AudioUsage::VIRTUAL_SOURCE;
+        case AUDIO_USAGE_ASSISTANT:
+            return media::AudioUsage::ASSISTANT;
+        case AUDIO_USAGE_CALL_ASSISTANT:
+            return media::AudioUsage::CALL_ASSISTANT;
+        case AUDIO_USAGE_EMERGENCY:
+            return media::AudioUsage::EMERGENCY;
+        case AUDIO_USAGE_SAFETY:
+            return media::AudioUsage::SAFETY;
+        case AUDIO_USAGE_VEHICLE_STATUS:
+            return media::AudioUsage::VEHICLE_STATUS;
+        case AUDIO_USAGE_ANNOUNCEMENT:
+            return media::AudioUsage::ANNOUNCEMENT;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_flags_mask_t>
+aidl2legacy_AudioFlag_audio_flags_mask_t(media::AudioFlag aidl) {
+    switch (aidl) {
+        case media::AudioFlag::AUDIBILITY_ENFORCED:
+            return AUDIO_FLAG_AUDIBILITY_ENFORCED;
+        case media::AudioFlag::SECURE:
+            return AUDIO_FLAG_SECURE;
+        case media::AudioFlag::SCO:
+            return AUDIO_FLAG_SCO;
+        case media::AudioFlag::BEACON:
+            return AUDIO_FLAG_BEACON;
+        case media::AudioFlag::HW_AV_SYNC:
+            return AUDIO_FLAG_HW_AV_SYNC;
+        case media::AudioFlag::HW_HOTWORD:
+            return AUDIO_FLAG_HW_HOTWORD;
+        case media::AudioFlag::BYPASS_INTERRUPTION_POLICY:
+            return AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY;
+        case media::AudioFlag::BYPASS_MUTE:
+            return AUDIO_FLAG_BYPASS_MUTE;
+        case media::AudioFlag::LOW_LATENCY:
+            return AUDIO_FLAG_LOW_LATENCY;
+        case media::AudioFlag::DEEP_BUFFER:
+            return AUDIO_FLAG_DEEP_BUFFER;
+        case media::AudioFlag::NO_MEDIA_PROJECTION:
+            return AUDIO_FLAG_NO_MEDIA_PROJECTION;
+        case media::AudioFlag::MUTE_HAPTIC:
+            return AUDIO_FLAG_MUTE_HAPTIC;
+        case media::AudioFlag::NO_SYSTEM_CAPTURE:
+            return AUDIO_FLAG_NO_SYSTEM_CAPTURE;
+        case media::AudioFlag::CAPTURE_PRIVATE:
+            return AUDIO_FLAG_CAPTURE_PRIVATE;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<media::AudioFlag>
+legacy2aidl_audio_flags_mask_t_AudioFlag(audio_flags_mask_t legacy) {
+    switch (legacy) {
+        case AUDIO_FLAG_NONE:
+            return unexpected(BAD_VALUE);
+        case AUDIO_FLAG_AUDIBILITY_ENFORCED:
+            return media::AudioFlag::AUDIBILITY_ENFORCED;
+        case AUDIO_FLAG_SECURE:
+            return media::AudioFlag::SECURE;
+        case AUDIO_FLAG_SCO:
+            return media::AudioFlag::SCO;
+        case AUDIO_FLAG_BEACON:
+            return media::AudioFlag::BEACON;
+        case AUDIO_FLAG_HW_AV_SYNC:
+            return media::AudioFlag::HW_AV_SYNC;
+        case AUDIO_FLAG_HW_HOTWORD:
+            return media::AudioFlag::HW_HOTWORD;
+        case AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY:
+            return media::AudioFlag::BYPASS_INTERRUPTION_POLICY;
+        case AUDIO_FLAG_BYPASS_MUTE:
+            return media::AudioFlag::BYPASS_MUTE;
+        case AUDIO_FLAG_LOW_LATENCY:
+            return media::AudioFlag::LOW_LATENCY;
+        case AUDIO_FLAG_DEEP_BUFFER:
+            return media::AudioFlag::DEEP_BUFFER;
+        case AUDIO_FLAG_NO_MEDIA_PROJECTION:
+            return media::AudioFlag::NO_MEDIA_PROJECTION;
+        case AUDIO_FLAG_MUTE_HAPTIC:
+            return media::AudioFlag::MUTE_HAPTIC;
+        case AUDIO_FLAG_NO_SYSTEM_CAPTURE:
+            return media::AudioFlag::NO_SYSTEM_CAPTURE;
+        case AUDIO_FLAG_CAPTURE_PRIVATE:
+            return media::AudioFlag::CAPTURE_PRIVATE;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_flags_mask_t>
+aidl2legacy_int32_t_audio_flags_mask_t_mask(int32_t aidl) {
+    return convertBitmask<audio_flags_mask_t, int32_t, audio_flags_mask_t, media::AudioFlag>(
+            aidl, aidl2legacy_AudioFlag_audio_flags_mask_t, index2enum_index<media::AudioFlag>,
+            enumToMask_bitmask<audio_flags_mask_t, audio_flags_mask_t>);
+}
+
+ConversionResult<int32_t>
+legacy2aidl_audio_flags_mask_t_int32_t_mask(audio_flags_mask_t legacy) {
+    return convertBitmask<int32_t, audio_flags_mask_t, media::AudioFlag, audio_flags_mask_t>(
+            legacy, legacy2aidl_audio_flags_mask_t_AudioFlag,
+            index2enum_bitmask<audio_flags_mask_t>,
+            enumToMask_index<int32_t, media::AudioFlag>);
+}
+
+ConversionResult<audio_attributes_t>
+aidl2legacy_AudioAttributesInternal_audio_attributes_t(const media::AudioAttributesInternal& aidl) {
+    audio_attributes_t legacy;
+    legacy.content_type = VALUE_OR_RETURN(
+            aidl2legacy_AudioContentType_audio_content_type_t(aidl.contentType));
+    legacy.usage = VALUE_OR_RETURN(aidl2legacy_AudioUsage_audio_usage_t(aidl.usage));
+    legacy.source = VALUE_OR_RETURN(aidl2legacy_AudioSourceType_audio_source_t(aidl.source));
+    legacy.flags = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_flags_mask_t_mask(aidl.flags));
+    RETURN_IF_ERROR(aidl2legacy_string(aidl.tags, legacy.tags, sizeof(legacy.tags)));
+    return legacy;
+}
+
+ConversionResult<media::AudioAttributesInternal>
+legacy2aidl_audio_attributes_t_AudioAttributesInternal(const audio_attributes_t& legacy) {
+    media::AudioAttributesInternal aidl;
+    aidl.contentType = VALUE_OR_RETURN(
+            legacy2aidl_audio_content_type_t_AudioContentType(legacy.content_type));
+    aidl.usage = VALUE_OR_RETURN(legacy2aidl_audio_usage_t_AudioUsage(legacy.usage));
+    aidl.source = VALUE_OR_RETURN(legacy2aidl_audio_source_t_AudioSourceType(legacy.source));
+    aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_flags_mask_t_int32_t_mask(legacy.flags));
+    aidl.tags = VALUE_OR_RETURN(legacy2aidl_string(legacy.tags, sizeof(legacy.tags)));
+    return aidl;
+}
+
+ConversionResult<audio_encapsulation_mode_t>
+aidl2legacy_audio_encapsulation_mode_t_AudioEncapsulationMode(media::AudioEncapsulationMode aidl) {
+    switch (aidl) {
+        case media::AudioEncapsulationMode::NONE:
+            return AUDIO_ENCAPSULATION_MODE_NONE;
+        case media::AudioEncapsulationMode::ELEMENTARY_STREAM:
+            return AUDIO_ENCAPSULATION_MODE_ELEMENTARY_STREAM;
+        case media::AudioEncapsulationMode::HANDLE:
+            return AUDIO_ENCAPSULATION_MODE_HANDLE;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<media::AudioEncapsulationMode>
+legacy2aidl_AudioEncapsulationMode_audio_encapsulation_mode_t(audio_encapsulation_mode_t legacy) {
+    switch (legacy) {
+        case AUDIO_ENCAPSULATION_MODE_NONE:
+            return media::AudioEncapsulationMode::NONE;
+        case AUDIO_ENCAPSULATION_MODE_ELEMENTARY_STREAM:
+            return media::AudioEncapsulationMode::ELEMENTARY_STREAM;
+        case AUDIO_ENCAPSULATION_MODE_HANDLE:
+            return media::AudioEncapsulationMode::HANDLE;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_offload_info_t>
+aidl2legacy_AudioOffloadInfo_audio_offload_info_t(const media::AudioOffloadInfo& aidl) {
+    audio_offload_info_t legacy;
+    legacy.version = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.version));
+    legacy.size = sizeof(audio_offload_info_t);
+    audio_config_base_t config = VALUE_OR_RETURN(
+            aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.config));
+    legacy.sample_rate = config.sample_rate;
+    legacy.channel_mask = config.channel_mask;
+    legacy.format = config.format;
+    legacy.stream_type = VALUE_OR_RETURN(
+            aidl2legacy_AudioStreamType_audio_stream_type_t(aidl.streamType));
+    legacy.bit_rate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.bitRate));
+    legacy.duration_us = VALUE_OR_RETURN(convertIntegral<int64_t>(aidl.durationUs));
+    legacy.has_video = aidl.hasVideo;
+    legacy.is_streaming = aidl.isStreaming;
+    legacy.bit_width = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.bitWidth));
+    legacy.offload_buffer_size = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.offloadBufferSize));
+    legacy.usage = VALUE_OR_RETURN(aidl2legacy_AudioUsage_audio_usage_t(aidl.usage));
+    legacy.encapsulation_mode = VALUE_OR_RETURN(
+            aidl2legacy_audio_encapsulation_mode_t_AudioEncapsulationMode(aidl.encapsulationMode));
+    legacy.content_id = VALUE_OR_RETURN(convertReinterpret<int32_t>(aidl.contentId));
+    legacy.sync_id = VALUE_OR_RETURN(convertReinterpret<int32_t>(aidl.syncId));
+    return legacy;
+}
+
+ConversionResult<media::AudioOffloadInfo>
+legacy2aidl_audio_offload_info_t_AudioOffloadInfo(const audio_offload_info_t& legacy) {
+    media::AudioOffloadInfo aidl;
+    // Version 0.1 fields.
+    if (legacy.size < offsetof(audio_offload_info_t, usage) + sizeof(audio_offload_info_t::usage)) {
+        return unexpected(BAD_VALUE);
+    }
+    aidl.version = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.version));
+    aidl.config.sampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.sample_rate));
+    aidl.config.channelMask = VALUE_OR_RETURN(
+            legacy2aidl_audio_channel_mask_t_int32_t(legacy.channel_mask));
+    aidl.config.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormat(legacy.format));
+    aidl.streamType = VALUE_OR_RETURN(
+            legacy2aidl_audio_stream_type_t_AudioStreamType(legacy.stream_type));
+    aidl.bitRate = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.bit_rate));
+    aidl.durationUs = VALUE_OR_RETURN(convertIntegral<int64_t>(legacy.duration_us));
+    aidl.hasVideo = legacy.has_video;
+    aidl.isStreaming = legacy.is_streaming;
+    aidl.bitWidth = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.bit_width));
+    aidl.offloadBufferSize = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.offload_buffer_size));
+    aidl.usage = VALUE_OR_RETURN(legacy2aidl_audio_usage_t_AudioUsage(legacy.usage));
+
+    // Version 0.2 fields.
+    if (legacy.version >= AUDIO_OFFLOAD_INFO_VERSION_0_2) {
+        if (legacy.size <
+            offsetof(audio_offload_info_t, sync_id) + sizeof(audio_offload_info_t::sync_id)) {
+            return unexpected(BAD_VALUE);
+        }
+        aidl.encapsulationMode = VALUE_OR_RETURN(
+                legacy2aidl_AudioEncapsulationMode_audio_encapsulation_mode_t(
+                        legacy.encapsulation_mode));
+        aidl.contentId = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.content_id));
+        aidl.syncId = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.sync_id));
+    }
+    return aidl;
+}
+
+ConversionResult<audio_config_t>
+aidl2legacy_AudioConfig_audio_config_t(const media::AudioConfig& aidl) {
+    audio_config_t legacy;
+    legacy.sample_rate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.sampleRate));
+    legacy.channel_mask = VALUE_OR_RETURN(
+            aidl2legacy_int32_t_audio_channel_mask_t(aidl.channelMask));
+    legacy.format = VALUE_OR_RETURN(aidl2legacy_AudioFormat_audio_format_t(aidl.format));
+    legacy.offload_info = VALUE_OR_RETURN(
+            aidl2legacy_AudioOffloadInfo_audio_offload_info_t(aidl.offloadInfo));
+    legacy.frame_count = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.frameCount));
+    return legacy;
+}
+
+ConversionResult<media::AudioConfig>
+legacy2aidl_audio_config_t_AudioConfig(const audio_config_t& legacy) {
+    media::AudioConfig aidl;
+    aidl.sampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.sample_rate));
+    aidl.channelMask = VALUE_OR_RETURN(
+            legacy2aidl_audio_channel_mask_t_int32_t(legacy.channel_mask));
+    aidl.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormat(legacy.format));
+    aidl.offloadInfo = VALUE_OR_RETURN(
+            legacy2aidl_audio_offload_info_t_AudioOffloadInfo(legacy.offload_info));
+    aidl.frameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(legacy.frame_count));
+    return aidl;
+}
+
+ConversionResult<audio_config_base_t>
+aidl2legacy_AudioConfigBase_audio_config_base_t(const media::AudioConfigBase& aidl) {
+    audio_config_base_t legacy;
+    legacy.sample_rate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.sampleRate));
+    legacy.channel_mask = VALUE_OR_RETURN(
+            aidl2legacy_int32_t_audio_channel_mask_t(aidl.channelMask));
+    legacy.format = VALUE_OR_RETURN(aidl2legacy_AudioFormat_audio_format_t(aidl.format));
+    return legacy;
+}
+
+ConversionResult<media::AudioConfigBase>
+legacy2aidl_audio_config_base_t_AudioConfigBase(const audio_config_base_t& legacy) {
+    media::AudioConfigBase aidl;
+    aidl.sampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.sample_rate));
+    aidl.channelMask = VALUE_OR_RETURN(
+            legacy2aidl_audio_channel_mask_t_int32_t(legacy.channel_mask));
+    aidl.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormat(legacy.format));
+    return aidl;
+}
+
+ConversionResult<sp<IMemory>>
+aidl2legacy_SharedFileRegion_IMemory(const media::SharedFileRegion& aidl) {
+    sp<IMemory> legacy;
+    if (!convertSharedFileRegionToIMemory(aidl, &legacy)) {
+        return unexpected(BAD_VALUE);
+    }
+    return legacy;
+}
+
+ConversionResult<media::SharedFileRegion>
+legacy2aidl_IMemory_SharedFileRegion(const sp<IMemory>& legacy) {
+    media::SharedFileRegion aidl;
+    if (!convertIMemoryToSharedFileRegion(legacy, &aidl)) {
+        return unexpected(BAD_VALUE);
+    }
+    return aidl;
+}
+
+ConversionResult<sp<IMemory>>
+aidl2legacy_NullableSharedFileRegion_IMemory(const std::optional<media::SharedFileRegion>& aidl) {
+    sp<IMemory> legacy;
+    if (!convertNullableSharedFileRegionToIMemory(aidl, &legacy)) {
+        return unexpected(BAD_VALUE);
+    }
+    return legacy;
+}
+
+ConversionResult<std::optional<media::SharedFileRegion>>
+legacy2aidl_NullableIMemory_SharedFileRegion(const sp<IMemory>& legacy) {
+    std::optional<media::SharedFileRegion> aidl;
+    if (!convertNullableIMemoryToSharedFileRegion(legacy, &aidl)) {
+        return unexpected(BAD_VALUE);
+    }
     return aidl;
 }
 
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index fef0ca9..c23c38c 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -15,9 +15,11 @@
     ],
     static_libs: [
         "audioflinger-aidl-unstable-cpp",
+        "av-types-aidl-unstable-cpp",
     ],
     export_static_lib_headers: [
         "audioflinger-aidl-unstable-cpp",
+        "av-types-aidl-unstable-cpp",
     ],
     target: {
         darwin: {
@@ -63,7 +65,7 @@
         export_aidl_headers: true,
         local_include_dirs: ["aidl"],
         include_dirs: [
-            "frameworks/av/media/libaudioclient/aidl",
+            "frameworks/av/aidl",
         ],
     },
 
@@ -71,7 +73,6 @@
         // AIDL files for audioclient interfaces
         // The headers for these interfaces will be available to any modules that
         // include libaudioclient, at the path "aidl/package/path/BnFoo.h"
-        ":libaudioclient_aidl_callback",
         ":libaudioclient_aidl_private",
         ":libaudioclient_aidl",
 
@@ -90,7 +91,9 @@
         "TrackPlayerBase.cpp",
     ],
     shared_libs: [
+        "audioclient-types-aidl-unstable-cpp",
         "audioflinger-aidl-unstable-cpp",
+        "av-types-aidl-unstable-cpp",
         "capture_state_listener-aidl-cpp",
         "libaudioclient_aidl_conversion",
         "libaudiofoundation",
@@ -159,11 +162,16 @@
     shared_libs: [
         "audioclient-types-aidl-unstable-cpp",
         "libbase",
+        "libbinder",
         "liblog",
+        "libshmemcompat",
         "libutils",
+        "shared-file-region-aidl-unstable-cpp",
     ],
     export_shared_lib_headers: [
         "audioclient-types-aidl-unstable-cpp",
+        "libbase",
+        "shared-file-region-aidl-unstable-cpp",
     ],
     cflags: [
         "-Wall",
@@ -197,15 +205,6 @@
     path: "aidl",
 }
 
-// AIDL interface for audio track callback
-filegroup {
-    name: "libaudioclient_aidl_callback",
-    srcs: [
-        "aidl/android/media/IAudioTrackCallback.aidl",
-    ],
-    path: "aidl",
-}
-
 aidl_interface {
     name: "capture_state_listener-aidl",
     unstable: true,
@@ -236,12 +235,20 @@
     double_loadable: true,
     local_include_dir: "aidl",
     srcs: [
+        "aidl/android/media/AudioAttributesInternal.aidl",
+        "aidl/android/media/AudioClient.aidl",
+        "aidl/android/media/AudioConfig.aidl",
+        "aidl/android/media/AudioConfigBase.aidl",
+        "aidl/android/media/AudioContentType.aidl",
+        "aidl/android/media/AudioEncapsulationMode.aidl",
+        "aidl/android/media/AudioFlag.aidl",
         "aidl/android/media/AudioGainConfig.aidl",
         "aidl/android/media/AudioGainMode.aidl",
         "aidl/android/media/AudioInputFlags.aidl",
         "aidl/android/media/AudioIoConfigEvent.aidl",
         "aidl/android/media/AudioIoDescriptor.aidl",
         "aidl/android/media/AudioIoFlags.aidl",
+        "aidl/android/media/AudioOffloadInfo.aidl",
         "aidl/android/media/AudioOutputFlags.aidl",
         "aidl/android/media/AudioPatch.aidl",
         "aidl/android/media/AudioPortConfig.aidl",
@@ -253,13 +260,22 @@
         "aidl/android/media/AudioPortConfigSessionExt.aidl",
         "aidl/android/media/AudioPortRole.aidl",
         "aidl/android/media/AudioPortType.aidl",
-        "aidl/android/media/AudioSessionType.aidl",
         "aidl/android/media/AudioSourceType.aidl",
         "aidl/android/media/AudioStreamType.aidl",
-    ],
+        "aidl/android/media/AudioUsage.aidl",
+     ],
     imports: [
         "audio_common-aidl",
     ],
+    backend: {
+        cpp: {
+            min_sdk_version: "29",
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.media",
+            ],
+        },
+    },
 }
 
 aidl_interface {
@@ -269,10 +285,17 @@
     host_supported: true,
     vendor_available: true,
     srcs: [
+        "aidl/android/media/CreateRecordRequest.aidl",
+        "aidl/android/media/CreateRecordResponse.aidl",
+        "aidl/android/media/CreateTrackRequest.aidl",
+        "aidl/android/media/CreateTrackResponse.aidl",
+
         "aidl/android/media/IAudioFlingerClient.aidl",
+        "aidl/android/media/IAudioTrackCallback.aidl",
     ],
     imports: [
         "audioclient-types-aidl",
+        "shared-file-region-aidl",
     ],
     double_loadable: true,
     backend: {
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 55b836f..4d9fbb0 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -35,6 +35,15 @@
 #include <media/MediaMetricsItem.h>
 #include <media/TypeConverter.h>
 
+#define VALUE_OR_FATAL(result)                   \
+    ({                                           \
+       auto _tmp = (result);                     \
+       LOG_ALWAYS_FATAL_IF(!_tmp.ok(),           \
+                           "Failed result (%d)", \
+                           _tmp.error());        \
+       std::move(_tmp.value());                  \
+     })
+
 #define WAIT_PERIOD_MS          10
 
 namespace android {
@@ -807,7 +816,9 @@
     originalSessionId = mSessionId;
 
     do {
-        record = audioFlinger->createRecord(input, output, &status);
+        media::CreateRecordResponse response;
+        record = audioFlinger->createRecord(VALUE_OR_FATAL(input.toAidl()), response, &status);
+        output = VALUE_OR_FATAL(IAudioFlinger::CreateRecordOutput::fromAidl(response));
         if (status == NO_ERROR) {
             break;
         }
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 0507879..cfe5f3a 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -33,10 +33,10 @@
 
 #include <system/audio.h>
 
-#define VALUE_OR_RETURN(x) \
+#define VALUE_OR_RETURN_STATUS(x) \
     ({ auto _tmp = (x); \
        if (!_tmp.ok()) return Status::fromStatusT(_tmp.error()); \
-       _tmp.value(); })
+       std::move(_tmp.value()); })
 
 // ----------------------------------------------------------------------------
 
@@ -532,10 +532,10 @@
 Status AudioSystem::AudioFlingerClient::ioConfigChanged(
         media::AudioIoConfigEvent _event,
         const media::AudioIoDescriptor& _ioDesc) {
-    audio_io_config_event event = VALUE_OR_RETURN(
+    audio_io_config_event event = VALUE_OR_RETURN_STATUS(
             aidl2legacy_AudioIoConfigEvent_audio_io_config_event(_event));
     sp<AudioIoDescriptor> ioDesc(
-            VALUE_OR_RETURN(aidl2legacy_AudioIoDescriptor_AudioIoDescriptor(_ioDesc)));
+            VALUE_OR_RETURN_STATUS(aidl2legacy_AudioIoDescriptor_AudioIoDescriptor(_ioDesc)));
 
     ALOGV("ioConfigChanged() event %d", event);
 
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 2c40fbb..14950a8 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -38,6 +38,15 @@
 #include <media/MediaMetricsItem.h>
 #include <media/TypeConverter.h>
 
+#define VALUE_OR_FATAL(result)                   \
+    ({                                           \
+       auto _tmp = (result);                     \
+       LOG_ALWAYS_FATAL_IF(!_tmp.ok(),           \
+                           "Failed result (%d)", \
+                           _tmp.error());        \
+       std::move(_tmp.value());                  \
+     })
+
 #define WAIT_PERIOD_MS                  10
 #define WAIT_STREAM_END_TIMEOUT_SEC     120
 static const int kMaxLoopCountNotifications = 32;
@@ -538,6 +547,7 @@
     } else {
         mOffloadInfo = NULL;
         memset(&mOffloadInfoCopy, 0, sizeof(audio_offload_info_t));
+        mOffloadInfoCopy = AUDIO_INFO_INITIALIZER;
     }
 
     mVolume[AUDIO_INTERLEAVE_LEFT] = 1.0f;
@@ -1596,11 +1606,13 @@
     input.audioTrackCallback = mAudioTrackCallback;
     input.opPackageName = mOpPackageName;
 
-    IAudioFlinger::CreateTrackOutput output;
-
-    sp<IAudioTrack> track = audioFlinger->createTrack(input,
-                                                      output,
+    media::CreateTrackResponse response;
+    sp<IAudioTrack> track = audioFlinger->createTrack(VALUE_OR_FATAL(input.toAidl()),
+                                                      response,
                                                       &status);
+    IAudioFlinger::CreateTrackOutput output = VALUE_OR_FATAL(
+            IAudioFlinger::CreateTrackOutput::fromAidl(
+                    response));
 
     if (status != NO_ERROR || output.outputId == AUDIO_IO_HANDLE_NONE) {
         ALOGE("%s(%d): AudioFlinger could not create track, status: %d output %d",
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index d86182e..57142b0 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -97,6 +97,156 @@
 
 #define MAX_ITEMS_PER_LIST 1024
 
+ConversionResult<media::CreateTrackRequest> IAudioFlinger::CreateTrackInput::toAidl() const {
+    media::CreateTrackRequest aidl;
+    aidl.attr = VALUE_OR_RETURN(legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
+    aidl.config = VALUE_OR_RETURN(legacy2aidl_audio_config_t_AudioConfig(config));
+    aidl.clientInfo = VALUE_OR_RETURN(legacy2aidl_AudioClient(clientInfo));
+    aidl.sharedBuffer = VALUE_OR_RETURN(legacy2aidl_NullableIMemory_SharedFileRegion(sharedBuffer));
+    aidl.notificationsPerBuffer = VALUE_OR_RETURN(convertIntegral<int32_t>(notificationsPerBuffer));
+    aidl.speed = speed;
+    aidl.audioTrackCallback = audioTrackCallback;
+    aidl.opPackageName = opPackageName;
+    aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_output_flags_mask(flags));
+    aidl.frameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(frameCount));
+    aidl.notificationFrameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(notificationFrameCount));
+    aidl.selectedDeviceId = VALUE_OR_RETURN(
+            legacy2aidl_audio_port_handle_t_int32_t(selectedDeviceId));
+    aidl.sessionId = VALUE_OR_RETURN(legacy2aidl_audio_session_t_int32_t(sessionId));
+    return aidl;
+}
+
+ConversionResult<IAudioFlinger::CreateTrackInput>
+IAudioFlinger::CreateTrackInput::fromAidl(const media::CreateTrackRequest& aidl) {
+    IAudioFlinger::CreateTrackInput legacy;
+    legacy.attr = VALUE_OR_RETURN(aidl2legacy_AudioAttributesInternal_audio_attributes_t(aidl.attr));
+    legacy.config = VALUE_OR_RETURN(aidl2legacy_AudioConfig_audio_config_t(aidl.config));
+    legacy.clientInfo = VALUE_OR_RETURN(aidl2legacy_AudioClient(aidl.clientInfo));
+    legacy.sharedBuffer = VALUE_OR_RETURN(aidl2legacy_NullableSharedFileRegion_IMemory(aidl.sharedBuffer));
+    legacy.notificationsPerBuffer = VALUE_OR_RETURN(
+            convertIntegral<uint32_t>(aidl.notificationsPerBuffer));
+    legacy.speed = aidl.speed;
+    legacy.audioTrackCallback = aidl.audioTrackCallback;
+    legacy.opPackageName = aidl.opPackageName;
+    legacy.flags = VALUE_OR_RETURN(aidl2legacy_audio_output_flags_mask(aidl.flags));
+    legacy.frameCount = VALUE_OR_RETURN(convertIntegral<size_t>(aidl.frameCount));
+    legacy.notificationFrameCount = VALUE_OR_RETURN(
+            convertIntegral<size_t>(aidl.notificationFrameCount));
+    legacy.selectedDeviceId = VALUE_OR_RETURN(
+            aidl2legacy_int32_t_audio_port_handle_t(aidl.selectedDeviceId));
+    legacy.sessionId = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_session_t(aidl.sessionId));
+    return legacy;
+}
+
+ConversionResult<media::CreateTrackResponse>
+IAudioFlinger::CreateTrackOutput::toAidl() const {
+    media::CreateTrackResponse aidl;
+    aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_output_flags_mask(flags));
+    aidl.frameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(frameCount));
+    aidl.notificationFrameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(notificationFrameCount));
+    aidl.selectedDeviceId = VALUE_OR_RETURN(
+            legacy2aidl_audio_port_handle_t_int32_t(selectedDeviceId));
+    aidl.sessionId = VALUE_OR_RETURN(legacy2aidl_audio_session_t_int32_t(sessionId));
+    aidl.sampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(sampleRate));
+    aidl.afFrameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(afFrameCount));
+    aidl.afSampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(afSampleRate));
+    aidl.afLatencyMs = VALUE_OR_RETURN(convertIntegral<int32_t>(afLatencyMs));
+    aidl.outputId = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(outputId));
+    aidl.portId = VALUE_OR_RETURN(legacy2aidl_audio_port_handle_t_int32_t(portId));
+    return aidl;
+}
+
+ConversionResult<IAudioFlinger::CreateTrackOutput>
+IAudioFlinger::CreateTrackOutput::fromAidl(
+        const media::CreateTrackResponse& aidl) {
+    IAudioFlinger::CreateTrackOutput legacy;
+    legacy.flags = VALUE_OR_RETURN(aidl2legacy_audio_output_flags_mask(aidl.flags));
+    legacy.frameCount = VALUE_OR_RETURN(convertIntegral<size_t>(aidl.frameCount));
+    legacy.notificationFrameCount = VALUE_OR_RETURN(
+            convertIntegral<size_t>(aidl.notificationFrameCount));
+    legacy.selectedDeviceId = VALUE_OR_RETURN(
+            aidl2legacy_int32_t_audio_port_handle_t(aidl.selectedDeviceId));
+    legacy.sessionId = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_session_t(aidl.sessionId));
+    legacy.sampleRate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.sampleRate));
+    legacy.afFrameCount = VALUE_OR_RETURN(convertIntegral<size_t>(aidl.afFrameCount));
+    legacy.afSampleRate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.afSampleRate));
+    legacy.afLatencyMs = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.afLatencyMs));
+    legacy.outputId = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_io_handle_t(aidl.outputId));
+    legacy.portId = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_port_handle_t(aidl.portId));
+    return legacy;
+}
+
+ConversionResult<media::CreateRecordRequest>
+IAudioFlinger::CreateRecordInput::toAidl() const {
+    media::CreateRecordRequest aidl;
+    aidl.attr = VALUE_OR_RETURN(legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
+    aidl.config = VALUE_OR_RETURN(legacy2aidl_audio_config_base_t_AudioConfigBase(config));
+    aidl.clientInfo = VALUE_OR_RETURN(legacy2aidl_AudioClient(clientInfo));
+    aidl.opPackageName = VALUE_OR_RETURN(legacy2aidl_String16_string(opPackageName));
+    aidl.riid = VALUE_OR_RETURN(legacy2aidl_audio_unique_id_t_int32_t(riid));
+    aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_input_flags_mask(flags));
+    aidl.frameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(frameCount));
+    aidl.notificationFrameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(notificationFrameCount));
+    aidl.selectedDeviceId = VALUE_OR_RETURN(
+            legacy2aidl_audio_port_handle_t_int32_t(selectedDeviceId));
+    aidl.sessionId = VALUE_OR_RETURN(legacy2aidl_audio_session_t_int32_t(sessionId));
+    return aidl;
+}
+
+ConversionResult<IAudioFlinger::CreateRecordInput>
+IAudioFlinger::CreateRecordInput::fromAidl(
+        const media::CreateRecordRequest& aidl) {
+    IAudioFlinger::CreateRecordInput legacy;
+    legacy.attr = VALUE_OR_RETURN(aidl2legacy_AudioAttributesInternal_audio_attributes_t(aidl.attr));
+    legacy.config = VALUE_OR_RETURN(aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.config));
+    legacy.clientInfo = VALUE_OR_RETURN(aidl2legacy_AudioClient(aidl.clientInfo));
+    legacy.opPackageName = VALUE_OR_RETURN(aidl2legacy_string_view_String16(aidl.opPackageName));
+    legacy.riid = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_unique_id_t(aidl.riid));
+    legacy.flags = VALUE_OR_RETURN(aidl2legacy_audio_input_flags_mask(aidl.flags));
+    legacy.frameCount = VALUE_OR_RETURN(convertIntegral<size_t>(aidl.frameCount));
+    legacy.notificationFrameCount = VALUE_OR_RETURN(
+            convertIntegral<size_t>(aidl.notificationFrameCount));
+    legacy.selectedDeviceId = VALUE_OR_RETURN(
+            aidl2legacy_int32_t_audio_port_handle_t(aidl.selectedDeviceId));
+    legacy.sessionId = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_session_t(aidl.sessionId));
+    return legacy;
+}
+
+ConversionResult<media::CreateRecordResponse>
+IAudioFlinger::CreateRecordOutput::toAidl() const {
+    media::CreateRecordResponse aidl;
+    aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_input_flags_mask(flags));
+    aidl.frameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(frameCount));
+    aidl.notificationFrameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(notificationFrameCount));
+    aidl.selectedDeviceId = VALUE_OR_RETURN(
+            legacy2aidl_audio_port_handle_t_int32_t(selectedDeviceId));
+    aidl.sessionId = VALUE_OR_RETURN(legacy2aidl_audio_session_t_int32_t(sessionId));
+    aidl.sampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(sampleRate));
+    aidl.inputId = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(inputId));
+    aidl.cblk = VALUE_OR_RETURN(legacy2aidl_NullableIMemory_SharedFileRegion(cblk));
+    aidl.buffers = VALUE_OR_RETURN(legacy2aidl_NullableIMemory_SharedFileRegion(buffers));
+    aidl.portId = VALUE_OR_RETURN(legacy2aidl_audio_port_handle_t_int32_t(portId));
+    return aidl;
+}
+
+ConversionResult<IAudioFlinger::CreateRecordOutput>
+IAudioFlinger::CreateRecordOutput::fromAidl(
+        const media::CreateRecordResponse& aidl) {
+    IAudioFlinger::CreateRecordOutput legacy;
+    legacy.flags = VALUE_OR_RETURN(aidl2legacy_audio_input_flags_mask(aidl.flags));
+    legacy.frameCount = VALUE_OR_RETURN(convertIntegral<size_t>(aidl.frameCount));
+    legacy.notificationFrameCount = VALUE_OR_RETURN(
+            convertIntegral<size_t>(aidl.notificationFrameCount));
+    legacy.selectedDeviceId = VALUE_OR_RETURN(
+            aidl2legacy_int32_t_audio_port_handle_t(aidl.selectedDeviceId));
+    legacy.sessionId = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_session_t(aidl.sessionId));
+    legacy.sampleRate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.sampleRate));
+    legacy.inputId = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_io_handle_t(aidl.inputId));
+    legacy.cblk = VALUE_OR_RETURN(aidl2legacy_NullableSharedFileRegion_IMemory(aidl.cblk));
+    legacy.buffers = VALUE_OR_RETURN(aidl2legacy_NullableSharedFileRegion_IMemory(aidl.buffers));
+    legacy.portId = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_port_handle_t(aidl.portId));
+    return legacy;
+}
 
 class BpAudioFlinger : public BpInterface<IAudioFlinger>
 {
@@ -106,9 +256,9 @@
     {
     }
 
-    virtual sp<IAudioTrack> createTrack(const CreateTrackInput& input,
-                                        CreateTrackOutput& output,
-                                        status_t *status)
+    virtual sp<IAudioTrack> createTrack(const media::CreateTrackRequest& input,
+                                        media::CreateTrackResponse& output,
+                                        status_t* status)
     {
         Parcel data, reply;
         sp<IAudioTrack> track;
@@ -118,7 +268,7 @@
             return track;
         }
 
-        input.writeToParcel(&data);
+        data.writeParcelable(input);
 
         status_t lStatus = remote()->transact(CREATE_TRACK, data, &reply);
         if (lStatus != NO_ERROR) {
@@ -141,9 +291,9 @@
         return track;
     }
 
-    virtual sp<media::IAudioRecord> createRecord(const CreateRecordInput& input,
-                                                 CreateRecordOutput& output,
-                                                 status_t *status)
+    virtual sp<media::IAudioRecord> createRecord(const media::CreateRecordRequest& input,
+                                                 media::CreateRecordResponse& output,
+                                                 status_t* status)
     {
         Parcel data, reply;
         sp<media::IAudioRecord> record;
@@ -153,7 +303,7 @@
             return record;
         }
 
-        input.writeToParcel(&data);
+        data.writeParcelable(input);
 
         status_t lStatus = remote()->transact(CREATE_RECORD, data, &reply);
         if (lStatus != NO_ERROR) {
@@ -1040,14 +1190,14 @@
         case CREATE_TRACK: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
 
-            CreateTrackInput input;
-            if (input.readFromParcel((Parcel*)&data) != NO_ERROR) {
+            media::CreateTrackRequest input;
+            if (data.readParcelable(&input) != NO_ERROR) {
                 reply->writeInt32(DEAD_OBJECT);
                 return NO_ERROR;
             }
 
             status_t status;
-            CreateTrackOutput output;
+            media::CreateTrackResponse output;
 
             sp<IAudioTrack> track= createTrack(input,
                                                output,
@@ -1065,14 +1215,14 @@
         case CREATE_RECORD: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
 
-            CreateRecordInput input;
-            if (input.readFromParcel((Parcel*)&data) != NO_ERROR) {
+            media::CreateRecordRequest input;
+            if (data.readParcelable(&input) != NO_ERROR) {
                 reply->writeInt32(DEAD_OBJECT);
                 return NO_ERROR;
             }
 
             status_t status;
-            CreateRecordOutput output;
+            media::CreateRecordResponse output;
 
             sp<media::IAudioRecord> record = createRecord(input,
                                                           output,
diff --git a/media/libaudioclient/PlayerBase.cpp b/media/libaudioclient/PlayerBase.cpp
index b0c68e5..c443865 100644
--- a/media/libaudioclient/PlayerBase.cpp
+++ b/media/libaudioclient/PlayerBase.cpp
@@ -22,7 +22,8 @@
 
 namespace android {
 
-using media::VolumeShaper;
+using media::VolumeShaperConfiguration;
+using media::VolumeShaperOperation;
 
 //--------------------------------------------------------------------------------------------------
 PlayerBase::PlayerBase() : BnPlayer(),
@@ -178,8 +179,8 @@
 }
 
 binder::Status PlayerBase::applyVolumeShaper(
-            const VolumeShaper::Configuration& configuration __unused,
-            const VolumeShaper::Operation& operation __unused) {
+            const VolumeShaperConfiguration& configuration __unused,
+            const VolumeShaperOperation& operation __unused) {
     ALOGW("applyVolumeShaper() is not supported");
     return binder::Status::ok();
 }
diff --git a/media/libaudioclient/TrackPlayerBase.cpp b/media/libaudioclient/TrackPlayerBase.cpp
index 0a914fc..e571838 100644
--- a/media/libaudioclient/TrackPlayerBase.cpp
+++ b/media/libaudioclient/TrackPlayerBase.cpp
@@ -106,11 +106,17 @@
 
 
 binder::Status TrackPlayerBase::applyVolumeShaper(
-        const VolumeShaper::Configuration& configuration,
-        const VolumeShaper::Operation& operation) {
+        const media::VolumeShaperConfiguration& configuration,
+        const media::VolumeShaperOperation& operation) {
 
-    sp<VolumeShaper::Configuration> spConfiguration = new VolumeShaper::Configuration(configuration);
-    sp<VolumeShaper::Operation> spOperation = new VolumeShaper::Operation(operation);
+    sp<VolumeShaper::Configuration> spConfiguration = new VolumeShaper::Configuration();
+    sp<VolumeShaper::Operation> spOperation = new VolumeShaper::Operation();
+
+    status_t s = spConfiguration->readFromParcelable(configuration)
+            ?: spOperation->readFromParcelable(operation);
+    if (s != OK) {
+        return binder::Status::fromStatusT(s);
+    }
 
     if (mAudioTrack != 0) {
         ALOGD("TrackPlayerBase::applyVolumeShaper() from IPlayer");
diff --git a/media/libaudioclient/aidl/android/media/AudioAttributesInternal.aidl b/media/libaudioclient/aidl/android/media/AudioAttributesInternal.aidl
new file mode 100644
index 0000000..699df0a
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioAttributesInternal.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2020 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;
+
+import android.media.AudioContentType;
+import android.media.AudioSourceType;
+import android.media.AudioUsage;
+
+/**
+ * The "Internal" suffix of this type name is to disambiguate it from the
+ * android.media.AudioAttributes SDK type.
+ * {@hide}
+ */
+parcelable AudioAttributesInternal {
+    AudioContentType contentType;
+    AudioUsage usage;
+    AudioSourceType source;
+    // Bitmask, indexed by AudioFlag.
+    int flags;
+    @utf8InCpp String tags; /* UTF8 */
+}
diff --git a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl b/media/libaudioclient/aidl/android/media/AudioClient.aidl
similarity index 73%
copy from media/libaudioclient/aidl/android/media/AudioSessionType.aidl
copy to media/libaudioclient/aidl/android/media/AudioClient.aidl
index d305c29..7bff0d6 100644
--- a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioClient.aidl
@@ -13,13 +13,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.media;
 
-@Backing(type="int")
-enum AudioSessionType {
-    DEVICE = -2,
-    OUTPUT_STAGE = -1,
-    OUTPUT_MIX = 0,
-    ALLOCATE = 0,
-    NONE = 0,
+/**
+ * {@hide}
+ */
+parcelable AudioClient {
+    /** Interpreted as uid_t. */
+    int clientUid;
+    /** Interpreted as pid_t. */
+    int clientPid;
+    /** Interpreted as pid_t. */
+    int clientTid;
+    @utf8InCpp String packageName;
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl b/media/libaudioclient/aidl/android/media/AudioConfig.aidl
similarity index 64%
copy from media/libaudioclient/aidl/android/media/AudioSessionType.aidl
copy to media/libaudioclient/aidl/android/media/AudioConfig.aidl
index d305c29..8dc97d3 100644
--- a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioConfig.aidl
@@ -13,13 +13,23 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.media;
 
-@Backing(type="int")
-enum AudioSessionType {
-    DEVICE = -2,
-    OUTPUT_STAGE = -1,
-    OUTPUT_MIX = 0,
-    ALLOCATE = 0,
-    NONE = 0,
+import android.media.AudioOffloadInfo;
+import android.media.audio.common.AudioFormat;
+
+/**
+ * {@hide}
+ */
+parcelable AudioConfig {
+    int sampleRate;
+    /**
+     * Interpreted as audio_channel_mask_t.
+     * TODO(ytai): Create a designated type.
+     */
+    int channelMask;
+    AudioFormat format;
+    AudioOffloadInfo offloadInfo;
+    long frameCount;
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl b/media/libaudioclient/aidl/android/media/AudioConfigBase.aidl
similarity index 75%
copy from media/libaudioclient/aidl/android/media/AudioSessionType.aidl
copy to media/libaudioclient/aidl/android/media/AudioConfigBase.aidl
index d305c29..8353c0d 100644
--- a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioConfigBase.aidl
@@ -13,13 +13,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.media;
 
-@Backing(type="int")
-enum AudioSessionType {
-    DEVICE = -2,
-    OUTPUT_STAGE = -1,
-    OUTPUT_MIX = 0,
-    ALLOCATE = 0,
-    NONE = 0,
+import android.media.audio.common.AudioFormat;
+
+/**
+ * {@hide}
+ */
+parcelable AudioConfigBase {
+    int sampleRate;
+    /** Interpreted as audio_channel_mask_t. */
+    int channelMask;
+    AudioFormat format;
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl b/media/libaudioclient/aidl/android/media/AudioContentType.aidl
similarity index 85%
rename from media/libaudioclient/aidl/android/media/AudioSessionType.aidl
rename to media/libaudioclient/aidl/android/media/AudioContentType.aidl
index d305c29..f734fba 100644
--- a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioContentType.aidl
@@ -16,10 +16,10 @@
 package android.media;
 
 @Backing(type="int")
-enum AudioSessionType {
-    DEVICE = -2,
-    OUTPUT_STAGE = -1,
-    OUTPUT_MIX = 0,
-    ALLOCATE = 0,
-    NONE = 0,
+enum AudioContentType {
+    UNKNOWN = 0,
+    SPEECH = 1,
+    MUSIC = 2,
+    MOVIE = 3,
+    SONIFICATION = 4,
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl b/media/libaudioclient/aidl/android/media/AudioEncapsulationMode.aidl
similarity index 84%
copy from media/libaudioclient/aidl/android/media/AudioSessionType.aidl
copy to media/libaudioclient/aidl/android/media/AudioEncapsulationMode.aidl
index d305c29..74a6141 100644
--- a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioEncapsulationMode.aidl
@@ -16,10 +16,8 @@
 package android.media;
 
 @Backing(type="int")
-enum AudioSessionType {
-    DEVICE = -2,
-    OUTPUT_STAGE = -1,
-    OUTPUT_MIX = 0,
-    ALLOCATE = 0,
-    NONE = 0,
+enum AudioEncapsulationMode {
+     NONE = 0,
+     ELEMENTARY_STREAM = 1,
+     HANDLE = 2,
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl b/media/libaudioclient/aidl/android/media/AudioFlag.aidl
similarity index 66%
copy from media/libaudioclient/aidl/android/media/AudioSessionType.aidl
copy to media/libaudioclient/aidl/android/media/AudioFlag.aidl
index d305c29..2602fe5 100644
--- a/media/libaudioclient/aidl/android/media/AudioSessionType.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioFlag.aidl
@@ -16,10 +16,19 @@
 package android.media;
 
 @Backing(type="int")
-enum AudioSessionType {
-    DEVICE = -2,
-    OUTPUT_STAGE = -1,
-    OUTPUT_MIX = 0,
-    ALLOCATE = 0,
-    NONE = 0,
+enum AudioFlag {
+    AUDIBILITY_ENFORCED = 0,
+    SECURE = 1,
+    SCO = 2,
+    BEACON = 3,
+    HW_AV_SYNC = 4,
+    HW_HOTWORD = 5,
+    BYPASS_INTERRUPTION_POLICY = 6,
+    BYPASS_MUTE = 7,
+    LOW_LATENCY = 8,
+    DEEP_BUFFER = 9,
+    NO_MEDIA_PROJECTION = 10,
+    MUTE_HAPTIC = 11,
+    NO_SYSTEM_CAPTURE = 12,
+    CAPTURE_PRIVATE = 13,
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioIoFlags.aidl b/media/libaudioclient/aidl/android/media/AudioIoFlags.aidl
index 1fe2acc..f9b25bf 100644
--- a/media/libaudioclient/aidl/android/media/AudioIoFlags.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioIoFlags.aidl
@@ -19,12 +19,9 @@
 /**
  * {@hide}
  */
-// TODO(b/150948558): This should be a union. In the meantime, we require
-// that exactly one of the below arrays has a single element and the rest
-// are empty.
-parcelable AudioIoFlags {
+union AudioIoFlags {
     /** Bitmask indexed by AudioInputFlags. */
-    int[] input;
+    int input;
     /** Bitmask indexed by AudioOutputFlags. */
-    int[] output;
+    int output;
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioOffloadInfo.aidl b/media/libaudioclient/aidl/android/media/AudioOffloadInfo.aidl
new file mode 100644
index 0000000..c86b3f0
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioOffloadInfo.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 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;
+
+import android.media.AudioConfigBase;
+import android.media.AudioEncapsulationMode;
+import android.media.AudioStreamType;
+import android.media.AudioUsage;
+import android.media.audio.common.AudioFormat;
+
+/**
+ * {@hide}
+ */
+parcelable AudioOffloadInfo {
+    /** Version of the info structure. Interpreted as a uint16_t version constant. */
+    int version;
+    /** Audio configuration. */
+    AudioConfigBase config;
+    /** Stream type. */
+    AudioStreamType streamType;
+    /** Bit rate in bits per second. */
+    int bitRate;
+    /** Duration in microseconds, -1 if unknown. */
+    long durationUs;
+    /** true if stream is tied to a video stream. */
+    boolean hasVideo;
+    /** true if streaming, false if local playback. */
+    boolean isStreaming;
+    int bitWidth;
+    /** Offload fragment size. */
+    int offloadBufferSize;
+    AudioUsage usage;
+    AudioEncapsulationMode encapsulationMode;
+    /** Content id from tuner HAL (0 if none). */
+    int contentId;
+    /** Sync id from tuner HAL (0 if none). */
+    int syncId;
+}
diff --git a/media/libaudioclient/aidl/android/media/AudioPortConfigExt.aidl b/media/libaudioclient/aidl/android/media/AudioPortConfigExt.aidl
index 83e985e..38da4f5 100644
--- a/media/libaudioclient/aidl/android/media/AudioPortConfigExt.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioPortConfigExt.aidl
@@ -23,15 +23,17 @@
 /**
  * {@hide}
  */
-parcelable AudioPortConfigExt {
-    // TODO(b/150948558): This should be a union. In the meantime, we require
-    // that exactly one of the below arrays has a single element and the rest
-    // are empty.
-
+union AudioPortConfigExt {
+    /**
+     * This represents an empty union. Value is ignored.
+     * TODO(ytai): replace with the canonical representation for an empty union, as soon as it is
+     *             established.
+     */
+    boolean nothing;
     /** Device specific info. */
-    AudioPortConfigDeviceExt[] device;
+    AudioPortConfigDeviceExt device;
     /** Mix specific info. */
-    AudioPortConfigMixExt[] mix;
+    AudioPortConfigMixExt mix;
     /** Session specific info. */
-    AudioPortConfigSessionExt[] session;
+    AudioPortConfigSessionExt session;
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioPortConfigMixExtUseCase.aidl b/media/libaudioclient/aidl/android/media/AudioPortConfigMixExtUseCase.aidl
index 675daf8..9e5e081 100644
--- a/media/libaudioclient/aidl/android/media/AudioPortConfigMixExtUseCase.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioPortConfigMixExtUseCase.aidl
@@ -22,13 +22,16 @@
 /**
  * {@hide}
  */
-parcelable AudioPortConfigMixExtUseCase {
-    // TODO(b/150948558): This should be a union. In the meantime, we require
-    // that exactly one of the below arrays has a single element and the rest
-    // are empty.
-
+union AudioPortConfigMixExtUseCase {
+    /**
+     * This to be set if the containing config has the AudioPortRole::NONE role.
+     * This represents an empty value (value is ignored).
+     * TODO(ytai): replace with the canonical representation for an empty union, as soon as it is
+     *             established.
+     */
+    boolean nothing;
     /** This to be set if the containing config has the AudioPortRole::SOURCE role. */
-    AudioStreamType[] stream;
+    AudioStreamType stream;
     /** This to be set if the containing config has the AudioPortRole::SINK role. */
-    AudioSourceType[] source;
+    AudioSourceType source;
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioPortConfigSessionExt.aidl b/media/libaudioclient/aidl/android/media/AudioPortConfigSessionExt.aidl
index d3261d9..a2cbf62 100644
--- a/media/libaudioclient/aidl/android/media/AudioPortConfigSessionExt.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioPortConfigSessionExt.aidl
@@ -16,11 +16,9 @@
 
 package android.media;
 
-import android.media.AudioSessionType;
-
 /**
  * {@hide}
  */
 parcelable AudioPortConfigSessionExt {
-    AudioSessionType session;
+    int session;
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioSourceType.aidl b/media/libaudioclient/aidl/android/media/AudioSourceType.aidl
index f6ecc46..35320f8 100644
--- a/media/libaudioclient/aidl/android/media/AudioSourceType.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioSourceType.aidl
@@ -17,6 +17,7 @@
 
 @Backing(type="int")
 enum AudioSourceType {
+    INVALID = -1,
     DEFAULT = 0,
     MIC = 1,
     VOICE_UPLINK = 2,
diff --git a/media/libaudioclient/aidl/android/media/AudioUsage.aidl b/media/libaudioclient/aidl/android/media/AudioUsage.aidl
new file mode 100644
index 0000000..137e7ff
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioUsage.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 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;
+
+@Backing(type="int")
+enum AudioUsage {
+    UNKNOWN = 0,
+    MEDIA = 1,
+    VOICE_COMMUNICATION = 2,
+    VOICE_COMMUNICATION_SIGNALLING = 3,
+    ALARM = 4,
+    NOTIFICATION = 5,
+    NOTIFICATION_TELEPHONY_RINGTONE = 6,
+    NOTIFICATION_COMMUNICATION_REQUEST = 7,
+    NOTIFICATION_COMMUNICATION_INSTANT = 8,
+    NOTIFICATION_COMMUNICATION_DELAYED = 9,
+    NOTIFICATION_EVENT = 10,
+    ASSISTANCE_ACCESSIBILITY = 11,
+    ASSISTANCE_NAVIGATION_GUIDANCE = 12,
+    ASSISTANCE_SONIFICATION = 13,
+    GAME = 14,
+    VIRTUAL_SOURCE = 15,
+    ASSISTANT = 16,
+    CALL_ASSISTANT = 17,
+    EMERGENCY = 1000,
+    SAFETY = 1001,
+    VEHICLE_STATUS = 1002,
+    ANNOUNCEMENT = 1003,
+}
diff --git a/media/libaudioclient/aidl/android/media/CreateRecordRequest.aidl b/media/libaudioclient/aidl/android/media/CreateRecordRequest.aidl
new file mode 100644
index 0000000..6da743a
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/CreateRecordRequest.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 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;
+
+import android.media.AudioAttributesInternal;
+import android.media.AudioClient;
+import android.media.AudioConfigBase;
+
+/**
+ * CreateRecordRequest contains all input arguments sent by AudioRecord to AudioFlinger
+ * when calling createRecord() including arguments that will be updated by AudioFlinger
+ * and returned in CreateRecordResponse object.
+ *
+ * {@hide}
+ */
+parcelable CreateRecordRequest {
+    AudioAttributesInternal attr;
+    AudioConfigBase config;
+    AudioClient clientInfo;
+    @utf8InCpp String opPackageName;
+    /** Interpreted as audio_unique_id_t. */
+    int riid;
+    /** Bitmask, indexed by AudioInputFlags. */
+    int flags;
+    long frameCount;
+    long notificationFrameCount;
+    /** Interpreted as audio_port_handle_t. */
+    int selectedDeviceId;
+    int sessionId;
+}
diff --git a/media/libaudioclient/aidl/android/media/CreateRecordResponse.aidl b/media/libaudioclient/aidl/android/media/CreateRecordResponse.aidl
new file mode 100644
index 0000000..0c9d7c3
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/CreateRecordResponse.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2020 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;
+
+import android.media.SharedFileRegion;
+
+/**
+ * CreateRecordResponse contains all output arguments returned by AudioFlinger to AudioRecord
+ * when calling createRecord() including arguments that were passed as I/O for update by
+ * CreateRecordRequest.
+ *
+ * {@hide}
+ */
+parcelable CreateRecordResponse {
+    /** Bitmask, indexed by AudioInputFlags. */
+    int flags;
+    long frameCount;
+    long notificationFrameCount;
+    /** Interpreted as audio_port_handle_t. */
+    int selectedDeviceId;
+    int sessionId;
+    int sampleRate;
+    /** Interpreted as audio_io_handle_t. */
+    int inputId;
+    @nullable SharedFileRegion cblk;
+    @nullable SharedFileRegion buffers;
+    /** Interpreted as audio_port_handle_t. */
+    int portId;
+}
diff --git a/media/libaudioclient/aidl/android/media/CreateTrackRequest.aidl b/media/libaudioclient/aidl/android/media/CreateTrackRequest.aidl
new file mode 100644
index 0000000..014b3ca
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/CreateTrackRequest.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2020 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;
+
+import android.media.AudioAttributesInternal;
+import android.media.AudioClient;
+import android.media.AudioConfig;
+import android.media.IAudioTrackCallback;
+import android.media.SharedFileRegion;
+
+/**
+ * CreateTrackInput contains all input arguments sent by AudioTrack to AudioFlinger
+ * when calling createTrack() including arguments that will be updated by AudioFlinger
+ * and returned in CreateTrackResponse object.
+ *
+ * {@hide}
+ */
+parcelable CreateTrackRequest {
+    AudioAttributesInternal attr;
+    AudioConfig config;
+    AudioClient clientInfo;
+    @nullable SharedFileRegion sharedBuffer;
+    int notificationsPerBuffer;
+    float speed;
+    IAudioTrackCallback audioTrackCallback;
+    @utf8InCpp String opPackageName;
+    /** Bitmask, indexed by AudioOutputFlags. */
+    int flags;
+    long frameCount;
+    long notificationFrameCount;
+    /** Interpreted as audio_port_handle_t. */
+    int selectedDeviceId;
+    int sessionId;
+}
diff --git a/media/libaudioclient/aidl/android/media/CreateTrackResponse.aidl b/media/libaudioclient/aidl/android/media/CreateTrackResponse.aidl
new file mode 100644
index 0000000..494e63f
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/CreateTrackResponse.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 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;
+
+/**
+ * CreateTrackOutput contains all output arguments returned by AudioFlinger to AudioTrack
+ * when calling createTrack() including arguments that were passed as I/O for update by
+ * CreateTrackRequest.
+ *
+ * {@hide}
+ */
+parcelable CreateTrackResponse {
+    /** Bitmask, indexed by AudioOutputFlags. */
+    int flags;
+    long frameCount;
+    long notificationFrameCount;
+    /** Interpreted as audio_port_handle_t. */
+    int selectedDeviceId;
+    int sessionId;
+    int sampleRate;
+    long afFrameCount;
+    int afSampleRate;
+    int afLatencyMs;
+    /** Interpreted as audio_io_handle_t. */
+    int outputId;
+    /** Interpreted as audio_port_handle_t. */
+    int portId;
+}
diff --git a/media/libaudioclient/aidl/android/media/IPlayer.aidl b/media/libaudioclient/aidl/android/media/IPlayer.aidl
index a90fcdd..8c2c471 100644
--- a/media/libaudioclient/aidl/android/media/IPlayer.aidl
+++ b/media/libaudioclient/aidl/android/media/IPlayer.aidl
@@ -16,8 +16,8 @@
 
 package android.media;
 
-import android.media.VolumeShaper.Configuration;
-import android.media.VolumeShaper.Operation;
+import android.media.VolumeShaperConfiguration;
+import android.media.VolumeShaperOperation;
 
 /**
  * @hide
@@ -29,6 +29,6 @@
     oneway void setVolume(float vol);
     oneway void setPan(float pan);
     oneway void setStartDelayMs(int delayMs);
-    oneway void applyVolumeShaper(in Configuration configuration,
-                                  in Operation operation);
+    oneway void applyVolumeShaper(in VolumeShaperConfiguration configuration,
+                                  in VolumeShaperOperation operation);
 }
diff --git a/media/libaudioclient/aidl/android/media/VolumeShaper/Configuration.aidl b/media/libaudioclient/aidl/android/media/VolumeShaper/Configuration.aidl
deleted file mode 100644
index fd0e60f..0000000
--- a/media/libaudioclient/aidl/android/media/VolumeShaper/Configuration.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2017 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.VolumeShaper;
-
-parcelable Configuration cpp_header "media/VolumeShaper.h";
diff --git a/media/libaudioclient/aidl/android/media/VolumeShaper/Operation.aidl b/media/libaudioclient/aidl/android/media/VolumeShaper/Operation.aidl
deleted file mode 100644
index 4290d9d..0000000
--- a/media/libaudioclient/aidl/android/media/VolumeShaper/Operation.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2017 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.VolumeShaper;
-
-parcelable Operation cpp_header "media/VolumeShaper.h";
diff --git a/media/libaudioclient/aidl/android/media/VolumeShaper/State.aidl b/media/libaudioclient/aidl/android/media/VolumeShaper/State.aidl
deleted file mode 100644
index f6a22b8..0000000
--- a/media/libaudioclient/aidl/android/media/VolumeShaper/State.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2017 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.VolumeShaper;
-
-parcelable State cpp_header "media/VolumeShaper.h";
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index a1b9b82..4df8083 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -16,9 +16,18 @@
 
 #pragma once
 
+#include <limits>
+#include <type_traits>
+
 #include <system/audio.h>
 
-#include <android-base/result.h>
+#include <android-base/expected.h>
+
+#include <android/media/AudioAttributesInternal.h>
+#include <android/media/AudioClient.h>
+#include <android/media/AudioConfig.h>
+#include <android/media/AudioConfigBase.h>
+#include <android/media/AudioFlag.h>
 #include <android/media/AudioGainMode.h>
 #include <android/media/AudioInputFlags.h>
 #include <android/media/AudioIoConfigEvent.h>
@@ -26,6 +35,10 @@
 #include <android/media/AudioOutputFlags.h>
 #include <android/media/AudioPortConfigType.h>
 
+#include <android/media/SharedFileRegion.h>
+
+#include <binder/IMemory.h>
+#include <media/AudioClient.h>
 #include <media/AudioIoDescriptor.h>
 
 namespace android {
@@ -33,6 +46,63 @@
 template <typename T>
 using ConversionResult = base::expected<T, status_t>;
 
+// Convenience macros for working with ConversionResult, useful for writing converted for aggregate
+// types.
+
+#define VALUE_OR_RETURN(result)                                \
+    ({                                                         \
+        auto _tmp = (result);                                  \
+        if (!_tmp.ok()) return base::unexpected(_tmp.error()); \
+        std::move(_tmp.value());                               \
+    })
+
+#define RETURN_IF_ERROR(result) \
+    if (status_t _tmp = (result); _tmp != OK) return base::unexpected(_tmp);
+
+/**
+ * A generic template to safely cast between integral types, respecting limits of the destination
+ * type.
+ */
+template<typename To, typename From>
+ConversionResult<To> convertIntegral(From from) {
+    // Special handling is required for signed / vs. unsigned comparisons, since otherwise we may
+    // have the signed converted to unsigned and produce wrong results.
+    if (std::is_signed_v<From> && !std::is_signed_v<To>) {
+        if (from < 0 || from > std::numeric_limits<To>::max()) {
+            return base::unexpected(BAD_VALUE);
+        }
+    } else if (std::is_signed_v<To> && !std::is_signed_v<From>) {
+        if (from > std::numeric_limits<To>::max()) {
+            return base::unexpected(BAD_VALUE);
+        }
+    } else {
+        if (from < std::numeric_limits<To>::min() || from > std::numeric_limits<To>::max()) {
+            return base::unexpected(BAD_VALUE);
+        }
+    }
+    return static_cast<To>(from);
+}
+
+// maxSize is the size of the C-string buffer (including the 0-terminator), NOT the max length of
+// the string.
+status_t aidl2legacy_string(std::string_view aidl, char* dest, size_t maxSize);
+ConversionResult<std::string> legacy2aidl_string(const char* legacy, size_t maxSize);
+
+ConversionResult<audio_module_handle_t> aidl2legacy_int32_t_audio_module_handle_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_module_handle_t_int32_t(audio_module_handle_t legacy);
+
+ConversionResult<audio_io_handle_t> aidl2legacy_int32_t_audio_io_handle_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_io_handle_t_int32_t(audio_io_handle_t legacy);
+
+ConversionResult<audio_port_handle_t> aidl2legacy_int32_t_audio_port_handle_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_port_handle_t_int32_t(audio_port_handle_t legacy);
+
+ConversionResult<audio_patch_handle_t> aidl2legacy_int32_t_audio_patch_handle_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_patch_handle_t_int32_t(audio_patch_handle_t legacy);
+
+ConversionResult<audio_unique_id_t> aidl2legacy_int32_t_audio_unique_id_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_unique_id_t_int32_t(audio_unique_id_t legacy);
+
 // The legacy enum is unnamed. Thus, we use int.
 ConversionResult<int> aidl2legacy_AudioPortConfigType(media::AudioPortConfigType aidl);
 // The legacy enum is unnamed. Thus, we use int.
@@ -44,6 +114,15 @@
 ConversionResult<audio_channel_mask_t> aidl2legacy_int32_t_audio_channel_mask_t(int32_t aidl);
 ConversionResult<int32_t> legacy2aidl_audio_channel_mask_t_int32_t(audio_channel_mask_t legacy);
 
+ConversionResult<pid_t> aidl2legacy_int32_t_pid_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_pid_t_int32_t(pid_t legacy);
+
+ConversionResult<uid_t> aidl2legacy_int32_t_uid_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_uid_t_int32_t(uid_t legacy);
+
+ConversionResult<String16> aidl2legacy_string_view_String16(std::string_view aidl);
+ConversionResult<std::string> legacy2aidl_String16_string(const String16& legacy);
+
 ConversionResult<audio_io_config_event> aidl2legacy_AudioIoConfigEvent_audio_io_config_event(
         media::AudioIoConfigEvent aidl);
 ConversionResult<media::AudioIoConfigEvent> legacy2aidl_audio_io_config_event_AudioIoConfigEvent(
@@ -114,10 +193,8 @@
 ConversionResult<media::AudioSourceType> legacy2aidl_audio_source_t_AudioSourceType(
         audio_source_t legacy);
 
-ConversionResult<audio_session_t> aidl2legacy_AudioSessionType_audio_session_t(
-        media::AudioSessionType aidl);
-ConversionResult<media::AudioSessionType> legacy2aidl_audio_session_t_AudioSessionType(
-        audio_session_t legacy);
+ConversionResult<audio_session_t> aidl2legacy_int32_t_audio_session_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_session_t_int32_t(audio_session_t legacy);
 
 ConversionResult<audio_port_config_mix_ext> aidl2legacy_AudioPortConfigMixExt(
         const media::AudioPortConfigMixExt& aidl, media::AudioPortRole role);
@@ -141,7 +218,66 @@
 
 ConversionResult<sp<AudioIoDescriptor>> aidl2legacy_AudioIoDescriptor_AudioIoDescriptor(
         const media::AudioIoDescriptor& aidl);
+
 ConversionResult<media::AudioIoDescriptor> legacy2aidl_AudioIoDescriptor_AudioIoDescriptor(
         const sp<AudioIoDescriptor>& legacy);
 
+ConversionResult<AudioClient> aidl2legacy_AudioClient(const media::AudioClient& aidl);
+ConversionResult<media::AudioClient> legacy2aidl_AudioClient(const AudioClient& legacy);
+
+ConversionResult<audio_content_type_t>
+aidl2legacy_AudioContentType_audio_content_type_t(media::AudioContentType aidl);
+ConversionResult<media::AudioContentType>
+legacy2aidl_audio_content_type_t_AudioContentType(audio_content_type_t legacy);
+
+ConversionResult<audio_usage_t>
+aidl2legacy_AudioUsage_audio_usage_t(media::AudioUsage aidl);
+ConversionResult<media::AudioUsage>
+legacy2aidl_audio_usage_t_AudioUsage(audio_usage_t legacy);
+
+ConversionResult<audio_flags_mask_t>
+aidl2legacy_AudioFlag_audio_flags_mask_t(media::AudioFlag aidl);
+ConversionResult<media::AudioFlag>
+legacy2aidl_audio_flags_mask_t_AudioFlag(audio_flags_mask_t legacy);
+
+ConversionResult<audio_flags_mask_t>
+aidl2legacy_int32_t_audio_flags_mask_t_mask(int32_t aidl);
+ConversionResult<int32_t>
+legacy2aidl_audio_flags_mask_t_int32_t_mask(audio_flags_mask_t legacy);
+
+ConversionResult<audio_attributes_t>
+aidl2legacy_AudioAttributesInternal_audio_attributes_t(const media::AudioAttributesInternal& aidl);
+ConversionResult<media::AudioAttributesInternal>
+legacy2aidl_audio_attributes_t_AudioAttributesInternal(const audio_attributes_t& legacy);
+
+ConversionResult<audio_encapsulation_mode_t>
+aidl2legacy_audio_encapsulation_mode_t_AudioEncapsulationMode(media::AudioEncapsulationMode aidl);
+ConversionResult<media::AudioEncapsulationMode>
+legacy2aidl_AudioEncapsulationMode_audio_encapsulation_mode_t(audio_encapsulation_mode_t legacy);
+
+ConversionResult<audio_offload_info_t>
+aidl2legacy_AudioOffloadInfo_audio_offload_info_t(const media::AudioOffloadInfo& aidl);
+ConversionResult<media::AudioOffloadInfo>
+legacy2aidl_audio_offload_info_t_AudioOffloadInfo(const audio_offload_info_t& legacy);
+
+ConversionResult<audio_config_t>
+aidl2legacy_AudioConfig_audio_config_t(const media::AudioConfig& aidl);
+ConversionResult<media::AudioConfig>
+legacy2aidl_audio_config_t_AudioConfig(const audio_config_t& legacy);
+
+ConversionResult<audio_config_base_t>
+aidl2legacy_AudioConfigBase_audio_config_base_t(const media::AudioConfigBase& aidl);
+ConversionResult<media::AudioConfigBase>
+legacy2aidl_audio_config_base_t_AudioConfigBase(const audio_config_base_t& legacy);
+
+ConversionResult<sp<IMemory>>
+aidl2legacy_SharedFileRegion_IMemory(const media::SharedFileRegion& aidl);
+ConversionResult<media::SharedFileRegion>
+legacy2aidl_IMemory_SharedFileRegion(const sp<IMemory>& legacy);
+
+ConversionResult<sp<IMemory>>
+aidl2legacy_NullableSharedFileRegion_IMemory(const std::optional<media::SharedFileRegion>& aidl);
+ConversionResult<std::optional<media::SharedFileRegion>>
+legacy2aidl_NullableIMemory_SharedFileRegion(const sp<IMemory>& legacy);
+
 }  // namespace android
diff --git a/media/libaudioclient/include/media/AudioClient.h b/media/libaudioclient/include/media/AudioClient.h
index 247af9e..0b89d15 100644
--- a/media/libaudioclient/include/media/AudioClient.h
+++ b/media/libaudioclient/include/media/AudioClient.h
@@ -18,14 +18,12 @@
 #ifndef ANDROID_AUDIO_CLIENT_H
 #define ANDROID_AUDIO_CLIENT_H
 
-#include <binder/Parcel.h>
-#include <binder/Parcelable.h>
-#include <system/audio.h>
+#include <sys/types.h>
 #include <utils/String16.h>
 
 namespace android {
 
-class AudioClient : public Parcelable {
+class AudioClient {
  public:
     AudioClient() :
         clientUid(-1), clientPid(-1), clientTid(-1), packageName("") {}
@@ -34,22 +32,6 @@
     pid_t clientPid;
     pid_t clientTid;
     String16 packageName;
-
-    status_t readFromParcel(const Parcel *parcel) override {
-        clientUid = parcel->readInt32();
-        clientPid = parcel->readInt32();
-        clientTid = parcel->readInt32();
-        packageName = parcel->readString16();
-        return NO_ERROR;
-    }
-
-    status_t writeToParcel(Parcel *parcel) const override {
-        parcel->writeInt32(clientUid);
-        parcel->writeInt32(clientPid);
-        parcel->writeInt32(clientTid);
-        parcel->writeString16(packageName);
-        return NO_ERROR;
-    }
 };
 
 }; // namespace android
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 413db71..3491fda 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -26,6 +26,7 @@
 #include <binder/IInterface.h>
 #include <binder/Parcel.h>
 #include <binder/Parcelable.h>
+#include <media/AidlConversion.h>
 #include <media/AudioClient.h>
 #include <media/DeviceDescriptorBase.h>
 #include <media/IAudioTrack.h>
@@ -37,6 +38,10 @@
 #include <string>
 #include <vector>
 
+#include "android/media/CreateRecordRequest.h"
+#include "android/media/CreateRecordResponse.h"
+#include "android/media/CreateTrackRequest.h"
+#include "android/media/CreateTrackResponse.h"
 #include "android/media/IAudioRecord.h"
 #include "android/media/IAudioFlingerClient.h"
 #include "android/media/IAudioTrackCallback.h"
@@ -56,76 +61,8 @@
      * when calling createTrack() including arguments that will be updated by AudioFlinger
      * and returned in CreateTrackOutput object
      */
-    class CreateTrackInput : public Parcelable {
+    class CreateTrackInput {
     public:
-        status_t readFromParcel(const Parcel *parcel) override {
-            /* input arguments*/
-            memset(&attr, 0, sizeof(audio_attributes_t));
-            if (parcel->read(&attr, sizeof(audio_attributes_t)) != NO_ERROR) {
-                return DEAD_OBJECT;
-            }
-            attr.tags[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE -1] = '\0';
-            memset(&config, 0, sizeof(audio_config_t));
-            if (parcel->read(&config, sizeof(audio_config_t)) != NO_ERROR) {
-                return DEAD_OBJECT;
-            }
-            if (clientInfo.readFromParcel(parcel) != NO_ERROR) {
-                return DEAD_OBJECT;
-            }
-            if (parcel->readInt32() != 0) {
-                // TODO: Using unsecurePointer() has some associated security
-                //       pitfalls (see declaration for details).
-                //       Either document why it is safe in this case or address
-                //       the issue (e.g. by copying).
-                sharedBuffer = interface_cast<IMemory>(parcel->readStrongBinder());
-                if (sharedBuffer == 0 || sharedBuffer->unsecurePointer() == NULL) {
-                    return BAD_VALUE;
-                }
-            }
-            notificationsPerBuffer = parcel->readInt32();
-            speed = parcel->readFloat();
-            audioTrackCallback = interface_cast<media::IAudioTrackCallback>(
-                    parcel->readStrongBinder());
-            const char* opPackageNamePtr = parcel->readCString();
-            if (opPackageNamePtr == nullptr) {
-                return FAILED_TRANSACTION;
-            }
-            opPackageName = opPackageNamePtr;
-
-            /* input/output arguments*/
-            (void)parcel->read(&flags, sizeof(audio_output_flags_t));
-            frameCount = parcel->readInt64();
-            notificationFrameCount = parcel->readInt64();
-            (void)parcel->read(&selectedDeviceId, sizeof(audio_port_handle_t));
-            (void)parcel->read(&sessionId, sizeof(audio_session_t));
-            return NO_ERROR;
-        }
-
-        status_t writeToParcel(Parcel *parcel) const override {
-            /* input arguments*/
-            (void)parcel->write(&attr, sizeof(audio_attributes_t));
-            (void)parcel->write(&config, sizeof(audio_config_t));
-            (void)clientInfo.writeToParcel(parcel);
-            if (sharedBuffer != 0) {
-                (void)parcel->writeInt32(1);
-                (void)parcel->writeStrongBinder(IInterface::asBinder(sharedBuffer));
-            } else {
-                (void)parcel->writeInt32(0);
-            }
-            (void)parcel->writeInt32(notificationsPerBuffer);
-            (void)parcel->writeFloat(speed);
-            (void)parcel->writeStrongBinder(IInterface::asBinder(audioTrackCallback));
-            (void)parcel->writeCString(opPackageName.c_str());
-
-            /* input/output arguments*/
-            (void)parcel->write(&flags, sizeof(audio_output_flags_t));
-            (void)parcel->writeInt64(frameCount);
-            (void)parcel->writeInt64(notificationFrameCount);
-            (void)parcel->write(&selectedDeviceId, sizeof(audio_port_handle_t));
-            (void)parcel->write(&sessionId, sizeof(audio_session_t));
-            return NO_ERROR;
-        }
-
         /* input */
         audio_attributes_t attr;
         audio_config_t config;
@@ -142,50 +79,17 @@
         size_t notificationFrameCount;
         audio_port_handle_t selectedDeviceId;
         audio_session_t sessionId;
+
+        ConversionResult<media::CreateTrackRequest> toAidl() const;
+        static ConversionResult<CreateTrackInput> fromAidl(const media::CreateTrackRequest& aidl);
     };
 
     /* CreateTrackOutput contains all output arguments returned by AudioFlinger to AudioTrack
      * when calling createTrack() including arguments that were passed as I/O for update by
      * CreateTrackInput.
      */
-    class CreateTrackOutput : public Parcelable {
+    class CreateTrackOutput {
     public:
-        status_t readFromParcel(const Parcel *parcel) override {
-            /* input/output arguments*/
-            (void)parcel->read(&flags, sizeof(audio_output_flags_t));
-            frameCount = parcel->readInt64();
-            notificationFrameCount = parcel->readInt64();
-            (void)parcel->read(&selectedDeviceId, sizeof(audio_port_handle_t));
-            (void)parcel->read(&sessionId, sizeof(audio_session_t));
-
-            /* output arguments*/
-            sampleRate = parcel->readUint32();
-            afFrameCount = parcel->readInt64();
-            afSampleRate = parcel->readInt64();
-            afLatencyMs = parcel->readInt32();
-            (void)parcel->read(&outputId, sizeof(audio_io_handle_t));
-            (void)parcel->read(&portId, sizeof(audio_port_handle_t));
-            return NO_ERROR;
-        }
-
-        status_t writeToParcel(Parcel *parcel) const override {
-            /* input/output arguments*/
-            (void)parcel->write(&flags, sizeof(audio_output_flags_t));
-            (void)parcel->writeInt64(frameCount);
-            (void)parcel->writeInt64(notificationFrameCount);
-            (void)parcel->write(&selectedDeviceId, sizeof(audio_port_handle_t));
-            (void)parcel->write(&sessionId, sizeof(audio_session_t));
-
-            /* output arguments*/
-            (void)parcel->writeUint32(sampleRate);
-            (void)parcel->writeInt64(afFrameCount);
-            (void)parcel->writeInt64(afSampleRate);
-            (void)parcel->writeInt32(afLatencyMs);
-            (void)parcel->write(&outputId, sizeof(audio_io_handle_t));
-            (void)parcel->write(&portId, sizeof(audio_port_handle_t));
-            return NO_ERROR;
-        }
-
         /* input/output */
         audio_output_flags_t flags;
         size_t frameCount;
@@ -200,59 +104,17 @@
         uint32_t afLatencyMs;
         audio_io_handle_t outputId;
         audio_port_handle_t portId;
+
+        ConversionResult<media::CreateTrackResponse> toAidl() const;
+        static ConversionResult<CreateTrackOutput> fromAidl(const media::CreateTrackResponse& aidl);
     };
 
     /* CreateRecordInput contains all input arguments sent by AudioRecord to AudioFlinger
      * when calling createRecord() including arguments that will be updated by AudioFlinger
      * and returned in CreateRecordOutput object
      */
-    class CreateRecordInput : public Parcelable {
+    class CreateRecordInput {
     public:
-        status_t readFromParcel(const Parcel *parcel) override {
-            /* input arguments*/
-            memset(&attr, 0, sizeof(audio_attributes_t));
-            if (parcel->read(&attr, sizeof(audio_attributes_t)) != NO_ERROR) {
-                return DEAD_OBJECT;
-            }
-            attr.tags[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE -1] = '\0';
-            memset(&config, 0, sizeof(audio_config_base_t));
-            if (parcel->read(&config, sizeof(audio_config_base_t)) != NO_ERROR) {
-                return DEAD_OBJECT;
-            }
-            if (clientInfo.readFromParcel(parcel) != NO_ERROR) {
-                return DEAD_OBJECT;
-            }
-            opPackageName = parcel->readString16();
-            if (parcel->read(&riid, sizeof(audio_unique_id_t)) != NO_ERROR) {
-                return DEAD_OBJECT;
-            }
-
-            /* input/output arguments*/
-            (void)parcel->read(&flags, sizeof(audio_input_flags_t));
-            frameCount = parcel->readInt64();
-            notificationFrameCount = parcel->readInt64();
-            (void)parcel->read(&selectedDeviceId, sizeof(audio_port_handle_t));
-            (void)parcel->read(&sessionId, sizeof(audio_session_t));
-            return NO_ERROR;
-        }
-
-        status_t writeToParcel(Parcel *parcel) const override {
-            /* input arguments*/
-            (void)parcel->write(&attr, sizeof(audio_attributes_t));
-            (void)parcel->write(&config, sizeof(audio_config_base_t));
-            (void)clientInfo.writeToParcel(parcel);
-            (void)parcel->writeString16(opPackageName);
-            (void)parcel->write(&riid, sizeof(audio_unique_id_t));
-
-            /* input/output arguments*/
-            (void)parcel->write(&flags, sizeof(audio_input_flags_t));
-            (void)parcel->writeInt64(frameCount);
-            (void)parcel->writeInt64(notificationFrameCount);
-            (void)parcel->write(&selectedDeviceId, sizeof(audio_port_handle_t));
-            (void)parcel->write(&sessionId, sizeof(audio_session_t));
-            return NO_ERROR;
-        }
-
         /* input */
         audio_attributes_t attr;
         audio_config_base_t config;
@@ -266,77 +128,17 @@
         size_t notificationFrameCount;
         audio_port_handle_t selectedDeviceId;
         audio_session_t sessionId;
+
+        ConversionResult<media::CreateRecordRequest> toAidl() const;
+        static ConversionResult<CreateRecordInput> fromAidl(const media::CreateRecordRequest& aidl);
     };
 
     /* CreateRecordOutput contains all output arguments returned by AudioFlinger to AudioRecord
      * when calling createRecord() including arguments that were passed as I/O for update by
      * CreateRecordInput.
      */
-    class CreateRecordOutput : public Parcelable {
+    class CreateRecordOutput {
     public:
-        status_t readFromParcel(const Parcel *parcel) override {
-            /* input/output arguments*/
-            (void)parcel->read(&flags, sizeof(audio_input_flags_t));
-            frameCount = parcel->readInt64();
-            notificationFrameCount = parcel->readInt64();
-            (void)parcel->read(&selectedDeviceId, sizeof(audio_port_handle_t));
-            (void)parcel->read(&sessionId, sizeof(audio_session_t));
-
-            /* output arguments*/
-            sampleRate = parcel->readUint32();
-            (void)parcel->read(&inputId, sizeof(audio_io_handle_t));
-            if (parcel->readInt32() != 0) {
-                cblk = interface_cast<IMemory>(parcel->readStrongBinder());
-                // TODO: Using unsecurePointer() has some associated security
-                //       pitfalls (see declaration for details).
-                //       Either document why it is safe in this case or address
-                //       the issue (e.g. by copying).
-                if (cblk == 0 || cblk->unsecurePointer() == NULL) {
-                    return BAD_VALUE;
-                }
-            }
-            if (parcel->readInt32() != 0) {
-                buffers = interface_cast<IMemory>(parcel->readStrongBinder());
-                // TODO: Using unsecurePointer() has some associated security
-                //       pitfalls (see declaration for details).
-                //       Either document why it is safe in this case or address
-                //       the issue (e.g. by copying).
-                if (buffers == 0 || buffers->unsecurePointer() == NULL) {
-                    return BAD_VALUE;
-                }
-            }
-            (void)parcel->read(&portId, sizeof(audio_port_handle_t));
-            return NO_ERROR;
-        }
-
-        status_t writeToParcel(Parcel *parcel) const override {
-            /* input/output arguments*/
-            (void)parcel->write(&flags, sizeof(audio_input_flags_t));
-            (void)parcel->writeInt64(frameCount);
-            (void)parcel->writeInt64(notificationFrameCount);
-            (void)parcel->write(&selectedDeviceId, sizeof(audio_port_handle_t));
-            (void)parcel->write(&sessionId, sizeof(audio_session_t));
-
-            /* output arguments*/
-            (void)parcel->writeUint32(sampleRate);
-            (void)parcel->write(&inputId, sizeof(audio_io_handle_t));
-            if (cblk != 0) {
-                (void)parcel->writeInt32(1);
-                (void)parcel->writeStrongBinder(IInterface::asBinder(cblk));
-            } else {
-                (void)parcel->writeInt32(0);
-            }
-            if (buffers != 0) {
-                (void)parcel->writeInt32(1);
-                (void)parcel->writeStrongBinder(IInterface::asBinder(buffers));
-            } else {
-                (void)parcel->writeInt32(0);
-            }
-            (void)parcel->write(&portId, sizeof(audio_port_handle_t));
-
-            return NO_ERROR;
-        }
-
         /* input/output */
         audio_input_flags_t flags;
         size_t frameCount;
@@ -350,6 +152,9 @@
         sp<IMemory> cblk;
         sp<IMemory> buffers;
         audio_port_handle_t portId;
+
+        ConversionResult<media::CreateRecordResponse> toAidl() const;
+        static ConversionResult<CreateRecordOutput> fromAidl(const media::CreateRecordResponse& aidl);
     };
 
     // invariant on exit for all APIs that return an sp<>:
@@ -358,13 +163,13 @@
     /* create an audio track and registers it with AudioFlinger.
      * return null if the track cannot be created.
      */
-    virtual sp<IAudioTrack> createTrack(const CreateTrackInput& input,
-                                        CreateTrackOutput& output,
-                                        status_t *status) = 0;
+    virtual sp<IAudioTrack> createTrack(const media::CreateTrackRequest& input,
+                                        media::CreateTrackResponse& output,
+                                        status_t* status) = 0;
 
-    virtual sp<media::IAudioRecord> createRecord(const CreateRecordInput& input,
-                                        CreateRecordOutput& output,
-                                        status_t *status) = 0;
+    virtual sp<media::IAudioRecord> createRecord(const media::CreateRecordRequest& input,
+                                                 media::CreateRecordResponse& output,
+                                                 status_t* status) = 0;
 
     // FIXME Surprisingly, format/latency don't work for input handles
 
diff --git a/media/libaudioclient/include/media/PlayerBase.h b/media/libaudioclient/include/media/PlayerBase.h
index e7a8abc..4aad9b4 100644
--- a/media/libaudioclient/include/media/PlayerBase.h
+++ b/media/libaudioclient/include/media/PlayerBase.h
@@ -19,6 +19,7 @@
 
 #include <audiomanager/AudioManager.h>
 #include <audiomanager/IAudioManager.h>
+#include <utils/Mutex.h>
 
 #include "android/media/BnPlayer.h"
 
@@ -40,8 +41,8 @@
     virtual binder::Status setPan(float pan) override;
     virtual binder::Status setStartDelayMs(int32_t delayMs) override;
     virtual binder::Status applyVolumeShaper(
-            const media::VolumeShaper::Configuration& configuration,
-            const media::VolumeShaper::Operation& operation) override;
+            const media::VolumeShaperConfiguration& configuration,
+            const media::VolumeShaperOperation& operation) override;
 
             status_t startWithStatus();
             status_t pauseWithStatus();
diff --git a/media/libaudioclient/include/media/TrackPlayerBase.h b/media/libaudioclient/include/media/TrackPlayerBase.h
index 66e9b3b..6d26e63 100644
--- a/media/libaudioclient/include/media/TrackPlayerBase.h
+++ b/media/libaudioclient/include/media/TrackPlayerBase.h
@@ -33,8 +33,8 @@
 
     //IPlayer implementation
     virtual binder::Status applyVolumeShaper(
-            const media::VolumeShaper::Configuration& configuration,
-            const media::VolumeShaper::Operation& operation);
+            const media::VolumeShaperConfiguration& configuration,
+            const media::VolumeShaperOperation& operation);
 
     //FIXME move to protected field, so far made public to minimize changes to AudioTrack logic
     sp<AudioTrack> mAudioTrack;
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 39523de..1a7eb6f 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -322,6 +322,8 @@
 
     shared_libs: [
         "android.hidl.token@1.0-utils",
+        "audioclient-types-aidl-unstable-cpp",
+        "av-types-aidl-unstable-cpp",
         "liblog",
         "libcutils",
         "libprocessgroup",
diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp
index 324f4ae..b62317a 100644
--- a/media/libmediaplayerservice/Android.bp
+++ b/media/libmediaplayerservice/Android.bp
@@ -15,6 +15,7 @@
     shared_libs: [
         "android.hardware.media.c2@1.0",
         "android.hardware.media.omx@1.0",
+        "av-types-aidl-unstable-cpp",
         "libbase",
         "libandroid_net",
         "libaudioclient",
diff --git a/media/libshmem/Android.bp b/media/libshmem/Android.bp
index c8d2284..b549b5d 100644
--- a/media/libshmem/Android.bp
+++ b/media/libshmem/Android.bp
@@ -1,6 +1,9 @@
 aidl_interface {
     name: "shared-file-region-aidl",
     unstable: true,
+    host_supported: true,
+    vendor_available: true,
+    double_loadable: true,
     local_include_dir: "aidl",
     srcs: [
         "aidl/android/media/SharedFileRegion.aidl",
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index 261af5a..7443320 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -37,6 +37,7 @@
     shared_libs: [
         "audioflinger-aidl-unstable-cpp",
         "audioclient-types-aidl-unstable-cpp",
+        "av-types-aidl-unstable-cpp",
         "libaudioclient_aidl_conversion",
         "libaudiofoundation",
         "libaudiohal",
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index e589eb9..4929346 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -22,12 +22,14 @@
 // Define AUDIO_ARRAYS_STATIC_CHECK to check all audio arrays are correct
 #define AUDIO_ARRAYS_STATIC_CHECK 1
 
-#define VALUE_OR_FATAL(result) \
-    ({ auto _tmp = (result); \
-       LOG_ALWAYS_FATAL_IF(!_tmp.ok(), \
+#define VALUE_OR_FATAL(result)                   \
+    ({                                           \
+       auto _tmp = (result);                     \
+       LOG_ALWAYS_FATAL_IF(!_tmp.ok(),           \
                            "Failed result (%d)", \
-                           _tmp.error()); \
-       _tmp.value(); })
+                           _tmp.error());        \
+       std::move(_tmp.value());                  \
+     })
 
 #include "Configuration.h"
 #include <dirent.h>
@@ -755,10 +757,27 @@
 
 // IAudioFlinger interface
 
-sp<IAudioTrack> AudioFlinger::createTrack(const CreateTrackInput& input,
-                                          CreateTrackOutput& output,
-                                          status_t *status)
+sp<IAudioTrack> AudioFlinger::createTrack(const media::CreateTrackRequest& _input,
+                                          media::CreateTrackResponse& _output,
+                                          status_t* status)
 {
+    // Local version of VALUE_OR_RETURN, specific to this method's calling conventions.
+#define VALUE_OR_EXIT(expr)         \
+    ({                              \
+        auto _tmp = (expr);         \
+        if (!_tmp.ok()) {           \
+            *status = _tmp.error(); \
+            return nullptr;         \
+        }                           \
+        std::move(_tmp.value());    \
+    })
+
+    CreateTrackInput input = VALUE_OR_EXIT(CreateTrackInput::fromAidl(_input));
+
+#undef VALUE_OR_EXIT
+
+    CreateTrackOutput output;
+
     sp<PlaybackThread::Track> track;
     sp<TrackHandle> trackHandle;
     sp<Client> client;
@@ -1015,6 +1034,8 @@
         AudioSystem::moveEffectsToIo(effectIds, effectThreadId);
     }
 
+    _output = VALUE_OR_FATAL(output.toAidl());
+
     // return handle to client
     trackHandle = new TrackHandle(track);
 
@@ -1997,10 +2018,26 @@
 
 // ----------------------------------------------------------------------------
 
-sp<media::IAudioRecord> AudioFlinger::createRecord(const CreateRecordInput& input,
-                                                   CreateRecordOutput& output,
-                                                   status_t *status)
+sp<media::IAudioRecord> AudioFlinger::createRecord(const media::CreateRecordRequest& _input,
+                                                   media::CreateRecordResponse& _output,
+                                                   status_t* status)
 {
+    // Local version of VALUE_OR_RETURN, specific to this method's calling conventions.
+#define VALUE_OR_EXIT(expr)         \
+    ({                              \
+        auto _tmp = (expr);         \
+        if (!_tmp.ok()) {           \
+            *status = _tmp.error(); \
+            return nullptr;         \
+        }                           \
+        std::move(_tmp.value());    \
+    })
+
+    CreateRecordInput input = VALUE_OR_EXIT(CreateRecordInput::fromAidl(_input));
+
+#undef VALUE_OR_EXIT
+    CreateRecordOutput output;
+
     sp<RecordThread::RecordTrack> recordTrack;
     sp<RecordHandle> recordHandle;
     sp<Client> client;
@@ -2138,6 +2175,8 @@
     output.buffers = recordTrack->getBuffers();
     output.portId = portId;
 
+    _output = VALUE_OR_FATAL(output.toAidl());
+
     // return handle to client
     recordHandle = new RecordHandle(recordTrack);
 
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 65d672a..2ff6af5 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -135,13 +135,13 @@
     virtual     status_t    dump(int fd, const Vector<String16>& args);
 
     // IAudioFlinger interface, in binder opcode order
-    virtual sp<IAudioTrack> createTrack(const CreateTrackInput& input,
-                                        CreateTrackOutput& output,
-                                        status_t *status);
+    virtual sp<IAudioTrack> createTrack(const media::CreateTrackRequest& input,
+                                        media::CreateTrackResponse& output,
+                                        status_t* status) override;
 
-    virtual sp<media::IAudioRecord> createRecord(const CreateRecordInput& input,
-                                                 CreateRecordOutput& output,
-                                                 status_t *status);
+    virtual sp<media::IAudioRecord> createRecord(const media::CreateRecordRequest& input,
+                                                 media::CreateRecordResponse& output,
+                                                 status_t* status) override;
 
     virtual     uint32_t    sampleRate(audio_io_handle_t ioHandle) const;
     virtual     audio_format_t format(audio_io_handle_t output) const;