Merge "audioflinger: Add session effects on spatializer mixer"
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index e1fe257..a70cc4b 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -1090,6 +1090,15 @@
      * (ACAMERA_LENS_OPTICAL_STABILIZATION_MODE), turning both modes on may
      * produce undesirable interaction, so it is recommended not to enable
      * both at the same time.</p>
+     * <p>If video stabilization is set to "PREVIEW_STABILIZATION",
+     * ACAMERA_LENS_OPTICAL_STABILIZATION_MODE is overridden. The camera sub-system may choose
+     * to turn on hardware based image stabilization in addition to software based stabilization
+     * if it deems that appropriate.
+     * This key may be a part of the available session keys, which camera clients may
+     * query via
+     * {@link ACameraManager_getCameraCharacteristics }.
+     * If this is the case, changing this key over the life-time of a capture session may
+     * cause delays / glitches.</p>
      *
      * @see ACAMERA_CONTROL_VIDEO_STABILIZATION_MODE
      * @see ACAMERA_LENS_OPTICAL_STABILIZATION_MODE
@@ -2571,12 +2580,18 @@
      * <p>If a camera device supports both OIS and digital image stabilization
      * (ACAMERA_CONTROL_VIDEO_STABILIZATION_MODE), turning both modes on may produce undesirable
      * interaction, so it is recommended not to enable both at the same time.</p>
+     * <p>If ACAMERA_CONTROL_VIDEO_STABILIZATION_MODE is set to "PREVIEW_STABILIZATION",
+     * ACAMERA_LENS_OPTICAL_STABILIZATION_MODE is overridden. The camera sub-system may choose
+     * to turn on hardware based image stabilization in addition to software based stabilization
+     * if it deems that appropriate. This key's value in the capture result will reflect which
+     * OIS mode was chosen.</p>
      * <p>Not all devices will support OIS; see
      * ACAMERA_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION for
      * available controls.</p>
      *
      * @see ACAMERA_CONTROL_VIDEO_STABILIZATION_MODE
      * @see ACAMERA_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION
+     * @see ACAMERA_LENS_OPTICAL_STABILIZATION_MODE
      */
     ACAMERA_LENS_OPTICAL_STABILIZATION_MODE =                   // byte (acamera_metadata_enum_android_lens_optical_stabilization_mode_t)
             ACAMERA_LENS_START + 4,
@@ -8014,6 +8029,17 @@
      */
     ACAMERA_CONTROL_VIDEO_STABILIZATION_MODE_ON                      = 1,
 
+    /**
+     * <p>Preview stabilization, where the preview in addition to all other non-RAW streams are
+     * stabilized with the same quality of stabilization, is enabled. This mode aims to give
+     * clients a 'what you see is what you get' effect. In this mode, the FoV reduction will
+     * be a maximum of 20 % both horizontally and vertically
+     * (10% from left, right, top, bottom) for the given zoom ratio / crop region.
+     * The resultant FoV will also be the same across all processed streams
+     * (that have the same aspect ratio).</p>
+     */
+    ACAMERA_CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION   = 2,
+
 } acamera_metadata_enum_android_control_video_stabilization_mode_t;
 
 // ACAMERA_CONTROL_AE_STATE
diff --git a/drm/drmserver/drmserver.rc b/drm/drmserver/drmserver.rc
index eb176c1..0319ff9 100644
--- a/drm/drmserver/drmserver.rc
+++ b/drm/drmserver/drmserver.rc
@@ -3,7 +3,7 @@
     class main
     user drm
     group drm system inet drmrpc readproc
-    writepid /dev/cpuset/foreground/tasks
+    task_profiles ProcessCapacityHigh
 
 on property:drm.service.enabled=true
     start drm
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service-lazy.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service-lazy.clearkey.rc
index 9afd3d7..ec4517d 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service-lazy.clearkey.rc
+++ b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service-lazy.clearkey.rc
@@ -11,4 +11,4 @@
     user media
     group media mediadrm
     ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks
+    task_profiles ProcessCapacityHigh
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service.clearkey.rc
index c1abe7f..3b48cf2 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service.clearkey.rc
+++ b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service.clearkey.rc
@@ -10,4 +10,4 @@
     user media
     group media mediadrm
     ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks
+    task_profiles ProcessCapacityHigh
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service-lazy.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service-lazy.clearkey.rc
index 1e0d431..6e64978 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service-lazy.clearkey.rc
+++ b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service-lazy.clearkey.rc
@@ -13,4 +13,4 @@
     user media
     group media mediadrm
     ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks
+    task_profiles ProcessCapacityHigh
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service.clearkey.rc
index 8130511..e302e1b 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service.clearkey.rc
+++ b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service.clearkey.rc
@@ -11,4 +11,4 @@
     user media
     group media mediadrm
     ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks
+    task_profiles ProcessCapacityHigh
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service-lazy.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service-lazy.clearkey.rc
index 46aba88..84a63a1 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service-lazy.clearkey.rc
+++ b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service-lazy.clearkey.rc
@@ -15,4 +15,4 @@
     user media
     group media mediadrm
     ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks
+    task_profiles ProcessCapacityHigh
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service.clearkey.rc
index 8186933..649599e 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service.clearkey.rc
+++ b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service.clearkey.rc
@@ -13,4 +13,4 @@
     user media
     group media mediadrm
     ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks
+    task_profiles ProcessCapacityHigh
diff --git a/media/libaaudio/fuzzer/Android.bp b/media/libaaudio/fuzzer/Android.bp
index b19376d..e2eec7a 100644
--- a/media/libaaudio/fuzzer/Android.bp
+++ b/media/libaaudio/fuzzer/Android.bp
@@ -14,6 +14,15 @@
  * limitations under the License.
  */
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_av_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_av_license"],
+}
+
 cc_fuzz {
     name: "libaaudio_fuzzer",
     srcs: [
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index 343bcef..8314320 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -1589,44 +1589,29 @@
 }
 
 ConversionResult<audio_io_flags> aidl2legacy_AudioIoFlags_audio_io_flags(
-        const AudioIoFlags& aidl, media::AudioPortRole role, media::AudioPortType type) {
+        const AudioIoFlags& aidl, bool isInput) {
     audio_io_flags legacy;
-    Direction dir = VALUE_OR_RETURN(direction(role, type));
-    switch (dir) {
-        case Direction::INPUT: {
-            legacy.input = VALUE_OR_RETURN(
-                    aidl2legacy_int32_t_audio_input_flags_t_mask(
-                            VALUE_OR_RETURN(UNION_GET(aidl, input))));
-        }
-            break;
-
-        case Direction::OUTPUT: {
-            legacy.output = VALUE_OR_RETURN(
-                    aidl2legacy_int32_t_audio_output_flags_t_mask(
-                            VALUE_OR_RETURN(UNION_GET(aidl, output))));
-        }
-            break;
+    if (isInput) {
+        legacy.input = VALUE_OR_RETURN(
+                aidl2legacy_int32_t_audio_input_flags_t_mask(
+                        VALUE_OR_RETURN(UNION_GET(aidl, input))));
+    } else {
+        legacy.output = VALUE_OR_RETURN(
+                aidl2legacy_int32_t_audio_output_flags_t_mask(
+                        VALUE_OR_RETURN(UNION_GET(aidl, output))));
     }
-
     return legacy;
 }
 
 ConversionResult<AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
-        const audio_io_flags& legacy, audio_port_role_t role, audio_port_type_t type) {
+        const audio_io_flags& legacy, bool isInput) {
     AudioIoFlags aidl;
-
-    Direction dir = VALUE_OR_RETURN(direction(role, type));
-    switch (dir) {
-        case Direction::INPUT:
-            UNION_SET(aidl, input,
-                      VALUE_OR_RETURN(legacy2aidl_audio_input_flags_t_int32_t_mask(
-                              legacy.input)));
-            break;
-        case Direction::OUTPUT:
-            UNION_SET(aidl, output,
-                      VALUE_OR_RETURN(legacy2aidl_audio_output_flags_t_int32_t_mask(
-                              legacy.output)));
-            break;
+    if (isInput) {
+        UNION_SET(aidl, input,
+                VALUE_OR_RETURN(legacy2aidl_audio_input_flags_t_int32_t_mask(legacy.input)));
+    } else {
+        UNION_SET(aidl, output,
+                VALUE_OR_RETURN(legacy2aidl_audio_output_flags_t_int32_t_mask(legacy.output)));
     }
     return aidl;
 }
@@ -2000,8 +1985,7 @@
     }
     if (aidl.hal.flags.has_value()) {
         legacy.flags = VALUE_OR_RETURN(
-                aidl2legacy_AudioIoFlags_audio_io_flags(
-                        aidl.hal.flags.value(), aidl.sys.role, aidl.sys.type));
+                aidl2legacy_AudioIoFlags_audio_io_flags(aidl.hal.flags.value(), isInput));
         legacy.config_mask |= AUDIO_PORT_CONFIG_FLAGS;
     }
     legacy.ext = VALUE_OR_RETURN(
@@ -2037,7 +2021,7 @@
     }
     if (legacy.config_mask & AUDIO_PORT_CONFIG_FLAGS) {
         aidl.hal.flags = VALUE_OR_RETURN(
-                legacy2aidl_audio_io_flags_AudioIoFlags(legacy.flags, legacy.role, legacy.type));
+                legacy2aidl_audio_io_flags_AudioIoFlags(legacy.flags, isInput));
     }
     RETURN_IF_ERROR(legacy2aidl_AudioPortExt(legacy.ext, legacy.type, legacy.role,
                     &aidl.hal.ext, &aidl.sys.ext));
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index fda9efb..a6c93cf 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -194,10 +194,9 @@
         audio_output_flags_t legacy);
 
 ConversionResult<audio_io_flags> aidl2legacy_AudioIoFlags_audio_io_flags(
-        const media::audio::common::AudioIoFlags& aidl,
-        media::AudioPortRole role, media::AudioPortType type);
+        const media::audio::common::AudioIoFlags& aidl, bool isInput);
 ConversionResult<media::audio::common::AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
