Merge "Support for BLE assisted P2P discovery and pairing" into main
diff --git a/audio/aidl/common/include/Utils.h b/audio/aidl/common/include/Utils.h
index ce29635..52ae936 100644
--- a/audio/aidl/common/include/Utils.h
+++ b/audio/aidl/common/include/Utils.h
@@ -29,7 +29,6 @@
 #include <aidl/android/media/audio/common/AudioIoFlags.h>
 #include <aidl/android/media/audio/common/AudioMode.h>
 #include <aidl/android/media/audio/common/AudioOutputFlags.h>
-#include <aidl/android/media/audio/common/AudioPolicyForcedConfig.h>
 #include <aidl/android/media/audio/common/PcmType.h>
 #include <android/binder_auto_utils.h>
 #include <utils/FastStrcmp.h>
@@ -63,31 +62,6 @@
         ::aidl::android::media::audio::common::AudioMode::CALL_SCREEN,
 };
 
-constexpr std::array<::aidl::android::media::audio::common::AudioPolicyForcedConfig, 17>
-        kValidAudioPolicyForcedConfig = {
-                ::aidl::android::media::audio::common::AudioPolicyForcedConfig::NONE,
-                ::aidl::android::media::audio::common::AudioPolicyForcedConfig::SPEAKER,
-                ::aidl::android::media::audio::common::AudioPolicyForcedConfig::HEADPHONES,
-                ::aidl::android::media::audio::common::AudioPolicyForcedConfig::BT_SCO,
-                ::aidl::android::media::audio::common::AudioPolicyForcedConfig::BT_A2DP,
-                ::aidl::android::media::audio::common::AudioPolicyForcedConfig::WIRED_ACCESSORY,
-                ::aidl::android::media::audio::common::AudioPolicyForcedConfig::BT_CAR_DOCK,
-                ::aidl::android::media::audio::common::AudioPolicyForcedConfig::BT_DESK_DOCK,
-                ::aidl::android::media::audio::common::AudioPolicyForcedConfig::ANALOG_DOCK,
-                ::aidl::android::media::audio::common::AudioPolicyForcedConfig::DIGITAL_DOCK,
-                ::aidl::android::media::audio::common::AudioPolicyForcedConfig::NO_BT_A2DP,
-                ::aidl::android::media::audio::common::AudioPolicyForcedConfig::SYSTEM_ENFORCED,
-                ::aidl::android::media::audio::common::AudioPolicyForcedConfig::
-                        HDMI_SYSTEM_AUDIO_ENFORCED,
-                ::aidl::android::media::audio::common::AudioPolicyForcedConfig::
-                        ENCODED_SURROUND_NEVER,
-                ::aidl::android::media::audio::common::AudioPolicyForcedConfig::
-                        ENCODED_SURROUND_ALWAYS,
-                ::aidl::android::media::audio::common::AudioPolicyForcedConfig::
-                        ENCODED_SURROUND_MANUAL,
-                ::aidl::android::media::audio::common::AudioPolicyForcedConfig::BT_BLE,
-};
-
 constexpr bool iequals(const std::string& str1, const std::string& str2) {
     return str1.length() == str2.length() &&
            !fasticmp<strncmp>(str1.c_str(), str2.c_str(), str1.length());
@@ -168,12 +142,6 @@
            kValidAudioModes.end();
 }
 
-constexpr bool isValidAudioPolicyForcedConfig(
-        ::aidl::android::media::audio::common::AudioPolicyForcedConfig config) {
-    return std::find(kValidAudioPolicyForcedConfig.begin(), kValidAudioPolicyForcedConfig.end(),
-                     config) != kValidAudioPolicyForcedConfig.end();
-}
-
 static inline bool maybeVendorExtension(const std::string& s) {
     // Only checks whether the string starts with the "vendor prefix".
     static const std::string vendorPrefix = "VX_";
diff --git a/audio/aidl/default/CapEngineConfigXmlConverter.cpp b/audio/aidl/default/CapEngineConfigXmlConverter.cpp
index a6e78b9..20fbca4 100644
--- a/audio/aidl/default/CapEngineConfigXmlConverter.cpp
+++ b/audio/aidl/default/CapEngineConfigXmlConverter.cpp
@@ -96,8 +96,8 @@
     } else if (!fastcmp<strncmp>(criterionName.c_str(), kXsdcForceConfigForUse,
             strlen(kXsdcForceConfigForUse))) {
         AudioHalCapCriterionV2::ForceConfigForUse value;
-        value.forceUse = VALUE_OR_RETURN(convertForceUseCriterionToAidl(criterionName));
-        value.values.emplace_back(VALUE_OR_RETURN(convertForcedConfigToAidl(criterionValue)));
+        value.values.emplace_back(
+                VALUE_OR_RETURN(convertForceUseToAidl(criterionName, criterionValue)));
         rule.criterionAndValue = AudioHalCapCriterionV2::make<Tag::forceConfigForUse>(value);
     } else {
         LOG(ERROR) << __func__ << " unrecognized criterion " << criterionName;
diff --git a/audio/aidl/default/XsdcConversion.cpp b/audio/aidl/default/XsdcConversion.cpp
index ba6110d..b42d7f5 100644
--- a/audio/aidl/default/XsdcConversion.cpp
+++ b/audio/aidl/default/XsdcConversion.cpp
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
 #include <inttypes.h>
 
 #include <unordered_set>
@@ -5,6 +21,7 @@
 #define LOG_TAG "AHAL_Config"
 #include <android-base/logging.h>
 #include <android-base/strings.h>
+#include <android/binder_enums.h>
 
 #include <aidl/android/media/audio/common/AudioPort.h>
 #include <aidl/android/media/audio/common/AudioPortConfig.h>
@@ -20,9 +37,7 @@
 
 using aidl::android::hardware::audio::common::iequals;
 using aidl::android::hardware::audio::common::isValidAudioMode;
-using aidl::android::hardware::audio::common::isValidAudioPolicyForcedConfig;
 using aidl::android::hardware::audio::common::kValidAudioModes;
-using aidl::android::hardware::audio::common::kValidAudioPolicyForcedConfig;
 using aidl::android::media::audio::common::AudioChannelLayout;
 using aidl::android::media::audio::common::AudioContentType;
 using aidl::android::media::audio::common::AudioDevice;
@@ -38,7 +53,6 @@
 using aidl::android::media::audio::common::AudioHalVolumeCurve;
 using aidl::android::media::audio::common::AudioIoFlags;
 using aidl::android::media::audio::common::AudioMode;
-using aidl::android::media::audio::common::AudioPolicyForcedConfig;
 using aidl::android::media::audio::common::AudioPolicyForceUse;
 using aidl::android::media::audio::common::AudioPort;
 using aidl::android::media::audio::common::AudioPortConfig;
@@ -49,9 +63,10 @@
 using aidl::android::media::audio::common::AudioSource;
 using aidl::android::media::audio::common::AudioStreamType;
 using aidl::android::media::audio::common::AudioUsage;
-using ::android::BAD_VALUE;
-using ::android::base::unexpected;
-using ::android::utilities::convertTo;
+using android::BAD_VALUE;
+using android::base::unexpected;
+using android::utilities::convertTo;
+using ndk::enum_range;
 
 namespace ap_xsd = android::audio::policy::configuration;
 namespace eng_xsd = android::audio::policy::engine::configuration;
@@ -531,18 +546,6 @@
     return result;
 }
 
-ConversionResult<AudioPolicyForcedConfig> convertForcedConfigToAidl(
-        const std::string& xsdcForcedConfigCriterionType) {
-    const auto it = std::find_if(
-            kValidAudioPolicyForcedConfig.begin(), kValidAudioPolicyForcedConfig.end(),
-            [&](const auto& config) { return toString(config) == xsdcForcedConfigCriterionType; });
-    if (it == kValidAudioPolicyForcedConfig.end()) {
-        LOG(ERROR) << __func__ << " invalid forced config " << xsdcForcedConfigCriterionType;
-        return unexpected(BAD_VALUE);
-    }
-    return *it;
-}
-
 ConversionResult<AudioMode> convertTelephonyModeToAidl(const std::string& xsdcModeCriterionType) {
     const auto it = std::find_if(kValidAudioModes.begin(), kValidAudioModes.end(),
                                  [&xsdcModeCriterionType](const auto& mode) {
@@ -637,6 +640,16 @@
     return aidlDeviceAddresses;
 }
 
+ConversionResult<AudioMode> convertAudioModeToAidl(const std::string& xsdcAudioModeType) {
+    const auto it = std::find_if(enum_range<AudioMode>().begin(), enum_range<AudioMode>().end(),
+                                 [&](const auto v) { return toString(v) == xsdcAudioModeType; });
+    if (it == enum_range<AudioMode>().end()) {
+        LOG(ERROR) << __func__ << " invalid audio mode " << xsdcAudioModeType;
+        return unexpected(BAD_VALUE);
+    }
+    return *it;
+}
+
 ConversionResult<std::vector<AudioMode>> convertTelephonyModesToAidl(
         const eng_xsd::CriterionTypeType& xsdcTelephonyModeCriterionType) {
     if (xsdcTelephonyModeCriterionType.getValues().empty()) {
@@ -647,71 +660,97 @@
     for (eng_xsd::ValuesType xsdcValues : xsdcTelephonyModeCriterionType.getValues()) {
         aidlAudioModes.reserve(xsdcValues.getValue().size());
         for (const eng_xsd::ValueType& xsdcValue : xsdcValues.getValue()) {
-            int integerValue = xsdcValue.getNumerical();
-            if (!isValidAudioMode(AudioMode(integerValue))) {
-                LOG(ERROR) << __func__ << " invalid audio mode " << integerValue;
-                return unexpected(BAD_VALUE);
-            }
-            aidlAudioModes.push_back(AudioMode(integerValue));
+            aidlAudioModes.push_back(
+                    VALUE_OR_RETURN(convertAudioModeToAidl(xsdcValue.getLiteral())));
         }
     }
     return aidlAudioModes;
 }
 
-ConversionResult<std::vector<AudioPolicyForcedConfig>> convertForcedConfigsToAidl(
+ConversionResult<std::vector<AudioPolicyForceUse>> convertForceUseConfigsToAidl(
+        const std::string& criterionValue,
         const eng_xsd::CriterionTypeType& xsdcForcedConfigCriterionType) {
     if (xsdcForcedConfigCriterionType.getValues().empty()) {
         LOG(ERROR) << __func__ << " no values provided";
         return unexpected(BAD_VALUE);
     }
-    std::vector<AudioPolicyForcedConfig> aidlForcedConfigs;
+    std::vector<AudioPolicyForceUse> aidlForcedConfigs;
     for (eng_xsd::ValuesType xsdcValues : xsdcForcedConfigCriterionType.getValues()) {
         aidlForcedConfigs.reserve(xsdcValues.getValue().size());
         for (const eng_xsd::ValueType& xsdcValue : xsdcValues.getValue()) {
-            int integerValue = xsdcValue.getNumerical();
-            if (!isValidAudioPolicyForcedConfig(AudioPolicyForcedConfig(integerValue))) {
-                LOG(ERROR) << __func__ << " invalid forced config mode " << integerValue;
-                return unexpected(BAD_VALUE);
-            }
-            aidlForcedConfigs.push_back(AudioPolicyForcedConfig(integerValue));
+            aidlForcedConfigs.push_back(
+                    VALUE_OR_RETURN(convertForceUseToAidl(criterionValue, xsdcValue.getLiteral())));
         }
     }
     return aidlForcedConfigs;
 }
 
-ConversionResult<AudioPolicyForceUse> convertForceUseCriterionToAidl(
-        const std::string& xsdcCriterionName) {
+template <typename T>
+ConversionResult<T> convertForceUseForcedConfigToAidl(
+        const std::string& xsdcForcedConfigCriterionType) {
+    const auto it = std::find_if(enum_range<T>().begin(), enum_range<T>().end(), [&](const auto v) {
+        return toString(v) == xsdcForcedConfigCriterionType;
+    });
+    if (it == enum_range<T>().end()) {
+        LOG(ERROR) << __func__ << " invalid forced config " << xsdcForcedConfigCriterionType;
+        return unexpected(BAD_VALUE);
+    }
+    return *it;
+}
+
+ConversionResult<AudioPolicyForceUse> convertForceUseToAidl(const std::string& xsdcCriterionName,
+                                                            const std::string& xsdcCriterionValue) {
     if (!fastcmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForCommunication,
-            strlen(kXsdcForceConfigForCommunication))) {
-        return AudioPolicyForceUse::COMMUNICATION;
+                          strlen(kXsdcForceConfigForCommunication))) {
+        const auto deviceCategory = VALUE_OR_RETURN(
+                convertForceUseForcedConfigToAidl<AudioPolicyForceUse::CommunicationDeviceCategory>(
+                        xsdcCriterionValue));
+        return AudioPolicyForceUse::make<AudioPolicyForceUse::forCommunication>(deviceCategory);
     }
     if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForMedia,
             strlen(kXsdcForceConfigForMedia))) {
-        return AudioPolicyForceUse::MEDIA;
+        const auto deviceCategory = VALUE_OR_RETURN(
+                convertForceUseForcedConfigToAidl<AudioPolicyForceUse::MediaDeviceCategory>(
+                        xsdcCriterionValue));
+        return AudioPolicyForceUse::make<AudioPolicyForceUse::forMedia>(deviceCategory);
     }
     if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForRecord,
             strlen(kXsdcForceConfigForRecord))) {
-        return AudioPolicyForceUse::RECORD;
+        const auto deviceCategory = VALUE_OR_RETURN(
+                convertForceUseForcedConfigToAidl<AudioPolicyForceUse::CommunicationDeviceCategory>(
+                        xsdcCriterionValue));
+        return AudioPolicyForceUse::make<AudioPolicyForceUse::forRecord>(deviceCategory);
     }
     if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForDock,
