Merge "Add AcqiredInfo.RETRYING_CAPTURE to IFingerprint" into sc-dev
diff --git a/audio/7.0/config/api/current.txt b/audio/7.0/config/api/current.txt
index 653531d..7d2706c 100644
--- a/audio/7.0/config/api/current.txt
+++ b/audio/7.0/config/api/current.txt
@@ -155,6 +155,12 @@
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_WIRED_HEADSET;
   }
 
+  public enum AudioEncapsulationType {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.V7_0.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_IEC61937;
+    enum_constant public static final android.audio.policy.configuration.V7_0.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_NONE;
+  }
+
   public enum AudioFormat {
     method @NonNull public String getRawName();
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_AAC;
@@ -488,10 +494,12 @@
   public class Profile {
     ctor public Profile();
     method @Nullable public java.util.List<android.audio.policy.configuration.V7_0.AudioChannelMask> getChannelMasks();
+    method @Nullable public android.audio.policy.configuration.V7_0.AudioEncapsulationType getEncapsulationType();
     method @Nullable public String getFormat();
     method @Nullable public String getName();
     method @Nullable public java.util.List<java.math.BigInteger> getSamplingRates();
     method public void setChannelMasks(@Nullable java.util.List<android.audio.policy.configuration.V7_0.AudioChannelMask>);
+    method public void setEncapsulationType(@Nullable android.audio.policy.configuration.V7_0.AudioEncapsulationType);
     method public void setFormat(@Nullable String);
     method public void setName(@Nullable String);
     method public void setSamplingRates(@Nullable java.util.List<java.math.BigInteger>);
diff --git a/audio/7.0/config/audio_policy_configuration.xsd b/audio/7.0/config/audio_policy_configuration.xsd
index ee51aa8..2030921 100644
--- a/audio/7.0/config/audio_policy_configuration.xsd
+++ b/audio/7.0/config/audio_policy_configuration.xsd
@@ -551,11 +551,18 @@
     <xs:simpleType name="channelMasks">
         <xs:list itemType="audioChannelMask" />
     </xs:simpleType>
+    <xs:simpleType name="audioEncapsulationType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_ENCAPSULATION_TYPE_NONE"/>
+            <xs:enumeration value="AUDIO_ENCAPSULATION_TYPE_IEC61937"/>
+        </xs:restriction>
+    </xs:simpleType>
     <xs:complexType name="profile">
         <xs:attribute name="name" type="xs:token" use="optional"/>
         <xs:attribute name="format" type="extendableAudioFormat" use="optional"/>
         <xs:attribute name="samplingRates" type="samplingRates" use="optional"/>
         <xs:attribute name="channelMasks" type="channelMasks" use="optional"/>
+        <xs:attribute name="encapsulationType" type="audioEncapsulationType" use="optional"/>
     </xs:complexType>
     <xs:simpleType name="audioGainMode">
         <xs:restriction base="xs:string">
diff --git a/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h b/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h
index 88dd12e..7d83556 100644
--- a/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h
+++ b/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h
@@ -287,6 +287,10 @@
     return isLinearPcm(stringToAudioFormat(format));
 }
 
+static inline bool isUnknownAudioEncapsulationType(const std::string& encapsulationType) {
+    return stringToAudioEncapsulationType(encapsulationType) == AudioEncapsulationType::UNKNOWN;
+}
+
 }  // namespace android::audio::policy::configuration::V7_0
 
 #endif  // ANDROID_AUDIO_POLICY_CONFIGURATION_V7_0__ENUMS_H
diff --git a/audio/common/7.0/types.hal b/audio/common/7.0/types.hal
index 4f920e4..6fca93e 100644
--- a/audio/common/7.0/types.hal
+++ b/audio/common/7.0/types.hal
@@ -145,6 +145,14 @@
 };
 
 /**
+ * Audio encapsulation type indicates the encapsulation type that is required
+ * for playback/capture.
+ * See 'audioEncapsulationType' in audio_policy_configuration.xsd for the list
+ * of allowed values.
+ */
+typedef string AudioEncapsulationType;
+
+/**
  * Configurations supported for a certain audio format.
  */
 struct AudioProfile {
@@ -156,6 +164,35 @@
 };
 
 /**
+ * AudioTransport struct describes the capability of an audio port. The
+ * capability is described via AudioProfile or raw hardware descriptors for
+ * for formats that are not supported by the platform.
+ */
+struct AudioTransport {
+    safe_union AudioCapability {
+        /**
+         * A certain audio format that is known by the platform and its
+         * corresponding configuration.
+         */
+        AudioProfile profile;
+        /**
+         * The audio descriptor that is reported from EDID. See HDMI
+         * specification 1.4b section 7 and CEA-861-G section 7.5.2 for more
+         * information. When this value is set, it indicates the standard is
+         * AUDIO_STANDARD_EDID.
+         */
+        vec<uint8_t> edid;
+    } audioCapability;
+
+    /**
+     * The encapsulation type that is required when the framework is using this
+     * format when playing or capturing to/from a stream or device exposing this
+     * audio transport.
+     */
+    AudioEncapsulationType encapsulationType;
+};
+
+/**
  * Major modes for a mobile device. The current mode setting affects audio
  * routing.
  */
@@ -488,8 +525,12 @@
      * E.g. "telephony_tx" or "fm_tuner".
      */
     string name;
-    /** List of audio profiles supported by the port. */
-    vec<AudioProfile> profiles;
+    /**
+     * List of audio transports supported by the audio port. This includes
+     * supported formats and raw hardware descriptors for formats not supported
+     * by the platform.
+     */
+    vec<AudioTransport> transports;
     /** List of gain controls attached to the port. */
     vec<AudioGain> gains;
     /** Parameters that depend on the actual port role. */
diff --git a/audio/common/all-versions/default/7.0/HidlUtils.cpp b/audio/common/all-versions/default/7.0/HidlUtils.cpp
index 2949fac..5a5b5d2 100644
--- a/audio/common/all-versions/default/7.0/HidlUtils.cpp
+++ b/audio/common/all-versions/default/7.0/HidlUtils.cpp
@@ -715,6 +715,27 @@
     return result;
 }
 
+status_t HidlUtils::encapsulationTypeFromHal(audio_encapsulation_type_t halEncapsulationType,
+                                             AudioEncapsulationType* encapsulationType) {
+    *encapsulationType = audio_encapsulation_type_to_string(halEncapsulationType);
+    if (!encapsulationType->empty() && !xsd::isUnknownAudioEncapsulationType(*encapsulationType)) {
+        return NO_ERROR;
+    }
+    ALOGE("Unknown audio encapsulation type value 0x%X", halEncapsulationType);
+    return BAD_VALUE;
+}
+
+status_t HidlUtils::encapsulationTypeToHal(const AudioEncapsulationType& encapsulationType,
+                                           audio_encapsulation_type_t* halEncapsulationType) {
+    if (!xsd::isUnknownAudioEncapsulationType(encapsulationType) &&
+        audio_encapsulation_type_from_string(encapsulationType.c_str(), halEncapsulationType)) {
+        return NO_ERROR;
+    }
+    ALOGE("Unknown audio encapsulation type \"%s\"", encapsulationType.c_str());
+    *halEncapsulationType = AUDIO_ENCAPSULATION_TYPE_NONE;
+    return BAD_VALUE;
+}
+
 status_t HidlUtils::audioPortFromHal(const struct audio_port& halPort, AudioPort* port) {
     struct audio_port_v7 halPortV7 = {};
     audio_populate_audio_port_v7(&halPort, &halPortV7);
@@ -758,11 +779,7 @@
     CONVERT_CHECKED(audioPortExtendedInfoFromHal(halPort.role, halPort.type, halDevice, halMix,
                                                  halSession, &port->ext, &isInput),
                     result);
-    port->profiles.resize(halPort.num_audio_profiles);
-    for (size_t i = 0; i < halPort.num_audio_profiles; ++i) {
-        CONVERT_CHECKED(audioProfileFromHal(halPort.audio_profiles[i], isInput, &port->profiles[i]),
-                        result);
-    }
+    CONVERT_CHECKED(audioTransportsFromHal(halPort, isInput, &port->transports), result);
     port->gains.resize(halPort.num_gains);
     for (size_t i = 0; i < halPort.num_gains; ++i) {
         CONVERT_CHECKED(audioGainFromHal(halPort.gains[i], isInput, &port->gains[i]), result);
@@ -780,15 +797,7 @@
         ALOGE("HIDL Audio Port name is too long: %zu", port.name.size());
         result = BAD_VALUE;
     }
-    halPort->num_audio_profiles = port.profiles.size();
-    if (halPort->num_audio_profiles > AUDIO_PORT_MAX_AUDIO_PROFILES) {
-        ALOGE("HIDL Audio Port has too many profiles: %u", halPort->num_audio_profiles);
-        halPort->num_audio_profiles = AUDIO_PORT_MAX_AUDIO_PROFILES;
-        result = BAD_VALUE;
-    }
-    for (size_t i = 0; i < halPort->num_audio_profiles; ++i) {
-        CONVERT_CHECKED(audioProfileToHal(port.profiles[i], &halPort->audio_profiles[i]), result);
-    }
+    CONVERT_CHECKED(audioTransportsToHal(port.transports, halPort), result);
     halPort->num_gains = port.gains.size();
     if (halPort->num_gains > AUDIO_PORT_MAX_GAINS) {
         ALOGE("HIDL Audio Port has too many gains: %u", halPort->num_gains);
@@ -824,6 +833,110 @@
     return result;
 }
 
+status_t HidlUtils::audioTransportsFromHal(const struct audio_port_v7& halPort, bool isInput,
+                                           hidl_vec<AudioTransport>* transports) {
+    if (halPort.num_audio_profiles > AUDIO_PORT_MAX_AUDIO_PROFILES ||
+        halPort.num_extra_audio_descriptors > AUDIO_PORT_MAX_EXTRA_AUDIO_DESCRIPTORS) {
+        ALOGE("%s, too many audio profiles(%u) or extra audio descriptors(%u)", __func__,
+              halPort.num_audio_profiles, halPort.num_extra_audio_descriptors);
+        return BAD_VALUE;
+    }
+    status_t result = NO_ERROR;
+    transports->resize(halPort.num_audio_profiles + halPort.num_extra_audio_descriptors);
+    size_t idx = 0;
+    for (size_t i = 0; i < halPort.num_audio_profiles; ++i) {
+        auto& transport = (*transports)[idx++];
+        transport.audioCapability.profile({});
+        CONVERT_CHECKED(audioProfileFromHal(halPort.audio_profiles[i], isInput,
+                                            &transport.audioCapability.profile()),
+                        result);
+        CONVERT_CHECKED(encapsulationTypeFromHal(halPort.audio_profiles[i].encapsulation_type,
+                                                 &transport.encapsulationType),
+                        result);
+    }
+    for (size_t i = 0; i < halPort.num_extra_audio_descriptors; ++i) {
+        switch (halPort.extra_audio_descriptors[i].standard) {
+            case AUDIO_STANDARD_EDID: {
+                const struct audio_extra_audio_descriptor* extraAudioDescriptor =
+                        &halPort.extra_audio_descriptors[i];
+                if (extraAudioDescriptor->descriptor_length <= EXTRA_AUDIO_DESCRIPTOR_SIZE) {
+                    auto& transport = (*transports)[idx++];
+                    transport.audioCapability.edid(
+                            hidl_vec<uint8_t>(extraAudioDescriptor->descriptor,
+                                              extraAudioDescriptor->descriptor +
+                                                      extraAudioDescriptor->descriptor_length));
+                    CONVERT_CHECKED(
+                            encapsulationTypeFromHal(extraAudioDescriptor->encapsulation_type,
+                                                     &transport.encapsulationType),
+                            result);
+                } else {
+                    ALOGE("%s, invalid descriptor length %u", __func__,
+                          extraAudioDescriptor->descriptor_length);
+                    result = BAD_VALUE;
+                }
+            } break;
+            case AUDIO_STANDARD_NONE:
+            default:
+                ALOGE("%s, invalid standard %u", __func__,
+                      halPort.extra_audio_descriptors[i].standard);
+                result = BAD_VALUE;
+                break;
+        }
+    }
+    return result;
+}
+
+status_t HidlUtils::audioTransportsToHal(const hidl_vec<AudioTransport>& transports,
+                                         struct audio_port_v7* halPort) {
+    status_t result = NO_ERROR;
+    halPort->num_audio_profiles = 0;
+    halPort->num_extra_audio_descriptors = 0;
+    for (const auto& transport : transports) {
+        switch (transport.audioCapability.getDiscriminator()) {
+            case AudioTransport::AudioCapability::hidl_discriminator::profile:
+                if (halPort->num_audio_profiles > AUDIO_PORT_MAX_AUDIO_PROFILES) {
+                    ALOGE("%s, too many audio profiles", __func__);
+                    result = BAD_VALUE;
+                    break;
+                }
+                CONVERT_CHECKED(
+                        audioProfileToHal(transport.audioCapability.profile(),
+                                          &halPort->audio_profiles[halPort->num_audio_profiles]),
+                        result);
+                CONVERT_CHECKED(encapsulationTypeToHal(
+                                        transport.encapsulationType,
+                                        &halPort->audio_profiles[halPort->num_audio_profiles++]
+                                                 .encapsulation_type),
+                                result);
+                break;
+            case AudioTransport::AudioCapability::hidl_discriminator::edid:
+                if (halPort->num_extra_audio_descriptors > AUDIO_PORT_MAX_EXTRA_AUDIO_DESCRIPTORS) {
+                    ALOGE("%s, too many extra audio descriptors", __func__);
+                    result = BAD_VALUE;
+                    break;
+                }
+                if (transport.audioCapability.edid().size() > EXTRA_AUDIO_DESCRIPTOR_SIZE) {
+                    ALOGE("%s, wrong edid size %zu", __func__,
+                          transport.audioCapability.edid().size());
+                    result = BAD_VALUE;
+                    break;
+                }
+                struct audio_extra_audio_descriptor* extraAudioDescriptor =
+                        &halPort->extra_audio_descriptors[halPort->num_extra_audio_descriptors++];
+                extraAudioDescriptor->standard = AUDIO_STANDARD_EDID;
+                extraAudioDescriptor->descriptor_length = transport.audioCapability.edid().size();
+                memcpy(extraAudioDescriptor->descriptor, transport.audioCapability.edid().data(),
+                       transport.audioCapability.edid().size() * sizeof(uint8_t));
+
+                CONVERT_CHECKED(encapsulationTypeToHal(transport.encapsulationType,
+                                                       &extraAudioDescriptor->encapsulation_type),
+                                result);
+                break;
+        }
+    }
+    return result;
+}
+
 status_t HidlUtils::audioProfileFromHal(const struct audio_profile& halProfile, bool isInput,
                                         AudioProfile* profile) {
     status_t result = NO_ERROR;
diff --git a/audio/common/all-versions/default/HidlUtils.h b/audio/common/all-versions/default/HidlUtils.h
index dd4ca4d..98ecc07 100644
--- a/audio/common/all-versions/default/HidlUtils.h
+++ b/audio/common/all-versions/default/HidlUtils.h
@@ -126,6 +126,10 @@
     static hidl_vec<AudioTag> filterOutNonVendorTags(const hidl_vec<AudioTag>& tags);
     static std::vector<std::string> filterOutNonVendorTags(const std::vector<std::string>& tags);
     static std::vector<std::string> splitAudioTags(const char* halTags);
+    static status_t audioTransportsFromHal(const struct audio_port_v7& halPort, bool isInput,
+                                           hidl_vec<AudioTransport>* transports);
+    static status_t audioTransportsToHal(const hidl_vec<AudioTransport>& transports,
+                                         struct audio_port_v7* halTransport);
 
   private:
     static status_t audioIndexChannelMaskFromHal(audio_channel_mask_t halChannelMask,
@@ -145,6 +149,10 @@
                                                struct audio_port_config_device_ext* device,
                                                struct audio_port_config_mix_ext* mix,
                                                struct audio_port_config_session_ext* session);
+    static status_t encapsulationTypeFromHal(audio_encapsulation_type_t halEncapsulationType,
+                                             AudioEncapsulationType* encapsulationType);
+    static status_t encapsulationTypeToHal(const AudioEncapsulationType& encapsulationType,
+                                           audio_encapsulation_type_t* halEncapsulationType);
 
 #endif  // MAJOR_VERSION >= 7
 
diff --git a/audio/common/all-versions/default/tests/hidlutils_tests.cpp b/audio/common/all-versions/default/tests/hidlutils_tests.cpp
index e154453..c9e6fac 100644
--- a/audio/common/all-versions/default/tests/hidlutils_tests.cpp
+++ b/audio/common/all-versions/default/tests/hidlutils_tests.cpp
@@ -47,6 +47,10 @@
 // AUDIO_STREAM_DEFAULT is framework-only
 static constexpr audio_stream_type_t kInvalidHalStreamType = static_cast<audio_stream_type_t>(-2);
 static constexpr audio_usage_t kInvalidHalUsage = static_cast<audio_usage_t>(0xFFFFFFFFU);
+static constexpr audio_encapsulation_type_t kInvalidEncapsulationType =
+        static_cast<audio_encapsulation_type_t>(0xFFFFFFFFU);
+static constexpr audio_standard_t kInvalidAudioStandard =
+        static_cast<audio_standard_t>(0xFFFFFFFFU);
 
 TEST(HidlUtils, ConvertInvalidChannelMask) {
     AudioChannelMask invalid;
@@ -950,6 +954,53 @@
     EXPECT_TRUE(audio_port_configs_are_equal(&halConfig, &halConfigBack));
 }
 
+TEST(HidlUtils, ConvertInvalidAudioTransports) {
+    hidl_vec<AudioTransport> invalid;
+    struct audio_port_v7 halInvalid = {};
+    halInvalid.num_audio_profiles = 1;
+    halInvalid.audio_profiles[0].format = kInvalidHalFormat;
+    halInvalid.audio_profiles[0].encapsulation_type = kInvalidEncapsulationType;
+    halInvalid.num_extra_audio_descriptors = 1;
+    halInvalid.extra_audio_descriptors[0].standard = kInvalidAudioStandard;
+    halInvalid.extra_audio_descriptors[0].descriptor_length = EXTRA_AUDIO_DESCRIPTOR_SIZE + 1;
+    EXPECT_EQ(BAD_VALUE,
+              HidlUtils::audioTransportsFromHal(halInvalid, false /*isInput*/, &invalid));
+    invalid.resize(2);
+    AudioProfile invalidProfile;
+    invalidProfile.format = "random string";
+    invalid[0].audioCapability.profile(invalidProfile);
+    invalid[0].encapsulationType = "random string";
+    invalid[0].audioCapability.edid(hidl_vec<uint8_t>(EXTRA_AUDIO_DESCRIPTOR_SIZE + 1));
+    invalid[1].encapsulationType = "random string";
+    EXPECT_EQ(BAD_VALUE, HidlUtils::audioTransportsToHal(invalid, &halInvalid));
+}
+
+TEST(HidlUtils, ConvertAudioTransports) {
+    hidl_vec<AudioTransport> transports;
+    transports.resize(2);
+    AudioProfile profile;
+    profile.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
+    profile.sampleRates.resize(2);
+    profile.sampleRates[0] = 44100;
+    profile.sampleRates[1] = 48000;
+    profile.channelMasks.resize(2);
+    profile.channelMasks[0] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO);
+    profile.channelMasks[1] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO);
+    transports[0].audioCapability.profile(profile);
+    hidl_vec<uint8_t> shortAudioDescriptor({0x11, 0x06, 0x01});
+    transports[0].encapsulationType =
+            toString(xsd::AudioEncapsulationType::AUDIO_ENCAPSULATION_TYPE_NONE);
+    transports[1].audioCapability.edid(std::move(shortAudioDescriptor));
+    transports[1].encapsulationType =
+            toString(xsd::AudioEncapsulationType::AUDIO_ENCAPSULATION_TYPE_IEC61937);
+    struct audio_port_v7 halPort;
+    EXPECT_EQ(NO_ERROR, HidlUtils::audioTransportsToHal(transports, &halPort));
+    hidl_vec<AudioTransport> transportsBack;
+    EXPECT_EQ(NO_ERROR,
+              HidlUtils::audioTransportsFromHal(halPort, false /*isInput*/, &transportsBack));
+    EXPECT_EQ(transports, transportsBack);
+}
+
 TEST(HidlUtils, ConvertInvalidAudioPort) {
     AudioPort invalid;
     struct audio_port_v7 halInvalid = {};
@@ -958,8 +1009,10 @@
     halInvalid.num_audio_profiles = 1;
     halInvalid.audio_profiles[0].format = kInvalidHalFormat;
     EXPECT_EQ(BAD_VALUE, HidlUtils::audioPortFromHal(halInvalid, &invalid));
-    invalid.profiles.resize(1);
-    invalid.profiles[0].format = "random string";
+    invalid.transports.resize(1);
+    AudioProfile invalidProfile;
+    invalidProfile.format = "random string";
+    invalid.transports[0].audioCapability.profile(invalidProfile);
     EXPECT_EQ(BAD_VALUE, HidlUtils::audioPortToHal(invalid, &halInvalid));
 }
 
@@ -967,14 +1020,22 @@
     AudioPort port = {};
     port.id = 42;
     port.name = "test";
-    port.profiles.resize(1);
-    port.profiles[0].format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
-    port.profiles[0].sampleRates.resize(2);
-    port.profiles[0].sampleRates[0] = 44100;
-    port.profiles[0].sampleRates[1] = 48000;
-    port.profiles[0].channelMasks.resize(2);
-    port.profiles[0].channelMasks[0] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO);
-    port.profiles[0].channelMasks[1] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO);
+    port.transports.resize(2);
+    AudioProfile profile;
+    profile.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
+    profile.sampleRates.resize(2);
+    profile.sampleRates[0] = 44100;
+    profile.sampleRates[1] = 48000;
+    profile.channelMasks.resize(2);
+    profile.channelMasks[0] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO);
+    profile.channelMasks[1] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO);
+    port.transports[0].audioCapability.profile(profile);
+    port.transports[0].encapsulationType =
+            toString(xsd::AudioEncapsulationType::AUDIO_ENCAPSULATION_TYPE_NONE);
+    hidl_vec<uint8_t> shortAudioDescriptor({0x11, 0x06, 0x01});
+    port.transports[1].audioCapability.edid(std::move(shortAudioDescriptor));
+    port.transports[1].encapsulationType =
+            toString(xsd::AudioEncapsulationType::AUDIO_ENCAPSULATION_TYPE_IEC61937);
     port.gains.resize(1);
     port.gains[0].channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO);
     port.ext.device({});