-        const audio_io_flags& legacy, audio_port_role_t role, audio_port_type_t type);
+        const audio_io_flags& legacy, bool isInput);
 
 ConversionResult<audio_port_config_device_ext>
 aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(
diff --git a/media/libaudiofoundation/AudioPort.cpp b/media/libaudiofoundation/AudioPort.cpp
index a00e00d..634b2e1 100644
--- a/media/libaudiofoundation/AudioPort.cpp
+++ b/media/libaudiofoundation/AudioPort.cpp
@@ -24,6 +24,22 @@
 
 namespace android {
 
+void AudioPort::setFlags(uint32_t flags)
+{
+    // force direct flag if offload flag is set: offloading implies a direct output stream
+    // and all common behaviors are driven by checking only the direct flag
+    // this should normally be set appropriately in the policy configuration file
+    if (mRole == AUDIO_PORT_ROLE_SOURCE &&
+            (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
+        flags |= AUDIO_OUTPUT_FLAG_DIRECT;
+    }
+    if (useInputChannelMask()) {
+        mFlags.input = static_cast<audio_input_flags_t>(flags);
+    } else {
+        mFlags.output = static_cast<audio_output_flags_t>(flags);
+    }
+}
+
 void AudioPort::importAudioPort(const sp<AudioPort>& port, bool force __unused)
 {
     for (const auto& profileToImport : port->mProfiles) {
@@ -195,16 +211,10 @@
            mType == other->getType() &&
            mRole == other->getRole() &&
            mProfiles.equals(other->getAudioProfiles()) &&
+           getFlags() == other->getFlags() &&
            mExtraAudioDescriptors == other->getExtraAudioDescriptors();
 }
 
-status_t AudioPort::writeToParcel(Parcel *parcel) const
-{
-    media::AudioPort parcelable;
-    return writeToParcelable(&parcelable)
-        ?: parcelable.writeToParcel(parcel);
-}
-
 status_t AudioPort::writeToParcelable(media::AudioPort* parcelable) const {
     parcelable->hal.name = mName;
     parcelable->sys.type = VALUE_OR_RETURN_STATUS(
@@ -215,6 +225,8 @@
             legacy2aidl_AudioProfileVector(mProfiles, useInputChannelMask()));
     parcelable->hal.profiles = aidlProfiles.first;
     parcelable->sys.profiles = aidlProfiles.second;
+    parcelable->hal.flags = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_io_flags_AudioIoFlags(mFlags, useInputChannelMask()));
     parcelable->hal.extraAudioDescriptors = mExtraAudioDescriptors;
     auto aidlGains = VALUE_OR_RETURN_STATUS(legacy2aidl_AudioGains(mGains));
     parcelable->hal.gains = aidlGains.first;
@@ -230,12 +242,6 @@
     return OK;
 }
 
-status_t AudioPort::readFromParcel(const Parcel *parcel) {
-    media::AudioPort parcelable;
-    return parcelable.readFromParcel(parcel)
-        ?: readFromParcelable(parcelable);
-}
-
 status_t AudioPort::readFromParcelable(const media::AudioPort& parcelable) {
     mName = parcelable.hal.name;
     mType = VALUE_OR_RETURN_STATUS(
@@ -246,6 +252,8 @@
             aidl2legacy_AudioProfileVector(
                     std::make_pair(parcelable.hal.profiles, parcelable.sys.profiles),
                     useInputChannelMask()));
+    mFlags = VALUE_OR_RETURN_STATUS(
+            aidl2legacy_AudioIoFlags_audio_io_flags(parcelable.hal.flags, useInputChannelMask()));
     mExtraAudioDescriptors = parcelable.hal.extraAudioDescriptors;
     mGains = VALUE_OR_RETURN_STATUS(
             aidl2legacy_AudioGains(std::make_pair(parcelable.hal.gains, parcelable.sys.gains)));
@@ -277,6 +285,9 @@
     if (config->config_mask & AUDIO_PORT_CONFIG_GAIN) {
         mGain = config->gain;
     }
+    if (config->config_mask & AUDIO_PORT_CONFIG_FLAGS) {
+        mFlags = config->flags;
+    }
 
     return NO_ERROR;
 }
@@ -330,6 +341,9 @@
     } else {
         dstConfig->config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
     }
+
+    updateField(mFlags, &audio_port_config::flags,
+            dstConfig, srcConfig, AUDIO_PORT_CONFIG_FLAGS, { AUDIO_INPUT_FLAG_NONE });
 }
 
 bool AudioPortConfig::hasGainController(bool canUseForVolume) const
@@ -342,12 +356,14 @@
                            : audioport->getGains().size() > 0;
 }
 
-bool AudioPortConfig::equals(const sp<AudioPortConfig> &other) const
+bool AudioPortConfig::equals(const sp<AudioPortConfig> &other, bool isInput) const
 {
     return other != nullptr &&
            mSamplingRate == other->getSamplingRate() &&
            mFormat == other->getFormat() &&
            mChannelMask == other->getChannelMask() &&
+           (isInput ? mFlags.input == other->getFlags().input :
+                   mFlags.output == other->getFlags().output )&&
            // Compare audio gain config
            mGain.index == other->mGain.index &&
            mGain.mode == other->mGain.mode &&
@@ -370,6 +386,8 @@
     media::audio::common::AudioGainConfig aidl_gain = VALUE_OR_RETURN_STATUS(
             legacy2aidl_audio_gain_config_AudioGainConfig(mGain, isInput));
     parcelable->gain = aidl_gain;
+    parcelable->flags = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_io_flags_AudioIoFlags(mFlags, isInput));
     return OK;
 }
 
@@ -393,6 +411,10 @@
         mGain = VALUE_OR_RETURN_STATUS(
                 aidl2legacy_AudioGainConfig_audio_gain_config(parcelable.gain.value(), isInput));
     }
+    if (parcelable.flags.has_value()) {
+        mFlags = VALUE_OR_RETURN_STATUS(
+                aidl2legacy_AudioIoFlags_audio_io_flags(parcelable.flags.value(), isInput));
+    }
     return OK;
 }
 
diff --git a/media/libaudiofoundation/DeviceDescriptorBase.cpp b/media/libaudiofoundation/DeviceDescriptorBase.cpp
index b383db4..c8222e7 100644
--- a/media/libaudiofoundation/DeviceDescriptorBase.cpp
+++ b/media/libaudiofoundation/DeviceDescriptorBase.cpp
@@ -164,7 +164,7 @@
 {
     return other != nullptr &&
            static_cast<const AudioPort*>(this)->equals(other) &&
-           static_cast<const AudioPortConfig*>(this)->equals(other) &&
+           static_cast<const AudioPortConfig*>(this)->equals(other, useInputChannelMask()) &&
            mDeviceTypeAddr.equals(other->mDeviceTypeAddr) &&
            checkEqual(mEncodedFormats, other->mEncodedFormats);
 }
@@ -183,14 +183,6 @@
     return false;
 }
 
-
-status_t DeviceDescriptorBase::writeToParcel(Parcel *parcel) const
-{
-    media::AudioPort parcelable;
-    return writeToParcelable(&parcelable)
-        ?: parcelable.writeToParcel(parcel);
-}
-
 status_t DeviceDescriptorBase::writeToParcelable(media::AudioPort* parcelable) const {
     AudioPort::writeToParcelable(parcelable);
     AudioPortConfig::writeToParcelable(&parcelable->hal.activeConfig, useInputChannelMask());
@@ -212,12 +204,6 @@
     return OK;
 }
 
-status_t DeviceDescriptorBase::readFromParcel(const Parcel *parcel) {
-    media::AudioPort parcelable;
-    return parcelable.readFromParcel(parcel)
-        ?: readFromParcelable(parcelable);
-}
-
 status_t DeviceDescriptorBase::readFromParcelable(const media::AudioPort& parcelable) {
     if (parcelable.sys.type != media::AudioPortType::DEVICE) {
         return BAD_VALUE;
diff --git a/media/libaudiofoundation/include/media/AudioPort.h b/media/libaudiofoundation/include/media/AudioPort.h
index b5a17c9..985e05e 100644
--- a/media/libaudiofoundation/include/media/AudioPort.h
+++ b/media/libaudiofoundation/include/media/AudioPort.h
@@ -33,7 +33,7 @@
 
 namespace android {
 
-class AudioPort : public virtual RefBase, public virtual Parcelable
+class AudioPort : public virtual RefBase
 {
 public:
     AudioPort(const std::string& name, audio_port_type_t type,  audio_port_role_t role) :
@@ -47,6 +47,9 @@
     audio_port_type_t getType() const { return mType; }
     audio_port_role_t getRole() const { return mRole; }
 
+    virtual void setFlags(uint32_t flags);
+    uint32_t getFlags() const { return useInputChannelMask() ? mFlags.input : mFlags.output; }
+
     void setGains(const AudioGains &gains) { mGains = gains; }
     const AudioGains &getGains() const { return mGains; }
 
@@ -93,15 +96,27 @@
                 ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SINK));
     }
 
+    bool isDirectOutput() const
+    {
+        return (mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) &&
+                ((mFlags.output & AUDIO_OUTPUT_FLAG_DIRECT) != 0);
+    }
+
+    bool isMmap() const
+    {
+        return (mType == AUDIO_PORT_TYPE_MIX)
+                && (((mRole == AUDIO_PORT_ROLE_SOURCE) &&
+                        ((mFlags.output & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) != 0))
+                    || ((mRole == AUDIO_PORT_ROLE_SINK) &&
+                        ((mFlags.input & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)));
+    }
+
     void dump(std::string *dst, int spaces, bool verbose = true) const;
 
     void log(const char* indent) const;
 
     bool equals(const sp<AudioPort>& other) const;
 
-    status_t writeToParcel(Parcel* parcel) const override;
-    status_t readFromParcel(const Parcel* parcel) override;
-
     status_t writeToParcelable(media::AudioPort* parcelable) const;
     status_t readFromParcelable(const media::AudioPort& parcelable);
 
@@ -130,6 +145,7 @@
     // Audio capabilities that are defined by hardware descriptors when the format is unrecognized
     // by the platform, e.g. short audio descriptor in EDID for HDMI.
     std::vector<media::audio::common::ExtraAudioDescriptor> mExtraAudioDescriptors;
+    union audio_io_flags mFlags = { .output = AUDIO_OUTPUT_FLAG_NONE };
 private:
     template <typename T, std::enable_if_t<std::is_same<T, struct audio_port>::value
                                         || std::is_same<T, struct audio_port_v7>::value, int> = 0>
@@ -162,10 +178,11 @@
     audio_format_t getFormat() const { return mFormat; }
     audio_channel_mask_t getChannelMask() const { return mChannelMask; }
     audio_port_handle_t getId() const { return mId; }
+    audio_io_flags getFlags() const { return mFlags; }
 
     bool hasGainController(bool canUseForVolume = false) const;
 
-    bool equals(const sp<AudioPortConfig>& other) const;
+    bool equals(const sp<AudioPortConfig>& other, bool isInput) const;
 
     status_t writeToParcelable(
             media::audio::common::AudioPortConfig* parcelable, bool isInput) const;
@@ -178,6 +195,7 @@
     audio_channel_mask_t mChannelMask = AUDIO_CHANNEL_NONE;
     audio_port_handle_t mId = AUDIO_PORT_HANDLE_NONE;
     struct audio_gain_config mGain = { .index = -1 };
+    union audio_io_flags mFlags = { AUDIO_INPUT_FLAG_NONE };
 };
 
 } // namespace android