-            strlen(kXsdcForceConfigForDock))) {
-        return AudioPolicyForceUse::DOCK;
+                           strlen(kXsdcForceConfigForDock))) {
+        const auto dockType =
+                VALUE_OR_RETURN(convertForceUseForcedConfigToAidl<AudioPolicyForceUse::DockType>(
+                        xsdcCriterionValue));
+        return AudioPolicyForceUse::make<AudioPolicyForceUse::dock>(dockType);
     }
     if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForSystem,
             strlen(kXsdcForceConfigForSystem))) {
-        return AudioPolicyForceUse::SYSTEM;
+        return AudioPolicyForceUse::make<AudioPolicyForceUse::systemSounds>(xsdcCriterionValue ==
+                                                                            "SYSTEM_ENFORCED");
     }
     if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForHdmiSystemAudio,
             strlen(kXsdcForceConfigForHdmiSystemAudio))) {
-        return AudioPolicyForceUse::HDMI_SYSTEM_AUDIO;
+        return AudioPolicyForceUse::make<AudioPolicyForceUse::hdmiSystemAudio>(
+                xsdcCriterionValue == "HDMI_SYSTEM_AUDIO_ENFORCED");
     }
     if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForEncodedSurround,
             strlen(kXsdcForceConfigForEncodedSurround))) {
-        return AudioPolicyForceUse::ENCODED_SURROUND;
+        const auto encodedSurround = VALUE_OR_RETURN(
+                convertForceUseForcedConfigToAidl<AudioPolicyForceUse::EncodedSurroundConfig>(
+                        xsdcCriterionValue));
+        return AudioPolicyForceUse::make<AudioPolicyForceUse::encodedSurround>(encodedSurround);
     }
     if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForVibrateRinging,
             strlen(kXsdcForceConfigForVibrateRinging))) {
-        return AudioPolicyForceUse::VIBRATE_RINGING;
+        const auto deviceCategory = VALUE_OR_RETURN(
+                convertForceUseForcedConfigToAidl<AudioPolicyForceUse::CommunicationDeviceCategory>(
+                        xsdcCriterionValue));
+        return AudioPolicyForceUse::make<AudioPolicyForceUse::forVibrateRinging>(deviceCategory);
     }
     LOG(ERROR) << __func__ << " unrecognized force use " << xsdcCriterionName;
     return unexpected(BAD_VALUE);
@@ -747,9 +786,8 @@
     }
     if (!fastcmp<strncmp>(xsdcCriterion.getName().c_str(), kXsdcForceConfigForUse,
             strlen(kXsdcForceConfigForUse))) {
-        return AudioHalCapCriterionV2::make<Tag::forceConfigForUse>(
-                VALUE_OR_RETURN(convertForceUseCriterionToAidl(xsdcCriterion.getName())),
-                VALUE_OR_RETURN(convertForcedConfigsToAidl(xsdcCriterionType)));
+        return AudioHalCapCriterionV2::make<Tag::forceConfigForUse>(VALUE_OR_RETURN(
+                convertForceUseConfigsToAidl(xsdcCriterion.getName(), xsdcCriterionType)));
     }
     LOG(ERROR) << __func__ << " unrecognized criterion " << xsdcCriterion.getName();
     return unexpected(BAD_VALUE);
diff --git a/audio/aidl/default/config/audioPolicy/engine/api/current.txt b/audio/aidl/default/config/audioPolicy/engine/api/current.txt
index 1ba91e6..41cfb44 100644
--- a/audio/aidl/default/config/audioPolicy/engine/api/current.txt
+++ b/audio/aidl/default/config/audioPolicy/engine/api/current.txt
@@ -148,6 +148,45 @@
     method public void setValue(@Nullable java.util.List<android.audio.policy.engine.configuration.FlagType>);
   }
 