diff --git a/automotive/vehicle/2.0/vts/functional/Android.bp b/automotive/vehicle/2.0/vts/functional/Android.bp
new file mode 100644
index 0000000..9f1dd6f
--- /dev/null
+++ b/automotive/vehicle/2.0/vts/functional/Android.bp
@@ -0,0 +1,21 @@
+cc_test {
+    name: "VtsHalAutomotiveVehicleV2_0TargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+    ],
+    srcs: [
+        "VtsHalAutomotiveVehicleV2_0TargetTest.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "liblog",
+    ],
+    static_libs: [
+        "android.hardware.automotive.vehicle@2.0",
+    ],
+    test_suites: [
+        "vts",
+        "general-tests",
+    ],
+}
diff --git a/automotive/vehicle/2.0/vts/functional/VtsHalAutomotiveVehicleV2_0TargetTest.cpp b/automotive/vehicle/2.0/vts/functional/VtsHalAutomotiveVehicleV2_0TargetTest.cpp
new file mode 100644
index 0000000..7f1d4d1
--- /dev/null
+++ b/automotive/vehicle/2.0/vts/functional/VtsHalAutomotiveVehicleV2_0TargetTest.cpp
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VtsHalAutomotiveVehicle"
+
+#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
+#include <utils/Log.h>
+
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+using namespace android::hardware::automotive::vehicle::V2_0;
+using ::android::sp;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+
+constexpr auto kTimeout = std::chrono::milliseconds(500);
+constexpr auto kInvalidProp = 0x31600207;
+
+class VtsVehicleCallback : public IVehicleCallback {
+  private:
+    using MutexGuard = std::lock_guard<std::mutex>;
+    using HidlVecOfValues = hidl_vec<VehiclePropValue>;
+    std::mutex mLock;
+    std::condition_variable mEventCond;
+    std::vector<HidlVecOfValues> mReceivedEvents;
+
+  public:
+    Return<void> onPropertyEvent(const hidl_vec<VehiclePropValue>& values) override {
+        {
+            MutexGuard guard(mLock);
+            mReceivedEvents.push_back(values);
+        }
+        mEventCond.notify_one();
+        return Return<void>();
+    }
+
+    Return<void> onPropertySet(const VehiclePropValue& /* value */) override {
+        return Return<void>();
+    }
+    Return<void> onPropertySetError(StatusCode /* errorCode */, int32_t /* propId */,
+                                    int32_t /* areaId */) override {
+        return Return<void>();
+    }
+
+    bool waitForExpectedEvents(size_t expectedEvents) {
+        std::unique_lock<std::mutex> g(mLock);
+
+        if (expectedEvents == 0 && mReceivedEvents.size() == 0) {
+            return mEventCond.wait_for(g, kTimeout) == std::cv_status::timeout;
+        }
+
+        while (expectedEvents != mReceivedEvents.size()) {
+            if (mEventCond.wait_for(g, kTimeout) == std::cv_status::timeout) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    void reset() { mReceivedEvents.clear(); }
+};
+
+class VehicleHalHidlTest : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        mVehicle = IVehicle::getService(GetParam());
+        ASSERT_NE(mVehicle.get(), nullptr);
+    }
+    virtual void TearDown() override {}
+
+    sp<IVehicle> mVehicle;
+
+    bool isBooleanGlobalProp(int32_t property) {
+        return (property & (int)VehiclePropertyType::MASK) == (int)VehiclePropertyType::BOOLEAN &&
+               (property & (int)VehicleArea::MASK) == (int)VehicleArea::GLOBAL;
+    }
+
+    void invokeGet(int32_t property, int32_t areaId) {
+        VehiclePropValue requestedValue{};
+        requestedValue.prop = property;
+        requestedValue.areaId = areaId;
+
+        invokeGet(requestedValue);
+    }
+
+    void invokeGet(const VehiclePropValue& requestedPropValue) {
+        mActualValue = VehiclePropValue{};  // reset previous values
+
+        StatusCode refStatus;
+        VehiclePropValue refValue;
+        bool isCalled = false;
+        mVehicle->get(requestedPropValue,
+                      [&refStatus, &refValue, &isCalled](StatusCode status,
+                                                         const VehiclePropValue& value) {
+                          refStatus = status;
+                          refValue = value;
+                          isCalled = true;
+                      });
+        ASSERT_TRUE(isCalled) << "callback wasn't called for property: " << requestedPropValue.prop;
+
+        mActualValue = refValue;
+        mActualStatusCode = refStatus;
+    }
+
+    VehiclePropValue mActualValue;
+    StatusCode mActualStatusCode;
+};
+
+// Test getAllPropConfig() returns at least 4 property configs.
+TEST_P(VehicleHalHidlTest, getAllPropConfigs) {
+    ALOGD("VehicleHalHidlTest::getAllPropConfigs");
+    bool isCalled = false;
+    hidl_vec<VehiclePropConfig> propConfigs;
+    mVehicle->getAllPropConfigs([&isCalled, &propConfigs](const hidl_vec<VehiclePropConfig>& cfgs) {
+        propConfigs = cfgs;
+        isCalled = true;
+    });
+    ASSERT_TRUE(isCalled);
+    ASSERT_GE(propConfigs.size(), 4);
+}
+
+// Test getPropConfig() can query all properties listed in CDD.
+TEST_P(VehicleHalHidlTest, getPropConfigs) {
+    ALOGD("VehicleHalHidlTest::getPropConfigs");
+    // Check the properties listed in CDD
+    hidl_vec<int32_t> properties = {
+            (int)VehicleProperty::GEAR_SELECTION, (int)VehicleProperty::NIGHT_MODE,
+            (int)VehicleProperty::PARKING_BRAKE_ON, (int)VehicleProperty::PERF_VEHICLE_SPEED};
+    bool isCalled = false;
+    mVehicle->getPropConfigs(
+            properties, [&isCalled](StatusCode status, const hidl_vec<VehiclePropConfig>& cfgs) {
+                ASSERT_EQ(StatusCode::OK, status);
+                ASSERT_EQ(4u, cfgs.size());
+                isCalled = true;
+            });
+    ASSERT_TRUE(isCalled);
+}
+
+// Test getPropConfig() with an invalid propertyId returns an error code.
+TEST_P(VehicleHalHidlTest, getPropConfigsWithInvalidProp) {
+    ALOGD("VehicleHalHidlTest::getPropConfigsWithInvalidProp");
+    hidl_vec<int32_t> properties = {kInvalidProp};
+    bool isCalled = false;
+    mVehicle->getPropConfigs(
+            properties, [&isCalled](StatusCode status, const hidl_vec<VehiclePropConfig>& cfgs) {
+                ASSERT_NE(StatusCode::OK, status);
+                ASSERT_EQ(0, cfgs.size());
+                isCalled = true;
+            });
+    ASSERT_TRUE(isCalled);
+}
+
+// Test get() return current value for properties.
+TEST_P(VehicleHalHidlTest, get) {
+    ALOGD("VehicleHalHidlTest::get");
+    invokeGet((int)VehicleProperty::PERF_VEHICLE_SPEED, 0);
+    ASSERT_EQ(StatusCode::OK, mActualStatusCode);
+}
+
+// Test get() with an invalid propertyId return an error codes.
+TEST_P(VehicleHalHidlTest, getInvalidProp) {
+    ALOGD("VehicleHalHidlTest::getInvalidProp");
+
+    invokeGet(kInvalidProp, 0);
+    ASSERT_NE(StatusCode::OK, mActualStatusCode);
+}
+
+// Test set() on read_write properties.
+TEST_P(VehicleHalHidlTest, setProp) {
+    ALOGD("VehicleHalHidlTest::setProp");
+    hidl_vec<VehiclePropConfig> propConfigs;
+    mVehicle->getAllPropConfigs(
+            [&propConfigs](const hidl_vec<VehiclePropConfig>& cfgs) { propConfigs = cfgs; });
+    for (const VehiclePropConfig& cfg : propConfigs) {
+        // test on boolean and writable property
+        if (cfg.access == VehiclePropertyAccess::READ_WRITE && isBooleanGlobalProp(cfg.prop)) {
+            invokeGet(cfg.prop, 0);
+            int setValue = mActualValue.value.int32Values[0] == 1 ? 0 : 1;
+            VehiclePropValue propToSet = mActualValue;
+            propToSet.value.int32Values[0] = setValue;
+            ASSERT_EQ(StatusCode::OK, mVehicle->set(propToSet));
+            // check set success
+            invokeGet(cfg.prop, 0);
+            ASSERT_EQ(StatusCode::OK, mActualStatusCode);
+            ASSERT_EQ(setValue, mActualValue.value.int32Values[0]);
+        }
+    }
+}
+
+// Test set() on an read_only property.
+TEST_P(VehicleHalHidlTest, setNotWritableProp) {
+    ALOGD("VehicleHalHidlTest::setNotWritableProp");
+    invokeGet(static_cast<int>(VehicleProperty::PERF_VEHICLE_SPEED), 0);
+    ASSERT_EQ(StatusCode::OK, mActualStatusCode);
+    VehiclePropValue vehicleSpeed = mActualValue;
+
+    ASSERT_EQ(StatusCode::ACCESS_DENIED, mVehicle->set(vehicleSpeed));
+}
+
+// Test subscribe() and unsubscribe().
+TEST_P(VehicleHalHidlTest, subscribeAndUnsubscribe) {
+    ALOGD("VehicleHalHidlTest::subscribeAndUnsubscribe");
+    const auto prop = static_cast<int>(VehicleProperty::PERF_VEHICLE_SPEED);
+    sp<VtsVehicleCallback> cb = new VtsVehicleCallback();
+
+    hidl_vec<SubscribeOptions> options = {
+            SubscribeOptions{.propId = prop, 100.0, .flags = SubscribeFlags::EVENTS_FROM_CAR}};
+
+    ASSERT_EQ(StatusCode::OK, mVehicle->subscribe(cb, options));
+    ASSERT_TRUE(cb->waitForExpectedEvents(10));
+
+    ASSERT_EQ(StatusCode::OK, mVehicle->unsubscribe(cb, prop));
+    cb->reset();
+    ASSERT_FALSE(cb->waitForExpectedEvents(10));
+}
+
+// Test subscribe() with an invalid property.
+TEST_P(VehicleHalHidlTest, subscribeInvalidProp) {
+    ALOGD("VehicleHalHidlTest::subscribeInvalidProp");
+
+    sp<VtsVehicleCallback> cb = new VtsVehicleCallback();
+
+    hidl_vec<SubscribeOptions> options = {SubscribeOptions{
+            .propId = kInvalidProp, 10.0, .flags = SubscribeFlags::EVENTS_FROM_CAR}};
+
+    ASSERT_NE(StatusCode::OK, mVehicle->subscribe(cb, options));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, VehicleHalHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IVehicle::descriptor)),
+        android::hardware::PrintInstanceNameToString);
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl
index 205429b..9033989 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl
@@ -34,17 +34,17 @@
 package android.hardware.biometrics.face;
 @VintfStability
 interface ISession {
-  void generateChallenge(in int cookie);
-  void revokeChallenge(in int cookie, in long challenge);
-  android.hardware.biometrics.common.ICancellationSignal enroll(in int cookie, in android.hardware.keymaster.HardwareAuthToken hat, in android.hardware.biometrics.face.EnrollmentType type, in android.hardware.biometrics.face.Feature[] features, in android.hardware.common.NativeHandle previewSurface);
-  android.hardware.biometrics.common.ICancellationSignal authenticate(in int cookie, in long operationId);
-  android.hardware.biometrics.common.ICancellationSignal detectInteraction(in int cookie);
-  void enumerateEnrollments(in int cookie);
-  void removeEnrollments(in int cookie, in int[] enrollmentIds);
-  void getFeatures(in int cookie, in int enrollmentId);
-  void setFeature(in int cookie, in android.hardware.keymaster.HardwareAuthToken hat, in int enrollmentId, in android.hardware.biometrics.face.Feature feature, boolean enabled);
-  void getAuthenticatorId(in int cookie);
-  void invalidateAuthenticatorId(in int cookie);
-  void resetLockout(in int cookie, in android.hardware.keymaster.HardwareAuthToken hat);
-  void close(in int cookie);
+  void generateChallenge();
+  void revokeChallenge(in long challenge);
+  android.hardware.biometrics.common.ICancellationSignal enroll(in android.hardware.keymaster.HardwareAuthToken hat, in android.hardware.biometrics.face.EnrollmentType type, in android.hardware.biometrics.face.Feature[] features, in android.hardware.common.NativeHandle previewSurface);
+  android.hardware.biometrics.common.ICancellationSignal authenticate(in long operationId);
+  android.hardware.biometrics.common.ICancellationSignal detectInteraction();
+  void enumerateEnrollments();
+  void removeEnrollments(in int[] enrollmentIds);
+  void getFeatures(in int enrollmentId);
+  void setFeature(in android.hardware.keymaster.HardwareAuthToken hat, in int enrollmentId, in android.hardware.biometrics.face.Feature feature, boolean enabled);
+  void getAuthenticatorId();
+  void invalidateAuthenticatorId();
+  void resetLockout(in android.hardware.keymaster.HardwareAuthToken hat);
+  void close();
 }
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISessionCallback.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISessionCallback.aidl
index b0bfa30..2bb053a 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISessionCallback.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISessionCallback.aidl
@@ -34,7 +34,6 @@
 package android.hardware.biometrics.face;
 @VintfStability
 interface ISessionCallback {
-  void onStateChanged(in int cookie, in android.hardware.biometrics.face.SessionState state);
   void onChallengeGenerated(in long challenge);
   void onChallengeRevoked(in long challenge);
   void onAuthenticationFrame(in android.hardware.biometrics.face.AuthenticationFrame frame);
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl
index 66c7c38..f9c13e6 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl
@@ -23,11 +23,25 @@
 import android.hardware.keymaster.HardwareAuthToken;
 
 /**
- * A session is a collection of immutable state (sensorId, userId), mutable state (SessionState),
- * methods available for the framework to call, and a callback (ISessionCallback) to notify the
- * framework about the events and results. A session is used to establish communication between
- * the framework and the HAL.
+ * Operations that can be performed for unique sessions retrieved via IFace#createSession.
+ * Operations defined within this interface can be divided into the following categories:
+ * 1) Cancellable operations. These are usually the operations that can execute for several
+ *     minutes. To allow for cancellation, they return an instance of ICancellationSignal that
+ *     lets the framework cancel them by calling ICancellationSignal#cancel. If such an operation
+ *     is cancelled, it must notify the framework by calling ISessionCallback#onError with
+ *     Error::CANCELED.
+ * 2) Non-cancellable operations. Such operations cannot be cancelled once started.
+ *
+ * The lifecycle of an operation ends when one of its terminal callbacks is called. For example,
+ * ISession#authenticate is considered completed when any of the following callbacks is called:
+ * ISessionCallback#onError, ISessionCallback#onAuthenticationSucceeded,
+ * ISessionCallback#onAuthenticationFailed.
+ *
+ * ISession only supports execution of one operation at a time, regardless of whether it's
+ * cancellable or not. The framework must wait for a corresponding callback indicating the end of
+ * the current operation before a new operation can be started.
  */
+
 @VintfStability
 interface ISession {
     /**
@@ -55,7 +69,7 @@
      *
      * Note that this interface allows multiple in-flight challenges. Invoking generateChallenge
      * twice does not invalidate the first challenge. The challenge is invalidated only when:
-     *   1) Its lifespan exceeds the HAL's internal challenge timeout
+     *   1) Its lifespan exceeds the challenge timeout defined in the TEE.
      *   2) IFingerprint#revokeChallenge is invoked
      *
      * For example, the following is a possible table of valid challenges:
@@ -68,9 +82,8 @@
      * | 0        | 10     | <Time4>    | <Random4> |
      * ----------------------------------------------
      *
-     * @param cookie A unique number identifying this operation
      */
-    void generateChallenge(in int cookie);
+    void generateChallenge();
 
     /**
      * revokeChallenge:
@@ -79,10 +92,9 @@
      * parameters is requested, the implementation must still notify the framework using the
      * provided callback.
      *
-     * @param cookie A unique number identifying this operation
      * @param challenge Challenge that should be revoked.
      */
-    void revokeChallenge(in int cookie, in long challenge);
+    void revokeChallenge(in long challenge);
 
     /**
      * getEnrollmentConfig:
@@ -101,19 +113,13 @@
      *
      * A request to add a face enrollment.
      *
-     * Once the HAL is able to start processing the enrollment request, it must notify the framework
-     * via ISessionCallback#onStateChanged with SessionState::ENROLLING.
-     *
      * At any point during enrollment, if a non-recoverable error occurs, the HAL must notify the
-     * framework via ISessionCallback#onError with the applicable enrollment-specific error, and
-     * then send ISessionCallback#onStateChanged(cookie, SessionState::IDLING) if no subsequent
-     * operation is in the queue.
+     * framework via ISessionCallback#onError with the applicable enrollment-specific error.
      *
      * Before capturing face data, the implementation must first verify the authenticity and
      * integrity of the provided HardwareAuthToken. In addition, it must check that the challenge
      * within the provided HardwareAuthToken is valid. See ISession#generateChallenge. If any of
-     * the above checks fail, the framework must be notified via ISessionCallback#onError and the
-     * HAL must notify the framework when it returns to the idle state. See
+     * the above checks fail, the framework must be notified using ISessionCallback#onError with
      * Error::UNABLE_TO_PROCESS.
      *
      * During enrollment, the implementation may notify the framework via
@@ -121,15 +127,12 @@
      * can be invoked multiple times if necessary. Similarly, the framework may be notified of
      * enrollment progress changes via ISessionCallback#onEnrollmentProgress. Once the framework is
      * notified that there are 0 "remaining" steps, the framework may cache the "enrollmentId". See
-     * ISessionCallback#onEnrollmentProgress for more info. The HAL must notify the framework once
-     * it returns to the idle state.
+     * ISessionCallback#onEnrollmentProgress for more info.
      *
-     * When a finger is successfully added and before the framework is notified of remaining=0, the
-     * implementation MUST update and associate this (sensorId, userId) pair with a new new
+     * When a face is successfully added and before the framework is notified of remaining=0, the
+     * implementation MUST update and associate this (sensorId, userId) pair with a new
      * entropy-encoded random identifier. See ISession#getAuthenticatorId for more information.
      *
-     * @param cookie An identifier used to track subsystem operations related to this call path. The
-     *               client must guarantee that it is unique per ISession.
      * @param hat See above documentation.
      * @param enrollmentType See the EnrollmentType enum.
      * @param features See the Feature enum.
@@ -139,7 +142,7 @@
      * @return ICancellationSignal An object that can be used by the framework to cancel this
      * operation.
      */
-    ICancellationSignal enroll(in int cookie, in HardwareAuthToken hat, in EnrollmentType type,
+    ICancellationSignal enroll(in HardwareAuthToken hat, in EnrollmentType type,
             in Feature[] features, in NativeHandle previewSurface);
 
     /**
@@ -147,13 +150,8 @@
      *
      * A request to start looking for faces to authenticate.
      *
-     * Once the HAL is able to start processing the authentication request, it must notify framework
-     * via ISessionCallback#onStateChanged with SessionState::AUTHENTICATING.
-     *
      * At any point during authentication, if a non-recoverable error occurs, the HAL must notify
-     * the framework via ISessionCallback#onError with the applicable authentication-specific error,
-     * and then send ISessionCallback#onStateChanged(cookie, SessionState::IDLING) if no
-     * subsequent operation is in the queue.
+     * the framework via ISessionCallback#onError with the applicable authentication-specific error.
      *
      * During authentication, the implementation may notify the framework via
      * ISessionCallback#onAcquired with messages that may be used to guide the user. This callback
@@ -175,8 +173,6 @@
      * must be set with the operationId passed in during #authenticate. If the sensor is NOT
      * SensorStrength::STRONG, the HardwareAuthToken MUST be null.
      *
-     * @param cookie An identifier used to track subsystem operations related to this call path. The
-     *               client must guarantee that it is unique per ISession.
      * @param operationId For sensors configured as SensorStrength::STRONG, this must be used ONLY
      *                    upon successful authentication and wrapped in the HardwareAuthToken's
      *                    "challenge" field and sent to the framework via
@@ -190,7 +186,7 @@
      * @return ICancellationSignal An object that can be used by the framework to cancel this
      * operation.
      */
-    ICancellationSignal authenticate(in int cookie, in long operationId);
+    ICancellationSignal authenticate(in long operationId);
 
     /**
      * detectInteraction:
@@ -199,17 +195,12 @@
      * SensorProps#supportsDetectInteraction is true. If invoked on implementations that do not
      * support this functionality, the HAL must respond with ISession#onError(UNABLE_TO_PROCESS, 0).
      *
-     * Once the HAL is able to start processing this request, it must notify the framework via
-     * ISessionCallback#onStateChanged with SessionState::DETECTING_INTERACTION.
-     *
      * The framework will use this method in cases where determing user presence is required, but
      * identifying/authentication is not. For example, when the device is encrypted (first boot) or
      * in lockdown mode.
      *
      * At any point during detectInteraction, if a non-recoverable error occurs, the HAL must notify
-     * the framework via ISessionCallback#onError with the applicable error, and then send
-     * ISessionCallback#onStateChanged(cookie, SessionState::IDLING) if no subsequent operation is
-     * in the queue.
+     * the framework via ISessionCallback#onError with the applicable error.
      *
      * The implementation must only check for a face-like image was detected (e.g. to
      * minimize interactions due to non-face objects), and the lockout counter must not
@@ -222,17 +213,14 @@
      * 1) Any face is detected and the framework is notified via
      *    ISessionCallback#onInteractiondetected
      * 2) The operation was cancelled by the framework (see ICancellationSignal)
-     * 3) The HAL ends the operation, for example when a subsequent operation pre-empts this one.
      *
      * Note that if the operation is canceled, the implementation must notify the framework via
      * ISessionCallback#onError with Error::CANCELED.
      *
-     * @param cookie An identifier used to track subsystem operations related to this call path.
-     *               The framework will guarantee that it is unique per ISession.
      * @return ICancellationSignal An object that can be used by the framework to cancel this
      * operation.
      */
-    ICancellationSignal detectInteraction(in int cookie);
+    ICancellationSignal detectInteraction();
 
     /*
      * enumerateEnrollments:
@@ -240,32 +228,22 @@
      * A request to enumerate (list) the enrollments for this (sensorId, userId) pair. The
      * framework typically uses this to ensure that its cache is in sync with the HAL.
      *
-     * Once the HAL is able to start processing this request, it must notify the framework via
-     * ISessionCallback#onStateChanged with SessionState::ENUMERATING_ENROLLMENTS.
-     *
      * The implementation must then notify the framework with a list of enrollments applicable
      * for the current session via ISessionCallback#onEnrollmentsEnumerated.
      *
-     * @param cookie An identifier used to track subsystem operations related to this call path.
-     *               The framework will guarantee that it is unique per ISession.
      */
-    void enumerateEnrollments(in int cookie);
+    void enumerateEnrollments();
 
     /**
      * removeEnrollments:
      *
      * A request to remove the enrollments for this (sensorId, userId) pair.
      *
-     * Once the HAL is able to start processing this request, it must notify the framework via
-     * ISessionCallback#onStateChanged with SessionState::REMOVING_ENROLLMENTS.
-     *
      * After removing the enrollmentIds from everywhere necessary (filesystem, secure subsystems,
      * etc), the implementation must notify the framework via ISessionCallback#onEnrollmentsRemoved.
      *
-     * @param cookie An identifier used to track subsystem operations related to this call path.
-     *               The framework will guarantee that it is unique per ISession.
      */
-    void removeEnrollments(in int cookie, in int[] enrollmentIds);
+    void removeEnrollments(in int[] enrollmentIds);
 
     /**
      * getFeatures:
@@ -273,20 +251,14 @@
      * Returns a list of currently enabled features for the provided enrollmentId.
      *
      * If the enrollmentId is invalid, the HAL must invoke ISessionCallback#onError with
-     * Error::UNABLE_TO_PROCESS and return to SessionState::IDLING if no subsequent work is in the
-     * queue.
-     *
-     * Once the HAL is able to start processing this request, it must notify the framework by using
-     * ISessionCallback#onStateChanged with SessionState::GETTING_FEATURES.
+     * Error::UNABLE_TO_PROCESS.
      *
      * The HAL must notify the framework about the result by calling
      * ISessionCallback#onFeaturesRetrieved.
      *
-     * @param cookie An identifier used to track subsystem operations related to this call path. The
-     *               client must guarantee that it is unique per ISession.
      * @param enrollmentId the ID of the enrollment for which the features are requested.
      */
-    void getFeatures(in int cookie, in int enrollmentId);
+    void getFeatures(in int enrollmentId);
 
     /**
      * setFeature:
@@ -296,24 +268,18 @@
      * (see @param hat). The HAL must verify the hat before changing any feature state.
      *
      * If either the hat or enrollmentId is invalid, the HAL must invoke ISessionCallback#onError
-     * with Error::UNABLE_TO_PROCESS and return to SessionState::IDLING if no subsequent work is in
-     * the queue.
-     *
-     * Once the HAL is able to start processing this request, it must notify the framework by using
-     * ISessionCallback#onStateChanged with SessionState::SETTING_FEATURE.
+     * with Error::UNABLE_TO_PROCESS.
      *
      * After the feature is successfully set, the HAL must notify the framework by calling
      * ISessionCallback#onFeatureSet.
      *
-     * @param cookie An identifier used to track subsystem operations related to this call path. The
-     *               client must guarantee that it is unique per ISession.
      * @param hat HardwareAuthToken See above documentation.
      * @param enrollmentId the ID of the enrollment for which the feature update is requested.
      * @param feature The feature to be enabled or disabled.
      * @param enabled Whether the provided features should be enabled or disabled.
      */
-    void setFeature(in int cookie, in HardwareAuthToken hat, in int enrollmentId,
-            in Feature feature, boolean enabled);
+    void setFeature(
+            in HardwareAuthToken hat, in int enrollmentId, in Feature feature, boolean enabled);
 
     /**
      * getAuthenticatorId:
@@ -341,10 +307,8 @@
      *   3) MUST not change if a face is deleted.
      *   4) MUST be an entropy-encoded random number
      *
-     * @param cookie An identifier used to track subsystem operations related to this call path. The
-     *               client must guarantee that it is unique per ISession.
      */
-    void getAuthenticatorId(in int cookie);
+    void getAuthenticatorId();
 
     /**
      * invalidateAuthenticatorId:
@@ -368,10 +332,8 @@
      * for more details). As such, the framework would coordinate invalidation across multiple
      * biometric HALs as necessary.
      *
-     * @param cookie An identifier used to track subsystem operations related to this call path. The
-     *               client must guarantee that it is unique per ISession.
      */
-    void invalidateAuthenticatorId(in int cookie);
+    void invalidateAuthenticatorId();
 
     /**
      * resetLockout:
@@ -382,8 +344,7 @@
      *   2) Verify that the timestamp provided within the HAT is relatively recent (e.g. on the
      *      order of minutes, not hours).
      * If either of the checks fail, the HAL must invoke ISessionCallback#onError with
-     * Error::UNABLE_TO_PROCESS and return to SessionState::IDLING if no subsequent work is in the
-     * queue.
+     * Error::UNABLE_TO_PROCESS.
      *
      * Upon successful verification, the HAL must clear the lockout counter and notify the framework
      * via ISessionCallback#onLockoutCleared.
@@ -414,27 +375,20 @@
      * See the Android CDD section 7.3.10 for the full set of lockout and rate-limiting
      * requirements.
      *
-     * @param cookie An identifier used to track subsystem operations related to this call path. The
-     *               client must guarantee that it is unique per ISession.
      * @param hat HardwareAuthToken See above documentation.
      */
-    void resetLockout(in int cookie, in HardwareAuthToken hat);
+    void resetLockout(in HardwareAuthToken hat);
 
     /*
      * Close this session and allow the HAL to release the resources associated with this session.
      *
-     * A session can only be closed when it's in SessionState::IDLING. Closing a session will
-     * result in a ISessionCallback#onStateChanged call with SessionState::CLOSED.
-     *
-     * If a session is unresponsive or stuck in a state other than SessionState::CLOSED,
-     * IFace#reset could be used as a last resort to terminate the session and recover the HAL
-     * from a bad state.
+     * A session can only be closed when the HAL is idling, i.e. not performing any operations.
+     * If the HAL is busy performing a cancellable operation, the operation must be explicitly
+     * cancelled with a call to ICancellationSignal#cancel before the session can be closed.
      *
      * All sessions must be explicitly closed. Calling IFace#createSession while there is an active
      * session is considered an error.
      *
-     * @param cookie An identifier used to track subsystem operations related to this call path. The
-     *               client must guarantee that it is unique per ISession.
      */
-    void close(in int cookie);
+    void close();
 }
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl
index c1aa3fc..a2601e7 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl
@@ -21,17 +21,11 @@
 import android.hardware.biometrics.face.EnrollmentFrame;
 import android.hardware.biometrics.face.Error;
 import android.hardware.biometrics.face.Feature;
-import android.hardware.biometrics.face.SessionState;
 import android.hardware.keymaster.HardwareAuthToken;
 
 @VintfStability
 interface ISessionCallback {
     /**
-     * Used to notify the framework of session state changes. See ISession for more information.
-     */
-    void onStateChanged(in int cookie, in SessionState state);
-
-    /**
      * Notifies the framework when a challenge is successfully generated.
      */
     void onChallengeGenerated(in long challenge);
@@ -42,9 +36,9 @@
     void onChallengeRevoked(in long challenge);
 
     /**
-     * This method must only be used to notify the framework during the following states:
-     *   1) SessionState::AUTHENTICATING
-     *   2) SessionState::DETECTING_INTERACTION
+     * This method must only be used to notify the framework during the following operations:
+     *   1) ISession#authenticate
+     *   2) ISession#detectInteraction
      *
      * These messages may be used to provide user guidance multiple times if necessary per
      * operation.
@@ -54,8 +48,8 @@
     void onAuthenticationFrame(in AuthenticationFrame frame);
 
     /**
-     * This method must only be used to notify the framework during the SessionState::ENROLLING
-     * state.
+     * This method must only be used to notify the framework during the ISession#enroll
+     * operation.
      *
      * These messages may be used to provide user guidance multiple times if necessary per
      * operation.
@@ -65,18 +59,18 @@
     void onEnrollmentFrame(in EnrollmentFrame frame);
 
     /**
-     * This method must only be used to notify the framework during the following states:
-     *   1) SessionState::ENROLLING
-     *   2) SessionState::AUTHENTICATING
-     *   3) SessionState::DETECTING_INTERACTION
-     *   4) SessionState::INVALIDATING_AUTHENTICATOR_ID
-     *   5) SessionState::RESETTING_LOCKOUT
+     * This method must only be used to notify the framework during the following operations:
+     *   1) ISession#enroll
+     *   2) ISession#authenticate
+     *   3) ISession#detectInteraction
+     *   4) ISession#invalidateAuthenticatorId
+     *   5) ISession#resetLockout
      *
      * These messages may be used to notify the framework or user that a non-recoverable error
      * has occurred. The operation is finished, and the HAL must proceed with the next operation
-     * or return to SessionState::IDLING if the queue is empty.
+     * or return to the idling state.
      *
-     * Note that cancellation (see common::ICancellationSignal) and preemption most be followed with
+     * Note that cancellation (see common::ICancellationSignal) and preemption must be followed with
      * an Error::CANCELED message.
      *
      * @param error See the Error enum.
@@ -88,8 +82,7 @@
     void onError(in Error error, in int vendorCode);
 
     /**
-     * This method must only be used to notify the framework during the following state:
-     *   1) SessionState::ENROLLING
+     * This method must only be used to notify the framework during the ISession#enroll operation.
      *
      * @param enrollmentId Unique stable identifier for the enrollment that's being added by this
      *                     ISession#enroll invocation.
@@ -98,7 +91,7 @@
     void onEnrollmentProgress(in int enrollmentId, int remaining);
 
     /**
-     * This method must only be used to notify the framework during SessionState::AUTHENTICATING.
+     * This method must only be used to notify the framework during ISession#authenticate.
      *
      * Used to notify the framework about a successful authentication. This ends the authentication
      * lifecycle.
@@ -112,7 +105,7 @@
     void onAuthenticationSucceeded(in int enrollmentId, in HardwareAuthToken hat);
 
     /**
-     * This method must only be used to notify the framework during SessionState::AUTHENTICATING.
+     * This method must only be used to notify the framework during ISession#authenticate.
      *
      * Used to notify the framework about a failed authentication. This ends the authentication
      * lifecycle.
@@ -120,7 +113,7 @@
     void onAuthenticationFailed();
 
     /**
-     * This method must only be used to notify the framework during SessionState::AUTHENTICATING.
+     * This method must only be used to notify the framework during ISession#authenticate.
      *
      * Authentication is locked out due to too many unsuccessful attempts. This is a rate-limiting
      * lockout, and authentication can be restarted after a period of time. See
@@ -133,7 +126,7 @@
     void onLockoutTimed(in long durationMillis);
 
     /**
-     * This method must only be used to notify the framework during SessionState::AUTHENTICATING.
+     * This method must only be used to notify the framework during ISession#authenticate.
      *
      * Authentication is disabled until the user unlocks with their device credential
      * (PIN/Pattern/Password). See ISession#resetLockout.
@@ -160,7 +153,7 @@
 
     /**
      * This method must only be used to notify the framework during
-     * SessionState::DETECTING_INTERACTION
+     * ISession#detectInteraction
      *
      * Notifies the framework that user interaction occurred. See ISession#detectInteraction.
      */
@@ -168,7 +161,7 @@
 
     /**
      * This method must only be used to notify the framework during
-     * SessionState::ENUMERATING_ENROLLMENTS.
+     * ISession#enumerateEnrollments.
      *
      * Notifies the framework of the current enrollments. See ISession#enumerateEnrollments.
      *
@@ -177,7 +170,7 @@
     void onEnrollmentsEnumerated(in int[] enrollmentIds);
 
     /**
-     * This method must only be used to notify the framework during SessionState::GETTING_FEATURES.
+     * This method must only be used to notify the framework during ISession#getFeatures.
      *
      * Provides a list of features that are currently enabled for the given enrollmentId.
      *
@@ -187,7 +180,7 @@
     void onFeaturesRetrieved(in Feature[] features, in int enrollmentId);
 
     /**
-     * This method must only be used to notify the framework during SessionState::SETTING_FEATURE.
+     * This method must only be used to notify the framework during ISession#setFeature.
      *
      * Notifies the framework that ISession#setFeature has completed.
      *
@@ -198,7 +191,7 @@
 
     /**
      * This method must only be used to notify the framework during
-     * SessionState::REMOVING_ENROLLMENTS.
+     * ISession#removeEnrollments.
      *
      * Notifies the framework that the specified enrollments are removed.
      *
@@ -208,7 +201,7 @@
 
     /**
      * This method must only be used to notify the framework during
-     * SessionState::GETTING_AUTHENTICATOR_ID.
+     * ISession#getAuthenticatorId.
      *
      * Notifies the framework with the authenticatorId corresponding to this session's
      * (userId, sensorId) pair.
@@ -219,7 +212,7 @@
 
     /**
      * This method must only be used to notify the framework during
-     * SessionState::INVALIDATING_AUTHENTICATOR_ID.
+     * ISession#invalidateAuthenticatorId.
      *
      * See ISession#invalidateAuthenticatorId for more information.
      *
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/SessionState.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/SessionState.aidl
deleted file mode 100644
index afde4eb..0000000
--- a/biometrics/face/aidl/android/hardware/biometrics/face/SessionState.aidl
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.biometrics.face;
-
-@VintfStability
-@Backing(type="byte")
-enum SessionState {
-    /**
-     * The HAL is not processing any session requests.
-     */
-    IDLING,
-
-    /**
-     * The session has been closed by the client.
-     */
-    CLOSED,
-
-    /**
-     * The HAL is processing the ISession#generateChallenge request.
-     */
-    GENERATING_CHALLENGE,
-
-    /**
-     * The HAL is processing the ISession#revokeChallenge request.
-     */
-    REVOKING_CHALLENGE,
-
-    /**
-     * The HAL is processing the ISession#enroll request.
-     */
-    ENROLLING,
-
-    /**
-     * The HAL is processing the ISession#authenticate request.
-     */
-    AUTHENTICATING,
-
-    /**
-     * The HAL is processing the ISession#detectInteraction request.
-     */
-    DETECTING_INTERACTION,
-
-    /**
-     * The HAL is processing the ISession#enumerateEnrollments request.
-     */
-    ENUMERATING_ENROLLMENTS,
-
-    /**
-     * The HAL is processing the ISession#removeEnrollments request.
-     */
-    REMOVING_ENROLLMENTS,
-
-    /**
-     * The HAL is processing the ISession#getFeatures request.
-     */
-    GETTING_FEATURES,
-
-    /**
-     * The HAL is processing the ISession#setFeature request.
-     */
-    SETTING_FEATURE,
-
-    /**
-     * The HAL is processing the ISession#getAuthenticatorId request.
-     */
-    GETTING_AUTHENTICATOR_ID,
-
-    /**
-     * The HAL is processing the ISession#invalidateAuthenticatorId request.
-     */
-    INVALIDATING_AUTHENTICATOR_ID,
-
-    /**
-     * The HAL is processing the ISession#resetLockout request.
-     */
-    RESETTING_LOCKOUT
-}
diff --git a/biometrics/face/aidl/default/Session.cpp b/biometrics/face/aidl/default/Session.cpp
index ce6c557..b5eb717 100644
--- a/biometrics/face/aidl/default/Session.cpp
+++ b/biometrics/face/aidl/default/Session.cpp
@@ -30,119 +30,105 @@
 
     ndk::ScopedAStatus cancel() override {
         cb_->onError(Error::CANCELED, 0 /* vendorCode */);
-        cb_->onStateChanged(0, SessionState::IDLING);
         return ndk::ScopedAStatus::ok();
     }
 };
 
 Session::Session(std::shared_ptr<ISessionCallback> cb) : cb_(std::move(cb)) {}
 
-ndk::ScopedAStatus Session::generateChallenge(int32_t /*cookie*/) {
+ndk::ScopedAStatus Session::generateChallenge() {
     LOG(INFO) << "generateChallenge";
     if (cb_) {
-        cb_->onStateChanged(0, SessionState::GENERATING_CHALLENGE);
         cb_->onChallengeGenerated(0);
-        cb_->onStateChanged(0, SessionState::IDLING);
     }
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Session::revokeChallenge(int32_t /*cookie*/, int64_t challenge) {
+ndk::ScopedAStatus Session::revokeChallenge(int64_t challenge) {
     LOG(INFO) << "revokeChallenge";
     if (cb_) {
-        cb_->onStateChanged(0, SessionState::REVOKING_CHALLENGE);
         cb_->onChallengeRevoked(challenge);
-        cb_->onStateChanged(0, SessionState::IDLING);
     }
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus Session::enroll(
-        int32_t /*cookie*/, const keymaster::HardwareAuthToken& /*hat*/,
-        EnrollmentType /*enrollmentType*/, const std::vector<Feature>& /*features*/,
-        const NativeHandle& /*previewSurface*/,
+        const keymaster::HardwareAuthToken& /*hat*/, EnrollmentType /*enrollmentType*/,
+        const std::vector<Feature>& /*features*/, const NativeHandle& /*previewSurface*/,
         std::shared_ptr<biometrics::common::ICancellationSignal>* /*return_val*/) {
     LOG(INFO) << "enroll";
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Session::authenticate(int32_t /*cookie*/, int64_t /*keystoreOperationId*/,
+ndk::ScopedAStatus Session::authenticate(int64_t /*keystoreOperationId*/,
                                          std::shared_ptr<common::ICancellationSignal>* return_val) {
     LOG(INFO) << "authenticate";
     if (cb_) {
-        cb_->onStateChanged(0, SessionState::AUTHENTICATING);
+        cb_->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */);
     }
     *return_val = SharedRefBase::make<CancellationSignal>(cb_);
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus Session::detectInteraction(
-        int32_t /*cookie*/, std::shared_ptr<common::ICancellationSignal>* /*return_val*/) {
+        std::shared_ptr<common::ICancellationSignal>* /*return_val*/) {
     LOG(INFO) << "detectInteraction";
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Session::enumerateEnrollments(int32_t /*cookie*/) {
+ndk::ScopedAStatus Session::enumerateEnrollments() {
     LOG(INFO) << "enumerateEnrollments";
     if (cb_) {
-        cb_->onStateChanged(0, SessionState::ENUMERATING_ENROLLMENTS);
         cb_->onEnrollmentsEnumerated(std::vector<int32_t>());
-        cb_->onStateChanged(0, SessionState::IDLING);
     }
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Session::removeEnrollments(int32_t /*cookie*/,
-                                              const std::vector<int32_t>& /*enrollmentIds*/) {
+ndk::ScopedAStatus Session::removeEnrollments(const std::vector<int32_t>& /*enrollmentIds*/) {
     LOG(INFO) << "removeEnrollments";
     if (cb_) {
-        cb_->onStateChanged(0, SessionState::REMOVING_ENROLLMENTS);
         cb_->onEnrollmentsRemoved(std::vector<int32_t>());
-        cb_->onStateChanged(0, SessionState::IDLING);
     }
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Session::getFeatures(int32_t /*cookie*/, int32_t /*enrollmentId*/) {
+ndk::ScopedAStatus Session::getFeatures(int32_t /*enrollmentId*/) {
     LOG(INFO) << "getFeatures";
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Session::setFeature(int32_t /*cookie*/,
-                                       const keymaster::HardwareAuthToken& /*hat*/,
+ndk::ScopedAStatus Session::setFeature(const keymaster::HardwareAuthToken& /*hat*/,
                                        int32_t /*enrollmentId*/, Feature /*feature*/,
                                        bool /*enabled*/) {
     LOG(INFO) << "setFeature";
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Session::getAuthenticatorId(int32_t /*cookie*/) {
+ndk::ScopedAStatus Session::getAuthenticatorId() {
     LOG(INFO) << "getAuthenticatorId";
     if (cb_) {
-        cb_->onStateChanged(0, SessionState::GETTING_AUTHENTICATOR_ID);
         cb_->onAuthenticatorIdRetrieved(0 /* authenticatorId */);
-        cb_->onStateChanged(0, SessionState::IDLING);
     }
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Session::invalidateAuthenticatorId(int32_t /*cookie*/) {
+ndk::ScopedAStatus Session::invalidateAuthenticatorId() {
     LOG(INFO) << "invalidateAuthenticatorId";
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Session::resetLockout(int32_t /*cookie*/,
-                                         const keymaster::HardwareAuthToken& /*hat*/) {
+ndk::ScopedAStatus Session::resetLockout(const keymaster::HardwareAuthToken& /*hat*/) {
     LOG(INFO) << "resetLockout";
     if (cb_) {
-        cb_->onStateChanged(0, SessionState::RESETTING_LOCKOUT);
         cb_->onLockoutCleared();
-        cb_->onStateChanged(0, SessionState::IDLING);
     }
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Session::close(int32_t /*cookie*/) {
+ndk::ScopedAStatus Session::close() {
+    if (cb_) {
+        cb_->onSessionClosed();
+    }
     return ndk::ScopedAStatus::ok();
 }
 
diff --git a/biometrics/face/aidl/default/Session.h b/biometrics/face/aidl/default/Session.h
index eb9ae83..73cdf08 100644
--- a/biometrics/face/aidl/default/Session.h
+++ b/biometrics/face/aidl/default/Session.h
@@ -30,40 +30,38 @@
   public:
     explicit Session(std::shared_ptr<ISessionCallback> cb);
 
-    ndk::ScopedAStatus generateChallenge(int32_t cookie) override;
+    ndk::ScopedAStatus generateChallenge() override;
 
-    ndk::ScopedAStatus revokeChallenge(int32_t cookie, int64_t challenge) override;
+    ndk::ScopedAStatus revokeChallenge(int64_t challenge) override;
 
-    ndk::ScopedAStatus enroll(int32_t cookie, const keymaster::HardwareAuthToken& hat,
+    ndk::ScopedAStatus enroll(const keymaster::HardwareAuthToken& hat,
                               EnrollmentType enrollmentType, const std::vector<Feature>& features,
                               const NativeHandle& previewSurface,
                               std::shared_ptr<common::ICancellationSignal>* return_val) override;
 
     ndk::ScopedAStatus authenticate(
-            int32_t cookie, int64_t keystoreOperationId,
+            int64_t keystoreOperationId,
             std::shared_ptr<common::ICancellationSignal>* returnVal) override;
 
     ndk::ScopedAStatus detectInteraction(
-            int32_t cookie, std::shared_ptr<common::ICancellationSignal>* returnVal) override;
+            std::shared_ptr<common::ICancellationSignal>* returnVal) override;
 
-    ndk::ScopedAStatus enumerateEnrollments(int32_t cookie) override;
+    ndk::ScopedAStatus enumerateEnrollments() override;
 
-    ndk::ScopedAStatus removeEnrollments(int32_t cookie,
-                                         const std::vector<int32_t>& enrollmentIds) override;
+    ndk::ScopedAStatus removeEnrollments(const std::vector<int32_t>& enrollmentIds) override;
 
-    ndk::ScopedAStatus getFeatures(int32_t cookie, int32_t enrollmentId) override;
+    ndk::ScopedAStatus getFeatures(int32_t enrollmentId) override;
 
-    ndk::ScopedAStatus setFeature(int32_t cookie, const keymaster::HardwareAuthToken& hat,
-                                  int32_t enrollmentId, Feature feature, bool enabled) override;
+    ndk::ScopedAStatus setFeature(const keymaster::HardwareAuthToken& hat, int32_t enrollmentId,
+                                  Feature feature, bool enabled) override;
 
-    ndk::ScopedAStatus getAuthenticatorId(int32_t cookie) override;
+    ndk::ScopedAStatus getAuthenticatorId() override;
 
-    ndk::ScopedAStatus invalidateAuthenticatorId(int32_t cookie) override;
+    ndk::ScopedAStatus invalidateAuthenticatorId() override;
 
-    ndk::ScopedAStatus resetLockout(int32_t cookie,
-                                    const keymaster::HardwareAuthToken& hat) override;
+    ndk::ScopedAStatus resetLockout(const keymaster::HardwareAuthToken& hat) override;
 
-    ndk::ScopedAStatus close(int32_t cookie) override;
+    ndk::ScopedAStatus close() override;
 
   private:
     std::shared_ptr<ISessionCallback> cb_;
diff --git a/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp b/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
index 936fcc6..60e0a2a 100644
--- a/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
+++ b/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
@@ -21,35 +21,31 @@
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
 
+#include <chrono>
 #include <future>
 
 namespace aidl::android::hardware::biometrics::face {
 namespace {
 
+using namespace std::literals::chrono_literals;
+
 constexpr int kSensorId = 0;
 constexpr int kUserId = 0;
-constexpr auto kCallbackTimeout = std::chrono::seconds(1);
 
-enum class SessionCallbackMethodName {
-    kOnStateChanged,
+enum class MethodName {
+    kOnError,
+    kOnSessionClosed,
 };
 
-struct SessionCallbackInvocation {
-    SessionCallbackMethodName method_name;
-    SessionState state;
+struct Invocation {
+    MethodName methodName;
+    Error error;
+    int32_t vendorCode;
 };
 
 class SessionCallback : public BnSessionCallback {
   public:
-    explicit SessionCallback(std::promise<SessionCallbackInvocation> invocation_promise)
-        : invocation_promise_(std::move(invocation_promise)) {}
-    ndk::ScopedAStatus onStateChanged(int32_t /*cookie*/, SessionState state) override {
-        SessionCallbackInvocation invocation = {};
-        invocation.method_name = SessionCallbackMethodName::kOnStateChanged;
-        invocation.state = state;
-        invocation_promise_.set_value(invocation);
-        return ndk::ScopedAStatus::ok();
-    }
+    explicit SessionCallback(Invocation* inv) : mInv(inv) {}
 
     ndk::ScopedAStatus onChallengeGenerated(int64_t /*challenge*/) override {
         return ndk::ScopedAStatus::ok();
@@ -67,7 +63,12 @@
         return ndk::ScopedAStatus::ok();
     }
 
-    ndk::ScopedAStatus onError(Error /*error*/, int32_t /*vendorCode*/) override {
+    ndk::ScopedAStatus onError(Error error, int32_t vendorCode) override {
+        *mInv = {};
+        mInv->methodName = MethodName::kOnError;
+        mInv->error = error;
+        mInv->vendorCode = vendorCode;
+
         return ndk::ScopedAStatus::ok();
     }
 
@@ -120,10 +121,15 @@
         return ndk::ScopedAStatus::ok();
     }
 
-    ndk::ScopedAStatus onSessionClosed() override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus onSessionClosed() override {
+        *mInv = {};
+        mInv->methodName = MethodName::kOnSessionClosed;
+
+        return ndk::ScopedAStatus::ok();
+    }
 
   private:
-    std::promise<SessionCallbackInvocation> invocation_promise_;
+    Invocation* mInv;
 };
 
 class Face : public testing::TestWithParam<std::string> {
@@ -131,28 +137,34 @@
     void SetUp() override {
         AIBinder* binder = AServiceManager_waitForService(GetParam().c_str());
         ASSERT_NE(binder, nullptr);
-        hal_ = IFace::fromBinder(ndk::SpAIBinder(binder));
+        mHal = IFace::fromBinder(ndk::SpAIBinder(binder));
     }
 
-    std::shared_ptr<IFace> hal_;
+    std::shared_ptr<IFace> mHal;
+    Invocation mInv;
 };
 
 TEST_P(Face, AuthenticateTest) {
-    std::promise<SessionCallbackInvocation> invocation_promise;
-    std::future<SessionCallbackInvocation> invocation_future = invocation_promise.get_future();
-    std::shared_ptr<SessionCallback> session_cb =
-            ndk::SharedRefBase::make<SessionCallback>(std::move(invocation_promise));
+    // Prepare the callback.
+    auto cb = ndk::SharedRefBase::make<SessionCallback>(&mInv);
 
+    // Create a session
     std::shared_ptr<ISession> session;
-    ASSERT_TRUE(hal_->createSession(kSensorId, kUserId, session_cb, &session).isOk());
+    ASSERT_TRUE(mHal->createSession(kSensorId, kUserId, cb, &session).isOk());
 
-    std::shared_ptr<common::ICancellationSignal> cancel_cb;
-    ASSERT_TRUE(session->authenticate(0, 0, &cancel_cb).isOk());
-    ASSERT_EQ(invocation_future.wait_for(kCallbackTimeout), std::future_status::ready);
+    // Call authenticate
+    std::shared_ptr<common::ICancellationSignal> cancellationSignal;
+    ASSERT_TRUE(session->authenticate(0 /* operationId */, &cancellationSignal).isOk());
 
-    SessionCallbackInvocation invocation = invocation_future.get();
-    EXPECT_EQ(invocation.method_name, SessionCallbackMethodName::kOnStateChanged);
-    EXPECT_EQ(invocation.state, SessionState::AUTHENTICATING);
+    // Get the results
+    EXPECT_EQ(mInv.methodName, MethodName::kOnError);
+    EXPECT_EQ(mInv.error, Error::UNABLE_TO_PROCESS);
+    EXPECT_EQ(mInv.vendorCode, 0);
+
+    // Close the session
+    ASSERT_TRUE(session->close().isOk());
+
+    EXPECT_EQ(mInv.methodName, MethodName::kOnSessionClosed);
 }
 
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Face);
@@ -161,6 +173,7 @@
                          ::android::PrintInstanceNameToString);
 
 }  // namespace
+}  // namespace aidl::android::hardware::biometrics::face
 
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
@@ -169,4 +182,3 @@
     return RUN_ALL_TESTS();
 }
 
-}  // namespace aidl::android::hardware::biometrics::face
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl
index 87eaf96..9934a76 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl
@@ -34,17 +34,17 @@
 package android.hardware.biometrics.fingerprint;
 @VintfStability
 interface ISession {
-  void generateChallenge(in int cookie);
-  void revokeChallenge(in int cookie, in long challenge);
-  android.hardware.biometrics.common.ICancellationSignal enroll(in int cookie, in android.hardware.keymaster.HardwareAuthToken hat);
-  android.hardware.biometrics.common.ICancellationSignal authenticate(in int cookie, in long operationId);
-  android.hardware.biometrics.common.ICancellationSignal detectInteraction(in int cookie);
-  void enumerateEnrollments(in int cookie);
-  void removeEnrollments(in int cookie, in int[] enrollmentIds);
-  void getAuthenticatorId(in int cookie);
-  void invalidateAuthenticatorId(in int cookie);
-  void resetLockout(in int cookie, in android.hardware.keymaster.HardwareAuthToken hat);
-  void close(in int cookie);
+  void generateChallenge();
+  void revokeChallenge(in long challenge);
+  android.hardware.biometrics.common.ICancellationSignal enroll(in android.hardware.keymaster.HardwareAuthToken hat);
+  android.hardware.biometrics.common.ICancellationSignal authenticate(in long operationId);
+  android.hardware.biometrics.common.ICancellationSignal detectInteraction();
+  void enumerateEnrollments();
+  void removeEnrollments(in int[] enrollmentIds);
+  void getAuthenticatorId();
+  void invalidateAuthenticatorId();
+  void resetLockout(in android.hardware.keymaster.HardwareAuthToken hat);
+  void close();
   void onPointerDown(in int pointerId, in int x, in int y, in float minor, in float major);
   void onPointerUp(in int pointerId);
   void onUiReady();
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
index 3a97717..3c40ad6 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
@@ -34,7 +34,6 @@
 package android.hardware.biometrics.fingerprint;
 @VintfStability
 interface ISessionCallback {
-  void onStateChanged(in int cookie, in android.hardware.biometrics.fingerprint.SessionState state);
   void onChallengeGenerated(in long challenge);
   void onChallengeRevoked(in long challenge);
   void onAcquired(in android.hardware.biometrics.fingerprint.AcquiredInfo info, in int vendorCode);
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SessionState.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SessionState.aidl
deleted file mode 100644
index 9b0b6f6..0000000
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SessionState.aidl
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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.biometrics.fingerprint;
-@Backing(type="byte") @VintfStability
-enum SessionState {
-  IDLING = 0,
-  CLOSED = 1,
-  GENERATING_CHALLENGE = 2,
-  REVOKING_CHALLENGE = 3,
-  ENROLLING = 4,
-  AUTHENTICATING = 5,
-  DETECTING_INTERACTION = 6,
-  ENUMERATING_ENROLLMENTS = 7,
-  REMOVING_ENROLLMENTS = 8,
-  GETTING_AUTHENTICATOR_ID = 9,
-  INVALIDATING_AUTHENTICATOR_ID = 10,
-  RESETTING_LOCKOUT = 11,
-}
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl
index 98a4530..271a9bf 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl
@@ -32,27 +32,14 @@
     /**
      * createSession:
      *
-     * Creates a session which can then be used by the framework to perform operations such as
-     * enroll, authenticate, etc for the given sensorId and userId.
+     * Creates a instance of ISession which can be used by the framework to perform operations
+     * such as ISession#enroll, ISession#authenticate, etc. for the given sensorId and userId.
      *
-     * Calling this method while there is an active session is considered an error. If the
-     * framework is in a bad state and for some reason cannot close its session, it should use
-     * the reset method below.
-     *
-     * A physical sensor identified by sensorId typically supports only a single in-flight session
-     * at a time. As such, if a session is currently in a state other than SessionState::IDLING, the
-     * HAL MUST finish or cancel the current operation and return to SessionState::IDLING before the
-     * new session is created. For example:
-     *   1) If a session for sensorId=0, userId=0 is currently in a cancellable state (see
-     *      ICancellationSignal) such as SessionState::AUTHENTICATING and the framework requests a
-     *      new session for sensorId=0, userId=10, the HAL must end the current session with
-     *      Error::CANCELED, invoke ISessionCallback#onStateChanged with SessionState::IDLING, and
-     *      then return a new session for sensorId=0, userId=10.
-     *   2) If a session for sensorId=0, userId=0 is currently in a non-cancellable state such as
-     *      SessionState::REMOVING_ENROLLMENTS, and the framework requests a new session for
-     *      sensorId=0, userId=10, the HAL must finish the current operation before invoking
-     *      ISessionCallback#onStateChanged with SessionState::IDLING, and return a new session for
-     *      sensorId=0, userId=10.
+     * Calling this method while there is an active session is considered an error. If the framework
+     * wants to create a new session when it already has an active session, it must first cancel the
+     * current operation if it's cancellable, or wait until it completes. Then, the framework must
+     * explicitly close the session with ISession#close. Once the framework receives
+     * ISessionCallback#onSessionClosed, a new session can be created.
      *
      * Implementations must store user-specific state or metadata in /data/vendor_de/<user>/fpdata
      * as specified by the SeLinux policy. This directory is created/removed by vold (see
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
index ef2e6fc..940548b 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
@@ -22,23 +22,28 @@
 /**
  * Operations that can be performed for unique sessions retrieved via IFingerprint#createSession.
  * Methods defined within this interface can be split into the following categories:
- *   1) Methods associated with a state (see the SessionState enum). State-based operations are
- *      handled by the HAL in FIFO order.
- *   1a) Cancellable state-based operations. If a cancellable operation is in-progress and the
- *       framework requests a subsequent state-based operation, the implementation should finish
- *       the operation via ISessionCallback#onError with Error::CANCELED.
- *   1b) Non-cancellable state-based operations. These operations should fully complete before the
- *       next state-based operation can be started.
- *   2) Methods without a state. These methods may be invoked by the framework depending on its
- *      use case. For example on devices with sensors of FingerprintSensorType::UNDER_DISPLAY_*,
- *      ISession#onFingerDown may be invoked while the HAL is in SessionState::ENROLLING,
- *      SessionState::AUTHENTICATING, or SessionState::DETECTING_INTERACTION.
+ *   1) Non-interrupting operations. These operations are handled by the HAL in FIFO order.
+ *   1a) Cancellable operations. These are usually the operations that can execute for several
+ *       minutes. To allow for cancellation, they return an instance of ICancellationSignal that
+ *       lets the framework cancel them by calling ICancellationSignal#cancel. If such an operation
+ *       is cancelled, it must notify the framework by calling ISessionCallback#onError with
+ *       Error::CANCELED.
+ *   1b) Non-cancellable operations. Such operations cannot be cancelled once started.
+ *   2) Interrupting operations. These operations may be invoked by the framework immediately,
+ *      regardless of whether another operation is executing. For example, on devices with sensors
+ *      of FingerprintSensorType::UNDER_DISPLAY_*, ISession#onFingerDown may be invoked while the
+ *      HAL is executing ISession#enroll, ISession#authenticate or ISession#detectInteraction.
  *
- * If the HAL has multiple operations in its queue, it is not required to notify the framework
- * of SessionState::IDLING between each operation. However, it must notify the framework when all
- * work is completed. See ISessionCallback#onStateChanged. For example, the following is a valid
- * sequence of ISessionCallback#onStateChanged invocations: SessionState::IDLING -->
- * SessionState::ENROLLING --> SessionState::ENUMERATING_ENROLLMENTS --> SessionState::IDLING.
+ * The lifecycle of a non-interrupting operation ends when one of its terminal callbacks is called.
+ * For example, ISession#authenticate is considered completed when either of the following callbacks
+ * is called: ISessionCallback#onError or ISessionCallback#onAuthenticationSucceeded.
+ *
+ * The lifecycle of an interrupting operation ends when it returns. Interrupting operations do not
+ * have callbacks.
+ *
+ * ISession only supports execution of one non-interrupting operation at a time, regardless of
+ * whether it's cancellable. The framework must wait for a corresponding callback indicating the end of
+ * the current non-interrupting operation before a new non-interrupting operation can be started.
  */
 @VintfStability
 interface ISession {
@@ -84,9 +89,8 @@
      * | 0        | 10     | <Time4>    | <Random4> |
      * ----------------------------------------------
      *
-     * @param cookie A unique number identifying this operation
      */
-    void generateChallenge(in int cookie);
+    void generateChallenge();
 
     /**
      * revokeChallenge:
@@ -95,23 +99,17 @@
      * parameters is requested, the implementation must still notify the framework using the
      * provided callback.
      *
-     * @param cookie A unique number identifying this operation
      * @param challenge Challenge that should be revoked.
      */
-    void revokeChallenge(in int cookie, in long challenge);
+    void revokeChallenge(in long challenge);
 
     /**
      * enroll:
      *
      * A request to add a fingerprint enrollment.
      *
-     * Once the HAL is able to start processing the enrollment request, it must notify the framework
-     * via ISessionCallback#onStateChanged with SessionState::ENROLLING.
-     *
      * At any point during enrollment, if a non-recoverable error occurs, the HAL must notify the
-     * framework via ISessionCallback#onError with the applicable enrollment-specific error, and
-     * then send ISessionCallback#onStateChanged(cookie, SessionState::IDLING) if no subsequent
-     * operation is in the queue.
+     * framework via ISessionCallback#onError with the applicable enrollment-specific error.
      *
      * Before capturing fingerprint data, the implementation must first verify the authenticity and
      * integrity of the provided HardwareAuthToken. In addition, it must check that the challenge
@@ -132,24 +130,17 @@
      * implementation MUST update and associate this (sensorId, userId) pair with a new new
      * entropy-encoded random identifier. See ISession#getAuthenticatorId for more information.
      *
-     * @param cookie An identifier used to track subsystem operations related to this call path. The
-     *               client must guarantee that it is unique per ISession.
      * @param hat See above documentation.
      */
-    ICancellationSignal enroll(in int cookie, in HardwareAuthToken hat);
+    ICancellationSignal enroll(in HardwareAuthToken hat);
 
     /**
      * authenticate:
      *
      * A request to start looking for fingerprints to authenticate.
      *
-     * Once the HAL is able to start processing the authentication request, it must notify framework
-     * via ISessionCallback#onStateChanged with SessionState::AUTHENTICATING.
-     *
      * At any point during authentication, if a non-recoverable error occurs, the HAL must notify
-     * the framework via ISessionCallback#onError with the applicable authentication-specific error,
-     * and then send ISessionCallback#onStateChanged(cookie, SessionState::IDLING) if no
-     * subsequent operation is in the queue.
+     * the framework via ISessionCallback#onError with the applicable authentication-specific error.
      *
      * During authentication, the implementation may notify the framework via
      * ISessionCallback#onAcquired with messages that may be used to guide the user. This callback
@@ -171,8 +162,6 @@
      * must be set with the operationId passed in during #authenticate. If the sensor is NOT
      * SensorStrength::STRONG, the HardwareAuthToken MUST be null.
      *
-     * @param cookie An identifier used to track subsystem operations related to this call path. The
-     *               client must guarantee that it is unique per ISession.
      * @param operationId For sensors configured as SensorStrength::STRONG, this must be used ONLY
      *                    upon successful authentication and wrapped in the HardwareAuthToken's
      *                    "challenge" field and sent to the framework via
@@ -184,7 +173,7 @@
      *                    setUserAuthenticationParameters in KeyGenParameterSpec.Builder and
      *                    KeyProtection.Builder.
      */
-    ICancellationSignal authenticate(in int cookie, in long operationId);
+    ICancellationSignal authenticate(in long operationId);
 
     /**
      * detectInteraction:
@@ -193,17 +182,12 @@
      * if SensorProps#supportsDetectInteraction is true. If invoked on implementations that do not
      * support this functionality, the HAL must respond with ISession#onError(UNABLE_TO_PROCESS, 0).
      *
-     * Once the HAL is able to start processing this request, it must notify the framework via
-     * ISessionCallback#onStateChanged with SessionState::DETECTING_INTERACTION.
-     *
      * The framework will use this method in cases where determing user presence is required, but
      * identifying/authentication is not. For example, when the device is encrypted (first boot) or
      * in lockdown mode.
      *
      * At any point during detectInteraction, if a non-recoverable error occurs, the HAL must notify
-     * the framework via ISessionCallback#onError with the applicable error, and then send
-     * ISessionCallback#onStateChanged(cookie, SessionState::IDLING) if no subsequent operation is
-     * in the queue.
+     * the framework via ISessionCallback#onError with the applicable error.
      *
      * The implementation must only check for a fingerprint-like image was detected (e.g. to
      * minimize interactions due to non-fingerprint objects), and the lockout counter must not
@@ -221,10 +205,8 @@
      * Note that if the operation is canceled, the implementation must notify the framework via
      * ISessionCallback#onError with Error::CANCELED.
      *
-     * @param cookie An identifier used to track subsystem operations related to this call path.
-     *               The framework will guarantee that it is unique per ISession.
      */
-    ICancellationSignal detectInteraction(in int cookie);
+    ICancellationSignal detectInteraction();
 
     /*
      * enumerateEnrollments:
@@ -232,32 +214,22 @@
      * A request to enumerate (list) the enrollments for this (sensorId, userId) pair. The
      * framework typically uses this to ensure that its cache is in sync with the HAL.
      *
-     * Once the HAL is able to start processing this request, it must notify the framework via
-     * ISessionCallback#onStateChanged with SessionState::ENUMERATING_ENROLLMENTS.
-     *
      * The implementation must then notify the framework with a list of enrollments applicable
      * for the current session via ISessionCallback#onEnrollmentsEnumerated.
      *
-     * @param cookie An identifier used to track subsystem operations related to this call path.
-     *               The framework will guarantee that it is unique per ISession.
      */
-    void enumerateEnrollments(in int cookie);
+    void enumerateEnrollments();
 
     /**
      * removeEnrollments:
      *
      * A request to remove the enrollments for this (sensorId, userId) pair.
      *
-     * Once the HAL is able to start processing this request, it must notify the framework via
-     * ISessionCallback#onStateChanged with SessionState::REMOVING_ENROLLMENTS.
-     *
      * After removing the enrollmentIds from everywhere necessary (filesystem, secure subsystems,
      * etc), the implementation must notify the framework via ISessionCallback#onEnrollmentsRemoved.
      *
-     * @param cookie An identifier used to track subsystem operations related to this call path.
-     *               The framework will guarantee that it is unique per ISession.
      */
-    void removeEnrollments(in int cookie, in int[] enrollmentIds);
+    void removeEnrollments(in int[] enrollmentIds);
 
     /**
      * getAuthenticatorId:
@@ -285,10 +257,8 @@
      *   3) MUST not change if a fingerprint is deleted.
      *   4) MUST be an entropy-encoded random number
      *
-     * @param cookie An identifier used to track subsystem operations related to this call path. The
-     *               client must guarantee that it is unique per ISession.
      */
-    void getAuthenticatorId(in int cookie);
+    void getAuthenticatorId();
 
     /**
      * invalidateAuthenticatorId:
@@ -312,10 +282,8 @@
      * for more details). As such, the framework would coordinate invalidation across multiple
      * biometric HALs as necessary.
      *
-     * @param cookie An identifier used to track subsystem operations related to this call path. The
-     *               client must guarantee that it is unique per ISession.
      */
-    void invalidateAuthenticatorId(in int cookie);
+    void invalidateAuthenticatorId();
 
     /**
      * resetLockout:
@@ -326,8 +294,7 @@
      *   2) Verify that the timestamp provided within the HAT is relatively recent (e.g. on the
      *      order of minutes, not hours).
      * If either of the checks fail, the HAL must invoke ISessionCallback#onError with
-     * Error::UNABLE_TO_PROCESS and return to SessionState::IDLING if no subsequent work is in the
-     * queue.
+     * Error::UNABLE_TO_PROCESS and return to the idling state.
      *
      * Upon successful verification, the HAL must clear the lockout counter and notify the framework
      * via ISessionCallback#onLockoutCleared.
@@ -358,29 +325,26 @@
      * See the Android CDD section 7.3.10 for the full set of lockout and rate-limiting
      * requirements.
      *
-     * @param cookie An identifier used to track subsystem operations related to this call path. The
-     *               client must guarantee that it is unique per ISession.
      * @param hat HardwareAuthToken See above documentation.
      */
-    void resetLockout(in int cookie, in HardwareAuthToken hat);
+    void resetLockout(in HardwareAuthToken hat);
 
     /*
      * Close this session and allow the HAL to release the resources associated with this session.
      *
-     * A session can only be closed when it's in SessionState::IDLING. Closing a session will
-     * result in a ISessionCallback#onStateChanged call with SessionState::CLOSED.
+     * A session can only be closed when the HAL is idling, i.e. not performing any of the
+     * non-interruptable operations. If the HAL is busy performing a cancellable operation, the
+     * operation must be explicitly cancelled with a call to ICancellationSignal#cancel before
+     * the session can be closed.
      *
-     * If a session is unresponsive or stuck in a state other than SessionState::CLOSED,
-     * IFingerprint#reset could be used as a last resort to terminate the session and recover the
-     * HAL from a bad state.
+     * After a session is closed, the HAL must notify the framework by calling
+     * ISessionCallback#onSessionClosed.
      *
      * All sessions must be explicitly closed. Calling IFingerprint#createSession while there is an
      * active session is considered an error.
      *
-     * @param cookie An identifier used to track subsystem operations related to this call path. The
-     *               client must guarantee that it is unique per ISession.
      */
-    void close(in int cookie);
+    void close();
 
     /**
      * Methods for notifying the under-display fingerprint sensor about external events.
@@ -394,9 +358,8 @@
      * of other types, the HAL must treat this as a no-op and return immediately.
      *
      * For sensors of type FingerprintSensorType::UNDER_DISPLAY_*, this method is used to notify the
-     * HAL of display touches. This method can be invoked when the session is in one of the
-     * following states: SessionState::ENROLLING, SessionState::AUTHENTICATING, or
-     * SessionState::DETECTING_INTERACTION.
+     * HAL of display touches. This method can be invoked when the HAL is performing any one of:
+     * ISession#authenticate, ISession#enroll, ISession#detectInteraction.
      *
      * Note that the framework will only invoke this method if the event occurred on the display on
      * which this sensor is located.
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
index cf3a271..95657b3 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
@@ -18,17 +18,11 @@
 
 import android.hardware.biometrics.fingerprint.AcquiredInfo;
 import android.hardware.biometrics.fingerprint.Error;
-import android.hardware.biometrics.fingerprint.SessionState;
 import android.hardware.keymaster.HardwareAuthToken;
 
 @VintfStability
 interface ISessionCallback {
     /**
-     * Used to notify the framework of session state changes. See ISession for more information.
-     */
-    void onStateChanged(in int cookie, in SessionState state);
-
-    /**
      * Notifies the framework when a challenge is successfully generated.
      */
     void onChallengeGenerated(in long challenge);
@@ -39,10 +33,10 @@
     void onChallengeRevoked(in long challenge);
 
     /**
-     * This method must only be used to notify the framework during the following states:
-     *   1) SessionState::ENROLLING
-     *   2) SessionState::AUTHENTICATING
-     *   3) SessionState::DETECTING_INTERACTION
+     * This method must only be used to notify the framework during the following operations:
+     *   1) ISession#enroll
+     *   2) ISession#authenticate
+     *   3) ISession#detectInteraction
      *
      * These messages may be used to provide user guidance multiple times if necessary per
      * operation.
@@ -56,18 +50,18 @@
     void onAcquired(in AcquiredInfo info, in int vendorCode);
 
     /**
-     * This method must only be used to notify the framework during the following states:
-     *   1) SessionState::ENROLLING
-     *   2) SessionState::AUTHENTICATING
-     *   3) SessionState::DETECTING_INTERACTION
-     *   4) SessionState::INVALIDATING_AUTHENTICATOR_ID
-     *   5) SessionState::RESETTING_LOCKOUT
+     * This method must only be used to notify the framework during the following operations:
+     *   1) ISession#enroll
+     *   2) ISession#authenticate
+     *   3) ISession#detectInteraction
+     *   4) ISession#invalidateAuthenticatorId
+     *   5) ISession#resetLockout
      *
      * These messages may be used to notify the framework or user that a non-recoverable error
-     * has occurred. The operation is finished, and the HAL must proceed with the next operation
-     * or return to SessionState::IDLING if the queue is empty.
+     * has occurred. The operation is finished, and the HAL can proceed with the next operation
+     * or return to the idling state.
      *
-     * Note that cancellation (see common::ICancellationSignal) and preemption most be followed with
+     * Note that cancellation (see common::ICancellationSignal) and preemption must be followed with
      * an Error::CANCELED message.
      *
      * @param error See the Error enum.
@@ -79,8 +73,7 @@
     void onError(in Error error, in int vendorCode);
 
     /**
-     * This method must only be used to notify the framework during the following state:
-     *   1) SessionState::ENROLLING
+     * This method must only be used to notify the framework during the ISession#enroll operation.
      *
      * @param enrollmentId Unique stable identifier for the enrollment that's being added by this
      *                     ISession#enroll invocation.
@@ -89,7 +82,7 @@
     void onEnrollmentProgress(in int enrollmentId, int remaining);
 
     /**
-     * This method must only be used to notify the framework during SessionState::AUTHENTICATING.
+     * This method must only be used to notify the framework during ISession#authenticate.
      *
      * Used to notify the framework upon successful authentication. Note that the authentication
      * lifecycle ends when either 1) a fingerprint is accepted, or 2) an error occurred. The
@@ -104,7 +97,7 @@
     void onAuthenticationSucceeded(in int enrollmentId, in HardwareAuthToken hat);
 
     /**
-     * This method must only be used to notify the framework during SessionState::AUTHENTICATING.
+     * This method must only be used to notify the framework during ISession#authenticate.
      *
      * Used to notify the framework upon rejected attempts. Note that the authentication
      * lifecycle ends when either 1) a fingerprint is accepted, or 2) an occurred. The
@@ -113,7 +106,7 @@
     void onAuthenticationFailed();
 
     /**
-     * This method must only be used to notify the framework during SessionState::AUTHENTICATING.
+     * This method must only be used to notify the framework during ISession#authenticate.
      *
      * Authentication is locked out due to too many unsuccessful attempts. This is a rate-limiting
      * lockout, and authentication can be restarted after a period of time. See
@@ -126,7 +119,7 @@
     void onLockoutTimed(in long durationMillis);
 
     /**
-     * This method must only be used to notify the framework during SessionState::AUTHENTICATING.
+     * This method must only be used to notify the framework during ISession#authenticate.
      *
      * Authentication is disabled until the user unlocks with their device credential
      * (PIN/Pattern/Password). See ISession#resetLockout.
@@ -153,7 +146,7 @@
 
     /**
      * This method must only be used to notify the framework during
-     * SessionState::DETECTING_INTERACTION
+     * ISession#detectInteraction
      *
      * Notifies the framework that user interaction occurred. See ISession#detectInteraction.
      */
@@ -161,7 +154,7 @@
 
     /**
      * This method must only be used to notify the framework during
-     * SessionState::ENUMERATING_ENROLLMENTS.
+     * ISession#enumerateEnrollments.
      *
      * Notifies the framework of the current enrollments. See ISession#enumerateEnrollments.
      *
@@ -171,7 +164,7 @@
 
     /**
      * This method must only be used to notify the framework during
-     * SessionState::REMOVING_ENROLLMENTS.
+     * ISession#removeEnrollments.
      *
      * Notifies the framework that the specified enrollments are removed.
      *
@@ -181,7 +174,7 @@
 
     /**
      * This method must only be used to notify the framework during
-     * SessionState::GETTING_AUTHENTICATOR_ID.
+     * ISession#getAuthenticatorId.
      *
      * Notifies the framework with the authenticatorId corresponding to this session's
      * (userId, sensorId) pair.
@@ -192,7 +185,7 @@
 
     /**
      * This method must only be used to notify the framework during
-     * SessionState::INVALIDATING_AUTHENTICATOR_ID.
+     * ISession#invalidateAuthenticatorId.
      *
      * See ISession#invalidateAuthenticatorId for more information.
      *
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SessionState.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SessionState.aidl
deleted file mode 100644
index 19a6ce3..0000000
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SessionState.aidl
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.biometrics.fingerprint;
-
-@VintfStability
-@Backing(type="byte")
-enum SessionState {
-    /**
-     * The HAL is not processing any session requests.
-     */
-    IDLING,
-
-    /**
-     * The session has been closed by the client.
-     */
-    CLOSED,
-
-    /**
-     * The HAL is processing the ISession#generateChallenge request.
-     */
-    GENERATING_CHALLENGE,
-
-    /**
-     * The HAL is processing the ISession#revokeChallenge request.
-     */
-    REVOKING_CHALLENGE,
-
-    /**
-     * The HAL is processing the ISession#enroll request.
-     */
-    ENROLLING,
-
-    /**
-     * The HAL is processing the ISession#authenticate request.
-     */
-    AUTHENTICATING,
-
-    /**
-     * The HAL is processing the ISession#detectInteraction request.
-     */
-    DETECTING_INTERACTION,
-
-    /**
-     * The HAL is processing the ISession#enumerateEnrollments request.
-     */
-    ENUMERATING_ENROLLMENTS,
-
-    /**
-     * The HAL is processing the ISession#removeEnrollments request.
-     */
-    REMOVING_ENROLLMENTS,
-
-    /**
-     * The HAL is processing the ISession#getAuthenticatorId request.
-     */
-    GETTING_AUTHENTICATOR_ID,
-
-    /**
-     * The HAL is processing the ISession#invalidateAuthenticatorId request.
-     */
-    INVALIDATING_AUTHENTICATOR_ID,
-
-    /**
-     * The HAL is processing the ISession#resetLockout request.
-     */
-    RESETTING_LOCKOUT
-}
diff --git a/biometrics/fingerprint/aidl/default/Fingerprint.cpp b/biometrics/fingerprint/aidl/default/Fingerprint.cpp
index fbfa52f..734ff60 100644
--- a/biometrics/fingerprint/aidl/default/Fingerprint.cpp
+++ b/biometrics/fingerprint/aidl/default/Fingerprint.cpp
@@ -22,7 +22,7 @@
 namespace {
 constexpr size_t MAX_WORKER_QUEUE_SIZE = 5;
 constexpr int SENSOR_ID = 1;
-constexpr common::SensorStrength SENSOR_STRENGTH = common::SensorStrength::STRONG;
+constexpr common::SensorStrength SENSOR_STRENGTH = common::SensorStrength::WEAK;
 constexpr int MAX_ENROLLMENTS_PER_USER = 5;
 constexpr FingerprintSensorType SENSOR_TYPE = FingerprintSensorType::REAR;
 constexpr bool SUPPORTS_NAVIGATION_GESTURES = true;
diff --git a/biometrics/fingerprint/aidl/default/Session.cpp b/biometrics/fingerprint/aidl/default/Session.cpp
index f030f13..ca481e7 100644
--- a/biometrics/fingerprint/aidl/default/Session.cpp
+++ b/biometrics/fingerprint/aidl/default/Session.cpp
@@ -39,54 +39,56 @@
 }
 
 void Session::scheduleStateOrCrash(SessionState state) {
-    CHECK(mScheduledState == SessionState::IDLING);
-    CHECK(mCurrentState == SessionState::IDLING);
+    // TODO(b/166800618): call enterIdling from the terminal callbacks and restore these checks.
+    // CHECK(mScheduledState == SessionState::IDLING);
+    // CHECK(mCurrentState == SessionState::IDLING);
     mScheduledState = state;
 }
 
-void Session::enterStateOrCrash(int cookie, SessionState state) {
+void Session::enterStateOrCrash(SessionState state) {
     CHECK(mScheduledState == state);
     mCurrentState = state;
     mScheduledState = SessionState::IDLING;
-    mCb->onStateChanged(cookie, mCurrentState);
 }
 
-void Session::enterIdling(int cookie) {
-    mCurrentState = SessionState::IDLING;
-    mCb->onStateChanged(cookie, mCurrentState);
+void Session::enterIdling() {
+    // TODO(b/166800618): call enterIdling from the terminal callbacks and rethink this conditional.
+    if (mCurrentState != SessionState::CLOSED) {
+        mCurrentState = SessionState::IDLING;
+    }
 }
 
 bool Session::isClosed() {
     return mCurrentState == SessionState::CLOSED;
 }
 
-ndk::ScopedAStatus Session::generateChallenge(int32_t cookie) {
+ndk::ScopedAStatus Session::generateChallenge() {
     LOG(INFO) << "generateChallenge";
     scheduleStateOrCrash(SessionState::GENERATING_CHALLENGE);
 
-    mWorker->schedule(Callable::from([this, cookie] {
-        enterStateOrCrash(cookie, SessionState::GENERATING_CHALLENGE);
+    mWorker->schedule(Callable::from([this] {
+        enterStateOrCrash(SessionState::GENERATING_CHALLENGE);
         mEngine->generateChallengeImpl(mCb.get());
-        enterIdling(cookie);
+        enterIdling();
     }));
 
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Session::revokeChallenge(int32_t cookie, int64_t challenge) {
+ndk::ScopedAStatus Session::revokeChallenge(int64_t challenge) {
     LOG(INFO) << "revokeChallenge";
     scheduleStateOrCrash(SessionState::REVOKING_CHALLENGE);
 
-    mWorker->schedule(Callable::from([this, cookie, challenge] {
-        enterStateOrCrash(cookie, SessionState::REVOKING_CHALLENGE);
+    mWorker->schedule(Callable::from([this, challenge] {
+        enterStateOrCrash(SessionState::REVOKING_CHALLENGE);
         mEngine->revokeChallengeImpl(mCb.get(), challenge);
-        enterIdling(cookie);
+        enterIdling();
     }));
 
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Session::enroll(int32_t cookie, const keymaster::HardwareAuthToken& hat,
+ndk::ScopedAStatus Session::enroll(const keymaster::HardwareAuthToken& hat,
                                    std::shared_ptr<common::ICancellationSignal>* out) {
     LOG(INFO) << "enroll";
     scheduleStateOrCrash(SessionState::ENROLLING);
@@ -94,21 +96,21 @@
     std::promise<void> cancellationPromise;
     auto cancFuture = cancellationPromise.get_future();
 
-    mWorker->schedule(Callable::from([this, cookie, hat, cancFuture = std::move(cancFuture)] {
-        enterStateOrCrash(cookie, SessionState::ENROLLING);
+    mWorker->schedule(Callable::from([this, hat, cancFuture = std::move(cancFuture)] {
+        enterStateOrCrash(SessionState::ENROLLING);
         if (shouldCancel(cancFuture)) {
             mCb->onError(Error::CANCELED, 0 /* vendorCode */);
         } else {
             mEngine->enrollImpl(mCb.get(), hat);
         }
-        enterIdling(cookie);
+        enterIdling();
     }));
 
     *out = SharedRefBase::make<CancellationSignal>(std::move(cancellationPromise));
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Session::authenticate(int32_t cookie, int64_t operationId,
+ndk::ScopedAStatus Session::authenticate(int64_t operationId,
                                          std::shared_ptr<common::ICancellationSignal>* out) {
     LOG(INFO) << "authenticate";
     scheduleStateOrCrash(SessionState::AUTHENTICATING);
@@ -116,112 +118,111 @@
     std::promise<void> cancPromise;
     auto cancFuture = cancPromise.get_future();
 
-    mWorker->schedule(
-            Callable::from([this, cookie, operationId, cancFuture = std::move(cancFuture)] {
-                enterStateOrCrash(cookie, SessionState::AUTHENTICATING);
-                if (shouldCancel(cancFuture)) {
-                    mCb->onError(Error::CANCELED, 0 /* vendorCode */);
-                } else {
-                    mEngine->authenticateImpl(mCb.get(), operationId);
-                }
-                enterIdling(cookie);
-            }));
+    mWorker->schedule(Callable::from([this, operationId, cancFuture = std::move(cancFuture)] {
+        enterStateOrCrash(SessionState::AUTHENTICATING);
+        if (shouldCancel(cancFuture)) {
+            mCb->onError(Error::CANCELED, 0 /* vendorCode */);
+        } else {
+            mEngine->authenticateImpl(mCb.get(), operationId);
+        }
+        enterIdling();
+    }));
 
     *out = SharedRefBase::make<CancellationSignal>(std::move(cancPromise));
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Session::detectInteraction(int32_t cookie,
-                                              std::shared_ptr<common::ICancellationSignal>* out) {
+ndk::ScopedAStatus Session::detectInteraction(std::shared_ptr<common::ICancellationSignal>* out) {
     LOG(INFO) << "detectInteraction";
     scheduleStateOrCrash(SessionState::DETECTING_INTERACTION);
 
     std::promise<void> cancellationPromise;
     auto cancFuture = cancellationPromise.get_future();
 
-    mWorker->schedule(Callable::from([this, cookie, cancFuture = std::move(cancFuture)] {
-        enterStateOrCrash(cookie, SessionState::DETECTING_INTERACTION);
+    mWorker->schedule(Callable::from([this, cancFuture = std::move(cancFuture)] {
+        enterStateOrCrash(SessionState::DETECTING_INTERACTION);
         if (shouldCancel(cancFuture)) {
             mCb->onError(Error::CANCELED, 0 /* vendorCode */);
         } else {
             mEngine->detectInteractionImpl(mCb.get());
         }
-        enterIdling(cookie);
+        enterIdling();
     }));
 
     *out = SharedRefBase::make<CancellationSignal>(std::move(cancellationPromise));
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Session::enumerateEnrollments(int32_t cookie) {
+ndk::ScopedAStatus Session::enumerateEnrollments() {
     LOG(INFO) << "enumerateEnrollments";
     scheduleStateOrCrash(SessionState::ENUMERATING_ENROLLMENTS);
 
-    mWorker->schedule(Callable::from([this, cookie] {
-        enterStateOrCrash(cookie, SessionState::ENUMERATING_ENROLLMENTS);
+    mWorker->schedule(Callable::from([this] {
+        enterStateOrCrash(SessionState::ENUMERATING_ENROLLMENTS);
         mEngine->enumerateEnrollmentsImpl(mCb.get());
-        enterIdling(cookie);
+        enterIdling();
     }));
 
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Session::removeEnrollments(int32_t cookie,
-                                              const std::vector<int32_t>& enrollmentIds) {
+ndk::ScopedAStatus Session::removeEnrollments(const std::vector<int32_t>& enrollmentIds) {
     LOG(INFO) << "removeEnrollments";
     scheduleStateOrCrash(SessionState::REMOVING_ENROLLMENTS);
 
-    mWorker->schedule(Callable::from([this, cookie, enrollmentIds] {
-        enterStateOrCrash(cookie, SessionState::REMOVING_ENROLLMENTS);
+    mWorker->schedule(Callable::from([this, enrollmentIds] {
+        enterStateOrCrash(SessionState::REMOVING_ENROLLMENTS);
         mEngine->removeEnrollmentsImpl(mCb.get(), enrollmentIds);
-        enterIdling(cookie);
+        enterIdling();
     }));
 
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Session::getAuthenticatorId(int32_t cookie) {
+ndk::ScopedAStatus Session::getAuthenticatorId() {
     LOG(INFO) << "getAuthenticatorId";
     scheduleStateOrCrash(SessionState::GETTING_AUTHENTICATOR_ID);
 
-    mWorker->schedule(Callable::from([this, cookie] {
-        enterStateOrCrash(cookie, SessionState::GETTING_AUTHENTICATOR_ID);
+    mWorker->schedule(Callable::from([this] {
+        enterStateOrCrash(SessionState::GETTING_AUTHENTICATOR_ID);
         mEngine->getAuthenticatorIdImpl(mCb.get());
-        enterIdling(cookie);
+        enterIdling();
     }));
 
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Session::invalidateAuthenticatorId(int32_t cookie) {
+ndk::ScopedAStatus Session::invalidateAuthenticatorId() {
     LOG(INFO) << "invalidateAuthenticatorId";
     scheduleStateOrCrash(SessionState::INVALIDATING_AUTHENTICATOR_ID);
 
-    mWorker->schedule(Callable::from([this, cookie] {
-        enterStateOrCrash(cookie, SessionState::INVALIDATING_AUTHENTICATOR_ID);
+    mWorker->schedule(Callable::from([this] {
+        enterStateOrCrash(SessionState::INVALIDATING_AUTHENTICATOR_ID);
         mEngine->invalidateAuthenticatorIdImpl(mCb.get());
-        enterIdling(cookie);
+        enterIdling();
     }));
 
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Session::resetLockout(int32_t cookie, const keymaster::HardwareAuthToken& hat) {
+ndk::ScopedAStatus Session::resetLockout(const keymaster::HardwareAuthToken& hat) {
     LOG(INFO) << "resetLockout";
     scheduleStateOrCrash(SessionState::RESETTING_LOCKOUT);
 
-    mWorker->schedule(Callable::from([this, cookie, hat] {
-        enterStateOrCrash(cookie, SessionState::RESETTING_LOCKOUT);
+    mWorker->schedule(Callable::from([this, hat] {
+        enterStateOrCrash(SessionState::RESETTING_LOCKOUT);
         mEngine->resetLockoutImpl(mCb.get(), hat);
-        enterIdling(cookie);
+        enterIdling();
     }));
 
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Session::close(int32_t /*cookie*/) {
+ndk::ScopedAStatus Session::close() {
     LOG(INFO) << "close";
-    CHECK(mCurrentState == SessionState::IDLING) << "Can't close a non-idling session. Crashing.";
+    // TODO(b/166800618): call enterIdling from the terminal callbacks and restore this check.
+    // CHECK(mCurrentState == SessionState::IDLING) << "Can't close a non-idling session.
+    // Crashing.";
     mCurrentState = SessionState::CLOSED;
     mCb->onSessionClosed();
     return ndk::ScopedAStatus::ok();
diff --git a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
index 42e1aa5..6667f7a 100644
--- a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
+++ b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
@@ -37,7 +37,7 @@
         cb->onEnrollmentProgress(0 /* enrollmentId */, 0 /* remaining */);
     }
 
-    void authenticateImpl(ISessionCallback* cb, int64_t /*operationId*/) {
+    void authenticateImpl(ISessionCallback* cb, int64_t /* operationId */) {
         LOG(INFO) << "authenticateImpl";
         cb->onAuthenticationSucceeded(0 /* enrollmentId */, {} /* hat */);
     }
diff --git a/biometrics/fingerprint/aidl/default/include/Session.h b/biometrics/fingerprint/aidl/default/include/Session.h
index 97d5645..9e46422 100644
--- a/biometrics/fingerprint/aidl/default/include/Session.h
+++ b/biometrics/fingerprint/aidl/default/include/Session.h
@@ -27,37 +27,50 @@
 namespace common = aidl::android::hardware::biometrics::common;
 namespace keymaster = aidl::android::hardware::keymaster;
 
+enum class SessionState {
+    IDLING,
+    CLOSED,
+    GENERATING_CHALLENGE,
+    REVOKING_CHALLENGE,
+    ENROLLING,
+    AUTHENTICATING,
+    DETECTING_INTERACTION,
+    ENUMERATING_ENROLLMENTS,
+    REMOVING_ENROLLMENTS,
+    GETTING_AUTHENTICATOR_ID,
+    INVALIDATING_AUTHENTICATOR_ID,
+    RESETTING_LOCKOUT,
+};
+
 class Session : public BnSession {
   public:
     Session(int sensorId, int userId, std::shared_ptr<ISessionCallback> cb,
             FakeFingerprintEngine* engine, WorkerThread* worker);
 
-    ndk::ScopedAStatus generateChallenge(int32_t cookie) override;
+    ndk::ScopedAStatus generateChallenge() override;
 
-    ndk::ScopedAStatus revokeChallenge(int32_t cookie, int64_t challenge) override;
+    ndk::ScopedAStatus revokeChallenge(int64_t challenge) override;
 
-    ndk::ScopedAStatus enroll(int32_t cookie, const keymaster::HardwareAuthToken& hat,
+    ndk::ScopedAStatus enroll(const keymaster::HardwareAuthToken& hat,
                               std::shared_ptr<common::ICancellationSignal>* out) override;
 
-    ndk::ScopedAStatus authenticate(int32_t cookie, int64_t operationId,
+    ndk::ScopedAStatus authenticate(int64_t operationId,
                                     std::shared_ptr<common::ICancellationSignal>* out) override;
 
     ndk::ScopedAStatus detectInteraction(
-            int32_t cookie, std::shared_ptr<common::ICancellationSignal>* out) override;
+            std::shared_ptr<common::ICancellationSignal>* out) override;
 
-    ndk::ScopedAStatus enumerateEnrollments(int32_t cookie) override;
+    ndk::ScopedAStatus enumerateEnrollments() override;
 
-    ndk::ScopedAStatus removeEnrollments(int32_t cookie,
-                                         const std::vector<int32_t>& enrollmentIds) override;
+    ndk::ScopedAStatus removeEnrollments(const std::vector<int32_t>& enrollmentIds) override;
 
-    ndk::ScopedAStatus getAuthenticatorId(int32_t cookie) override;
+    ndk::ScopedAStatus getAuthenticatorId() override;
 
-    ndk::ScopedAStatus invalidateAuthenticatorId(int32_t cookie) override;
+    ndk::ScopedAStatus invalidateAuthenticatorId() override;
 
-    ndk::ScopedAStatus resetLockout(int32_t cookie,
-                                    const keymaster::HardwareAuthToken& hat) override;
+    ndk::ScopedAStatus resetLockout(const keymaster::HardwareAuthToken& hat) override;
 
-    ndk::ScopedAStatus close(int32_t cookie) override;
+    ndk::ScopedAStatus close() override;
 
     ndk::ScopedAStatus onPointerDown(int32_t pointerId, int32_t x, int32_t y, float minor,
                                      float major) override;
@@ -76,11 +89,11 @@
     // Crashes the HAL if the provided state doesn't match the previously scheduled state.
     // Otherwise, transitions into the provided state, clears the scheduled state, and notifies
     // the client about the transition by calling ISessionCallback#onStateChanged.
-    void enterStateOrCrash(int cookie, SessionState state);
+    void enterStateOrCrash(SessionState state);
 
     // Sets the current state to SessionState::IDLING and notifies the client about the transition
     // by calling ISessionCallback#onStateChanged.
-    void enterIdling(int cookie);
+    void enterIdling();
 
     // The sensor and user IDs for which this session was created.
     int32_t mSensorId;
diff --git a/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp b/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp
index 885f703..f1cfb17 100644
--- a/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp
+++ b/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp
@@ -22,46 +22,20 @@
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
 
+#include <chrono>
 #include <future>
 
 namespace aidl::android::hardware::biometrics::fingerprint {
 namespace {
 
+using namespace std::literals::chrono_literals;
+
 constexpr int kSensorId = 0;
 constexpr int kUserId = 0;
-constexpr auto kCallbackTimeout = std::chrono::seconds(1);
-
-enum class MethodName {
-    kOnStateChanged,
-};
-
-struct Invocation {
-    MethodName methodName;
-    int32_t cookie;
-    SessionState state;
-};
 
 class SessionCallback : public BnSessionCallback {
   public:
-    explicit SessionCallback() : mIsPromiseValid(false) {}
-
-    void setPromise(std::promise<std::vector<Invocation>>&& promise) {
-        mPromise = std::move(promise);
-        mIsPromiseValid = true;
-    }
-
-    ndk::ScopedAStatus onStateChanged(int32_t cookie, SessionState state) override {
-        Invocation invocation = {};
-        invocation.methodName = MethodName::kOnStateChanged;
-        invocation.cookie = cookie;
-        invocation.state = state;
-        mInvocations.push_back(invocation);
-        if (state == SessionState::IDLING) {
-            assert(mIsPromiseValid);
-            mPromise.set_value(mInvocations);
-        }
-        return ndk::ScopedAStatus::ok();
-    }
+    explicit SessionCallback(std::promise<void>&& promise) : mPromise(std::move(promise)) {}
 
     ndk::ScopedAStatus onChallengeGenerated(int64_t /*challenge*/) override {
         return ndk::ScopedAStatus::ok();
@@ -119,12 +93,13 @@
         return ndk::ScopedAStatus::ok();
     }
 
-    ndk::ScopedAStatus onSessionClosed() override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus onSessionClosed() override {
+        mPromise.set_value();
+        return ndk::ScopedAStatus::ok();
+    }
 
   private:
-    bool mIsPromiseValid;
-    std::vector<Invocation> mInvocations;
-    std::promise<std::vector<Invocation>> mPromise;
+    std::promise<void> mPromise;
 };
 
 class Fingerprint : public testing::TestWithParam<std::string> {
@@ -139,33 +114,26 @@
 };
 
 TEST_P(Fingerprint, AuthenticateTest) {
-    // Prepare the callback
-    std::promise<std::vector<Invocation>> promise;
+    auto promise = std::promise<void>{};
     auto future = promise.get_future();
-    std::shared_ptr<SessionCallback> cb = ndk::SharedRefBase::make<SessionCallback>();
-    cb->setPromise(std::move(promise));
+    // Prepare the callback.
+    auto cb = ndk::SharedRefBase::make<SessionCallback>(std::move(promise));
 
     // Create a session
     std::shared_ptr<ISession> session;
     ASSERT_TRUE(mHal->createSession(kSensorId, kUserId, cb, &session).isOk());
 
     // Call authenticate
-    int32_t cookie = 123;
     std::shared_ptr<common::ICancellationSignal> cancellationSignal;
-    ASSERT_TRUE(session->authenticate(cookie, 0, &cancellationSignal).isOk());
+    ASSERT_TRUE(session->authenticate(-1 /* operationId */, &cancellationSignal).isOk());
 
     // Get the results
-    ASSERT_TRUE(future.wait_for(kCallbackTimeout) == std::future_status::ready);
-    std::vector<Invocation> invocations = future.get();
+    // TODO(b/166799066): test authenticate.
 
     // Close the session
-    ASSERT_TRUE(session->close(0).isOk());
-
-    ASSERT_FALSE(invocations.empty());
-    EXPECT_EQ(invocations.front().methodName, MethodName::kOnStateChanged);
-    EXPECT_EQ(invocations.front().state, SessionState::AUTHENTICATING);
-    EXPECT_EQ(invocations.back().methodName, MethodName::kOnStateChanged);
-    EXPECT_EQ(invocations.back().state, SessionState::IDLING);
+    ASSERT_TRUE(session->close().isOk());
+    auto status = future.wait_for(1s);
+    ASSERT_EQ(status, std::future_status::ready);
 }
 
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Fingerprint);
diff --git a/camera/device/3.7/Android.bp b/camera/device/3.7/Android.bp
index 163f781..15c1b5c 100644
--- a/camera/device/3.7/Android.bp
+++ b/camera/device/3.7/Android.bp
@@ -24,6 +24,11 @@
         "android.hardware.camera.device@3.4",
         "android.hardware.camera.device@3.5",
         "android.hardware.camera.device@3.6",
+        "android.hardware.camera.metadata@3.2",
+        "android.hardware.camera.metadata@3.3",
+        "android.hardware.camera.metadata@3.4",
+        "android.hardware.camera.metadata@3.5",
+        "android.hardware.camera.metadata@3.6",
         "android.hardware.graphics.common@1.0",
         "android.hidl.base@1.0",
     ],
diff --git a/camera/device/3.7/types.hal b/camera/device/3.7/types.hal
index 9450c2f..6910e65 100644
--- a/camera/device/3.7/types.hal
+++ b/camera/device/3.7/types.hal
@@ -21,6 +21,8 @@
 import @3.4::CaptureRequest;
 import @3.4::Stream;
 
+import android.hardware.camera.metadata@3.6::CameraMetadataEnumAndroidSensorPixelMode;
+
 /**
  * Stream:
  *
@@ -57,6 +59,14 @@
      * usage flag.
      */
     int32_t groupId;
+
+    /**
+     *  The sensor pixel modes used by this stream. This can assist the camera
+     *  HAL in decision making about stream combination support.
+     *  If this is empty, the HAL must assume that this stream will only be used
+     *  with ANDROID_SENSOR_PIXEL_MODE set to ANDROID_SENSOR_PIXEL_MODE_DEFAULT.
+     */
+    vec<CameraMetadataEnumAndroidSensorPixelMode> sensorPixelModesUsed;
 };
 
 /**
diff --git a/camera/metadata/3.6/types.hal b/camera/metadata/3.6/types.hal
index 3472ae9..709cfb3 100644
--- a/camera/metadata/3.6/types.hal
+++ b/camera/metadata/3.6/types.hal
@@ -36,6 +36,43 @@
  * '/system/media/camera/docs/docs.html' in the corresponding Android source tree.</p>
  */
 enum CameraMetadataTag : @3.5::CameraMetadataTag {
+    /** android.control.availableHighSpeedVideoConfigurationsMaximumResolution [static, int32[], hidden]
+     *
+     * <p>List of available high speed video size, fps range and max batch size configurations
+     * supported by the camera device, in the format of
+     * (width, height, fps_min, fps_max, batch_size_max),
+     * when ANDROID_SENSOR_PIXEL_MODE is set to
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+     *
+     * @see ANDROID_SENSOR_PIXEL_MODE
+     */
+    ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS_MAXIMUM_RESOLUTION = android.hardware.camera.metadata@3.5::CameraMetadataTag:ANDROID_CONTROL_END_3_5,
+
+    ANDROID_CONTROL_END_3_6,
+
+    /** android.lens.distortionMaximumResolution [static, float[], public]
+     *
+     * <p>The correction coefficients to correct for this camera device's
+     * radial and tangential lens distortion for a
+     * CaptureRequest with ANDROID_SENSOR_PIXEL_MODE set to
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+     *
+     * @see ANDROID_SENSOR_PIXEL_MODE
+     */
+    ANDROID_LENS_DISTORTION_MAXIMUM_RESOLUTION = android.hardware.camera.metadata@3.3::CameraMetadataTag:ANDROID_LENS_END_3_3,
+
+    /** android.lens.intrinsicCalibrationMaximumResolution [static, float[], public]
+     *
+     * <p>The parameters for this camera device's intrinsic
+     * calibration when ANDROID_SENSOR_PIXEL_MODE is set to
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+     *
+     * @see ANDROID_SENSOR_PIXEL_MODE
+     */
+    ANDROID_LENS_INTRINSIC_CALIBRATION_MAXIMUM_RESOLUTION,
+
+    ANDROID_LENS_END_3_6,
+
     /** android.scaler.defaultSecureImageSize [static, int32[], public]
      *
      * <p>Default YUV/PRIVATE size to use for requesting secure image buffers.</p>
@@ -50,14 +87,237 @@
      */
     ANDROID_SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS,
 
+    /** android.scaler.availableStreamConfigurationsMaximumResolution [static, enum[], ndk_public]
+     *
+     * <p>The available stream configurations that this
+     * camera device supports (i.e. format, width, height, output/input stream) for a
+     * CaptureRequest with ANDROID_SENSOR_PIXEL_MODE set to
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+     *
+     * @see ANDROID_SENSOR_PIXEL_MODE
+     */
+    ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION,
+
+    /** android.scaler.availableMinFrameDurationsMaximumResolution [static, int64[], ndk_public]
+     *
+     * <p>This lists the minimum frame duration for each
+     * format/size combination when the camera device is sent a CaptureRequest with
+     * ANDROID_SENSOR_PIXEL_MODE set to
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+     *
+     * @see ANDROID_SENSOR_PIXEL_MODE
+     */
+    ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION,
+
+    /** android.scaler.availableStallDurationsMaximumResolution [static, int64[], ndk_public]
+     *
+     * <p>This lists the maximum stall duration for each
+     * output format/size combination when CaptureRequests are submitted with
+     * ANDROID_SENSOR_PIXEL_MODE set to
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a></p>
+     *
+     * @see ANDROID_SENSOR_PIXEL_MODE
+     */
+    ANDROID_SCALER_AVAILABLE_STALL_DURATIONS_MAXIMUM_RESOLUTION,
+
+    /** android.scaler.availableInputOutputFormatsMapMaximumResolution [static, int32, hidden]
+     *
+     * <p>The mapping of image formats that are supported by this
+     * camera device for input streams, to their corresponding output formats, when
+     * ANDROID_SENSOR_PIXEL_MODE is set to
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+     *
+     * @see ANDROID_SENSOR_PIXEL_MODE
+     */
+    ANDROID_SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP_MAXIMUM_RESOLUTION,
+
     ANDROID_SCALER_END_3_6,
 
+    /** android.sensor.opaqueRawSizeMaximumResolution [static, int32[], system]
+     *
+     * <p>Size in bytes for all the listed opaque RAW buffer sizes when
+     * ANDROID_SENSOR_PIXEL_MODE is set to
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+     *
+     * @see ANDROID_SENSOR_PIXEL_MODE
+     */
+    ANDROID_SENSOR_OPAQUE_RAW_SIZE_MAXIMUM_RESOLUTION = android.hardware.camera.metadata@3.2::CameraMetadataTag:ANDROID_SENSOR_END,
+
+    /** android.sensor.pixelMode [dynamic, enum, public]
+     *
+     * <p>Switches sensor pixel mode between maximum resolution mode and default mode.</p>
+     */
+    ANDROID_SENSOR_PIXEL_MODE,
+
+    /** android.sensor.rawBinningFactorUsed [dynamic, enum, public]
+     *
+     * <p>Whether <code>RAW</code> images requested have their bayer pattern as described by
+     * ANDROID_SENSOR_INFO_BINNING_FACTOR.</p>
+     *
+     * @see ANDROID_SENSOR_INFO_BINNING_FACTOR
+     */
+    ANDROID_SENSOR_RAW_BINNING_FACTOR_USED,
+
+    ANDROID_SENSOR_END_3_6,
+
+    /** android.sensor.info.activeArraySizeMaximumResolution [static, int32[], public]
+     *
+     * <p>The area of the image sensor which corresponds to active pixels after any geometric
+     * distortion correction has been applied, when the sensor runs in maximum resolution mode.</p>
+     */
+    ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION = android.hardware.camera.metadata@3.2::CameraMetadataTag:ANDROID_SENSOR_INFO_END,
+
+    /** android.sensor.info.pixelArraySizeMaximumResolution [static, int32[], public]
+     *
+     * <p>Dimensions of the full pixel array, possibly
+     * including black calibration pixels, when the sensor runs in maximum resolution mode.
+     * Analogous to ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, when ANDROID_SENSOR_PIXEL_MODE is
+     * set to
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+     *
+     * @see ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE
+     * @see ANDROID_SENSOR_PIXEL_MODE
+     */
+    ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE_MAXIMUM_RESOLUTION,
+
+    /** android.sensor.info.preCorrectionActiveArraySizeMaximumResolution [static, int32[], public]
+     *
+     * <p>The area of the image sensor which corresponds to active pixels prior to the
+     * application of any geometric distortion correction, when the sensor runs in maximum
+     * resolution mode. This key must be used for crop / metering regions, only when
+     * ANDROID_SENSOR_PIXEL_MODE is set to
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+     *
+     * @see ANDROID_SENSOR_PIXEL_MODE
+     */
+    ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION,
+
+    /** android.sensor.info.binningFactor [static, int32[], public]
+     *
+     * <p>Dimensions of the group of pixels which are under the same color filter.
+     * This specifies the width and height (pair of integers) of the group of pixels which fall
+     * under the same color filter for ULTRA_HIGH_RESOLUTION sensors.</p>
+     */
+    ANDROID_SENSOR_INFO_BINNING_FACTOR,
+
+    ANDROID_SENSOR_INFO_END_3_6,
+
+    /** android.depth.availableDepthStreamConfigurationsMaximumResolution [static, enum[], ndk_public]
+     *
+     * <p>The available depth dataspace stream
+     * configurations that this camera device supports
+     * (i.e. format, width, height, output/input stream) when a CaptureRequest is submitted with
+     * ANDROID_SENSOR_PIXEL_MODE set to
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+     *
+     * @see ANDROID_SENSOR_PIXEL_MODE
+     */
+    ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION = android.hardware.camera.metadata@3.4::CameraMetadataTag:ANDROID_DEPTH_END_3_4,
+
+    /** android.depth.availableDepthMinFrameDurationsMaximumResolution [static, int64[], ndk_public]
+     *
+     * <p>This lists the minimum frame duration for each
+     * format/size combination for depth output formats when a CaptureRequest is submitted with
+     * ANDROID_SENSOR_PIXEL_MODE set to
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+     *
+     * @see ANDROID_SENSOR_PIXEL_MODE
+     */
+    ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION,
+
+    /** android.depth.availableDepthStallDurationsMaximumResolution [static, int64[], ndk_public]
+     *
+     * <p>This lists the maximum stall duration for each
+     * output format/size combination for depth streams for CaptureRequests where
+     * ANDROID_SENSOR_PIXEL_MODE is set to
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+     *
+     * @see ANDROID_SENSOR_PIXEL_MODE
+     */
+    ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS_MAXIMUM_RESOLUTION,
+
+    /** android.depth.availableDynamicDepthStreamConfigurationsMaximumResolution [static, enum[], ndk_public]
+     *
+     * <p>The available dynamic depth dataspace stream
+     * configurations that this camera device supports (i.e. format, width, height,
+     * output/input stream) for CaptureRequests where ANDROID_SENSOR_PIXEL_MODE is set to
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+     *
+     * @see ANDROID_SENSOR_PIXEL_MODE
+     */
+    ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION,
+
+    /** android.depth.availableDynamicDepthMinFrameDurationsMaximumResolution [static, int64[], ndk_public]
+     *
+     * <p>This lists the minimum frame duration for each
+     * format/size combination for dynamic depth output streams  for CaptureRequests where
+     * ANDROID_SENSOR_PIXEL_MODE is set to
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+     *
+     * @see ANDROID_SENSOR_PIXEL_MODE
+     */
+    ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION,
+
+    /** android.depth.availableDynamicDepthStallDurationsMaximumResolution [static, int64[], ndk_public]
+     *
+     * <p>This lists the maximum stall duration for each
+     * output format/size combination for dynamic depth streams for CaptureRequests where
+     * ANDROID_SENSOR_PIXEL_MODE is set to
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+     *
+     * @see ANDROID_SENSOR_PIXEL_MODE
+     */
+    ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS_MAXIMUM_RESOLUTION,
+
+    ANDROID_DEPTH_END_3_6,
+
+    /** android.heic.availableHeicStreamConfigurationsMaximumResolution [static, enum[], ndk_public]
+     *
+     * <p>The available HEIC (ISO/IEC 23008-12) stream
+     * configurations that this camera device supports
+     * (i.e. format, width, height, output/input stream).</p>
+     */
+    ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION = android.hardware.camera.metadata@3.4::CameraMetadataTag:ANDROID_HEIC_END_3_4,
+
+    /** android.heic.availableHeicMinFrameDurationsMaximumResolution [static, int64[], ndk_public]
+     *
+     * <p>This lists the minimum frame duration for each
+     * format/size combination for HEIC output formats for CaptureRequests where
+     * ANDROID_SENSOR_PIXEL_MODE is set to
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+     *
+     * @see ANDROID_SENSOR_PIXEL_MODE
+     */
+    ANDROID_HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION,
+
+    /** android.heic.availableHeicStallDurationsMaximumResolution [static, int64[], ndk_public]
+     *
+     * <p>This lists the maximum stall duration for each
+     * output format/size combination for HEIC streams for CaptureRequests where
+     * ANDROID_SENSOR_PIXEL_MODE is set to
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>.</p>
+     *
+     * @see ANDROID_SENSOR_PIXEL_MODE
+     */
+    ANDROID_HEIC_AVAILABLE_HEIC_STALL_DURATIONS_MAXIMUM_RESOLUTION,
+
+    ANDROID_HEIC_END_3_6,
+
 };
 
 /*
  * Enumeration definitions for the various entries that need them
  */
 
+/** android.request.availableCapabilities enumeration values added since v3.5
+ * @see ANDROID_REQUEST_AVAILABLE_CAPABILITIES
+ */
+enum CameraMetadataEnumAndroidRequestAvailableCapabilities :
+        @3.5::CameraMetadataEnumAndroidRequestAvailableCapabilities {
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR,
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_REMOSAIC_REPROCESSING,
+};
+
 /** android.scaler.physicalCameraMultiResolutionStreamConfigurations enumeration values
  * @see ANDROID_SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS
  */
@@ -65,3 +325,51 @@
     ANDROID_SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS_OUTPUT,
     ANDROID_SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS_INPUT,
 };
+
+/** android.scaler.availableStreamConfigurationsMaximumResolution enumeration values
+ * @see ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION
+ */
+enum CameraMetadataEnumAndroidScalerAvailableStreamConfigurationsMaximumResolution : uint32_t {
+    ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_OUTPUT,
+    ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_INPUT,
+};
+
+/** android.sensor.pixelMode enumeration values
+ * @see ANDROID_SENSOR_PIXEL_MODE
+ */
+enum CameraMetadataEnumAndroidSensorPixelMode : uint32_t {
+    ANDROID_SENSOR_PIXEL_MODE_DEFAULT,
+    ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION,
+};
+
+/** android.sensor.rawBinningFactorUsed enumeration values
+ * @see ANDROID_SENSOR_RAW_BINNING_FACTOR_USED
+ */
+enum CameraMetadataEnumAndroidSensorRawBinningFactorUsed : uint32_t {
+    ANDROID_SENSOR_RAW_BINNING_FACTOR_USED_TRUE,
+    ANDROID_SENSOR_RAW_BINNING_FACTOR_USED_FALSE,
+};
+
+/** android.depth.availableDepthStreamConfigurationsMaximumResolution enumeration values
+ * @see ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION
+ */
+enum CameraMetadataEnumAndroidDepthAvailableDepthStreamConfigurationsMaximumResolution : uint32_t {
+    ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_OUTPUT,
+    ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_INPUT,
+};
+
+/** android.depth.availableDynamicDepthStreamConfigurationsMaximumResolution enumeration values
+ * @see ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION
+ */
+enum CameraMetadataEnumAndroidDepthAvailableDynamicDepthStreamConfigurationsMaximumResolution : uint32_t {
+    ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_OUTPUT,
+    ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_INPUT,
+};
+
+/** android.heic.availableHeicStreamConfigurationsMaximumResolution enumeration values
+ * @see ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION
+ */
+enum CameraMetadataEnumAndroidHeicAvailableHeicStreamConfigurationsMaximumResolution : uint32_t {
+    ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_OUTPUT,
+    ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION_INPUT,
+};
diff --git a/contexthub/1.2/types.hal b/contexthub/1.2/types.hal
index 5033ce8..75122bc 100644
--- a/contexthub/1.2/types.hal
+++ b/contexthub/1.2/types.hal
@@ -35,10 +35,12 @@
     AIRPLANE_MODE,
 
     /**
-     * Indicates if the microphone access was turned off globally by the user,
-     * in which case audio data cannot be used and propagated by CHRE.
+     * Indicates if the microphone access is available for CHRE. Microphone
+     * access is disabled if the user has turned off the microphone as a
+     * privacy setting, in which case audio data cannot be used and propagated
+     * by CHRE.
      */
-    GLOBAL_MIC_DISABLE,
+    MICROPHONE,
 };
 
 struct ContextHubMsg {
diff --git a/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp b/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp
index 3510c23..9ee40ed 100644
--- a/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp
+++ b/contexthub/1.2/vts/functional/VtsHalContexthubV1_2TargetTest.cpp
@@ -131,10 +131,10 @@
     ASSERT_OK(registerCallback_1_2(nullptr));
 }
 
-TEST_P(ContexthubHidlTest, TestOnGlobalMicDisableSettingChanged) {
+TEST_P(ContexthubHidlTest, TestOnMicrophoneSettingChanged) {
     ASSERT_OK(registerCallback_1_2(new ContexthubCallbackV1_2()));
-    hubApi->onSettingChanged_1_2(Setting::GLOBAL_MIC_DISABLE, SettingValue::DISABLED);
-    hubApi->onSettingChanged_1_2(Setting::GLOBAL_MIC_DISABLE, SettingValue::ENABLED);
+    hubApi->onSettingChanged_1_2(Setting::MICROPHONE, SettingValue::DISABLED);
+    hubApi->onSettingChanged_1_2(Setting::MICROPHONE, SettingValue::ENABLED);
     ASSERT_OK(registerCallback_1_2(nullptr));
 }
 
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/BlocklistedSource.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/BlocklistedSource.aidl
index 1a2feb7..a4f0097 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/BlocklistedSource.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/BlocklistedSource.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/CorrelationVector.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/CorrelationVector.aidl
index 9c9a241..b0848bb 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/CorrelationVector.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/CorrelationVector.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/ElapsedRealtime.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/ElapsedRealtime.aidl
index fbcc8a3..7d3baa4 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/ElapsedRealtime.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/ElapsedRealtime.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssClock.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssClock.aidl
index 15fe2e9..c54cc2c 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssClock.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssClock.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssConstellationType.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssConstellationType.aidl
index f873b87..c1fcfcc 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssConstellationType.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssConstellationType.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl
index 9e05db7..ebb5d0b 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMeasurement.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMeasurement.aidl
index bc73bb1..948c540 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMeasurement.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMeasurement.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMultipathIndicator.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMultipathIndicator.aidl
index b9db343..24f45c4 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMultipathIndicator.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssMultipathIndicator.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssPowerStats.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssPowerStats.aidl
index 6676e2e..670244f 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssPowerStats.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssPowerStats.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssSignalType.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssSignalType.aidl
index ba02f72..c2a5b51 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssSignalType.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssSignalType.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
index 10b05a7..f93b496 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl
index 9ad9159..fb0931c 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -37,4 +38,5 @@
   const int CAPABILITY_SATELLITE_BLOCKLIST = 512;
   const int CAPABILITY_CORRELATION_VECTOR = 4096;
   const int CAPABILITY_SATELLITE_PVT = 8192;
+  const int CAPABILITY_MEASUREMENT_CORRECTIONS_FOR_DRIVING = 16384;
 }
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssConfiguration.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssConfiguration.aidl
index 20dd781..54cd022 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssConfiguration.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssConfiguration.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementCallback.aidl
index 93894bf..6e62617 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementCallback.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementCallback.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementInterface.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementInterface.aidl
index 07a51ae..24d6f9c 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementInterface.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementInterface.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndication.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndication.aidl
index 1cc7f71..fbf1f6f 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndication.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndication.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndicationCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndicationCallback.aidl
index 01f91dc..bfa787e 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndicationCallback.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPowerIndicationCallback.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsds.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsds.aidl
index 1758792..526ecc8 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsds.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsds.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsdsCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsdsCallback.aidl
index a1af105..2205bc4 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsdsCallback.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssPsdsCallback.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/PsdsType.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/PsdsType.aidl
index b387121..727bb69 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/PsdsType.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/PsdsType.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteClockInfo.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteClockInfo.aidl
index 4dd45b2..ed23e63 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteClockInfo.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteClockInfo.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePositionEcef.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePositionEcef.aidl
index c96b2e5..e1a20c3 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePositionEcef.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePositionEcef.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePvt.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePvt.aidl
index 95af152..747ee90 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePvt.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatellitePvt.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteVelocityEcef.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteVelocityEcef.aidl
index 558aec9..a571048 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteVelocityEcef.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/SatelliteVelocityEcef.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl b/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl
index 8881ea7..aad09ef 100644
--- a/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl
+++ b/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl
@@ -16,8 +16,8 @@
 
 package android.hardware.gnss;
 
-import android.hardware.gnss.IGnssPsds;
 import android.hardware.gnss.IGnssConfiguration;
+import android.hardware.gnss.IGnssPsds;
 
 /**
  * This interface is required for the HAL to communicate certain information
@@ -26,15 +26,17 @@
  */
 @VintfStability
 interface IGnssCallback {
-
     /** Capability bit mask indicating that GNSS supports blocklisting satellites */
     const int CAPABILITY_SATELLITE_BLOCKLIST = 1 << 9;
 
     /** Capability bit mask indicating that GNSS supports correlation vector */
-    const int CAPABILITY_CORRELATION_VECTOR =  1 << 12;
+    const int CAPABILITY_CORRELATION_VECTOR = 1 << 12;
 
     /** Capability bit mask indicating that GNSS supports satellite PVT */
-    const int CAPABILITY_SATELLITE_PVT       = 1 << 13;
+    const int CAPABILITY_SATELLITE_PVT = 1 << 13;
+
+    /** Capability bit mask indicating that GNSS supports measurement corrections for driving */
+    const int CAPABILITY_MEASUREMENT_CORRECTIONS_FOR_DRIVING = 1 << 14;
 
     /**
      * Callback to inform framework of the GNSS HAL implementation's capabilities.
diff --git a/keymaster/4.1/default/Android.bp b/keymaster/4.1/default/Android.bp
index 3e2289a..6ec1fae 100644
--- a/keymaster/4.1/default/Android.bp
+++ b/keymaster/4.1/default/Android.bp
@@ -45,5 +45,14 @@
         "liblog",
         "libutils",
     ],
+    required: [
+        "android.hardware.hardware_keystore.km41.xml",
+    ],
+}
 
+prebuilt_etc {
+    name: "android.hardware.hardware_keystore.km41.xml",
+    sub_dir: "permissions",
+    vendor: true,
+    src: "android.hardware.hardware_keystore.km41.xml",
 }
diff --git a/keymaster/4.1/default/android.hardware.hardware_keystore.km41.xml b/keymaster/4.1/default/android.hardware.hardware_keystore.km41.xml
new file mode 100644
index 0000000..0dbeed8
--- /dev/null
+++ b/keymaster/4.1/default/android.hardware.hardware_keystore.km41.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<permissions>
+  <feature name="android.hardware.hardware_keystore" version="41" />
+</permissions>
diff --git a/radio/1.6/IRadio.hal b/radio/1.6/IRadio.hal
index d201332..a4e8811 100644
--- a/radio/1.6/IRadio.hal
+++ b/radio/1.6/IRadio.hal
@@ -544,4 +544,43 @@
      * as the input param.
      */
     oneway setCarrierInfoForImsiEncryption_1_6(int32_t serial, @1.6::ImsiEncryptionInfo imsiEncryptionInfo);
+
+    /**
+     * Get the local and global phonebook records from the SIM card.
+     * This should be called again after a simPhonebookChanged notification is received.
+     *
+     * The phonebook records are received via IRadioIndication.simPhonebookRecordsReceived()
+     *
+     * @param serial Serial number of request.
+     *
+     * Response callback is IRadioResponse.getSimPhonebookRecordsResponse()
+     */
+    oneway getSimPhonebookRecords(int32_t serial);
+
+    /**
+     * Get the phone book capacity
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is defined from IRadioResponse.getSimPhonebookCapacityResponse()
+     */
+    oneway getSimPhonebookCapacity(int32_t serial);
+
+    /**
+     * Insert, delete or update a phonebook record on the SIM card.
+     * If the index of recordInfo is 0, the phonebook record will be added to global or
+     * local phonebook, and global phonebook has higher priority than local phonebook.
+     *
+     * If the fields in the recordInfo are all empty except for the index, the phonebook
+     * record specified by the index will be deleted.
+     *
+     * The indication simPhonebookChanged will be called after every successful call of
+     * updateSimPhonebookRecords.
+     *
+     * @param serial Serial number of request.
+     * @param recordInfo Details of the record to insert, delete or update.
+     *
+     * Response callback is IRadioResponse.updateSimPhonebookRecordsResponse()
+     */
+    oneway updateSimPhonebookRecords(int32_t serial, PhonebookRecordInfo recordInfo);
 };
diff --git a/radio/1.6/IRadioIndication.hal b/radio/1.6/IRadioIndication.hal
index a53d7c1..9788345 100644
--- a/radio/1.6/IRadioIndication.hal
+++ b/radio/1.6/IRadioIndication.hal
@@ -23,7 +23,9 @@
 import @1.6::NetworkScanResult;
 import @1.6::SignalStrength;
 import @1.6::SetupDataCallResult;
+import @1.6::PbReceivedStatus;
 import @1.6::PhysicalChannelConfig;
+import @1.6::PhonebookRecordInfo;
 
 /**
  * Interface declaring unsolicited radio indications.
@@ -72,7 +74,6 @@
      */
     oneway currentLinkCapacityEstimate_1_6(RadioIndicationType type, LinkCapacityEstimate lce);
 
-
     /**
      * Indicates current signal strength of the radio.
      *
@@ -113,4 +114,27 @@
      */
     oneway currentPhysicalChannelConfigs_1_6(RadioIndicationType type,
             vec<PhysicalChannelConfig> configs);
+
+    /**
+     * Indicates whether SIM phonebook is changed.
+     *
+     * This indication is sent whenever the SIM phonebook is changed, including SIM is
+     * inserted or removed and updated by IRadio.updateSimPhonebookRecords.
+     *
+     * @param type Type of radio indication
+     */
+    oneway simPhonebookChanged(RadioIndicationType type);
+
+    /**
+     * Indicates the content of all the used records in the SIM phonebook.
+     *
+     * This indication is associated with the API getSimPhonebookRecords and
+     * might be received more than once that is replying on the record count.
+     *
+     * @param type Type of radio indication
+     * @param status Status of PbReceivedStatus
+     * @param records Vector of PhonebookRecordInfo
+     */
+    oneway simPhonebookRecordsReceived(RadioIndicationType type,
+            PbReceivedStatus status, vec<PhonebookRecordInfo> records);
 };
diff --git a/radio/1.6/IRadioResponse.hal b/radio/1.6/IRadioResponse.hal
index 805586b..33fe94f 100644
--- a/radio/1.6/IRadioResponse.hal
+++ b/radio/1.6/IRadioResponse.hal
@@ -27,6 +27,7 @@
 import @1.6::SetupDataCallResult;
 import @1.6::SignalStrength;
 import @1.6::SlicingConfig;
+import @1.6::PhonebookCapacity;
 
 /**
  * Interface declaring response functions to solicited radio requests.
@@ -437,4 +438,57 @@
      */
     oneway getSlicingConfigResponse(RadioResponseInfo info,
             SlicingConfig slicingConfig);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     * REQUEST_NOT_SUPPORTED may only be returned on devices that don't support this API,
+     * indicated by the HAL capability CAPABILITY_SIM_PHONEBOOK_IN_MODEM.
+     */
+    oneway getSimPhonebookRecordsResponse(RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param capacity Response capacity enum indicating response processing status
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     * REQUEST_NOT_SUPPORTED may only be returned on devices that don't support this API,
+     * indicated by the HAL capability CAPABILITY_SIM_PHONEBOOK_IN_MODEM.
+     */
+    oneway getSimPhonebookCapacityResponse(RadioResponseInfo info, PhonebookCapacity capacity);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param updatedRecordIndex The index of the updated or inserted record in the phonebook and
+     *                           the minimum value is 1
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SIM_ERR
+     *   RadioError:NO_SUCH_ENTRY
+     *   RadioError:NO_RESOURCES
+     * REQUEST_NOT_SUPPORTED may only be returned on devices that don't support this API,
+     * indicated by the HAL capability CAPABILITY_SIM_PHONEBOOK_IN_MODEM.
+     */
+    oneway updateSimPhonebookRecordsResponse(RadioResponseInfo info, int32_t updatedRecordIndex);
 };
diff --git a/radio/1.6/types.hal b/radio/1.6/types.hal
index f2c0e76..3fd31cc 100644
--- a/radio/1.6/types.hal
+++ b/radio/1.6/types.hal
@@ -1094,3 +1094,106 @@
     @1.1::ImsiEncryptionInfo base;
     PublicKeyType keyType;         // Public key type
 };
+
+/**
+ * Phonebook-record-information specified by EF_ADN(Abbreviated dialing numbers)
+ * record of SIM as per 3GPP spec 31.102 v15 Section-4.4.2.3.
+ */
+struct PhonebookRecordInfo {
+    /** Record index. 0 is used to insert a record */
+    uint32_t recordId;
+
+    /** Alpha identifier, empty string if no value */
+    string name;
+
+    /** Dialling number, empty string if no value */
+    string number;
+
+    /** Email addresses */
+    vec<string> emails;
+
+    /** Additional numbers */
+    vec<string> additionalNumbers;
+};
+
+struct PhonebookCapacity {
+    /**
+     * Maximum number of ADN records possible in the SIM phonebook
+     * Needs to be non-negative
+     */
+    int32_t maxAdnRecords;
+
+    /**
+     * Used ADN records in the SIM phonebook
+     * Needs to be non-negative
+     */
+    int32_t usedAdnRecords;
+
+    /**
+     * Maximum email records possible in the SIM phonebook
+     * Needs to be non-negative
+     */
+    int32_t maxEmailRecords;
+
+    /**
+     * Used email records in the SIM phonebook
+     * Needs to be non-negative
+     */
+    int32_t usedEmailRecords;
+
+    /**
+     * Maximum additional number records possible in the SIM phonebook
+     * Needs to be non-negative
+     */
+    int32_t maxAdditionalNumberRecords;
+
+    /**
+     * Used additional number records in the SIM phonebook
+     * Needs to be non-negative
+     */
+    int32_t usedAdditionalNumberRecords;
+
+    /**
+     * Maximum name length possible in the SIM phonebook
+     * Needs to be non-negative
+     */
+    int32_t maxNameLen;
+
+    /**
+     * Maximum number length possible in the SIM phonebook
+     * Needs to be non-negative
+     */
+    int32_t maxNumberLen;
+
+    /**
+     * Maximum email length possible in the SIM phonebook
+     * Needs to be non-negative
+     */
+    int32_t maxEmailLen;
+
+    /**
+     * Maximum additional number length possible in the SIM phonebook
+     * Needs to be non-negative
+     */
+    int32_t maxAdditionalNumberLen;
+};
+
+/**
+ * Enum representing the status of the received PB indication,
+ * PB_RECEIVED_OK indicates this retrieval is fine
+ * PB_RECEIVED_ERROR indicates one error happens, in general, the process
+ *   can't be restored soon.
+ * PB_RECEIVED_ABORT indicates the process is interrupted, in this case,
+ *   modem might need resources and interrupt the current process, or it is
+ *   timed out to receive all indications, and client can retry soon.
+ * PB_RECEIVED_FINAL indicates the whole process is finished with a full
+ *   chunk of phonebook data, means this is a last indication with the left
+ *   data.
+ */
+enum PbReceivedStatus : int32_t {
+    PB_RECEIVED_OK = 1,
+    PB_RECEIVED_ERROR = 2,
+    PB_RECEIVED_ABORT = 3,
+    PB_RECEIVED_FINAL = 4,
+};
+
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
index 70abc4b..e060dae 100644
--- a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
@@ -733,8 +733,8 @@
 
     radio_v1_6->setCarrierInfoForImsiEncryption_1_6(serial, imsiInfo);
     EXPECT_EQ(std::cv_status::no_timeout, wait());
-    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
-    EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo_v1_0.type);
+    EXPECT_EQ(serial, radioRsp_v1_6->rspInfo_v1_0.serial);
 
     if (cardStatus.base.base.base.cardState == CardState::ABSENT) {
         ASSERT_TRUE(CheckAnyOfErrors(
@@ -743,3 +743,141 @@
                  ::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
     }
 }
+
+/*
+ * Test IRadio.getSimPhonebookRecords() for the response returned.
+ */
+TEST_F(RadioHidlTest_v1_6, getSimPhonebookRecords) {
+    serial = GetRandomSerialNumber();
+    radio_v1_6->getSimPhonebookRecords(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+    if (cardStatus.base.base.base.cardState == CardState::ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_v1_6->rspInfo.error,
+            {::android::hardware::radio::V1_6::RadioError::INVALID_SIM_STATE,
+             ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+             ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+             ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+             ::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED},
+             CHECK_GENERAL_ERROR));
+    } else if (cardStatus.base.base.base.cardState == CardState::PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_v1_6->rspInfo.error,
+            {::android::hardware::radio::V1_6::RadioError::NONE,
+             ::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED},
+             CHECK_GENERAL_ERROR));
+    }
+}
+
+/*
+ * Test IRadio.getSimPhonebookCapacity for the response returned.
+ */
+TEST_P(RadioHidlTest_v1_6, getSimPhonebookCapacity) {
+    serial = GetRandomSerialNumber();
+    radio_v1_6->getSimPhonebookCapacity(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+    if (cardStatus.base.base.base.cardState == CardState::ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_v1_6->rspInfo.error,
+            {::android::hardware::radio::V1_6::RadioError::INVALID_SIM_STATE,
+             ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+             ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+             ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+             ::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED},
+             CHECK_GENERAL_ERROR));
+    } else if (cardStatus.base.base.base.cardState == CardState::PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_v1_6->rspInfo.error,
+            {::android::hardware::radio::V1_6::RadioError::NONE,
+            ::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED},
+            CHECK_GENERAL_ERROR));
+
+        ::android::hardware::radio::V1_6::PhonebookCapacity pbCapacity =
+             radioRsp_v1_6->capacity;
+        if(pbCapacity.maxAdnRecords > 0) {
+            EXPECT_TRUE(pbCapacity.maxNameLen > 0 && pbCapacity.maxNumberLen > 0);
+            EXPECT_TRUE(pbCapacity.usedAdnRecords <= pbCapacity.maxAdnRecords);
+        }
+
+        if(pbCapacity.maxEmailRecords > 0) {
+            EXPECT_TRUE(pbCapacity.maxEmailLen > 0);
+            EXPECT_TRUE(pbCapacity.usedEmailRecords <= pbCapacity.maxEmailRecords);
+        }
+
+        if(pbCapacity.maxAdditionalNumberRecords > 0) {
+            EXPECT_TRUE(pbCapacity.maxAdditionalNumberLen > 0);
+            EXPECT_TRUE(pbCapacity.usedAdditionalNumberRecords <= pbCapacity.maxAdditionalNumberRecords);
+        }
+    }
+}
+
+/*
+ * Test IRadio.updateSimPhonebookRecords() for the response returned.
+ */
+TEST_F(RadioHidlTest_v1_6, updateSimPhonebookRecords) {
+    serial = GetRandomSerialNumber();
+    radio_v1_6->getSimPhonebookCapacity(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+    if (cardStatus.base.base.base.cardState == CardState::ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_v1_6->rspInfo.error,
+            {::android::hardware::radio::V1_6::RadioError::INVALID_SIM_STATE,
+             ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+             ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+             ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+             ::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED},
+             CHECK_GENERAL_ERROR));
+    } else if (cardStatus.base.base.base.cardState == CardState::PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_v1_6->rspInfo.error,
+            {::android::hardware::radio::V1_6::RadioError::NONE,
+             ::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED},
+             CHECK_GENERAL_ERROR));
+        ::android::hardware::radio::V1_6::PhonebookCapacity pbCapacity =
+                radioRsp_v1_6->capacity;
+
+        serial = GetRandomSerialNumber();
+        radio_v1_6->getSimPhonebookRecords(serial);
+
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+        EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+        EXPECT_EQ(::android::hardware::radio::V1_6::RadioError::NONE, radioRsp_v1_6->rspInfo.error);
+
+        if(pbCapacity.maxAdnRecords > 0
+                && pbCapacity.usedAdnRecords < pbCapacity.maxAdnRecords) {
+            // Add a phonebook record
+            PhonebookRecordInfo recordInfo;
+            recordInfo.recordId = 0;
+            recordInfo.name = "ABC";
+            recordInfo.number = "1234567890";
+            serial = GetRandomSerialNumber();
+            radio_v1_6->updateSimPhonebookRecords(serial, recordInfo);
+
+            EXPECT_EQ(std::cv_status::no_timeout, wait());
+            EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+            EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+            EXPECT_EQ(::android::hardware::radio::V1_6::RadioError::NONE, radioRsp_v1_6->rspInfo.error);
+            int index = radioRsp_v1_6->updatedRecordIndex;
+            EXPECT_TRUE(index > 0);
+
+            // Deleted a phonebook record
+            recordInfo.recordId = index;
+            recordInfo.name = "";
+            recordInfo.number = "";
+            serial = GetRandomSerialNumber();
+            radio_v1_6->updateSimPhonebookRecords(serial, recordInfo);
+
+            EXPECT_EQ(std::cv_status::no_timeout, wait());
+            EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+            EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+            EXPECT_EQ(::android::hardware::radio::V1_6::RadioError::NONE, radioRsp_v1_6->rspInfo.error);
+        }
+    }
+}
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h b/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h
index 23378b5..4fc17e5 100644
--- a/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h
+++ b/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h
@@ -103,6 +103,11 @@
     ::android::hardware::hidl_vec<::android::hardware::radio::V1_5::BarringInfo> barringInfos;
 
     RadioResponse_v1_6(RadioResponseWaiter& parent_v1_6);
+
+    // Phone Book
+    ::android::hardware::radio::V1_6::PhonebookCapacity capacity;
+    int32_t updatedRecordIndex;
+
     virtual ~RadioResponse_v1_6() = default;
 
     Return<void> getIccCardStatusResponse(
@@ -829,6 +834,17 @@
     Return<void> getSlicingConfigResponse(
             const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
             const ::android::hardware::radio::V1_6::SlicingConfig& slicingConfig);
+
+    Return<void> getSimPhonebookRecordsResponse(
+            const ::android::hardware::radio::V1_6::RadioResponseInfo& info);
+
+    Return<void> getSimPhonebookCapacityResponse(
+            const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_6::PhonebookCapacity& capacity);
+
+    Return<void> updateSimPhonebookRecordsResponse(
+            const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+            int32_t updatedRecordIndex);
 };
 
 /* Callback class for radio indication */
@@ -1073,6 +1089,14 @@
             const ::android::hardware::radio::V1_5::CellIdentity& /*cellIdentity*/,
             const ::android::hardware::hidl_vec<::android::hardware::radio::V1_5::BarringInfo>&
             /*barringInfos*/);
+
+    Return<void> simPhonebookChanged(RadioIndicationType type);
+
+    Return<void> simPhonebookRecordsReceived(
+            RadioIndicationType type,
+            ::android::hardware::radio::V1_6::PbReceivedStatus status,
+            const ::android::hardware::hidl_vec<::android::hardware::radio::V1_6::PhonebookRecordInfo>&
+                    records);
 };
 
 // The main test class for Radio HIDL.
diff --git a/radio/1.6/vts/functional/radio_indication.cpp b/radio/1.6/vts/functional/radio_indication.cpp
index e7a9680..8292131 100644
--- a/radio/1.6/vts/functional/radio_indication.cpp
+++ b/radio/1.6/vts/functional/radio_indication.cpp
@@ -412,3 +412,16 @@
                 ::android::hardware::radio::V1_6::CellInfo>& /*records*/) {
     return Void();
 }
+
+Return<void> RadioIndication_v1_6::simPhonebookChanged(
+        RadioIndicationType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::simPhonebookRecordsReceived(
+        RadioIndicationType /*type*/,
+        ::android::hardware::radio::V1_6::PbReceivedStatus /*status*/,
+        const ::android::hardware::hidl_vec<
+        ::android::hardware::radio::V1_6::PhonebookRecordInfo>& /*records*/) {
+    return Void();
+}
diff --git a/radio/1.6/vts/functional/radio_response.cpp b/radio/1.6/vts/functional/radio_response.cpp
index d0c2984..2b6d1bb 100644
--- a/radio/1.6/vts/functional/radio_response.cpp
+++ b/radio/1.6/vts/functional/radio_response.cpp
@@ -87,7 +87,9 @@
 }
 
 Return<void> RadioResponse_v1_6::hangupConnectionResponse(
-        const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+        const ::android::hardware::radio::V1_0::RadioResponseInfo& info) {
+    rspInfo_v1_0 = info;
+    parent_v1_6.notify(info.serial);
     return Void();
 }
 
@@ -749,7 +751,9 @@
 
 /* 1.1 Apis */
 Return<void> RadioResponse_v1_6::setCarrierInfoForImsiEncryptionResponse(
-        const ::android::hardware::radio::V1_0::RadioResponseInfo& /*info*/) {
+        const ::android::hardware::radio::V1_0::RadioResponseInfo& info) {
+    rspInfo_v1_0 = info;
+    parent_v1_6.notify(info.serial);
     return Void();
 }
 
@@ -1232,3 +1236,28 @@
     parent_v1_6.notify(info.serial);
     return Void();
 }
+
+Return<void> RadioResponse_v1_6::getSimPhonebookRecordsResponse(
+        const ::android::hardware::radio::V1_6::RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getSimPhonebookCapacityResponse(
+        const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+        const ::android::hardware::radio::V1_6::PhonebookCapacity& capacity) {
+    rspInfo = info;
+    this->capacity = capacity;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::updateSimPhonebookRecordsResponse(
+        const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
+        int32_t updatedRecordIndex) {
+    rspInfo = info;
+    this->updatedRecordIndex = updatedRecordIndex;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/DeviceInfo.aidl
similarity index 78%
copy from biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
copy to security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/DeviceInfo.aidl
index 4db47c9..d04d49c 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/DeviceInfo.aidl
@@ -31,21 +31,9 @@
 // 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.biometrics.face;
-@Backing(type="byte") @VintfStability
-enum SessionState {
-  IDLING = 0,
-  CLOSED = 1,
-  GENERATING_CHALLENGE = 2,
-  REVOKING_CHALLENGE = 3,
-  ENROLLING = 4,
-  AUTHENTICATING = 5,
-  DETECTING_INTERACTION = 6,
-  ENUMERATING_ENROLLMENTS = 7,
-  REMOVING_ENROLLMENTS = 8,
-  GETTING_FEATURES = 9,
-  SETTING_FEATURE = 10,
-  GETTING_AUTHENTICATOR_ID = 11,
-  INVALIDATING_AUTHENTICATOR_ID = 12,
-  RESETTING_LOCKOUT = 13,
+package android.hardware.security.keymint;
+/* @hide */
+@VintfStability
+parcelable DeviceInfo {
+  byte[] deviceInfo;
 }
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
index 195590c..4f6fb28 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -47,6 +47,7 @@
   android.hardware.security.keymint.BeginResult begin(in android.hardware.security.keymint.KeyPurpose purpose, in byte[] keyBlob, in android.hardware.security.keymint.KeyParameter[] params, in android.hardware.security.keymint.HardwareAuthToken authToken);
   void deviceLocked(in boolean passwordOnly, in @nullable android.hardware.security.secureclock.TimeStampToken timestampToken);
   void earlyBootEnded();
+  byte[] convertStorageKeyToEphemeral(in byte[] storageKeyBlob);
   byte[] performOperation(in byte[] request);
   const int AUTH_TOKEN_MAC_LENGTH = 32;
 }
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
index 63bad2c..88c479c 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
@@ -36,7 +36,7 @@
 @VintfStability
 interface IRemotelyProvisionedComponent {
   byte[] generateEcdsaP256KeyPair(in boolean testMode, out android.hardware.security.keymint.MacedPublicKey macedPublicKey);
-  void generateCertificateRequest(in boolean testMode, in android.hardware.security.keymint.MacedPublicKey[] keysToSign, in byte[] endpointEncryptionCertChain, in byte[] challenge, out byte[] keysToSignMac, out android.hardware.security.keymint.ProtectedData protectedData);
+  byte[] generateCertificateRequest(in boolean testMode, in android.hardware.security.keymint.MacedPublicKey[] keysToSign, in byte[] endpointEncryptionCertChain, in byte[] challenge, out android.hardware.security.keymint.DeviceInfo deviceInfo, out android.hardware.security.keymint.ProtectedData protectedData);
   const int STATUS_FAILED = 1;
   const int STATUS_INVALID_MAC = 2;
   const int STATUS_PRODUCTION_KEY_IN_TEST_REQUEST = 3;
diff --git a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
new file mode 100644
index 0000000..3ea14a1
--- /dev/null
+++ b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.keymint;
+
+/**
+ * DeviceInfo contains information about the device that's fed in as AAD in the signature of the
+ * device private key over the MAC key used for the bundle of public keys. These values are intended
+ * to be checked by the server to verify that the certificate signing request crafted by
+ * an IRemotelyProvisionedComponent HAL instance is coming from the expected device based
+ * on values initially uploaded during device manufacture in the factory.
+ * @hide
+ */
+@VintfStability
+parcelable DeviceInfo {
+    /**
+     * DeviceInfo is a CBOR Map structure described by the following CDDL.
+     *
+     *     DeviceInfo = {
+     *         ? "brand" : tstr,
+     *         ? "manufacturer" : tstr,
+     *         ? "product" : tstr,
+     *         ? "model" : tstr,
+     *         ? "board" : tstr,
+     *         ? "vb_state" : "green" / "yellow" / "orange",    // Taken from the AVB values
+     *         ? "bootloader_state" : "locked" / "unlocked",    // Taken from the AVB values
+     *         ? "os_version" : tstr,                    // Same as android.os.Build.VERSION.release
+     *         ? "system_patch_level" : uint,                   // YYYYMMDD
+     *         ? "boot_patch_level" : uint,                     // YYYYMMDD
+     *         ? "vendor_patch_level" : uint,                   // YYYYMMDD
+     *     }
+     */
+    byte[] deviceInfo;
+}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
index 3100b23..17aab25 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -762,6 +762,27 @@
      */
     void earlyBootEnded();
 
+    /*
+     * Called by the client to get a wrapped per-boot ephemeral key from a wrapped storage key.
+     * Clients will then use the returned per-boot ephemeral key in place of the wrapped storage
+     * key. Whenever the hardware is presented with a per-boot ephemeral key for an operation, it
+     * must use the storage key associated with that ephemeral key to perform the requested
+     * operation.
+     *
+     * Implementations should return ErrorCode::UNIMPLEMENTED if they don't support wrapped storage
+     * keys.
+     *
+     * Implementations should return ErrorCode::INVALID_ARGUMENT (as a ServiceSpecificException)
+     * if the input key blob doesn't represent a valid long-lived wrapped storage key.
+     *
+     * @param storageKeyBlob is the wrapped storage key for which the client wants a per-boot
+     *        ephemeral key
+     *
+     * @return a buffer containing the per-boot ephemeral keyblob that should henceforth be used in
+     *         place of the input storageKeyBlob
+     */
+    byte[] convertStorageKeyToEphemeral(in byte[] storageKeyBlob);
+
     /**
      * Called by the client to perform a KeyMint operation.
      *
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
index 5c8ca6d..1cb50ba 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.security.keymint;
 
+import android.hardware.security.keymint.DeviceInfo;
 import android.hardware.security.keymint.MacedPublicKey;
 import android.hardware.security.keymint.ProtectedData;
 
@@ -257,7 +258,7 @@
      * @param out ProtectedData contains the encrypted BCC and the ephemeral MAC key used to
      *        authenticate the keysToSign (see keysToSignMac output argument).
      */
-    void generateCertificateRequest(in boolean testMode, in MacedPublicKey[] keysToSign,
-            in byte[] endpointEncryptionCertChain, in byte[] challenge, out byte[] keysToSignMac,
+    byte[] generateCertificateRequest(in boolean testMode, in MacedPublicKey[] keysToSign,
+            in byte[] endpointEncryptionCertChain, in byte[] challenge, out DeviceInfo deviceInfo,
             out ProtectedData protectedData);
 }
diff --git a/security/keymint/aidl/default/Android.bp b/security/keymint/aidl/default/Android.bp
index 63b91fe..ebdc9b7 100644
--- a/security/keymint/aidl/default/Android.bp
+++ b/security/keymint/aidl/default/Android.bp
@@ -39,6 +39,17 @@
     srcs: [
         "service.cpp",
     ],
+    required: [
+        "RemoteProvisioner",
+        "android.hardware.hardware_keystore.xml",
+    ],
+}
+
+prebuilt_etc {
+    name: "android.hardware.hardware_keystore.xml",
+    sub_dir: "permissions",
+    vendor: true,
+    src: "android.hardware.hardware_keystore.xml",
 }
 
 cc_library {
diff --git a/security/keymint/aidl/default/RemotelyProvisionedComponent.cpp b/security/keymint/aidl/default/RemotelyProvisionedComponent.cpp
index 749f0bc..4dbaa05 100644
--- a/security/keymint/aidl/default/RemotelyProvisionedComponent.cpp
+++ b/security/keymint/aidl/default/RemotelyProvisionedComponent.cpp
@@ -322,8 +322,8 @@
 
 ScopedAStatus RemotelyProvisionedComponent::generateCertificateRequest(
         bool testMode, const vector<MacedPublicKey>& keysToSign,
-        const bytevec& endpointEncCertChain, const bytevec& challenge, bytevec* keysToSignMac,
-        ProtectedData* protectedData) {
+        const bytevec& endpointEncCertChain, const bytevec& challenge, DeviceInfo* deviceInfo,
+        ProtectedData* protectedData, bytevec* keysToSignMac) {
     auto pubKeysToSign = validateAndExtractPubkeys(testMode, keysToSign,
                                                    testMode ? remote_prov::kTestMacKey : macKey_);
     if (!pubKeysToSign.isOk()) return pubKeysToSign.moveError();
@@ -343,11 +343,12 @@
         bcc = bcc_.clone();
     }
 
+    deviceInfo->deviceInfo = createDeviceInfo();
     auto signedMac = constructCoseSign1(devicePrivKey /* Signing key */,  //
                                         ephemeralMacKey /* Payload */,
                                         cppbor::Array() /* AAD */
                                                 .add(challenge)
-                                                .add(createDeviceInfo())
+                                                .add(deviceInfo->deviceInfo)
                                                 .encode());
     if (!signedMac) return Status(signedMac.moveMessage());
 
diff --git a/security/keymint/aidl/default/RemotelyProvisionedComponent.h b/security/keymint/aidl/default/RemotelyProvisionedComponent.h
index e8d2343..65b1bbc 100644
--- a/security/keymint/aidl/default/RemotelyProvisionedComponent.h
+++ b/security/keymint/aidl/default/RemotelyProvisionedComponent.h
@@ -39,8 +39,8 @@
                                              const std::vector<MacedPublicKey>& keysToSign,
                                              const std::vector<uint8_t>& endpointEncCertChain,
                                              const std::vector<uint8_t>& challenge,
-                                             std::vector<uint8_t>* keysToSignMac,
-                                             ProtectedData* protectedData) override;
+                                             DeviceInfo* deviceInfo, ProtectedData* protectedData,
+                                             std::vector<uint8_t>* keysToSignMac) override;
 
   private:
     // TODO(swillden): Move these into an appropriate Context class.
diff --git a/security/keymint/aidl/default/android.hardware.hardware_keystore.xml b/security/keymint/aidl/default/android.hardware.hardware_keystore.xml
new file mode 100644
index 0000000..e5a9345
--- /dev/null
+++ b/security/keymint/aidl/default/android.hardware.hardware_keystore.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<permissions>
+  <feature name="android.hardware.hardware_keystore" version="100" />
+</permissions>
diff --git a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index 50e6cce..9b797de 100644
--- a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -227,11 +227,12 @@
 TEST_P(CertificateRequestTest, EmptyRequest_testMode) {
     bool testMode = true;
     bytevec keysToSignMac;
+    DeviceInfo deviceInfo;
     ProtectedData protectedData;
     auto challenge = randomBytes(32);
-    auto status = provisionable_->generateCertificateRequest(testMode, {} /* keysToSign */,
-                                                             eekChain_.chain, challenge,
-                                                             &keysToSignMac, &protectedData);
+    auto status = provisionable_->generateCertificateRequest(
+            testMode, {} /* keysToSign */, eekChain_.chain, challenge, &deviceInfo, &protectedData,
+            &keysToSignMac);
     ASSERT_TRUE(status.isOk()) << status.getMessage();
 
     auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData);
@@ -297,11 +298,12 @@
 TEST_P(CertificateRequestTest, EmptyRequest_prodMode) {
     bool testMode = false;
     bytevec keysToSignMac;
+    DeviceInfo deviceInfo;
     ProtectedData protectedData;
     auto challenge = randomBytes(32);
-    auto status = provisionable_->generateCertificateRequest(testMode, {} /* keysToSign */,
-                                                             eekChain_.chain, challenge,
-                                                             &keysToSignMac, &protectedData);
+    auto status = provisionable_->generateCertificateRequest(
+            testMode, {} /* keysToSign */, eekChain_.chain, challenge, &deviceInfo, &protectedData,
+            &keysToSignMac);
     ASSERT_FALSE(status.isOk());
     ASSERT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
 }
@@ -314,10 +316,12 @@
     generateKeys(testMode, 4 /* numKeys */);
 
     bytevec keysToSignMac;
+    DeviceInfo deviceInfo;
     ProtectedData protectedData;
     auto challenge = randomBytes(32);
-    auto status = provisionable_->generateCertificateRequest(
-            testMode, keysToSign_, eekChain_.chain, challenge, &keysToSignMac, &protectedData);
+    auto status = provisionable_->generateCertificateRequest(testMode, keysToSign_, eekChain_.chain,
+                                                             challenge, &deviceInfo, &protectedData,
+                                                             &keysToSignMac);
     ASSERT_TRUE(status.isOk()) << status.getMessage();
 
     auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData);
@@ -384,10 +388,12 @@
     generateKeys(testMode, 4 /* numKeys */);
 
     bytevec keysToSignMac;
+    DeviceInfo deviceInfo;
     ProtectedData protectedData;
     auto challenge = randomBytes(32);
-    auto status = provisionable_->generateCertificateRequest(
-            testMode, keysToSign_, eekChain_.chain, challenge, &keysToSignMac, &protectedData);
+    auto status = provisionable_->generateCertificateRequest(testMode, keysToSign_, eekChain_.chain,
+                                                             challenge, &deviceInfo, &protectedData,
+                                                             &keysToSignMac);
     ASSERT_FALSE(status.isOk());
     ASSERT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
 }
@@ -400,11 +406,12 @@
     generateKeys(false /* testMode */, 2 /* numKeys */);
 
     bytevec keysToSignMac;
+    DeviceInfo deviceInfo;
     ProtectedData protectedData;
     auto challenge = randomBytes(32);
-    auto status = provisionable_->generateCertificateRequest(true /* testMode */, keysToSign_,
-                                                             eekChain_.chain, challenge,
-                                                             &keysToSignMac, &protectedData);
+    auto status = provisionable_->generateCertificateRequest(
+            true /* testMode */, keysToSign_, eekChain_.chain, challenge, &deviceInfo,
+            &protectedData, &keysToSignMac);
     ASSERT_FALSE(status.isOk());
     ASSERT_EQ(status.getServiceSpecificError(),
               BnRemotelyProvisionedComponent::STATUS_PRODUCTION_KEY_IN_TEST_REQUEST);
@@ -418,10 +425,11 @@
     generateKeys(true /* testMode */, 2 /* numKeys */);
 
     bytevec keysToSignMac;
+    DeviceInfo deviceInfo;
     ProtectedData protectedData;
     auto status = provisionable_->generateCertificateRequest(
             false /* testMode */, keysToSign_, eekChain_.chain, randomBytes(32) /* challenge */,
-            &keysToSignMac, &protectedData);
+            &deviceInfo, &protectedData, &keysToSignMac);
     ASSERT_FALSE(status.isOk());
     ASSERT_EQ(status.getServiceSpecificError(),
               BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST);
diff --git a/security/secureclock/aidl/vts/functional/Android.bp b/security/secureclock/aidl/vts/functional/Android.bp
index 6dfa417..56c8e1d 100644
--- a/security/secureclock/aidl/vts/functional/Android.bp
+++ b/security/secureclock/aidl/vts/functional/Android.bp
@@ -39,11 +39,11 @@
     shared_libs: [
         "libbinder_ndk",
         "libcrypto",
-        "libkeymint",
     ],
     static_libs: [
         "android.hardware.security.keymint-V1-ndk_platform",
         "android.hardware.security.secureclock-V1-ndk_platform",
+        "libkeymint",
     ],
     test_suites: [
         "general-tests",
diff --git a/security/secureclock/aidl/vts/functional/AndroidTest.xml b/security/secureclock/aidl/vts/functional/AndroidTest.xml
deleted file mode 100644
index 4861c7c..0000000
--- a/security/secureclock/aidl/vts/functional/AndroidTest.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<configuration description="Runs VtsAidlSecureClockTargetTest.">
-    <option name="test-suite-tag" value="apct" />
-    <option name="test-suite-tag" value="apct-native" />
-
-    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
-    </target_preparer>
-
-    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
-        <option name="cleanup" value="true" />
-        <option name="push"
-                value="VtsAidlSecureClockTargetTest->/data/local/tmp/VtsAidlSecureClockTargetTest" />
-    </target_preparer>
-
-    <test class="com.android.tradefed.testtype.GTest" >
-        <option name="native-test-device-path" value="/data/local/tmp" />
-        <option name="module-name" value="VtsAidlSecureClockTargetTest" />
-        <option name="native-test-timeout" value="900000"/>
-    </test>
-</configuration>
diff --git a/security/sharedsecret/aidl/vts/functional/Android.bp b/security/sharedsecret/aidl/vts/functional/Android.bp
index 1bc5beb..d3747fc 100644
--- a/security/sharedsecret/aidl/vts/functional/Android.bp
+++ b/security/sharedsecret/aidl/vts/functional/Android.bp
@@ -39,11 +39,11 @@
     shared_libs: [
         "libbinder_ndk",
         "libcrypto",
-        "libkeymint",
     ],
     static_libs: [
         "android.hardware.security.keymint-V1-ndk_platform",
         "android.hardware.security.sharedsecret-V1-ndk_platform",
+        "libkeymint",
     ],
     test_suites: [
         "general-tests",
diff --git a/security/sharedsecret/aidl/vts/functional/AndroidTest.xml b/security/sharedsecret/aidl/vts/functional/AndroidTest.xml
deleted file mode 100644
index c6697bc..0000000
--- a/security/sharedsecret/aidl/vts/functional/AndroidTest.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<configuration description="Runs VtsAidlSharedSecretTargetTest.">
-    <option name="test-suite-tag" value="apct" />
-    <option name="test-suite-tag" value="apct-native" />
-
-    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
-    </target_preparer>
-
-    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
-        <option name="cleanup" value="true" />
-        <option name="push"
-                value="VtsAidlSharedSecretTargetTest->/data/local/tmp/VtsAidlSharedSecretTargetTest" />
-    </target_preparer>
-
-    <test class="com.android.tradefed.testtype.GTest" >
-        <option name="native-test-device-path" value="/data/local/tmp" />
-        <option name="module-name" value="VtsAidlSharedSecretTargetTest" />
-        <option name="native-test-timeout" value="900000"/>
-    </test>
-</configuration>
diff --git a/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp b/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp
index 83f6ef3..8426120 100644
--- a/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp
+++ b/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp
@@ -114,14 +114,14 @@
     const vector<shared_ptr<ISharedSecret>>& allSharedSecrets() { return allSharedSecrets_; }
 
     static void SetUpTestCase() {
-        if (allSharedSecrets_.empty()) {
-            auto names = ::android::getAidlHalInstanceNames(ISharedSecret::descriptor);
-            for (const auto& name : names) {
-                auto servicePtr = getSharedSecretService(name.c_str());
-                if (servicePtr != nullptr) allSharedSecrets_.push_back(std::move(servicePtr));
-            }
+        ASSERT_TRUE(allSharedSecrets_.empty()) << "The Shared Secret vector is not empty.";
+        auto names = ::android::getAidlHalInstanceNames(ISharedSecret::descriptor);
+        for (const auto& name : names) {
+            auto servicePtr = getSharedSecretService(name.c_str());
+            if (servicePtr != nullptr) allSharedSecrets_.push_back(std::move(servicePtr));
         }
     }
+
     static void TearDownTestCase() {}
     void SetUp() override {}
     void TearDown() override {}
@@ -134,6 +134,9 @@
 
 TEST_F(SharedSecretAidlTest, GetParameters) {
     auto sharedSecrets = allSharedSecrets();
+    if (sharedSecrets.empty()) {
+        GTEST_SKIP() << "Skipping the test because no shared secret service is found.";
+    }
     for (auto sharedSecret : sharedSecrets) {
         auto result1 = getSharedSecretParameters(sharedSecret);
         EXPECT_EQ(ErrorCode::OK, result1.error);
@@ -148,14 +151,18 @@
 }
 
 TEST_F(SharedSecretAidlTest, ComputeSharedSecret) {
+    auto sharedSecrets = allSharedSecrets();
+    if (sharedSecrets.empty()) {
+        GTEST_SKIP() << "Skipping the test as no shared secret service is found.";
+    }
     auto params = getAllSharedSecretParameters();
-    ASSERT_EQ(allSharedSecrets().size(), params.size())
+    ASSERT_EQ(sharedSecrets.size(), params.size())
             << "One or more shared secret services failed to provide parameters.";
     auto nonces = copyNonces(params);
-    EXPECT_EQ(allSharedSecrets().size(), nonces.size());
+    EXPECT_EQ(sharedSecrets.size(), nonces.size());
     std::sort(nonces.begin(), nonces.end());
     std::unique(nonces.begin(), nonces.end());
-    EXPECT_EQ(allSharedSecrets().size(), nonces.size());
+    EXPECT_EQ(sharedSecrets.size(), nonces.size());
 
     auto responses = computeAllSharedSecrets(params);
     ASSERT_GT(responses.size(), 0U);
@@ -163,7 +170,7 @@
 
     // Do it a second time.  Should get the same answers.
     params = getAllSharedSecretParameters();
-    ASSERT_EQ(allSharedSecrets().size(), params.size())
+    ASSERT_EQ(sharedSecrets.size(), params.size())
             << "One or more shared secret services failed to provide parameters.";
 
     responses = computeAllSharedSecrets(params);
@@ -188,10 +195,14 @@
 }
 
 TEST_F(SharedSecretAidlTest, ComputeSharedSecretCorruptNonce) {
+    auto sharedSecrets = allSharedSecrets();
+    if (sharedSecrets.empty()) {
+        GTEST_SKIP() << "Skipping the test as no shared secret service is found.";
+    }
     auto fixup_hmac = finally([&]() { computeAllSharedSecrets(getAllSharedSecretParameters()); });
 
     auto params = getAllSharedSecretParameters();
-    ASSERT_EQ(allSharedSecrets().size(), params.size())
+    ASSERT_EQ(sharedSecrets.size(), params.size())
             << "One or more shared secret services failed to provide parameters.";
 
     // All should be well in the normal case
@@ -224,9 +235,13 @@
 }
 
 TEST_F(SharedSecretAidlTest, ComputeSharedSecretCorruptSeed) {
+    auto sharedSecrets = allSharedSecrets();
+    if (sharedSecrets.empty()) {
+        GTEST_SKIP() << "Skipping the test as no shared secret service is found.";
+    }
     auto fixup_hmac = finally([&]() { computeAllSharedSecrets(getAllSharedSecretParameters()); });
     auto params = getAllSharedSecretParameters();
-    ASSERT_EQ(allSharedSecrets().size(), params.size())
+    ASSERT_EQ(sharedSecrets.size(), params.size())
             << "One or more shared secret service failed to provide parameters.";
 
     // All should be well in the normal case
diff --git a/sensors/common/utils/EventMessageQueueWrapper.h b/sensors/common/utils/EventMessageQueueWrapper.h
index c4f92c8..63e4eb0 100644
--- a/sensors/common/utils/EventMessageQueueWrapper.h
+++ b/sensors/common/utils/EventMessageQueueWrapper.h
@@ -33,7 +33,7 @@
 namespace V2_1 {
 namespace implementation {
 
-class EventMessageQueueWrapperBase : public RefBase {
+class EventMessageQueueWrapperBase {
   public:
     virtual ~EventMessageQueueWrapperBase() {}
 
diff --git a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
index 8cf5003..47a8cc0 100644
--- a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
+++ b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
@@ -462,6 +462,7 @@
 
     // Wait for events to be written back to the Event FMQ
     callback.waitForEvents(sensors, milliseconds(1000) /* timeout */);
+    getEnvironment()->unregisterCallback();
 
     for (const auto& s : sensors) {
         auto events = callback.getEvents(s.sensorHandle);
@@ -485,7 +486,6 @@
         ASSERT_EQ(lastEvent.u.vec3.status, injectedEvent.u.vec3.status);
     }
 
-    getEnvironment()->unregisterCallback();
     ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::NORMAL));
 }
 
@@ -603,7 +603,7 @@
                          << " type=" << static_cast<int>(sensor.type) << " name=" << sensor.name);
 
             Result flushResult = flush(sensor.sensorHandle);
-            ASSERT_EQ(flushResult, expectedResponse);
+            EXPECT_EQ(flushResult, expectedResponse);
         }
     }
 
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/ActivePwle.aidl
similarity index 78%
copy from biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
copy to vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/ActivePwle.aidl
index 4db47c9..de3ad3c 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/ActivePwle.aidl
@@ -31,21 +31,12 @@
 // 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.biometrics.face;
-@Backing(type="byte") @VintfStability
-enum SessionState {
-  IDLING = 0,
-  CLOSED = 1,
-  GENERATING_CHALLENGE = 2,
-  REVOKING_CHALLENGE = 3,
-  ENROLLING = 4,
-  AUTHENTICATING = 5,
-  DETECTING_INTERACTION = 6,
-  ENUMERATING_ENROLLMENTS = 7,
-  REMOVING_ENROLLMENTS = 8,
-  GETTING_FEATURES = 9,
-  SETTING_FEATURE = 10,
-  GETTING_AUTHENTICATOR_ID = 11,
-  INVALIDATING_AUTHENTICATOR_ID = 12,
-  RESETTING_LOCKOUT = 13,
+package android.hardware.vibrator;
+@VintfStability
+parcelable ActivePwle {
+  float startAmplitude;
+  float startFrequency;
+  float endAmplitude;
+  float endFrequency;
+  int duration;
 }
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Braking.aidl
similarity index 78%
rename from biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
rename to vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Braking.aidl
index 4db47c9..d38c584 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Braking.aidl
@@ -31,21 +31,9 @@
 // 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.biometrics.face;
-@Backing(type="byte") @VintfStability
-enum SessionState {
-  IDLING = 0,
-  CLOSED = 1,
-  GENERATING_CHALLENGE = 2,
-  REVOKING_CHALLENGE = 3,
-  ENROLLING = 4,
-  AUTHENTICATING = 5,
-  DETECTING_INTERACTION = 6,
-  ENUMERATING_ENROLLMENTS = 7,
-  REMOVING_ENROLLMENTS = 8,
-  GETTING_FEATURES = 9,
-  SETTING_FEATURE = 10,
-  GETTING_AUTHENTICATOR_ID = 11,
-  INVALIDATING_AUTHENTICATOR_ID = 12,
-  RESETTING_LOCKOUT = 13,
+package android.hardware.vibrator;
+@Backing(type="int") @VintfStability
+enum Braking {
+  NONE = 0,
+  CLAB = 1,
 }
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/BrakingPwle.aidl
similarity index 78%
copy from biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
copy to vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/BrakingPwle.aidl
index 4db47c9..fa7b43a 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/BrakingPwle.aidl
@@ -31,21 +31,9 @@
 // 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.biometrics.face;
-@Backing(type="byte") @VintfStability
-enum SessionState {
-  IDLING = 0,
-  CLOSED = 1,
-  GENERATING_CHALLENGE = 2,
-  REVOKING_CHALLENGE = 3,
-  ENROLLING = 4,
-  AUTHENTICATING = 5,
-  DETECTING_INTERACTION = 6,
-  ENUMERATING_ENROLLMENTS = 7,
-  REMOVING_ENROLLMENTS = 8,
-  GETTING_FEATURES = 9,
-  SETTING_FEATURE = 10,
-  GETTING_AUTHENTICATOR_ID = 11,
-  INVALIDATING_AUTHENTICATOR_ID = 12,
-  RESETTING_LOCKOUT = 13,
+package android.hardware.vibrator;
+@VintfStability
+parcelable BrakingPwle {
+  android.hardware.vibrator.Braking braking;
+  int duration;
 }
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositeEffect.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositeEffect.aidl
index 0995d2d..3be58a1 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositeEffect.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositeEffect.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePrimitive.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePrimitive.aidl
index 0b4b527..50de13f 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePrimitive.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePrimitive.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Effect.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Effect.aidl
index 0d2b340..adf0f20 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Effect.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/Effect.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/EffectStrength.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/EffectStrength.aidl
index 808644a..af5e158 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/EffectStrength.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/EffectStrength.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl
index 1f2d946..b7afb66 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -50,6 +51,13 @@
   void alwaysOnDisable(in int id);
   float getResonantFrequency();
   float getQFactor();
+  float getFrequencyResolution();
+  float getFrequencyMinimum();
+  float[] getBandwidthAmplitudeMap();
+  int getPwlePrimitiveDurationMax();
+  int getPwleCompositionSizeMax();
+  android.hardware.vibrator.Braking[] getSupportedBraking();
+  void composePwle(in android.hardware.vibrator.PrimitivePwle[] composite, in android.hardware.vibrator.IVibratorCallback callback);
   const int CAP_ON_CALLBACK = 1;
   const int CAP_PERFORM_CALLBACK = 2;
   const int CAP_AMPLITUDE_CONTROL = 4;
@@ -59,4 +67,6 @@
   const int CAP_ALWAYS_ON_CONTROL = 64;
   const int CAP_GET_RESONANT_FREQUENCY = 128;
   const int CAP_GET_Q_FACTOR = 256;
+  const int CAP_FREQUENCY_CONTROL = 512;
+  const int CAP_COMPOSE_PWLE_EFFECTS = 1024;
 }
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorCallback.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorCallback.aidl
index f99ecc1..99d6d22 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorCallback.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorCallback.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl
index 8e3ac88..290c68d 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibratorManager.aidl
@@ -12,7 +12,8 @@
  * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PrimitivePwle.aidl
similarity index 78%
copy from biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
copy to vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PrimitivePwle.aidl
index 4db47c9..584bcf4 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/SessionState.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PrimitivePwle.aidl
@@ -31,21 +31,9 @@
 // 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.biometrics.face;
-@Backing(type="byte") @VintfStability
-enum SessionState {
-  IDLING = 0,
-  CLOSED = 1,
-  GENERATING_CHALLENGE = 2,
-  REVOKING_CHALLENGE = 3,
-  ENROLLING = 4,
-  AUTHENTICATING = 5,
-  DETECTING_INTERACTION = 6,
-  ENUMERATING_ENROLLMENTS = 7,
-  REMOVING_ENROLLMENTS = 8,
-  GETTING_FEATURES = 9,
-  SETTING_FEATURE = 10,
-  GETTING_AUTHENTICATOR_ID = 11,
-  INVALIDATING_AUTHENTICATOR_ID = 12,
-  RESETTING_LOCKOUT = 13,
+package android.hardware.vibrator;
+@VintfStability
+union PrimitivePwle {
+  android.hardware.vibrator.ActivePwle active;
+  android.hardware.vibrator.BrakingPwle braking;
 }
diff --git a/vibrator/aidl/android/hardware/vibrator/ActivePwle.aidl b/vibrator/aidl/android/hardware/vibrator/ActivePwle.aidl
new file mode 100644
index 0000000..fd5f8d1
--- /dev/null
+++ b/vibrator/aidl/android/hardware/vibrator/ActivePwle.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.vibrator;
+
+@VintfStability
+parcelable ActivePwle {
+    /**
+     * Amplitude ranging from 0.0 (inclusive) to 1.0 (inclusive)
+     * in units of output acceleration amplitude, not voltage amplitude.
+     *
+     * 0.0 represents no output acceleration amplitude
+     * 1.0 represents maximum output acceleration amplitude at resonant frequency
+     */
+    float startAmplitude;
+    /**
+     * Absolute frequency point in the units of hertz
+     */
+    float startFrequency;
+    /**
+     * Amplitude ranging from 0.0 (inclusive) to 1.0 (inclusive)
+     * in units of output acceleration amplitude, not voltage amplitude.
+     *
+     * 0.0 represents no output acceleration amplitude
+     * 1.0 represents maximum output acceleration amplitude at resonant frequency
+     */
+    float endAmplitude;
+    /**
+     * Absolute frequency point in the units of hertz
+     */
+    float endFrequency;
+    /**
+     * Total duration from start point to end point in the units of milliseconds
+     */
+    int duration;
+}
diff --git a/vibrator/aidl/android/hardware/vibrator/Braking.aidl b/vibrator/aidl/android/hardware/vibrator/Braking.aidl
new file mode 100644
index 0000000..2bc51db
--- /dev/null
+++ b/vibrator/aidl/android/hardware/vibrator/Braking.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.vibrator;
+
+@VintfStability
+@Backing(type="int")
+enum Braking {
+    /**
+     * No braking mechanism used.
+     * This is the default if the hardware does not support any braking mechanism.
+     */
+    NONE,
+    /**
+     * Closed-loop active braking.
+     *
+     * This effect should produce a sharp, crisp end to the waveform
+     * Support is optional.
+     */
+    CLAB,
+}
diff --git a/vibrator/aidl/android/hardware/vibrator/BrakingPwle.aidl b/vibrator/aidl/android/hardware/vibrator/BrakingPwle.aidl
new file mode 100644
index 0000000..00675ed
--- /dev/null
+++ b/vibrator/aidl/android/hardware/vibrator/BrakingPwle.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.vibrator;
+
+import android.hardware.vibrator.Braking;
+
+/**
+ * BrakingPwle is defined as a segment of zero output acceleration amplitude of duration length.
+ *
+ * There should be no output acceleration and the vibrator should be off for the entire duration.
+ * If the hardware supports braking mechanism(s), they can be set here.
+ */
+@VintfStability
+parcelable BrakingPwle {
+    /**
+     * Braking mechanism applied to adjacent segments
+     */
+    Braking braking;
+    /**
+     * Total duration of zero output acceleration in the units of milliseconds.
+     */
+    int duration;
+}
diff --git a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
index cba76dc..592d151 100644
--- a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
@@ -17,10 +17,12 @@
 package android.hardware.vibrator;
 
 import android.hardware.vibrator.IVibratorCallback;
+import android.hardware.vibrator.Braking;
 import android.hardware.vibrator.Effect;
 import android.hardware.vibrator.EffectStrength;
 import android.hardware.vibrator.CompositeEffect;
 import android.hardware.vibrator.CompositePrimitive;
+import android.hardware.vibrator.PrimitivePwle;
 
 @VintfStability
 interface IVibrator {
@@ -60,6 +62,14 @@
      * Whether getQFactor is supported.
      */
     const int CAP_GET_Q_FACTOR = 1 << 8;
+    /**
+     * Whether frequency control is supported.
+     */
+    const int CAP_FREQUENCY_CONTROL = 1 << 9;
+    /**
+     * Whether composePwle is supported.
+     */
+    const int CAP_COMPOSE_PWLE_EFFECTS = 1 << 10;
 
     /**
      * Determine capabilities of the vibrator HAL (CAP_* mask)
@@ -240,18 +250,109 @@
     void alwaysOnDisable(in int id);
 
     /**
-     * Retrieve the measured resonant frequency of the actuator. This may not be supported
-     * and this support is reflected in getCapabilities (CAP_GET_RESONANT_FREQUENCY)
+     * Retrieve the measured resonant frequency of the actuator.
      *
-     * @return Measured resonant frequency in Hz.
+     * This may not be supported and this support is reflected in
+     * getCapabilities (CAP_GET_RESONANT_FREQUENCY)
+     *
+     * @return Measured resonant frequency in Hz. Non-zero value if supported,
+     *         or value should be ignored if not supported.
      */
     float getResonantFrequency();
 
     /**
-     * Retrieve the measured Q factor. This may not be supported
-     * and this support is reflected in getCapabilities (CAP_GET_Q_FACTOR)
+     * Retrieve the measured Q factor.
      *
-     * @return Measured Q factor.
+     * This may not be supported and this support is reflected in
+     * getCapabilities (CAP_GET_Q_FACTOR)
+     *
+     * @return Measured Q factor. Non-zero value if supported, or value should be
+     *         ignored if not supported.
      */
     float getQFactor();
+
+    /**
+     * Retrieve the frequency resolution used in getBandwidthAmplitudeMap() in units of hertz
+     *
+     * This may not be supported and this support is reflected in
+     * getCapabilities (CAP_FREQUENCY_CONTROL).
+     *
+     * @return The frequency resolution of the bandwidth amplitude map.
+     *         Non-zero value if supported, or value should be ignored if not supported.
+     */
+    float getFrequencyResolution();
+
+    /**
+     * Retrieve the minimum allowed frequency in units of hertz
+     *
+     * This may not be supported and this support is reflected in
+     * getCapabilities (CAP_FREQUENCY_CONTROL).
+     *
+     * @return The minimum frequency allowed. Non-zero value if supported,
+     *         or value should be ignored if not supported.
+     */
+    float getFrequencyMinimum();
+
+    /**
+     * Retrieve the output acceleration amplitude values per frequency supported
+     *
+     * This may not be supported and this support is reflected in
+     * getCapabilities (CAP_FREQUENCY_CONTROL).
+     *
+     * The mapping is represented as a list of amplitude values in the inclusive range [0.0, 1.0].
+     * The first value represents the amplitude at the frequency returned by getFrequencyMinimum().
+     * Each subsequent element is the amplitude at the next supported frequency, in increments
+     * of getFrequencyResolution(). The value returned by getResonantFrequency() must be
+     * represented in the returned list.
+     *
+     * @return The maximum output acceleration amplitude for each supported frequency,
+     *         starting at getMinimumFrequency()
+     */
+    float[] getBandwidthAmplitudeMap();
+
+    /**
+     * Retrieve the maximum duration allowed for any primitive PWLE in units of milliseconds.
+     *
+     * This may not be supported and this support is reflected in
+     * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS).
+     *
+     * @return The maximum duration allowed for a single PrimitivePwle.
+     *         Non-zero value if supported, or value should be ignored if not supported.
+     */
+    int getPwlePrimitiveDurationMax();
+
+    /**
+     * Retrieve the maximum count for allowed PWLEs in one composition.
+     *
+     * This may not be supported and this support is reflected in
+     * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS).
+     *
+     * @return The maximum count allowed. Non-zero value if supported,
+     *         or value should be ignored if not supported.
+     */
+    int getPwleCompositionSizeMax();
+
+    /**
+     * List of supported braking mechanism.
+     *
+     * This may not be supported and this support is reflected in
+     * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS).
+     * Implementations are optional but encouraged if available.
+     *
+     * @return The braking mechanisms which are supported by the composePwle API.
+     */
+    Braking[] getSupportedBraking();
+
+    /**
+     * Fire off a string of PWLEs.
+     *
+     * This may not be supported and this support is reflected in
+     * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS).
+     *
+     * Doing this operation while the vibrator is already on is undefined behavior. Clients should
+     * explicitly call off. IVibratorCallback.onComplete() support is required for this API.
+     *
+     * @param composite Array of PWLEs.
+     */
+    void composePwle(in PrimitivePwle[] composite, in IVibratorCallback callback);
 }
diff --git a/vibrator/aidl/android/hardware/vibrator/PrimitivePwle.aidl b/vibrator/aidl/android/hardware/vibrator/PrimitivePwle.aidl
new file mode 100644
index 0000000..813c7dc
--- /dev/null
+++ b/vibrator/aidl/android/hardware/vibrator/PrimitivePwle.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.vibrator;
+
+import android.hardware.vibrator.ActivePwle;
+import android.hardware.vibrator.BrakingPwle;
+
+@VintfStability
+union PrimitivePwle {
+    ActivePwle active;
+    BrakingPwle braking;
+}
diff --git a/vibrator/aidl/default/Vibrator.cpp b/vibrator/aidl/default/Vibrator.cpp
index bf61bfe..c6682b3 100644
--- a/vibrator/aidl/default/Vibrator.cpp
+++ b/vibrator/aidl/default/Vibrator.cpp
@@ -26,9 +26,16 @@
 
 static constexpr int32_t kComposeDelayMaxMs = 1000;
 static constexpr int32_t kComposeSizeMax = 256;
+static constexpr int32_t kComposePwleSizeMax = 127;
 
 static constexpr float kResonantFrequency = 150.0;
 static constexpr float kQFactor = 11.0;
+static constexpr int32_t COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS = 16383;
+static constexpr float PWLE_LEVEL_MIN = 0.0;
+static constexpr float PWLE_LEVEL_MAX = 0.98256;
+static constexpr float PWLE_FREQUENCY_RESOLUTION_HZ = 1.0;
+static constexpr float PWLE_FREQUENCY_MIN_HZ = 140.0;
+static constexpr float PWLE_FREQUENCY_MAX_HZ = 160.0;
 
 ndk::ScopedAStatus Vibrator::getCapabilities(int32_t* _aidl_return) {
     LOG(INFO) << "Vibrator reporting capabilities";
@@ -36,7 +43,8 @@
                     IVibrator::CAP_AMPLITUDE_CONTROL | IVibrator::CAP_EXTERNAL_CONTROL |
                     IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL | IVibrator::CAP_COMPOSE_EFFECTS |
                     IVibrator::CAP_ALWAYS_ON_CONTROL | IVibrator::CAP_GET_RESONANT_FREQUENCY |
-                    IVibrator::CAP_GET_Q_FACTOR;
+                    IVibrator::CAP_GET_Q_FACTOR | IVibrator::CAP_FREQUENCY_CONTROL |
+                    IVibrator::CAP_COMPOSE_PWLE_EFFECTS;
     return ndk::ScopedAStatus::ok();
 }
 
@@ -215,6 +223,169 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus Vibrator::getFrequencyResolution(float *freqResolutionHz) {
+    *freqResolutionHz = PWLE_FREQUENCY_RESOLUTION_HZ;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::getFrequencyMinimum(float *freqMinimumHz) {
+    *freqMinimumHz = PWLE_FREQUENCY_MIN_HZ;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::getBandwidthAmplitudeMap(std::vector<float> *_aidl_return) {
+    // A valid array should be of size:
+    //     (PWLE_FREQUENCY_MAX_HZ - PWLE_FREQUENCY_MIN_HZ) / PWLE_FREQUENCY_RESOLUTION_HZ
+    *_aidl_return = {0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.10,
+                     0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.20};
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::getPwlePrimitiveDurationMax(int32_t *durationMs) {
+    *durationMs = COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::getPwleCompositionSizeMax(int32_t *maxSize) {
+    *maxSize = kComposePwleSizeMax;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Vibrator::getSupportedBraking(std::vector<Braking> *supported) {
+    *supported = {
+            Braking::NONE,
+            Braking::CLAB,
+    };
+    return ndk::ScopedAStatus::ok();
+}
+
+void resetPreviousEndAmplitudeEndFrequency(float &prevEndAmplitude, float &prevEndFrequency) {
+    const float reset = -1.0;
+    prevEndAmplitude = reset;
+    prevEndFrequency = reset;
+}
+
+void incrementIndex(int &index) {
+    index += 1;
+}
+
+void constructActiveDefaults(std::ostringstream &pwleBuilder, const int &segmentIdx) {
+    pwleBuilder << ",C" << segmentIdx << ":1";
+    pwleBuilder << ",B" << segmentIdx << ":0";
+    pwleBuilder << ",AR" << segmentIdx << ":0";
+    pwleBuilder << ",V" << segmentIdx << ":0";
+}
+
+void constructActiveSegment(std::ostringstream &pwleBuilder, const int &segmentIdx, int duration,
+                            float amplitude, float frequency) {
+    pwleBuilder << ",T" << segmentIdx << ":" << duration;
+    pwleBuilder << ",L" << segmentIdx << ":" << amplitude;
+    pwleBuilder << ",F" << segmentIdx << ":" << frequency;
+    constructActiveDefaults(pwleBuilder, segmentIdx);
+}
+
+void constructBrakingSegment(std::ostringstream &pwleBuilder, const int &segmentIdx, int duration,
+                             Braking brakingType) {
+    pwleBuilder << ",T" << segmentIdx << ":" << duration;
+    pwleBuilder << ",L" << segmentIdx << ":" << 0;
+    pwleBuilder << ",F" << segmentIdx << ":" << 0;
+    pwleBuilder << ",C" << segmentIdx << ":0";
+    pwleBuilder << ",B" << segmentIdx << ":"
+                << static_cast<std::underlying_type<Braking>::type>(brakingType);
+    pwleBuilder << ",AR" << segmentIdx << ":0";
+    pwleBuilder << ",V" << segmentIdx << ":0";
+}
+
+ndk::ScopedAStatus Vibrator::composePwle(const std::vector<PrimitivePwle> &composite,
+                                         const std::shared_ptr<IVibratorCallback> &callback) {
+    std::ostringstream pwleBuilder;
+    std::string pwleQueue;
+
+    int compositionSizeMax;
+    getPwleCompositionSizeMax(&compositionSizeMax);
+    if (composite.size() <= 0 || composite.size() > compositionSizeMax) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+
+    float prevEndAmplitude;
+    float prevEndFrequency;
+    resetPreviousEndAmplitudeEndFrequency(prevEndAmplitude, prevEndFrequency);
+
+    int segmentIdx = 0;
+    uint32_t totalDuration = 0;
+
+    pwleBuilder << "S:0,WF:4,RP:0,WT:0";
+
+    for (auto &e : composite) {
+        switch (e.getTag()) {
+            case PrimitivePwle::active: {
+                auto active = e.get<PrimitivePwle::active>();
+                if (active.duration < 0 ||
+                    active.duration > COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) {
+                    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+                }
+                if (active.startAmplitude < PWLE_LEVEL_MIN ||
+                    active.startAmplitude > PWLE_LEVEL_MAX ||
+                    active.endAmplitude < PWLE_LEVEL_MIN || active.endAmplitude > PWLE_LEVEL_MAX) {
+                    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+                }
+                if (active.startFrequency < PWLE_FREQUENCY_MIN_HZ ||
+                    active.startFrequency > PWLE_FREQUENCY_MAX_HZ ||
+                    active.endFrequency < PWLE_FREQUENCY_MIN_HZ ||
+                    active.endFrequency > PWLE_FREQUENCY_MAX_HZ) {
+                    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+                }
+
+                if (!((active.startAmplitude == prevEndAmplitude) &&
+                      (active.startFrequency == prevEndFrequency))) {
+                    constructActiveSegment(pwleBuilder, segmentIdx, 0, active.startAmplitude,
+                                           active.startFrequency);
+                    incrementIndex(segmentIdx);
+                }
+
+                constructActiveSegment(pwleBuilder, segmentIdx, active.duration,
+                                       active.endAmplitude, active.endFrequency);
+                incrementIndex(segmentIdx);
+
+                prevEndAmplitude = active.endAmplitude;
+                prevEndFrequency = active.endFrequency;
+                totalDuration += active.duration;
+                break;
+            }
+            case PrimitivePwle::braking: {
+                auto braking = e.get<PrimitivePwle::braking>();
+                if (braking.braking > Braking::CLAB) {
+                    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+                }
+                if (braking.duration > COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) {
+                    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+                }
+
+                constructBrakingSegment(pwleBuilder, segmentIdx, 0, braking.braking);
+                incrementIndex(segmentIdx);
+
+                constructBrakingSegment(pwleBuilder, segmentIdx, braking.duration, braking.braking);
+                incrementIndex(segmentIdx);
+
+                resetPreviousEndAmplitudeEndFrequency(prevEndAmplitude, prevEndFrequency);
+                totalDuration += braking.duration;
+                break;
+            }
+        }
+    }
+
+    std::thread([=] {
+        LOG(INFO) << "Starting composePwle on another thread";
+        usleep(totalDuration * 1000);
+        if (callback != nullptr) {
+            LOG(INFO) << "Notifying compose PWLE complete";
+            callback->onComplete();
+        }
+    }).detach();
+
+    return ndk::ScopedAStatus::ok();
+}
+
 }  // namespace vibrator
 }  // namespace hardware
 }  // namespace android
diff --git a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
index a2af963..4203bf2 100644
--- a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
+++ b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
@@ -46,6 +46,15 @@
     ndk::ScopedAStatus alwaysOnDisable(int32_t id) override;
     ndk::ScopedAStatus getResonantFrequency(float *resonantFreqHz) override;
     ndk::ScopedAStatus getQFactor(float *qFactor) override;
+    ndk::ScopedAStatus getFrequencyResolution(float *freqResolutionHz) override;
+    ndk::ScopedAStatus getFrequencyMinimum(float *freqMinimumHz) override;
+    ndk::ScopedAStatus getBandwidthAmplitudeMap(std::vector<float> *_aidl_return) override;
+    ndk::ScopedAStatus getPwlePrimitiveDurationMax(int32_t *durationMs) override;
+    ndk::ScopedAStatus getPwleCompositionSizeMax(int32_t *maxSize) override;
+    ndk::ScopedAStatus getSupportedBraking(std::vector<Braking>* supported) override;
+    ndk::ScopedAStatus composePwle(const std::vector<PrimitivePwle> &composite,
+                                   const std::shared_ptr<IVibratorCallback> &callback) override;
+
 };
 
 }  // namespace vibrator
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index 2540d0b..a9d1ed5 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -15,7 +15,6 @@
  */
 #include <aidl/Gtest.h>
 #include <aidl/Vintf.h>
-
 #include <android/hardware/vibrator/BnVibratorCallback.h>
 #include <android/hardware/vibrator/IVibrator.h>
 #include <android/hardware/vibrator/IVibratorManager.h>
@@ -29,13 +28,17 @@
 using android::sp;
 using android::String16;
 using android::binder::Status;
+using android::hardware::vibrator::ActivePwle;
 using android::hardware::vibrator::BnVibratorCallback;
+using android::hardware::vibrator::Braking;
+using android::hardware::vibrator::BrakingPwle;
 using android::hardware::vibrator::CompositeEffect;
 using android::hardware::vibrator::CompositePrimitive;
 using android::hardware::vibrator::Effect;
 using android::hardware::vibrator::EffectStrength;
 using android::hardware::vibrator::IVibrator;
 using android::hardware::vibrator::IVibratorManager;
+using android::hardware::vibrator::PrimitivePwle;
 using std::chrono::high_resolution_clock;
 
 const std::vector<Effect> kEffects{android::enum_range<Effect>().begin(),
@@ -44,32 +47,32 @@
                                                    android::enum_range<EffectStrength>().end()};
 
 const std::vector<Effect> kInvalidEffects = {
-        static_cast<Effect>(static_cast<int32_t>(kEffects.front()) - 1),
-        static_cast<Effect>(static_cast<int32_t>(kEffects.back()) + 1),
+    static_cast<Effect>(static_cast<int32_t>(kEffects.front()) - 1),
+    static_cast<Effect>(static_cast<int32_t>(kEffects.back()) + 1),
 };
 
 const std::vector<EffectStrength> kInvalidEffectStrengths = {
-        static_cast<EffectStrength>(static_cast<int8_t>(kEffectStrengths.front()) - 1),
-        static_cast<EffectStrength>(static_cast<int8_t>(kEffectStrengths.back()) + 1),
+    static_cast<EffectStrength>(static_cast<int8_t>(kEffectStrengths.front()) - 1),
+    static_cast<EffectStrength>(static_cast<int8_t>(kEffectStrengths.back()) + 1),
 };
 
 const std::vector<CompositePrimitive> kCompositePrimitives{
-        android::enum_range<CompositePrimitive>().begin(),
-        android::enum_range<CompositePrimitive>().end()};
+    android::enum_range<CompositePrimitive>().begin(),
+    android::enum_range<CompositePrimitive>().end()};
 
 const std::vector<CompositePrimitive> kOptionalPrimitives = {
-        CompositePrimitive::THUD,
-        CompositePrimitive::SPIN,
+    CompositePrimitive::THUD,
+    CompositePrimitive::SPIN,
 };
 
 const std::vector<CompositePrimitive> kInvalidPrimitives = {
-        static_cast<CompositePrimitive>(static_cast<int32_t>(kCompositePrimitives.front()) - 1),
-        static_cast<CompositePrimitive>(static_cast<int32_t>(kCompositePrimitives.back()) + 1),
+    static_cast<CompositePrimitive>(static_cast<int32_t>(kCompositePrimitives.front()) - 1),
+    static_cast<CompositePrimitive>(static_cast<int32_t>(kCompositePrimitives.back()) + 1),
 };
 
 class CompletionCallback : public BnVibratorCallback {
   public:
-    CompletionCallback(const std::function<void()>& callback) : mCallback(callback) {}
+    CompletionCallback(const std::function<void()> &callback) : mCallback(callback) {}
     Status onComplete() override {
         mCallback();
         return Status::ok();
@@ -109,6 +112,89 @@
     int32_t capabilities;
 };
 
+static float getResonantFrequencyHz(sp<IVibrator> vibrator, int32_t capabilities) {
+    float resonantFrequencyHz;
+    Status status = vibrator->getResonantFrequency(&resonantFrequencyHz);
+    if (capabilities & IVibrator::CAP_GET_RESONANT_FREQUENCY) {
+        EXPECT_GT(resonantFrequencyHz, 0);
+        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+    } else {
+        EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+    }
+    return resonantFrequencyHz;
+}
+
+static float getFrequencyResolutionHz(sp<IVibrator> vibrator, int32_t capabilities) {
+    float freqResolutionHz;
+    Status status = vibrator->getFrequencyResolution(&freqResolutionHz);
+    if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
+        EXPECT_GT(freqResolutionHz, 0);
+        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+    } else {
+        EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+    }
+    return freqResolutionHz;
+}
+
+static float getFrequencyMinimumHz(sp<IVibrator> vibrator, int32_t capabilities) {
+    float freqMinimumHz;
+    Status status = vibrator->getFrequencyMinimum(&freqMinimumHz);
+    if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
+        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+
+        float resonantFrequencyHz = getResonantFrequencyHz(vibrator, capabilities);
+
+        EXPECT_GT(freqMinimumHz, 0);
+        EXPECT_LE(freqMinimumHz, resonantFrequencyHz);
+    } else {
+        EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+    }
+    return freqMinimumHz;
+}
+
+static float getFrequencyMaximumHz(sp<IVibrator> vibrator, int32_t capabilities) {
+    std::vector<float> bandwidthAmplitudeMap;
+    Status status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap);
+    if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
+        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+    } else {
+        EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+    }
+
+    float freqMaximumHz =
+        (bandwidthAmplitudeMap.size() * getFrequencyResolutionHz(vibrator, capabilities)) +
+        getFrequencyMinimumHz(vibrator, capabilities);
+    return freqMaximumHz;
+}
+
+static float getAmplitudeMin() {
+    return 0.0;
+}
+
+static float getAmplitudeMax() {
+    return 1.0;
+}
+
+static ActivePwle composeValidActivePwle(sp<IVibrator> vibrator, int32_t capabilities) {
+    float frequencyHz;
+    if (capabilities & IVibrator::CAP_GET_RESONANT_FREQUENCY) {
+        frequencyHz = getResonantFrequencyHz(vibrator, capabilities);
+    } else if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
+        frequencyHz = getFrequencyMinimumHz(vibrator, capabilities);
+    } else {
+        frequencyHz = 150.0;  // default value commonly used
+    }
+
+    ActivePwle active;
+    active.startAmplitude = (getAmplitudeMin() + getAmplitudeMax()) / 2;
+    active.startFrequency = frequencyHz;
+    active.endAmplitude = (getAmplitudeMin() + getAmplitudeMax()) / 2;
+    active.endFrequency = frequencyHz;
+    active.duration = 1000;
+
+    return active;
+}
+
 TEST_P(VibratorAidl, OnThenOffBeforeTimeout) {
     EXPECT_TRUE(vibrator->on(2000, nullptr /*callback*/).isOk());
     sleep(1);
@@ -116,12 +202,13 @@
 }
 
 TEST_P(VibratorAidl, OnWithCallback) {
-    if (!(capabilities & IVibrator::CAP_ON_CALLBACK)) return;
+    if (!(capabilities & IVibrator::CAP_ON_CALLBACK))
+        return;
 
     std::promise<void> completionPromise;
     std::future<void> completionFuture{completionPromise.get_future()};
     sp<CompletionCallback> callback =
-            new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+        new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
     uint32_t durationMs = 250;
     std::chrono::milliseconds timeout{durationMs * 2};
     EXPECT_TRUE(vibrator->on(durationMs, callback).isOk());
@@ -142,7 +229,7 @@
 
     for (Effect effect : kEffects) {
         bool isEffectSupported =
-                std::find(supported.begin(), supported.end(), effect) != supported.end();
+            std::find(supported.begin(), supported.end(), effect) != supported.end();
 
         for (EffectStrength strength : kEffectStrengths) {
             int32_t lengthMs = 0;
@@ -154,27 +241,28 @@
                 usleep(lengthMs * 1000);
             } else {
                 EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION)
-                        << toString(effect) << " " << toString(strength);
+                    << toString(effect) << " " << toString(strength);
             }
         }
     }
 }
 
 TEST_P(VibratorAidl, ValidateEffectWithCallback) {
-    if (!(capabilities & IVibrator::CAP_PERFORM_CALLBACK)) return;
+    if (!(capabilities & IVibrator::CAP_PERFORM_CALLBACK))
+        return;
 
     std::vector<Effect> supported;
     ASSERT_TRUE(vibrator->getSupportedEffects(&supported).isOk());
 
     for (Effect effect : kEffects) {
         bool isEffectSupported =
-                std::find(supported.begin(), supported.end(), effect) != supported.end();
+            std::find(supported.begin(), supported.end(), effect) != supported.end();
 
         for (EffectStrength strength : kEffectStrengths) {
             std::promise<void> completionPromise;
             std::future<void> completionFuture{completionPromise.get_future()};
             sp<CompletionCallback> callback =
-                    new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+                new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
             int lengthMs = 0;
             Status status = vibrator->perform(effect, strength, callback, &lengthMs);
 
@@ -185,7 +273,8 @@
                 EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
             }
 
-            if (!status.isOk()) continue;
+            if (!status.isOk())
+                continue;
 
             std::chrono::milliseconds timeout{lengthMs * 2};
             EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
@@ -194,7 +283,8 @@
 }
 
 TEST_P(VibratorAidl, ValidateEffectWithCallbackNotSupported) {
-    if (capabilities & IVibrator::CAP_PERFORM_CALLBACK) return;
+    if (capabilities & IVibrator::CAP_PERFORM_CALLBACK)
+        return;
 
     for (Effect effect : kEffects) {
         for (EffectStrength strength : kEffectStrengths) {
@@ -212,7 +302,7 @@
             int32_t lengthMs;
             Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
             EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION)
-                    << toString(effect) << " " << toString(strength);
+                << toString(effect) << " " << toString(strength);
         }
     }
     for (Effect effect : kEffects) {
@@ -220,7 +310,7 @@
             int32_t lengthMs;
             Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
             EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION)
-                    << toString(effect) << " " << toString(strength);
+                << toString(effect) << " " << toString(strength);
         }
     }
 }
@@ -261,7 +351,7 @@
 
 TEST_P(VibratorAidl, ExternalAmplitudeControl) {
     const bool supportsExternalAmplitudeControl =
-            (capabilities & IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL) > 0;
+        (capabilities & IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL) > 0;
 
     if (capabilities & IVibrator::CAP_EXTERNAL_CONTROL) {
         EXPECT_TRUE(vibrator->setExternalControl(true).isOk());
@@ -293,10 +383,10 @@
 
         for (auto primitive : kCompositePrimitives) {
             bool isPrimitiveSupported =
-                    std::find(supported.begin(), supported.end(), primitive) != supported.end();
+                std::find(supported.begin(), supported.end(), primitive) != supported.end();
             bool isPrimitiveOptional =
-                    std::find(kOptionalPrimitives.begin(), kOptionalPrimitives.end(), primitive) !=
-                    kOptionalPrimitives.end();
+                std::find(kOptionalPrimitives.begin(), kOptionalPrimitives.end(), primitive) !=
+                kOptionalPrimitives.end();
 
             EXPECT_TRUE(isPrimitiveSupported || isPrimitiveOptional) << toString(primitive);
         }
@@ -310,7 +400,7 @@
 
         for (auto primitive : kCompositePrimitives) {
             bool isPrimitiveSupported =
-                    std::find(supported.begin(), supported.end(), primitive) != supported.end();
+                std::find(supported.begin(), supported.end(), primitive) != supported.end();
             int32_t duration;
 
             Status status = vibrator->getPrimitiveDuration(primitive, &duration);
@@ -366,7 +456,7 @@
 
         for (auto primitive : kCompositePrimitives) {
             bool isPrimitiveSupported =
-                    std::find(supported.begin(), supported.end(), primitive) != supported.end();
+                std::find(supported.begin(), supported.end(), primitive) != supported.end();
 
             if (!isPrimitiveSupported) {
                 unsupported.push_back(primitive);
@@ -376,7 +466,7 @@
         for (auto primitive : unsupported) {
             std::vector<CompositeEffect> composite(1);
 
-            for (auto& effect : composite) {
+            for (auto &effect : composite) {
                 effect.delayMs = 0;
                 effect.primitive = primitive;
                 effect.scale = 1.0f;
@@ -391,7 +481,7 @@
 TEST_P(VibratorAidl, ComposeScaleBoundary) {
     if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
         std::vector<CompositeEffect> composite(1);
-        CompositeEffect& effect = composite[0];
+        CompositeEffect &effect = composite[0];
 
         effect.delayMs = 0;
         effect.primitive = CompositePrimitive::CLICK;
@@ -478,7 +568,7 @@
             std::promise<void> completionPromise;
             std::future<void> completionFuture{completionPromise.get_future()};
             sp<CompletionCallback> callback =
-                    new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+                new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
             CompositeEffect effect;
             std::vector<CompositeEffect> composite;
             int32_t durationMs;
@@ -493,16 +583,15 @@
 
             EXPECT_EQ(Status::EX_NONE,
                       vibrator->getPrimitiveDuration(primitive, &durationMs).exceptionCode())
-                    << toString(primitive);
+                << toString(primitive);
             duration = std::chrono::milliseconds(durationMs);
 
             EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, callback).exceptionCode())
-                    << toString(primitive);
+                << toString(primitive);
             start = high_resolution_clock::now();
 
-            EXPECT_EQ(completionFuture.wait_for(duration + allowedLatency),
-                      std::future_status::ready)
-                    << toString(primitive);
+            EXPECT_EQ(completionFuture.wait_for(duration + allowedLatency), std::future_status::ready)
+                << toString(primitive);
             end = high_resolution_clock::now();
 
             elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
@@ -519,17 +608,17 @@
 
         for (Effect effect : kEffects) {
             bool isEffectSupported =
-                    std::find(supported.begin(), supported.end(), effect) != supported.end();
+                std::find(supported.begin(), supported.end(), effect) != supported.end();
 
             for (EffectStrength strength : kEffectStrengths) {
                 Status status = vibrator->alwaysOnEnable(0, effect, strength);
 
                 if (isEffectSupported) {
                     EXPECT_EQ(Status::EX_NONE, status.exceptionCode())
-                            << toString(effect) << " " << toString(strength);
+                        << toString(effect) << " " << toString(strength);
                 } else {
                     EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode())
-                            << toString(effect) << " " << toString(strength);
+                        << toString(effect) << " " << toString(strength);
                 }
             }
         }
@@ -539,27 +628,253 @@
 }
 
 TEST_P(VibratorAidl, GetResonantFrequency) {
-    float resonantFrequency;
-    Status status = vibrator->getResonantFrequency(&resonantFrequency);
-    if (capabilities & IVibrator::CAP_GET_RESONANT_FREQUENCY) {
-        ASSERT_NE(resonantFrequency, 0);
-        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
-    } else {
-        EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
-    }
+    getResonantFrequencyHz(vibrator, capabilities);
 }
 
 TEST_P(VibratorAidl, GetQFactor) {
     float qFactor;
     Status status = vibrator->getQFactor(&qFactor);
     if (capabilities & IVibrator::CAP_GET_Q_FACTOR) {
-        ASSERT_NE(qFactor, 0);
+        ASSERT_GT(qFactor, 0);
         EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
     } else {
         EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
     }
 }
 
+TEST_P(VibratorAidl, GetFrequencyResolution) {
+    getFrequencyResolutionHz(vibrator, capabilities);
+}
+
+TEST_P(VibratorAidl, GetFrequencyMinimum) {
+    getFrequencyMinimumHz(vibrator, capabilities);
+}
+
+TEST_P(VibratorAidl, GetBandwidthAmplitudeMap) {
+    std::vector<float> bandwidthAmplitudeMap;
+    Status status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap);
+    if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
+        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+        ASSERT_FALSE(bandwidthAmplitudeMap.empty());
+
+        int minMapSize = (getResonantFrequencyHz(vibrator, capabilities) -
+                          getFrequencyMinimumHz(vibrator, capabilities)) /
+                         getFrequencyResolutionHz(vibrator, capabilities);
+        ASSERT_GT(bandwidthAmplitudeMap.size(), minMapSize);
+
+        for (float e : bandwidthAmplitudeMap) {
+            ASSERT_GE(e, 0.0);
+            ASSERT_LE(e, 1.0);
+        }
+    } else {
+        EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+    }
+}
+
+TEST_P(VibratorAidl, GetPwlePrimitiveDurationMax) {
+    int32_t durationMs;
+    Status status = vibrator->getPwlePrimitiveDurationMax(&durationMs);
+    if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
+        ASSERT_NE(durationMs, 0);
+        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+    } else {
+        EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+    }
+}
+
+TEST_P(VibratorAidl, GetPwleCompositionSizeMax) {
+    int32_t maxSize;
+    Status status = vibrator->getPwleCompositionSizeMax(&maxSize);
+    if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
+        ASSERT_NE(maxSize, 0);
+        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+    } else {
+        EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+    }
+}
+
+TEST_P(VibratorAidl, GetSupportedBraking) {
+    std::vector<Braking> supported;
+    Status status = vibrator->getSupportedBraking(&supported);
+    if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
+        bool isDefaultNoneSupported =
+            std::find(supported.begin(), supported.end(), Braking::NONE) != supported.end();
+        ASSERT_TRUE(isDefaultNoneSupported);
+        EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
+    } else {
+        EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+    }
+}
+
+TEST_P(VibratorAidl, ComposeValidPwle) {
+    if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
+        ActivePwle active = composeValidActivePwle(vibrator, capabilities);
+
+        std::vector<Braking> supported;
+        ASSERT_TRUE(vibrator->getSupportedBraking(&supported).isOk());
+        bool isClabSupported =
+            std::find(supported.begin(), supported.end(), Braking::CLAB) != supported.end();
+        BrakingPwle braking;
+        braking.braking = isClabSupported ? Braking::CLAB : Braking::NONE;
+        braking.duration = 100;
+
+        std::vector<PrimitivePwle> pwleQueue;
+        PrimitivePwle pwle;
+        pwle = active;
+        pwleQueue.emplace_back(std::move(pwle));
+        pwle = braking;
+        pwleQueue.emplace_back(std::move(pwle));
+        pwle = active;
+        pwleQueue.emplace_back(std::move(pwle));
+
+        EXPECT_EQ(Status::EX_NONE, vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
+        vibrator->off();
+    }
+}
+
+TEST_P(VibratorAidl, ComposeValidPwleWithCallback) {
+    if (!((capabilities & IVibrator::CAP_ON_CALLBACK) &&
+          (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS)))
+        return;
+
+    std::promise<void> completionPromise;
+    std::future<void> completionFuture{completionPromise.get_future()};
+    sp<CompletionCallback> callback =
+        new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+    uint32_t durationMs = 2100;  // Sum of 2 active and 1 braking below
+    std::chrono::milliseconds timeout{durationMs * 2};
+
+    ActivePwle active = composeValidActivePwle(vibrator, capabilities);
+
+    std::vector<Braking> supported;
+    ASSERT_TRUE(vibrator->getSupportedBraking(&supported).isOk());
+    bool isClabSupported =
+        std::find(supported.begin(), supported.end(), Braking::CLAB) != supported.end();
+    BrakingPwle braking;
+    braking.braking = isClabSupported ? Braking::CLAB : Braking::NONE;
+    braking.duration = 100;
+
+    std::vector<PrimitivePwle> pwleQueue;
+    PrimitivePwle pwle;
+    pwle = active;
+    pwleQueue.emplace_back(std::move(pwle));
+    pwle = braking;
+    pwleQueue.emplace_back(std::move(pwle));
+    pwle = active;
+    pwleQueue.emplace_back(std::move(pwle));
+
+    EXPECT_TRUE(vibrator->composePwle(pwleQueue, callback).isOk());
+    EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
+    EXPECT_TRUE(vibrator->off().isOk());
+}
+
+TEST_P(VibratorAidl, ComposePwleSegmentBoundary) {
+    if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
+        std::vector<PrimitivePwle> pwleQueue;
+        // test empty queue
+        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
+                  vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
+        vibrator->off();
+
+        ActivePwle active = composeValidActivePwle(vibrator, capabilities);
+
+        PrimitivePwle pwle;
+        pwle = active;
+        int segmentCountMax;
+        vibrator->getPwleCompositionSizeMax(&segmentCountMax);
+
+        // Create PWLE queue with more segments than allowed
+        for (int i = 0; i < segmentCountMax + 10; i++) {
+            pwleQueue.emplace_back(std::move(pwle));
+        }
+
+        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
+                  vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
+        vibrator->off();
+    }
+}
+
+TEST_P(VibratorAidl, ComposePwleAmplitudeParameterBoundary) {
+    if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
+        ActivePwle active = composeValidActivePwle(vibrator, capabilities);
+        active.startAmplitude = getAmplitudeMax() + 1.0;  // Amplitude greater than allowed
+        active.endAmplitude = getAmplitudeMax() + 1.0;    // Amplitude greater than allowed
+
+        std::vector<PrimitivePwle> pwleQueueGreater;
+        PrimitivePwle pwle;
+        pwle = active;
+        pwleQueueGreater.emplace_back(std::move(pwle));
+
+        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
+                  vibrator->composePwle(pwleQueueGreater, nullptr).exceptionCode());
+        vibrator->off();
+
+        active.startAmplitude = getAmplitudeMin() - 1.0;  // Amplitude less than allowed
+        active.endAmplitude = getAmplitudeMin() - 1.0;    // Amplitude less than allowed
+
+        std::vector<PrimitivePwle> pwleQueueLess;
+        pwle = active;
+        pwleQueueLess.emplace_back(std::move(pwle));
+
+        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
+                  vibrator->composePwle(pwleQueueLess, nullptr).exceptionCode());
+        vibrator->off();
+    }
+}
+
+TEST_P(VibratorAidl, ComposePwleFrequencyParameterBoundary) {
+    if ((capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) &&
+        (capabilities & IVibrator::CAP_FREQUENCY_CONTROL)) {
+        float freqMinimumHz = getFrequencyMinimumHz(vibrator, capabilities);
+        float freqMaximumHz = getFrequencyMaximumHz(vibrator, capabilities);
+        float freqResolutionHz = getFrequencyResolutionHz(vibrator, capabilities);
+
+        ActivePwle active = composeValidActivePwle(vibrator, capabilities);
+        active.startFrequency =
+            freqMaximumHz + freqResolutionHz;                    // Frequency greater than allowed
+        active.endFrequency = freqMaximumHz + freqResolutionHz;  // Frequency greater than allowed
+
+        std::vector<PrimitivePwle> pwleQueueGreater;
+        PrimitivePwle pwle;
+        pwle = active;
+        pwleQueueGreater.emplace_back(std::move(pwle));
+
+        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
+                  vibrator->composePwle(pwleQueueGreater, nullptr).exceptionCode());
+        vibrator->off();
+
+        active.startFrequency = freqMinimumHz - freqResolutionHz;  // Frequency less than allowed
+        active.endFrequency = freqMinimumHz - freqResolutionHz;    // Frequency less than allowed
+
+        std::vector<PrimitivePwle> pwleQueueLess;
+        pwle = active;
+        pwleQueueLess.emplace_back(std::move(pwle));
+
+        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
+                  vibrator->composePwle(pwleQueueLess, nullptr).exceptionCode());
+        vibrator->off();
+    }
+}
+
+TEST_P(VibratorAidl, ComposePwleSegmentDurationBoundary) {
+    if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
+        ActivePwle active = composeValidActivePwle(vibrator, capabilities);
+
+        int segmentDurationMaxMs;
+        vibrator->getPwlePrimitiveDurationMax(&segmentDurationMaxMs);
+        active.duration = segmentDurationMaxMs + 10;  // Segment duration greater than allowed
+
+        std::vector<PrimitivePwle> pwleQueue;
+        PrimitivePwle pwle;
+        pwle = active;
+        pwleQueue.emplace_back(std::move(pwle));
+
+        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
+                  vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
+        vibrator->off();
+    }
+}
+
 std::vector<std::tuple<int32_t, int32_t>> GenerateVibratorMapping() {
     std::vector<std::tuple<int32_t, int32_t>> tuples;
     auto managerAidlNames = android::getAidlHalInstanceNames(IVibratorManager::descriptor);
@@ -569,7 +884,7 @@
         auto managerName = String16(managerAidlNames[i].c_str());
         auto vibratorManager = android::waitForDeclaredService<IVibratorManager>(managerName);
         if (vibratorManager->getVibratorIds(&vibratorIds).isOk()) {
-            for (auto& vibratorId : vibratorIds) {
+            for (auto &vibratorId : vibratorIds) {
                 tuples.push_back(std::make_tuple(i, vibratorId));
             }
         }
@@ -583,8 +898,8 @@
     return tuples;
 }
 
-std::string PrintGeneratedTest(const testing::TestParamInfo<VibratorAidl::ParamType>& info) {
-    const auto& [managerIdx, vibratorId] = info.param;
+std::string PrintGeneratedTest(const testing::TestParamInfo<VibratorAidl::ParamType> &info) {
+    const auto &[managerIdx, vibratorId] = info.param;
     if (managerIdx < 0) {
         return std::string("TOP_LEVEL_VIBRATOR_") + std::to_string(vibratorId);
     }
@@ -596,7 +911,7 @@
 INSTANTIATE_TEST_SUITE_P(Vibrator, VibratorAidl, testing::ValuesIn(GenerateVibratorMapping()),
                          PrintGeneratedTest);
 
-int main(int argc, char** argv) {
+int main(int argc, char **argv) {
     ::testing::InitGoogleTest(&argc, argv);
     ProcessState::self()->setThreadPoolMaxThreadCount(1);
     ProcessState::self()->startThreadPool();
diff --git a/wifi/1.5/default/hidl_struct_util.cpp b/wifi/1.5/default/hidl_struct_util.cpp
index 125a50f..338a8f1 100644
--- a/wifi/1.5/default/hidl_struct_util.cpp
+++ b/wifi/1.5/default/hidl_struct_util.cpp
@@ -954,27 +954,29 @@
 
 bool convertLegacyLinkLayerRadioStatsToHidl(
     const legacy_hal::LinkLayerRadioStats& legacy_radio_stat,
-    V1_3::StaLinkLayerRadioStats* hidl_radio_stat) {
+    V1_5::StaLinkLayerRadioStats* hidl_radio_stat) {
     if (!hidl_radio_stat) {
         return false;
     }
     *hidl_radio_stat = {};
 
-    hidl_radio_stat->V1_0.onTimeInMs = legacy_radio_stat.stats.on_time;
-    hidl_radio_stat->V1_0.txTimeInMs = legacy_radio_stat.stats.tx_time;
-    hidl_radio_stat->V1_0.rxTimeInMs = legacy_radio_stat.stats.rx_time;
-    hidl_radio_stat->V1_0.onTimeInMsForScan =
+    hidl_radio_stat->radioId = legacy_radio_stat.stats.radio;
+    hidl_radio_stat->V1_3.V1_0.onTimeInMs = legacy_radio_stat.stats.on_time;
+    hidl_radio_stat->V1_3.V1_0.txTimeInMs = legacy_radio_stat.stats.tx_time;
+    hidl_radio_stat->V1_3.V1_0.rxTimeInMs = legacy_radio_stat.stats.rx_time;
+    hidl_radio_stat->V1_3.V1_0.onTimeInMsForScan =
         legacy_radio_stat.stats.on_time_scan;
-    hidl_radio_stat->V1_0.txTimeInMsPerLevel =
+    hidl_radio_stat->V1_3.V1_0.txTimeInMsPerLevel =
         legacy_radio_stat.tx_time_per_levels;
-    hidl_radio_stat->onTimeInMsForNanScan = legacy_radio_stat.stats.on_time_nbd;
-    hidl_radio_stat->onTimeInMsForBgScan =
+    hidl_radio_stat->V1_3.onTimeInMsForNanScan =
+        legacy_radio_stat.stats.on_time_nbd;
+    hidl_radio_stat->V1_3.onTimeInMsForBgScan =
         legacy_radio_stat.stats.on_time_gscan;
-    hidl_radio_stat->onTimeInMsForRoamScan =
+    hidl_radio_stat->V1_3.onTimeInMsForRoamScan =
         legacy_radio_stat.stats.on_time_roam_scan;
-    hidl_radio_stat->onTimeInMsForPnoScan =
+    hidl_radio_stat->V1_3.onTimeInMsForPnoScan =
         legacy_radio_stat.stats.on_time_pno_scan;
-    hidl_radio_stat->onTimeInMsForHs20Scan =
+    hidl_radio_stat->V1_3.onTimeInMsForHs20Scan =
         legacy_radio_stat.stats.on_time_hs20;
 
     std::vector<V1_3::WifiChannelStats> hidl_channel_stats;
@@ -996,7 +998,7 @@
         hidl_channel_stats.push_back(hidl_channel_stat);
     }
 
-    hidl_radio_stat->channelStats = hidl_channel_stats;
+    hidl_radio_stat->V1_3.channelStats = hidl_channel_stats;
 
     return true;
 }
@@ -1089,9 +1091,9 @@
     }
     hidl_stats->iface.peers = hidl_peers_info_stats;
     // radio legacy_stats conversion.
-    std::vector<V1_3::StaLinkLayerRadioStats> hidl_radios_stats;
+    std::vector<V1_5::StaLinkLayerRadioStats> hidl_radios_stats;
     for (const auto& legacy_radio_stats : legacy_stats.radios) {
-        V1_3::StaLinkLayerRadioStats hidl_radio_stats;
+        V1_5::StaLinkLayerRadioStats hidl_radio_stats;
         if (!convertLegacyLinkLayerRadioStatsToHidl(legacy_radio_stats,
                                                     &hidl_radio_stats)) {
             return false;
diff --git a/wifi/1.5/default/tests/hidl_struct_util_unit_tests.cpp b/wifi/1.5/default/tests/hidl_struct_util_unit_tests.cpp
index e70d7ba..4b4ebd6 100644
--- a/wifi/1.5/default/tests/hidl_struct_util_unit_tests.cpp
+++ b/wifi/1.5/default/tests/hidl_struct_util_unit_tests.cpp
@@ -180,6 +180,7 @@
     legacy_stats.iface.num_peers = 1;
 
     for (auto& radio : legacy_stats.radios) {
+        radio.stats.radio = rand();
         radio.stats.on_time = rand();
         radio.stats.tx_time = rand();
         radio.stats.rx_time = rand();
@@ -314,48 +315,53 @@
 
     EXPECT_EQ(legacy_stats.radios.size(), converted.radios.size());
     for (size_t i = 0; i < legacy_stats.radios.size(); i++) {
+        EXPECT_EQ(legacy_stats.radios[i].stats.radio,
+                  converted.radios[i].radioId);
         EXPECT_EQ(legacy_stats.radios[i].stats.on_time,
-                  converted.radios[i].V1_0.onTimeInMs);
+                  converted.radios[i].V1_3.V1_0.onTimeInMs);
         EXPECT_EQ(legacy_stats.radios[i].stats.tx_time,
-                  converted.radios[i].V1_0.txTimeInMs);
+                  converted.radios[i].V1_3.V1_0.txTimeInMs);
         EXPECT_EQ(legacy_stats.radios[i].stats.rx_time,
-                  converted.radios[i].V1_0.rxTimeInMs);
+                  converted.radios[i].V1_3.V1_0.rxTimeInMs);
         EXPECT_EQ(legacy_stats.radios[i].stats.on_time_scan,
-                  converted.radios[i].V1_0.onTimeInMsForScan);
+                  converted.radios[i].V1_3.V1_0.onTimeInMsForScan);
         EXPECT_EQ(legacy_stats.radios[i].tx_time_per_levels.size(),
-                  converted.radios[i].V1_0.txTimeInMsPerLevel.size());
+                  converted.radios[i].V1_3.V1_0.txTimeInMsPerLevel.size());
         for (size_t j = 0; j < legacy_stats.radios[i].tx_time_per_levels.size();
              j++) {
             EXPECT_EQ(legacy_stats.radios[i].tx_time_per_levels[j],
-                      converted.radios[i].V1_0.txTimeInMsPerLevel[j]);
+                      converted.radios[i].V1_3.V1_0.txTimeInMsPerLevel[j]);
         }
         EXPECT_EQ(legacy_stats.radios[i].stats.on_time_nbd,
-                  converted.radios[i].onTimeInMsForNanScan);
+                  converted.radios[i].V1_3.onTimeInMsForNanScan);
         EXPECT_EQ(legacy_stats.radios[i].stats.on_time_gscan,
-                  converted.radios[i].onTimeInMsForBgScan);
+                  converted.radios[i].V1_3.onTimeInMsForBgScan);
         EXPECT_EQ(legacy_stats.radios[i].stats.on_time_roam_scan,
-                  converted.radios[i].onTimeInMsForRoamScan);
+                  converted.radios[i].V1_3.onTimeInMsForRoamScan);
         EXPECT_EQ(legacy_stats.radios[i].stats.on_time_pno_scan,
-                  converted.radios[i].onTimeInMsForPnoScan);
+                  converted.radios[i].V1_3.onTimeInMsForPnoScan);
         EXPECT_EQ(legacy_stats.radios[i].stats.on_time_hs20,
-                  converted.radios[i].onTimeInMsForHs20Scan);
+                  converted.radios[i].V1_3.onTimeInMsForHs20Scan);
         EXPECT_EQ(legacy_stats.radios[i].channel_stats.size(),
-                  converted.radios[i].channelStats.size());
+                  converted.radios[i].V1_3.channelStats.size());
         for (size_t k = 0; k < legacy_stats.radios[i].channel_stats.size();
              k++) {
             auto& legacy_channel_st = legacy_stats.radios[i].channel_stats[k];
             EXPECT_EQ(WifiChannelWidthInMhz::WIDTH_20,
-                      converted.radios[i].channelStats[k].channel.width);
-            EXPECT_EQ(WifiChannelInMhz(legacy_channel_st.channel.center_freq),
-                      converted.radios[i].channelStats[k].channel.centerFreq);
-            EXPECT_EQ(WifiChannelInMhz(legacy_channel_st.channel.center_freq0),
-                      converted.radios[i].channelStats[k].channel.centerFreq0);
-            EXPECT_EQ(WifiChannelInMhz(legacy_channel_st.channel.center_freq1),
-                      converted.radios[i].channelStats[k].channel.centerFreq1);
+                      converted.radios[i].V1_3.channelStats[k].channel.width);
+            EXPECT_EQ(
+                WifiChannelInMhz(legacy_channel_st.channel.center_freq),
+                converted.radios[i].V1_3.channelStats[k].channel.centerFreq);
+            EXPECT_EQ(
+                WifiChannelInMhz(legacy_channel_st.channel.center_freq0),
+                converted.radios[i].V1_3.channelStats[k].channel.centerFreq0);
+            EXPECT_EQ(
+                WifiChannelInMhz(legacy_channel_st.channel.center_freq1),
+                converted.radios[i].V1_3.channelStats[k].channel.centerFreq1);
             EXPECT_EQ(legacy_channel_st.cca_busy_time,
-                      converted.radios[i].channelStats[k].ccaBusyTimeInMs);
+                      converted.radios[i].V1_3.channelStats[k].ccaBusyTimeInMs);
             EXPECT_EQ(legacy_channel_st.on_time,
-                      converted.radios[i].channelStats[k].onTimeInMs);
+                      converted.radios[i].V1_3.channelStats[k].onTimeInMs);
         }
     }
 
diff --git a/wifi/1.5/types.hal b/wifi/1.5/types.hal
index 0543004..3c19791 100644
--- a/wifi/1.5/types.hal
+++ b/wifi/1.5/types.hal
@@ -253,6 +253,21 @@
     vec<StaPeerInfo> peers;
 };
 
+struct StaLinkLayerRadioStats {
+    /**
+     * Baseline information as defined in HAL 1.3.
+     */
+    @1.3::StaLinkLayerRadioStats V1_3;
+
+    /**
+     * Radio ID: An implementation specific value identifying the radio interface for which the
+     * stats are produced. Framework must not interpret this value. It must use this value for
+     * persistently identifying the statistics between calls,
+     * e.g. if the HAL provides them in different order.
+     */
+    int32_t radioId;
+};
+
 /**
  * Link layer stats retrieved via |getLinkLayerStats|.
  */