diff --git a/media/libaudiofoundation/include/media/DeviceDescriptorBase.h b/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
index a4092eb..b70da8a 100644
--- a/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
+++ b/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
@@ -79,9 +79,6 @@
 
     bool equals(const sp<DeviceDescriptorBase>& other) const;
 
-    status_t writeToParcel(Parcel* parcel) const override;
-    status_t readFromParcel(const Parcel* parcel) override;
-
     status_t writeToParcelable(media::AudioPort* parcelable) const;
     status_t readFromParcelable(const media::AudioPort& parcelable);
 
diff --git a/media/libaudiofoundation/tests/audiofoundation_parcelable_test.cpp b/media/libaudiofoundation/tests/audiofoundation_parcelable_test.cpp
index 0315a59..50d8dc8 100644
--- a/media/libaudiofoundation/tests/audiofoundation_parcelable_test.cpp
+++ b/media/libaudiofoundation/tests/audiofoundation_parcelable_test.cpp
@@ -112,38 +112,37 @@
 }
 
 TEST(AudioFoundationParcelableTest, ParcelingAudioPort) {
-    Parcel data;
     sp<AudioPort> audioPort = new AudioPort(
             "AudioPortName", AUDIO_PORT_TYPE_DEVICE, AUDIO_PORT_ROLE_SINK);
     audioPort->setGains(getAudioGainsForTest());
     audioPort->setAudioProfiles(getAudioProfileVectorForTest());
 
-    ASSERT_EQ(data.writeParcelable(*audioPort), NO_ERROR);
-    data.setDataPosition(0);
+    media::AudioPort parcelable;
+    ASSERT_EQ(NO_ERROR, audioPort->writeToParcelable(&parcelable));
     sp<AudioPort> audioPortFromParcel = new AudioPort(
             "", AUDIO_PORT_TYPE_NONE, AUDIO_PORT_ROLE_NONE);
-    ASSERT_EQ(data.readParcelable(audioPortFromParcel.get()), NO_ERROR);
+    ASSERT_EQ(NO_ERROR, audioPortFromParcel->readFromParcelable(parcelable));
     ASSERT_TRUE(audioPortFromParcel->equals(audioPort));
 }
 
 TEST(AudioFoundationParcelableTest, ParcelingAudioPortConfig) {
+    const bool isInput = false;
     Parcel data;
     sp<AudioPortConfig> audioPortConfig = new AudioPortConfigTestStub();
     audioPortConfig->applyAudioPortConfig(&TEST_AUDIO_PORT_CONFIG);
     media::audio::common::AudioPortConfig parcelable{};
-    ASSERT_EQ(NO_ERROR, audioPortConfig->writeToParcelable(&parcelable, false /*isInput*/));
+    ASSERT_EQ(NO_ERROR, audioPortConfig->writeToParcelable(&parcelable, isInput));
     ASSERT_EQ(NO_ERROR, data.writeParcelable(parcelable));
     data.setDataPosition(0);
     media::audio::common::AudioPortConfig parcelableFromParcel{};
     ASSERT_EQ(NO_ERROR, data.readParcelable(&parcelableFromParcel));
     sp<AudioPortConfig> audioPortConfigFromParcel = new AudioPortConfigTestStub();
     ASSERT_EQ(NO_ERROR, audioPortConfigFromParcel->readFromParcelable(
-                    parcelableFromParcel, false /*isInput*/));
-    ASSERT_TRUE(audioPortConfigFromParcel->equals(audioPortConfig));
+                    parcelableFromParcel, isInput));
+    ASSERT_TRUE(audioPortConfigFromParcel->equals(audioPortConfig, isInput));
 }
 
 TEST(AudioFoundationParcelableTest, ParcelingDeviceDescriptorBase) {
-    Parcel data;
     sp<DeviceDescriptorBase> desc = new DeviceDescriptorBase(AUDIO_DEVICE_OUT_SPEAKER);
     desc->setGains(getAudioGainsForTest());
     desc->setAudioProfiles(getAudioProfileVectorForTest());
@@ -153,10 +152,10 @@
     ASSERT_EQ(desc->setEncapsulationMetadataTypes(
             AUDIO_ENCAPSULATION_METADATA_TYPE_ALL_POSITION_BITS), NO_ERROR);
 
-    ASSERT_EQ(data.writeParcelable(*desc), NO_ERROR);
-    data.setDataPosition(0);
+    media::AudioPort parcelable;
+    ASSERT_EQ(NO_ERROR, desc->writeToParcelable(&parcelable));
     sp<DeviceDescriptorBase> descFromParcel = new DeviceDescriptorBase(AUDIO_DEVICE_NONE);
-    ASSERT_EQ(data.readParcelable(descFromParcel.get()), NO_ERROR);
+    ASSERT_EQ(NO_ERROR, descFromParcel->readFromParcelable(parcelable));
     ASSERT_TRUE(descFromParcel->equals(desc));
 }
 
diff --git a/media/libeffects/testlibs/Android.bp b/media/libeffects/testlibs/Android.bp
new file mode 100644
index 0000000..5ba56bb
--- /dev/null
+++ b/media/libeffects/testlibs/Android.bp
@@ -0,0 +1,77 @@
+// Test Reverb library
+package {
+    default_applicable_licenses: [
+        "frameworks_av_media_libeffects_testlibs_license",
+    ],
+}
+
+license {
+    name: "frameworks_av_media_libeffects_testlibs_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
+cc_library {
+    name: "libreverbtest",
+    host_supported: true,
+    vendor: true,
+    srcs: [
+        "EffectReverb.c",
+        "EffectsMath.c",
+    ],
+
+    shared_libs: [
+        "libcutils",
+        "liblog",
+    ],
+
+    relative_install_path: "soundfx",
+
+    cflags: [
+        "-fvisibility=hidden",
+        "-Wall",
+        "-Werror",
+        "-Wno-address-of-packed-member",
+    ],
+
+    header_libs: [
+        "libaudioeffects",
+    ],
+}
+
+cc_library {
+    name: "libequalizertest",
+    host_supported: true,
+    vendor: true,
+    srcs: [
+        "AudioBiquadFilter.cpp",
+        "AudioCoefInterpolator.cpp",
+        "AudioEqualizer.cpp",
+        "AudioPeakingFilter.cpp",
+        "AudioShelvingFilter.cpp",
+        "EffectEqualizer.cpp",
+        "EffectsMath.c",
+    ],
+
+    shared_libs: [
+        "libcutils",
+        "liblog",
+    ],
+
+    relative_install_path: "soundfx",
+
+    cflags: [
+        "-fvisibility=hidden",
+        "-Wall",
+        "-Werror",
+    ],
+
+    header_libs: [
+        "libaudioeffects",
+    ],
+}
diff --git a/media/libeffects/testlibs/Android.mk_ b/media/libeffects/testlibs/Android.mk_
deleted file mode 100644
index 14c373f..0000000
--- a/media/libeffects/testlibs/Android.mk_
+++ /dev/null
@@ -1,55 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-# Test Reverb library
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-	EffectReverb.c.arm \
-	EffectsMath.c.arm
-
-LOCAL_CFLAGS := -O2
-
-LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-	libdl
-
-LOCAL_MODULE_RELATIVE_PATH := soundfx
-LOCAL_MODULE := libreverbtest
-
-LOCAL_C_INCLUDES := \
-	$(call include-path-for, audio-effects) \
-	$(call include-path-for, graphics corecg)
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_SHARED_LIBRARY)
-
-# Test Equalizer library
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-	EffectsMath.c.arm \
-	EffectEqualizer.cpp \
-	AudioBiquadFilter.cpp.arm \
-	AudioCoefInterpolator.cpp.arm \
-	AudioPeakingFilter.cpp.arm \
-	AudioShelvingFilter.cpp.arm \
-	AudioEqualizer.cpp.arm
-
-LOCAL_CFLAGS := -O2
-
-LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-	libdl
-
-LOCAL_MODULE_RELATIVE_PATH := soundfx
-LOCAL_MODULE := libequalizertest
-
-LOCAL_C_INCLUDES := \
-	$(call include-path-for, graphics corecg) \
-	$(call include-path-for, audio-effects)
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_SHARED_LIBRARY)
-
diff --git a/media/libeffects/testlibs/AudioEqualizer.cpp b/media/libeffects/testlibs/AudioEqualizer.cpp
index 4f3a308..141750b 100644
--- a/media/libeffects/testlibs/AudioEqualizer.cpp
+++ b/media/libeffects/testlibs/AudioEqualizer.cpp
@@ -19,7 +19,7 @@
 #include <assert.h>
 #include <stdlib.h>
 #include <new>