+  public enum ForcedConfigCommunicationDeviceType {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigCommunicationDeviceType BT_BLE;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigCommunicationDeviceType BT_SCO;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigCommunicationDeviceType NONE;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigCommunicationDeviceType SPEAKER;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigCommunicationDeviceType WIRED_ACCESSORY;
+  }
+
+  public enum ForcedConfigDockType {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigDockType ANALOG_DOCK;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigDockType BT_CAR_DOCK;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigDockType BT_DESK_DOCK;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigDockType DIGITAL_DOCK;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigDockType NONE;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigDockType WIRED_ACCESSORY;
+  }
+
+  public enum ForcedConfigMediaDeviceType {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigMediaDeviceType ANALOG_DOCK;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigMediaDeviceType BT_A2DP;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigMediaDeviceType DIGITAL_DOCK;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigMediaDeviceType HEADPHONES;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigMediaDeviceType NONE;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigMediaDeviceType NO_BT_A2DP;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigMediaDeviceType SPEAKER;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedConfigMediaDeviceType WIRED_ACCESSORY;
+  }
+
+  public enum ForcedEncodingSourroundConfigType {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedEncodingSourroundConfigType ALWAYS;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedEncodingSourroundConfigType MANUAL;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedEncodingSourroundConfigType NEVER;
+    enum_constant public static final android.audio.policy.engine.configuration.ForcedEncodingSourroundConfigType UNSPECIFIED;
+  }
+
   public enum PfwCriterionTypeEnum {
     method @NonNull public String getRawName();
     enum_constant public static final android.audio.policy.engine.configuration.PfwCriterionTypeEnum exclusive;
@@ -245,10 +284,8 @@
     ctor public ValueType();
     method @Nullable public String getAndroid_type();
     method @Nullable public String getLiteral();
-    method @Nullable public long getNumerical();
     method public void setAndroid_type(@Nullable String);
     method public void setLiteral(@Nullable String);
-    method public void setNumerical(@Nullable long);
   }
 
   public class ValuesType {
diff --git a/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd b/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd
index 6422277..7d9b06e 100644
--- a/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd
+++ b/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd
@@ -191,10 +191,9 @@
     <xs:complexType name="valueType">
         <xs:annotation>
             <xs:documentation xml:lang="en">
-                Criterion type is provided as a tuple of 'human readable' string (referred as the
-                literal part, that will allow to express 'human readable' rules, numerical value
-                associated in order to improve performances of the parameter framework library used,
-                and an optional android type.
+                Criterion type is provided as a pair of 'human readable' string (referred as the
+                literal part, that will allow to express 'human readable' rules and an optional
+                android type.
                 This android type is reserved for device type mapping with parameter framework
                 representation on a bitfield (Only one bit is expected to represent a device) and
                 android representation of a type that may use several bits.
@@ -203,7 +202,6 @@
             </xs:documentation>
         </xs:annotation>
         <xs:attribute name="literal" type="xs:string" use="required"/>
-        <xs:attribute name="numerical" type="xs:long" use="required"/>
         <xs:attribute name="android_type" type="longDecimalOrHexType" use="optional"/>
     </xs:complexType>
 
@@ -410,6 +408,49 @@
         </xs:restriction>
     </xs:simpleType>
 
+    <xs:simpleType name="forcedConfigCommunicationDeviceType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="NONE"/>
+            <xs:enumeration value="SPEAKER"/>
+            <xs:enumeration value="BT_SCO"/>
+            <xs:enumeration value="BT_BLE"/>
+            <xs:enumeration value="WIRED_ACCESSORY"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="forcedConfigMediaDeviceType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="NONE"/>
+            <xs:enumeration value="SPEAKER"/>
+            <xs:enumeration value="HEADPHONES"/>
+            <xs:enumeration value="BT_A2DP"/>
+            <xs:enumeration value="ANALOG_DOCK"/>
+            <xs:enumeration value="DIGITAL_DOCK"/>
+            <xs:enumeration value="WIRED_ACCESSORY"/>
+            <xs:enumeration value="NO_BT_A2DP"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="forcedConfigDockType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="NONE"/>
+            <xs:enumeration value="BT_CAR_DOCK"/>
+            <xs:enumeration value="BT_DESK_DOCK"/>
+            <xs:enumeration value="ANALOG_DOCK"/>
+            <xs:enumeration value="DIGITAL_DOCK"/>
+            <xs:enumeration value="WIRED_ACCESSORY"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="forcedEncodingSourroundConfigType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="UNSPECIFIED"/>
+            <xs:enumeration value="NEVER"/>
+            <xs:enumeration value="ALWAYS"/>
+            <xs:enumeration value="MANUAL"/>
+        </xs:restriction>
+    </xs:simpleType>
+
     <xs:simpleType name="sourceEnumType">
         <xs:restriction base="xs:string">
             <xs:enumeration value="AUDIO_SOURCE_DEFAULT"/>
diff --git a/audio/aidl/default/include/core-impl/XsdcConversion.h b/audio/aidl/default/include/core-impl/XsdcConversion.h
index e855a3e..f00206b 100644
--- a/audio/aidl/default/include/core-impl/XsdcConversion.h
+++ b/audio/aidl/default/include/core-impl/XsdcConversion.h
@@ -1,6 +1,20 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
 #include <string>
-#include <unordered_map>
-#include <unordered_set>
 
 #include <aidl/android/media/audio/common/AudioHalCapCriterion.h>
 #include <aidl/android/media/audio/common/AudioHalCapCriterionType.h>
@@ -21,10 +35,8 @@
 
 static constexpr const char kXsdcForceConfigForUse[] = "ForceUseFor";
 
-ConversionResult<aidlaudiocommon::AudioPolicyForceUse> convertForceUseCriterionToAidl(
-        const std::string& xsdcCriterionName);
-ConversionResult<aidlaudiocommon::AudioPolicyForcedConfig> convertForcedConfigToAidl(
-        const std::string& xsdcForcedConfigCriterionType);
+ConversionResult<aidlaudiocommon::AudioPolicyForceUse> convertForceUseToAidl(
+        const std::string& xsdcCriterionName, const std::string& xsdcCriterionValue);
 ConversionResult<aidlaudiocommon::AudioDeviceAddress> convertDeviceAddressToAidl(
         const std::string& xsdcAddress);
 ConversionResult<aidlaudiocommon::AudioMode> convertTelephonyModeToAidl(
diff --git a/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
index 583143c..eaec88b 100644
--- a/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp
@@ -55,7 +55,6 @@
 using aidl::android::media::audio::common::AudioHalVolumeGroup;
 using aidl::android::media::audio::common::AudioMode;
 using aidl::android::media::audio::common::AudioPolicyForceUse;
-using aidl::android::media::audio::common::AudioPolicyForcedConfig;
 using aidl::android::media::audio::common::AudioProductStrategyType;
 using aidl::android::media::audio::common::AudioSource;
 using aidl::android::media::audio::common::AudioStreamType;
@@ -577,7 +576,7 @@
     void ValidateCapSpecificConfig(const AudioHalEngineConfig::CapSpecificConfig& capCfg) {
         EXPECT_TRUE(capCfg.criteriaV2.has_value());
         std::unordered_set<AudioHalCapCriterionV2::Tag> criterionTagSet;
-        std::unordered_set<AudioPolicyForceUse> forceUseCriterionUseSet;
+        std::unordered_set<AudioPolicyForceUse::Tag> forceUseCriterionUseSet;
         for (const auto& criterion : capCfg.criteriaV2.value()) {
             EXPECT_TRUE(criterion.has_value());
             if (criterion.value().getTag() != AudioHalCapCriterionV2::forceConfigForUse) {
@@ -585,7 +584,9 @@
             } else {
                 auto forceUseCriterion =
                         criterion.value().get<AudioHalCapCriterionV2::forceConfigForUse>();
-                EXPECT_TRUE(forceUseCriterionUseSet.insert(forceUseCriterion.forceUse).second);
+                ASSERT_FALSE(forceUseCriterion.values.empty());
+                EXPECT_TRUE(forceUseCriterionUseSet.insert(forceUseCriterion.values[0].getTag())
+                                    .second);
             }
             EXPECT_NO_FATAL_FAILURE(ValidateAudioHalCapCriterion(criterion.value()));
         }
diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/AlertUrgency.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/AlertUrgency.aidl
index a0ef4a9..c7bfdbc 100644
--- a/broadcastradio/aidl/android/hardware/broadcastradio/AlertUrgency.aidl
+++ b/broadcastradio/aidl/android/hardware/broadcastradio/AlertUrgency.aidl
@@ -46,7 +46,7 @@
     PAST,
 
     /**
-     * Unknown rgency.
+     * Unknown urgency.
      */
     UNKNOWN,
 }
diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/Coordinate.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/Coordinate.aidl
index b881534..9c9680b 100644
--- a/broadcastradio/aidl/android/hardware/broadcastradio/Coordinate.aidl
+++ b/broadcastradio/aidl/android/hardware/broadcastradio/Coordinate.aidl
@@ -34,7 +34,7 @@
     /**
      * Longitude of the cooridinate.
      *
-     * <p>Longitude is in the range of -90 to 90.
+     * <p>Longitude is in the range of -180 to 180.
      */
     double longitude;
 }
diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/Geocode.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/Geocode.aidl
index f0162ca..ca98154 100644
--- a/broadcastradio/aidl/android/hardware/broadcastradio/Geocode.aidl
+++ b/broadcastradio/aidl/android/hardware/broadcastradio/Geocode.aidl
@@ -17,9 +17,10 @@
 package android.hardware.broadcastradio;
 
 /**
- * Geographic code reprensenting location in alert message
+ * Geographic code reprensenting location in alert message.
  *
- * <p>(see ITU-T X.1303 bis for more info).
+ * <p>Geocode is mainly for information display instead of parsing on radio application side. See
+ * ITU-T X.1303 bis for more info.
  */
 @VintfStability
 @JavaDerive(equals=true, toString=true)
diff --git a/graphics/common/aidl/android/hardware/graphics/common/DisplayHotplugEvent.aidl b/graphics/common/aidl/android/hardware/graphics/common/DisplayHotplugEvent.aidl
index c807ffd..f779105 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/DisplayHotplugEvent.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/DisplayHotplugEvent.aidl
@@ -23,23 +23,23 @@
 @Backing(type="int")
 enum DisplayHotplugEvent {
     /**
-     * Display is successfully connected.
-     * Connected may be called more than once and the behavior of subsequent
-     * calls is that SurfaceFlinger queries the display properties again.
+     * Display was successfully connected.
+     * CONNECTED may be emitted more than once and the behavior of subsequent
+     * events is that SurfaceFlinger queries the display properties again.
      */
     CONNECTED = 0,
 
-    /** Display is successfully disconnected */
+    /** Display was successfully disconnected */
     DISCONNECTED = 1,
 
-    /** Display is plugged in, but an unknown error occurred */
+    /** Unknown error occurred */
     ERROR_UNKNOWN = -1,
 
-    /** Display is plugged in, but incompatible cable error detected */
+    /** Display was plugged in, but incompatible cable error detected */
     ERROR_INCOMPATIBLE_CABLE = -2,
 
     /**
-     * Display is plugged in, but exceeds the max number of
+     * Display was plugged in, but exceeds the max number of
      * displays that can be simultaneously connected
      */
     ERROR_TOO_MANY_DISPLAYS = -3,
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayIdentification.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayIdentification.aidl
index a0cc9b0..06f2dde 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayIdentification.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayIdentification.aidl
@@ -36,4 +36,5 @@
 parcelable DisplayIdentification {
   byte port;
   byte[] data;
+  android.hardware.graphics.composer3.ScreenPartStatus screenPartStatus = android.hardware.graphics.composer3.ScreenPartStatus.UNSUPPORTED;
 }
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
index 55604a6..adbc344 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
@@ -88,6 +88,7 @@
   android.hardware.graphics.composer3.DisplayConfiguration[] getDisplayConfigurations(long display, int maxFrameIntervalNs);
   oneway void notifyExpectedPresent(long display, in android.hardware.graphics.composer3.ClockMonotonicTimestamp expectedPresentTime, int frameIntervalNs);
   int getMaxLayerPictureProfiles(long display);
+  oneway void startHdcpNegotiation(long display, in android.hardware.drm.HdcpLevels levels);
   const int EX_BAD_CONFIG = 1;
   const int EX_BAD_DISPLAY = 2;
   const int EX_BAD_LAYER = 3;
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LutProperties.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LutProperties.aidl
index 6a4593a..9516351 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LutProperties.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LutProperties.aidl
@@ -46,5 +46,6 @@
   enum SamplingKey {
     RGB,
     MAX_RGB,
+    CIE_Y,
   }
 }
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ScreenPartStatus.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ScreenPartStatus.aidl
new file mode 100644
index 0000000..ff55370
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ScreenPartStatus.aidl
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2024, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.graphics.composer3;
+@Backing(type="int") @VintfStability
+enum ScreenPartStatus {
+  UNSUPPORTED = 0,
+  ORIGINAL = 1,
+  REPLACED = 2,
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayIdentification.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayIdentification.aidl
index 03ef8e6..a477eb6 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayIdentification.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayIdentification.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.graphics.composer3;
 
+import android.hardware.graphics.composer3.ScreenPartStatus;
 /**
  * Output parameters for IComposerClient.getDisplayIdentificationData
  */
@@ -29,4 +30,8 @@
      * The EDID 1.3 blob identifying the display.
      */
     byte[] data;
+    /**
+     * Indicator for part originality of the screen
+     */
+    ScreenPartStatus screenPartStatus = ScreenPartStatus.UNSUPPORTED;
 }
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
index edbb988..b4d2e7f 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.graphics.composer3;
 
+import android.hardware.drm.HdcpLevels;
 import android.hardware.graphics.common.DisplayDecorationSupport;
 import android.hardware.graphics.common.Hdr;
 import android.hardware.graphics.common.HdrConversionCapability;
@@ -938,4 +939,21 @@
      * pipeline, a value of zero should be returned here.
      */
     int getMaxLayerPictureProfiles(long display);
+
+    /**
+     * Supports HDCP lazy activation.
+     *
+     * When SurfaceFlinger detects secure layers, this method is called to instruct HWC side that
+     * HDCP negotiation process can be started.
+     *
+     * When HDCP is successfully started or failed to start, HWC reports the HDCP levels via
+     * IComposerCallback.onHdcpLevelsChanged().
+     *
+     * @param display is the display whose HDCP negotiation can be started.
+     * @param levels is the desired HDCP levels.
+     *
+     * @see IComposerCallback.onHdcpLevelsChanged
+     *
+     */
+    oneway void startHdcpNegotiation(long display, in HdcpLevels levels);
 }
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/LutProperties.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/LutProperties.aidl
index d3dd30e..5f436d9 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/LutProperties.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/LutProperties.aidl
@@ -42,7 +42,6 @@
      * The implementations should use a sampling strategy
      * at least as good as linear sampling.
      */
-    // TODO(b/358422255): add sampling ways
-    @VintfStability enum SamplingKey { RGB, MAX_RGB }
+    @VintfStability enum SamplingKey { RGB, MAX_RGB, CIE_Y }
     SamplingKey[] samplingKeys;
 }
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/ScreenPartStatus.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ScreenPartStatus.aidl
new file mode 100644
index 0000000..48c1270
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ScreenPartStatus.aidl
@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) 2024, 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.hardware.graphics.composer3;
+
+/**
+ * Information relating to internal screen panel part originality
+ */
+@VintfStability
+@Backing(type="int")
+enum ScreenPartStatus {
+    /**
+     * Device cannot differentiate an original screen from a replaced screen.
+     */
+    UNSUPPORTED = 0,
+    /**
+     * Device has the original screen it was manufactured with.
+     */
+    ORIGINAL = 1,
+    /**
+     * Device has a replaced screen.
+     */
+    REPLACED = 2,
+}
diff --git a/graphics/composer/aidl/vts/Android.bp b/graphics/composer/aidl/vts/Android.bp
index 894ca52..61c2593 100644
--- a/graphics/composer/aidl/vts/Android.bp
+++ b/graphics/composer/aidl/vts/Android.bp
@@ -71,6 +71,7 @@
         "libarect",
         "libbase",
         "libfmq",
+        "libgmock",
         "libgtest",
         "libmath",
         "librenderengine",
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
index 8006523..354e3e0 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -29,6 +29,7 @@
 #include <android/hardware/graphics/composer3/ComposerClientWriter.h>
 #include <binder/ProcessState.h>
 #include <cutils/ashmem.h>
+#include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <ui/Fence.h>
 #include <ui/GraphicBuffer.h>
@@ -47,6 +48,8 @@
 #undef LOG_TAG
 #define LOG_TAG "VtsHalGraphicsComposer3_TargetTest"
 
+using testing::Ge;
+
 namespace aidl::android::hardware::graphics::composer3::vts {
 
 using namespace std::chrono_literals;
@@ -1265,6 +1268,16 @@
         EXPECT_TRUE(status.isOk());
         EXPECT_FALSE(displayConfigurations.empty());
 
+        const bool areAllModesARR =
+                std::all_of(displayConfigurations.cbegin(), displayConfigurations.cend(),
+                            [](const auto& config) { return config.vrrConfig.has_value(); });
+
+        const bool areAllModesMRR =
+                std::all_of(displayConfigurations.cbegin(), displayConfigurations.cend(),
+                            [](const auto& config) { return !config.vrrConfig.has_value(); });
+
+        EXPECT_TRUE(areAllModesARR || areAllModesMRR) << "Mixing MRR and ARR modes is not allowed";
+
         for (const auto& displayConfig : displayConfigurations) {
             EXPECT_NE(-1, displayConfig.width);
             EXPECT_NE(-1, displayConfig.height);
@@ -1399,14 +1412,6 @@
     }
 }
 
-TEST_P(GraphicsComposerAidlV3Test, GetMaxLayerPictureProfiles) {
-    for (const auto& display : mDisplays) {
-        const auto& [status, maxPorfiles] =
-                mComposerClient->getMaxLayerPictureProfiles(display.getDisplayId());
-        EXPECT_TRUE(status.isOk());
-    }
-}
-
 // Tests for Command.
 class GraphicsComposerAidlCommandTest : public GraphicsComposerAidlTest {
   protected:
@@ -3239,19 +3244,44 @@
     });
 }
 