-#include <utils/Log.h>
+#include <log/log.h>
 
 #include "AudioEqualizer.h"
 #include "AudioPeakingFilter.h"
diff --git a/media/libeffects/testlibs/AudioPeakingFilter.cpp b/media/libeffects/testlibs/AudioPeakingFilter.cpp
index 99323ac..4257eca 100644
--- a/media/libeffects/testlibs/AudioPeakingFilter.cpp
+++ b/media/libeffects/testlibs/AudioPeakingFilter.cpp
@@ -87,9 +87,9 @@
 void AudioPeakingFilter::commit(bool immediate) {
     audio_coef_t coefs[5];
     int intCoord[3] = {
-        mFrequency >> FREQ_PRECISION_BITS,
+        (int)(mFrequency >> FREQ_PRECISION_BITS),
         mGain >> GAIN_PRECISION_BITS,
-        mBandwidth >> BANDWIDTH_PRECISION_BITS
+        (int)(mBandwidth >> BANDWIDTH_PRECISION_BITS)
     };
     uint32_t fracCoord[3] = {
         mFrequency << (32 - FREQ_PRECISION_BITS),
diff --git a/media/libeffects/testlibs/AudioShelvingFilter.cpp b/media/libeffects/testlibs/AudioShelvingFilter.cpp
index e031287..ad43c5a 100644
--- a/media/libeffects/testlibs/AudioShelvingFilter.cpp
+++ b/media/libeffects/testlibs/AudioShelvingFilter.cpp
@@ -89,8 +89,8 @@
 void AudioShelvingFilter::commit(bool immediate) {
     audio_coef_t coefs[5];
     int intCoord[2] = {
-        mFrequency >> FREQ_PRECISION_BITS,
-        mGain >> GAIN_PRECISION_BITS
+        (int)(mFrequency >> FREQ_PRECISION_BITS),
+        (int)(mGain >> GAIN_PRECISION_BITS)
     };
     uint32_t fracCoord[2] = {
         mFrequency << (32 - FREQ_PRECISION_BITS),
diff --git a/media/libeffects/testlibs/EffectEqualizer.cpp b/media/libeffects/testlibs/EffectEqualizer.cpp
index db4d009..72b530d 100644
--- a/media/libeffects/testlibs/EffectEqualizer.cpp
+++ b/media/libeffects/testlibs/EffectEqualizer.cpp
@@ -131,7 +131,8 @@
                             int32_t ioId,
                             effect_handle_t *pHandle) {
     int ret;
-    int i;
+    (void)sessionId;
+    (void)ioId;
 
     ALOGV("EffectLibCreateEffect start");
 
@@ -160,7 +161,7 @@
     pContext->state = EQUALIZER_STATE_INITIALIZED;
 
     ALOGV("EffectLibCreateEffect %p, size %d",
-         pContext, AudioEqualizer::GetInstanceSize(kNumBands)+sizeof(EqualizerContext));
+         pContext, (int)(AudioEqualizer::GetInstanceSize(kNumBands)+sizeof(EqualizerContext)));
 
     return 0;
 
@@ -294,7 +295,6 @@
 
 int Equalizer_init(EqualizerContext *pContext)
 {
-    int status;
 
     ALOGV("Equalizer_init start");
 
@@ -630,7 +630,6 @@
         void *pCmdData, uint32_t *replySize, void *pReplyData) {
 
     android::EqualizerContext * pContext = (android::EqualizerContext *) self;
-    int retsize;
 
     if (pContext == NULL || pContext->state == EQUALIZER_STATE_UNINITIALIZED) {
         return -EINVAL;
@@ -750,13 +749,13 @@
         NULL
 };
 
-
+__attribute__ ((visibility ("default")))
 audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
-    tag : AUDIO_EFFECT_LIBRARY_TAG,
-    version : EFFECT_LIBRARY_API_VERSION,
-    name : "Test Equalizer Library",
-    implementor : "The Android Open Source Project",
-    create_effect : android::EffectCreate,
-    release_effect : android::EffectRelease,
-    get_descriptor : android::EffectGetDescriptor,
+    .tag = AUDIO_EFFECT_LIBRARY_TAG,
+    .version = EFFECT_LIBRARY_API_VERSION,
+    .name = "Test Equalizer Library",
+    .implementor = "The Android Open Source Project",
+    .create_effect = android::EffectCreate,
+    .release_effect = android::EffectRelease,
+    .get_descriptor = android::EffectGetDescriptor,
 };
diff --git a/media/libeffects/testlibs/EffectReverb.c b/media/libeffects/testlibs/EffectReverb.c
index fce9bed..efba4f4 100644
--- a/media/libeffects/testlibs/EffectReverb.c
+++ b/media/libeffects/testlibs/EffectReverb.c
@@ -107,6 +107,8 @@
     const effect_descriptor_t *desc;
     int aux = 0;
     int preset = 0;
+    (void)sessionId;
+    (void)ioId;
 
     ALOGV("EffectLibCreateEffect start");
 
@@ -149,7 +151,7 @@
 
     module->context.mState = REVERB_STATE_INITIALIZED;
 
-    ALOGV("EffectLibCreateEffect %p ,size %d", module, sizeof(reverb_module_t));
+    ALOGV("EffectLibCreateEffect %p ,size %zu", module, sizeof(reverb_module_t));
 
     return 0;
 }
@@ -283,7 +285,6 @@
         void *pCmdData, uint32_t *replySize, void *pReplyData) {
     reverb_module_t *pRvbModule = (reverb_module_t *) self;
     reverb_object_t *pReverb;
-    int retsize;
 
     if (pRvbModule == NULL ||
             pRvbModule->context.mState == REVERB_STATE_UNINITIALIZED) {
@@ -758,7 +759,6 @@
     int32_t *pValue32;
     int16_t *pValue16;
     t_reverb_settings *pProperties;
-    int32_t i;
     int32_t temp;
     int32_t temp2;
     uint32_t size;
@@ -1654,7 +1654,6 @@
     int32_t nApOut;
 
     int32_t j;
-    int32_t nEarlyOut;
 
     int32_t tempValue;
 
@@ -2203,6 +2202,7 @@
     return 0;
 }
 
+__attribute__ ((visibility ("default")))
 audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
     .tag = AUDIO_EFFECT_LIBRARY_TAG,
     .version = EFFECT_LIBRARY_API_VERSION,
diff --git a/media/libeffects/testlibs/EffectReverb.h b/media/libeffects/testlibs/EffectReverb.h
index 756c5ea..8f405d4 100644
--- a/media/libeffects/testlibs/EffectReverb.h
+++ b/media/libeffects/testlibs/EffectReverb.h
@@ -443,7 +443,4 @@
 */
 static int ReverbUpdateRoom(reverb_object_t* pReverbData, bool fullUpdate);
 
-
-static int ReverbComputeConstants(reverb_object_t *pReverbData, uint32_t samplingRate);
-
 #endif /*ANDROID_EFFECTREVERB_H_*/
diff --git a/media/libheadtracking/SensorPoseProvider-example.cpp b/media/libheadtracking/SensorPoseProvider-example.cpp
index a246e8b..88e222e 100644
--- a/media/libheadtracking/SensorPoseProvider-example.cpp
+++ b/media/libheadtracking/SensorPoseProvider-example.cpp
@@ -40,7 +40,7 @@
 class Listener : public SensorPoseProvider::Listener {
   public:
     void onPose(int64_t timestamp, int32_t handle, const Pose3f& pose,
-                const std::optional<Twist3f>& twist) override {
+                const std::optional<Twist3f>& twist, bool isNewReference) override {
         int64_t now = elapsedRealtimeNano();
 
         std::cout << "onPose t=" << timestamp
@@ -53,7 +53,7 @@
         } else {
             std::cout << "<none>";
         }
-        std::cout << std::endl;
+        std::cout << " isNewReference=" << isNewReference << std::endl;
     }
 };
 
@@ -67,11 +67,15 @@
 
     std::unique_ptr<SensorPoseProvider> provider =
             SensorPoseProvider::create(kPackageName, &listener);
-    int32_t headHandle = provider->startSensor(headSensor->getHandle(), 500ms);
+    if (!provider->startSensor(headSensor->getHandle(), 500ms)) {
+        std::cout << "Failed to start head sensor" << std::endl;
+    }
     sleep(2);
-    provider->startSensor(screenSensor->getHandle(), 500ms);
+    if (!provider->startSensor(screenSensor->getHandle(), 500ms)) {
+        std::cout << "Failed to start screenSensor sensor" << std::endl;
+    }
     sleep(2);
-    provider->stopSensor(headHandle);
+    provider->stopSensor(headSensor->getHandle());
     sleep(2);
     return 0;
 }
diff --git a/media/libheadtracking/SensorPoseProvider.cpp b/media/libheadtracking/SensorPoseProvider.cpp
index c4c031d..ec5e1ec 100644
--- a/media/libheadtracking/SensorPoseProvider.cpp
+++ b/media/libheadtracking/SensorPoseProvider.cpp
@@ -24,6 +24,7 @@
 #include <map>
 #include <thread>
 
+#include <android-base/thread_annotations.h>
 #include <log/log_main.h>
 #include <sensor/Sensor.h>
 #include <sensor/SensorEventQueue.h>