-TEST_P(GraphicsComposerAidlCommandV3Test, getMaxLayerPictureProfiles_success) {
+class GraphicsComposerAidlCommandV4Test : public GraphicsComposerAidlCommandTest {
+  protected:
+    void SetUp() override {
+        GraphicsComposerAidlTest::SetUp();
+        if (getInterfaceVersion() <= 3) {
+            GTEST_SKIP() << "Device interface version is expected to be >= 4";
+        }
+    }
+};
+
+TEST_P(GraphicsComposerAidlCommandV4Test, getMaxLayerPictureProfiles_success) {
     for (auto& display : mDisplays) {
         int64_t displayId = display.getDisplayId();
         if (!hasDisplayCapability(displayId, DisplayCapability::PICTURE_PROCESSING)) {
             continue;
         }
         const auto& [status, maxProfiles] =
-                mComposerClient->getMaxLayerPictureProfiles(getPrimaryDisplayId());
+                mComposerClient->getMaxLayerPictureProfiles(displayId);
         EXPECT_TRUE(status.isOk());
+        EXPECT_THAT(maxProfiles, Ge(0));
     }
 }
 
-TEST_P(GraphicsComposerAidlCommandV3Test, setDisplayPictureProfileId_success) {
+TEST_P(GraphicsComposerAidlCommandV4Test, getMaxLayerPictureProfiles_unsupported) {
+    for (auto& display : mDisplays) {
+        int64_t displayId = display.getDisplayId();
+        if (hasDisplayCapability(displayId, DisplayCapability::PICTURE_PROCESSING)) {
+            continue;
+        }
+        const auto& [status, maxProfiles] =
+                mComposerClient->getMaxLayerPictureProfiles(displayId);
+        EXPECT_FALSE(status.isOk());
+        EXPECT_NO_FATAL_FAILURE(
+                assertServiceSpecificError(status, IComposerClient::EX_UNSUPPORTED));
+    }
+}
+
+TEST_P(GraphicsComposerAidlCommandV4Test, setDisplayPictureProfileId_success) {
     for (auto& display : mDisplays) {
         int64_t displayId = display.getDisplayId();
         if (!hasDisplayCapability(displayId, DisplayCapability::PICTURE_PROCESSING)) {
@@ -3262,7 +3292,7 @@
         const auto layer = createOnScreenLayer(display);
         const auto buffer = allocate(::android::PIXEL_FORMAT_RGBA_8888);
         ASSERT_NE(nullptr, buffer->handle);
-        // TODO(b/337330263): Lookup profile IDs from PictureProfileService
+        // TODO(b/337330263): Lookup profile IDs from MediaQualityManager
         writer.setDisplayPictureProfileId(displayId, PictureProfileId(1));
         writer.setLayerBuffer(displayId, layer, /*slot*/ 0, buffer->handle,
                               /*acquireFence*/ -1);
@@ -3271,7 +3301,7 @@
     }
 }
 
-TEST_P(GraphicsComposerAidlCommandV3Test, setLayerPictureProfileId_success) {
+TEST_P(GraphicsComposerAidlCommandV4Test, setLayerPictureProfileId_success) {
     for (auto& display : mDisplays) {
         int64_t displayId = display.getDisplayId();
         if (!hasDisplayCapability(displayId, DisplayCapability::PICTURE_PROCESSING)) {
@@ -3289,14 +3319,14 @@
         ASSERT_NE(nullptr, buffer->handle);
         writer.setLayerBuffer(displayId, layer, /*slot*/ 0, buffer->handle,
                               /*acquireFence*/ -1);
-        // TODO(b/337330263): Lookup profile IDs from PictureProfileService
+        // TODO(b/337330263): Lookup profile IDs from MediaQualityManager
         writer.setLayerPictureProfileId(displayId, layer, PictureProfileId(1));
         execute();
         ASSERT_TRUE(mReader.takeErrors().empty());
     }
 }
 
-TEST_P(GraphicsComposerAidlCommandV3Test, setLayerPictureProfileId_failsWithTooManyProfiles) {
+TEST_P(GraphicsComposerAidlCommandV4Test, setLayerPictureProfileId_failsWithTooManyProfiles) {
     for (auto& display : mDisplays) {
         int64_t displayId = display.getDisplayId();
         if (!hasDisplayCapability(displayId, DisplayCapability::PICTURE_PROCESSING)) {
@@ -3315,7 +3345,7 @@
             ASSERT_NE(nullptr, buffer->handle);
             writer.setLayerBuffer(displayId, layer, /*slot*/ 0, buffer->handle,
                                   /*acquireFence*/ -1);
-            // TODO(b/337330263): Lookup profile IDs from PictureProfileService
+            // TODO(b/337330263): Lookup profile IDs from MediaQualityManager
             writer.setLayerPictureProfileId(displayId, layer, PictureProfileId(profileId));
         }
         execute();
@@ -3325,16 +3355,6 @@
     }
 }
 
-class GraphicsComposerAidlCommandV4Test : public GraphicsComposerAidlCommandTest {
-  protected:
-    void SetUp() override {
-        GraphicsComposerAidlTest::SetUp();
-        if (getInterfaceVersion() <= 3) {
-            GTEST_SKIP() << "Device interface version is expected to be >= 4";
-        }
-    }
-};
-
 TEST_P(GraphicsComposerAidlCommandV4Test, SetUnsupportedLayerLuts) {
     auto& writer = getWriter(getPrimaryDisplayId());
     const auto& [layerStatus, layer] =
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CompositionData.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CompositionData.aidl
new file mode 100644
index 0000000..9ab4818
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CompositionData.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.power;
+@VintfStability
+parcelable CompositionData {
+  long timestampNanos;
+  long[] scheduledPresentTimestampsNanos;
+  long latchTimestampNanos;
+  android.hardware.power.FrameProducer[] producers;
+  @nullable android.hardware.power.CompositionUpdate updateData;
+  long[] outputIds;
+}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CompositionUpdate.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CompositionUpdate.aidl
new file mode 100644
index 0000000..a0c4b21
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CompositionUpdate.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.power;
+@VintfStability
+parcelable CompositionUpdate {
+  long timestampNanos;
+  android.hardware.power.FrameProducerUpdate[] producerUpdates;
+  long[] deadOutputIds;
+}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CpuHeadroomParams.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CpuHeadroomParams.aidl
index 09a2ace..de92105 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CpuHeadroomParams.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CpuHeadroomParams.aidl
@@ -34,9 +34,10 @@
 package android.hardware.power;
 @JavaDerive(equals=true, toString=true) @VintfStability
 parcelable CpuHeadroomParams {
-  android.hardware.power.CpuHeadroomParams.CalculationType calculationType;
-  android.hardware.power.CpuHeadroomParams.SelectionType selectionType;
-  int pid;
+  android.hardware.power.CpuHeadroomParams.CalculationType calculationType = android.hardware.power.CpuHeadroomParams.CalculationType.MIN;
+  int calculationWindowMillis = 1000;
+  android.hardware.power.CpuHeadroomParams.SelectionType selectionType = android.hardware.power.CpuHeadroomParams.SelectionType.ALL;
+  int[] tids;
   enum CalculationType {
     MIN,
     AVERAGE,
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CpuHeadroomResult.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CpuHeadroomResult.aidl
new file mode 100644
index 0000000..9303906
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CpuHeadroomResult.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.power;
+@JavaDerive(equals=true, toString=true) @VintfStability
+union CpuHeadroomResult {
+  float globalHeadroom;
+  float[] perCoreHeadroom;
+}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/FrameProducer.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/FrameProducer.aidl
new file mode 100644
index 0000000..0d9084b
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/FrameProducer.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.power;
+@VintfStability
+parcelable FrameProducer {
+  long producerId;
+  int uid;
+  double fps;
+  @nullable android.hardware.power.LatchedFrameData currentlyLatchedFrame;
+  boolean cpuDeadlineMissed;
+  boolean gpuDeadlineMissed;
+}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/FrameProducerUpdate.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/FrameProducerUpdate.aidl
new file mode 100644
index 0000000..08ea3dc
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/FrameProducerUpdate.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.power;
+@VintfStability
+parcelable FrameProducerUpdate {
+  long producerId;
+  boolean isDead;
+  int[] sessions;
+}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/GpuHeadroomParams.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/GpuHeadroomParams.aidl
index 64bb4a4..6faa938 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/GpuHeadroomParams.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/GpuHeadroomParams.aidl
@@ -34,7 +34,8 @@
 package android.hardware.power;
 @JavaDerive(equals=true, toString=true) @VintfStability
 parcelable GpuHeadroomParams {
-  android.hardware.power.GpuHeadroomParams.CalculationType calculationType;
+  android.hardware.power.GpuHeadroomParams.CalculationType calculationType = android.hardware.power.GpuHeadroomParams.CalculationType.MIN;
+  int calculationWindowMillis = 1000;
   enum CalculationType {
     MIN,
     AVERAGE,
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/GpuHeadroomResult.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/GpuHeadroomResult.aidl
new file mode 100644
index 0000000..bbd3d8b
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/GpuHeadroomResult.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.power;
+@JavaDerive(equals=true, toString=true) @VintfStability
+union GpuHeadroomResult {
+  float globalHeadroom;
+}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl
index 10456cb..9d20ca1 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl
@@ -44,8 +44,10 @@
   android.hardware.power.ChannelConfig getSessionChannel(in int tgid, in int uid);
   oneway void closeSessionChannel(in int tgid, in int uid);
   android.hardware.power.SupportInfo getSupportInfo();
-  float[] getCpuHeadroom(in android.hardware.power.CpuHeadroomParams params);
-  float getGpuHeadroom(in android.hardware.power.GpuHeadroomParams params);
+  android.hardware.power.CpuHeadroomResult getCpuHeadroom(in android.hardware.power.CpuHeadroomParams params);
+  android.hardware.power.GpuHeadroomResult getGpuHeadroom(in android.hardware.power.GpuHeadroomParams params);
   long getCpuHeadroomMinIntervalMillis();
   long getGpuHeadroomMinIntervalMillis();
+  oneway void sendCompositionData(in android.hardware.power.CompositionData[] data);
+  oneway void sendCompositionUpdate(in android.hardware.power.CompositionUpdate update);
 }
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/LatchedFrameData.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/LatchedFrameData.aidl
new file mode 100644
index 0000000..01ce157
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/LatchedFrameData.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.power;
+@VintfStability
+parcelable LatchedFrameData {
+  long frameStartTimestampNanos;
+  long intendedPresentTimestampNanos;
+  long bufferSubmissionTimestampNanos;
+  long gpuSignalTimestampNanos;
+  boolean usedGpu;
+  @nullable ParcelFileDescriptor gpuAcquireFence;
+}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionMode.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionMode.aidl
index ffa790d..448dbb3 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionMode.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionMode.aidl
@@ -36,4 +36,6 @@
 enum SessionMode {
   POWER_EFFICIENCY,
   GRAPHICS_PIPELINE,
+  AUTO_CPU,
+  AUTO_GPU,
 }
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SupportInfo.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SupportInfo.aidl
index 85da2fc..9609169 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SupportInfo.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SupportInfo.aidl
@@ -40,4 +40,12 @@
   long sessionHints;
   long sessionModes;
   long sessionTags;
+  android.hardware.power.SupportInfo.CompositionDataSupportInfo compositionData;
+  @VintfStability
+  parcelable CompositionDataSupportInfo {
+    boolean isSupported;
+    boolean disableGpuFences;
+    int maxBatchSize;
+    boolean alwaysBatch;
+  }
 }
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/WorkDuration.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/WorkDuration.aidl
index 45013dd..25a5350 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/WorkDuration.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/WorkDuration.aidl
@@ -39,4 +39,5 @@
   long workPeriodStartTimestampNanos;
   long cpuDurationNanos;
   long gpuDurationNanos;
+  long intendedPresentTimestampNanos;
 }
diff --git a/power/aidl/android/hardware/power/CompositionData.aidl b/power/aidl/android/hardware/power/CompositionData.aidl
new file mode 100644
index 0000000..43c636f
--- /dev/null
+++ b/power/aidl/android/hardware/power/CompositionData.aidl
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2024 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.hardware.power;
+
+import android.hardware.power.CompositionUpdate;
+import android.hardware.power.FrameProducer;
+
+/**
+ * Object sent to PowerHAL once per frame during commit that contains relevant
+ * timing data for a given set of frame producers, drawing to a given set of outputs.
+ *
+ * This will generally be layer objects drawing to displays, but could also represent
+ * things like arbitrary graphics buffers drawing into network sockets. All frame
+ * producers that participated in this composition and have associated
+ * sessions will be listed under "producers".
+ *
+ * All timestamps use SYSTEM_TIME_MONOTONIC clock, at nanosecond resolution.
+ */
+@VintfStability
+parcelable CompositionData {
+    /**
+     * Timestamp for when the message was sent, useful to combine and correlate
+     * composition data with any reported info from sessions.
+     *
+     * The latchTime can be used alongside this for chronologically
+     * ordering events that happened during latching, such as frame drop.
+     */
+    long timestampNanos;
+
+    /**
+     * Scheduled presentation times for each outputId, corresponding to the outputId
+     * with the same index.
+     */
+    long[] scheduledPresentTimestampsNanos;
+
+    /**
+     * The current frame's latch time for buffers targeting its vsync, this serves
+     * as the effective frame deadline unless the frame latches with GPU unsignaled.
+     */
+    long latchTimestampNanos;
+
+    /**
+     * The set of frame producers that tried to present this vsync on these outputs,
+     * ignoring the ones without associated sessions.
+     */
+    FrameProducer[] producers;
+
+    /**
+     * Optional parcel containing information not bound to a specific frame,
+     * such as lifecycle updates. These updates can be sent along with CompositionData
+     * to minimize additional calls, when appropriate.
+     */
+    @nullable CompositionUpdate updateData;
+
+    /**
+     * A list of IDs corresponding to one or more outputs, such as displays,
+     * that are the intended recipients of this frame composition. Each output
+     * ID is guaranteed to be unique for its lifetime.
+     */
+    long[] outputIds;
+}
diff --git a/power/aidl/android/hardware/power/CompositionUpdate.aidl b/power/aidl/android/hardware/power/CompositionUpdate.aidl
new file mode 100644
index 0000000..7cd451c
--- /dev/null
+++ b/power/aidl/android/hardware/power/CompositionUpdate.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 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.hardware.power;
+
+import android.hardware.power.FrameProducerUpdate;
+
+/**
+ * An update regarding composition objects that might be sent outside of a normal
+ * sendCompositionData call, such as for lifecycle updates. This object is either
+ * attached to CompositionData or sent separately, depending on current activity
+ * and urgency.
+ */
+@VintfStability
+parcelable CompositionUpdate {
+    /**
+     * Timestamp for when the message was sent.
+     */
+    long timestampNanos;
+
+    /**
+     * Update objects for all frame producers that have changed.
+     */
+    FrameProducerUpdate[] producerUpdates;
+
+    /**
+     * The IDs of any outputs that have disconnected in the framework.
+     */
+    long[] deadOutputIds;
+}
diff --git a/power/aidl/android/hardware/power/CpuHeadroomParams.aidl b/power/aidl/android/hardware/power/CpuHeadroomParams.aidl
index cf71b67..64c7b44 100644
--- a/power/aidl/android/hardware/power/CpuHeadroomParams.aidl
+++ b/power/aidl/android/hardware/power/CpuHeadroomParams.aidl
@@ -32,7 +32,14 @@
     /**
      * The calculation type.
      */
-    CalculationType calculationType;
+    CalculationType calculationType = CalculationType.MIN;
+
+    /**
+     * The calculation rolling window size in milliseconds.
+     * The device should support a superset of [50, 10000] and try to use the closest feasible
+     * window size to the provided value param.
+     */
+    int calculationWindowMillis = 1000;
 
     /**
      * Defines how to select the CPU.
@@ -47,16 +54,17 @@
     /**
      * The CPU selection type.
      */
-    SelectionType selectionType;
+    SelectionType selectionType = SelectionType.ALL;
 
     /**
-     * The caller thread's PID.
+     * The thread TIDs to track.
      *
-     * If pid is positive, return the headroom only for cores that are available
-     * to the given pid, otherwise return the headroom(s) for all cores.
+     * If tids are not-empty, return the headrooms only for cores that are available
+     * to the given tids, otherwise return the headroom(s) for all cores.
      *
-     * This should handle all the cases including but not limited to thread core
-     * affinity and app cpuset that change the available CPU cores for the caller.
+     * This should handle all the cases including but not limited to core affinity and app cpuset
+     * that change the available CPU cores for the caller. And the HAL should check that the TIDs
+     * have the same core affinity.
      */
-    int pid;
+    int[] tids;
 }
diff --git a/power/aidl/android/hardware/power/CpuHeadroomResult.aidl b/power/aidl/android/hardware/power/CpuHeadroomResult.aidl
new file mode 100644
index 0000000..316d5f6
--- /dev/null
+++ b/power/aidl/android/hardware/power/CpuHeadroomResult.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 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.hardware.power;
+
+/**
+ * Headroom value result depending on the request params.
+ *
+ * Each value is ranged from [0, 100], where 0 indicates no CPU resources were left
+ * during the calculation interval and the app may expect low resources to be granted.
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+union CpuHeadroomResult {
+    /**
+     * If ALL selection type is requested.
+     */
+    float globalHeadroom;
+    /**
+     * If PER_CORE selection type is requested.
+     */
+    float[] perCoreHeadroom;
+}
diff --git a/power/aidl/android/hardware/power/FrameProducer.aidl b/power/aidl/android/hardware/power/FrameProducer.aidl
new file mode 100644
index 0000000..9ff77d3
--- /dev/null
+++ b/power/aidl/android/hardware/power/FrameProducer.aidl
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2024 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.hardware.power;
+
+import android.hardware.power.LatchedFrameData;
+
+/**
+ * Abstract unit of frame production. Frame production could be for outputs
+ * such as layers, sets of layers, serial devices, or a network connection.
+ * Frame producers are associated with one or more sessions that provide timing context
+ * and thread associations for the producer.
+ */
+@VintfStability
+parcelable FrameProducer {
+    /**
+     * ID of the producer, unique per-producer at a given time.
+     */
+    long producerId;
+
+    /**
+     * UID of the process that owns the producer.
+     */
+    int uid;
+
+    /**
+     * The framerate of the producer. This parameter will be set when SF is reasonably
+     * confident it knows what framerate of the frame producer is, and will
+     * be set to -1 in cases where SF is not sure, or it's rapidly changing.
+     */
+    double fps;
+
+    /**
+     * Info for the currently latching frame on this producer,
+     * this value will be null if the producer tried but failed to latch.
+     */
+    @nullable LatchedFrameData currentlyLatchedFrame;
+
+    /**
+     * True if SF thinks a frame tried to latch for this producer but failed because the
+     * CPU did not submit a buffer on time; currentlyLatchedFrame is null if this is true.
+     */
+    boolean cpuDeadlineMissed;
+
+    /**
+     * True if SF thinks a frame tried to latch for this producer, but failed because the
+     * GPU did not finish on time; currentlyLatchedFrame is null if this is true.
+     */
+    boolean gpuDeadlineMissed;
+}
diff --git a/power/aidl/android/hardware/power/FrameProducerUpdate.aidl b/power/aidl/android/hardware/power/FrameProducerUpdate.aidl
new file mode 100644
index 0000000..3075a8e
--- /dev/null
+++ b/power/aidl/android/hardware/power/FrameProducerUpdate.aidl
@@ -0,0 +1,45 @@
+
+/*
+ * Copyright (C) 2024 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.hardware.power;
+
+/**
+ * A single update for an individual producer object.
+ */
+@VintfStability
+parcelable FrameProducerUpdate {
+    /**
+     * The ID of the producer, guaranteed to be unique at a given time.
+     */
+    long producerId;
+
+    /**
+     * If true, this producer is no longer active and its data can be released.
+     * "sessions" will be blank in this case, as there are no more associations
+     * with this producer.
+     */
+    boolean isDead;
+
+    /**
+     * The IDs of all sessions associated with the producer, corresponding to the
+     * ID in SessionConfig returned to the framework during session creation.
+     *
+     * If an object was created without a Session ID by using an older creation
+     * method, it is not eligible to be associated to a FrameProducer.
+     */
+    int[] sessions;
+}
diff --git a/power/aidl/android/hardware/power/GpuHeadroomParams.aidl b/power/aidl/android/hardware/power/GpuHeadroomParams.aidl
index 972adbc..68848d8 100644
--- a/power/aidl/android/hardware/power/GpuHeadroomParams.aidl
+++ b/power/aidl/android/hardware/power/GpuHeadroomParams.aidl
@@ -32,5 +32,11 @@
     /**
      * The calculation type.
      */
-    CalculationType calculationType;
+    CalculationType calculationType = CalculationType.MIN;
+
+    /**
+     * The device should support a superset of [50, 10000] and try to use the closest feasible
+     * window size to the provided value param.
+     */
+    int calculationWindowMillis = 1000;
 }
diff --git a/power/aidl/android/hardware/power/GpuHeadroomResult.aidl b/power/aidl/android/hardware/power/GpuHeadroomResult.aidl
new file mode 100644
index 0000000..ef3257d
--- /dev/null
+++ b/power/aidl/android/hardware/power/GpuHeadroomResult.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 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.hardware.power;
+
+/**
+ * Headroom value result depending on the request params.
+ *
+ * Each value is ranged from [0, 100], where 0 indicates no GPU resources were left
+ * during the calculation interval and the app may expect low resources to be granted.
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+union GpuHeadroomResult {
+    float globalHeadroom;
+}
diff --git a/power/aidl/android/hardware/power/IPower.aidl b/power/aidl/android/hardware/power/IPower.aidl
index e2f121c..41a9379 100644
--- a/power/aidl/android/hardware/power/IPower.aidl
+++ b/power/aidl/android/hardware/power/IPower.aidl
@@ -18,8 +18,12 @@
 
 import android.hardware.power.Boost;
 import android.hardware.power.ChannelConfig;
+import android.hardware.power.CompositionData;
+import android.hardware.power.CompositionUpdate;
 import android.hardware.power.CpuHeadroomParams;
+import android.hardware.power.CpuHeadroomResult;
 import android.hardware.power.GpuHeadroomParams;
+import android.hardware.power.GpuHeadroomResult;
 import android.hardware.power.IPowerHintSession;
 import android.hardware.power.Mode;
 import android.hardware.power.SessionConfig;
@@ -152,9 +156,7 @@
      * Called to get detailed information on the support status of various PowerHAL
      * features, such as hint sessions and specific boosts.
      *
-     * @return  a SupportInfo giving detailed support information, or
-     *          EX_UNSUPPORTED_OPERATION if detailed support checking is itself
-     *          not supported.
+     * @return  a SupportInfo giving detailed support information.
      */
     SupportInfo getSupportInfo();
 
@@ -162,24 +164,21 @@
      * Provides an estimate of available CPU headroom the device based on past history.
      * <p>
      * @param params params to customize the CPU headroom calculation
-     * @return a single value or an array of values depending on selection type of params.
-     *         Each value is ranged from [0, 100], and 0 indicates no CPU resources were left
-     *         during the calculation interval and the app may expect low resources to be granted.
      * @throws EX_UNSUPPORTED_OPERATION if the API is unsupported or the request params can't be
      *         served.
+     * @throws EX_SECURITY if the TIDs passed in do not belong to the same process.
+     * @throws EX_ILLEGAL_STATE if the TIDs passed in do not have the same core affinity setting.
      */
-    float[] getCpuHeadroom(in CpuHeadroomParams params);
+    CpuHeadroomResult getCpuHeadroom(in CpuHeadroomParams params);
 
     /**
      * Provides an estimate of available GPU headroom the device based on past history.
      * <p>
      * @param params params to customize the GPU headroom calculation
-     * @return Value is ranged from [0, 100], and 0 indicates no GPU resources were left
-     *         during the calculation interval and the app may expect low resources to be granted.
      * @throws EX_UNSUPPORTED_OPERATION if the API is unsupported or the request params can't be
      *         served.
      */
-    float getGpuHeadroom(in GpuHeadroomParams params);
+    GpuHeadroomResult getGpuHeadroom(in GpuHeadroomParams params);
 
     /**
      * Minimum polling interval for calling getCpuHeadroom in milliseconds.
@@ -200,4 +199,22 @@
      * @throws EX_UNSUPPORTED_OPERATION if the API is unsupported.
      */
     long getGpuHeadroomMinIntervalMillis();
+
+    /**
+     * Sent to PowerHAL when there are surface-attached sessions being composed,
+     * providing FPS and frame timing data that can be used to supplement
+     * and validate timing sent via reportActual. This call can be batched,
+     * especially in the case of a steady state or low-intensity workload.
+     *
+     * @param   data The aggregated composition data object.
+     */
+    oneway void sendCompositionData(in CompositionData[] data);
+
+    /**
+     * Sent to inform the HAL about important updates outside of the normal
+     * reporting cycle, such as lifecycle updates for displays or FrameProducers.
+     *
+     * @param   update The aggregated composition update object.
+     */
+    oneway void sendCompositionUpdate(in CompositionUpdate update);
 }
diff --git a/power/aidl/android/hardware/power/LatchedFrameData.aidl b/power/aidl/android/hardware/power/LatchedFrameData.aidl
new file mode 100644
index 0000000..0642669
--- /dev/null
+++ b/power/aidl/android/hardware/power/LatchedFrameData.aidl
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2024 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.hardware.power;
+
+/**
+ * Frame information for a specific frame producer on a specific composition, used to
+ * provide timing information and adjust boosting or scheduling strategies for sessions
+ * associated with that producer to compensate for observed behavior.
+ *
+ * All timestamps use SYSTEM_TIME_MONOTONIC clock, at nanosecond resolution.
+ */
+@VintfStability
+parcelable LatchedFrameData {
+    /**
+     * Timestamp for the start of this frame, will be set to -1 if unknown.
+     */
+    long frameStartTimestampNanos;
+
+    /**
+     * Original, intended presentation time of the frame.
+     *
+     * This can be used along with the buffer submission timestamp to infer
+     * if the frame was supposed to present during a previous composition and got delayed.
+     *
+     * It can be compared with the "intendedPresentTimestampNanos" on WorkDurations to
+     * determine which reported duration sessions correspond with which LatchedFrameData,
+     * for sessions that use both manual reporting and have associated FrameProducers
+     */
+    long intendedPresentTimestampNanos;
+
+    /**
+     * Timestamp of buffer submission to SF from the CPU.
+     */
+    long bufferSubmissionTimestampNanos;
+
+    /**
+     * Timestamp where the GPU fence signaled, will be set to -1 if the buffer
+     * latched unsignaled or if the GPU was not used.
+     */
+    long gpuSignalTimestampNanos;
+
+    /**
+     * True if this frame used the GPU for rendering.
+     */
+    boolean usedGpu;
+
+    /**
+     * Optional GPU fence, sent only when the buffer latches unsignaled, and if
+     * sending fences is configured on the device in SupportInfo. If the updates
+     * are batched, a fence will only be sent for the most recent update.
+     *
+     * Can be used to get accurate gpu completion timestamps, and to boost if it
+     * looks like a frame might not signal before the deadline.
+     */
+    @nullable ParcelFileDescriptor gpuAcquireFence;
+}
diff --git a/power/aidl/android/hardware/power/SessionMode.aidl b/power/aidl/android/hardware/power/SessionMode.aidl
index 3d5a76f..5bd0e15 100644
--- a/power/aidl/android/hardware/power/SessionMode.aidl
+++ b/power/aidl/android/hardware/power/SessionMode.aidl
@@ -32,4 +32,20 @@
      * which will be called of higher priority in terms of CPU resources and scheduling.
      */
     GRAPHICS_PIPELINE,
+
+    /**
+     * This mode indicates that the session does not intend to report CPU timing
+     * information, and that it instead will rely entirely on information from
+     * SurfaceFlinger. This mode is only supported for sessions that have
+     * GRAPHICS_PIPELINE enabled.
+     */
+    AUTO_CPU,
+
+    /**
+     * This mode indicates that the session does not intend to report GPU timing
+     * information, and that it instead will rely entirely on information from
+     * SurfaceFlinger. This mode is only supported for sessions that have
+     * GRAPHICS_PIPELINE enabled.
+     */
+    AUTO_GPU,
 }
diff --git a/power/aidl/android/hardware/power/SupportInfo.aidl b/power/aidl/android/hardware/power/SupportInfo.aidl
index 46bcdd3..4178b3a 100644
--- a/power/aidl/android/hardware/power/SupportInfo.aidl
+++ b/power/aidl/android/hardware/power/SupportInfo.aidl
@@ -37,37 +37,73 @@
 @VintfStability
 parcelable SupportInfo {
     /**
-     * Boolean representing whether hint sessions are supported on this device
+     * Boolean representing whether hint sessions are supported on this device.
      */
     boolean usesSessions;
 
     /**
-     * The set of "Boost" enum values that are supported by this device
-     * Each bit should correspond to a value of the "Boost.aidl" enum
+     * The set of "Boost" enum values that are supported by this device,
+     * each bit should correspond to a value of the "Boost.aidl" enum.
      */
     long boosts;
 
     /**
-     * The set of "Mode" enum values that are supported by this device
-     * Each bit should correspond to a value of the "Mode.aidl" enum
+     * The set of "Mode" enum values that are supported by this device,
+     * each bit should correspond to a value of the "Mode.aidl" enum.
      */
     long modes;
 
     /**
-     * The set of "SessionHint" enum values that are supported by this device
-     * Each bit should correspond to a value of the "SessionHint.aidl" enum
+     * The set of "SessionHint" enum values that are supported by this device,
+     * each bit should correspond to a value of the "SessionHint.aidl" enum.
      */
     long sessionHints;
 
     /**
-     * The set of "SessionMode" enum values that are supported by this device
-     * Each bit should correspond to a value of the "SessionMode.aidl" enum
+     * The set of "SessionMode" enum values that are supported by this device,
+     * each bit should correspond to a value of the "SessionMode.aidl" enum.
      */
     long sessionModes;
 
     /**
-     * The set of "SessionTag" enum values that are supported by this device
-     * Each bit should correspond to a value of the "SessionTag.aidl" enum
+     * The set of "SessionTag" enum values that are supported by this device,
+     * each bit should correspond to a value of the "SessionTag.aidl" enum.
      */
     long sessionTags;
+
+    /**
+     * Parcel detailing support info for receiving additional frame composition
+     * data when sessions are associated with frame producers.
+     */
+    CompositionDataSupportInfo compositionData;
+
+    @VintfStability
+    parcelable CompositionDataSupportInfo {
+        /**
+         * Whether the sendCompositionData and sendCompositionUpdate APIs are
+         * supported on this device. The rest of the fields on this parcelable
+         * are ignored if this is false.
+         */
+        boolean isSupported;
+
+        /**
+         * Whether to disable sending relevant GPU fence file descriptors along with
+         * timing information when the frame callback happens.
+         */
+        boolean disableGpuFences;
+
+        /**
+         * The maximum number of updates to batch before sending. This can be ignored
+         * if "overrideIfUrgent" is set. Setting to a value less than or equal to 1
+         * disables batching entirely.
+         */
+        int maxBatchSize;
+
+        /**
+         * Whether to ignore important notifications such as FPS changes and frame
+         * deadline misses, and always send maximum size batches. By default, the
+         * framework will send batches early if these important events happen.
+         */
+        boolean alwaysBatch;
+    }
 }
diff --git a/power/aidl/android/hardware/power/WorkDuration.aidl b/power/aidl/android/hardware/power/WorkDuration.aidl
index fcd638b..bcf279a 100644
--- a/power/aidl/android/hardware/power/WorkDuration.aidl
+++ b/power/aidl/android/hardware/power/WorkDuration.aidl
@@ -19,7 +19,7 @@
 @VintfStability
 parcelable WorkDuration {
     /**
-     * Time stamp in nanoseconds based on CLOCK_MONOTONIC when the duration
+     * Timestamp in nanoseconds based on CLOCK_MONOTONIC when the duration
      * sample was measured.
      */
     long timeStampNanos;
@@ -49,4 +49,21 @@
      * SDK/NDK reportActualWorkDuration API.
      */
     long gpuDurationNanos;
+
+    /**
+     * Timestamp indicating the approximate time when this frame is intended to
+     * present by the app, and will be required for all sessions associated with
+     * frame producers. This should always be provided if the session is associated
+     * with a pipeline, even if it is not using the GRAPHICS_PIPELINE mode.
+     *
+     * This timestamp is intended to be used for correlating CompositionData timing
+     * information with reported WorkDurations from apps. WorkDurations for
+     * sessions associated with a frame producers, without a reasonable value set
+     * for this field should be discarded.
+     *
+     * Intended vsync times can be inferred or retrieved from Choreographer callbacks.
+     * While this timestamp is not required to be perfectly accurate, it should
+     * roughly correspond with an expected vsync time, and should be discarded otherwise.
+     */
+    long intendedPresentTimestampNanos;
 }
diff --git a/power/aidl/default/Power.cpp b/power/aidl/default/Power.cpp
index 1fc0a0a..8490b62 100644
--- a/power/aidl/default/Power.cpp
+++ b/power/aidl/default/Power.cpp
@@ -33,6 +33,8 @@
 using ::aidl::android::hardware::common::fmq::MQDescriptor;
 using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
 using ::aidl::android::hardware::power::ChannelMessage;
+using ::aidl::android::hardware::power::CompositionData;
+using ::aidl::android::hardware::power::CompositionUpdate;
 using ::android::AidlMessageQueue;
 
 using ndk::ScopedAStatus;
@@ -69,14 +71,22 @@
     return ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Power::getCpuHeadroom(const CpuHeadroomParams& _,
-                                         std::vector<float>* _aidl_return) {
-    *_aidl_return = {0.5f};
-    return ndk::ScopedAStatus::ok();
+ndk::ScopedAStatus Power::getCpuHeadroom(const CpuHeadroomParams& params,
+                                         CpuHeadroomResult* _aidl_return) {
+    if (params.selectionType == CpuHeadroomParams::SelectionType::ALL) {
+        _aidl_return->set<CpuHeadroomResult::globalHeadroom>(100.0f);
+        return ndk::ScopedAStatus::ok();
+    } else if (params.selectionType == CpuHeadroomParams::SelectionType::PER_CORE) {
+        std::vector<float> headroom = {50.0f, 100.0f};
+        _aidl_return->set<CpuHeadroomResult::perCoreHeadroom>(headroom);
+        return ndk::ScopedAStatus::ok();
+    }
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
 }
 
-ndk::ScopedAStatus Power::getGpuHeadroom(const GpuHeadroomParams& _, float* _aidl_return) {
-    *_aidl_return = 0.5f;
+ndk::ScopedAStatus Power::getGpuHeadroom(const GpuHeadroomParams& _,
+                                         GpuHeadroomResult* _aidl_return) {
+    _aidl_return->set<GpuHeadroomResult::globalHeadroom>(100.0f);
     return ndk::ScopedAStatus::ok();
 }
 
@@ -142,19 +152,33 @@
 }
 
 ndk::ScopedAStatus Power::getSupportInfo(SupportInfo* _aidl_return) {
-    static SupportInfo supportInfo = {
-            .usesSessions = false,
-            .modes = bitsForEnum<Mode>(),
-            .boosts = bitsForEnum<Boost>(),
-            .sessionHints = 0,
-            .sessionModes = 0,
-            .sessionTags = 0,
-    };
+    static SupportInfo supportInfo = {.usesSessions = false,
+                                      .modes = bitsForEnum<Mode>(),
+                                      .boosts = bitsForEnum<Boost>(),
+                                      .sessionHints = 0,
+                                      .sessionModes = 0,
+                                      .sessionTags = 0,
+                                      .compositionData = {
+                                              .isSupported = false,
+                                              .disableGpuFences = false,
+                                              .maxBatchSize = 1,
+                                              .alwaysBatch = false,
+                                      }};
     // Copy the support object into the binder
     *_aidl_return = supportInfo;
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus Power::sendCompositionData(const std::vector<CompositionData>&) {
+    LOG(INFO) << "Composition data received!";
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Power::sendCompositionUpdate(const CompositionUpdate&) {
+    LOG(INFO) << "Composition update received!";
+    return ndk::ScopedAStatus::ok();
+}
+
 }  // namespace example
 }  // namespace impl
 }  // namespace power
diff --git a/power/aidl/default/Power.h b/power/aidl/default/Power.h
index a77a514..c4aa7ab 100644
--- a/power/aidl/default/Power.h
+++ b/power/aidl/default/Power.h
@@ -46,11 +46,14 @@
     ndk::ScopedAStatus closeSessionChannel(int32_t tgid, int32_t uid) override;
     ndk::ScopedAStatus getSupportInfo(SupportInfo* _aidl_return) override;
     ndk::ScopedAStatus getCpuHeadroom(const CpuHeadroomParams& params,
-                                      std::vector<float>* _aidl_return) override;
+                                      CpuHeadroomResult* _aidl_return) override;
+
     ndk::ScopedAStatus getGpuHeadroom(const GpuHeadroomParams& params,
-                                      float* _aidl_return) override;
+                                      GpuHeadroomResult* _aidl_return) override;
     ndk::ScopedAStatus getCpuHeadroomMinIntervalMillis(int64_t* _aidl_return) override;
     ndk::ScopedAStatus getGpuHeadroomMinIntervalMillis(int64_t* _aidl_return) override;
+    ndk::ScopedAStatus sendCompositionData(const std::vector<CompositionData>& in_data) override;
+    ndk::ScopedAStatus sendCompositionUpdate(const CompositionUpdate& in_update) override;
 
   private:
     std::vector<std::shared_ptr<IPowerHintSession>> mPowerHintSessions;
diff --git a/power/aidl/vts/VtsHalPowerTargetTest.cpp b/power/aidl/vts/VtsHalPowerTargetTest.cpp
index 5e3ddd5..ffe20c6 100644
--- a/power/aidl/vts/VtsHalPowerTargetTest.cpp
+++ b/power/aidl/vts/VtsHalPowerTargetTest.cpp
@@ -36,6 +36,8 @@
 namespace aidl::android::hardware::power {
 namespace {
 
+using namespace std::chrono_literals;
+
 using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
 using ::android::AidlMessageQueue;
 using ::android::hardware::EventFlag;
@@ -43,7 +45,9 @@
 using android::hardware::power::ChannelConfig;
 using android::hardware::power::ChannelMessage;
 using android::hardware::power::CpuHeadroomParams;
+using android::hardware::power::CpuHeadroomResult;
 using android::hardware::power::GpuHeadroomParams;
+using android::hardware::power::GpuHeadroomResult;
 using android::hardware::power::IPower;
 using android::hardware::power::IPowerHintSession;
 using android::hardware::power::Mode;
@@ -137,7 +141,11 @@
         power = IPower::fromBinder(ndk::SpAIBinder(binder));
         auto status = power->getInterfaceVersion(&mServiceVersion);
         ASSERT_TRUE(status.isOk());
-        if (mServiceVersion >= 2) {
+        if (mServiceVersion >= 6) {
+            mSupportInfo = std::make_optional<SupportInfo>();
+            ASSERT_TRUE(power->getSupportInfo(&(*mSupportInfo)).isOk());
+            mSessionSupport = mSupportInfo->usesSessions;
+        } else if (mServiceVersion >= 2) {
             status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &mSession);
             mSessionSupport = status.isOk();
         }
@@ -147,6 +155,7 @@
     int32_t mServiceVersion;
     std::shared_ptr<IPowerHintSession> mSession;
     bool mSessionSupport = false;
+    std::optional<SupportInfo> mSupportInfo = std::nullopt;
 };
 
 class HintSessionAidl : public PowerAidl {
@@ -300,7 +309,7 @@
         GTEST_SKIP() << "DEVICE not launching with Power V6 and beyond.";
     }
     CpuHeadroomParams params;
-    std::vector<float> headroom;
+    CpuHeadroomResult headroom;
     auto ret = power->getCpuHeadroom(params, &headroom);
     if (ret.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
         GTEST_SKIP() << "power->getCpuHeadroom is not supported";
@@ -309,9 +318,9 @@
     int64_t minIntervalMillis;
     ASSERT_TRUE(power->getCpuHeadroomMinIntervalMillis(&minIntervalMillis).isOk());
     ASSERT_GE(minIntervalMillis, 0);
-    ASSERT_GE(headroom.size(), 1);
-    ASSERT_GE(headroom[0], 0.0f);
-    ASSERT_LE(headroom[0], 100.00f);
+    ASSERT_EQ(headroom.getTag(), CpuHeadroomResult::globalHeadroom);
+    ASSERT_GE(headroom.get<CpuHeadroomResult::globalHeadroom>(), 0.0f);
+    ASSERT_LE(headroom.get<CpuHeadroomResult::globalHeadroom>(), 100.00f);
 }
 
 TEST_P(PowerAidl, getGpuHeadroom) {
@@ -319,7 +328,7 @@
         GTEST_SKIP() << "DEVICE not launching with Power V6 and beyond.";
     }
     GpuHeadroomParams params;
-    float headroom;
+    GpuHeadroomResult headroom;
     auto ret = power->getGpuHeadroom(params, &headroom);
     if (ret.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
         GTEST_SKIP() << "power->getGpuHeadroom is not supported";
@@ -328,8 +337,9 @@
     int64_t minIntervalMillis;
     ASSERT_TRUE(power->getGpuHeadroomMinIntervalMillis(&minIntervalMillis).isOk());
     ASSERT_GE(minIntervalMillis, 0);
-    ASSERT_GE(headroom, 0.0f);
-    ASSERT_LE(headroom, 100.00f);
+    ASSERT_EQ(headroom.getTag(), GpuHeadroomResult::globalHeadroom);
+    ASSERT_GE(headroom.get<GpuHeadroomResult::globalHeadroom>(), 0.0f);
+    ASSERT_LE(headroom.get<GpuHeadroomResult::globalHeadroom>(), 100.00f);
 }
 
 // FIXED_PERFORMANCE mode is required for all devices which ship on Android 11
@@ -341,20 +351,49 @@
 }
 
 TEST_P(PowerAidl, hasSupportInfo) {
-    SupportInfo config;
-    ASSERT_TRUE(power->getSupportInfo(&config).isOk());
+    if (mServiceVersion < 6) {
+        GTEST_SKIP() << "DEVICE not launching with Power V6 and beyond.";
+    }
+    ASSERT_TRUE(mSupportInfo.has_value());
     for (Mode mode : kModes) {
         bool supported;
         power->isModeSupported(mode, &supported);
-        ASSERT_EQ(supported, supportFromBitset(config.modes, mode));
+        ASSERT_EQ(supported, supportFromBitset(mSupportInfo->modes, mode));
     }
     for (Boost boost : kBoosts) {
         bool supported;
         power->isBoostSupported(boost, &supported);
-        ASSERT_EQ(supported, supportFromBitset(config.boosts, boost));
+        ASSERT_EQ(supported, supportFromBitset(mSupportInfo->boosts, boost));
     }
 }
 
+TEST_P(PowerAidl, receivesCompositionData) {
+    if (mServiceVersion < 6) {
+        GTEST_SKIP() << "DEVICE not launching with Power V6 and beyond.";
+    }
+    if (mSupportInfo->compositionData.isSupported) {
+        GTEST_SKIP() << "Composition data marked as unsupported.";
+    }
+    // Sending an empty object is fine, we just want to confirm it accepts the tx
+    std::vector<CompositionData> out{};
+    out.emplace_back();
+    auto status = power->sendCompositionData(out);
+    ASSERT_TRUE(status.isOk());
+}
+
+TEST_P(PowerAidl, receivesCompositionUpdate) {
+    if (mServiceVersion < 6) {
+        GTEST_SKIP() << "DEVICE not launching with Power V6 and beyond.";
+    }
+    if (mSupportInfo->compositionData.isSupported) {
+        GTEST_SKIP() << "Composition data marked as unsupported.";
+    }
+
+    CompositionUpdate out{};
+    auto status = power->sendCompositionUpdate(out);
+    ASSERT_TRUE(status.isOk());
+}
+
 TEST_P(HintSessionAidl, createAndCloseHintSession) {
     if (!mSessionSupport) {
         GTEST_SKIP() << "DEVICE not support Hint Session.";
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
index 6ff66e7..4fe3bd9 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
@@ -158,7 +158,7 @@
      *     Failed                     (3),
      * }
      *
-     * # Modules contains version info about APEX modules that have been updated after the last OTA.
+     * # Modules contains version information for APEX modules.
      * # Note that the Modules information is DER-encoded before being hashed, which requires a
      * # specific ordering (lexicographic by encoded value) for the constituent Module entries. This
      * # ensures that the ordering of Module entries is predictable and that the resulting SHA-256
diff --git a/security/see/Android.bp b/security/see/Android.bp
new file mode 100644
index 0000000..ba873e0
--- /dev/null
+++ b/security/see/Android.bp
@@ -0,0 +1,5 @@
+dirgroup {
+    name: "trusty_dirgroup_hardware_interfaces_security_see",
+    dirs: ["."],
+    visibility: ["//trusty/vendor/google/aosp/scripts"],
+}
diff --git a/security/see/OWNERS b/security/see/OWNERS
new file mode 100644
index 0000000..d1a606f
--- /dev/null
+++ b/security/see/OWNERS
@@ -0,0 +1,5 @@
+# include OWNERS from the top level trusty repo
+include trusty:main:/OWNERS
+
+paulcrowley@google.com
+swillden@google.com
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermal.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermal.aidl
index 904496c..3cff780 100644
--- a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermal.aidl
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermal.aidl
@@ -46,4 +46,5 @@
   void unregisterThermalChangedCallback(in android.hardware.thermal.IThermalChangedCallback callback);
   void registerCoolingDeviceChangedCallbackWithType(in android.hardware.thermal.ICoolingDeviceChangedCallback callback, in android.hardware.thermal.CoolingType type);
   void unregisterCoolingDeviceChangedCallback(in android.hardware.thermal.ICoolingDeviceChangedCallback callback);
+  float forecastSkinTemperature(in int forecastSeconds);
 }
diff --git a/thermal/aidl/android/hardware/thermal/IThermal.aidl b/thermal/aidl/android/hardware/thermal/IThermal.aidl
index 4aa4090..87f7637 100644
--- a/thermal/aidl/android/hardware/thermal/IThermal.aidl
+++ b/thermal/aidl/android/hardware/thermal/IThermal.aidl
@@ -225,4 +225,20 @@
      *         getMessage() must be populated with human-readable error message.
      */
     void unregisterCoolingDeviceChangedCallback(in ICoolingDeviceChangedCallback callback);
+
+    /**
+     * Retrieves the forecasted skin temperature in Celsius.
+     *
+     * @param forecastSeconds the number of seconds to forecast the skin temperature, it should
+     *                        at least support superset of [0, 60] seconds range.
+     *
+     * @return forecasted skin temperature in Celsius.
+     *
+     * @throws EX_ILLEGAL_STATE If the Thermal HAL is not initialized successfully
+     * @throws EX_ILLEGAL_ARGUMENT If the provided forecastSeconds is negative
+     * @throws EX_UNSUPPORTED_OPERATION if API is not supported or the forecastSeconds exceeds the
+     *         supported range. And the getMessage() must be populated with human-readable
+     *         error message.
+     */
+    float forecastSkinTemperature(in int forecastSeconds);
 }
diff --git a/thermal/aidl/default/Thermal.cpp b/thermal/aidl/default/Thermal.cpp
index 41d0be8..339e9b8 100644
--- a/thermal/aidl/default/Thermal.cpp
+++ b/thermal/aidl/default/Thermal.cpp
@@ -191,4 +191,9 @@
     }
     return ScopedAStatus::ok();
 }
+
+ndk::ScopedAStatus Thermal::forecastSkinTemperature(int32_t, float*) {
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
 }  // namespace aidl::android::hardware::thermal::impl::example
diff --git a/thermal/aidl/default/Thermal.h b/thermal/aidl/default/Thermal.h
index d3d8874..a4d8b00 100644
--- a/thermal/aidl/default/Thermal.h
+++ b/thermal/aidl/default/Thermal.h
@@ -60,6 +60,8 @@
 
     ndk::ScopedAStatus unregisterCoolingDeviceChangedCallback(
             const std::shared_ptr<ICoolingDeviceChangedCallback>& in_callback) override;
+    ndk::ScopedAStatus forecastSkinTemperature(int32_t forecastSeconds,
+                                               float* _aidl_return) override;
 
   private:
     std::mutex thermal_callback_mutex_;
diff --git a/thermal/aidl/vts/VtsHalThermalTargetTest.cpp b/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
index 066e773..17653b4 100644
--- a/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
+++ b/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
@@ -426,6 +426,23 @@
     }
 }
 