@@ -86,7 +87,7 @@
         if (mSensor != SensorPoseProvider::INVALID_HANDLE) {
             int ret = mQueue->disableSensor(mSensor);
             if (ret) {
-                ALOGE("Failed to disable sensor: %s\n", strerror(ret));
+                ALOGE("Failed to disable sensor: %s", strerror(ret));
             }
         }
     }
@@ -123,9 +124,23 @@
     }
 
     bool startSensor(int32_t sensor, std::chrono::microseconds samplingPeriod) override {
+        // Figure out the sensor's data format.
+        DataFormat format = getSensorFormat(sensor);
+        if (format == DataFormat::kUnknown) {
+            ALOGE("Unknown format for sensor %" PRId32, sensor);
+            return false;
+        }
+
+        {
+            std::lock_guard lock(mMutex);
+            mEnabledSensorFormats.emplace(sensor, format);
+        }
+
         // Enable the sensor.
         if (mQueue->enableSensor(sensor, samplingPeriod.count(), 0, 0)) {
             ALOGE("Failed to enable sensor");
+            std::lock_guard lock(mMutex);
+            mEnabledSensorFormats.erase(sensor);
             return false;
         }
 
@@ -133,14 +148,32 @@
         return true;
     }
 
-    void stopSensor(int handle) override { mEnabledSensors.erase(handle); }
+    void stopSensor(int handle) override {
+        mEnabledSensors.erase(handle);
+        std::lock_guard lock(mMutex);
+        mEnabledSensorFormats.erase(handle);
+    }
 
   private:
+    enum DataFormat {
+        kUnknown,
+        kQuaternion,
+        kRotationVectorsAndFlags,
+    };
+
+    struct PoseEvent {
+        Pose3f pose;
+        std::optional<Twist3f> twist;
+        bool isNewReference;
+    };
+
     sp<Looper> mLooper;
     Listener* const mListener;
-
+    SensorManager* const mSensorManager;
     std::thread mThread;
+    std::mutex mMutex;
     std::map<int32_t, SensorEnableGuard> mEnabledSensors;
+    std::map<int32_t, DataFormat> mEnabledSensorFormats GUARDED_BY(mMutex);
     sp<SensorEventQueue> mQueue;
 
     // We must do some of the initialization operations on the worker thread, because the API relies
@@ -153,21 +186,19 @@
 
     SensorPoseProviderImpl(const char* packageName, Listener* listener)
         : mListener(listener),
-          mThread([this, p = std::string(packageName)] { threadFunc(p.c_str()); }) {}
+          mSensorManager(&SensorManager::getInstanceForPackage(String16(packageName))),
+          mThread([this] { threadFunc(); }) {}
 
     void initFinished(bool success) { mInitPromise.set_value(success); }
 
     bool waitInitFinished() { return mInitPromise.get_future().get(); }
 