+// Test Thermal->forecastSkinTemperature.
+TEST_P(ThermalAidlTest, ForecastSkinTemperatureTest) {
+    auto apiLevel = ::android::base::GetIntProperty<int32_t>("ro.vendor.api_level", 0);
+    if (apiLevel < 202504) {
+        GTEST_SKIP() << "Skipping test as the vendor level is below 202504: " << apiLevel;
+    }
+    float temperature = 0.0f;
+    ::ndk::ScopedAStatus status = mThermal->forecastSkinTemperature(1, &temperature);
+    if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+        GTEST_SKIP() << "Skipping test as temperature forecast is not supported";
+    }
+    for (int i = 0; i <= 60; i++) {
+        status = mThermal->forecastSkinTemperature(i, &temperature);
+        ASSERT_NE(NAN, temperature);
+    }
+}
+
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ThermalAidlTest);
 INSTANTIATE_TEST_SUITE_P(
         Thermal, ThermalAidlTest,
diff --git a/vibrator/aidl/android/hardware/vibrator/CompositePwleV2.aidl b/vibrator/aidl/android/hardware/vibrator/CompositePwleV2.aidl
index 9662ca0..f0d0970 100644
--- a/vibrator/aidl/android/hardware/vibrator/CompositePwleV2.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/CompositePwleV2.aidl
@@ -21,7 +21,11 @@
 @VintfStability
 parcelable CompositePwleV2 {
     /**
-     * An array of primitives that represents the PWLE effect
+     * Represents a PWLE (Piecewise-Linear Envelope) effect as an array of primitives.
+     *
+     * A PWLE effect defines a vibration waveform using amplitude and frequency points.
+     * The envelope linearly interpolates both amplitude and frequency between consecutive points,
+     * creating smooth transitions in the vibration pattern.
      */
     PwleV2Primitive[] pwlePrimitives;
 }
diff --git a/vibrator/aidl/android/hardware/vibrator/FrequencyAccelerationMapEntry.aidl b/vibrator/aidl/android/hardware/vibrator/FrequencyAccelerationMapEntry.aidl
index 470dc80..013ae84 100644
--- a/vibrator/aidl/android/hardware/vibrator/FrequencyAccelerationMapEntry.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/FrequencyAccelerationMapEntry.aidl
@@ -29,7 +29,7 @@
      *
      * This value represents the maximum safe output acceleration (in Gs) achievable at the
      * specified frequency, typically determined during calibration. The actual output acceleration
-     * is assumed to scale linearly with the input amplitude within the range of [0, 1].
+     * should scale linearly based on the 'amplitude' input value.
      */
     float maxOutputAccelerationGs;
 }