-    void threadFunc(const char* packageName) {
+    void threadFunc() {
         // Obtain looper.
         mLooper = Looper::prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
 
-        // Obtain sensor manager.
-        SensorManager& sensorManager = SensorManager::getInstanceForPackage(String16(packageName));
-
         // Create event queue.
-        mQueue = sensorManager.createEventQueue();
+        mQueue = mSensorManager->createEventQueue();
 
         if (mQueue == nullptr) {
             ALOGE("Failed to create a sensor event queue");
@@ -217,24 +248,98 @@
     }
 
     void handleEvent(const ASensorEvent& event) {
-        auto value = parseEvent(event);
-        mListener->onPose(event.timestamp, event.sensor, std::get<0>(value), std::get<1>(value));
+        DataFormat format;
+        {
+            std::lock_guard lock(mMutex);
+            auto iter = mEnabledSensorFormats.find(event.sensor);
+            if (iter == mEnabledSensorFormats.end()) {
+                // This can happen if we have any pending events shortly after stopping.
+                return;
+            }
+            format = iter->second;
+        }
+        auto value = parseEvent(event, format);
+        mListener->onPose(event.timestamp, event.sensor, value.pose, value.twist,
+                          value.isNewReference);
     }
 
-    static std::tuple<Pose3f, std::optional<Twist3f>> parseEvent(const ASensorEvent& event) {
+    DataFormat getSensorFormat(int32_t handle) {
+        std::optional<const Sensor> sensor = getSensorByHandle(handle);
+        if (!sensor) {
+            ALOGE("Sensor not found: %d", handle);
+            return DataFormat::kUnknown;
+        }
+        if (sensor->getType() == ASENSOR_TYPE_ROTATION_VECTOR ||
+            sensor->getType() == ASENSOR_TYPE_GAME_ROTATION_VECTOR) {
+            return DataFormat::kQuaternion;
+        }
+
+        if (sensor->getStringType() == "com.google.hardware.sensor.hid_dynamic.headtracker") {
+            return DataFormat::kRotationVectorsAndFlags;
+        }
+
+        return DataFormat::kUnknown;
+    }
+
+    std::optional<const Sensor> getSensorByHandle(int32_t handle) {
+        const Sensor* const* list;
+        ssize_t size;
+
+        // Search static sensor list.
+        size = mSensorManager->getSensorList(&list);
+        if (size < 0) {
+            ALOGE("getSensorList failed with error code %zd", size);
+            return std::nullopt;
+        }
+        for (size_t i = 0; i < size; ++i) {
+            if (list[i]->getHandle() == handle) {
+                return *list[i];
+            }
+        }
+
+        // Search dynamic sensor list.
+        Vector<Sensor> dynList;
+        size = mSensorManager->getDynamicSensorList(dynList);
+        if (size < 0) {
+            ALOGE("getDynamicSensorList failed with error code %zd", size);
+            return std::nullopt;
+        }
+        for (size_t i = 0; i < size; ++i) {
+            if (dynList[i].getHandle() == handle) {
+                return dynList[i];
+            }
+        }
+
+        return std::nullopt;
+    }
+
+    static PoseEvent parseEvent(const ASensorEvent& event, DataFormat format) {
         // TODO(ytai): Add more types.
-        switch (event.type) {
-            case ASENSOR_TYPE_ROTATION_VECTOR:
-            case ASENSOR_TYPE_GAME_ROTATION_VECTOR: {
+        switch (format) {
+            case DataFormat::kQuaternion: {
                 Eigen::Quaternionf quat(event.data[3], event.data[0], event.data[1], event.data[2]);
                 // Adapt to different frame convention.
                 quat *= rotateX(-M_PI_2);
-                return std::make_tuple(Pose3f(quat), std::optional<Twist3f>());
+                return PoseEvent{Pose3f(quat), std::optional<Twist3f>(), false};
+            }
+
+            case DataFormat::kRotationVectorsAndFlags: {
+                // Custom sensor, assumed to contain:
+                // 3 floats representing orientation as a rotation vector (in rad).
+                // 3 floats representing angular velocity as a rotation vector (in rad/s).
+                // 1 uint32_t of flags, where:
+                // - LSb is '1' iff the given sample is the first one in a new frame of reference.
+                // - The rest of the bits are reserved for future use.
+                Eigen::Vector3f rotation = {event.data[0], event.data[1], event.data[2]};
+                Eigen::Vector3f twist = {event.data[3], event.data[4], event.data[5]};
+                Eigen::Quaternionf quat = rotationVectorToQuaternion(rotation);
+                uint32_t flags = *reinterpret_cast<const uint32_t*>(&event.data[6]);
+                return PoseEvent{Pose3f(quat), Twist3f(Eigen::Vector3f::Zero(), twist),
+                                 (flags & (1 << 0)) != 0};
             }
 
             default:
-                ALOGE("Unsupported sensor type: %" PRId32, event.type);
-                return std::make_tuple(Pose3f(), std::optional<Twist3f>());
+                LOG_ALWAYS_FATAL("Unexpected sensor type: %d", static_cast<int>(format));
         }
     }
 };
diff --git a/media/libheadtracking/include/media/SensorPoseProvider.h b/media/libheadtracking/include/media/SensorPoseProvider.h
index 1a5deb0..d2a6b77 100644
--- a/media/libheadtracking/include/media/SensorPoseProvider.h
+++ b/media/libheadtracking/include/media/SensorPoseProvider.h
@@ -61,7 +61,7 @@
         virtual ~Listener() = default;
 
         virtual void onPose(int64_t timestamp, int32_t handle, const Pose3f& pose,
-                            const std::optional<Twist3f>& twist) = 0;
+                            const std::optional<Twist3f>& twist, bool isNewReference) = 0;
     };
 
     /**
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 1c9b9e4..5215c1b 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -949,6 +949,9 @@
         mVideoWidth = ext1;
         mVideoHeight = ext2;
         break;
+    case MEDIA_STARTED:
+        ALOGV("Received media started message");
+        break;
     case MEDIA_NOTIFY_TIME:
         ALOGV("Received notify time message");
         break;
diff --git a/media/libmediametrics/include/media/MediaMetricsItem.h b/media/libmediametrics/include/media/MediaMetricsItem.h
index 428992c..347fe28 100644
--- a/media/libmediametrics/include/media/MediaMetricsItem.h
+++ b/media/libmediametrics/include/media/MediaMetricsItem.h
@@ -470,11 +470,10 @@
     status_t extract(std::string *val, const char **bufferpptr, const char *bufferptrmax) {
         const char *ptr = *bufferpptr;
         while (*ptr != 0) {
-            if (ptr >= bufferptrmax) {
+            if (++ptr >= bufferptrmax) {
                 ALOGE("%s: buffer exceeded", __func__);
                 return BAD_VALUE;
             }
-            ++ptr;
         }
         const size_t size = (ptr - *bufferpptr) + 1;
         *val = *bufferpptr;
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 9620d24..4f0909b 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -102,7 +102,11 @@
     AttributionSourceState myAttributionSource;
     myAttributionSource.uid = VALUE_OR_FATAL(android::legacy2aidl_uid_t_int32_t(getuid()));
     myAttributionSource.pid = VALUE_OR_FATAL(android::legacy2aidl_pid_t_int32_t(getpid()));
-    myAttributionSource.token = sp<BBinder>::make();
+    if (callerAttributionSource.token != nullptr) {
+        myAttributionSource.token = callerAttributionSource.token;
+    } else {
+        myAttributionSource.token = sp<BBinder>::make();
+    }
     myAttributionSource.next.push_back(nextAttributionSource);
 
     return std::optional<AttributionSourceState>{myAttributionSource};
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index a40f6aa..cf699d3 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -93,8 +93,10 @@
     audio_patch_handle_t getPatchHandle() const override;
     void setPatchHandle(audio_patch_handle_t handle) override;
     bool isMmap() override {
-        if (getPolicyAudioPort() != nullptr) {
-            return getPolicyAudioPort()->isMmap();
+        if (const auto policyPort = getPolicyAudioPort(); policyPort != nullptr) {
+            if (const auto port = policyPort->asAudioPort(); port != nullptr) {
+                return port->isMmap();
+            }
         }
         return false;
     }
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 123011a..d06496d 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -270,8 +270,10 @@
     audio_patch_handle_t getPatchHandle() const override;
     void setPatchHandle(audio_patch_handle_t handle) override;
     bool isMmap() override {
-        if (getPolicyAudioPort() != nullptr) {
-            return getPolicyAudioPort()->isMmap();
+        if (const auto policyPort = getPolicyAudioPort(); policyPort != nullptr) {
+            if (const auto port = policyPort->asAudioPort(); port != nullptr) {
+                return port->isMmap();
+            }
         }
         return false;
     }
diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index 0e1548f..2e680e3 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -57,11 +57,12 @@
     // Once capture clients are tracked individually and not per session this can be removed
     // MMAP no IRQ input streams do not have the default limitation of one active client
     // max as they can be used in shared mode by the same application.
+    // NOTE: Please consider moving to AudioPort when addressing the FIXME
     // NOTE: this works for explicit values set in audio_policy_configuration.xml because
     // flags are parsed before maxActiveCount by the serializer.
     void setFlags(uint32_t flags) override
     {
-        PolicyAudioPort::setFlags(flags);
+        AudioPort::setFlags(flags);
         if (getRole() == AUDIO_PORT_ROLE_SINK && (flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
             maxActiveCount = 0;
         }
diff --git a/services/audiopolicy/common/managerdefinitions/include/PolicyAudioPort.h b/services/audiopolicy/common/managerdefinitions/include/PolicyAudioPort.h
index ab33b38..acf787b 100644
--- a/services/audiopolicy/common/managerdefinitions/include/PolicyAudioPort.h
+++ b/services/audiopolicy/common/managerdefinitions/include/PolicyAudioPort.h
@@ -36,7 +36,7 @@
 class PolicyAudioPort : public virtual RefBase, private HandleGenerator<audio_port_handle_t>
 {
 public:
-    PolicyAudioPort() : mFlags(AUDIO_OUTPUT_FLAG_NONE) {}
+    PolicyAudioPort() = default;
 
     virtual ~PolicyAudioPort() = default;
 
@@ -49,19 +49,6 @@
 
     virtual sp<AudioPort> asAudioPort() const = 0;
 
-    virtual void setFlags(uint32_t flags)
-    {
-        //force direct flag if offload flag is set: offloading implies a direct output stream
-        // and all common behaviors are driven by checking only the direct flag
-        // this should normally be set appropriately in the policy configuration file
-        if (asAudioPort()->getRole() == AUDIO_PORT_ROLE_SOURCE &&
-                (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
-            flags |= AUDIO_OUTPUT_FLAG_DIRECT;
-        }
-        mFlags = flags;
-    }
-    uint32_t getFlags() const { return mFlags; }
-
     virtual void attach(const sp<HwModule>& module);
     virtual void detach();
     bool isAttached() { return mModule != 0; }
@@ -105,22 +92,6 @@
     const char *getModuleName() const;
     sp<HwModule> getModule() const { return mModule; }
 
-    inline bool isDirectOutput() const
-    {
-        return (asAudioPort()->getType() == AUDIO_PORT_TYPE_MIX) &&
-                (asAudioPort()->getRole() == AUDIO_PORT_ROLE_SOURCE) &&
-                (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD));
-    }
-
-    inline bool isMmap() const
-    {
-        return (asAudioPort()->getType() == AUDIO_PORT_TYPE_MIX)
-                && (((asAudioPort()->getRole() == AUDIO_PORT_ROLE_SOURCE) &&
-                        ((mFlags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) != 0))
-                    || ((asAudioPort()->getRole() == AUDIO_PORT_ROLE_SINK) &&
-                        ((mFlags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)));
-    }
-
     void addRoute(const sp<AudioRoute> &route) { mRoutes.add(route); }
     const AudioRouteVector &getRoutes() const { return mRoutes; }
 
@@ -129,7 +100,6 @@
                          const ChannelMaskSet &channelMasks) const;
     void pickSamplingRate(uint32_t &rate, const SampleRateSet &samplingRates) const;
 
-    uint32_t mFlags; // attribute flags mask (e.g primary output, direct output...).
     sp<HwModule> mModule;     // audio HW module exposing this I/O stream
     AudioRouteVector mRoutes; // Routes involving this port
 };
@@ -141,27 +111,18 @@
 
     virtual sp<PolicyAudioPort> getPolicyAudioPort() const = 0;
 
-    status_t validationBeforeApplyConfig(const struct audio_port_config *config) const;
-
-    void applyPolicyAudioPortConfig(const struct audio_port_config *config) {
-        if (config->config_mask & AUDIO_PORT_CONFIG_FLAGS) {
-            mFlags = config->flags;
-        }
+    status_t validationBeforeApplyConfig(const struct audio_port_config *config) const {
+        sp<PolicyAudioPort> policyAudioPort = getPolicyAudioPort();
+        return policyAudioPort ? policyAudioPort->checkExactAudioProfile(config) : NO_INIT;
     }
 
-    void toPolicyAudioPortConfig(
-            struct audio_port_config *dstConfig,
-            const struct audio_port_config *srcConfig = NULL) const;
-
-
-    virtual bool hasSameHwModuleAs(const sp<PolicyAudioPortConfig>& other) const {
+    bool hasSameHwModuleAs(const sp<PolicyAudioPortConfig>& other) const {
         return (other.get() != nullptr) && (other->getPolicyAudioPort().get() != nullptr) &&
                 (getPolicyAudioPort().get() != nullptr) &&
                 (other->getPolicyAudioPort()->getModuleHandle() ==
                         getPolicyAudioPort()->getModuleHandle());
     }
 
-    union audio_io_flags mFlags = { AUDIO_INPUT_FLAG_NONE };
 };
 
 } // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index 7016a08..6c1240b 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -62,7 +62,6 @@
     toAudioPortConfig(&localBackupConfig);
     if ((status = validationBeforeApplyConfig(config)) == NO_ERROR) {
         AudioPortConfig::applyAudioPortConfig(config, backupConfig);
-        applyPolicyAudioPortConfig(config);
     }
 
     if (backupConfig != NULL) {
@@ -83,7 +82,6 @@
     }
 
     AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
-    toPolicyAudioPortConfig(dstConfig, srcConfig);
 
     dstConfig->role = AUDIO_PORT_ROLE_SINK;
     dstConfig->type = AUDIO_PORT_TYPE_MIX;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 34b5c1a..b054c6d 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -188,7 +188,6 @@
     toAudioPortConfig(&localBackupConfig);
     if ((status = validationBeforeApplyConfig(config)) == NO_ERROR) {
         AudioPortConfig::applyAudioPortConfig(config, backupConfig);
-        applyPolicyAudioPortConfig(config);
     }
 
     if (backupConfig != NULL) {
@@ -207,7 +206,6 @@
         dstConfig->config_mask |= srcConfig->config_mask;
     }
     AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
-    toPolicyAudioPortConfig(dstConfig, srcConfig);
 
     dstConfig->role = AUDIO_PORT_ROLE_SOURCE;
     dstConfig->type = AUDIO_PORT_TYPE_MIX;
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index 4a4ee12..141c2be 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -118,7 +118,6 @@
     toAudioPortConfig(&localBackupConfig);
     if ((status = validationBeforeApplyConfig(config)) == NO_ERROR) {
         AudioPortConfig::applyAudioPortConfig(config, backupConfig);
-        applyPolicyAudioPortConfig(config);
     }
 
     if (backupConfig != NULL) {
@@ -131,8 +130,6 @@
                                          const struct audio_port_config *srcConfig) const
 {
     DeviceDescriptorBase::toAudioPortConfig(dstConfig, srcConfig);
-    toPolicyAudioPortConfig(dstConfig, srcConfig);
-
     dstConfig->ext.device.hw_module = getModuleHandle();
 }
 
diff --git a/services/audiopolicy/common/managerdefinitions/src/PolicyAudioPort.cpp b/services/audiopolicy/common/managerdefinitions/src/PolicyAudioPort.cpp
index 5986069..ce8178f 100644
--- a/services/audiopolicy/common/managerdefinitions/src/PolicyAudioPort.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/PolicyAudioPort.cpp
@@ -87,7 +87,7 @@
     // For direct outputs, pick minimum sampling rate: this helps ensuring that the
     // channel count / sampling rate combination chosen will be supported by the connected
     // sink
-    if (isDirectOutput()) {
+    if (asAudioPort()->isDirectOutput()) {
         uint32_t samplingRate = UINT_MAX;
         for (const auto rate : samplingRates) {
             if ((rate < samplingRate) && (rate > 0)) {
@@ -122,7 +122,7 @@
     // For direct outputs, pick minimum channel count: this helps ensuring that the
     // channel count / sampling rate combination chosen will be supported by the connected
     // sink
-    if (isDirectOutput()) {
+    if (asAudioPort()->isDirectOutput()) {
         uint32_t channelCount = UINT_MAX;
         for (const auto channelMask : channelMasks) {
             uint32_t cnlCount;
@@ -236,7 +236,7 @@
     audio_format_t bestFormat = sPcmFormatCompareTable[ARRAY_SIZE(sPcmFormatCompareTable) - 1];
     // For mixed output and inputs, use best mixer output format.
     // Do not limit format otherwise
-    if ((asAudioPort()->getType() != AUDIO_PORT_TYPE_MIX) || isDirectOutput()) {
+    if ((asAudioPort()->getType() != AUDIO_PORT_TYPE_MIX) || asAudioPort()->isDirectOutput()) {
         bestFormat = AUDIO_FORMAT_INVALID;
     }
 
@@ -266,29 +266,4 @@
             asAudioPort()->getName().c_str(), samplingRate, channelMask, format);
 }
 
-// --- PolicyAudioPortConfig class implementation
-
-status_t PolicyAudioPortConfig::validationBeforeApplyConfig(
-        const struct audio_port_config *config) const
-{
-    sp<PolicyAudioPort> policyAudioPort = getPolicyAudioPort();
-    return policyAudioPort ? policyAudioPort->checkExactAudioProfile(config) : NO_INIT;
-}
-
-void PolicyAudioPortConfig::toPolicyAudioPortConfig(struct audio_port_config *dstConfig,
-                                                    const struct audio_port_config *srcConfig) const
-{
-    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_FLAGS) {
-        if ((srcConfig != nullptr) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_FLAGS)) {
-            dstConfig->flags = srcConfig->flags;
-        } else {
-            dstConfig->flags = mFlags;
-        }
-    } else {
-        dstConfig->flags = { AUDIO_INPUT_FLAG_NONE };
-    }
-}
-
-
-
 } // namespace android
diff --git a/services/audiopolicy/service/SpatializerPoseController.cpp b/services/audiopolicy/service/SpatializerPoseController.cpp
index eb23298..ffedf63 100644
--- a/services/audiopolicy/service/SpatializerPoseController.cpp
+++ b/services/audiopolicy/service/SpatializerPoseController.cpp
@@ -224,13 +224,19 @@
 }
 
 void SpatializerPoseController::onPose(int64_t timestamp, int32_t sensor, const Pose3f& pose,
-                                       const std::optional<Twist3f>& twist) {
+                                       const std::optional<Twist3f>& twist, bool isNewReference) {
     std::lock_guard lock(mMutex);
     if (sensor == mHeadSensor) {
         mProcessor->setWorldToHeadPose(timestamp, pose, twist.value_or(Twist3f()));
+        if (isNewReference) {
+            mProcessor->recenter(true, false);
+        }
     }
     if (sensor == mScreenSensor) {
         mProcessor->setWorldToScreenPose(timestamp, pose);
+        if (isNewReference) {
+            mProcessor->recenter(false, true);
+        }
     }
 }
 
diff --git a/services/audiopolicy/service/SpatializerPoseController.h b/services/audiopolicy/service/SpatializerPoseController.h
index c579622..2b5c189 100644
--- a/services/audiopolicy/service/SpatializerPoseController.h
+++ b/services/audiopolicy/service/SpatializerPoseController.h
@@ -130,7 +130,7 @@
     bool mCalculated = false;
 
     void onPose(int64_t timestamp, int32_t sensor, const media::Pose3f& pose,
-                const std::optional<media::Twist3f>& twist) override;
+                const std::optional<media::Twist3f>& twist, bool isNewReference) override;
 
     /**
      * Calculates the new outputs and updates internal state. Must be called with the lock held.
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 67ec150..1c26081 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -379,6 +379,12 @@
             }
 
             String8 physicalId(it.id.c_str());
+            bool hasTestPatternModePhysicalKey = std::find(mSupportedPhysicalRequestKeys.begin(),
+                    mSupportedPhysicalRequestKeys.end(), ANDROID_SENSOR_TEST_PATTERN_MODE) !=
+                    mSupportedPhysicalRequestKeys.end();
+            bool hasTestPatternDataPhysicalKey = std::find(mSupportedPhysicalRequestKeys.begin(),
+                    mSupportedPhysicalRequestKeys.end(), ANDROID_SENSOR_TEST_PATTERN_DATA) !=
+                    mSupportedPhysicalRequestKeys.end();
             if (physicalId != mDevice->getId()) {
                 auto found = std::find(requestedPhysicalIds.begin(), requestedPhysicalIds.end(),
                         it.id);
@@ -404,7 +410,8 @@
                         }
                     }
 
-                    physicalSettingsList.push_back({it.id, filteredParams});
+                    physicalSettingsList.push_back({it.id, filteredParams,
+                            hasTestPatternModePhysicalKey, hasTestPatternDataPhysicalKey});
                 }
             } else {
                 physicalSettingsList.push_back({it.id, it.settings});
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 8168821..06a3d36 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -109,6 +109,16 @@
     struct PhysicalCameraSettings {
         std::string cameraId;
         CameraMetadata metadata;
+
+        // Whether the physical camera supports testPatternMode/testPatternData
+        bool mHasTestPatternModeTag = true;
+        bool mHasTestPatternDataTag = true;
+
+        // Original value of TEST_PATTERN_MODE and DATA so that they can be
+        // restored when sensor muting is turned off
+        int32_t mOriginalTestPatternMode = 0;
+        int32_t mOriginalTestPatternData[4] = {};
+
     };
     typedef List<PhysicalCameraSettings> PhysicalCameraSettingsList;
 
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 6a1001b..cbea9a2 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -2471,22 +2471,24 @@
     }
 
     if (mSupportCameraMute) {
-        auto testPatternModeEntry =
-                newRequest->mSettingsList.begin()->metadata.find(ANDROID_SENSOR_TEST_PATTERN_MODE);
-        newRequest->mOriginalTestPatternMode = testPatternModeEntry.count > 0 ?
-                testPatternModeEntry.data.i32[0] :
-                ANDROID_SENSOR_TEST_PATTERN_MODE_OFF;
+        for (auto& settings : newRequest->mSettingsList) {
+            auto testPatternModeEntry =
+                    settings.metadata.find(ANDROID_SENSOR_TEST_PATTERN_MODE);
+            settings.mOriginalTestPatternMode = testPatternModeEntry.count > 0 ?
+                    testPatternModeEntry.data.i32[0] :
+                    ANDROID_SENSOR_TEST_PATTERN_MODE_OFF;
 
-        auto testPatternDataEntry =
-                newRequest->mSettingsList.begin()->metadata.find(ANDROID_SENSOR_TEST_PATTERN_DATA);
-        if (testPatternDataEntry.count >= 4) {
-            memcpy(newRequest->mOriginalTestPatternData, testPatternDataEntry.data.i32,
-                    sizeof(CaptureRequest::mOriginalTestPatternData));
-        } else {
-            newRequest->mOriginalTestPatternData[0] = 0;
-            newRequest->mOriginalTestPatternData[1] = 0;
-            newRequest->mOriginalTestPatternData[2] = 0;
-            newRequest->mOriginalTestPatternData[3] = 0;
+            auto testPatternDataEntry =
+                    settings.metadata.find(ANDROID_SENSOR_TEST_PATTERN_DATA);
+            if (testPatternDataEntry.count >= 4) {
+                memcpy(settings.mOriginalTestPatternData, testPatternDataEntry.data.i32,
+                        sizeof(PhysicalCameraSettings::mOriginalTestPatternData));
+            } else {
+                settings.mOriginalTestPatternData[0] = 0;
+                settings.mOriginalTestPatternData[1] = 0;
+                settings.mOriginalTestPatternData[2] = 0;
+                settings.mOriginalTestPatternData[3] = 0;
+            }
         }
     }
 
@@ -5962,48 +5964,53 @@
 
     bool changed = false;
 
-    int32_t testPatternMode = request->mOriginalTestPatternMode;
-    int32_t testPatternData[4] = {
-        request->mOriginalTestPatternData[0],
-        request->mOriginalTestPatternData[1],
-        request->mOriginalTestPatternData[2],
-        request->mOriginalTestPatternData[3]
-    };
+    // For a multi-camera, the physical cameras support the same set of
+    // test pattern modes as the logical camera.
+    for (auto& settings : request->mSettingsList) {
+        CameraMetadata &metadata = settings.metadata;
 
-    if (mCameraMute != ANDROID_SENSOR_TEST_PATTERN_MODE_OFF) {
-        testPatternMode = mCameraMute;
-        testPatternData[0] = 0;
-        testPatternData[1] = 0;
-        testPatternData[2] = 0;
-        testPatternData[3] = 0;
-    }
-
-    CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
-
-    auto testPatternEntry = metadata.find(ANDROID_SENSOR_TEST_PATTERN_MODE);
-    if (testPatternEntry.count > 0) {
-        if (testPatternEntry.data.i32[0] != testPatternMode) {
-            testPatternEntry.data.i32[0] = testPatternMode;
-            changed = true;
+        int32_t testPatternMode = settings.mOriginalTestPatternMode;
+        int32_t testPatternData[4] = {
+            settings.mOriginalTestPatternData[0],
+            settings.mOriginalTestPatternData[1],
+            settings.mOriginalTestPatternData[2],
+            settings.mOriginalTestPatternData[3]
+        };
+        if (mCameraMute != ANDROID_SENSOR_TEST_PATTERN_MODE_OFF) {
+            testPatternMode = mCameraMute;
+            testPatternData[0] = 0;
+            testPatternData[1] = 0;
+            testPatternData[2] = 0;
+            testPatternData[3] = 0;
         }
-    } else {
-        metadata.update(ANDROID_SENSOR_TEST_PATTERN_MODE,
-                &testPatternMode, 1);
-        changed = true;
-    }
 
-    auto testPatternColor = metadata.find(ANDROID_SENSOR_TEST_PATTERN_DATA);
-    if (testPatternColor.count >= 4) {
-        for (size_t i = 0; i < 4; i++) {
-            if (testPatternColor.data.i32[i] != testPatternData[i]) {
-                testPatternColor.data.i32[i] = testPatternData[i];
+        auto testPatternEntry = metadata.find(ANDROID_SENSOR_TEST_PATTERN_MODE);
+        bool supportTestPatternModeKey = settings.mHasTestPatternModeTag;
+        if (testPatternEntry.count > 0) {
+            if (testPatternEntry.data.i32[0] != testPatternMode) {
+                testPatternEntry.data.i32[0] = testPatternMode;
                 changed = true;
             }
+        } else if (supportTestPatternModeKey) {
+            metadata.update(ANDROID_SENSOR_TEST_PATTERN_MODE,
+                    &testPatternMode, 1);
+            changed = true;
         }
-    } else {
-        metadata.update(ANDROID_SENSOR_TEST_PATTERN_DATA,
-                testPatternData, 4);
-        changed = true;
+
+        auto testPatternColor = metadata.find(ANDROID_SENSOR_TEST_PATTERN_DATA);
+        bool supportTestPatternDataKey = settings.mHasTestPatternDataTag;
+        if (testPatternColor.count >= 4) {
+            for (size_t i = 0; i < 4; i++) {
+                if (testPatternColor.data.i32[i] != testPatternData[i]) {
+                    testPatternColor.data.i32[i] = testPatternData[i];
+                    changed = true;
+                }
+            }
+        } else if (supportTestPatternDataKey) {
+            metadata.update(ANDROID_SENSOR_TEST_PATTERN_DATA,
+                    testPatternData, 4);
+            changed = true;
+        }
     }
 
     return changed;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 94f32a1..e0ea7a1 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -579,10 +579,6 @@
         // overriding of ROTATE_AND_CROP value and adjustment of coordinates
         // in several other controls in both the request and the result
         bool                                mRotateAndCropAuto;
-        // Original value of TEST_PATTERN_MODE and DATA so that they can be
-        // restored when sensor muting is turned off
-        int32_t                             mOriginalTestPatternMode;
-        int32_t                             mOriginalTestPatternData[4];
 
         // Whether this capture request has its zoom ratio set to 1.0x before
         // the framework overrides it for camera HAL consumption.
@@ -590,7 +586,6 @@
         // The systemTime timestamp when the request is created.
         nsecs_t                             mRequestTimeNs;
 
-
         // Whether this capture request's distortion correction update has
         // been done.
         bool                                mDistortionCorrectionUpdated = false;
diff --git a/services/mediacodec/registrant/CodecServiceRegistrant.cpp b/services/mediacodec/registrant/CodecServiceRegistrant.cpp
index b479433..1de9efe 100644
--- a/services/mediacodec/registrant/CodecServiceRegistrant.cpp
+++ b/services/mediacodec/registrant/CodecServiceRegistrant.cpp
@@ -17,7 +17,7 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "CodecServiceRegistrant"
 
-#include <android-base/properties.h>
+#include <android/api-level.h>
 #include <android-base/logging.h>
 #include <android-base/properties.h>
 
@@ -416,48 +416,33 @@
 
     using namespace ::android::hardware::media::c2;
 
-    int platformVersion =
-        android::base::GetIntProperty("ro.build.version.sdk", int32_t(29));
-    // STOPSHIP: Remove code name checking once platform version bumps up to 30.
-    std::string codeName =
-        android::base::GetProperty("ro.build.version.codename", "");
-    if (codeName == "S") {
-        platformVersion = 31;
-    }
+    int platformVersion = android_get_device_api_level();
 
-    switch (platformVersion) {
-        case 31: {
-            android::sp<V1_2::IComponentStore> storeV1_2 =
-                new V1_2::utils::ComponentStore(store);
-            if (storeV1_2->registerAsService("software") != android::OK) {
-                LOG(ERROR) << "Cannot register software Codec2 v1.2 service.";
-                return;
-            }
-            break;
-        }
-        case 30: {
-            android::sp<V1_1::IComponentStore> storeV1_1 =
-                new V1_1::utils::ComponentStore(store);
-            if (storeV1_1->registerAsService("software") != android::OK) {
-                LOG(ERROR) << "Cannot register software Codec2 v1.1 service.";
-                return;
-            }
-            break;
-        }
-        case 29: {
-            android::sp<V1_0::IComponentStore> storeV1_0 =
-                new V1_0::utils::ComponentStore(store);
-            if (storeV1_0->registerAsService("software") != android::OK) {
-                LOG(ERROR) << "Cannot register software Codec2 v1.0 service.";
-                return;
-            }
-            break;
-        }
-        default: {
-            LOG(ERROR) << "The platform version " << platformVersion <<
-                          " is not supported.";
+    if (platformVersion >= __ANDROID_API_S__) {
+        android::sp<V1_2::IComponentStore> storeV1_2 =
+            new V1_2::utils::ComponentStore(store);
+        if (storeV1_2->registerAsService("software") != android::OK) {
+            LOG(ERROR) << "Cannot register software Codec2 v1.2 service.";
             return;
         }
+    } else if (platformVersion == __ANDROID_API_R__) {
+        android::sp<V1_1::IComponentStore> storeV1_1 =
+            new V1_1::utils::ComponentStore(store);
+        if (storeV1_1->registerAsService("software") != android::OK) {
+            LOG(ERROR) << "Cannot register software Codec2 v1.1 service.";
+            return;
+        }
+    } else if (platformVersion == __ANDROID_API_Q__) {
+        android::sp<V1_0::IComponentStore> storeV1_0 =
+            new V1_0::utils::ComponentStore(store);
+        if (storeV1_0->registerAsService("software") != android::OK) {
+            LOG(ERROR) << "Cannot register software Codec2 v1.0 service.";
+            return;
+        }
+    } else {  // platformVersion < __ANDROID_API_Q__
+        LOG(ERROR) << "The platform version " << platformVersion <<
+                      " is not supported.";
+        return;
     }
     if (!ionPropertiesDefined()) {
         using IComponentStore =
diff --git a/services/tuner/hidl/TunerHidlFrontend.cpp b/services/tuner/hidl/TunerHidlFrontend.cpp
index bbfc90f..1f28406 100644
--- a/services/tuner/hidl/TunerHidlFrontend.cpp
+++ b/services/tuner/hidl/TunerHidlFrontend.cpp
@@ -1158,12 +1158,19 @@
     }
     case FrontendSettings::isdbt: {
         const FrontendIsdbtSettings& isdbt = aidlSettings.get<FrontendSettings::isdbt>();
+        HidlFrontendIsdbtModulation modulation = HidlFrontendIsdbtModulation::UNDEFINED;
+        HidlFrontendIsdbtCoderate coderate = HidlFrontendIsdbtCoderate::UNDEFINED;
+        if (isdbt.layerSettings.size() > 0) {
+            modulation =
+                    static_cast<HidlFrontendIsdbtModulation>(isdbt.layerSettings[0].modulation);
+            coderate = static_cast<HidlFrontendIsdbtCoderate>(isdbt.layerSettings[0].coderate);
+        }
         settings.isdbt({
                 .frequency = static_cast<uint32_t>(isdbt.frequency),
-                .modulation = static_cast<HidlFrontendIsdbtModulation>(isdbt.modulation),
+                .modulation = modulation,
                 .bandwidth = static_cast<HidlFrontendIsdbtBandwidth>(isdbt.bandwidth),
                 .mode = static_cast<HidlFrontendIsdbtMode>(isdbt.mode),
-                .coderate = static_cast<HidlFrontendIsdbtCoderate>(isdbt.coderate),
+                .coderate = coderate,
                 .guardInterval = static_cast<HidlFrontendIsdbtGuardInterval>(isdbt.guardInterval),
                 .serviceAreaId = static_cast<uint32_t>(isdbt.serviceAreaId),
         });
diff --git a/services/tuner/hidl/TunerHidlService.cpp b/services/tuner/hidl/TunerHidlService.cpp
index 8d4053a..f4b0cde 100644
--- a/services/tuner/hidl/TunerHidlService.cpp
+++ b/services/tuner/hidl/TunerHidlService.cpp
@@ -19,6 +19,7 @@
 
 #include "TunerHidlService.h"
 
+#include <aidl/android/hardware/tv/tuner/FrontendIsdbtTimeInterleaveMode.h>
 #include <aidl/android/hardware/tv/tuner/Result.h>
 #include <android/binder_manager.h>
 #include <binder/IPCThreadState.h>
@@ -42,6 +43,7 @@
 using ::aidl::android::hardware::tv::tuner::FrontendIsdbs3Capabilities;
 using ::aidl::android::hardware::tv::tuner::FrontendIsdbsCapabilities;
 using ::aidl::android::hardware::tv::tuner::FrontendIsdbtCapabilities;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbtTimeInterleaveMode;
 using ::aidl::android::hardware::tv::tuner::FrontendType;
 using ::aidl::android::hardware::tv::tuner::Result;
 using ::aidl::android::media::tv::tunerresourcemanager::TunerFrontendInfo;
@@ -618,6 +620,10 @@
                             static_cast<int32_t>(halInfo.frontendCaps.isdbtCaps().coderateCap),
                     .guardIntervalCap =
                             static_cast<int32_t>(halInfo.frontendCaps.isdbtCaps().guardIntervalCap),
+                    .timeInterleaveCap =
+                            static_cast<int32_t>(FrontendIsdbtTimeInterleaveMode::UNDEFINED),
+                    .isSegmentAuto = false,
+                    .isFullSegment = false,
             };
             caps.set<FrontendCapabilities::isdbtCaps>(isdbtCaps);
         }