diff --git a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
index a2f0017..81d7948 100644
--- a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
@@ -472,7 +472,11 @@
     int getPwleV2PrimitiveDurationMinMillis();
 
     /**
-     * Play composed sequence of chirps with optional callback upon completion.
+     * Play composed sequence of PWLEs with optional callback upon completion.
+     *
+     * A PWLE (Piecewise-Linear Envelope) effect defines a vibration waveform using amplitude and
+     * frequency points. The envelope linearly interpolates both amplitude and frequency between
+     * consecutive points, creating smooth transitions in the vibration pattern.
      *
      * This may not be supported and this support is reflected in
      * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS_V2).
diff --git a/vibrator/aidl/default/VibrationSession.cpp b/vibrator/aidl/default/VibrationSession.cpp
index cfb6608..4eac831 100644
--- a/vibrator/aidl/default/VibrationSession.cpp
+++ b/vibrator/aidl/default/VibrationSession.cpp
@@ -24,7 +24,7 @@
 namespace hardware {
 namespace vibrator {
 
-static constexpr int32_t SESSION_END_DELAY_MS = 50;
+static constexpr int32_t SESSION_END_DELAY_MS = 20;
 
 ndk::ScopedAStatus VibrationSession::close() {
     LOG(VERBOSE) << "Vibration Session close";
diff --git a/wifi/aidl/default/aidl_callback_util.h b/wifi/aidl/default/aidl_callback_util.h
index 2419db9..d077683 100644
--- a/wifi/aidl/default/aidl_callback_util.h
+++ b/wifi/aidl/default/aidl_callback_util.h
@@ -26,6 +26,7 @@
 namespace {
 std::unordered_map<void* /* callback */, void* /* handler */> callback_handler_map_;
 std::mutex callback_handler_lock_;
+int32_t min_callback_version_ = INT_MAX;
 }
 
 namespace aidl {
@@ -50,6 +51,13 @@
             return false;
         }
 
+        // Callback interface version indicates which methods are available
+        int callbackVersion = getCallbackInterfaceVersion(cb);
+        if (callbackVersion < min_callback_version_) {
+            LOG(INFO) << "Setting min callback version to " << callbackVersion;
+            min_callback_version_ = callbackVersion;
+        }
+
         std::unique_lock<std::mutex> lk(callback_handler_lock_);
         void* cbPtr = reinterpret_cast<void*>(cb->asBinder().get());
         const auto& cbPosition = findCbInSet(cbPtr);
@@ -111,6 +119,8 @@
         // unique_lock unlocked here
     }
 
+    int32_t getMinCallbackVersion() { return min_callback_version_; }
+
   private:
     std::set<std::shared_ptr<CallbackType>> cb_set_;
     AIBinder_DeathRecipient* death_handler_;
@@ -145,6 +155,15 @@
         }
     }
 
+    static int32_t getCallbackInterfaceVersion(std::shared_ptr<CallbackType> callback) {
+        int32_t callbackVersion;
+        if (!callback->getInterfaceVersion(&callbackVersion).isOk()) {
+            LOG(ERROR) << "Unable to check the callback version";
+            return INT_MAX;
+        }
+        return callbackVersion;
+    }
+
     DISALLOW_COPY_AND_ASSIGN(AidlCallbackHandler);
 };
 
diff --git a/wifi/aidl/default/wifi_nan_iface.cpp b/wifi/aidl/default/wifi_nan_iface.cpp
index cefe7f7..9d50798 100644
--- a/wifi/aidl/default/wifi_nan_iface.cpp
+++ b/wifi/aidl/default/wifi_nan_iface.cpp
@@ -672,6 +672,10 @@
     return ifname_;
 }
 
+int32_t WifiNanIface::getMinCallbackVersion() {
+    return event_cb_handler_.getMinCallbackVersion();
+}
+
 std::set<std::shared_ptr<IWifiNanIfaceEventCallback>> WifiNanIface::getEventCallbacks() {
     LOG(ERROR) << "Using original getEventCallbacks";
     return event_cb_handler_.getCallbacks();
diff --git a/wifi/aidl/default/wifi_nan_iface.h b/wifi/aidl/default/wifi_nan_iface.h
index a49ae8c..d2d1d5c 100644
--- a/wifi/aidl/default/wifi_nan_iface.h
+++ b/wifi/aidl/default/wifi_nan_iface.h
@@ -134,6 +134,8 @@
     ndk::ScopedAStatus suspendRequestInternal(char16_t in_cmdId, int8_t sessionId);
     ndk::ScopedAStatus resumeRequestInternal(char16_t in_cmdId, int8_t sessionId);
 
+    int32_t getMinCallbackVersion();
+
     // Overridden in the gTest suite.
     virtual std::set<std::shared_ptr<IWifiNanIfaceEventCallback>> getEventCallbacks();