Merge tag 'android-security-11.0.0_r49' into int/11/fp3

Android security 11.0.0 release 49

* tag 'android-security-11.0.0_r49':
  audio HAL - fix UAFs
  [RESTRICT AUTOMERGE] Fix CryptoPlugin use after free vulnerability.
  Fix potential decrypt destPtr overflow.
  Fix potential decrypt src pointer overflow.

Change-Id: Idb9fef5844c34e140a9a8b5761e053fa8d626dd2
diff --git a/audio/common/all-versions/default/service/Android.bp b/audio/common/all-versions/default/service/Android.bp
index 3e8b715..e5d4770 100644
--- a/audio/common/all-versions/default/service/Android.bp
+++ b/audio/common/all-versions/default/service/Android.bp
@@ -20,11 +20,19 @@
     shared_libs: [
         "libcutils",
         "libbinder",
+	"libhwbinder",
         "libhidlbase",
         "liblog",
         "libutils",
         "libhardware",
     ],
+    arch : {
+        arm : {
+	    cflags: [
+                "-DARCH_ARM_32",
+	    ]
+	}
+    },
 }
 
 // Legacy service name, use android.hardware.audio.service instead
diff --git a/audio/common/all-versions/default/service/android.hardware.audio.service.rc b/audio/common/all-versions/default/service/android.hardware.audio.service.rc
index f7e1e24..45fef9a 100644
--- a/audio/common/all-versions/default/service/android.hardware.audio.service.rc
+++ b/audio/common/all-versions/default/service/android.hardware.audio.service.rc
@@ -2,7 +2,7 @@
     class hal
     user audioserver
     # media gid needed for /dev/fm (radio) and for /data/misc/media (tee)
-    group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct wakelock
+    group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct wakelock context_hub
     capabilities BLOCK_SUSPEND
     ioprio rt 4
     task_profiles ProcessCapacityHigh HighPerformance
diff --git a/audio/common/all-versions/default/service/service.cpp b/audio/common/all-versions/default/service/service.cpp
index 147d062..2801769 100644
--- a/audio/common/all-versions/default/service/service.cpp
+++ b/audio/common/all-versions/default/service/service.cpp
@@ -30,6 +30,18 @@
 
 using InterfacesList = std::vector<std::string>;
 
+#ifdef ARCH_ARM_32
+//default h/w binder memsize is 1 MB
+#define DEFAULT_HW_BINDER_MEM_SIZE_KB 1024
+
+size_t getHWBinderMmapSize(){
+    int32_t value = DEFAULT_HW_BINDER_MEM_SIZE_KB;
+    value = property_get_int32("persist.vendor.audio.hw.binder.size_kbyte", value);
+    ALOGD("Init hw binder with mem  size = %d  ", value);
+    return 1024 * value;
+}
+#endif
+
 /** Try to register the provided factories in the provided order.
  *  If any registers successfully, do not register any other and return true.
  *  If all fail, return false.
@@ -45,6 +57,9 @@
 }
 
 int main(int /* argc */, char* /* argv */ []) {
+#ifdef ARCH_ARM_32
+    android::hardware::ProcessState::initWithMmapSize(getHWBinderMmapSize());
+#endif
     ::android::ProcessState::initWithDriver("/dev/vndbinder");
     // start a threadpool for vndbinder interactions
     ::android::ProcessState::self()->startThreadPool();
diff --git a/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp b/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp
index 0bff9df..f27f266 100644
--- a/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp
+++ b/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp
@@ -34,11 +34,19 @@
         authsecret = IAuthSecret::getService(GetParam());
         ASSERT_NE(authsecret, nullptr);
 
+        // Notify LSS to generate PIN code '1234' and corresponding secret.
+        (void)system("cmd lock_settings set-pin 1234");
+
         // All tests must enroll the correct secret first as this cannot be changed
         // without a factory reset and the order of tests could change.
         authsecret->primaryUserCredential(CORRECT_SECRET);
     }
 
+    static void TearDownTestSuite() {
+        // clean up PIN code after testing
+        (void)system("cmd lock_settings clear --old 1234");
+    }
+
     sp<IAuthSecret> authsecret;
     hidl_vec<uint8_t> CORRECT_SECRET{61, 93, 124, 240, 5, 0, 7, 201, 9, 129, 11, 12, 0, 14, 0, 16};
     hidl_vec<uint8_t> WRONG_SECRET{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
diff --git a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
index 8b68fd6..f1c8f9f 100644
--- a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
+++ b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
@@ -72,6 +72,8 @@
 using ::android::hardware::automotive::evs::V1_0::DisplayDesc;
 using ::android::hardware::automotive::evs::V1_0::DisplayState;
 using ::android::hardware::graphics::common::V1_0::PixelFormat;
+using ::android::frameworks::automotive::display::V1_0::HwDisplayConfig;
+using ::android::frameworks::automotive::display::V1_0::HwDisplayState;
 using IEvsCamera_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsCamera;
 using IEvsCamera_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsCamera;
 using IEvsDisplay_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsDisplay;
@@ -303,11 +305,22 @@
             const auto id = 0xFFFFFFFF; // meaningless id
             hidl_vec<uint8_t> values;
             auto err = pCam->setExtendedInfo_1_1(id, values);
-            ASSERT_NE(EvsResult::INVALID_ARG, err);
+            if (isLogicalCam) {
+                // Logical camera device does not support setExtendedInfo
+                // method.
+                ASSERT_EQ(EvsResult::INVALID_ARG, err);
+            } else {
+                ASSERT_NE(EvsResult::INVALID_ARG, err);
+            }
 
-            pCam->getExtendedInfo_1_1(id, [](const auto& result, const auto& data) {
-                ASSERT_NE(EvsResult::INVALID_ARG, result);
-                ASSERT_EQ(0, data.size());
+
+            pCam->getExtendedInfo_1_1(id, [&isLogicalCam](const auto& result, const auto& data) {
+                if (isLogicalCam) {
+                    ASSERT_EQ(EvsResult::INVALID_ARG, result);
+                } else {
+                    ASSERT_NE(EvsResult::INVALID_ARG, result);
+                    ASSERT_EQ(0, data.size());
+                }
             });
 
             // Explicitly close the camera so resources are released right away
@@ -605,7 +618,10 @@
     LOG(INFO) << "Display " << targetDisplayId << " is alreay in use.";
 
     // Get the display descriptor
-    pDisplay->getDisplayInfo_1_1([](const auto& config, const auto& state) {
+    pDisplay->getDisplayInfo_1_1([](const HwDisplayConfig& config, const HwDisplayState& state) {
+        ASSERT_GT(config.size(), 0);
+        ASSERT_GT(state.size(), 0);
+
         android::DisplayConfig* pConfig = (android::DisplayConfig*)config.data();
         const auto width = pConfig->resolution.getWidth();
         const auto height = pConfig->resolution.getHeight();
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index d9ac239..590adc5 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -108,6 +108,9 @@
     srcs: [
         "impl/vhal_v2_0/EmulatedUserHal.cpp",
     ],
+    whole_static_libs: [
+        "android.hardware.automotive.vehicle@2.0-user-hal-helper-lib",
+    ],
 }
 
 // Vehicle HAL Server reference impl lib
@@ -134,7 +137,6 @@
     local_include_dirs: ["common/include/vhal_v2_0"],
     export_include_dirs: ["impl"],
     srcs: [
-        "impl/vhal_v2_0/EmulatedUserHal.cpp",
         "impl/vhal_v2_0/GeneratorHub.cpp",
         "impl/vhal_v2_0/JsonFakeValueGenerator.cpp",
         "impl/vhal_v2_0/LinearFakeValueGenerator.cpp",
@@ -143,6 +145,7 @@
     ],
     whole_static_libs: [
         "android.hardware.automotive.vehicle@2.0-server-common-lib",
+        "android.hardware.automotive.vehicle@2.0-user-hal-helper-lib",
     ],
     static_libs: [
         "android.hardware.automotive.vehicle@2.0-libproto-native",
diff --git a/automotive/vehicle/2.0/default/VehicleService.cpp b/automotive/vehicle/2.0/default/VehicleService.cpp
index 47133fd..cf1e4ba 100644
--- a/automotive/vehicle/2.0/default/VehicleService.cpp
+++ b/automotive/vehicle/2.0/default/VehicleService.cpp
@@ -22,7 +22,6 @@
 
 #include <android/binder_process.h>
 #include <utils/Looper.h>
-#include <vhal_v2_0/EmulatedUserHal.h>
 #include <vhal_v2_0/EmulatedVehicleConnector.h>
 #include <vhal_v2_0/EmulatedVehicleHal.h>
 #include <vhal_v2_0/VehicleHalManager.h>
@@ -34,9 +33,8 @@
 
 int main(int /* argc */, char* /* argv */ []) {
     auto store = std::make_unique<VehiclePropertyStore>();
-    auto connector = impl::makeEmulatedPassthroughConnector();
-    auto userHal = connector->getEmulatedUserHal();
-    auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get(), connector.get(), userHal);
+    auto connector = std::make_unique<impl::EmulatedVehicleConnector>();
+    auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get(), connector.get());
     auto emulator = std::make_unique<impl::VehicleEmulator>(hal.get());
     auto service = std::make_unique<VehicleHalManager>(hal.get());
     connector->setValuePool(hal->getValuePool());
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
index b09e9bf..dc5d3d3 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
@@ -78,6 +78,7 @@
         } else {
             ALOGW("Requested config for undefined property: 0x%x", prop);
             _hidl_cb(StatusCode::INVALID_ARG, hidl_vec<VehiclePropConfig>());
+            return Void();
         }
     }
 
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index 16c33b9..dec2d8c 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -266,6 +266,20 @@
          .initialValue = {.stringValue = "Toy Vehicle"}},
         {.config =
                  {
+                         .prop = toInt(VehicleProperty::INFO_MODEL),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::STATIC,
+                 },
+         .initialValue = {.stringValue = "Speedy Model"}},
+        {.config =
+                 {
+                         .prop = toInt(VehicleProperty::INFO_MODEL_YEAR),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::STATIC,
+                 },
+         .initialValue = {.int32Values = {2020}}},
+        {.config =
+                 {
                          .prop = toInt(VehicleProperty::INFO_EXTERIOR_DIMENSIONS),
                          .access = VehiclePropertyAccess::READ,
                          .changeMode = VehiclePropertyChangeMode::STATIC,
@@ -403,7 +417,7 @@
                          .minSampleRate = 1.0f,
                          .maxSampleRate = 2.0f,
                  },
-         .initialValue = {.floatValues = {100.0f}}},  // units in meters
+         .initialValue = {.floatValues = {50000.0f}}},  // units in meters
 
         {.config =
                  {
@@ -674,6 +688,12 @@
                          .prop = toInt(VehicleProperty::GEAR_SELECTION),
                          .access = VehiclePropertyAccess::READ,
                          .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                         .configArray = {(int)VehicleGear::GEAR_PARK,
+                                         (int)VehicleGear::GEAR_NEUTRAL,
+                                         (int)VehicleGear::GEAR_REVERSE,
+                                         (int)VehicleGear::GEAR_DRIVE, (int)VehicleGear::GEAR_1,
+                                         (int)VehicleGear::GEAR_2, (int)VehicleGear::GEAR_3,
+                                         (int)VehicleGear::GEAR_4, (int)VehicleGear::GEAR_5},
                  },
          .initialValue = {.int32Values = {toInt(VehicleGear::GEAR_PARK)}}},
 
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp
index ea38cb3..3bdf5a8 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp
@@ -15,10 +15,12 @@
  */
 #define LOG_TAG "EmulatedUserHal"
 
+#include "EmulatedUserHal.h"
+
 #include <cutils/log.h>
 #include <utils/SystemClock.h>
 
-#include "EmulatedUserHal.h"
+#include "UserHalHelper.h"
 
 namespace android {
 namespace hardware {
@@ -28,12 +30,35 @@
 
 namespace impl {
 
-constexpr int INITIAL_USER_INFO = static_cast<int>(VehicleProperty::INITIAL_USER_INFO);
-constexpr int SWITCH_USER = static_cast<int>(VehicleProperty::SWITCH_USER);
-constexpr int CREATE_USER = static_cast<int>(VehicleProperty::CREATE_USER);
-constexpr int REMOVE_USER = static_cast<int>(VehicleProperty::REMOVE_USER);
-constexpr int USER_IDENTIFICATION_ASSOCIATION =
-        static_cast<int>(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION);
+namespace {
+
+using android::base::Error;
+using android::base::Result;
+
+constexpr int32_t INITIAL_USER_INFO = static_cast<int32_t>(VehicleProperty::INITIAL_USER_INFO);
+constexpr int32_t SWITCH_USER = static_cast<int32_t>(VehicleProperty::SWITCH_USER);
+constexpr int32_t CREATE_USER = static_cast<int32_t>(VehicleProperty::CREATE_USER);
+constexpr int32_t REMOVE_USER = static_cast<int32_t>(VehicleProperty::REMOVE_USER);
+constexpr int32_t USER_IDENTIFICATION_ASSOCIATION =
+        static_cast<int32_t>(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION);
+
+Result<int32_t> getRequestId(const VehiclePropValue& value) {
+    if (value.value.int32Values.size() < 1) {
+        return Error(static_cast<int>(StatusCode::INVALID_ARG))
+               << "no int32values on " << toString(value);
+    }
+    return value.value.int32Values[0];
+}
+
+Result<SwitchUserMessageType> getSwitchUserMessageType(const VehiclePropValue& value) {
+    if (value.value.int32Values.size() < 2) {
+        return Error(static_cast<int>(StatusCode::INVALID_ARG))
+               << "missing switch user message type " << toString(value);
+    }
+    return user_hal_helper::verifyAndCast<SwitchUserMessageType>(value.value.int32Values[1]);
+}
+
+}  // namespace
 
 bool EmulatedUserHal::isSupported(int32_t prop) {
     switch (prop) {
@@ -48,7 +73,7 @@
     }
 }
 
-android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetProperty(
+Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetProperty(
         const VehiclePropValue& value) {
     ALOGV("onSetProperty(): %s", toString(value).c_str());
 
@@ -65,12 +90,12 @@
         case USER_IDENTIFICATION_ASSOCIATION:
             return onSetUserIdentificationAssociation(value);
         default:
-            return android::base::Error(static_cast<int>(StatusCode::INVALID_ARG))
+            return Error(static_cast<int>(StatusCode::INVALID_ARG))
                    << "Unsupported property: " << toString(value);
     }
 }
 
-android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onGetProperty(
+Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onGetProperty(
         const VehiclePropValue& value) {
     ALOGV("onGetProperty(%s)", toString(value).c_str());
     switch (value.prop) {
@@ -79,42 +104,41 @@
         case CREATE_USER:
         case REMOVE_USER:
             ALOGE("onGetProperty(): %d is only supported on SET", value.prop);
-            return android::base::Error(static_cast<int>(StatusCode::INVALID_ARG))
-                   << "only supported on SET";
+            return Error(static_cast<int>(StatusCode::INVALID_ARG)) << "only supported on SET";
         case USER_IDENTIFICATION_ASSOCIATION:
             return onGetUserIdentificationAssociation(value);
         default:
             ALOGE("onGetProperty(): %d is not supported", value.prop);
-            return android::base::Error(static_cast<int>(StatusCode::INVALID_ARG))
-                   << "not supported by User HAL";
+            return Error(static_cast<int>(StatusCode::INVALID_ARG)) << "not supported by User HAL";
     }
 }
 
-android::base::Result<std::unique_ptr<VehiclePropValue>>
-EmulatedUserHal::onGetUserIdentificationAssociation(const VehiclePropValue& value) {
-    if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) {
-        ALOGI("get(USER_IDENTIFICATION_ASSOCIATION): returning %s",
-              toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str());
-        auto newValue = std::unique_ptr<VehiclePropValue>(
-                new VehiclePropValue(*mSetUserIdentificationAssociationResponseFromCmd));
+Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onGetUserIdentificationAssociation(
+        const VehiclePropValue& value) {
+    if (mSetUserIdentificationAssociationResponseFromCmd == nullptr) {
+        return defaultUserIdentificationAssociation(value);
+    }
+    ALOGI("get(USER_IDENTIFICATION_ASSOCIATION): returning %s",
+          toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str());
+    auto newValue = std::unique_ptr<VehiclePropValue>(
+            new VehiclePropValue(*mSetUserIdentificationAssociationResponseFromCmd));
+    auto requestId = getRequestId(value);
+    if (requestId.ok()) {
         // Must use the same requestId
-        if (value.value.int32Values.size() > 0) {
-            newValue->value.int32Values[0] = value.value.int32Values[0];
-        } else {
-            ALOGE("get(USER_IDENTIFICATION_ASSOCIATION): no requestId on %s",
-                  toString(value).c_str());
-        }
-        return newValue;
+        newValue->value.int32Values[0] = *requestId;
+    } else {
+        ALOGE("get(USER_IDENTIFICATION_ASSOCIATION): no requestId on %s", toString(value).c_str());
     }
-    return defaultUserIdentificationAssociation(value);
+    return newValue;
 }
 
-android::base::Result<std::unique_ptr<VehiclePropValue>>
-EmulatedUserHal::onSetInitialUserInfoResponse(const VehiclePropValue& value) {
-    if (value.value.int32Values.size() == 0) {
-        ALOGE("set(INITIAL_USER_INFO): no int32values, ignoring it: %s", toString(value).c_str());
-        return android::base::Error(static_cast<int>(StatusCode::INVALID_ARG))
-               << "no int32values on " << toString(value);
+Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetInitialUserInfoResponse(
+        const VehiclePropValue& value) {
+    auto requestId = getRequestId(value);
+    if (!requestId.ok()) {
+        ALOGE("Failed to get requestId on set(INITIAL_USER_INFO): %s",
+              requestId.error().message().c_str());
+        return requestId.error();
     }
 
     if (value.areaId != 0) {
@@ -124,85 +148,82 @@
     }
 
     ALOGD("set(INITIAL_USER_INFO) called from Android: %s", toString(value).c_str());
-
-    int32_t requestId = value.value.int32Values[0];
     if (mInitialUserResponseFromCmd != nullptr) {
         ALOGI("replying INITIAL_USER_INFO with lshal value:  %s",
               toString(*mInitialUserResponseFromCmd).c_str());
-        return sendUserHalResponse(std::move(mInitialUserResponseFromCmd), requestId);
+        return sendUserHalResponse(std::move(mInitialUserResponseFromCmd), *requestId);
     }
 
     // Returns default response
-    auto updatedValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue);
-    updatedValue->prop = INITIAL_USER_INFO;
-    updatedValue->timestamp = elapsedRealtimeNano();
-    updatedValue->value.int32Values.resize(2);
-    updatedValue->value.int32Values[0] = requestId;
-    updatedValue->value.int32Values[1] = (int32_t)InitialUserInfoResponseAction::DEFAULT;
-
+    auto updatedValue = user_hal_helper::toVehiclePropValue(InitialUserInfoResponse{
+            .requestId = *requestId,
+            .action = InitialUserInfoResponseAction::DEFAULT,
+    });
     ALOGI("no lshal response; replying with InitialUserInfoResponseAction::DEFAULT: %s",
           toString(*updatedValue).c_str());
-
     return updatedValue;
 }
 
-android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetSwitchUserResponse(
+Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetSwitchUserResponse(
         const VehiclePropValue& value) {
-    if (value.value.int32Values.size() == 0) {
-        ALOGE("set(SWITCH_USER): no int32values, ignoring it: %s", toString(value).c_str());
-        return android::base::Error(static_cast<int>(StatusCode::INVALID_ARG))
-               << "no int32values on " << toString(value);
+    auto requestId = getRequestId(value);
+    if (!requestId.ok()) {
+        ALOGE("Failed to get requestId on set(SWITCH_USER): %s",
+              requestId.error().message().c_str());
+        return requestId.error();
+    }
+
+    auto messageType = getSwitchUserMessageType(value);
+    if (!messageType.ok()) {
+        ALOGE("Failed to get messageType on set(SWITCH_USER): %s",
+              messageType.error().message().c_str());
+        return messageType.error();
     }
 
     if (value.areaId != 0) {
+        if (*messageType == SwitchUserMessageType::VEHICLE_REQUEST) {
+            // User HAL can also request a user switch, so we need to check it first
+            ALOGD("set(SWITCH_USER) called from lshal to emulate a vehicle request: %s",
+                  toString(value).c_str());
+            return std::unique_ptr<VehiclePropValue>(new VehiclePropValue(value));
+        }
+        // Otherwise, we store it
         ALOGD("set(SWITCH_USER) called from lshal; storing it: %s", toString(value).c_str());
         mSwitchUserResponseFromCmd.reset(new VehiclePropValue(value));
         return {};
     }
     ALOGD("set(SWITCH_USER) called from Android: %s", toString(value).c_str());
 
-    int32_t requestId = value.value.int32Values[0];
     if (mSwitchUserResponseFromCmd != nullptr) {
         ALOGI("replying SWITCH_USER with lshal value:  %s",
               toString(*mSwitchUserResponseFromCmd).c_str());
-        return sendUserHalResponse(std::move(mSwitchUserResponseFromCmd), requestId);
+        return sendUserHalResponse(std::move(mSwitchUserResponseFromCmd), *requestId);
     }
 
-    if (value.value.int32Values.size() > 1) {
-        auto messageType = static_cast<SwitchUserMessageType>(value.value.int32Values[1]);
-        switch (messageType) {
-            case SwitchUserMessageType::LEGACY_ANDROID_SWITCH:
-                ALOGI("request is LEGACY_ANDROID_SWITCH; ignoring it");
-                return {};
-            case SwitchUserMessageType::ANDROID_POST_SWITCH:
-                ALOGI("request is ANDROID_POST_SWITCH; ignoring it");
-                return {};
-            default:
-                break;
-        }
+    if (*messageType == SwitchUserMessageType::LEGACY_ANDROID_SWITCH ||
+        *messageType == SwitchUserMessageType::ANDROID_POST_SWITCH) {
+        ALOGI("request is %s; ignoring it", toString(*messageType).c_str());
+        return {};
     }
 
     // Returns default response
-    auto updatedValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue);
-    updatedValue->prop = SWITCH_USER;
-    updatedValue->timestamp = elapsedRealtimeNano();
-    updatedValue->value.int32Values.resize(3);
-    updatedValue->value.int32Values[0] = requestId;
-    updatedValue->value.int32Values[1] = (int32_t)SwitchUserMessageType::VEHICLE_RESPONSE;
-    updatedValue->value.int32Values[2] = (int32_t)SwitchUserStatus::SUCCESS;
-
+    auto updatedValue = user_hal_helper::toVehiclePropValue(SwitchUserResponse{
+            .requestId = *requestId,
+            .messageType = SwitchUserMessageType::VEHICLE_RESPONSE,
+            .status = SwitchUserStatus::SUCCESS,
+    });
     ALOGI("no lshal response; replying with VEHICLE_RESPONSE / SUCCESS: %s",
           toString(*updatedValue).c_str());
-
     return updatedValue;
 }
 
-android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetCreateUserResponse(
+Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetCreateUserResponse(
         const VehiclePropValue& value) {
-    if (value.value.int32Values.size() == 0) {
-        ALOGE("set(CREATE_USER): no int32values, ignoring it: %s", toString(value).c_str());
-        return android::base::Error(static_cast<int>(StatusCode::INVALID_ARG))
-               << "no int32values on " << toString(value);
+    auto requestId = getRequestId(value);
+    if (!requestId.ok()) {
+        ALOGE("Failed to get requestId on set(CREATE_USER): %s",
+              requestId.error().message().c_str());
+        return requestId.error();
     }
 
     if (value.areaId != 0) {
@@ -212,33 +233,28 @@
     }
     ALOGD("set(CREATE_USER) called from Android: %s", toString(value).c_str());
 
-    int32_t requestId = value.value.int32Values[0];
     if (mCreateUserResponseFromCmd != nullptr) {
         ALOGI("replying CREATE_USER with lshal value:  %s",
               toString(*mCreateUserResponseFromCmd).c_str());
-        return sendUserHalResponse(std::move(mCreateUserResponseFromCmd), requestId);
+        return sendUserHalResponse(std::move(mCreateUserResponseFromCmd), *requestId);
     }
 
     // Returns default response
-    auto updatedValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue);
-    updatedValue->prop = CREATE_USER;
-    updatedValue->timestamp = elapsedRealtimeNano();
-    updatedValue->value.int32Values.resize(2);
-    updatedValue->value.int32Values[0] = requestId;
-    updatedValue->value.int32Values[1] = (int32_t)CreateUserStatus::SUCCESS;
-
+    auto updatedValue = user_hal_helper::toVehiclePropValue(CreateUserResponse{
+            .requestId = *requestId,
+            .status = CreateUserStatus::SUCCESS,
+    });
     ALOGI("no lshal response; replying with SUCCESS: %s", toString(*updatedValue).c_str());
-
     return updatedValue;
 }
 
-android::base::Result<std::unique_ptr<VehiclePropValue>>
-EmulatedUserHal::onSetUserIdentificationAssociation(const VehiclePropValue& value) {
-    if (value.value.int32Values.size() == 0) {
-        ALOGE("set(USER_IDENTIFICATION_ASSOCIATION): no int32values, ignoring it: %s",
-              toString(value).c_str());
-        return android::base::Error(static_cast<int>(StatusCode::INVALID_ARG))
-               << "no int32values on " << toString(value);
+Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetUserIdentificationAssociation(
+        const VehiclePropValue& value) {
+    auto requestId = getRequestId(value);
+    if (!requestId.ok()) {
+        ALOGE("Failed to get requestId on set(USER_IDENTIFICATION_ASSOCIATION): %s",
+              requestId.error().message().c_str());
+        return requestId.error();
     }
 
     if (value.areaId != 0) {
@@ -249,28 +265,26 @@
     }
     ALOGD("set(USER_IDENTIFICATION_ASSOCIATION) called from Android: %s", toString(value).c_str());
 
-    int32_t requestId = value.value.int32Values[0];
     if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) {
         ALOGI("replying USER_IDENTIFICATION_ASSOCIATION with lshal value:  %s",
               toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str());
         // Not moving response so it can be used on GET requests
         auto copy = std::unique_ptr<VehiclePropValue>(
                 new VehiclePropValue(*mSetUserIdentificationAssociationResponseFromCmd));
-        return sendUserHalResponse(std::move(copy), requestId);
+        return sendUserHalResponse(std::move(copy), *requestId);
     }
-
     // Returns default response
     return defaultUserIdentificationAssociation(value);
 }
 
-android::base::Result<std::unique_ptr<VehiclePropValue>>
-EmulatedUserHal::defaultUserIdentificationAssociation(const VehiclePropValue& request) {
+Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::defaultUserIdentificationAssociation(
+        const VehiclePropValue& request) {
     // TODO(b/159498909): return a response with NOT_ASSOCIATED_ANY_USER for all requested types
     ALOGE("no lshal response for %s; replying with NOT_AVAILABLE", toString(request).c_str());
-    return android::base::Error(static_cast<int>(StatusCode::NOT_AVAILABLE)) << "not set by lshal";
+    return Error(static_cast<int>(StatusCode::NOT_AVAILABLE)) << "not set by lshal";
 }
 
-android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::sendUserHalResponse(
+Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::sendUserHalResponse(
         std::unique_ptr<VehiclePropValue> response, int32_t requestId) {
     switch (response->areaId) {
         case 1:
@@ -284,17 +298,16 @@
         case 3:
             ALOGD("not generating a property change event because of lshal prop: %s",
                   toString(*response).c_str());
-            return android::base::Error(static_cast<int>(StatusCode::NOT_AVAILABLE))
+            return Error(static_cast<int>(StatusCode::NOT_AVAILABLE))
                    << "not generating a property change event because of lshal prop: "
                    << toString(*response);
         default:
             ALOGE("invalid action on lshal response: %s", toString(*response).c_str());
-            return android::base::Error(static_cast<int>(StatusCode::INTERNAL_ERROR))
+            return Error(static_cast<int>(StatusCode::INTERNAL_ERROR))
                    << "invalid action on lshal response: " << toString(*response);
     }
 
     ALOGD("updating property to: %s", toString(*response).c_str());
-
     return response;
 }
 
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
index 7f9362f..ed3f4a2 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
@@ -35,13 +35,33 @@
 
 namespace impl {
 
-class EmulatedPassthroughConnector : public PassthroughConnector {
-  public:
-    bool onDump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
-};
+EmulatedUserHal* EmulatedVehicleConnector::getEmulatedUserHal() {
+    return &mEmulatedUserHal;
+}
 
-bool EmulatedPassthroughConnector::onDump(const hidl_handle& handle,
-                                          const hidl_vec<hidl_string>& options) {
+StatusCode EmulatedVehicleConnector::onSetProperty(const VehiclePropValue& value,
+                                                   bool updateStatus) {
+    if (mEmulatedUserHal.isSupported(value.prop)) {
+        LOG(INFO) << "onSetProperty(): property " << value.prop << " will be handled by UserHal";
+
+        const auto& ret = mEmulatedUserHal.onSetProperty(value);
+        if (!ret.ok()) {
+            LOG(ERROR) << "onSetProperty(): HAL returned error: " << ret.error().message();
+            return StatusCode(ret.error().code());
+        }
+        auto updatedValue = ret.value().get();
+        if (updatedValue != nullptr) {
+            LOG(INFO) << "onSetProperty(): updating property returned by HAL: "
+                      << toString(*updatedValue);
+            onPropertyValueFromCar(*updatedValue, updateStatus);
+        }
+        return StatusCode::OK;
+    }
+    return this->VehicleHalServer::onSetProperty(value, updateStatus);
+}
+
+bool EmulatedVehicleConnector::onDump(const hidl_handle& handle,
+                                      const hidl_vec<hidl_string>& options) {
     int fd = handle->data[0];
 
     if (options.size() > 0) {
@@ -68,10 +88,6 @@
     return true;
 }
 
-PassthroughConnectorPtr makeEmulatedPassthroughConnector() {
-    return std::make_unique<EmulatedPassthroughConnector>();
-}
-
 }  // namespace impl
 
 }  // namespace V2_0
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
index 57cbb8b..4c6c661 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
@@ -19,6 +19,7 @@
 
 #include <vhal_v2_0/VehicleConnector.h>
 
+#include "EmulatedUserHal.h"
 #include "VehicleHalClient.h"
 #include "VehicleHalServer.h"
 
@@ -30,10 +31,20 @@
 
 namespace impl {
 
-using PassthroughConnector = IPassThroughConnector<VehicleHalClient, VehicleHalServer>;
-using PassthroughConnectorPtr = std::unique_ptr<PassthroughConnector>;
+class EmulatedVehicleConnector : public IPassThroughConnector<VehicleHalClient, VehicleHalServer> {
+  public:
+    EmulatedVehicleConnector() {}
 
-PassthroughConnectorPtr makeEmulatedPassthroughConnector();
+    EmulatedUserHal* getEmulatedUserHal();
+
+    // Methods from VehicleHalServer
+    StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) override;
+
+    bool onDump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
+
+  private:
+    EmulatedUserHal mEmulatedUserHal;
+};
 
 }  // namespace impl
 
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
index a0b566d..1d51600 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
@@ -15,13 +15,8 @@
  */
 #define LOG_TAG "DefaultVehicleHal_v2_0"
 
-#include <android-base/macros.h>
-#include <android-base/properties.h>
 #include <android/log.h>
-#include <dirent.h>
-#include <sys/system_properties.h>
-#include <fstream>
-#include <regex>
+#include <android-base/macros.h>
 
 #include "EmulatedVehicleHal.h"
 #include "JsonFakeValueGenerator.h"
@@ -107,30 +102,6 @@
     mVehicleClient->registerPropertyValueCallback(std::bind(&EmulatedVehicleHal::onPropertyValue,
                                                             this, std::placeholders::_1,
                                                             std::placeholders::_2));
-
-    mInitVhalValueOverride =
-            android::base::GetBoolProperty("persist.vendor.vhal_init_value_override", false);
-    if (mInitVhalValueOverride) {
-        getAllPropertiesOverride();
-    }
-}
-
-void EmulatedVehicleHal::getAllPropertiesOverride() {
-    if (auto dir = opendir("/vendor/etc/vhaloverride/")) {
-        std::regex reg_json(".*[.]json", std::regex::icase);
-        while (auto f = readdir(dir)) {
-            if (!regex_match(f->d_name, reg_json)) {
-                continue;
-            }
-            std::string file = "/vendor/etc/vhaloverride/" + std::string(f->d_name);
-            JsonFakeValueGenerator tmpGenerator(file);
-
-            std::vector<VehiclePropValue> propvalues = tmpGenerator.getAllEvents();
-            mVehiclePropertiesOverride.insert(std::end(mVehiclePropertiesOverride),
-                                              std::begin(propvalues), std::end(propvalues));
-        }
-        closedir(dir);
-    }
 }
 
 VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
@@ -239,14 +210,6 @@
         return StatusCode::NOT_AVAILABLE;
     }
 
-    if (mInEmulator && propValue.prop == toInt(VehicleProperty::DISPLAY_BRIGHTNESS)) {
-        // Emulator does not support remote brightness control, b/139959479
-        // do not send it down so that it does not bring unnecessary property change event
-        // return other error code, such NOT_AVAILABLE, causes Emulator to be freezing
-        // TODO: return StatusCode::NOT_AVAILABLE once the above issue is fixed
-        return StatusCode::OK;
-    }
-
     /**
      * After checking all conditions, such as the property is available, a real vhal will
      * sent the events to Car ECU to take actions.
@@ -272,17 +235,6 @@
     return false;
 }
 
-// determine if it's running inside Android Emulator
-static bool isInEmulator() {
-    char propValue[PROP_VALUE_MAX];
-    bool isEmulator = (__system_property_get("ro.kernel.qemu", propValue) != 0);
-    if (!isEmulator) {
-        isEmulator = (__system_property_get("ro.hardware", propValue) != 0) &&
-                     (!strcmp(propValue, "ranchu") || !strcmp(propValue, "goldfish"));
-    }
-    return isEmulator;
-}
-
 // Parse supported properties list and generate vector of property values to hold current values.
 void EmulatedVehicleHal::onCreate() {
     static constexpr bool shouldUpdateStatus = true;
@@ -327,21 +279,12 @@
                 }
             } else {
                 prop.value = it.initialValue;
-                if (mInitVhalValueOverride) {
-                    for (auto& itOverride : mVehiclePropertiesOverride) {
-                        if (itOverride.prop == cfg.prop) {
-                            prop.value = itOverride.value;
-                        }
-                    }
-                }
             }
             mPropStore->writeValue(prop, shouldUpdateStatus);
         }
     }
     initObd2LiveFrame(*mPropStore->getConfigOrDie(OBD2_LIVE_FRAME));
     initObd2FreezeFrame(*mPropStore->getConfigOrDie(OBD2_FREEZE_FRAME));
-    mInEmulator = isInEmulator();
-    ALOGD("mInEmulator=%s", mInEmulator ? "true" : "false");
 }
 
 std::vector<VehiclePropConfig> EmulatedVehicleHal::listProperties()  {
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
index eb38d7d..30f6bfa 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
@@ -63,7 +63,6 @@
     //  Methods from EmulatedVehicleHalIface
     bool setPropertyFromVehicle(const VehiclePropValue& propValue) override;
     std::vector<VehiclePropValue> getAllProperties() const override;
-    void getAllPropertiesOverride();
 
 private:
     constexpr std::chrono::nanoseconds hertzToNanoseconds(float hz) const {
@@ -88,9 +87,6 @@
     std::unordered_set<int32_t> mHvacPowerProps;
     RecurrentTimer mRecurrentTimer;
     VehicleHalClient* mVehicleClient;
-    bool mInEmulator;
-    bool mInitVhalValueOverride;
-    std::vector<VehiclePropValue> mVehiclePropertiesOverride;
     EmulatedUserHal* mEmulatedUserHal;
 };
 
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.cpp
index 548285a..9be9ea7 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.cpp
@@ -31,6 +31,14 @@
 GeneratorHub::GeneratorHub(const OnHalEvent& onHalEvent)
     : mOnHalEvent(onHalEvent), mThread(&GeneratorHub::run, this) {}
 
+GeneratorHub::~GeneratorHub() {
+    mShuttingDownFlag.store(true);
+    mCond.notify_all();
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+}
+
 void GeneratorHub::registerGenerator(int32_t cookie, FakeValueGeneratorPtr generator) {
     {
         std::lock_guard<std::mutex> g(mLock);
@@ -58,15 +66,18 @@
 }
 
 void GeneratorHub::run() {
-    while (true) {
+    while (!mShuttingDownFlag.load()) {
         std::unique_lock<std::mutex> g(mLock);
         // Pop events whose generator does not exist (may be already unregistered)
         while (!mEventQueue.empty()
                && mGenerators.find(mEventQueue.top().cookie) == mGenerators.end()) {
              mEventQueue.pop();
         }
-        // Wait until event queue is not empty
-        mCond.wait(g, [this] { return !mEventQueue.empty(); });
+        // Wait until event queue is not empty or shutting down flag is set
+        mCond.wait(g, [this] { return !mEventQueue.empty() || mShuttingDownFlag.load(); });
+        if (mShuttingDownFlag.load()) {
+            break;
+        }
 
         const VhalEvent& curEvent = mEventQueue.top();
 
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.h
index dcf6a4f..b25dbf1 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.h
@@ -58,7 +58,7 @@
 
 public:
     GeneratorHub(const OnHalEvent& onHalEvent);
-    ~GeneratorHub() = default;
+    ~GeneratorHub();
 
     /**
      * Register a new generator. The generator will be discarded if it could not produce next event.
@@ -84,6 +84,7 @@
     mutable std::mutex mLock;
     std::condition_variable mCond;
     std::thread mThread;
+    std::atomic<bool> mShuttingDownFlag{false};
 };
 
 }  // namespace impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
index 890eb33..8677f83 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
@@ -48,22 +48,6 @@
     mNumOfIterations = v.int32Values.size() < 2 ? -1 : v.int32Values[1];
 }
 
-JsonFakeValueGenerator::JsonFakeValueGenerator(std::string path) {
-    std::ifstream ifs(path);
-    if (!ifs) {
-        ALOGE("%s: couldn't open %s for parsing.", __func__, path.c_str());
-    }
-    mGenCfg = {
-        .index = 0,
-        .events = parseFakeValueJson(ifs),
-    };
-    mNumOfIterations = mGenCfg.events.size();
-}
-
-std::vector<VehiclePropValue> JsonFakeValueGenerator::getAllEvents() {
-    return mGenCfg.events;
-}
-
 VehiclePropValue JsonFakeValueGenerator::nextEvent() {
     VehiclePropValue generatedValue;
     if (!hasNext()) {
@@ -125,7 +109,6 @@
 
         Json::Value rawEventValue = rawEvent["value"];
         auto& value = event.value;
-        int32_t count;
         switch (getPropType(event.prop)) {
             case VehiclePropertyType::BOOLEAN:
             case VehiclePropertyType::INT32:
@@ -143,13 +126,6 @@
             case VehiclePropertyType::STRING:
                 value.stringValue = rawEventValue.asString();
                 break;
-            case VehiclePropertyType::INT32_VEC:
-                value.int32Values.resize(rawEventValue.size());
-                count = 0;
-                for (auto& it : rawEventValue) {
-                    value.int32Values[count++] = it.asInt();
-                }
-                break;
             case VehiclePropertyType::MIXED:
                 copyMixedValueJson(value, rawEventValue);
                 if (isDiagnosticProperty(event.prop)) {
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
index dc8ff66..70575f7 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
@@ -41,12 +41,9 @@
 
 public:
     JsonFakeValueGenerator(const VehiclePropValue& request);
-    JsonFakeValueGenerator(std::string path);
-
     ~JsonFakeValueGenerator() = default;
 
     VehiclePropValue nextEvent();
-    std::vector<VehiclePropValue> getAllEvents();
 
     bool hasNext();
 
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
index 36f2534..0ee1835 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
@@ -41,10 +41,6 @@
     return mValuePool;
 }
 
-EmulatedUserHal* VehicleHalServer::getEmulatedUserHal() {
-    return &mEmulatedUserHal;
-}
-
 void VehicleHalServer::setValuePool(VehiclePropValuePool* valuePool) {
     if (!valuePool) {
         LOG(WARNING) << __func__ << ": Setting value pool to nullptr!";
@@ -185,22 +181,6 @@
 }
 
 StatusCode VehicleHalServer::onSetProperty(const VehiclePropValue& value, bool updateStatus) {
-    if (mEmulatedUserHal.isSupported(value.prop)) {
-        LOG(INFO) << "onSetProperty(): property " << value.prop << " will be handled by UserHal";
-
-        const auto& ret = mEmulatedUserHal.onSetProperty(value);
-        if (!ret.ok()) {
-            LOG(ERROR) << "onSetProperty(): HAL returned error: " << ret.error().message();
-            return StatusCode(ret.error().code());
-        }
-        auto updatedValue = ret.value().get();
-        if (updatedValue != nullptr) {
-            LOG(INFO) << "onSetProperty(): updating property returned by HAL: "
-                      << toString(*updatedValue);
-            onPropertyValueFromCar(*updatedValue, updateStatus);
-        }
-        return StatusCode::OK;
-    }
     LOG(DEBUG) << "onSetProperty(" << value.prop << ")";
 
     // Some properties need to be treated non-trivially
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h
index fca78bc..117eadb 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h
@@ -19,7 +19,6 @@
 #include <vhal_v2_0/VehicleObjectPool.h>
 #include <vhal_v2_0/VehicleServer.h>
 
-#include "EmulatedUserHal.h"
 #include "GeneratorHub.h"
 
 namespace android::hardware::automotive::vehicle::V2_0::impl {
@@ -38,8 +37,6 @@
     // Set the Property Value Pool used in this server
     void setValuePool(VehiclePropValuePool* valuePool);
 
-    EmulatedUserHal* getEmulatedUserHal();
-
   private:
     using VehiclePropValuePtr = recyclable_ptr<VehiclePropValue>;
 
@@ -56,11 +53,6 @@
     VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action, int32_t keyCode,
                                              int32_t targetDisplay);
 
-    // data members
-
-  protected:
-    EmulatedUserHal mEmulatedUserHal;
-
   private:
     GeneratorHub mGeneratorHub{
             std::bind(&VehicleHalServer::onFakeValueGenerated, this, std::placeholders::_1)};
diff --git a/automotive/vehicle/2.0/utils/Android.bp b/automotive/vehicle/2.0/utils/Android.bp
new file mode 100644
index 0000000..e354634
--- /dev/null
+++ b/automotive/vehicle/2.0/utils/Android.bp
@@ -0,0 +1,41 @@
+// 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.
+
+// User HAL helper library.
+cc_library_static {
+    name: "android.hardware.automotive.vehicle@2.0-user-hal-helper-lib",
+    defaults: ["vhal_v2_0_defaults"],
+    vendor: true,
+    host_supported: true,
+    srcs: [
+        "UserHalHelper.cpp",
+    ],
+    export_include_dirs: [
+        ".",
+    ],
+}
+
+cc_test {
+    name: "android.hardware.automotive.vehicle@2.0-utils-unit-tests",
+    defaults: ["vhal_v2_0_defaults"],
+    vendor: true,
+    srcs: [
+        "tests/UserHalHelper_test.cpp",
+    ],
+    static_libs: [
+        "android.hardware.automotive.vehicle@2.0-user-hal-helper-lib",
+        "libgmock",
+    ],
+    test_suites: ["general-tests"],
+}
diff --git a/automotive/vehicle/2.0/utils/UserHalHelper.cpp b/automotive/vehicle/2.0/utils/UserHalHelper.cpp
new file mode 100644
index 0000000..abf59b7
--- /dev/null
+++ b/automotive/vehicle/2.0/utils/UserHalHelper.cpp
@@ -0,0 +1,362 @@
+/*
+ * 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 "UserHalHelper"
+
+#include "UserHalHelper.h"
+
+#include <log/log.h>
+#include <utils/SystemClock.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace user_hal_helper {
+namespace {
+
+using android::base::Error;
+using android::base::Result;
+
+static constexpr const char* kSeparator = "||";
+static const size_t kNumFieldsPerUserInfo = 2;
+static const size_t kNumFieldsPerSetAssociation = 2;
+
+Result<void> verifyPropValue(const VehiclePropValue& propValue, VehicleProperty vehicleProperty,
+                             size_t minInt32Values) {
+    auto prop = verifyAndCast<VehicleProperty>(propValue.prop);
+    if (!prop.ok()) {
+        return Error() << "Invalid vehicle property: " << prop.error();
+    }
+    if (*prop != vehicleProperty) {
+        return Error() << "Mismatching " << toString(vehicleProperty) << " request, received "
+                       << toString(*prop) << " property";
+    }
+    if (propValue.value.int32Values.size() < minInt32Values) {
+        return Error() << "Int32Values must have at least " << minInt32Values
+                       << " values, received " << propValue.value.int32Values.size();
+    }
+    return {};
+}
+
+Result<void> parseUserInfo(const hidl_vec<int32_t>& int32Values, size_t startPos,
+                           UserInfo* userInfo) {
+    if (int32Values.size() < startPos + kNumFieldsPerUserInfo) {
+        return Error() << "Int32Values must have at least " << startPos + 2 << " values, received "
+                       << int32Values.size();
+    }
+    userInfo->userId = int32Values[startPos];
+    auto userFlags = verifyAndCast<UserFlags>(int32Values[startPos + 1]);
+    if (!userFlags.ok()) {
+        return Error() << "Invalid user flags: " << userFlags.error();
+    }
+    userInfo->flags = *userFlags;
+    return {};
+}
+
+Result<void> parseUsersInfo(const hidl_vec<int32_t>& int32Values, size_t startPos,
+                            UsersInfo* usersInfo) {
+    if (int32Values.size() < startPos + 3) {
+        return Error() << "Int32Values must have at least " << startPos + 3 << " values, received "
+                       << int32Values.size();
+    }
+    auto ret = parseUserInfo(int32Values, startPos, &usersInfo->currentUser);
+    if (!ret.ok()) {
+        return ret;
+    }
+    usersInfo->numberUsers = int32Values[startPos + 2];
+    usersInfo->existingUsers.resize(usersInfo->numberUsers);
+    for (size_t i = 0; i < static_cast<size_t>(usersInfo->numberUsers); ++i) {
+        ret = parseUserInfo(int32Values, startPos + 3 + (kNumFieldsPerUserInfo * i),
+                            &usersInfo->existingUsers[i]);
+        if (!ret.ok()) {
+            return Error() << "Failed to parse existing user '" << i << "' info: " << ret.error();
+        }
+    }
+    return {};
+}
+
+Result<void> parseUserAssociationTypes(
+        const hidl_vec<int32_t>& int32Values, size_t startPos, size_t numberAssociationTypes,
+        hidl_vec<UserIdentificationAssociationType>* associationTypes) {
+    size_t minInt32Values = startPos + numberAssociationTypes;
+    if (int32Values.size() < minInt32Values) {
+        return Error() << "Int32Values must have at least " << minInt32Values
+                       << " values, received " << int32Values.size();
+    }
+    associationTypes->resize(numberAssociationTypes);
+    for (size_t i = 0; i < static_cast<size_t>(numberAssociationTypes); ++i) {
+        size_t pos = startPos + i;
+        auto type = verifyAndCast<UserIdentificationAssociationType>(int32Values[pos]);
+        if (!type.ok()) {
+            return Error() << "Invalid association type in query '" << i << "': " << type.error();
+        }
+        (*associationTypes)[i] = *type;
+    }
+    return {};
+}
+
+Result<void> parseUserAssociations(const hidl_vec<int32_t>& int32Values, size_t startPos,
+                                   size_t numberAssociations,
+                                   hidl_vec<UserIdentificationSetAssociation>* associations) {
+    size_t minInt32Values = startPos + (numberAssociations * kNumFieldsPerSetAssociation);
+    if (int32Values.size() < minInt32Values) {
+        return Error() << "Int32Values must have at least " << minInt32Values
+                       << " values, received " << int32Values.size();
+    }
+    associations->resize(numberAssociations);
+    for (size_t i = 0; i < static_cast<size_t>(numberAssociations); ++i) {
+        size_t pos = startPos + (kNumFieldsPerSetAssociation * i);
+        auto type = verifyAndCast<UserIdentificationAssociationType>(int32Values[pos]);
+        if (!type.ok()) {
+            return Error() << "Invalid association type in request '" << i << "': " << type.error();
+        }
+        (*associations)[i].type = *type;
+        auto value = verifyAndCast<UserIdentificationAssociationSetValue>(int32Values[pos + 1]);
+        if (!value.ok()) {
+            return Error() << "Invalid association set value in request '" << i
+                           << "': " << value.error();
+        }
+        (*associations)[i].value = *value;
+    }
+    return {};
+}
+
+}  // namespace
+
+template <typename T>
+Result<T> verifyAndCast(int32_t value) {
+    T castValue = static_cast<T>(value);
+    for (const auto& v : hidl_enum_range<T>()) {
+        if (castValue == v) {
+            return castValue;
+        }
+    }
+    return Error() << "Value " << value << " not in enum values";
+}
+
+Result<InitialUserInfoRequest> toInitialUserInfoRequest(const VehiclePropValue& propValue) {
+    auto ret = verifyPropValue(propValue, VehicleProperty::INITIAL_USER_INFO, 2);
+    if (!ret.ok()) {
+        return ret.error();
+    }
+    InitialUserInfoRequest request;
+    request.requestId = propValue.value.int32Values[0];
+    auto requestType = verifyAndCast<InitialUserInfoRequestType>(propValue.value.int32Values[1]);
+    if (!requestType.ok()) {
+        return Error() << "Invalid InitialUserInfoRequestType: " << requestType.error();
+    }
+    request.requestType = *requestType;
+    ret = parseUsersInfo(propValue.value.int32Values, 2, &request.usersInfo);
+    if (!ret.ok()) {
+        return Error() << "Failed to parse users info: " << ret.error();
+    }
+    return request;
+}
+
+Result<SwitchUserRequest> toSwitchUserRequest(const VehiclePropValue& propValue) {
+    auto ret = verifyPropValue(propValue, VehicleProperty::SWITCH_USER, 2);
+    if (!ret.ok()) {
+        return ret.error();
+    }
+    SwitchUserRequest request;
+    auto messageType = verifyAndCast<SwitchUserMessageType>(propValue.value.int32Values[1]);
+    if (!messageType.ok()) {
+        return Error() << "Invalid SwitchUserMessageType: " << messageType.error();
+    }
+    if (*messageType != SwitchUserMessageType::LEGACY_ANDROID_SWITCH &&
+        *messageType != SwitchUserMessageType::ANDROID_SWITCH &&
+        *messageType != SwitchUserMessageType::ANDROID_POST_SWITCH) {
+        return Error() << "Invalid " << toString(*messageType)
+                       << " message type from Android System";
+    }
+    request.requestId = propValue.value.int32Values[0];
+    request.messageType = *messageType;
+    ret = parseUserInfo(propValue.value.int32Values, 2, &request.targetUser);
+    if (!ret.ok()) {
+        return Error() << "Failed to parse target user info: " << ret.error();
+    }
+    ret = parseUsersInfo(propValue.value.int32Values, 4, &request.usersInfo);
+    if (!ret.ok()) {
+        return Error() << "Failed to parse users info: " << ret.error();
+    }
+    return request;
+}
+
+Result<CreateUserRequest> toCreateUserRequest(const VehiclePropValue& propValue) {
+    auto ret = verifyPropValue(propValue, VehicleProperty::CREATE_USER, 1);
+    if (!ret.ok()) {
+        return ret.error();
+    }
+    CreateUserRequest request;
+    request.requestId = propValue.value.int32Values[0];
+    ret = parseUserInfo(propValue.value.int32Values, 1, &request.newUserInfo);
+    if (!ret.ok()) {
+        return Error() << "Failed to parse new user info: " << ret.error();
+    }
+    request.newUserName = propValue.value.stringValue;
+    ret = parseUsersInfo(propValue.value.int32Values, 3, &request.usersInfo);
+    if (!ret.ok()) {
+        return Error() << "Failed to parse users info: " << ret.error();
+    }
+    return request;
+}
+
+Result<RemoveUserRequest> toRemoveUserRequest(const VehiclePropValue& propValue) {
+    auto ret = verifyPropValue(propValue, VehicleProperty::REMOVE_USER, 1);
+    if (!ret.ok()) {
+        return ret.error();
+    }
+    RemoveUserRequest request;
+    request.requestId = propValue.value.int32Values[0];
+    ret = parseUserInfo(propValue.value.int32Values, 1, &request.removedUserInfo);
+    if (!ret.ok()) {
+        return Error() << "Failed to parse removed user info: " << ret.error();
+    }
+    ret = parseUsersInfo(propValue.value.int32Values, 3, &request.usersInfo);
+    if (!ret.ok()) {
+        return Error() << "Failed to parse users info: " << ret.error();
+    }
+    return request;
+}
+
+Result<UserIdentificationGetRequest> toUserIdentificationGetRequest(
+        const VehiclePropValue& propValue) {
+    auto ret = verifyPropValue(propValue, VehicleProperty::USER_IDENTIFICATION_ASSOCIATION, 4);
+    if (!ret.ok()) {
+        return ret.error();
+    }
+    UserIdentificationGetRequest request;
+    request.requestId = propValue.value.int32Values[0];
+    ret = parseUserInfo(propValue.value.int32Values, 1, &request.userInfo);
+    if (!ret.ok()) {
+        return Error() << "Failed to parse user info: " << ret.error();
+    }
+    request.numberAssociationTypes = propValue.value.int32Values[3];
+    ret = parseUserAssociationTypes(propValue.value.int32Values, 4, request.numberAssociationTypes,
+                                    &request.associationTypes);
+    if (!ret.ok()) {
+        return Error() << "Failed to parse UserIdentificationAssociationType: " << ret.error();
+    }
+    return request;
+}
+
+Result<UserIdentificationSetRequest> toUserIdentificationSetRequest(
+        const VehiclePropValue& propValue) {
+    auto ret = verifyPropValue(propValue, VehicleProperty::USER_IDENTIFICATION_ASSOCIATION, 4);
+    if (!ret.ok()) {
+        return ret.error();
+    }
+    UserIdentificationSetRequest request;
+    request.requestId = propValue.value.int32Values[0];
+    ret = parseUserInfo(propValue.value.int32Values, 1, &request.userInfo);
+    if (!ret.ok()) {
+        return Error() << "Failed to parse user info: " << ret.error();
+    }
+    request.numberAssociations = propValue.value.int32Values[3];
+    ret = parseUserAssociations(propValue.value.int32Values, 4, request.numberAssociations,
+                                &request.associations);
+    if (!ret.ok()) {
+        return Error() << "Failed to parse UserIdentificationSetAssociation: " << ret.error();
+    }
+    return request;
+}
+
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const SwitchUserRequest& request) {
+    if (request.messageType != SwitchUserMessageType::VEHICLE_REQUEST) {
+        ALOGE("Invalid %s message type %s from HAL", toString(VehicleProperty::SWITCH_USER).c_str(),
+              toString(request.messageType).c_str());
+        return nullptr;
+    }
+    auto propValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue());
+    propValue->prop = static_cast<int32_t>(VehicleProperty::SWITCH_USER);
+    propValue->timestamp = elapsedRealtimeNano();
+    propValue->value.int32Values.resize(3);
+    propValue->value.int32Values[0] = static_cast<int32_t>(request.requestId);
+    propValue->value.int32Values[1] = static_cast<int32_t>(request.messageType);
+    propValue->value.int32Values[2] = static_cast<int32_t>(request.targetUser.userId);
+    return propValue;
+}
+
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const InitialUserInfoResponse& response) {
+    auto propValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue());
+    propValue->prop = static_cast<int32_t>(VehicleProperty::INITIAL_USER_INFO);
+    propValue->timestamp = elapsedRealtimeNano();
+    propValue->value.int32Values.resize(4);
+    propValue->value.int32Values[0] = static_cast<int32_t>(response.requestId);
+    propValue->value.int32Values[1] = static_cast<int32_t>(response.action);
+    propValue->value.int32Values[2] = static_cast<int32_t>(response.userToSwitchOrCreate.userId);
+    propValue->value.int32Values[3] = static_cast<int32_t>(response.userToSwitchOrCreate.flags);
+    propValue->value.stringValue = std::string(response.userLocales) + std::string(kSeparator) +
+                                   std::string(response.userNameToCreate);
+    return propValue;
+}
+
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const SwitchUserResponse& response) {
+    auto propValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue());
+    propValue->prop = static_cast<int32_t>(VehicleProperty::SWITCH_USER);
+    propValue->timestamp = elapsedRealtimeNano();
+    propValue->value.int32Values.resize(3);
+    propValue->value.int32Values[0] = static_cast<int32_t>(response.requestId);
+    propValue->value.int32Values[1] = static_cast<int32_t>(response.messageType);
+    propValue->value.int32Values[2] = static_cast<int32_t>(response.status);
+    if (response.status == SwitchUserStatus::FAILURE) {
+        propValue->value.stringValue = response.errorMessage;
+    }
+    return propValue;
+}
+
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const CreateUserResponse& response) {
+    auto propValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue());
+    propValue->prop = static_cast<int32_t>(VehicleProperty::CREATE_USER);
+    propValue->timestamp = elapsedRealtimeNano();
+    propValue->value.int32Values.resize(2);
+    propValue->value.int32Values[0] = static_cast<int32_t>(response.requestId);
+    propValue->value.int32Values[1] = static_cast<int32_t>(response.status);
+    if (response.status == CreateUserStatus::FAILURE) {
+        propValue->value.stringValue = response.errorMessage;
+    }
+    return propValue;
+}
+
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const UserIdentificationResponse& response) {
+    auto propValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue());
+    propValue->prop = static_cast<int32_t>(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION);
+    propValue->timestamp = elapsedRealtimeNano();
+    propValue->value.int32Values.resize(2 + (response.numberAssociation * 2));
+    propValue->value.int32Values[0] = static_cast<int32_t>(response.requestId);
+    propValue->value.int32Values[1] = static_cast<int32_t>(response.numberAssociation);
+    for (size_t i = 0; i < static_cast<size_t>(response.numberAssociation); ++i) {
+        size_t int32ValuesPos = 2 + (2 * i);
+        propValue->value.int32Values[int32ValuesPos] =
+                static_cast<int32_t>(response.associations[i].type);
+        propValue->value.int32Values[int32ValuesPos + 1] =
+                static_cast<int32_t>(response.associations[i].value);
+    }
+    if (!response.errorMessage.empty()) {
+        propValue->value.stringValue = response.errorMessage;
+    }
+    return propValue;
+}
+
+}  // namespace user_hal_helper
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/2.0/utils/UserHalHelper.h b/automotive/vehicle/2.0/utils/UserHalHelper.h
new file mode 100644
index 0000000..fad7145
--- /dev/null
+++ b/automotive/vehicle/2.0/utils/UserHalHelper.h
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_automotive_vehicle_V2_0_impl_UserHalHelper_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_UserHalHelper_H_
+
+#include <android-base/result.h>
+#include <android/hardware/automotive/vehicle/2.0/types.h>
+
+#include <functional>
+#include <memory>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace user_hal_helper {
+
+// Verify whether the |value| can be casted to the type |T| and return the casted value on success.
+// Otherwise, return the error.
+template <typename T>
+android::base::Result<T> verifyAndCast(int32_t value);
+
+// Below functions parse VehiclePropValues to the respective User HAL request structs. On success,
+// these functions return the User HAL struct. Otherwise, they return the error.
+android::base::Result<InitialUserInfoRequest> toInitialUserInfoRequest(
+        const VehiclePropValue& propValue);
+android::base::Result<SwitchUserRequest> toSwitchUserRequest(const VehiclePropValue& propValue);
+android::base::Result<CreateUserRequest> toCreateUserRequest(const VehiclePropValue& propValue);
+android::base::Result<RemoveUserRequest> toRemoveUserRequest(const VehiclePropValue& propValue);
+android::base::Result<UserIdentificationGetRequest> toUserIdentificationGetRequest(
+        const VehiclePropValue& propValue);
+android::base::Result<UserIdentificationSetRequest> toUserIdentificationSetRequest(
+        const VehiclePropValue& propValue);
+
+// Below functions convert the User HAL structs to VehiclePropValues. On success, these functions
+// return the pointer to VehiclePropValue. Otherwise, they return nullptr.
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const SwitchUserRequest& request);
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const InitialUserInfoResponse& response);
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const SwitchUserResponse& response);
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const CreateUserResponse& response);
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const UserIdentificationResponse& response);
+
+}  // namespace user_hal_helper
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_V2_0_impl_UserHalHelper_H_
diff --git a/automotive/vehicle/2.0/utils/tests/UserHalHelper_test.cpp b/automotive/vehicle/2.0/utils/tests/UserHalHelper_test.cpp
new file mode 100644
index 0000000..7da87a2
--- /dev/null
+++ b/automotive/vehicle/2.0/utils/tests/UserHalHelper_test.cpp
@@ -0,0 +1,666 @@
+/*
+ * 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.
+ */
+
+#include "UserHalHelper.h"
+
+#include <gtest/gtest.h>
+
+#include <cstdint>
+
+#include "gmock/gmock.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace user_hal_helper {
+
+namespace {
+
+using testing::Eq;
+using testing::Gt;
+using testing::IsNull;
+using testing::NotNull;
+using testing::Pointee;
+
+constexpr int32_t INITIAL_USER_INFO = static_cast<int32_t>(VehicleProperty::INITIAL_USER_INFO);
+constexpr int32_t SWITCH_USER = static_cast<int32_t>(VehicleProperty::SWITCH_USER);
+constexpr int32_t CREATE_USER = static_cast<int32_t>(VehicleProperty::CREATE_USER);
+constexpr int32_t REMOVE_USER = static_cast<int32_t>(VehicleProperty::REMOVE_USER);
+constexpr int32_t USER_IDENTIFICATION_ASSOCIATION =
+        static_cast<int32_t>(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION);
+
+constexpr int32_t FIRST_BOOT_AFTER_OTA =
+        static_cast<int32_t>(InitialUserInfoRequestType::FIRST_BOOT_AFTER_OTA);
+constexpr int32_t LEGACY_ANDROID_SWITCH =
+        static_cast<int32_t>(SwitchUserMessageType::LEGACY_ANDROID_SWITCH);
+constexpr int32_t VEHICLE_REQUEST = static_cast<int32_t>(SwitchUserMessageType::VEHICLE_REQUEST);
+
+constexpr int32_t GUEST_USER = static_cast<int32_t>(UserFlags::GUEST);
+constexpr int32_t NONE_USER = static_cast<int32_t>(UserFlags::NONE);
+constexpr int32_t SYSTEM_USER = static_cast<int32_t>(UserFlags::SYSTEM);
+
+constexpr int32_t USER_ID_ASSOC_KEY_FOB =
+        static_cast<int32_t>(UserIdentificationAssociationType::KEY_FOB);
+constexpr int32_t USER_ID_ASSOC_CUSTOM_1 =
+        static_cast<int32_t>(UserIdentificationAssociationType::CUSTOM_1);
+
+constexpr int32_t USER_ID_ASSOC_SET_CURRENT_USER =
+        static_cast<int32_t>(UserIdentificationAssociationSetValue::ASSOCIATE_CURRENT_USER);
+constexpr int32_t USER_ID_ASSOC_UNSET_CURRENT_USER =
+        static_cast<int32_t>(UserIdentificationAssociationSetValue::DISASSOCIATE_CURRENT_USER);
+
+constexpr int32_t USER_ID_ASSOC_CURRENT_USER =
+        static_cast<int32_t>(UserIdentificationAssociationValue::ASSOCIATED_CURRENT_USER);
+constexpr int32_t USER_ID_ASSOC_NO_USER =
+        static_cast<int32_t>(UserIdentificationAssociationValue::NOT_ASSOCIATED_ANY_USER);
+
+}  // namespace
+
+TEST(UserHalHelperTest, TestToInitialUserInfoRequest) {
+    VehiclePropValue propValue{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, SYSTEM_USER,
+                                      10, NONE_USER}},
+    };
+    InitialUserInfoRequest expected{
+            .requestId = 23,
+            .requestType = InitialUserInfoRequestType::FIRST_BOOT_AFTER_OTA,
+            .usersInfo = {{10, UserFlags::NONE},
+                          2,
+                          {{0, UserFlags::SYSTEM}, {10, UserFlags::NONE}}},
+    };
+
+    auto actual = toInitialUserInfoRequest(propValue);
+
+    ASSERT_TRUE(actual.ok()) << actual.error().message();
+    EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestFailsToInitialUserInfoRequestWithMismatchingPropType) {
+    VehiclePropValue propValue{
+            .prop = INT32_MAX,
+            .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, SYSTEM_USER,
+                                      10, NONE_USER}},
+    };
+
+    auto actual = toInitialUserInfoRequest(propValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type";
+}
+
+TEST(UserHalHelperTest, TestFailsToInitialUserInfoRequestWithInvalidRequestType) {
+    VehiclePropValue propValue{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, INT32_MAX, 10, NONE_USER, 2, 0, SYSTEM_USER, 10,
+                                      NONE_USER}},
+    };
+
+    auto actual = toInitialUserInfoRequest(propValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on invalid request type";
+}
+
+TEST(UserHalHelperTest, TestFailsToInitialUserInfoRequestWithInvalidUserFlag) {
+    VehiclePropValue propValue{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, SYSTEM_USER,
+                                      10, INT32_MAX}},
+    };
+
+    auto actual = toInitialUserInfoRequest(propValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on invalid user flags";
+}
+
+TEST(UserHalHelperTest, TestFailsToInitialUserInfoRequestWithIncompleteUsersInfo) {
+    VehiclePropValue propValueMissingSecondUserInfo{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0,
+                                      SYSTEM_USER /*Missing 2nd UserInfo*/}},
+    };
+
+    auto actual = toInitialUserInfoRequest(propValueMissingSecondUserInfo);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing second user info";
+
+    VehiclePropValue propValueMissingUsersInfo{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, /*Missing UsersInfo*/}},
+    };
+
+    actual = toInitialUserInfoRequest(propValueMissingUsersInfo);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing users info";
+}
+
+TEST(UserHalHelperTest, TestToSwitchUserRequest) {
+    VehiclePropValue propValue{
+            .prop = SWITCH_USER,
+            .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, 0, SYSTEM_USER, 10, NONE_USER, 2,
+                                      0, SYSTEM_USER, 10, NONE_USER}},
+    };
+    SwitchUserRequest expected{
+            .requestId = 23,
+            .messageType = SwitchUserMessageType::LEGACY_ANDROID_SWITCH,
+            .targetUser = {0, UserFlags::SYSTEM},
+            .usersInfo = {{10, UserFlags::NONE},
+                          2,
+                          {{0, UserFlags::SYSTEM}, {10, UserFlags::NONE}}},
+    };
+
+    auto actual = toSwitchUserRequest(propValue);
+
+    ASSERT_TRUE(actual.ok()) << actual.error().message();
+    EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestFailsToSwitchUserRequestWithMismatchingPropType) {
+    VehiclePropValue propValue{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, 0, SYSTEM_USER, 10, NONE_USER, 2,
+                                      0, SYSTEM_USER, 10, NONE_USER}},
+    };
+
+    auto actual = toSwitchUserRequest(propValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type";
+}
+
+TEST(UserHalHelperTest, TestFailsToSwitchUserRequestWithInvalidMessageType) {
+    VehiclePropValue propValueIncompatibleMessageType{
+            .prop = SWITCH_USER,
+            .value = {.int32Values = {23, VEHICLE_REQUEST, 0, SYSTEM_USER, 10, NONE_USER, 2, 0,
+                                      SYSTEM_USER, 10, NONE_USER}},
+    };
+
+    auto actual = toSwitchUserRequest(propValueIncompatibleMessageType);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on incompatible message type";
+
+    VehiclePropValue propValueInvalidMessageType{
+            .prop = SWITCH_USER,
+            .value = {.int32Values = {23, INT32_MAX, 0, SYSTEM_USER, 10, NONE_USER, 2, 0,
+                                      SYSTEM_USER, 10, NONE_USER}},
+    };
+
+    actual = toSwitchUserRequest(propValueInvalidMessageType);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on invalid message type";
+}
+
+TEST(UserHalHelperTest, TestFailsToSwitchUserRequestWithIncompleteUsersInfo) {
+    VehiclePropValue propValueMissingSecondUserInfo{
+            .prop = SWITCH_USER,
+            .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, 0, SYSTEM_USER, 10, NONE_USER, 2,
+                                      0, SYSTEM_USER,
+                                      /*Missing 2nd UserInfo*/}},
+    };
+
+    auto actual = toSwitchUserRequest(propValueMissingSecondUserInfo);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing second user info";
+
+    VehiclePropValue propValueMissingUsersInfo{
+            .prop = SWITCH_USER,
+            .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, 0, SYSTEM_USER,
+                                      /*Missing UsersInfo*/}},
+    };
+
+    actual = toSwitchUserRequest(propValueMissingUsersInfo);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing users info";
+
+    VehiclePropValue propValueMissingTargetUser{
+            .prop = SWITCH_USER,
+            .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, /*Missing target UserInfo*/}},
+    };
+
+    actual = toSwitchUserRequest(propValueMissingTargetUser);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing target user info";
+}
+
+TEST(UserHalHelperTest, TestToCreateUserRequest) {
+    VehiclePropValue propValue{
+            .prop = CREATE_USER,
+            .value = {.int32Values = {23, 11, GUEST_USER, 10, NONE_USER, 2, 0, SYSTEM_USER, 10,
+                                      NONE_USER},
+                      .stringValue = "Guest11"},
+    };
+    CreateUserRequest expected{
+            .requestId = 23,
+            .newUserInfo = {11, UserFlags::GUEST},
+            .newUserName = "Guest11",
+            .usersInfo = {{10, UserFlags::NONE},
+                          2,
+                          {{0, UserFlags::SYSTEM}, {10, UserFlags::NONE}}},
+    };
+
+    auto actual = toCreateUserRequest(propValue);
+
+    ASSERT_TRUE(actual.ok()) << actual.error().message();
+    EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestFailsToCreateUserRequestWithMismatchingPropType) {
+    VehiclePropValue propValue{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, 11, GUEST_USER, 10, NONE_USER, 2, 0, SYSTEM_USER, 10,
+                                      NONE_USER},
+                      .stringValue = "Guest11"},
+    };
+
+    auto actual = toCreateUserRequest(propValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type";
+}
+
+TEST(UserHalHelperTest, TestFailsToCreateUserRequestWithIncompleteUsersInfo) {
+    VehiclePropValue propValueMissingSecondUserInfo{
+            .prop = CREATE_USER,
+            .value = {.int32Values = {23, 11, GUEST_USER, 10, NONE_USER, 2, 0,
+                                      SYSTEM_USER /*Missing 2nd UserInfo*/},
+                      .stringValue = "Guest11"},
+    };
+
+    auto actual = toCreateUserRequest(propValueMissingSecondUserInfo);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing second user info";
+
+    VehiclePropValue propValueMissingUsersInfo{
+            .prop = CREATE_USER,
+            .value = {.int32Values = {23, 11, GUEST_USER, /*Missing UsersInfo*/},
+                      .stringValue = "Guest11"},
+    };
+
+    actual = toCreateUserRequest(propValueMissingUsersInfo);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing users info";
+
+    VehiclePropValue propValueMissingCreateUserInfo{
+            .prop = CREATE_USER,
+            .value = {.int32Values = {23, /*Missing create UserInfo*/}, .stringValue = "Guest11"},
+    };
+
+    actual = toCreateUserRequest(propValueMissingCreateUserInfo);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing create user info";
+}
+
+TEST(UserHalHelperTest, TestToRemoveUserRequest) {
+    VehiclePropValue propValue{
+            .prop = REMOVE_USER,
+            .value = {.int32Values = {23, 10, NONE_USER, 10, NONE_USER, 2, 0, SYSTEM_USER, 10,
+                                      NONE_USER}},
+    };
+    RemoveUserRequest expected{
+            .requestId = 23,
+            .removedUserInfo = {10, UserFlags::NONE},
+            .usersInfo = {{10, UserFlags::NONE},
+                          2,
+                          {{0, UserFlags::SYSTEM}, {10, UserFlags::NONE}}},
+    };
+
+    auto actual = toRemoveUserRequest(propValue);
+
+    ASSERT_TRUE(actual.ok()) << actual.error().message();
+    EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestFailsToRemoveUserRequestWithMismatchingPropType) {
+    VehiclePropValue propValue{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, 10, NONE_USER, 10, NONE_USER, 2, 0, SYSTEM_USER, 10,
+                                      NONE_USER}},
+    };
+
+    auto actual = toRemoveUserRequest(propValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type";
+}
+
+TEST(UserHalHelperTest, TestFailsToRemoveUserRequestWithIncompleteUsersInfo) {
+    VehiclePropValue propValueMissingSecondUserInfo{
+            .prop = REMOVE_USER,
+            .value = {.int32Values = {23, 10, NONE_USER, 10, NONE_USER, 2, 0,
+                                      SYSTEM_USER /*Missing 2nd UserInfo*/}},
+    };
+
+    auto actual = toRemoveUserRequest(propValueMissingSecondUserInfo);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing second user info";
+
+    VehiclePropValue propValueMissingUsersInfo{
+            .prop = REMOVE_USER,
+            .value = {.int32Values = {23, 10, NONE_USER, /*Missing UsersInfo*/}},
+    };
+
+    actual = toRemoveUserRequest(propValueMissingUsersInfo);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing users info";
+
+    VehiclePropValue propValueMissingRemoveUserInfo{
+            .prop = REMOVE_USER,
+            .value = {.int32Values = {23, /*Missing remove UserInfo*/}},
+    };
+
+    actual = toRemoveUserRequest(propValueMissingRemoveUserInfo);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing remove user info";
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequest) {
+    VehiclePropValue propValue{
+            .prop = USER_IDENTIFICATION_ASSOCIATION,
+            .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB,
+                                      USER_ID_ASSOC_CUSTOM_1}},
+    };
+    UserIdentificationGetRequest expected{
+            .requestId = 23,
+            .userInfo = {10, UserFlags::NONE},
+            .numberAssociationTypes = 2,
+            .associationTypes = {UserIdentificationAssociationType::KEY_FOB,
+                                 UserIdentificationAssociationType::CUSTOM_1},
+    };
+
+    auto actual = toUserIdentificationGetRequest(propValue);
+
+    ASSERT_TRUE(actual.ok()) << actual.error().message();
+    EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequestWithMismatchingPropType) {
+    VehiclePropValue propValue{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB,
+                                      USER_ID_ASSOC_CUSTOM_1}},
+    };
+
+    auto actual = toUserIdentificationGetRequest(propValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type";
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequestWithInvalidAssociationTypes) {
+    VehiclePropValue propValue{
+            .prop = USER_IDENTIFICATION_ASSOCIATION,
+            .value = {.int32Values = {23, 10, NONE_USER, 1, INT32_MAX}},
+    };
+
+    auto actual = toUserIdentificationGetRequest(propValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on invalid association type";
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequestWithIncompleteAssociationTypes) {
+    VehiclePropValue propValueMissingSecondAssociationType{
+            .prop = USER_IDENTIFICATION_ASSOCIATION,
+            .value = {.int32Values = {23, 10, NONE_USER, 2,
+                                      USER_ID_ASSOC_KEY_FOB /*Missing 2nd association type*/}},
+    };
+
+    auto actual = toUserIdentificationGetRequest(propValueMissingSecondAssociationType);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing second association type";
+
+    VehiclePropValue propValueMissingNumberAssociationTypes{
+            .prop = USER_IDENTIFICATION_ASSOCIATION,
+            .value = {.int32Values = {23, 10, NONE_USER, /*Missing number association types*/}},
+    };
+
+    actual = toUserIdentificationGetRequest(propValueMissingNumberAssociationTypes);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing number association types";
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequestWithMissingUserInfo) {
+    VehiclePropValue propValue{
+            .prop = USER_IDENTIFICATION_ASSOCIATION,
+            .value = {.int32Values = {23, /*Missing user info*/}},
+    };
+
+    auto actual = toUserIdentificationGetRequest(propValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing UserInfo";
+}
+
+TEST(UserHalHelperTest, TestToUserIdentificationSetRequest) {
+    VehiclePropValue propValue{
+            .prop = USER_IDENTIFICATION_ASSOCIATION,
+            .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB,
+                                      USER_ID_ASSOC_SET_CURRENT_USER, USER_ID_ASSOC_CUSTOM_1,
+                                      USER_ID_ASSOC_UNSET_CURRENT_USER}},
+    };
+    UserIdentificationSetRequest expected{
+            .requestId = 23,
+            .userInfo = {10, UserFlags::NONE},
+            .numberAssociations = 2,
+            .associations = {{UserIdentificationAssociationType::KEY_FOB,
+                              UserIdentificationAssociationSetValue::ASSOCIATE_CURRENT_USER},
+                             {UserIdentificationAssociationType::CUSTOM_1,
+                              UserIdentificationAssociationSetValue::DISASSOCIATE_CURRENT_USER}},
+    };
+
+    auto actual = toUserIdentificationSetRequest(propValue);
+
+    ASSERT_TRUE(actual.ok()) << actual.error().message();
+    EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationSetRequestWithMismatchingPropType) {
+    VehiclePropValue propValue{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB,
+                                      USER_ID_ASSOC_SET_CURRENT_USER, USER_ID_ASSOC_CUSTOM_1,
+                                      USER_ID_ASSOC_UNSET_CURRENT_USER}},
+    };
+
+    auto actual = toUserIdentificationSetRequest(propValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type";
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationSetRequestWithInvalidAssociations) {
+    VehiclePropValue propValueInvalidAssociationType{
+            .prop = USER_IDENTIFICATION_ASSOCIATION,
+            .value = {.int32Values = {23, 10, NONE_USER, 1, INT32_MAX,
+                                      USER_ID_ASSOC_SET_CURRENT_USER}},
+    };
+
+    auto actual = toUserIdentificationSetRequest(propValueInvalidAssociationType);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on invalid association type";
+
+    VehiclePropValue propValueInvalidAssociationValue{
+            .prop = USER_IDENTIFICATION_ASSOCIATION,
+            .value = {.int32Values = {23, 10, NONE_USER, USER_ID_ASSOC_KEY_FOB, INT32_MAX}},
+    };
+
+    actual = toUserIdentificationSetRequest(propValueInvalidAssociationValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing number association types";
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationSetRequestWithIncompleteAssociations) {
+    VehiclePropValue propValueMissingSecondAssociationType{
+            .prop = USER_IDENTIFICATION_ASSOCIATION,
+            .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB,
+                                      USER_ID_ASSOC_SET_CURRENT_USER,
+                                      /*Missing 2nd association*/}},
+    };
+
+    auto actual = toUserIdentificationSetRequest(propValueMissingSecondAssociationType);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing second association type";
+
+    VehiclePropValue propValueMissingNumberAssociationTypes{
+            .prop = USER_IDENTIFICATION_ASSOCIATION,
+            .value = {.int32Values = {23, 10, NONE_USER, /*Missing number associations*/}},
+    };
+
+    actual = toUserIdentificationSetRequest(propValueMissingNumberAssociationTypes);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing number association types";
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationSetRequestWithMissingUserInfo) {
+    VehiclePropValue propValue{
+            .prop = USER_IDENTIFICATION_ASSOCIATION,
+            .value = {.int32Values = {23, /*Missing user info*/}},
+    };
+
+    auto actual = toUserIdentificationSetRequest(propValue);
+
+    EXPECT_FALSE(actual.ok()) << "No error returned on missing UserInfo";
+}
+
+TEST(UserHalHelperTest, TestSwitchUserRequestToVehiclePropValue) {
+    SwitchUserRequest request{
+            .requestId = 23,
+            .messageType = SwitchUserMessageType::VEHICLE_REQUEST,
+            .targetUser = {11, UserFlags::GUEST},
+    };
+    VehiclePropValue expected{
+            .prop = SWITCH_USER,
+            .value = {.int32Values = {23,
+                                      static_cast<int32_t>(SwitchUserMessageType::VEHICLE_REQUEST),
+                                      11}},
+    };
+
+    auto actual = toVehiclePropValue(request);
+
+    ASSERT_THAT(actual, NotNull());
+    EXPECT_THAT(actual->timestamp, Gt(0));
+    // Don't rely on real timestamp in tests as the expected and actual objects won't have the same
+    // timestamps. Thus remove the timestamps before comparing them.
+    actual->timestamp = 0;
+    EXPECT_THAT(actual, Pointee(Eq(expected)));
+}
+
+TEST(UserHalHelperTest, TestFailsSwitchUserRequestToVehiclePropValueWithIncompatibleMessageType) {
+    SwitchUserRequest request{
+            .requestId = 23,
+            .messageType = SwitchUserMessageType::VEHICLE_RESPONSE,
+            .targetUser = {11, UserFlags::GUEST},
+    };
+
+    auto actual = toVehiclePropValue(request);
+
+    EXPECT_THAT(actual, IsNull());
+}
+
+TEST(UserHalHelperTest, TestInitialUserInfoResponseToVehiclePropValue) {
+    InitialUserInfoResponse response{
+            .requestId = 23,
+            .action = InitialUserInfoResponseAction::CREATE,
+            .userToSwitchOrCreate = {11, UserFlags::GUEST},
+            .userLocales = "en-US,pt-BR",
+            .userNameToCreate = "Owner",
+    };
+    VehiclePropValue expected{
+            .prop = INITIAL_USER_INFO,
+            .value = {.int32Values = {23,
+                                      static_cast<int32_t>(InitialUserInfoResponseAction::CREATE),
+                                      11, GUEST_USER},
+                      .stringValue = "en-US,pt-BR||Owner"},
+    };
+
+    auto actual = toVehiclePropValue(response);
+
+    ASSERT_THAT(actual, NotNull());
+    EXPECT_THAT(actual->timestamp, Gt(0));
+    actual->timestamp = 0;
+    EXPECT_THAT(actual, Pointee(Eq(expected)));
+}
+
+TEST(UserHalHelperTest, TestSwitchUserResponseToVehiclePropValue) {
+    SwitchUserResponse response{
+            .requestId = 23,
+            .messageType = SwitchUserMessageType::VEHICLE_RESPONSE,
+            .status = SwitchUserStatus::FAILURE,
+            .errorMessage = "random error",
+    };
+    VehiclePropValue expected{
+            .prop = SWITCH_USER,
+            .value = {.int32Values = {23,
+                                      static_cast<int32_t>(SwitchUserMessageType::VEHICLE_RESPONSE),
+                                      static_cast<int32_t>(SwitchUserStatus::FAILURE)},
+                      .stringValue = "random error"},
+    };
+
+    auto actual = toVehiclePropValue(response);
+
+    ASSERT_THAT(actual, NotNull());
+    EXPECT_THAT(actual->timestamp, Gt(0));
+    actual->timestamp = 0;
+    EXPECT_THAT(actual, Pointee(Eq(expected)));
+}
+
+TEST(UserHalHelperTest, TestCreateUserResponseToVehiclePropValue) {
+    CreateUserResponse response{
+            .requestId = 23,
+            .status = CreateUserStatus::FAILURE,
+            .errorMessage = "random error",
+    };
+    VehiclePropValue expected{
+            .prop = CREATE_USER,
+            .value = {.int32Values = {23, static_cast<int32_t>(CreateUserStatus::FAILURE)},
+                      .stringValue = "random error"},
+    };
+
+    auto actual = toVehiclePropValue(response);
+
+    ASSERT_THAT(actual, NotNull());
+    EXPECT_THAT(actual->timestamp, Gt(0));
+    actual->timestamp = 0;
+    EXPECT_THAT(actual, Pointee(Eq(expected)));
+}
+
+TEST(UserHalHelperTest, TestUserIdentificationResponseToVehiclePropValue) {
+    UserIdentificationResponse response{
+            .requestId = 23,
+            .numberAssociation = 2,
+            .associations = {{UserIdentificationAssociationType::KEY_FOB,
+                              UserIdentificationAssociationValue::ASSOCIATED_CURRENT_USER},
+                             {UserIdentificationAssociationType::CUSTOM_1,
+                              UserIdentificationAssociationValue::NOT_ASSOCIATED_ANY_USER}},
+            .errorMessage = "random error",
+    };
+    VehiclePropValue expected{
+            .prop = USER_IDENTIFICATION_ASSOCIATION,
+            .value = {.int32Values = {23, 2, USER_ID_ASSOC_KEY_FOB, USER_ID_ASSOC_CURRENT_USER,
+                                      USER_ID_ASSOC_CUSTOM_1, USER_ID_ASSOC_NO_USER},
+                      .stringValue = "random error"},
+    };
+
+    auto actual = toVehiclePropValue(response);
+
+    ASSERT_THAT(actual, NotNull());
+    EXPECT_THAT(actual->timestamp, Gt(0));
+    actual->timestamp = 0;
+    EXPECT_THAT(actual, Pointee(Eq(expected)));
+}
+
+}  // namespace user_hal_helper
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/bluetooth/audio/2.0/default/session/BluetoothAudioSupportedCodecsDB.cpp b/bluetooth/audio/2.0/default/session/BluetoothAudioSupportedCodecsDB.cpp
index 6ea61e1..c368197 100644
--- a/bluetooth/audio/2.0/default/session/BluetoothAudioSupportedCodecsDB.cpp
+++ b/bluetooth/audio/2.0/default/session/BluetoothAudioSupportedCodecsDB.cpp
@@ -74,7 +74,7 @@
     .objectType = AacObjectType::MPEG2_LC,
     .sampleRate = SampleRate::RATE_44100,
     .channelMode = ChannelMode::STEREO,
-    .variableBitRateEnabled = AacVariableBitRate::DISABLED,
+    .variableBitRateEnabled = AacVariableBitRate::ENABLED,
     .bitsPerSample = BitsPerSample::BITS_16};
 
 // LDAC: mSampleRate:(44100|48000|88200|96000), mBitsPerSample:(16|24|32),
diff --git a/boot/1.0/default/Android.bp b/boot/1.0/default/Android.bp
index fdf7a1e..e6d46be 100644
--- a/boot/1.0/default/Android.bp
+++ b/boot/1.0/default/Android.bp
@@ -30,6 +30,13 @@
         "libhidlbase",
         "libutils",
         "android.hardware.boot@1.0",
+        "libhwbinder",
     ],
-
+    arch: {
+        arm: {
+            cflags: [
+                "-DARCH_ARM_32"
+            ],
+        },
+    },
 }
diff --git a/boot/1.0/default/service.cpp b/boot/1.0/default/service.cpp
index f3996ef..2b50740 100644
--- a/boot/1.0/default/service.cpp
+++ b/boot/1.0/default/service.cpp
@@ -17,10 +17,14 @@
 
 #include <android/hardware/boot/1.0/IBootControl.h>
 #include <hidl/LegacySupport.h>
+#include <hwbinder/ProcessState.h>
 
 using ::android::hardware::boot::V1_0::IBootControl;
 using android::hardware::defaultPassthroughServiceImplementation;
 
 int main (int /* argc */, char * /* argv */ []) {
+#ifdef ARCH_ARM_32
+    android::hardware::ProcessState::initWithMmapSize((size_t)8192);
+#endif
     return defaultPassthroughServiceImplementation<IBootControl>();
 }
diff --git a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
index d170a6d..694d52a 100644
--- a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
+++ b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
@@ -116,7 +116,10 @@
 };
 
 static void printSkipped(std::string msg) {
-    std::cout << "[  SKIPPED ] " << msg << std::endl;
+    const auto testInfo = testing::UnitTest::GetInstance()->current_test_info();
+    std::cout << "[  SKIPPED ] " << testInfo->test_case_name() << "." << testInfo->name()
+              << std::endl;
+    std::cout << msg << std::endl;
 }
 
 MATCHER_P(InfoHasId, id,
@@ -428,8 +431,9 @@
     ProgramInfo infoCb = {};
     EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged_,
                         InfoHasId(utils::make_identifier(IdentifierType::AMFM_FREQUENCY, freq)))
-        .Times(AnyNumber())
-        .WillOnce(DoAll(SaveArg<0>(&infoCb), testing::Return(ByMove(Void()))));
+            .Times(AnyNumber())
+            .WillOnce(DoAll(SaveArg<0>(&infoCb), testing::Return(ByMove(Void()))))
+            .WillRepeatedly(testing::InvokeWithoutArgs([] { return Void(); }));
     auto result = mSession->tune(sel);
 
     // expect a failure if it's not supported
diff --git a/camera/common/1.0/default/CameraModule.cpp b/camera/common/1.0/default/CameraModule.cpp
index 86f26e4..188b4be 100644
--- a/camera/common/1.0/default/CameraModule.cpp
+++ b/camera/common/1.0/default/CameraModule.cpp
@@ -267,6 +267,22 @@
     return res;
 }
 
+int CameraModule::getCameraDeviceVersion(int cameraId, uint32_t* version) {
+    ATRACE_CALL();
+    int ret;
+    if (getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_5 &&
+            mModule->get_camera_device_version != NULL) {
+        ret = mModule->get_camera_device_version(cameraId, version);
+    } else {
+        struct camera_info info;
+        ret = getCameraInfo(cameraId, &info);
+        if (ret == OK) {
+            *version = info.device_version;
+        }
+    }
+    return ret;
+}
+
 int CameraModule::getCameraInfo(int cameraId, struct camera_info *info) {
     ATRACE_CALL();
     Mutex::Autolock lock(mCameraInfoLock);
@@ -367,11 +383,9 @@
 int CameraModule::getDeviceVersion(int cameraId) {
     ssize_t index = mDeviceVersionMap.indexOfKey(cameraId);
     if (index == NAME_NOT_FOUND) {
-        int deviceVersion;
+        uint32_t deviceVersion;
         if (getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_0) {
-            struct camera_info info;
-            getCameraInfo(cameraId, &info);
-            deviceVersion = info.device_version;
+            getCameraDeviceVersion(cameraId, &deviceVersion);
         } else {
             deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
         }
@@ -529,24 +543,28 @@
 }
 
 void CameraModule::removeCamera(int cameraId) {
-    std::unordered_set<std::string> physicalIds;
-    camera_metadata_t *metadata = const_cast<camera_metadata_t*>(
-            mCameraInfoMap.valueFor(cameraId).static_camera_characteristics);
-    common::V1_0::helper::CameraMetadata hidlMetadata(metadata);
+    // Skip HAL1 devices which isn't cached in mCameraInfoMap and don't advertise
+    // static_camera_characteristics
+    if (getDeviceVersion(cameraId) >= CAMERA_DEVICE_API_VERSION_3_0) {
+        std::unordered_set<std::string> physicalIds;
+        camera_metadata_t *metadata = const_cast<camera_metadata_t*>(
+                mCameraInfoMap.valueFor(cameraId).static_camera_characteristics);
+        common::V1_0::helper::CameraMetadata hidlMetadata(metadata);
 
-    if (isLogicalMultiCamera(hidlMetadata, &physicalIds)) {
-        for (const auto& id : physicalIds) {
-            int idInt = std::stoi(id);
-            if (mPhysicalCameraInfoMap.indexOfKey(idInt) >= 0) {
-                free_camera_metadata(mPhysicalCameraInfoMap[idInt]);
-                mPhysicalCameraInfoMap.removeItem(idInt);
-            } else {
-                ALOGE("%s: Cannot find corresponding static metadata for physical id %s",
-                        __FUNCTION__, id.c_str());
+        if (isLogicalMultiCamera(hidlMetadata, &physicalIds)) {
+            for (const auto& id : physicalIds) {
+                int idInt = std::stoi(id);
+                if (mPhysicalCameraInfoMap.indexOfKey(idInt) >= 0) {
+                    free_camera_metadata(mPhysicalCameraInfoMap[idInt]);
+                    mPhysicalCameraInfoMap.removeItem(idInt);
+                } else {
+                    ALOGE("%s: Cannot find corresponding static metadata for physical id %s",
+                            __FUNCTION__, id.c_str());
+                }
             }
         }
     }
-    free_camera_metadata(metadata);
+
     mCameraInfoMap.removeItem(cameraId);
     mDeviceVersionMap.removeItem(cameraId);
 }
diff --git a/camera/common/1.0/default/include/CameraModule.h b/camera/common/1.0/default/include/CameraModule.h
index c89e934..8195835 100644
--- a/camera/common/1.0/default/include/CameraModule.h
+++ b/camera/common/1.0/default/include/CameraModule.h
@@ -49,6 +49,7 @@
     // Returns OK on success, NO_INIT on failure
     int init();
 
+    int getCameraDeviceVersion(int cameraId, uint32_t* version);
     int getCameraInfo(int cameraId, struct camera_info *info);
     int getDeviceVersion(int cameraId);
     int getNumberOfCameras(void);
diff --git a/camera/device/1.0/default/Android.bp b/camera/device/1.0/default/Android.bp
index da70577..f407476 100644
--- a/camera/device/1.0/default/Android.bp
+++ b/camera/device/1.0/default/Android.bp
@@ -10,6 +10,7 @@
         "libhidlmemory",
         "libutils",
         "android.hardware.camera.device@1.0",
+        "vendor.qti.hardware.camera.device@1.0",
         "android.hardware.camera.common@1.0",
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.mapper@2.0",
@@ -31,4 +32,8 @@
         "media_plugin_headers",
     ],
     export_include_dirs: ["."],
+    // Since this platform module has been forked to depend on a vendor
+    // proprietary library, we exclude it from the vendor snapshot so that it
+    // will be built from source as part of the vendor build.
+    exclude_from_vendor_snapshot: true,
 }
diff --git a/camera/device/1.0/default/CameraDevice.cpp b/camera/device/1.0/default/CameraDevice.cpp
index 2dd6094..9b6e4b9 100644
--- a/camera/device/1.0/default/CameraDevice.cpp
+++ b/camera/device/1.0/default/CameraDevice.cpp
@@ -430,30 +430,68 @@
              index, mem->mNumBufs);
         return;
     }
-    if (object->mDeviceCallback != nullptr) {
-        CameraFrameMetadata hidlMetadata;
-        if (metadata) {
-            hidlMetadata.faces.resize(metadata->number_of_faces);
-            for (size_t i = 0; i < hidlMetadata.faces.size(); i++) {
-                hidlMetadata.faces[i].score = metadata->faces[i].score;
-                hidlMetadata.faces[i].id = metadata->faces[i].id;
-                for (int k = 0; k < 4; k++) {
-                    hidlMetadata.faces[i].rect[k] = metadata->faces[i].rect[k];
-                }
-                for (int k = 0; k < 2; k++) {
-                    hidlMetadata.faces[i].leftEye[k] = metadata->faces[i].left_eye[k];
-                }
-                for (int k = 0; k < 2; k++) {
-                    hidlMetadata.faces[i].rightEye[k] = metadata->faces[i].right_eye[k];
-                }
-                for (int k = 0; k < 2; k++) {
-                    hidlMetadata.faces[i].mouth[k] = metadata->faces[i].mouth[k];
-                }
-            }
-        }
-        CameraHeapMemory* mem = static_cast<CameraHeapMemory *>(data->handle);
-        object->mDeviceCallback->dataCallback(
-                (DataCallbackMsg) msg_type, mem->handle.mId, index, hidlMetadata);
+    if(object->mQDeviceCallback != nullptr) {
+         vendor::qti::hardware::camera::device::V1_0::QCameraFrameMetadata hidlMetadata;
+         if (metadata) {
+             hidlMetadata.faces.resize(metadata->number_of_faces);
+             for (size_t i = 0; i < hidlMetadata.faces.size(); i++) {
+                 hidlMetadata.faces[i].score = metadata->faces[i].score;
+                 hidlMetadata.faces[i].id = metadata->faces[i].id;
+                 for (int k = 0; k < 4; k++) {
+                     hidlMetadata.faces[i].rect[k] = metadata->faces[i].rect[k];
+                 }
+                 for (int k = 0; k < 2; k++) {
+                     hidlMetadata.faces[i].leftEye[k] = metadata->faces[i].left_eye[k];
+                 }
+                 for (int k = 0; k < 2; k++) {
+                     hidlMetadata.faces[i].rightEye[k] = metadata->faces[i].right_eye[k];
+                 }
+                 for (int k = 0; k < 2; k++) {
+                     hidlMetadata.faces[i].mouth[k] = metadata->faces[i].mouth[k];
+                 }
+                 hidlMetadata.faces[i].smile_degree = metadata->faces[i].smile_degree;
+                 hidlMetadata.faces[i].smile_score = metadata->faces[i].smile_score;
+                 hidlMetadata.faces[i].blink_detected = metadata->faces[i].blink_detected;
+                 hidlMetadata.faces[i].face_recognised = metadata->faces[i].face_recognised;
+                 hidlMetadata.faces[i].gaze_angle = metadata->faces[i].gaze_angle;
+                 hidlMetadata.faces[i].updown_dir = metadata->faces[i].updown_dir;
+                 hidlMetadata.faces[i].leftright_dir = metadata->faces[i].leftright_dir;
+                 hidlMetadata.faces[i].roll_dir = metadata->faces[i].roll_dir;
+                 hidlMetadata.faces[i].left_right_gaze = metadata->faces[i].left_right_gaze;
+                 hidlMetadata.faces[i].top_bottom_gaze = metadata->faces[i].top_bottom_gaze;
+                 hidlMetadata.faces[i].leye_blink = metadata->faces[i].leye_blink;
+                 hidlMetadata.faces[i].reye_blink = metadata->faces[i].reye_blink;
+             }
+         }
+         CameraHeapMemory* mem = static_cast<CameraHeapMemory *>(data->handle);
+         object->mQDeviceCallback->QDataCallback(
+                 (DataCallbackMsg) msg_type, mem->handle.mId, index, hidlMetadata);
+    } else {
+       if (object->mDeviceCallback != nullptr) {
+           CameraFrameMetadata hidlMetadata;
+           if (metadata) {
+               hidlMetadata.faces.resize(metadata->number_of_faces);
+               for (size_t i = 0; i < hidlMetadata.faces.size(); i++) {
+                   hidlMetadata.faces[i].score = metadata->faces[i].score;
+                   hidlMetadata.faces[i].id = metadata->faces[i].id;
+                   for (int k = 0; k < 4; k++) {
+                       hidlMetadata.faces[i].rect[k] = metadata->faces[i].rect[k];
+                   }
+                   for (int k = 0; k < 2; k++) {
+                       hidlMetadata.faces[i].leftEye[k] = metadata->faces[i].left_eye[k];
+                   }
+                   for (int k = 0; k < 2; k++) {
+                       hidlMetadata.faces[i].rightEye[k] = metadata->faces[i].right_eye[k];
+                   }
+                   for (int k = 0; k < 2; k++) {
+                       hidlMetadata.faces[i].mouth[k] = metadata->faces[i].mouth[k];
+                   }
+               }
+           }
+           CameraHeapMemory* mem = static_cast<CameraHeapMemory *>(data->handle);
+           object->mDeviceCallback->dataCallback(
+                   (DataCallbackMsg) msg_type, mem->handle.mId, index, hidlMetadata);
+       }
     }
 }
 
@@ -669,6 +707,11 @@
 
     initHalPreviewWindow();
     mDeviceCallback = callback;
+    mQDeviceCallback =
+        vendor::qti::hardware::camera::device::V1_0::IQCameraDeviceCallback::castFrom(callback);
+    if(mQDeviceCallback == nullptr) {
+        ALOGI("could not cast ICameraDeviceCallback to IQCameraDeviceCallback");
+    }
 
     if (mDevice->ops->set_callbacks) {
         mDevice->ops->set_callbacks(mDevice,
diff --git a/camera/device/1.0/default/CameraDevice_1_0.h b/camera/device/1.0/default/CameraDevice_1_0.h
index 2c980f0..e5a194e 100644
--- a/camera/device/1.0/default/CameraDevice_1_0.h
+++ b/camera/device/1.0/default/CameraDevice_1_0.h
@@ -24,6 +24,7 @@
 #include "HandleImporter.h"
 
 #include <android/hardware/camera/device/1.0/ICameraDevice.h>
+#include <vendor/qti/hardware/camera/device/1.0/IQCameraDeviceCallback.h>
 #include <android/hidl/allocator/1.0/IAllocator.h>
 #include <android/hidl/memory/1.0/IMemory.h>
 #include <hidl/MQDescriptor.h>
@@ -44,6 +45,7 @@
 using ::android::hardware::camera::device::V1_0::CameraInfo;
 using ::android::hardware::camera::device::V1_0::CommandType;
 using ::android::hardware::camera::device::V1_0::ICameraDevice;
+using ::vendor::qti::hardware::camera::device::V1_0::IQCameraDeviceCallback;
 using ::android::hardware::camera::device::V1_0::ICameraDeviceCallback;
 using ::android::hardware::camera::device::V1_0::ICameraDevicePreviewCallback;
 using ::android::hardware::camera::device::V1_0::MemoryId;
@@ -164,6 +166,7 @@
     const SortedVector<std::pair<std::string, std::string>>& mCameraDeviceNames;
 
     sp<ICameraDeviceCallback> mDeviceCallback = nullptr;
+    sp<IQCameraDeviceCallback> mQDeviceCallback = nullptr;
 
     mutable Mutex mMemoryMapLock; // gating access to mMemoryMap
                                   // must not hold mLock after this lock is acquired
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index 99cdccb..8d3bf02 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -925,12 +925,12 @@
                     mStreamMap[id].data_space);
             mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
         } else {
-            // width/height/format must not change, but usage/rotation might need to change
+            // width/height must not change, but usage/rotation might need to change
+            // format might change and get updated with overrideFormat
             if (mStreamMap[id].stream_type !=
                     (int) requestedConfiguration.streams[i].streamType ||
                     mStreamMap[id].width != requestedConfiguration.streams[i].width ||
                     mStreamMap[id].height != requestedConfiguration.streams[i].height ||
-                    mStreamMap[id].format != (int) requestedConfiguration.streams[i].format ||
                     mStreamMap[id].data_space !=
                             mapToLegacyDataspace( static_cast<android_dataspace_t> (
                                     requestedConfiguration.streams[i].dataSpace))) {
diff --git a/camera/device/3.2/default/convert.cpp b/camera/device/3.2/default/convert.cpp
index 06ad7e9..628b7af 100644
--- a/camera/device/3.2/default/convert.cpp
+++ b/camera/device/3.2/default/convert.cpp
@@ -66,6 +66,8 @@
     dst->data_space = (android_dataspace_t) src.dataSpace;
     dst->rotation = (int) src.rotation;
     dst->usage = (uint32_t) src.usage;
+    dst->reserved[0] = NULL;
+    dst->reserved[1] = NULL;
     // Fields to be filled by HAL (max_buffers, priv) are initialized to 0
     dst->max_buffers = 0;
     dst->priv = 0;
@@ -88,6 +90,23 @@
         ALOGW("%s: Stream type %d is not currently supported!",
                 __FUNCTION__, src->stream_type);
     }
+
+    HalStream* halStream = NULL;
+    if (src->reserved[0] != NULL) {
+        halStream = (HalStream*)(src->reserved[0]);
+    } else if (src->reserved[1] != NULL) {
+        halStream = (HalStream*)(src->reserved[1]);
+    }
+
+    // Check if overrideFormat is set and honor it
+    if (halStream != NULL) {
+        dst->overrideFormat = (PixelFormat) halStream->overrideFormat;
+        if (src->stream_type == CAMERA3_STREAM_OUTPUT) {
+            dst->producerUsage = (BufferUsageFlags)halStream->producerUsage;
+        } else if (src->stream_type == CAMERA3_STREAM_INPUT) {
+            dst->consumerUsage = (BufferUsageFlags)halStream->consumerUsage;
+        }
+    }
 }
 
 void convertToHidl(const camera3_stream_configuration_t& src, HalStreamConfiguration* dst) {
diff --git a/camera/device/3.3/default/convert.cpp b/camera/device/3.3/default/convert.cpp
index dae190b..ac17d83 100644
--- a/camera/device/3.3/default/convert.cpp
+++ b/camera/device/3.3/default/convert.cpp
@@ -47,6 +47,22 @@
         ALOGW("%s: Stream type %d is not currently supported!",
                 __FUNCTION__, src->stream_type);
     }
+
+    HalStream* halStream = NULL;
+    if (src->reserved[0] != NULL) {
+        halStream = (HalStream*)(src->reserved[0]);
+    } else if (src->reserved[1] != NULL) {
+        halStream = (HalStream*)(src->reserved[1]);
+    }
+
+    if (halStream != NULL) {
+        dst->v3_2.overrideFormat  = (PixelFormat) halStream->v3_2.overrideFormat;
+        if (src->stream_type == CAMERA3_STREAM_OUTPUT) {
+            dst->v3_2.producerUsage = (BufferUsageFlags)halStream->v3_2.producerUsage;
+        } else if (src->stream_type == CAMERA3_STREAM_INPUT) {
+            dst->v3_2.consumerUsage = (BufferUsageFlags)halStream->v3_2.consumerUsage;
+        }
+    }
 }
 
 void convertToHidl(const camera3_stream_configuration_t& src, HalStreamConfiguration* dst) {
diff --git a/camera/provider/2.4/default/Android.bp b/camera/provider/2.4/default/Android.bp
index 627ddf4..24ab95e 100644
--- a/camera/provider/2.4/default/Android.bp
+++ b/camera/provider/2.4/default/Android.bp
@@ -6,6 +6,7 @@
     shared_libs: [
         "android.hardware.camera.common@1.0",
         "android.hardware.camera.device@1.0",
+        "vendor.qti.hardware.camera.device@1.0",
         "android.hardware.camera.device@3.2",
         "android.hardware.camera.device@3.3",
         "android.hardware.camera.device@3.4",
@@ -36,6 +37,10 @@
         "camera.device@3.5-impl_headers",
     ],
     export_include_dirs: ["."],
+    // Since this framework module has been forked to depend on a vendor
+    // proprietary library, we exclude this module from the vendor snapshot so
+    // that it will be built from source as part of the vendor image build.
+    exclude_from_vendor_snapshot: true,
 }
 
 cc_library_shared {
@@ -79,6 +84,10 @@
         "camera.device@3.6-external-impl_headers"
     ],
     export_include_dirs: ["."],
+    // Since this framework module has a transitive dependency  on a vendor
+    // proprietary library, we exclude this module from the vendor snapshot so
+    // that it will be built from source as part of the vendor image build.
+    exclude_from_vendor_snapshot: true,
 }
 
 cc_library_shared {
@@ -127,6 +136,10 @@
         "android.hardware.camera.common@1.0-helper",
     ],
     export_include_dirs: ["."],
+    // Since this framework module has a transitive dependency  on a vendor
+    // proprietary library, we exclude this module from the vendor snapshot so
+    // that it will be built from source as part of the vendor image build.
+    exclude_from_vendor_snapshot: true,
 }
 
 cc_defaults {
@@ -138,6 +151,7 @@
     shared_libs: [
         "android.hardware.camera.common@1.0",
         "android.hardware.camera.device@1.0",
+        "vendor.qti.hardware.camera.device@1.0",
         "android.hardware.camera.device@3.2",
         "android.hardware.camera.device@3.3",
         "android.hardware.camera.device@3.4",
@@ -164,6 +178,10 @@
         "camera.device@3.5-external-impl_headers",
         "camera.device@3.5-impl_headers",
     ],
+    // Since this framework module has been forked to depend on a vendor
+    // proprietary library, we exclude this module from the vendor snapshot so
+    // that it will be built from source as part of the vendor image build.
+    exclude_from_vendor_snapshot: true,
 }
 
 cc_binary {
@@ -226,4 +244,8 @@
         "camera.device@3.5-external-impl_headers",
         "camera.device@3.5-impl_headers",
     ],
+    // Since this framework module has a transitive dependency  on a vendor
+    // proprietary library, we exclude this module from the vendor snapshot so
+    // that it will be built from source as part of the vendor image build.
+    exclude_from_vendor_snapshot: true,
 }
diff --git a/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cpp b/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cpp
index 4cff1b7..18149e5 100644
--- a/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cpp
+++ b/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cpp
@@ -87,23 +87,32 @@
     if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_2 &&
             mModule->isOpenLegacyDefined()) {
         // try open_legacy to see if it actually works
-        struct hw_device_t* halDev = nullptr;
-        int ret = mModule->openLegacy(cameraId, CAMERA_DEVICE_API_VERSION_1_0, &halDev);
-        if (ret == 0) {
-            mOpenLegacySupported[cameraIdStr] = true;
-            halDev->close(halDev);
-            deviceNamePair = std::make_pair(cameraIdStr,
+        if ((property_get_bool("ro.config.low_ram", /*default*/ false))) {
+           deviceNamePair = std::make_pair(cameraIdStr,
                             getHidlDeviceName(cameraIdStr, CAMERA_DEVICE_API_VERSION_1_0));
-            mCameraDeviceNames.add(deviceNamePair);
-            if (cam_new) {
-                mCallbacks->cameraDeviceStatusChange(deviceNamePair.second, status);
-            }
-        } else if (ret == -EBUSY || ret == -EUSERS) {
+           mCameraDeviceNames.add(deviceNamePair);
+           if (cam_new) {
+              mCallbacks->cameraDeviceStatusChange(deviceNamePair.second, status);
+           }
+          } else {
+            struct hw_device_t* halDev = nullptr;
+            int ret = mModule->openLegacy(cameraId, CAMERA_DEVICE_API_VERSION_1_0, &halDev);
+            if (ret == 0) {
+               mOpenLegacySupported[cameraIdStr] = true;
+               halDev->close(halDev);
+               deviceNamePair = std::make_pair(cameraIdStr,
+                                getHidlDeviceName(cameraIdStr, CAMERA_DEVICE_API_VERSION_1_0));
+               mCameraDeviceNames.add(deviceNamePair);
+               if (cam_new) {
+                 mCallbacks->cameraDeviceStatusChange(deviceNamePair.second, status);
+              }
+            } else if (ret == -EBUSY || ret == -EUSERS) {
             // Looks like this provider instance is not initialized during
             // system startup and there are other camera users already.
             // Not a good sign but not fatal.
-            ALOGW("%s: open_legacy try failed!", __FUNCTION__);
-        }
+              ALOGW("%s: open_legacy try failed!", __FUNCTION__);
+            }
+         }
     }
 }
 
@@ -314,15 +323,15 @@
 
     mNumberOfLegacyCameras = mModule->getNumberOfCameras();
     for (int i = 0; i < mNumberOfLegacyCameras; i++) {
-        struct camera_info info;
-        auto rc = mModule->getCameraInfo(i, &info);
+        uint32_t device_version;
+        auto rc = mModule->getCameraDeviceVersion(i, &device_version);
         if (rc != NO_ERROR) {
-            ALOGE("%s: Camera info query failed!", __func__);
+            ALOGE("%s: Camera device version query failed!", __func__);
             mModule.clear();
             return true;
         }
 
-        if (checkCameraVersion(i, info) != OK) {
+        if (checkCameraVersion(i, device_version) != OK) {
             ALOGE("%s: Camera version check failed!", __func__);
             mModule.clear();
             return true;
@@ -342,7 +351,7 @@
 /**
  * Check that the device HAL version is still in supported.
  */
-int LegacyCameraProviderImpl_2_4::checkCameraVersion(int id, camera_info info) {
+int LegacyCameraProviderImpl_2_4::checkCameraVersion(int id, uint32_t device_version) {
     if (mModule == nullptr) {
         return NO_INIT;
     }
@@ -352,7 +361,7 @@
     uint16_t moduleVersion = mModule->getModuleApiVersion();
     if (moduleVersion >= CAMERA_MODULE_API_VERSION_2_0) {
         // Verify the device version is in the supported range
-        switch (info.device_version) {
+        switch (device_version) {
             case CAMERA_DEVICE_API_VERSION_1_0:
             case CAMERA_DEVICE_API_VERSION_3_2:
             case CAMERA_DEVICE_API_VERSION_3_3:
@@ -370,7 +379,7 @@
                 if (moduleVersion < CAMERA_MODULE_API_VERSION_2_5) {
                     ALOGE("%s: Device %d has unsupported version combination:"
                             "HAL version %x and module version %x",
-                            __FUNCTION__, id, info.device_version, moduleVersion);
+                            __FUNCTION__, id, device_version, moduleVersion);
                     return NO_INIT;
                 }
                 break;
@@ -380,8 +389,8 @@
             case CAMERA_DEVICE_API_VERSION_3_1:
                 // no longer supported
             default:
-                ALOGE("%s: Device %d has HAL version %x, which is not supported",
-                        __FUNCTION__, id, info.device_version);
+                ALOGE("%s: Device %d has HAL version %x, which is not supported", __FUNCTION__, id,
+                      device_version);
                 return NO_INIT;
         }
     }
diff --git a/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.h b/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.h
index b4914b3..9ec5c5e 100644
--- a/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.h
+++ b/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.h
@@ -97,7 +97,7 @@
 
     hidl_vec<VendorTagSection> mVendorTagSections;
     bool setUpVendorTags();
-    int checkCameraVersion(int id, camera_info info);
+    int checkCameraVersion(int id, uint32_t device_version);
 
     // create HIDL device name from camera ID and legacy device version
     std::string getHidlDeviceName(std::string cameraId, int deviceVersion);
diff --git a/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service.rc b/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service.rc
index f7ac9f8..ff924ed 100644
--- a/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service.rc
+++ b/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service.rc
@@ -5,4 +5,4 @@
     group audio camera input drmrpc
     ioprio rt 4
     capabilities SYS_NICE
-    task_profiles CameraServiceCapacity MaxPerformance
+    task_profiles CameraServiceCapacity HighPerformance
diff --git a/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service_64.rc b/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service_64.rc
index a32dd46..642e84e 100644
--- a/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service_64.rc
+++ b/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service_64.rc
@@ -5,4 +5,4 @@
     group audio camera input drmrpc
     ioprio rt 4
     capabilities SYS_NICE
-    task_profiles CameraServiceCapacity MaxPerformance
+    task_profiles CameraServiceCapacity HighPerformance
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index f235235..560b24e 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -888,6 +888,8 @@
     static Status getSystemCameraKind(const camera_metadata_t* staticMeta,
                                       SystemCameraKind* systemCameraKind);
 
+    static V3_2::DataspaceFlags getDataspace(PixelFormat format);
+
     void processCaptureRequestInternal(uint64_t bufferusage, RequestTemplate reqTemplate,
                                        bool useSecureOnlyCameras);
 
@@ -3173,7 +3175,6 @@
     }
 }
 
-
 // Verify that all supported stream formats and sizes can be configured
 // successfully.
 TEST_P(CameraHidlTest, configureStreamsAvailableOutputs) {
@@ -3216,17 +3217,7 @@
         uint32_t streamConfigCounter = 0;
         for (auto& it : outputStreams) {
             V3_2::Stream stream3_2;
-            V3_2::DataspaceFlags dataspaceFlag = 0;
-            switch (static_cast<PixelFormat>(it.format)) {
-                case PixelFormat::BLOB:
-                    dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::V0_JFIF);
-                    break;
-                case PixelFormat::Y16:
-                    dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::DEPTH);
-                    break;
-                default:
-                    dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::UNKNOWN);
-            }
+            V3_2::DataspaceFlags dataspaceFlag = getDataspace(static_cast<PixelFormat>(it.format));
             stream3_2 = {streamId,
                              StreamType::OUTPUT,
                              static_cast<uint32_t>(it.width),
@@ -3346,17 +3337,8 @@
             size_t j = 0;
             for (const auto& it : outputStreams) {
                 V3_2::Stream stream3_2;
-                V3_2::DataspaceFlags dataspaceFlag = 0;
-                switch (static_cast<PixelFormat>(it.format)) {
-                    case PixelFormat::BLOB:
-                        dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::V0_JFIF);
-                        break;
-                    case PixelFormat::Y16:
-                        dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::DEPTH);
-                        break;
-                    default:
-                        dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::UNKNOWN);
-                }
+                V3_2::DataspaceFlags dataspaceFlag =
+                        getDataspace(static_cast<PixelFormat>(it.format));
                 stream3_2 = {streamId++,
                              StreamType::OUTPUT,
                              static_cast<uint32_t>(it.width),
@@ -4453,9 +4435,12 @@
                             nullptr};
         } else {
             allocateGraphicBuffer(testStream.width, testStream.height,
-                    android_convertGralloc1To0Usage(halStreamConfig.streams[0].producerUsage,
-                        halStreamConfig.streams[0].consumerUsage),
-                    halStreamConfig.streams[0].overrideFormat, &buffer_handle);
+                                  /* We don't look at halStreamConfig.streams[0].consumerUsage
+                                   * since that is 0 for output streams
+                                   */
+                                  android_convertGralloc1To0Usage(
+                                          halStreamConfig.streams[0].producerUsage, bufferUsage),
+                                  halStreamConfig.streams[0].overrideFormat, &buffer_handle);
             outputBuffer = {halStreamConfig.streams[0].id,
                             bufferId,
                             buffer_handle,
@@ -5893,6 +5878,23 @@
     return ret;
 }
 
+// Select an appropriate dataspace given a specific pixel format.
+V3_2::DataspaceFlags CameraHidlTest::getDataspace(PixelFormat format) {
+    switch (format) {
+        case PixelFormat::BLOB:
+            return static_cast<V3_2::DataspaceFlags>(Dataspace::V0_JFIF);
+        case PixelFormat::Y16:
+            return static_cast<V3_2::DataspaceFlags>(Dataspace::DEPTH);
+        case PixelFormat::RAW16:
+        case PixelFormat::RAW_OPAQUE:
+        case PixelFormat::RAW10:
+        case PixelFormat::RAW12:
+            return static_cast<V3_2::DataspaceFlags>(Dataspace::ARBITRARY);
+        default:
+            return static_cast<V3_2::DataspaceFlags>(Dataspace::UNKNOWN);
+    }
+}
+
 // Check whether this is a monochrome camera using the static camera characteristics.
 Status CameraHidlTest::isMonochromeCamera(const camera_metadata_t *staticMeta) {
     Status ret = Status::METHOD_NOT_SUPPORTED;
@@ -6267,17 +6269,8 @@
     ASSERT_EQ(Status::OK, rc);
     ASSERT_FALSE(outputStreams.empty());
 
-    V3_2::DataspaceFlags dataspaceFlag = 0;
-    switch (static_cast<PixelFormat>(outputStreams[idx].format)) {
-        case PixelFormat::BLOB:
-            dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::V0_JFIF);
-            break;
-        case PixelFormat::Y16:
-            dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::DEPTH);
-            break;
-        default:
-            dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::UNKNOWN);
-    }
+    V3_2::DataspaceFlags dataspaceFlag =
+            getDataspace(static_cast<PixelFormat>(outputStreams[idx].format));
 
     ::android::hardware::hidl_vec<V3_4::Stream> streams3_4(/*size*/1);
     V3_4::Stream stream3_4 = {{ 0 /*streamId*/, StreamType::OUTPUT,
diff --git a/camera/provider/2.5/default/Android.bp b/camera/provider/2.5/default/Android.bp
index 9ddf651..66a2d5b 100644
--- a/camera/provider/2.5/default/Android.bp
+++ b/camera/provider/2.5/default/Android.bp
@@ -35,6 +35,10 @@
         "camera.device@3.5-impl_headers",
     ],
     export_include_dirs: ["."],
+    // Since this framework module has a transitive dependency  on a vendor
+    // proprietary library, we exclude this module from the vendor snapshot so
+    // that it will be built from source as part of the vendor image build.
+    exclude_from_vendor_snapshot: true,
 }
 
 cc_library_shared {
@@ -78,6 +82,10 @@
         "camera.device@3.6-external-impl_headers"
     ],
     export_include_dirs: ["."],
+    // Since this framework module has a transitive dependency  on a vendor
+    // proprietary library, we exclude this module from the vendor snapshot so
+    // that it will be built from source as part of the vendor image build.
+    exclude_from_vendor_snapshot: true,
 }
 
 cc_defaults {
@@ -114,6 +122,10 @@
         "camera.device@3.4-impl_headers",
         "camera.device@3.5-impl_headers"
     ],
+    // Since this framework module has a transitive dependency  on a vendor
+    // proprietary library, we exclude this module from the vendor snapshot so
+    // that it will be built from source as part of the vendor image build.
+    exclude_from_vendor_snapshot: true,
 }
 
 cc_binary {
@@ -187,4 +199,8 @@
         "camera.device@3.5-impl_headers",
         "camera.device@3.6-external-impl_headers",
     ],
+    // Since this framework module has a transitive dependency  on a vendor
+    // proprietary library, we exclude this module from the vendor snapshot so
+    // that it will be built from source as part of the vendor image build.
+    exclude_from_vendor_snapshot: true,
 }
diff --git a/cas/1.0/default/Android.bp b/cas/1.0/default/Android.bp
index f9977ff..3891a0e 100644
--- a/cas/1.0/default/Android.bp
+++ b/cas/1.0/default/Android.bp
@@ -24,10 +24,16 @@
       "liblog",
       "libstagefright_foundation",
       "libutils",
+      "libhwbinder"
     ],
     header_libs: [
       "media_plugin_headers",
     ],
+    arch: {
+        arm: {
+            cflags: ["-DARCH_ARM_32"],
+        },
+    },
 }
 
 cc_binary {
diff --git a/cas/1.0/default/service.cpp b/cas/1.0/default/service.cpp
index 754c0c5..dfb385d 100644
--- a/cas/1.0/default/service.cpp
+++ b/cas/1.0/default/service.cpp
@@ -27,6 +27,10 @@
 
 #include "MediaCasService.h"
 
+#ifdef ARCH_ARM_32
+#include <hwbinder/ProcessState.h>
+#endif
+
 using android::hardware::configureRpcThreadpool;
 using android::hardware::joinRpcThreadpool;
 using android::hardware::LazyServiceRegistrar;
@@ -40,6 +44,9 @@
 #endif
 
 int main() {
+    #ifdef ARCH_ARM_32
+        android::hardware::ProcessState::initWithMmapSize((size_t)32768);
+    #endif
     configureRpcThreadpool(8, true /* callerWillJoin */);
 
     // Setup hwbinder service
diff --git a/compatibility_matrices/compatibility_matrix.4.xml b/compatibility_matrices/compatibility_matrix.4.xml
index e5e012c..9f486dd 100644
--- a/compatibility_matrices/compatibility_matrix.4.xml
+++ b/compatibility_matrices/compatibility_matrix.4.xml
@@ -499,6 +499,7 @@
         <interface>
             <name>IHostapd</name>
             <instance>default</instance>
+            <instance>wigighostapd</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
diff --git a/compatibility_matrices/compatibility_matrix.5.xml b/compatibility_matrices/compatibility_matrix.5.xml
index e772b6f..53b9be8 100644
--- a/compatibility_matrices/compatibility_matrix.5.xml
+++ b/compatibility_matrices/compatibility_matrix.5.xml
@@ -541,6 +541,7 @@
         <interface>
             <name>IHostapd</name>
             <instance>default</instance>
+            <instance>wigighostapd</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
diff --git a/current.txt b/current.txt
index 6696516..6f509c3 100644
--- a/current.txt
+++ b/current.txt
@@ -765,3 +765,13 @@
 2ce1f7fb52e49f80b13a9b153d491bce530552f02357ea729acae922a8659f93 android.hardware.wifi.supplicant@1.3::ISupplicantStaIfaceCallback
 77531c8d048f8f8ae532babd0ca86332a865ec9aace1b051226ef2b21123e645 android.hardware.wifi.supplicant@1.3::ISupplicantStaNetwork
 98592d193a717066facf91428426e5abe211e3bd718bc372e29fb944ddbe6e7c android.hardware.wifi.supplicant@1.3::types
+
+# ABI preserving changes to HALs
+1ca372cd67d197df099e87616a613ba6ede6552638a603e18f86c8834302c3d1 android.hardware.gnss@1.0::IGnssMeasurementCallback
+6a271e493907e8ba20912e42771bd0d99ae45431a851d5675ef9496d02510a34 android.hardware.gnss@1.1::IGnssMeasurementCallback
+cd84ab19c590e0e73dd2307b591a3093ee18147ef95e6d5418644463a6620076 android.hardware.neuralnetworks@1.2::IDevice
+9625e85f56515ad2cf87b6a1847906db669f746ea4ab02cd3d4ca25abc9b0109 android.hardware.neuralnetworks@1.2::types
+9e758e208d14f7256e0885d6d8ad0b61121b21d8c313864f981727ae55bffd16 android.hardware.neuralnetworks@1.3::types
+0f53d70e1eadf8d987766db4bf6ae2048004682168f4cab118da576787def3fa android.hardware.radio@1.0::types
+38d65fb20c60a5b823298560fc0825457ecdc49603a4b4e94bf81511790737da android.hardware.radio@1.4::types
+954c334efd80e8869b66d1ce5fe2755712d96ba4b3c38d415739c330af5fb4cb android.hardware.radio@1.5::types
diff --git a/drm/1.0/default/Android.bp b/drm/1.0/default/Android.bp
index 1122e46..48e084e 100644
--- a/drm/1.0/default/Android.bp
+++ b/drm/1.0/default/Android.bp
@@ -1,3 +1,17 @@
+// Copyright (C) 2016-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.
+
 cc_library_static {
     name: "android.hardware.drm@1.0-helper",
     vendor_available: true,
@@ -22,3 +36,111 @@
     ],
     export_include_dirs: ["include"],
 }
+
+soong_config_module_type {
+    name: "android_hardware_drm_1_0_multilib",
+    module_type: "cc_defaults",
+    config_namespace: "ANDROID",
+    bool_variables: ["TARGET_ENABLE_MEDIADRM_64"],
+    properties: ["compile_multilib"],
+}
+
+android_hardware_drm_1_0_multilib {
+    name: "android.hardware.drm@1.0-multilib-lib",
+    compile_multilib: "32",
+    soong_config_variables: {
+        TARGET_ENABLE_MEDIADRM_64: {
+            compile_multilib: "both",
+        }
+    }
+}
+
+android_hardware_drm_1_0_multilib {
+    name: "android.hardware.drm@1.0-multilib-exe",
+    compile_multilib: "32",
+    soong_config_variables: {
+        TARGET_ENABLE_MEDIADRM_64: {
+            compile_multilib: "first",
+        }
+    }
+}
+
+cc_defaults {
+    name: "android.hardware.drm@1.0-service-defaults",
+    proprietary: true,
+    relative_install_path: "hw",
+    include_dirs: ["hardware/interfaces/drm"],
+    header_libs: ["media_plugin_headers"],
+    static_libs: ["android.hardware.drm@1.0-helper"],
+
+    shared_libs: [
+        "android.hardware.drm@1.0",
+        "android.hidl.memory@1.0",
+        "libhidlbase",
+        "libhardware",
+        "liblog",
+        "libutils",
+        "libbinder",
+    ],
+}
+
+//############ Build legacy drm service ############
+
+cc_binary {
+    name: "android.hardware.drm@1.0-service",
+    defaults: [
+        "android.hardware.drm@1.0-multilib-exe",
+        "android.hardware.drm@1.0-service-defaults"
+    ],
+    init_rc: ["android.hardware.drm@1.0-service.rc"],
+    srcs: ["service.cpp"],
+}
+
+//############ Build legacy drm lazy service ############
+
+cc_binary {
+    name: "android.hardware.drm@1.0-service-lazy",
+    defaults: [
+        "android.hardware.drm@1.0-multilib-exe",
+        "android.hardware.drm@1.0-service-defaults"
+    ],
+    overrides: ["android.hardware.drm@1.0-service"],
+    init_rc: ["android.hardware.drm@1.0-service-lazy.rc"],
+    srcs: ["serviceLazy.cpp"],
+}
+
+//############ Build legacy drm impl library ############
+
+cc_library_shared {
+    name: "android.hardware.drm@1.0-impl",
+    defaults: ["android.hardware.drm@1.0-multilib-lib"],
+    proprietary: true,
+    relative_install_path: "hw",
+
+    include_dirs: [
+        "frameworks/native/include",
+        "frameworks/av/include",
+    ],
+
+    shared_libs: [
+        "android.hardware.drm@1.0",
+        "android.hidl.memory@1.0",
+        "libcutils",
+        "libhidlbase",
+        "libhidlmemory",
+        "liblog",
+        "libstagefright_foundation",
+        "libutils",
+    ],
+
+    static_libs: ["android.hardware.drm@1.0-helper"],
+
+    srcs: [
+        "DrmFactory.cpp",
+        "DrmPlugin.cpp",
+        "CryptoFactory.cpp",
+        "CryptoPlugin.cpp",
+        "LegacyPluginPath.cpp",
+        "TypeConvert.cpp",
+    ],
+}
diff --git a/drm/1.0/default/Android.mk b/drm/1.0/default/Android.mk
deleted file mode 100644
index 9016dc3..0000000
--- a/drm/1.0/default/Android.mk
+++ /dev/null
@@ -1,81 +0,0 @@
-#
-# Copyright (C) 2016 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.
-
-
-############# Build legacy drm service ############
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-include $(LOCAL_PATH)/common_default_service.mk
-LOCAL_MODULE := android.hardware.drm@1.0-service
-LOCAL_INIT_RC := android.hardware.drm@1.0-service.rc
-LOCAL_SRC_FILES := service.cpp
-
-include $(BUILD_EXECUTABLE)
-
-############# Build legacy drm lazy service ############
-
-include $(CLEAR_VARS)
-
-include $(LOCAL_PATH)/common_default_service.mk
-LOCAL_MODULE := android.hardware.drm@1.0-service-lazy
-LOCAL_OVERRIDES_MODULES := android.hardware.drm@1.0-service
-LOCAL_INIT_RC := android.hardware.drm@1.0-service-lazy.rc
-LOCAL_SRC_FILES := serviceLazy.cpp
-
-include $(BUILD_EXECUTABLE)
-
-############# Build legacy drm impl library ############
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.drm@1.0-impl
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_SRC_FILES := \
-    DrmFactory.cpp \
-    DrmPlugin.cpp \
-    CryptoFactory.cpp \
-    CryptoPlugin.cpp \
-    LegacyPluginPath.cpp \
-    TypeConvert.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
-    android.hardware.drm@1.0 \
-    android.hidl.memory@1.0 \
-    libcutils \
-    libhidlbase \
-    libhidlmemory \
-    liblog \
-    libstagefright_foundation \
-    libutils \
-
-LOCAL_STATIC_LIBRARIES := \
-    android.hardware.drm@1.0-helper \
-
-LOCAL_C_INCLUDES := \
-    frameworks/native/include \
-    frameworks/av/include
-
-# TODO: Some legacy DRM plugins only support 32-bit. They need to be migrated to
-# 64-bit. (b/18948909) Once all of a device's legacy DRM plugins support 64-bit,
-# that device can turn on TARGET_ENABLE_MEDIADRM_64 to build this impl as
-# 64-bit.
-ifneq ($(TARGET_ENABLE_MEDIADRM_64), true)
-LOCAL_32_BIT_ONLY := true
-endif
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/drm/1.0/default/common_default_service.mk b/drm/1.0/default/common_default_service.mk
deleted file mode 100644
index 1b5a975..0000000
--- a/drm/1.0/default/common_default_service.mk
+++ /dev/null
@@ -1,44 +0,0 @@
-#
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-include $(CLEAR_VARS)
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := hw
-
-LOCAL_SHARED_LIBRARIES := \
-  android.hardware.drm@1.0 \
-  android.hidl.memory@1.0 \
-  libhidlbase \
-  libhardware \
-  liblog \
-  libutils \
-  libbinder \
-
-LOCAL_STATIC_LIBRARIES := \
-  android.hardware.drm@1.0-helper \
-
-LOCAL_C_INCLUDES := \
-  hardware/interfaces/drm
-
-LOCAL_HEADER_LIBRARIES := \
-  media_plugin_headers
-
-# TODO(b/18948909) Some legacy DRM plugins only support 32-bit. They need to be
-# migrated to 64-bit. Once all of a device's legacy DRM plugins support 64-bit,
-# that device can turn on TARGET_ENABLE_MEDIADRM_64 to build this service as
-# 64-bit.
-ifneq ($(TARGET_ENABLE_MEDIADRM_64), true)
-LOCAL_32_BIT_ONLY := true
-endif
diff --git a/drm/1.0/vts/functional/AndroidTest.xml b/drm/1.0/vts/functional/AndroidTest.xml
index 92ea7e4..02c51cc 100644
--- a/drm/1.0/vts/functional/AndroidTest.xml
+++ b/drm/1.0/vts/functional/AndroidTest.xml
@@ -16,6 +16,7 @@
 <configuration description="Runs VtsHalDrmV1_0TargetTest.">
     <option name="test-suite-tag" value="apct" />
     <option name="test-suite-tag" value="apct-native" />
+    <option name="not-shardable" value="true" />
 
     <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
 
diff --git a/drm/1.1/vts/functional/AndroidTest.xml b/drm/1.1/vts/functional/AndroidTest.xml
index 24eeb72..4757d4a 100644
--- a/drm/1.1/vts/functional/AndroidTest.xml
+++ b/drm/1.1/vts/functional/AndroidTest.xml
@@ -16,6 +16,7 @@
 <configuration description="Runs VtsHalDrmV1_1TargetTest.">
     <option name="test-suite-tag" value="apct" />
     <option name="test-suite-tag" value="apct-native" />
+    <option name="not-shardable" value="true" />
 
     <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
 
diff --git a/drm/1.2/vts/functional/AndroidTest.xml b/drm/1.2/vts/functional/AndroidTest.xml
index 3285c37..106ad33 100644
--- a/drm/1.2/vts/functional/AndroidTest.xml
+++ b/drm/1.2/vts/functional/AndroidTest.xml
@@ -16,6 +16,7 @@
 <configuration description="Runs VtsHalDrmV1_2TargetTest.">
     <option name="test-suite-tag" value="apct" />
     <option name="test-suite-tag" value="apct-native" />
+    <option name="not-shardable" value="true" />
 
     <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
 
diff --git a/drm/1.3/vts/functional/AndroidTest.xml b/drm/1.3/vts/functional/AndroidTest.xml
index 9cc8e0c..4ec5c70 100644
--- a/drm/1.3/vts/functional/AndroidTest.xml
+++ b/drm/1.3/vts/functional/AndroidTest.xml
@@ -16,6 +16,7 @@
 <configuration description="Runs VtsHalDrmV1_3TargetTest.">
     <option name="test-suite-tag" value="apct" />
     <option name="test-suite-tag" value="apct-native" />
+    <option name="not-shardable" value="true" />
 
     <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
 
diff --git a/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
index 33feb5e..16e634f 100644
--- a/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
@@ -247,8 +247,10 @@
     ALOGD("Observed %d GnssSvStatus, while awaiting one location (%d received)",
           sv_info_list_cbq_size, location_called_count);
 
-    hidl_vec<IGnssCallback_2_1::GnssSvInfo> last_sv_info_list;
-    ASSERT_TRUE(gnss_cb_->sv_info_list_cbq_.retrieve(last_sv_info_list, 1));
+    // Get the last sv_info_list
+    std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_vec_list;
+    gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec_list, sv_info_list_cbq_size, 1);
+    hidl_vec<IGnssCallback_2_1::GnssSvInfo> last_sv_info_list = sv_info_vec_list.back();
 
     bool nonZeroCn0Found = false;
     for (auto sv_info : last_sv_info_list) {
@@ -361,6 +363,12 @@
  * formerly strongest satellite
  */
 TEST_P(GnssHalTest, BlacklistIndividualSatellites) {
+    if (!(gnss_cb_->last_capabilities_ & IGnssCallback_2_1::Capabilities::SATELLITE_BLACKLIST)) {
+        ALOGI("Test BlacklistIndividualSatellites skipped. SATELLITE_BLACKLIST capability not "
+              "supported.");
+        return;
+    }
+
     const int kLocationsToAwait = 3;
     const int kRetriesToUnBlacklist = 10;
 
@@ -502,6 +510,12 @@
  * 4a & b) Clean up by turning off location, and send in empty blacklist.
  */
 TEST_P(GnssHalTest, BlacklistConstellationLocationOff) {
+    if (!(gnss_cb_->last_capabilities_ & IGnssCallback_2_1::Capabilities::SATELLITE_BLACKLIST)) {
+        ALOGI("Test BlacklistConstellationLocationOff skipped. SATELLITE_BLACKLIST capability not "
+              "supported.");
+        return;
+    }
+
     const int kLocationsToAwait = 3;
     const int kGnssSvInfoListTimeout = 2;
 
@@ -578,6 +592,12 @@
  * 4a & b) Clean up by turning off location, and send in empty blacklist.
  */
 TEST_P(GnssHalTest, BlacklistConstellationLocationOn) {
+    if (!(gnss_cb_->last_capabilities_ & IGnssCallback_2_1::Capabilities::SATELLITE_BLACKLIST)) {
+        ALOGI("Test BlacklistConstellationLocationOn skipped. SATELLITE_BLACKLIST capability not "
+              "supported.");
+        return;
+    }
+
     const int kLocationsToAwait = 3;
     const int kGnssSvInfoListTimeout = 2;
 
@@ -673,4 +693,4 @@
             iMeasurementCorrections->setCorrections_1_1(Utils::getMockMeasurementCorrections_1_1());
     ASSERT_TRUE(result.isOk());
     EXPECT_TRUE(result);
-}
\ No newline at end of file
+}
diff --git a/graphics/allocator/2.0/default/Android.bp b/graphics/allocator/2.0/default/Android.bp
index 59229b0..3a2808e 100644
--- a/graphics/allocator/2.0/default/Android.bp
+++ b/graphics/allocator/2.0/default/Android.bp
@@ -33,4 +33,11 @@
         "liblog",
         "libutils",
     ],
+    arch: {
+        arm: {
+            cflags: [
+                "-DARCH_ARM_32"
+            ],
+        },
+    },
 }
diff --git a/graphics/allocator/2.0/default/service.cpp b/graphics/allocator/2.0/default/service.cpp
index bc0539a..ca1fee4 100644
--- a/graphics/allocator/2.0/default/service.cpp
+++ b/graphics/allocator/2.0/default/service.cpp
@@ -19,10 +19,15 @@
 #include <android/hardware/graphics/allocator/2.0/IAllocator.h>
 
 #include <hidl/LegacySupport.h>
+#include <hwbinder/ProcessState.h>
 
 using android::hardware::defaultPassthroughServiceImplementation;
 using android::hardware::graphics::allocator::V2_0::IAllocator;
 
 int main() {
+
+#ifdef ARCH_ARM_32
+    android::hardware::ProcessState::initWithMmapSize((size_t)(32768));
+#endif
     return defaultPassthroughServiceImplementation<IAllocator>(4);
 }
diff --git a/graphics/composer/2.1/default/Android.bp b/graphics/composer/2.1/default/Android.bp
index 533687b..422dc5f 100644
--- a/graphics/composer/2.1/default/Android.bp
+++ b/graphics/composer/2.1/default/Android.bp
@@ -1,31 +1,3 @@
-cc_library_shared {
-    name: "android.hardware.graphics.composer@2.1-impl",
-    defaults: ["hidl_defaults"],
-    vendor: true,
-    relative_install_path: "hw",
-    srcs: ["passthrough.cpp"],
-    header_libs: [
-        "android.hardware.graphics.composer@2.1-passthrough",
-    ],
-    shared_libs: [
-        "android.hardware.graphics.composer@2.1",
-        "android.hardware.graphics.composer@2.1-resources",
-        "libbase",
-        "libcutils",
-        "libfmq",
-        "libhardware",
-        "libhidlbase",
-        "liblog",
-        "libsync",
-        "libutils",
-        "libhwc2on1adapter",
-        "libhwc2onfbadapter",
-    ],
-    cflags: [
-        "-DLOG_TAG=\"ComposerHal\""
-    ],
-}
-
 cc_binary {
     name: "android.hardware.graphics.composer@2.1-service",
     defaults: ["hidl_defaults"],
@@ -33,12 +5,30 @@
     relative_install_path: "hw",
     srcs: ["service.cpp"],
     init_rc: ["android.hardware.graphics.composer@2.1-service.rc"],
+    header_libs: [
+        "android.hardware.graphics.composer@2.1-passthrough",
+    ],
     shared_libs: [
         "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.composer@2.1-resources",
+        "libbase",
+        "libhwbinder",
         "libbinder",
+        "libcutils",
+        "libfmq",
+        "libhardware",
         "libhidlbase",
+        "libhwc2on1adapter",
+        "libhwc2onfbadapter",
         "liblog",
         "libsync",
         "libutils",
     ],
+    arch: {
+        arm: {
+            cflags: [
+                "-DARCH_ARM_32"
+            ],
+        },
+    },
 }
diff --git a/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc b/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc
index cbd589a..5b8a46f 100644
--- a/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc
+++ b/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc
@@ -1,8 +1,8 @@
 service vendor.hwcomposer-2-1 /vendor/bin/hw/android.hardware.graphics.composer@2.1-service
-    interface android.hardware.graphics.composer@2.1::IComposer default
     class hal animation
     user system
     group graphics drmrpc
     capabilities SYS_NICE
     onrestart restart surfaceflinger
     writepid /dev/cpuset/system-background/tasks
+    socket pps stream 0660 system system
diff --git a/graphics/composer/2.1/default/passthrough.cpp b/graphics/composer/2.1/default/passthrough.cpp
deleted file mode 100644
index ef7ed7c..0000000
--- a/graphics/composer/2.1/default/passthrough.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android/hardware/graphics/composer/2.1/IComposer.h>
-#include <composer-passthrough/2.1/HwcLoader.h>
-
-using android::hardware::graphics::composer::V2_1::IComposer;
-using android::hardware::graphics::composer::V2_1::passthrough::HwcLoader;
-
-extern "C" IComposer* HIDL_FETCH_IComposer(const char* /* name */) {
-    return HwcLoader::load();
-}
diff --git a/graphics/composer/2.1/default/service.cpp b/graphics/composer/2.1/default/service.cpp
index 82a33f6..b8ddd21 100644
--- a/graphics/composer/2.1/default/service.cpp
+++ b/graphics/composer/2.1/default/service.cpp
@@ -21,10 +21,12 @@
 #include <android/hardware/graphics/composer/2.1/IComposer.h>
 
 #include <binder/ProcessState.h>
+#include <composer-passthrough/2.1/HwcLoader.h>
 #include <hidl/LegacySupport.h>
+#include <hwbinder/ProcessState.h>
 
 using android::hardware::graphics::composer::V2_1::IComposer;
-using android::hardware::defaultPassthroughServiceImplementation;
+using android::hardware::graphics::composer::V2_1::passthrough::HwcLoader;
 
 int main() {
     // the conventional HAL might start binder services
@@ -40,5 +42,23 @@
         ALOGE("Couldn't set SCHED_FIFO: %d", errno);
     }
 
-    return defaultPassthroughServiceImplementation<IComposer>(4);
+#ifdef ARCH_ARM_32
+    android::hardware::ProcessState::initWithMmapSize((size_t)(32768));
+#endif
+
+    android::hardware::configureRpcThreadpool(4, true /* will join */);
+
+    android::sp<IComposer> composer = HwcLoader::load();
+    if (composer == nullptr) {
+        return 1;
+    }
+    if (composer->registerAsService() != android::NO_ERROR) {
+        ALOGE("failed to register service");
+        return 1;
+    }
+
+    android::hardware::joinRpcThreadpool();
+
+    ALOGE("service is terminating");
+    return 1;
 }
diff --git a/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc b/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc
index efe6dad..289a91c 100644
--- a/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc
+++ b/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc
@@ -4,4 +4,5 @@
     group graphics drmrpc
     capabilities SYS_NICE
     onrestart restart surfaceflinger
+    socket pps stream 0660 system system
     writepid /dev/cpuset/system-background/tasks
diff --git a/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc b/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc
index 81ce890..5cc19bb 100644
--- a/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc
+++ b/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc
@@ -4,4 +4,5 @@
     group graphics drmrpc
     capabilities SYS_NICE
     onrestart restart surfaceflinger
+    socket pps stream 0660 system system
     writepid /dev/cpuset/system-background/tasks
diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
index e0e1394..19c4653 100644
--- a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
+++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
@@ -222,6 +222,10 @@
     Error getDisplayCapabilities(
             Display display,
             std::vector<IComposerClient::DisplayCapability>* outCapabilities) override {
+        if (!mDispatch.getDisplayCapabilities) {
+            return Error::UNSUPPORTED;
+        }
+
         uint32_t count = 0;
         int32_t error = mDispatch.getDisplayCapabilities(mDevice, display, &count, nullptr);
         if (error != HWC2_ERROR_NONE) {
diff --git a/graphics/composer/2.4/default/android.hardware.graphics.composer@2.4-service.rc b/graphics/composer/2.4/default/android.hardware.graphics.composer@2.4-service.rc
index a296b0a..802b99e 100644
--- a/graphics/composer/2.4/default/android.hardware.graphics.composer@2.4-service.rc
+++ b/graphics/composer/2.4/default/android.hardware.graphics.composer@2.4-service.rc
@@ -5,3 +5,4 @@
     capabilities SYS_NICE
     onrestart restart surfaceflinger
     writepid /dev/cpuset/system-background/tasks
+    socket pps stream 0660 system system
diff --git a/health/1.0/default/Android.bp b/health/1.0/default/Android.bp
index 7581335..b815eae 100644
--- a/health/1.0/default/Android.bp
+++ b/health/1.0/default/Android.bp
@@ -51,6 +51,12 @@
         "android.hardware.health@1.0-convert",
         "libhealthd.default",
     ],
+
+    shared_libs: [
+        "libhidlbase",
+        "libutils",
+        "android.hardware.health@1.0",
+    ],
 }
 
 cc_binary {
diff --git a/health/1.0/default/android.hardware.health@1.0-service.rc b/health/1.0/default/android.hardware.health@1.0-service.rc
index 405784f..569dc88 100644
--- a/health/1.0/default/android.hardware.health@1.0-service.rc
+++ b/health/1.0/default/android.hardware.health@1.0-service.rc
@@ -2,4 +2,4 @@
     class hal
     user system
     group system
-    capabilities WAKE_ALARM
+    capabilities WAKE_ALARM BLOCK_SUSPEND
diff --git a/health/2.1/default/android.hardware.health@2.1-service.rc b/health/2.1/default/android.hardware.health@2.1-service.rc
index b6d9e3b..8728257 100644
--- a/health/2.1/default/android.hardware.health@2.1-service.rc
+++ b/health/2.1/default/android.hardware.health@2.1-service.rc
@@ -2,5 +2,5 @@
     class hal charger
     user system
     group system
-    capabilities WAKE_ALARM
+    capabilities WAKE_ALARM BLOCK_SUSPEND
     file /dev/kmsg w
diff --git a/identity/aidl/android/hardware/identity/IIdentityCredential.aidl b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
index 730b601..702334d 100644
--- a/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
+++ b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
@@ -55,7 +55,7 @@
      * This method may only be called once per instance. If called more than once, STATUS_FAILED
      * will be returned.
      *
-     * @return the unencrypted key-pair in PKCS#8 format.
+     * @return the private key, in DER format as specified in RFC 5915.
      */
     byte[] createEphemeralKeyPair();
 
@@ -88,10 +88,10 @@
      * The setRequestedNamespaces() and setVerificationToken() methods will be called before
      * this method is called.
      *
-     * This method be called after createEphemeralKeyPair(), setReaderEphemeralPublicKey(),
-     * createAuthChallenge() and before startRetrieveEntry(). This method call is followed by
-     * multiple calls of startRetrieveEntryValue(), retrieveEntryValue(), and finally
-     * finishRetrieval().
+     * This method is called after createEphemeralKeyPair(), setReaderEphemeralPublicKey(),
+     * createAuthChallenge() (note that those calls are optional) and before startRetrieveEntry().
+     * This method call is followed by multiple calls of startRetrieveEntryValue(),
+     * retrieveEntryValue(), and finally finishRetrieval().
      *
      * It is permissible to perform data retrievals multiple times using the same instance (e.g.
      * startRetrieval(), then multiple calls of startRetrieveEntryValue(), retrieveEntryValue(),
@@ -343,12 +343,13 @@
      *
      *  - signature: must be set to ECDSA.
      *
-     *  - subject: CN shall be set to "Android Identity Credential Authentication Key".
+     *  - subject: CN shall be set to "Android Identity Credential Authentication Key". (fixed
+     *    value: same on all certs)
      *
-     *  - issuer: shall be set to "credentialStoreName (credentialStoreAuthorName)" using the
-     *    values returned in HardwareInformation.
+     *  - issuer: CN shall be set to "Android Identity Credential Key". (fixed value:
+     *    same on all certs)
      *
-     *  - validity: should be from current time and one year in the future.
+     *  - validity: should be from current time and one year in the future (365 days).
      *
      *  - subjectPublicKeyInfo: must contain attested public key.
      *
diff --git a/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl b/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
index 297fd1d..c48cb66 100644
--- a/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
+++ b/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
@@ -37,12 +37,12 @@
      *
      *  - signature: must be set to ECDSA.
      *
-     *  - subject: CN shall be set to "Android Identity Credential Key".
+     *  - subject: CN shall be set to "Android Identity Credential Key". (fixed value:
+     *    same on all certs)
      *
-     *  - issuer: shall be set to "credentialStoreName (credentialStoreAuthorName)" using the
-     *    values returned in HardwareInformation.
+     *  - issuer: Same as the subject field of the batch attestation key.
      *
-     *  - validity: should be from current time and expire at the same time as the
+     *  - validity: Should be set to current time and expire at the same time as the
      *    attestation batch certificate used.
      *
      *  - subjectPublicKeyInfo: must contain attested public key.
@@ -55,19 +55,14 @@
      *
      *  - The attestationSecurityLevel field must be set to either Software (0),
      *    TrustedEnvironment (1), or StrongBox (2) depending on how attestation is
-     *    implemented. Only the default AOSP implementation of this HAL may use
-     *    value 0 (additionally, this implementation must not be used on production
-     *    devices).
+     *    implemented.
      *
-     *  - The keymasterVersion field in the attestation extension must be set to (10*major + minor)
-     *    where major and minor are the Identity Credential interface major and minor versions.
-     *    Specifically for this version of the interface (1.0) this value is 10.
+     *  - The keymasterVersion field in the attestation extension must be set to the.
+     *    same value as used for Android Keystore keys.
      *
      *  - The keymasterSecurityLevel field in the attestation extension must be set to
      *    either Software (0), TrustedEnvironment (1), or StrongBox (2) depending on how
-     *    the Trusted Application backing the HAL implementation is implemented. Only
-     *    the default AOSP implementation of this HAL may use value 0 (additionally, this
-     *    implementation must not be used on production devices)
+     *    the Trusted Application backing the HAL implementation is implemented.
      *
      *  - The attestationChallenge field must be set to the passed-in challenge.
      *
@@ -81,7 +76,8 @@
      *
      *    - Tag::IDENTITY_CREDENTIAL_KEY which indicates that the key is an Identity
      *      Credential key (which can only sign/MAC very specific messages) and not an Android
-     *      Keystore key (which can be used to sign/MAC anything).
+     *      Keystore key (which can be used to sign/MAC anything). This must not be set
+     *      for test credentials.
      *
      *    - Tag::PURPOSE must be set to SIGN
      *
@@ -95,10 +91,13 @@
      *
      *    - Tag::EC_CURVE must be set to P_256
      *
-     * Additional authorizations may be needed in the softwareEnforced and teeEnforced
-     * fields - the above is not an exhaustive list. Specifically, authorizations containing
-     * information about the root of trust, OS version, verified boot state, and so on should
-     * be included.
+     *    - Tag::ROOT_OF_TRUST must be set
+     *
+     *    - Tag::OS_VERSION and Tag::OS_PATCHLEVEL must be set
+     *
+     * Additional authorizations may be appear in the softwareEnforced and teeEnforced
+     * fields. For example if the device has a boot or vendor partitions, then BOOT_PATCHLEVEL
+     * and VENDOR_PATCHLEVEL should be set.
      *
      * Since the chain is required to be generated using Keymaster Attestation, the returned
      * certificate chain has the following properties:
@@ -112,8 +111,8 @@
      * As with any user of attestation, the Issuing Authority (as a relying party) wishing
      * to issue a credential to a device using these APIs, must carefully examine the
      * returned certificate chain for all of the above (and more). In particular, the Issuing
-     * Authority should check the root of trust, verified boot state, patch level,
-     * application id, etc.
+     * Authority should check the root of trust (which include verified boot state), patch level,
+     * attestation application id, etc.
      *
      * This all depends on the needs of the Issuing Authority and the kind of credential but
      * in general an Issuing Authority should never issue a credential to a device without
diff --git a/identity/aidl/default/IdentityCredential.cpp b/identity/aidl/default/IdentityCredential.cpp
index 10f9aa5..41d410d 100644
--- a/identity/aidl/default/IdentityCredential.cpp
+++ b/identity/aidl/default/IdentityCredential.cpp
@@ -276,6 +276,7 @@
     auto itemsRequest = byteStringToUnsigned(itemsRequestS);
     auto readerSignature = byteStringToUnsigned(readerSignatureS);
 
+    std::unique_ptr<cppbor::Item> sessionTranscriptItem;
     if (sessionTranscript.size() > 0) {
         auto [item, _, message] = cppbor::parse(sessionTranscript);
         if (item == nullptr) {
@@ -283,7 +284,7 @@
                     IIdentityCredentialStore::STATUS_INVALID_DATA,
                     "SessionTranscript contains invalid CBOR"));
         }
-        sessionTranscriptItem_ = std::move(item);
+        sessionTranscriptItem = std::move(item);
     }
     if (numStartRetrievalCalls_ > 0) {
         if (sessionTranscript_ != sessionTranscript) {
@@ -323,7 +324,7 @@
         vector<uint8_t> encodedReaderAuthentication =
                 cppbor::Array()
                         .add("ReaderAuthentication")
-                        .add(sessionTranscriptItem_->clone())
+                        .add(std::move(sessionTranscriptItem))
                         .add(cppbor::Semantic(24, itemsRequestBytes))
                         .encode();
         vector<uint8_t> encodedReaderAuthenticationBytes =
@@ -781,13 +782,6 @@
     optional<vector<uint8_t>> mac;
     if (signingKeyBlob_.size() > 0 && sessionTranscript_.size() > 0 &&
         readerPublicKey_.size() > 0) {
-        cppbor::Array array;
-        array.add("DeviceAuthentication");
-        array.add(sessionTranscriptItem_->clone());
-        array.add(docType_);
-        array.add(cppbor::Semantic(24, encodedDeviceNameSpaces));
-        vector<uint8_t> deviceAuthenticationBytes = cppbor::Semantic(24, array.encode()).encode();
-
         vector<uint8_t> docTypeAsBlob(docType_.begin(), docType_.end());
         optional<vector<uint8_t>> signingKey =
                 support::decryptAes128Gcm(storageKey_, signingKeyBlob_, docTypeAsBlob);
@@ -797,31 +791,15 @@
                     "Error decrypting signingKeyBlob"));
         }
 
-        optional<vector<uint8_t>> sharedSecret =
-                support::ecdh(readerPublicKey_, signingKey.value());
-        if (!sharedSecret) {
-            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
-                    IIdentityCredentialStore::STATUS_FAILED, "Error doing ECDH"));
-        }
-
-        // Mix-in SessionTranscriptBytes
         vector<uint8_t> sessionTranscriptBytes = cppbor::Semantic(24, sessionTranscript_).encode();
-        vector<uint8_t> sharedSecretWithSessionTranscriptBytes = sharedSecret.value();
-        std::copy(sessionTranscriptBytes.begin(), sessionTranscriptBytes.end(),
-                  std::back_inserter(sharedSecretWithSessionTranscriptBytes));
-
-        vector<uint8_t> salt = {0x00};
-        vector<uint8_t> info = {};
-        optional<vector<uint8_t>> derivedKey =
-                support::hkdf(sharedSecretWithSessionTranscriptBytes, salt, info, 32);
-        if (!derivedKey) {
+        optional<vector<uint8_t>> eMacKey =
+                support::calcEMacKey(signingKey.value(), readerPublicKey_, sessionTranscriptBytes);
+        if (!eMacKey) {
             return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
-                    IIdentityCredentialStore::STATUS_FAILED,
-                    "Error deriving key from shared secret"));
+                    IIdentityCredentialStore::STATUS_FAILED, "Error calculating EMacKey"));
         }
-
-        mac = support::coseMac0(derivedKey.value(), {},      // payload
-                                deviceAuthenticationBytes);  // detached content
+        mac = support::calcMac(sessionTranscript_, docType_, encodedDeviceNameSpaces,
+                               eMacKey.value());
         if (!mac) {
             return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
                     IIdentityCredentialStore::STATUS_FAILED, "Error MACing data"));
@@ -835,9 +813,9 @@
 
 ndk::ScopedAStatus IdentityCredential::generateSigningKeyPair(
         vector<int8_t>* outSigningKeyBlob, Certificate* outSigningKeyCertificate) {
-    string serialDecimal = "0";  // TODO: set serial to something unique
-    string issuer = "Android Open Source Project";
-    string subject = "Android IdentityCredential Reference Implementation";
+    string serialDecimal = "1";
+    string issuer = "Android Identity Credential Key";
+    string subject = "Android Identity Credential Authentication Key";
     time_t validityNotBefore = time(nullptr);
     time_t validityNotAfter = validityNotBefore + 365 * 24 * 3600;
 
diff --git a/identity/aidl/default/IdentityCredential.h b/identity/aidl/default/IdentityCredential.h
index 40070c0..f44d731 100644
--- a/identity/aidl/default/IdentityCredential.h
+++ b/identity/aidl/default/IdentityCredential.h
@@ -103,7 +103,6 @@
     map<int32_t, int> profileIdToAccessCheckResult_;
     vector<uint8_t> signingKeyBlob_;
     vector<uint8_t> sessionTranscript_;
-    std::unique_ptr<cppbor::Item> sessionTranscriptItem_;
     vector<uint8_t> itemsRequest_;
     vector<int32_t> requestCountsRemaining_;
     map<string, set<string>> requestedNameSpacesAndNames_;
diff --git a/identity/aidl/default/WritableIdentityCredential.cpp b/identity/aidl/default/WritableIdentityCredential.cpp
index c218866..4428543 100644
--- a/identity/aidl/default/WritableIdentityCredential.cpp
+++ b/identity/aidl/default/WritableIdentityCredential.cpp
@@ -74,7 +74,7 @@
     vector<uint8_t> appId(attestationApplicationId.begin(), attestationApplicationId.end());
 
     optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> keyAttestationPair =
-            support::createEcKeyPairAndAttestation(challenge, appId);
+            support::createEcKeyPairAndAttestation(challenge, appId, testCredential_);
     if (!keyAttestationPair) {
         LOG(ERROR) << "Error creating credentialKey and attestation";
         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
diff --git a/identity/aidl/vts/Android.bp b/identity/aidl/vts/Android.bp
index c1f44e7..03966de 100644
--- a/identity/aidl/vts/Android.bp
+++ b/identity/aidl/vts/Android.bp
@@ -9,7 +9,6 @@
         "VtsIWritableIdentityCredentialTests.cpp",
         "VtsIdentityTestUtils.cpp",
         "VtsAttestationTests.cpp",
-        "VtsAttestationParserSupport.cpp",
         "UserAuthTests.cpp",
         "ReaderAuthTests.cpp",
     ],
@@ -20,13 +19,14 @@
     static_libs: [
         "libcppbor",
         "libkeymaster_portable",
-        "libsoft_attestation_cert",
         "libpuresoftkeymasterdevice",
         "android.hardware.keymaster@4.0",
         "android.hardware.identity-support-lib",
         "android.hardware.identity-cpp",
         "android.hardware.keymaster-cpp",
         "android.hardware.keymaster-ndk_platform",
+        "libkeymaster4support",
+        "libkeymaster4_1support",
     ],
     test_suites: [
         "general-tests",
diff --git a/identity/aidl/vts/VtsAttestationParserSupport.cpp b/identity/aidl/vts/VtsAttestationParserSupport.cpp
deleted file mode 100644
index 71fe733..0000000
--- a/identity/aidl/vts/VtsAttestationParserSupport.cpp
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "VtsAttestationParserSupport.h"
-
-#include <aidl/Gtest.h>
-#include <map>
-
-namespace android::hardware::identity::test_utils {
-
-using std::endl;
-using std::map;
-using std::optional;
-using std::string;
-using std::vector;
-
-using ::android::sp;
-using ::android::String16;
-using ::android::binder::Status;
-
-using ::keymaster::ASN1_OBJECT_Ptr;
-using ::keymaster::AuthorizationSet;
-using ::keymaster::EVP_PKEY_Ptr;
-using ::keymaster::kAttestionRecordOid;
-using ::keymaster::TAG_ATTESTATION_APPLICATION_ID;
-using ::keymaster::TAG_IDENTITY_CREDENTIAL_KEY;
-using ::keymaster::TAG_INCLUDE_UNIQUE_ID;
-using ::keymaster::TypedTag;
-using ::keymaster::X509_Ptr;
-
-using support::certificateChainSplit;
-
-optional<keymaster_cert_chain_t> AttestationCertificateParser::certificateChainToKeymasterChain(
-        const vector<Certificate>& certificates) {
-    if (certificates.size() <= 0) {
-        return {};
-    }
-
-    keymaster_cert_chain_t kCert;
-    kCert.entry_count = certificates.size();
-    kCert.entries = (keymaster_blob_t*)malloc(sizeof(keymaster_blob_t) * kCert.entry_count);
-
-    int index = 0;
-    for (const auto& c : certificates) {
-        kCert.entries[index].data_length = c.encodedCertificate.size();
-        uint8_t* data = (uint8_t*)malloc(c.encodedCertificate.size());
-
-        memcpy(data, c.encodedCertificate.data(), c.encodedCertificate.size());
-        kCert.entries[index].data = (const uint8_t*)data;
-        index++;
-    }
-
-    return kCert;
-}
-
-bool AttestationCertificateParser::parse() {
-    optional<keymaster_cert_chain_t> cert_chain = certificateChainToKeymasterChain(origCertChain_);
-    if (!cert_chain) {
-        return false;
-    }
-
-    if (cert_chain.value().entry_count < 3) {
-        return false;
-    }
-
-    if (!verifyChain(cert_chain.value())) {
-        return false;
-    }
-
-    if (!verifyAttestationRecord(cert_chain.value().entries[0])) {
-        return false;
-    }
-
-    keymaster_free_cert_chain(&cert_chain.value());
-    return true;
-}
-
-ASN1_OCTET_STRING* AttestationCertificateParser::getAttestationRecord(X509* certificate) {
-    ASN1_OBJECT_Ptr oid(OBJ_txt2obj(kAttestionRecordOid, 1));
-    if (!oid.get()) return nullptr;
-
-    int location = X509_get_ext_by_OBJ(certificate, oid.get(), -1);
-    if (location == -1) return nullptr;
-
-    X509_EXTENSION* attest_rec_ext = X509_get_ext(certificate, location);
-    if (!attest_rec_ext) return nullptr;
-
-    ASN1_OCTET_STRING* attest_rec = X509_EXTENSION_get_data(attest_rec_ext);
-    return attest_rec;
-}
-
-X509* AttestationCertificateParser::parseCertBlob(const keymaster_blob_t& blob) {
-    const uint8_t* p = blob.data;
-    return d2i_X509(nullptr, &p, blob.data_length);
-}
-
-bool AttestationCertificateParser::verifyAttestationRecord(
-        const keymaster_blob_t& attestation_cert) {
-    X509_Ptr cert(parseCertBlob(attestation_cert));
-    if (!cert.get()) {
-        return false;
-    }
-
-    ASN1_OCTET_STRING* attest_rec = getAttestationRecord(cert.get());
-    if (!attest_rec) {
-        return false;
-    }
-
-    keymaster_blob_t att_unique_id = {};
-    keymaster_blob_t att_challenge;
-    keymaster_error_t ret = parse_attestation_record(
-            attest_rec->data, attest_rec->length, &att_attestation_version_,
-            &att_attestation_security_level_, &att_keymaster_version_,
-            &att_keymaster_security_level_, &att_challenge, &att_sw_enforced_, &att_hw_enforced_,
-            &att_unique_id);
-    if (ret) {
-        return false;
-    }
-
-    att_challenge_.assign(att_challenge.data, att_challenge.data + att_challenge.data_length);
-    return true;
-}
-
-uint32_t AttestationCertificateParser::getKeymasterVersion() {
-    return att_keymaster_version_;
-}
-
-uint32_t AttestationCertificateParser::getAttestationVersion() {
-    return att_attestation_version_;
-}
-
-vector<uint8_t> AttestationCertificateParser::getAttestationChallenge() {
-    return att_challenge_;
-}
-
-keymaster_security_level_t AttestationCertificateParser::getKeymasterSecurityLevel() {
-    return att_keymaster_security_level_;
-}
-
-keymaster_security_level_t AttestationCertificateParser::getAttestationSecurityLevel() {
-    return att_attestation_security_level_;
-}
-
-// Verify the Attestation certificates are correctly chained.
-bool AttestationCertificateParser::verifyChain(const keymaster_cert_chain_t& chain) {
-    for (size_t i = 0; i < chain.entry_count - 1; ++i) {
-        keymaster_blob_t& key_cert_blob = chain.entries[i];
-        keymaster_blob_t& signing_cert_blob = chain.entries[i + 1];
-
-        X509_Ptr key_cert(parseCertBlob(key_cert_blob));
-        X509_Ptr signing_cert(parseCertBlob(signing_cert_blob));
-        if (!key_cert.get() || !signing_cert.get()) {
-            return false;
-        }
-
-        EVP_PKEY_Ptr signing_pubkey(X509_get_pubkey(signing_cert.get()));
-        if (!signing_pubkey.get()) return false;
-
-        if (X509_verify(key_cert.get(), signing_pubkey.get()) != 1) {
-            return false;
-        }
-
-        if (i + 1 == chain.entry_count - 1) {
-            // Last entry is self-signed.
-            if (X509_verify(signing_cert.get(), signing_pubkey.get()) != 1) {
-                return false;
-            }
-        }
-    }
-
-    return true;
-}
-
-}  // namespace android::hardware::identity::test_utils
diff --git a/identity/aidl/vts/VtsAttestationParserSupport.h b/identity/aidl/vts/VtsAttestationParserSupport.h
deleted file mode 100644
index 7c7e1b6..0000000
--- a/identity/aidl/vts/VtsAttestationParserSupport.h
+++ /dev/null
@@ -1,122 +0,0 @@
-
-/*
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef VTS_ATTESTATION_PARSER_SUPPORT_H
-#define VTS_ATTESTATION_PARSER_SUPPORT_H
-
-//#include <aidl/Gtest.h>
-#include <android/hardware/identity/IIdentityCredentialStore.h>
-#include <android/hardware/identity/support/IdentityCredentialSupport.h>
-#include <android/hardware/keymaster/4.0/types.h>
-#include <hardware/keymaster_defs.h>
-#include <keymaster/android_keymaster_utils.h>
-#include <keymaster/authorization_set.h>
-#include <keymaster/contexts/pure_soft_keymaster_context.h>
-#include <keymaster/contexts/soft_attestation_cert.h>
-#include <keymaster/keymaster_tags.h>
-#include <keymaster/km_openssl/attestation_utils.h>
-#include <vector>
-
-namespace android::hardware::identity::test_utils {
-
-using ::std::optional;
-using ::std::string;
-using ::std::vector;
-
-using ::keymaster::AuthorizationSet;
-using ::keymaster::TypedTag;
-
-class AttestationCertificateParser {
-  public:
-    AttestationCertificateParser(const vector<Certificate>& certChain)
-        : origCertChain_(certChain) {}
-
-    bool parse();
-
-    uint32_t getKeymasterVersion();
-    uint32_t getAttestationVersion();
-    vector<uint8_t> getAttestationChallenge();
-    keymaster_security_level_t getKeymasterSecurityLevel();
-    keymaster_security_level_t getAttestationSecurityLevel();
-
-    template <keymaster_tag_t Tag>
-    bool getSwEnforcedBool(TypedTag<KM_BOOL, Tag> tag) {
-        if (att_sw_enforced_.GetTagValue(tag)) {
-            return true;
-        }
-
-        return false;
-    }
-
-    template <keymaster_tag_t Tag>
-    bool getHwEnforcedBool(TypedTag<KM_BOOL, Tag> tag) {
-        if (att_hw_enforced_.GetTagValue(tag)) {
-            return true;
-        }
-
-        return false;
-    }
-
-    template <keymaster_tag_t Tag>
-    optional<vector<uint8_t>> getHwEnforcedBlob(TypedTag<KM_BYTES, Tag> tag) {
-        keymaster_blob_t blob;
-        if (att_hw_enforced_.GetTagValue(tag, &blob)) {
-            return {};
-        }
-
-        vector<uint8_t> ret(blob.data, blob.data + blob.data_length);
-        return ret;
-    }
-
-    template <keymaster_tag_t Tag>
-    optional<vector<uint8_t>> getSwEnforcedBlob(TypedTag<KM_BYTES, Tag> tag) {
-        keymaster_blob_t blob;
-        if (!att_sw_enforced_.GetTagValue(tag, &blob)) {
-            return {};
-        }
-
-        vector<uint8_t> ret(blob.data, blob.data + blob.data_length);
-        return ret;
-    }
-
-  private:
-    // Helper functions.
-    bool verifyChain(const keymaster_cert_chain_t& chain);
-
-    ASN1_OCTET_STRING* getAttestationRecord(X509* certificate);
-
-    X509* parseCertBlob(const keymaster_blob_t& blob);
-
-    bool verifyAttestationRecord(const keymaster_blob_t& attestation_cert);
-
-    optional<keymaster_cert_chain_t> certificateChainToKeymasterChain(
-            const vector<Certificate>& certificates);
-
-    // Private variables.
-    vector<Certificate> origCertChain_;
-    AuthorizationSet att_sw_enforced_;
-    AuthorizationSet att_hw_enforced_;
-    uint32_t att_attestation_version_;
-    uint32_t att_keymaster_version_;
-    keymaster_security_level_t att_attestation_security_level_;
-    keymaster_security_level_t att_keymaster_security_level_;
-    vector<uint8_t> att_challenge_;
-};
-
-}  // namespace android::hardware::identity::test_utils
-
-#endif  // VTS_ATTESTATION_PARSER_SUPPORT_H
diff --git a/identity/aidl/vts/VtsAttestationTests.cpp b/identity/aidl/vts/VtsAttestationTests.cpp
index c7cdfc7..e5871fb 100644
--- a/identity/aidl/vts/VtsAttestationTests.cpp
+++ b/identity/aidl/vts/VtsAttestationTests.cpp
@@ -29,7 +29,6 @@
 #include <future>
 #include <map>
 
-#include "VtsAttestationParserSupport.h"
 #include "VtsIdentityTestUtils.h"
 
 namespace android::hardware::identity {
@@ -44,7 +43,6 @@
 using ::android::String16;
 using ::android::binder::Status;
 
-using test_utils::AttestationCertificateParser;
 using test_utils::setupWritableCredential;
 using test_utils::validateAttestationCertificate;
 
@@ -61,38 +59,12 @@
     sp<IIdentityCredentialStore> credentialStore_;
 };
 
-TEST_P(VtsAttestationTests, verifyAttestationWithNonemptyChallengeEmptyId) {
-    Status result;
-
-    HardwareInformation hwInfo;
-    ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
-
-    sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(setupWritableCredential(writableCredential, credentialStore_));
-
-    string challenge = "NotSoRandomChallenge";
-    vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
-    vector<Certificate> attestationCertificate;
-    vector<uint8_t> attestationApplicationId = {};
-
-    result = writableCredential->getAttestationCertificate(
-            attestationApplicationId, attestationChallenge, &attestationCertificate);
-
-    ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
-                               << endl;
-
-    EXPECT_TRUE(validateAttestationCertificate(attestationCertificate, attestationChallenge,
-                                               attestationApplicationId, hwInfo));
-}
-
 TEST_P(VtsAttestationTests, verifyAttestationWithNonemptyChallengeNonemptyId) {
     Status result;
 
-    HardwareInformation hwInfo;
-    ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
-
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(setupWritableCredential(writableCredential, credentialStore_,
+                                        false /* testCredential */));
 
     string challenge = "NotSoRandomChallenge1NotSoRandomChallenge1NotSoRandomChallenge1";
     vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
@@ -106,18 +78,16 @@
     ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                << endl;
 
-    EXPECT_TRUE(validateAttestationCertificate(attestationCertificate, attestationChallenge,
-                                               attestationApplicationId, hwInfo));
+    validateAttestationCertificate(attestationCertificate, attestationChallenge,
+                                   attestationApplicationId, false);
 }
 
 TEST_P(VtsAttestationTests, verifyAttestationWithVeryShortChallengeAndId) {
     Status result;
 
-    HardwareInformation hwInfo;
-    ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
-
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(setupWritableCredential(writableCredential, credentialStore_,
+                                        false /* testCredential */));
 
     string challenge = "c";
     vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
@@ -131,8 +101,8 @@
     ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                << endl;
 
-    EXPECT_TRUE(validateAttestationCertificate(attestationCertificate, attestationChallenge,
-                                               attestationApplicationId, hwInfo));
+    validateAttestationCertificate(attestationCertificate, attestationChallenge,
+                                   attestationApplicationId, false);
 }
 
 INSTANTIATE_TEST_SUITE_P(
diff --git a/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp b/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
index e347654..7657943 100644
--- a/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
+++ b/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
@@ -174,16 +174,17 @@
 
     string cborPretty;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    true /* testCredential */));
 
     string challenge = "attestationChallenge";
-    test_utils::AttestationData attData(writableCredential, challenge, {});
+    test_utils::AttestationData attData(writableCredential, challenge,
+                                        {1} /* atteestationApplicationId */);
     ASSERT_TRUE(attData.result.isOk())
             << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
 
-    EXPECT_TRUE(validateAttestationCertificate(attData.attestationCertificate,
-                                               attData.attestationChallenge,
-                                               attData.attestationApplicationId, hwInfo));
+    validateAttestationCertificate(attData.attestationCertificate, attData.attestationChallenge,
+                                   attData.attestationApplicationId, true);
 
     // This is kinda of a hack but we need to give the size of
     // ProofOfProvisioning that we'll expect to receive.
@@ -368,6 +369,7 @@
     optional<vector<uint8_t>> signingPubKey =
             support::certificateChainGetTopMostKey(signingKeyCertificate.encodedCertificate);
     EXPECT_TRUE(signingPubKey);
+    test_utils::verifyAuthKeyCertificate(signingKeyCertificate.encodedCertificate);
 
     // Since we're using a test-credential we know storageKey meaning we can get the
     // private key. Do this, derive the public key from it, and check this matches what
@@ -418,9 +420,9 @@
     }
 
     vector<uint8_t> mac;
-    vector<uint8_t> deviceNameSpacesBytes;
-    ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesBytes).isOk());
-    cborPretty = support::cborPrettyPrint(deviceNameSpacesBytes, 32, {});
+    vector<uint8_t> deviceNameSpacesEncoded;
+    ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesEncoded).isOk());
+    cborPretty = support::cborPrettyPrint(deviceNameSpacesEncoded, 32, {});
     ASSERT_EQ(
             "{\n"
             "  'PersonalData' : {\n"
@@ -435,37 +437,19 @@
             "  },\n"
             "}",
             cborPretty);
-    // The data that is MACed is ["DeviceAuthentication", sessionTranscript, docType,
-    // deviceNameSpacesBytes] so build up that structure
-    cppbor::Array deviceAuthentication;
-    deviceAuthentication.add("DeviceAuthentication");
-    deviceAuthentication.add(sessionTranscript.clone());
 
     string docType = "org.iso.18013-5.2019.mdl";
-    deviceAuthentication.add(docType);
-    deviceAuthentication.add(cppbor::Semantic(24, deviceNameSpacesBytes));
-    vector<uint8_t> deviceAuthenticationBytes =
-            cppbor::Semantic(24, deviceAuthentication.encode()).encode();
-    // Derive the key used for MACing.
     optional<vector<uint8_t>> readerEphemeralPrivateKey =
             support::ecKeyPairGetPrivateKey(readerEphemeralKeyPair.value());
-    optional<vector<uint8_t>> sharedSecret =
-            support::ecdh(signingPubKey.value(), readerEphemeralPrivateKey.value());
-    ASSERT_TRUE(sharedSecret);
-    // Mix-in SessionTranscriptBytes
-    vector<uint8_t> sessionTranscriptBytes =
-            cppbor::Semantic(24, sessionTranscript.encode()).encode();
-    vector<uint8_t> sharedSecretWithSessionTranscriptBytes = sharedSecret.value();
-    std::copy(sessionTranscriptBytes.begin(), sessionTranscriptBytes.end(),
-              std::back_inserter(sharedSecretWithSessionTranscriptBytes));
-    vector<uint8_t> salt = {0x00};
-    vector<uint8_t> info = {};
-    optional<vector<uint8_t>> derivedKey =
-            support::hkdf(sharedSecretWithSessionTranscriptBytes, salt, info, 32);
-    ASSERT_TRUE(derivedKey);
+    optional<vector<uint8_t>> eMacKey = support::calcEMacKey(
+            readerEphemeralPrivateKey.value(),                           // Private Key
+            signingPubKey.value(),                                       // Public Key
+            cppbor::Semantic(24, sessionTranscript.encode()).encode());  // SessionTranscriptBytes
     optional<vector<uint8_t>> calculatedMac =
-            support::coseMac0(derivedKey.value(), {},      // payload
-                              deviceAuthenticationBytes);  // detached content
+            support::calcMac(sessionTranscript.encode(),  // SessionTranscript
+                             docType,                     // DocType
+                             deviceNameSpacesEncoded,     // DeviceNamespaces
+                             eMacKey.value());            // EMacKey
     ASSERT_TRUE(calculatedMac);
     EXPECT_EQ(mac, calculatedMac);
 
@@ -480,18 +464,14 @@
                                 signingKeyBlob, sessionTranscriptEncoded, {},  // readerSignature,
                                 testEntriesEntryCounts)
                         .isOk());
-    ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesBytes).isOk());
-    cborPretty = support::cborPrettyPrint(deviceNameSpacesBytes, 32, {});
+    ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesEncoded).isOk());
+    cborPretty = support::cborPrettyPrint(deviceNameSpacesEncoded, 32, {});
     ASSERT_EQ("{}", cborPretty);
     // Calculate DeviceAuthentication and MAC (MACing key hasn't changed)
-    deviceAuthentication = cppbor::Array();
-    deviceAuthentication.add("DeviceAuthentication");
-    deviceAuthentication.add(sessionTranscript.clone());
-    deviceAuthentication.add(docType);
-    deviceAuthentication.add(cppbor::Semantic(24, deviceNameSpacesBytes));
-    deviceAuthenticationBytes = cppbor::Semantic(24, deviceAuthentication.encode()).encode();
-    calculatedMac = support::coseMac0(derivedKey.value(), {},      // payload
-                                      deviceAuthenticationBytes);  // detached content
+    calculatedMac = support::calcMac(sessionTranscript.encode(),  // SessionTranscript
+                                     docType,                     // DocType
+                                     deviceNameSpacesEncoded,     // DeviceNamespaces
+                                     eMacKey.value());            // EMacKey
     ASSERT_TRUE(calculatedMac);
     EXPECT_EQ(mac, calculatedMac);
 
@@ -506,18 +486,14 @@
                                 signingKeyBlob, sessionTranscriptEncoded, {},  // readerSignature,
                                 testEntriesEntryCounts)
                         .isOk());
-    ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesBytes).isOk());
-    cborPretty = support::cborPrettyPrint(deviceNameSpacesBytes, 32, {});
+    ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesEncoded).isOk());
+    cborPretty = support::cborPrettyPrint(deviceNameSpacesEncoded, 32, {});
     ASSERT_EQ("{}", cborPretty);
     // Calculate DeviceAuthentication and MAC (MACing key hasn't changed)
-    deviceAuthentication = cppbor::Array();
-    deviceAuthentication.add("DeviceAuthentication");
-    deviceAuthentication.add(sessionTranscript.clone());
-    deviceAuthentication.add(docType);
-    deviceAuthentication.add(cppbor::Semantic(24, deviceNameSpacesBytes));
-    deviceAuthenticationBytes = cppbor::Semantic(24, deviceAuthentication.encode()).encode();
-    calculatedMac = support::coseMac0(derivedKey.value(), {},      // payload
-                                      deviceAuthenticationBytes);  // detached content
+    calculatedMac = support::calcMac(sessionTranscript.encode(),  // SessionTranscript
+                                     docType,                     // DocType
+                                     deviceNameSpacesEncoded,     // DeviceNamespaces
+                                     eMacKey.value());            // EMacKey
     ASSERT_TRUE(calculatedMac);
     EXPECT_EQ(mac, calculatedMac);
 }
diff --git a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
index b572b0f..5435ed8 100644
--- a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
+++ b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
@@ -61,7 +61,8 @@
     ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
 
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     vector<uint8_t> attestationChallenge;
     vector<Certificate> attestationCertificate;
@@ -82,12 +83,13 @@
     ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
 
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     string challenge = "NotSoRandomChallenge1NotSoRandomChallenge1NotSoRandomChallenge1";
     vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
     vector<Certificate> attestationCertificate;
-    vector<uint8_t> attestationApplicationId = {};
+    vector<uint8_t> attestationApplicationId = {1};
 
     result = writableCredential->getAttestationCertificate(
             attestationApplicationId, attestationChallenge, &attestationCertificate);
@@ -95,27 +97,27 @@
     EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                << endl;
 
-    EXPECT_TRUE(test_utils::validateAttestationCertificate(
-            attestationCertificate, attestationChallenge, attestationApplicationId, hwInfo));
+    test_utils::validateAttestationCertificate(attestationCertificate, attestationChallenge,
+                                               attestationApplicationId, false);
 }
 
 TEST_P(IdentityCredentialTests, verifyAttestationDoubleCallFails) {
     Status result;
 
-    HardwareInformation hwInfo;
-    ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
-
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     string challenge = "NotSoRandomChallenge1";
-    test_utils::AttestationData attData(writableCredential, challenge, {});
-    ASSERT_TRUE(test_utils::validateAttestationCertificate(
-            attData.attestationCertificate, attData.attestationChallenge,
-            attData.attestationApplicationId, hwInfo));
+    test_utils::AttestationData attData(writableCredential, challenge,
+                                        {1} /* atteestationApplicationId */);
+    test_utils::validateAttestationCertificate(attData.attestationCertificate,
+                                               attData.attestationChallenge,
+                                               attData.attestationApplicationId, false);
 
     string challenge2 = "NotSoRandomChallenge2";
-    test_utils::AttestationData attData2(writableCredential, challenge2, {});
+    test_utils::AttestationData attData2(writableCredential, challenge2,
+                                         {} /* atteestationApplicationId */);
     EXPECT_FALSE(attData2.result.isOk()) << attData2.result.exceptionCode() << "; "
                                          << attData2.result.exceptionMessage() << endl;
     EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, attData2.result.exceptionCode());
@@ -125,7 +127,8 @@
 TEST_P(IdentityCredentialTests, verifyStartPersonalization) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     // First call should go through
     const vector<int32_t> entryCounts = {2, 4};
@@ -147,7 +150,8 @@
 TEST_P(IdentityCredentialTests, verifyStartPersonalizationMin) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     // Verify minimal number of profile count and entry count
     const vector<int32_t> entryCounts = {1, 1};
@@ -160,7 +164,8 @@
 TEST_P(IdentityCredentialTests, verifyStartPersonalizationOne) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     // Verify minimal number of profile count and entry count
     const vector<int32_t> entryCounts = {1};
@@ -173,7 +178,8 @@
 TEST_P(IdentityCredentialTests, verifyStartPersonalizationLarge) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     // Verify set a large number of profile count and entry count is ok
     const vector<int32_t> entryCounts = {3000};
@@ -186,7 +192,8 @@
 TEST_P(IdentityCredentialTests, verifyProfileNumberMismatchShouldFail) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     // Enter mismatched entry and profile numbers
     const vector<int32_t> entryCounts = {5, 6};
@@ -224,7 +231,8 @@
 TEST_P(IdentityCredentialTests, verifyDuplicateProfileId) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     const vector<int32_t> entryCounts = {3, 6};
     writableCredential->setExpectedProofOfProvisioningSize(123456);
@@ -283,10 +291,12 @@
     ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
 
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     string challenge = "NotSoRandomChallenge1";
-    test_utils::AttestationData attData(writableCredential, challenge, {});
+    test_utils::AttestationData attData(writableCredential, challenge,
+                                        {} /* atteestationApplicationId */);
     EXPECT_TRUE(attData.result.isOk())
             << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
 
@@ -294,7 +304,7 @@
     ASSERT_TRUE(readerCertificate1);
 
     const vector<int32_t> entryCounts = {1u};
-    size_t expectedPoPSize = 186 + readerCertificate1.value().size();
+    size_t expectedPoPSize = 185 + readerCertificate1.value().size();
     // OK to fail, not available in v1 HAL
     writableCredential->setExpectedProofOfProvisioningSize(expectedPoPSize);
     result = writableCredential->startPersonalization(1, entryCounts);
@@ -308,7 +318,7 @@
     ASSERT_TRUE(secureProfiles);
 
     const vector<test_utils::TestEntryData> testEntries1 = {
-            {"Name Space", "Last name", string("Turing"), vector<int32_t>{0, 1}},
+            {"Name Space", "Last name", string("Turing"), vector<int32_t>{1}},
     };
 
     map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
@@ -347,11 +357,11 @@
             "      {\n"
             "        'name' : 'Last name',\n"
             "        'value' : 'Turing',\n"
-            "        'accessControlProfiles' : [0, 1, ],\n"
+            "        'accessControlProfiles' : [1, ],\n"
             "      },\n"
             "    ],\n"
             "  },\n"
-            "  true,\n"
+            "  false,\n"
             "]",
             cborPretty);
 
@@ -370,10 +380,12 @@
     ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
 
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     string challenge = "NotSoRandomChallenge";
-    test_utils::AttestationData attData(writableCredential, challenge, {});
+    test_utils::AttestationData attData(writableCredential, challenge,
+                                        {} /* atteestationApplicationId */);
     EXPECT_TRUE(attData.result.isOk())
             << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
 
@@ -510,7 +522,7 @@
             "      },\n"
             "    ],\n"
             "  },\n"
-            "  true,\n"
+            "  false,\n"
             "]",
             cborPretty);
 
@@ -529,10 +541,12 @@
     ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
 
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     string challenge = "NotSoRandomChallenge";
-    test_utils::AttestationData attData(writableCredential, challenge, {});
+    test_utils::AttestationData attData(writableCredential, challenge,
+                                        {} /* atteestationApplicationId */);
     ASSERT_TRUE(attData.result.isOk())
             << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
 
@@ -591,10 +605,12 @@
     ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
 
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     string challenge = "NotSoRandomChallenge";
-    test_utils::AttestationData attData(writableCredential, challenge, {});
+    test_utils::AttestationData attData(writableCredential, challenge,
+                                        {} /* atteestationApplicationId */);
     ASSERT_TRUE(attData.result.isOk())
             << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
 
@@ -667,7 +683,8 @@
 
 TEST_P(IdentityCredentialTests, verifyAccessControlProfileIdOutOfRange) {
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
 
     const vector<int32_t> entryCounts = {1};
     writableCredential->setExpectedProofOfProvisioningSize(123456);
diff --git a/identity/aidl/vts/VtsIdentityTestUtils.cpp b/identity/aidl/vts/VtsIdentityTestUtils.cpp
index b6ed80f..3b10651 100644
--- a/identity/aidl/vts/VtsIdentityTestUtils.cpp
+++ b/identity/aidl/vts/VtsIdentityTestUtils.cpp
@@ -14,13 +14,17 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "VtsIdentityTestUtils"
+
 #include "VtsIdentityTestUtils.h"
 
 #include <aidl/Gtest.h>
+#include <android-base/logging.h>
+#include <keymaster/km_openssl/openssl_utils.h>
+#include <keymasterV4_1/attestation_record.h>
+#include <charconv>
 #include <map>
 
-#include "VtsAttestationParserSupport.h"
-
 namespace android::hardware::identity::test_utils {
 
 using std::endl;
@@ -32,15 +36,15 @@
 using ::android::sp;
 using ::android::String16;
 using ::android::binder::Status;
+using ::keymaster::X509_Ptr;
 
 bool setupWritableCredential(sp<IWritableIdentityCredential>& writableCredential,
-                             sp<IIdentityCredentialStore>& credentialStore) {
+                             sp<IIdentityCredentialStore>& credentialStore, bool testCredential) {
     if (credentialStore == nullptr) {
         return false;
     }
 
     string docType = "org.iso.18013-5.2019.mdl";
-    bool testCredential = true;
     Status result = credentialStore->createCredential(docType, testCredential, &writableCredential);
 
     if (result.isOk() && writableCredential != nullptr) {
@@ -178,63 +182,269 @@
     }
 }
 
-bool validateAttestationCertificate(const vector<Certificate>& inputCertificates,
-                                    const vector<uint8_t>& expectedChallenge,
-                                    const vector<uint8_t>& expectedAppId,
-                                    const HardwareInformation& hwInfo) {
-    AttestationCertificateParser certParser_(inputCertificates);
-    bool ret = certParser_.parse();
-    EXPECT_TRUE(ret);
-    if (!ret) {
+string x509NameToRfc2253String(X509_NAME* name) {
+    char* buf;
+    size_t bufSize;
+    BIO* bio;
+
+    bio = BIO_new(BIO_s_mem());
+    X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253);
+    bufSize = BIO_get_mem_data(bio, &buf);
+    string ret = string(buf, bufSize);
+    BIO_free(bio);
+
+    return ret;
+}
+
+int parseDigits(const char** s, int numDigits) {
+    int result;
+    auto [_, ec] = std::from_chars(*s, *s + numDigits, result);
+    if (ec != std::errc()) {
+        LOG(ERROR) << "Error parsing " << numDigits << " digits "
+                   << " from " << s;
+        return 0;
+    }
+    *s += numDigits;
+    return result;
+}
+
+bool parseAsn1Time(const ASN1_TIME* asn1Time, time_t* outTime) {
+    struct tm tm;
+
+    memset(&tm, '\0', sizeof(tm));
+    const char* timeStr = (const char*)asn1Time->data;
+    const char* s = timeStr;
+    if (asn1Time->type == V_ASN1_UTCTIME) {
+        tm.tm_year = parseDigits(&s, 2);
+        if (tm.tm_year < 70) {
+            tm.tm_year += 100;
+        }
+    } else if (asn1Time->type == V_ASN1_GENERALIZEDTIME) {
+        tm.tm_year = parseDigits(&s, 4) - 1900;
+        tm.tm_year -= 1900;
+    } else {
+        LOG(ERROR) << "Unsupported ASN1_TIME type " << asn1Time->type;
+        return false;
+    }
+    tm.tm_mon = parseDigits(&s, 2) - 1;
+    tm.tm_mday = parseDigits(&s, 2);
+    tm.tm_hour = parseDigits(&s, 2);
+    tm.tm_min = parseDigits(&s, 2);
+    tm.tm_sec = parseDigits(&s, 2);
+    // This may need to be updated if someone create certificates using +/- instead of Z.
+    //
+    if (*s != 'Z') {
+        LOG(ERROR) << "Expected Z in string '" << timeStr << "' at offset " << (s - timeStr);
         return false;
     }
 
-    // As per the IC HAL, the version of the Identity
-    // Credential HAL is 1.0 - and this is encoded as major*10 + minor. This field is used by
-    // Keymaster which is known to report integers less than or equal to 4 (for KM up to 4.0)
-    // and integers greater or equal than 41 (for KM starting with 4.1).
-    //
-    // Since we won't get to version 4.0 of the IC HAL for a while, let's also check that a KM
-    // version isn't errornously returned.
-    EXPECT_LE(10, certParser_.getKeymasterVersion());
-    EXPECT_GT(40, certParser_.getKeymasterVersion());
-    EXPECT_LE(3, certParser_.getAttestationVersion());
-
-    // Verify the app id matches to whatever we set it to be.
-    optional<vector<uint8_t>> appId =
-            certParser_.getSwEnforcedBlob(::keymaster::TAG_ATTESTATION_APPLICATION_ID);
-    if (appId) {
-        EXPECT_EQ(expectedAppId.size(), appId.value().size());
-        EXPECT_EQ(0, memcmp(expectedAppId.data(), appId.value().data(), expectedAppId.size()));
-    } else {
-        // app id not found
-        EXPECT_EQ(0, expectedAppId.size());
+    time_t t = timegm(&tm);
+    if (t == -1) {
+        LOG(ERROR) << "Error converting broken-down time to time_t";
+        return false;
     }
-
-    EXPECT_TRUE(certParser_.getHwEnforcedBool(::keymaster::TAG_IDENTITY_CREDENTIAL_KEY));
-    EXPECT_FALSE(certParser_.getHwEnforcedBool(::keymaster::TAG_INCLUDE_UNIQUE_ID));
-
-    // Verify the challenge always matches in size and data of what is passed
-    // in.
-    vector<uint8_t> attChallenge = certParser_.getAttestationChallenge();
-    EXPECT_EQ(expectedChallenge.size(), attChallenge.size());
-    EXPECT_EQ(0, memcmp(expectedChallenge.data(), attChallenge.data(), expectedChallenge.size()));
-
-    // Ensure the attestation conveys that it's implemented in secure hardware (with carve-out
-    // for the reference implementation which cannot be implemented in secure hardware).
-    if (hwInfo.credentialStoreName == "Identity Credential Reference Implementation" &&
-        hwInfo.credentialStoreAuthorName == "Google") {
-        EXPECT_LE(KM_SECURITY_LEVEL_SOFTWARE, certParser_.getKeymasterSecurityLevel());
-        EXPECT_LE(KM_SECURITY_LEVEL_SOFTWARE, certParser_.getAttestationSecurityLevel());
-
-    } else {
-        // Actual devices should use TrustedEnvironment or StrongBox.
-        EXPECT_LE(KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT, certParser_.getKeymasterSecurityLevel());
-        EXPECT_LE(KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT, certParser_.getAttestationSecurityLevel());
-    }
+    *outTime = t;
     return true;
 }
 
+void validateAttestationCertificate(const vector<Certificate>& credentialKeyCertChain,
+                                    const vector<uint8_t>& expectedChallenge,
+                                    const vector<uint8_t>& expectedAppId, bool isTestCredential) {
+    ASSERT_GE(credentialKeyCertChain.size(), 2);
+
+    vector<uint8_t> certBytes = credentialKeyCertChain[0].encodedCertificate;
+    const uint8_t* certData = certBytes.data();
+    X509_Ptr cert = X509_Ptr(d2i_X509(nullptr, &certData, certBytes.size()));
+
+    vector<uint8_t> batchCertBytes = credentialKeyCertChain[1].encodedCertificate;
+    const uint8_t* batchCertData = batchCertBytes.data();
+    X509_Ptr batchCert = X509_Ptr(d2i_X509(nullptr, &batchCertData, batchCertBytes.size()));
+
+    // First get some values from the batch certificate which is checked
+    // against the top-level certificate (subject, notAfter)
+    //
+
+    X509_NAME* batchSubject = X509_get_subject_name(batchCert.get());
+    ASSERT_NE(nullptr, batchSubject);
+    time_t batchNotAfter;
+    ASSERT_TRUE(parseAsn1Time(X509_get0_notAfter(batchCert.get()), &batchNotAfter));
+
+    // Check all the requirements from IWritableIdentityCredential::getAttestationCertificate()...
+    //
+
+    //  - version: INTEGER 2 (means v3 certificate).
+    EXPECT_EQ(2, X509_get_version(cert.get()));
+
+    //  - serialNumber: INTEGER 1 (fixed value: same on all certs).
+    EXPECT_EQ(1, ASN1_INTEGER_get(X509_get_serialNumber(cert.get())));
+
+    //  - signature: must be set to ECDSA.
+    EXPECT_EQ(NID_ecdsa_with_SHA256, X509_get_signature_nid(cert.get()));
+
+    //  - subject: CN shall be set to "Android Identity Credential Key". (fixed value:
+    //    same on all certs)
+    X509_NAME* subject = X509_get_subject_name(cert.get());
+    ASSERT_NE(nullptr, subject);
+    EXPECT_EQ("CN=Android Identity Credential Key", x509NameToRfc2253String(subject));
+
+    //  - issuer: Same as the subject field of the batch attestation key.
+    X509_NAME* issuer = X509_get_issuer_name(cert.get());
+    ASSERT_NE(nullptr, issuer);
+    EXPECT_EQ(x509NameToRfc2253String(batchSubject), x509NameToRfc2253String(issuer));
+
+    //  - validity: Should be from current time and expire at the same time as the
+    //    attestation batch certificate used.
+    //
+    //  Allow for 10 seconds drift to account for the time drift between Secure HW
+    //  and this environment plus the difference between when the certificate was
+    //  created and until now
+    //
+    time_t notBefore;
+    ASSERT_TRUE(parseAsn1Time(X509_get0_notBefore(cert.get()), &notBefore));
+    uint64_t now = time(nullptr);
+    int64_t diffSecs = now - notBefore;
+    int64_t allowDriftSecs = 10;
+    EXPECT_LE(-allowDriftSecs, diffSecs);
+    EXPECT_GE(allowDriftSecs, diffSecs);
+
+    time_t notAfter;
+    ASSERT_TRUE(parseAsn1Time(X509_get0_notAfter(cert.get()), &notAfter));
+    EXPECT_EQ(notAfter, batchNotAfter);
+
+    auto [err, attRec] = keymaster::V4_1::parse_attestation_record(certBytes);
+    ASSERT_EQ(keymaster::V4_1::ErrorCode::OK, err);
+
+    //  - subjectPublicKeyInfo: must contain attested public key.
+
+    //  - The attestationVersion field in the attestation extension must be at least 3.
+    EXPECT_GE(attRec.attestation_version, 3);
+
+    //  - The attestationSecurityLevel field must be set to either Software (0),
+    //    TrustedEnvironment (1), or StrongBox (2) depending on how attestation is
+    //    implemented.
+    EXPECT_GE(attRec.attestation_security_level,
+              keymaster::V4_0::SecurityLevel::TRUSTED_ENVIRONMENT);
+
+    //  - The keymasterVersion field in the attestation extension must be set to the.
+    //    same value as used for Android Keystore keys.
+    //
+    // Nothing to check here...
+
+    //  - The keymasterSecurityLevel field in the attestation extension must be set to
+    //    either Software (0), TrustedEnvironment (1), or StrongBox (2) depending on how
+    //    the Trusted Application backing the HAL implementation is implemented.
+    EXPECT_GE(attRec.keymaster_security_level, keymaster::V4_0::SecurityLevel::TRUSTED_ENVIRONMENT);
+
+    //  - The attestationChallenge field must be set to the passed-in challenge.
+    EXPECT_EQ(expectedChallenge.size(), attRec.attestation_challenge.size());
+    EXPECT_TRUE(memcmp(expectedChallenge.data(), attRec.attestation_challenge.data(),
+                       attRec.attestation_challenge.size()) == 0);
+
+    //  - The uniqueId field must be empty.
+    EXPECT_EQ(attRec.unique_id.size(), 0);
+
+    //  - The softwareEnforced field in the attestation extension must include
+    //    Tag::ATTESTATION_APPLICATION_ID which must be set to the bytes of the passed-in
+    //    attestationApplicationId.
+    EXPECT_TRUE(attRec.software_enforced.Contains(keymaster::V4_0::TAG_ATTESTATION_APPLICATION_ID,
+                                                  expectedAppId));
+
+    //  - The teeEnforced field in the attestation extension must include
+    //
+    //    - Tag::IDENTITY_CREDENTIAL_KEY which indicates that the key is an Identity
+    //      Credential key (which can only sign/MAC very specific messages) and not an Android
+    //      Keystore key (which can be used to sign/MAC anything). This must not be set
+    //      for test credentials.
+    bool hasIcKeyTag =
+            attRec.hardware_enforced.Contains(static_cast<android::hardware::keymaster::V4_0::Tag>(
+                    keymaster::V4_1::Tag::IDENTITY_CREDENTIAL_KEY));
+    if (isTestCredential) {
+        EXPECT_FALSE(hasIcKeyTag);
+    } else {
+        EXPECT_TRUE(hasIcKeyTag);
+    }
+
+    //    - Tag::PURPOSE must be set to SIGN
+    EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_PURPOSE,
+                                                  keymaster::V4_0::KeyPurpose::SIGN));
+
+    //    - Tag::KEY_SIZE must be set to the appropriate key size, in bits (e.g. 256)
+    EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_KEY_SIZE, 256));
+
+    //    - Tag::ALGORITHM must be set to EC
+    EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_ALGORITHM,
+                                                  keymaster::V4_0::Algorithm::EC));
+
+    //    - Tag::NO_AUTH_REQUIRED must be set
+    EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_NO_AUTH_REQUIRED));
+
+    //    - Tag::DIGEST must be include SHA_2_256
+    EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_DIGEST,
+                                                  keymaster::V4_0::Digest::SHA_2_256));
+
+    //    - Tag::EC_CURVE must be set to P_256
+    EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_EC_CURVE,
+                                                  keymaster::V4_0::EcCurve::P_256));
+
+    //    - Tag::ROOT_OF_TRUST must be set
+    //
+    EXPECT_GE(attRec.root_of_trust.security_level,
+              keymaster::V4_0::SecurityLevel::TRUSTED_ENVIRONMENT);
+
+    //    - Tag::OS_VERSION and Tag::OS_PATCHLEVEL must be set
+    EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_OS_VERSION));
+    EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_OS_PATCHLEVEL));
+
+    // TODO: we could retrieve osVersion and osPatchLevel from Android itself and compare it
+    // with what was reported in the certificate.
+}
+
+void verifyAuthKeyCertificate(const vector<uint8_t>& authKeyCertChain) {
+    const uint8_t* data = authKeyCertChain.data();
+    auto cert = X509_Ptr(d2i_X509(nullptr, &data, authKeyCertChain.size()));
+
+    //  - version: INTEGER 2 (means v3 certificate).
+    EXPECT_EQ(X509_get_version(cert.get()), 2);
+
+    //  - serialNumber: INTEGER 1 (fixed value: same on all certs).
+    EXPECT_EQ(ASN1_INTEGER_get(X509_get_serialNumber(cert.get())), 1);
+
+    //  - signature: must be set to ECDSA.
+    EXPECT_EQ(X509_get_signature_nid(cert.get()), NID_ecdsa_with_SHA256);
+
+    //  - subject: CN shall be set to "Android Identity Credential Authentication Key". (fixed
+    //    value: same on all certs)
+    X509_NAME* subject = X509_get_subject_name(cert.get());
+    ASSERT_NE(subject, nullptr);
+    EXPECT_EQ(x509NameToRfc2253String(subject),
+              "CN=Android Identity Credential Authentication Key");
+
+    //  - issuer: CN shall be set to "Android Identity Credential Key". (fixed value:
+    //    same on all certs)
+    X509_NAME* issuer = X509_get_issuer_name(cert.get());
+    ASSERT_NE(issuer, nullptr);
+    EXPECT_EQ(x509NameToRfc2253String(issuer), "CN=Android Identity Credential Key");
+
+    //  - subjectPublicKeyInfo: must contain attested public key.
+
+    //  - validity: should be from current time and one year in the future (365 days).
+    time_t notBefore, notAfter;
+    ASSERT_TRUE(parseAsn1Time(X509_get0_notAfter(cert.get()), &notAfter));
+    ASSERT_TRUE(parseAsn1Time(X509_get0_notBefore(cert.get()), &notBefore));
+
+    //  Allow for 10 seconds drift to account for the time drift between Secure HW
+    //  and this environment plus the difference between when the certificate was
+    //  created and until now
+    //
+    uint64_t now = time(nullptr);
+    int64_t diffSecs = now - notBefore;
+    int64_t allowDriftSecs = 10;
+    EXPECT_LE(-allowDriftSecs, diffSecs);
+    EXPECT_GE(allowDriftSecs, diffSecs);
+    constexpr uint64_t kSecsInOneYear = 365 * 24 * 60 * 60;
+    EXPECT_EQ(notBefore + kSecsInOneYear, notAfter);
+}
+
 vector<RequestNamespace> buildRequestNamespaces(const vector<TestEntryData> entries) {
     vector<RequestNamespace> ret;
     RequestNamespace curNs;
diff --git a/identity/aidl/vts/VtsIdentityTestUtils.h b/identity/aidl/vts/VtsIdentityTestUtils.h
index 673b736..85c24f8 100644
--- a/identity/aidl/vts/VtsIdentityTestUtils.h
+++ b/identity/aidl/vts/VtsIdentityTestUtils.h
@@ -34,8 +34,8 @@
 
 struct AttestationData {
     AttestationData(sp<IWritableIdentityCredential>& writableCredential, string challenge,
-                    vector<uint8_t> applicationId)
-        : attestationApplicationId(applicationId) {
+                    vector<uint8_t> attestationAppId)
+        : attestationApplicationId(attestationAppId) {
         // ASSERT_NE(writableCredential, nullptr);
 
         if (!challenge.empty()) {
@@ -94,7 +94,7 @@
 };
 
 bool setupWritableCredential(sp<IWritableIdentityCredential>& writableCredential,
-                             sp<IIdentityCredentialStore>& credentialStore);
+                             sp<IIdentityCredentialStore>& credentialStore, bool testCredential);
 
 optional<vector<uint8_t>> generateReaderCertificate(string serialDecimal);
 
@@ -111,13 +111,17 @@
 
 void setImageData(vector<uint8_t>& image);
 
-bool validateAttestationCertificate(const vector<Certificate>& inputCertificates,
+void validateAttestationCertificate(const vector<Certificate>& credentialKeyCertChain,
                                     const vector<uint8_t>& expectedChallenge,
-                                    const vector<uint8_t>& expectedAppId,
-                                    const HardwareInformation& hwInfo);
+                                    const vector<uint8_t>& expectedAppId, bool isTestCredential);
 
 vector<RequestNamespace> buildRequestNamespaces(const vector<TestEntryData> entries);
 
+// Verifies that the X.509 certificate for a just created authentication key
+// is valid.
+//
+void verifyAuthKeyCertificate(const vector<uint8_t>& authKeyCertChain);
+
 }  // namespace android::hardware::identity::test_utils
 
 #endif  // VTS_IDENTITY_TEST_UTILS_H
diff --git a/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h b/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
index f7ec7c5..3aa5bb6 100644
--- a/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
+++ b/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
@@ -35,6 +35,9 @@
 using ::std::vector;
 using ::std::pair;
 
+// The semantic tag for a bstr which includes Encoded CBOR (RFC 7049, section 2.4)
+const int kSemanticTagEncodedCbor = 24;
+
 // ---------------------------------------------------------------------------
 // Miscellaneous utilities.
 // ---------------------------------------------------------------------------
@@ -108,45 +111,47 @@
 // ---------------------------------------------------------------------------
 // EC crypto functionality / abstraction (only supports P-256).
 // ---------------------------------------------------------------------------
+
 // Creates an 256-bit EC key using the NID_X9_62_prime256v1 curve, returns the
-// PKCS#8 encoded key-pair.  Also generates an attestation
-// certificate using the |challenge| and |applicationId|, and returns the generated
-// certificate in X.509 certificate chain format.
+// DER encoded private key.  Also generates an attestation using the |challenge|
+// and |applicationId|, and returns the generated certificate chain.
 //
-// The attestation time fields used will be the current time, and expires in one year.
+// The notBeffore field will be the current time and the notAfter will be the same
+// same time as the batch certificate.
 //
 // The first parameter of the return value is the keyPair generated, second return in
 // the pair is the attestation certificate generated.
-optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> createEcKeyPairAndAttestation(
-        const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId);
-
-// Like createEcKeyPairAndAttestation() but allows you to choose the public key.
 //
+optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> createEcKeyPairAndAttestation(
+        const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId,
+        bool isTestCredential);
+
+// (TODO: remove when no longer used by 3rd party.)
 optional<vector<vector<uint8_t>>> createAttestationForEcPublicKey(
         const vector<uint8_t>& publicKey, const vector<uint8_t>& challenge,
         const vector<uint8_t>& applicationId);
 
 // Creates an 256-bit EC key using the NID_X9_62_prime256v1 curve, returns the
-// PKCS#8 encoded key-pair.
+// private key in DER format (as specified in RFC 5915).
 //
 optional<vector<uint8_t>> createEcKeyPair();
 
-// For an EC key |keyPair| encoded in PKCS#8 format, extracts the public key in
+// For an EC key |keyPair| encoded in DER format, extracts the public key in
 // uncompressed point form.
 //
 optional<vector<uint8_t>> ecKeyPairGetPublicKey(const vector<uint8_t>& keyPair);
 
-// For an EC key |keyPair| encoded in PKCS#8 format, extracts the private key as
+// For an EC key |keyPair| encoded in DER format, extracts the private key as
 // an EC uncompressed key.
 //
 optional<vector<uint8_t>> ecKeyPairGetPrivateKey(const vector<uint8_t>& keyPair);
 
-// Creates a PKCS#8 encoded key-pair from a private key (which must be uncompressed,
-// e.g. 32 bytes). The public key is derived from the given private key..
+// Creates a DER encoded representation from a private key (which must be uncompressed,
+// e.g. 32 bytes).
 //
 optional<vector<uint8_t>> ecPrivateKeyToKeyPair(const vector<uint8_t>& privateKey);
 
-// For an EC key |keyPair| encoded in PKCS#8 format, creates a PKCS#12 structure
+// For an EC key |keyPair| encoded in DER format, creates a PKCS#12 structure
 // with the key-pair (not using a password to encrypt the data). The public key
 // in the created structure is included as a certificate, using the given fields
 // |serialDecimal|, |issuer|, |subject|, |validityNotBefore|, and
@@ -209,6 +214,13 @@
 //
 optional<pair<size_t, size_t>> certificateFindSignature(const vector<uint8_t>& x509Certificate);
 
+// Extracts notBefore and notAfter from the top-most certificate in |certificateChain
+// (which should be a concatenated chain of DER-encoded X.509 certificates).
+//
+// Returns notBefore and notAfter in that order.
+//
+optional<pair<time_t, time_t>> certificateGetValidity(const vector<uint8_t>& x509Certificate);
+
 // Generates a X.509 certificate for |publicKey| (which must be in the format
 // returned by ecKeyPairGetPublicKey()).
 //
@@ -351,6 +363,15 @@
 // Utility functions specific to IdentityCredential.
 // ---------------------------------------------------------------------------
 
+optional<vector<uint8_t>> calcMac(const vector<uint8_t>& sessionTranscriptEncoded,
+                                  const string& docType,
+                                  const vector<uint8_t>& deviceNameSpacesEncoded,
+                                  const vector<uint8_t>& eMacKey);
+
+optional<vector<uint8_t>> calcEMacKey(const vector<uint8_t>& privateKey,
+                                      const vector<uint8_t>& publicKey,
+                                      const vector<uint8_t>& sessionTranscriptBytes);
+
 // Returns the testing AES-128 key where all bits are set to 0.
 const vector<uint8_t>& getTestHardwareBoundKey();
 
diff --git a/identity/support/src/IdentityCredentialSupport.cpp b/identity/support/src/IdentityCredentialSupport.cpp
index 8e099e7..08559c6 100644
--- a/identity/support/src/IdentityCredentialSupport.cpp
+++ b/identity/support/src/IdentityCredentialSupport.cpp
@@ -44,6 +44,7 @@
 
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
+#include <charconv>
 
 #include <cppbor.h>
 #include <cppbor_parse.h>
@@ -870,16 +871,97 @@
     return hmac;
 }
 
+int parseDigits(const char** s, int numDigits) {
+    int result;
+    auto [_, ec] = std::from_chars(*s, *s + numDigits, result);
+    if (ec != std::errc()) {
+        LOG(ERROR) << "Error parsing " << numDigits << " digits "
+                   << " from " << s;
+        return 0;
+    }
+    *s += numDigits;
+    return result;
+}
+
+bool parseAsn1Time(const ASN1_TIME* asn1Time, time_t* outTime) {
+    struct tm tm;
+
+    memset(&tm, '\0', sizeof(tm));
+    const char* timeStr = (const char*)asn1Time->data;
+    const char* s = timeStr;
+    if (asn1Time->type == V_ASN1_UTCTIME) {
+        tm.tm_year = parseDigits(&s, 2);
+        if (tm.tm_year < 70) {
+            tm.tm_year += 100;
+        }
+    } else if (asn1Time->type == V_ASN1_GENERALIZEDTIME) {
+        tm.tm_year = parseDigits(&s, 4) - 1900;
+        tm.tm_year -= 1900;
+    } else {
+        LOG(ERROR) << "Unsupported ASN1_TIME type " << asn1Time->type;
+        return false;
+    }
+    tm.tm_mon = parseDigits(&s, 2) - 1;
+    tm.tm_mday = parseDigits(&s, 2);
+    tm.tm_hour = parseDigits(&s, 2);
+    tm.tm_min = parseDigits(&s, 2);
+    tm.tm_sec = parseDigits(&s, 2);
+    // This may need to be updated if someone create certificates using +/- instead of Z.
+    //
+    if (*s != 'Z') {
+        LOG(ERROR) << "Expected Z in string '" << timeStr << "' at offset " << (s - timeStr);
+        return false;
+    }
+
+    time_t t = timegm(&tm);
+    if (t == -1) {
+        LOG(ERROR) << "Error converting broken-down time to time_t";
+        return false;
+    }
+    *outTime = t;
+    return true;
+}
+
 // Generates the attestation certificate with the parameters passed in.  Note
 // that the passed in |activeTimeMilliSeconds| |expireTimeMilliSeconds| are in
 // milli seconds since epoch.  We are setting them to milliseconds due to
 // requirement in AuthorizationSet KM_DATE fields.  The certificate created is
 // actually in seconds.
-optional<vector<vector<uint8_t>>> createAttestation(const EVP_PKEY* key,
-                                                    const vector<uint8_t>& applicationId,
-                                                    const vector<uint8_t>& challenge,
-                                                    uint64_t activeTimeMilliSeconds,
-                                                    uint64_t expireTimeMilliSeconds) {
+//
+// If 0 is passed for expiration time, the expiration time from batch
+// certificate will be used.
+//
+optional<vector<vector<uint8_t>>> createAttestation(
+        const EVP_PKEY* key, const vector<uint8_t>& applicationId, const vector<uint8_t>& challenge,
+        uint64_t activeTimeMilliSeconds, uint64_t expireTimeMilliSeconds, bool isTestCredential) {
+    const keymaster_cert_chain_t* attestation_chain =
+            ::keymaster::getAttestationChain(KM_ALGORITHM_EC, nullptr);
+    if (attestation_chain == nullptr) {
+        LOG(ERROR) << "Error getting attestation chain";
+        return {};
+    }
+    if (expireTimeMilliSeconds == 0) {
+        if (attestation_chain->entry_count < 1) {
+            LOG(ERROR) << "Expected at least one entry in attestation chain";
+            return {};
+        }
+        keymaster_blob_t* bcBlob = &(attestation_chain->entries[0]);
+        const uint8_t* bcData = bcBlob->data;
+        auto bc = X509_Ptr(d2i_X509(nullptr, &bcData, bcBlob->data_length));
+        time_t bcNotAfter;
+        if (!parseAsn1Time(X509_get0_notAfter(bc.get()), &bcNotAfter)) {
+            LOG(ERROR) << "Error getting notAfter from batch certificate";
+            return {};
+        }
+        expireTimeMilliSeconds = bcNotAfter * 1000;
+    }
+    const keymaster_key_blob_t* attestation_signing_key =
+            ::keymaster::getAttestationKey(KM_ALGORITHM_EC, nullptr);
+    if (attestation_signing_key == nullptr) {
+        LOG(ERROR) << "Error getting attestation key";
+        return {};
+    }
+
     ::keymaster::AuthorizationSet auth_set(
             ::keymaster::AuthorizationSetBuilder()
                     .Authorization(::keymaster::TAG_ATTESTATION_CHALLENGE, challenge.data(),
@@ -901,7 +983,7 @@
     ::keymaster::AuthorizationSet swEnforced(::keymaster::AuthorizationSetBuilder().Authorization(
             ::keymaster::TAG_CREATION_DATETIME, activeTimeMilliSeconds));
 
-    ::keymaster::AuthorizationSet hwEnforced(
+    ::keymaster::AuthorizationSetBuilder hwEnforcedBuilder =
             ::keymaster::AuthorizationSetBuilder()
                     .Authorization(::keymaster::TAG_PURPOSE, KM_PURPOSE_SIGN)
                     .Authorization(::keymaster::TAG_KEY_SIZE, 256)
@@ -909,34 +991,29 @@
                     .Authorization(::keymaster::TAG_NO_AUTH_REQUIRED)
                     .Authorization(::keymaster::TAG_DIGEST, KM_DIGEST_SHA_2_256)
                     .Authorization(::keymaster::TAG_EC_CURVE, KM_EC_CURVE_P_256)
-                    .Authorization(::keymaster::TAG_IDENTITY_CREDENTIAL_KEY));
+                    .Authorization(::keymaster::TAG_OS_VERSION, 42)
+                    .Authorization(::keymaster::TAG_OS_PATCHLEVEL, 43);
 
-    const keymaster_cert_chain_t* attestation_chain =
-            ::keymaster::getAttestationChain(KM_ALGORITHM_EC, nullptr);
-
-    if (attestation_chain == nullptr) {
-        LOG(ERROR) << "Error getting attestation chain";
-        return {};
+    // Only include TAG_IDENTITY_CREDENTIAL_KEY if it's not a test credential
+    if (!isTestCredential) {
+        hwEnforcedBuilder.Authorization(::keymaster::TAG_IDENTITY_CREDENTIAL_KEY);
     }
-
-    const keymaster_key_blob_t* attestation_signing_key =
-            ::keymaster::getAttestationKey(KM_ALGORITHM_EC, nullptr);
-    if (attestation_signing_key == nullptr) {
-        LOG(ERROR) << "Error getting attestation key";
-        return {};
-    }
+    ::keymaster::AuthorizationSet hwEnforced(hwEnforcedBuilder);
 
     keymaster_error_t error;
     ::keymaster::CertChainPtr cert_chain_out;
-    ::keymaster::PureSoftKeymasterContext context;
 
-    // set identity version to 10 per hal requirements specified in IWriteableCredential.hal
-    // For now, the identity version in the attestation is set in the keymaster
-    // version field in the portable keymaster lib, which is a bit misleading.
-    uint identity_version = 10;
+    // Pretend to be implemented in a trusted environment just so we can pass
+    // the VTS tests. Of course, this is a pretend-only game since hopefully no
+    // relying party is ever going to trust our batch key and those keys above
+    // it.
+    //
+    ::keymaster::PureSoftKeymasterContext context(KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT);
+
     error = generate_attestation_from_EVP(key, swEnforced, hwEnforced, auth_set, context,
-                                          identity_version, *attestation_chain,
-                                          *attestation_signing_key, &cert_chain_out);
+                                          ::keymaster::kCurrentKeymasterVersion, *attestation_chain,
+                                          *attestation_signing_key,
+                                          "Android Identity Credential Key", &cert_chain_out);
 
     if (KM_ERROR_OK != error || !cert_chain_out) {
         LOG(ERROR) << "Error generate attestation from EVP key" << error;
@@ -957,7 +1034,8 @@
 }
 
 optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> createEcKeyPairAndAttestation(
-        const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId) {
+        const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId,
+        bool isTestCredential) {
     auto ec_key = ::keymaster::EC_KEY_Ptr(EC_KEY_new());
     auto pkey = ::keymaster::EVP_PKEY_Ptr(EVP_PKEY_new());
     auto group = ::keymaster::EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
@@ -978,12 +1056,11 @@
         return {};
     }
 
-    uint64_t now = time(nullptr);
-    uint64_t secondsInOneYear = 365 * 24 * 60 * 60;
-    uint64_t expireTimeMs = (now + secondsInOneYear) * 1000;
+    uint64_t nowMs = time(nullptr) * 1000;
+    uint64_t expireTimeMs = 0;  // Set to same as batch certificate
 
-    optional<vector<vector<uint8_t>>> attestationCert =
-            createAttestation(pkey.get(), applicationId, challenge, now * 1000, expireTimeMs);
+    optional<vector<vector<uint8_t>>> attestationCert = createAttestation(
+            pkey.get(), applicationId, challenge, nowMs, expireTimeMs, isTestCredential);
     if (!attestationCert) {
         LOG(ERROR) << "Error create attestation from key and challenge";
         return {};
@@ -1031,14 +1108,12 @@
         return {};
     }
 
-    uint64_t now = (std::chrono::duration_cast<std::chrono::nanoseconds>(
-                    std::chrono::system_clock::now().time_since_epoch()).
-                    count()/ 1000000000);
-    uint64_t secondsInOneYear = 365 * 24 * 60 * 60;
-    uint64_t expireTimeMs = (now + secondsInOneYear) * 1000;
+    uint64_t nowMs = time(nullptr) * 1000;
+    uint64_t expireTimeMs = 0;  // Set to same as batch certificate
 
     optional<vector<vector<uint8_t>>> attestationCert =
-            createAttestation(pkey.get(), applicationId, challenge, now * 1000, expireTimeMs);
+            createAttestation(pkey.get(), applicationId, challenge, nowMs, expireTimeMs,
+                              false /* isTestCredential */);
     if (!attestationCert) {
         LOG(ERROR) << "Error create attestation from key and challenge";
         return {};
@@ -1652,6 +1727,32 @@
     return std::make_pair(tbsCertificateOffset, tbsCertificateSize);
 }
 
+optional<pair<time_t, time_t>> certificateGetValidity(const vector<uint8_t>& x509Certificate) {
+    vector<X509_Ptr> certs;
+    if (!parseX509Certificates(x509Certificate, certs)) {
+        LOG(ERROR) << "Error parsing certificates";
+        return {};
+    }
+    if (certs.size() < 1) {
+        LOG(ERROR) << "No certificates in chain";
+        return {};
+    }
+
+    time_t notBefore;
+    time_t notAfter;
+    if (!parseAsn1Time(X509_get0_notBefore(certs[0].get()), &notBefore)) {
+        LOG(ERROR) << "Error parsing notBefore";
+        return {};
+    }
+
+    if (!parseAsn1Time(X509_get0_notAfter(certs[0].get()), &notAfter)) {
+        LOG(ERROR) << "Error parsing notAfter";
+        return {};
+    }
+
+    return std::make_pair(notBefore, notAfter);
+}
+
 optional<pair<size_t, size_t>> certificateFindSignature(const vector<uint8_t>& x509Certificate) {
     vector<X509_Ptr> certs;
     if (!parseX509Certificates(x509Certificate, certs)) {
@@ -2224,6 +2325,49 @@
 // Utility functions specific to IdentityCredential.
 // ---------------------------------------------------------------------------
 
+optional<vector<uint8_t>> calcEMacKey(const vector<uint8_t>& privateKey,
+                                      const vector<uint8_t>& publicKey,
+                                      const vector<uint8_t>& sessionTranscriptBytes) {
+    optional<vector<uint8_t>> sharedSecret = support::ecdh(publicKey, privateKey);
+    if (!sharedSecret) {
+        LOG(ERROR) << "Error performing ECDH";
+        return {};
+    }
+    vector<uint8_t> salt = support::sha256(sessionTranscriptBytes);
+    vector<uint8_t> info = {'E', 'M', 'a', 'c', 'K', 'e', 'y'};
+    optional<vector<uint8_t>> derivedKey = support::hkdf(sharedSecret.value(), salt, info, 32);
+    if (!derivedKey) {
+        LOG(ERROR) << "Error performing HKDF";
+        return {};
+    }
+    return derivedKey.value();
+}
+
+optional<vector<uint8_t>> calcMac(const vector<uint8_t>& sessionTranscriptEncoded,
+                                  const string& docType,
+                                  const vector<uint8_t>& deviceNameSpacesEncoded,
+                                  const vector<uint8_t>& eMacKey) {
+    auto [sessionTranscriptItem, _, errMsg] = cppbor::parse(sessionTranscriptEncoded);
+    if (sessionTranscriptItem == nullptr) {
+        LOG(ERROR) << "Error parsing sessionTranscriptEncoded: " << errMsg;
+        return {};
+    }
+    // The data that is MACed is ["DeviceAuthentication", sessionTranscript, docType,
+    // deviceNameSpacesBytes] so build up that structure
+    cppbor::Array deviceAuthentication =
+            cppbor::Array()
+                    .add("DeviceAuthentication")
+                    .add(std::move(sessionTranscriptItem))
+                    .add(docType)
+                    .add(cppbor::Semantic(kSemanticTagEncodedCbor, deviceNameSpacesEncoded));
+    vector<uint8_t> deviceAuthenticationBytes =
+            cppbor::Semantic(kSemanticTagEncodedCbor, deviceAuthentication.encode()).encode();
+    optional<vector<uint8_t>> calculatedMac =
+            support::coseMac0(eMacKey, {},                 // payload
+                              deviceAuthenticationBytes);  // detached content
+    return calculatedMac;
+}
+
 vector<vector<uint8_t>> chunkVector(const vector<uint8_t>& content, size_t maxChunkSize) {
     vector<vector<uint8_t>> ret;
 
diff --git a/identity/support/tests/IdentityCredentialSupportTest.cpp b/identity/support/tests/IdentityCredentialSupportTest.cpp
index c356549..266f263 100644
--- a/identity/support/tests/IdentityCredentialSupportTest.cpp
+++ b/identity/support/tests/IdentityCredentialSupportTest.cpp
@@ -436,6 +436,300 @@
             support::cborPrettyPrint(mac.value()));
 }
 
+// Generates a private key in DER format for a small value of 'd'.
+//
+// Used for test vectors.
+//
+vector<uint8_t> p256PrivateKeyFromD(uint8_t d) {
+    vector<uint8_t> privateUncompressed;
+    privateUncompressed.resize(32);
+    privateUncompressed[31] = d;
+    optional<vector<uint8_t>> privateKey = support::ecPrivateKeyToKeyPair(privateUncompressed);
+    return privateKey.value();
+}
+
+std::pair<vector<uint8_t>, vector<uint8_t>> p256PrivateKeyGetXandY(
+        const vector<uint8_t> privateKey) {
+    optional<vector<uint8_t>> publicUncompressed = support::ecKeyPairGetPublicKey(privateKey);
+    vector<uint8_t> x = vector<uint8_t>(publicUncompressed.value().begin() + 1,
+                                        publicUncompressed.value().begin() + 33);
+    vector<uint8_t> y = vector<uint8_t>(publicUncompressed.value().begin() + 33,
+                                        publicUncompressed.value().begin() + 65);
+    return std::make_pair(x, y);
+}
+
+const cppbor::Item* findValueForTstr(const cppbor::Map* map, const string& keyValue) {
+    // TODO: Need cast until libcppbor's Map::get() is marked as const
+    auto [item, found] = ((cppbor::Map*)map)->get(keyValue);
+    if (!found) {
+        return nullptr;
+    }
+    return item.get();
+}
+
+const cppbor::Array* findArrayValueForTstr(const cppbor::Map* map, const string& keyValue) {
+    const cppbor::Item* item = findValueForTstr(map, keyValue);
+    if (item == nullptr) {
+        return nullptr;
+    }
+    return item->asArray();
+}
+
+const cppbor::Map* findMapValueForTstr(const cppbor::Map* map, const string& keyValue) {
+    const cppbor::Item* item = findValueForTstr(map, keyValue);
+    if (item == nullptr) {
+        return nullptr;
+    }
+    return item->asMap();
+}
+
+const cppbor::Semantic* findSemanticValueForTstr(const cppbor::Map* map, const string& keyValue) {
+    const cppbor::Item* item = findValueForTstr(map, keyValue);
+    if (item == nullptr) {
+        return nullptr;
+    }
+    return item->asSemantic();
+}
+
+const std::string findStringValueForTstr(const cppbor::Map* map, const string& keyValue) {
+    const cppbor::Item* item = findValueForTstr(map, keyValue);
+    if (item == nullptr) {
+        return nullptr;
+    }
+    const cppbor::Tstr* tstr = item->asTstr();
+    if (tstr == nullptr) {
+        return "";
+    }
+    return tstr->value();
+}
+
+TEST(IdentityCredentialSupport, testVectors_18013_5) {
+    // This is a test against known vectors for ISO 18013-5.
+    //
+    // The objective of this test is to verify that support::calcEMacKey() and
+    // support::calcMac() agree with the given test vectors.
+    //
+
+    // We're given static device key:
+    //
+    //     x: 28412803729898893058558238221310261427084375743576167377786533380249859400145
+    //     y: 65403602826180996396520286939226973026599920614829401631985882360676038096704
+    //     d: 11
+    //
+    vector<uint8_t> deviceKey = p256PrivateKeyFromD(11);
+    auto [deviceKeyX, deviceKeyY] = p256PrivateKeyGetXandY(deviceKey);
+    EXPECT_EQ(support::encodeHex(deviceKeyX),
+              "3ed113b7883b4c590638379db0c21cda16742ed0255048bf433391d374bc21d1");
+    EXPECT_EQ(support::encodeHex(deviceKeyY),
+              "9099209accc4c8a224c843afa4f4c68a090d04da5e9889dae2f8eefce82a3740");
+
+    // We're given Ephemeral reader key:
+    //
+    //   x: 59535862115950685744176693329402396749019581632805653266809849538337418304154
+    //   y: 53776829996815113213100700404832701936765102413212294632483274374518863708344
+    //   d: 20
+    //
+    vector<uint8_t> ephemeralReaderKey = p256PrivateKeyFromD(20);
+    auto [ephemeralReaderKeyX, ephemeralReaderKeyY] = p256PrivateKeyGetXandY(ephemeralReaderKey);
+    EXPECT_EQ(support::encodeHex(ephemeralReaderKeyX),
+              "83a01a9378395bab9bcd6a0ad03cc56d56e6b19250465a94a234dc4c6b28da9a");
+    EXPECT_EQ(support::encodeHex(ephemeralReaderKeyY),
+              "76e49b6de2f73234ae6a5eb9d612b75c9f2202bb6923f54ff8240aaa86f640b8");
+    vector<uint8_t> ephemeralReaderKeyPublic =
+            support::ecKeyPairGetPublicKey(ephemeralReaderKey).value();
+
+    // We're given SessionEstablishment.
+    //
+    //   SessionEstablishment = {
+    //     "eReaderKey" : EReaderKeyBytes,
+    //     "data" : bstr ; Encrypted mdoc request
+    //   }
+    //
+    // Fish out EReaderKey from this.
+    //
+    // Note that the test vector below is incorrect insofar that it uses
+    // "eReaderKeyBytes" instead of just "eReaderKey". This will be corrected in
+    // the future.
+    //
+    optional<vector<uint8_t>> sessionEstablishmentEncoded = support::decodeHex(
+            "a26f655265616465724b65794279746573d818584ba40102200121582083a01a9378395bab9bcd6a0ad03c"
+            "c56d56e6b19250465a94a234dc4c6b28da9a22582076e49b6de2f73234ae6a5eb9d612b75c9f2202bb6923"
+            "f54ff8240aaa86f640b864646174615902d945b31040c57491acb6d46a71f6c1f67a0b837df1bda9089fd0"
+            "3d0b1fdac3eeb2874a4ef6f90c97d03397186ba00a91102faae7e992e15f761d5662c3c37e3c6c2cfd2ebc"
+            "0bf59dbb8795e377bd7dd353230a41ba2d82294b45871a39b42ca531f26b52f46e356fbaf5075c8fd5b8b0"
+            "8a0df4a1d2e1bdd2e5d69169c1efbb51e393e608d833d325bebfbccb2e15ec08f94b264582fa7b93f7cebc"
+            "aa69f4f0cac2744d4fe35b04df26b2ae69273eed33024949080c1c95a6ef046beede959e9494297dd770af"
+            "4ac6fdd56783aa012555c213dc05cf0f41d1c95119720fcfe1621027f80e2ddd56ea3c1fc596f7b2579333"
+            "5a887ec788092b4a69d23b6219e27d0249b50b3fdcb95b5227007689362e0416b3bae3dae7cb56b4394666"
+            "4e3a3f60dce8d0b678fcd754bebf87bd2b0278dd782d952488a46f2874e34c2dd97bb74084a62b850e9719"
+            "252cd1dca7dbf1858193f6cf093cb3735312bbe1138cf29d8f350e285923f8ef07065299926720b42264e8"
+            "fd5d4b133e72f47c4e999ea689c353f8b41e50a59838e1a0d09eca4a557f77a9c389a0591ad1639119ce86"
+            "edc3320130480ee5101effae6066e8c85aac9ead2ae83e49c1e508aab02f753decbb522ea2200d62fd5d26"
+            "094bd35100bffaa1cdc6af9f7e9cfe7b63da6b5671cd5ac2cf5da450c72addc64cde441f3b7f7fdaf930ad"
+            "1e13388e8a7308d8ca4607e59e082db431a232e7e12cb692baeb4b2127e110ff24cea322ffdbc2e4d9c4c6"
+            "bed27753137d07897c8613627a799a560cf1a2d1edb3de029442862940a5ed7785eea8b6ace93aa6af0792"
+            "fd82877f62d07b757d0179ecbb7347004ecc9c0690d41f75f188cb17ffd2cec2ad8c9675466bb33b737a2a"
+            "e7592b2dcb8132aced2e572266f3f5413a5f9d6d4339a1e4662622af2e7e157a4ea3bfd5c4247e2ec91d8c"
+            "5c3c17427d5edfae673d0e0f782a8d40fa805fd8bc82ae3cb21a65cdad863e02309f6b01d1753fa884b778"
+            "f6e019a2004d8964deeb11f1fd478fcb");
+    ASSERT_TRUE(sessionEstablishmentEncoded);
+    auto [sessionEstablishmentItem, _se, _se2] = cppbor::parse(sessionEstablishmentEncoded.value());
+    const cppbor::Map* sessionEstablishment = sessionEstablishmentItem->asMap();
+    ASSERT_NE(sessionEstablishment, nullptr);
+    const cppbor::Semantic* eReaderKeyBytes =
+            findSemanticValueForTstr(sessionEstablishment, "eReaderKeyBytes");
+    ASSERT_NE(eReaderKeyBytes, nullptr);
+    ASSERT_EQ(eReaderKeyBytes->value(), 24);
+    const cppbor::Bstr* eReaderKeyBstr = eReaderKeyBytes->child()->asBstr();
+    ASSERT_NE(eReaderKeyBstr, nullptr);
+    vector<uint8_t> eReaderKeyEncoded = eReaderKeyBstr->value();
+    // TODO: verify this agrees with ephemeralReaderKeyX and ephemeralReaderKeyY
+
+    // We're given DeviceEngagement.
+    //
+    vector<uint8_t> deviceEngagementEncoded =
+            support::decodeHex(
+                    "a20063312e30018201d818584ba401022001215820cef66d6b2a3a993e591214d1ea223fb545ca"
+                    "6c471c48306e4c36069404c5723f225820878662a229aaae906e123cdd9d3b4c10590ded29fe75"
+                    "1eeeca34bbaa44af0773")
+                    .value();
+
+    // Now calculate SessionTranscriptBytes. It is defined as
+    //
+    //   SessionTranscript = [
+    //      DeviceEngagementBytes,
+    //      EReaderKeyBytes,
+    //      Handover
+    //   ]
+    //
+    //   SessionTranscriptBytes = #6.24(bstr .cbor SessionTranscript)
+    //
+    cppbor::Array sessionTranscript;
+    sessionTranscript.add(cppbor::Semantic(24, deviceEngagementEncoded));
+    sessionTranscript.add(cppbor::Semantic(24, eReaderKeyEncoded));
+    sessionTranscript.add(cppbor::Null());
+    vector<uint8_t> sessionTranscriptEncoded = sessionTranscript.encode();
+    vector<uint8_t> sessionTranscriptBytes =
+            cppbor::Semantic(24, sessionTranscriptEncoded).encode();
+
+    // The expected EMacKey is 4c1ebb8aacc633465390fa44edfdb49cb57f2e079aaa771d812584699c0b97e2
+    //
+    // Verify that support::calcEMacKey() gets the same result.
+    //
+    optional<vector<uint8_t>> eMacKey =
+            support::calcEMacKey(support::ecKeyPairGetPrivateKey(deviceKey).value(),  // private key
+                                 ephemeralReaderKeyPublic,                            // public key
+                                 sessionTranscriptBytes);  // sessionTranscriptBytes
+    ASSERT_TRUE(eMacKey);
+    ASSERT_EQ(support::encodeHex(eMacKey.value()),
+              "4c1ebb8aacc633465390fa44edfdb49cb57f2e079aaa771d812584699c0b97e2");
+
+    // Also do it the other way around
+    //
+    optional<vector<uint8_t>> eMacKey2 = support::calcEMacKey(
+            support::ecKeyPairGetPrivateKey(ephemeralReaderKey).value(),  // private key
+            support::ecKeyPairGetPublicKey(deviceKey).value(),            // public key
+            sessionTranscriptBytes);                                      // sessionTranscriptBytes
+    ASSERT_TRUE(eMacKey2);
+    ASSERT_EQ(support::encodeHex(eMacKey2.value()),
+              "4c1ebb8aacc633465390fa44edfdb49cb57f2e079aaa771d812584699c0b97e2");
+
+    // We're given DeviceResponse
+    //
+    vector<uint8_t> deviceResponseEncoded =
+            support::decodeHex(
+                    "a36776657273696f6e63312e3069646f63756d656e747381a367646f6354797065756f72672e69"
+                    "736f2e31383031332e352e312e6d444c6c6973737565725369676e6564a26a6e616d6553706163"
+                    "6573a2716f72672e69736f2e31383031332e352e3181d8185863a4686469676573744944016672"
+                    "616e646f6d58208798645b20ea200e19ffabac92624bee6aec63aceedecfb1b80077d22bfc20e9"
+                    "71656c656d656e744964656e7469666965726b66616d696c795f6e616d656c656c656d656e7456"
+                    "616c756563446f656b636f6d2e6578616d706c6581d8185864a468646967657374494401667261"
+                    "6e646f6d5820218ecf13521b53f4b96abaebe56417afec0e4c91fc8fb26086cd1e5cdc1a94ff71"
+                    "656c656d656e744964656e7469666965726f616e6f746865725f656c656d656e746c656c656d65"
+                    "6e7456616c75650a6a697373756572417574688443a10126a118215901d2308201ce30820174a0"
+                    "0302010202141f7d44f4f107c5ee3f566049cf5d72de294b0d23300a06082a8648ce3d04030230"
+                    "233114301206035504030c0b75746f7069612069616361310b3009060355040613025553301e17"
+                    "0d3230313030313030303030305a170d3231313030313030303030305a30213112301006035504"
+                    "030c0975746f706961206473310b30090603550406130255533059301306072a8648ce3d020106"
+                    "082a8648ce3d03010703420004301d9e502dc7e05da85da026a7ae9aa0fac9db7d52a95b3e3e3f"
+                    "9aa0a1b45b8b6551b6f6b3061223e0d23c026b017d72298d9ae46887ca61d58db6aea17ee267a3"
+                    "8187308184301e0603551d120417301581136578616d706c65406578616d706c652e636f6d301c"
+                    "0603551d1f041530133011a00fa00d820b6578616d706c652e636f6d301d0603551d0e04160414"
+                    "7bef4db59a1ffb07592bfc57f4743b8a73aea792300e0603551d0f0101ff040403020780301506"
+                    "03551d250101ff040b3009060728818c5d050102300a06082a8648ce3d04030203480030450220"
+                    "21d52fb1fbda80e5bfda1e8dfb1bc7bf0acb7261d5c9ff54425af76eb21571c602210082bf301f"
+                    "89e0a2cb9ca9c9050352de80b47956764f7a3e07bf6a8cd87528a3b55901d2d8185901cda66776"
+                    "657273696f6e63312e306f646967657374416c676f726974686d675348412d3235366c76616c75"
+                    "6544696765737473a2716f72672e69736f2e31383031332e352e31a20058203b22af1126771f02"
+                    "f0ea0d546d4ee3c5b51637381154f5211b79daf5f9facaa8015820f2cba0ce3cde5df901a3da75"
+                    "13a4d7f7225fdfe5a306544529bf3dbcce655ca06b636f6d2e6578616d706c65a200582072636d"
+                    "ddc282424a63499f4b3927aaa3b74da7b9c0134178bf735e949e4a761e01582006322d3cbe6603"
+                    "876bdacc5b6679b51b0fc53d029c244fd5ea719d9028459c916d6465766963654b6579496e666f"
+                    "a1696465766963654b6579a4010220012158203ed113b7883b4c590638379db0c21cda16742ed0"
+                    "255048bf433391d374bc21d12258209099209accc4c8a224c843afa4f4c68a090d04da5e9889da"
+                    "e2f8eefce82a374067646f6354797065756f72672e69736f2e31383031332e352e312e6d444c6c"
+                    "76616c6964697479496e666fa3667369676e6564c074323032302d31302d30315431333a33303a"
+                    "30325a6976616c696446726f6dc074323032302d31302d30315431333a33303a30325a6a76616c"
+                    "6964556e74696cc074323032312d31302d30315431333a33303a30325a5840273ec1b59817d571"
+                    "b5a2c5c0ab0ea213d42acb18547fd7097afcc888a22ecbb863c6461ce0e240880895b4aaa84308"
+                    "784571c7be7aa3a2e7e3a2ea1a145ed1966c6465766963655369676e6564a26a6e616d65537061"
+                    "636573d81841a06a64657669636541757468a1696465766963654d61638443a10105a0f6582009"
+                    "da7c964ac004ec36ec64edd0c1abf50c03433c215c3ddb144768abcdf20a60667374617475730"
+                    "0")
+                    .value();
+    auto [deviceResponseItem, _, _2] = cppbor::parse(deviceResponseEncoded);
+    const cppbor::Map* deviceResponse = deviceResponseItem->asMap();
+    ASSERT_NE(deviceResponse, nullptr);
+    const cppbor::Array* documents = findArrayValueForTstr(deviceResponse, "documents");
+    ASSERT_NE(documents, nullptr);
+    ASSERT_EQ(documents->size(), 1);
+    const cppbor::Map* document = ((*documents)[0])->asMap();
+    ASSERT_NE(document, nullptr);
+
+    // Get docType
+    string docType = findStringValueForTstr(document, "docType");
+    ASSERT_EQ(docType, "org.iso.18013.5.1.mDL");
+
+    // Drill down...
+    const cppbor::Map* deviceSigned = findMapValueForTstr(document, "deviceSigned");
+    ASSERT_NE(deviceSigned, nullptr);
+
+    // Dig out the encoded form of DeviceNameSpaces
+    //
+    const cppbor::Semantic* deviceNameSpacesBytes =
+            findSemanticValueForTstr(deviceSigned, "nameSpaces");
+    ASSERT_NE(deviceNameSpacesBytes, nullptr);
+    ASSERT_EQ(deviceNameSpacesBytes->value(), 24);
+    const cppbor::Bstr* deviceNameSpacesBstr = deviceNameSpacesBytes->child()->asBstr();
+    ASSERT_NE(deviceNameSpacesBstr, nullptr);
+    vector<uint8_t> deviceNameSpacesEncoded = deviceNameSpacesBstr->value();
+
+    // (For this version of 18013-5, DeviceNameSpaces is always supposed to be empty, check that.)
+    EXPECT_EQ(deviceNameSpacesEncoded, cppbor::Map().encode());
+
+    const cppbor::Map* deviceAuth = findMapValueForTstr(deviceSigned, "deviceAuth");
+    ASSERT_NE(deviceAuth, nullptr);
+    // deviceMac is is the COSE_Mac0.. dig out the encoded form to check that
+    // support::calcMac() gives exactly the same bytes.
+    //
+    const cppbor::Array* deviceMac = findArrayValueForTstr(deviceAuth, "deviceMac");
+    ASSERT_NE(deviceMac, nullptr);
+    vector<uint8_t> deviceMacEncoded = deviceMac->encode();
+
+    // Now we calculate what it should be..
+    optional<vector<uint8_t>> calculatedMac =
+            support::calcMac(sessionTranscriptEncoded,  // SessionTranscript
+                             docType,                   // DocType
+                             deviceNameSpacesEncoded,   // DeviceNamespaces
+                             eMacKey.value());          // EMacKey
+    ASSERT_TRUE(calculatedMac);
+
+    // ... and hopefully it's the same!
+    ASSERT_EQ(calculatedMac.value().size(), deviceMacEncoded.size());
+    EXPECT_TRUE(memcmp(calculatedMac.value().data(), deviceMacEncoded.data(),
+                       deviceMacEncoded.size()) == 0);
+}
+
 }  // namespace identity
 }  // namespace hardware
 }  // namespace android
diff --git a/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h b/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
index ff08066..3e29206 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
@@ -17,6 +17,7 @@
 #ifndef SYSTEM_SECURITY_KEYSTORE_KM4_AUTHORIZATION_SET_H_
 #define SYSTEM_SECURITY_KEYSTORE_KM4_AUTHORIZATION_SET_H_
 
+#include <functional>
 #include <vector>
 
 #include <keymasterV4_0/keymaster_tags.h>
@@ -165,11 +166,12 @@
      */
     bool Contains(Tag tag) const { return find(tag) != -1; }
 
-    template <TagType tag_type, Tag tag, typename ValueT>
-    bool Contains(TypedTag<tag_type, tag> ttag, const ValueT& value) const {
+    template <TagType tag_type, Tag tag, typename ValueT, typename Comparator = std::equal_to<>>
+    bool Contains(TypedTag<tag_type, tag> ttag, const ValueT& value,
+                  Comparator cmp = Comparator()) const {
         for (const auto& param : data_) {
             auto entry = authorizationValue(ttag, param);
-            if (entry.isOk() && static_cast<ValueT>(entry.value()) == value) return true;
+            if (entry.isOk() && cmp(static_cast<ValueT>(entry.value()), value)) return true;
         }
         return false;
     }
diff --git a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
index bc7f311..befb7d3 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
@@ -73,6 +73,9 @@
 static const int32_t KM_TAG_DIGEST_OLD = static_cast<int32_t>(TagType::ENUM) | 5;
 static const int32_t KM_TAG_PADDING_OLD = static_cast<int32_t>(TagType::ENUM) | 7;
 
+static const int32_t KM_TAG_FBE_ICE = static_cast<int32_t>(TagType::BOOL) | 16201;
+static const int32_t KM_TAG_KEY_TYPE = static_cast<int32_t>(TagType::UINT) | 16202;
+
 constexpr TagType typeFromTag(Tag tag) {
     return static_cast<TagType>(static_cast<uint32_t>(tag) & static_cast<uint32_t>(0xf0000000));
 }
diff --git a/keymaster/4.0/vts/functional/VerificationTokenTest.cpp b/keymaster/4.0/vts/functional/VerificationTokenTest.cpp
index bab1439..4f0a7a3 100644
--- a/keymaster/4.0/vts/functional/VerificationTokenTest.cpp
+++ b/keymaster/4.0/vts/functional/VerificationTokenTest.cpp
@@ -111,19 +111,19 @@
 
     EXPECT_GE(host_time_delta, time_to_sleep)
         << "We slept for " << time_to_sleep << " ms, the clock must have advanced by that much";
-    EXPECT_LE(host_time_delta, time_to_sleep + 20)
+    EXPECT_LE(host_time_delta, time_to_sleep + 100)
         << "The verifyAuthorization call took " << (host_time_delta - time_to_sleep)
         << " ms?  That's awful!";
 
     auto km_time_delta = result2.token.timestamp - result1.token.timestamp;
 
     // If not too much else is going on on the system, the time delta should be quite close.  Allow
-    // 2 ms of slop just to avoid test flakiness.
+    // 20 ms of slop just to avoid test flakiness.
     //
     // TODO(swillden): see if we can output values so they can be gathered across many runs and
     // report if times aren't nearly always <1ms apart.
-    EXPECT_LE(host_time_delta, km_time_delta + 2);
-    EXPECT_LE(km_time_delta, host_time_delta + 2);
+    EXPECT_LE(host_time_delta, km_time_delta + 20);
+    EXPECT_LE(km_time_delta, host_time_delta + 20);
     ASSERT_EQ(result1.token.mac.size(), result2.token.mac.size());
     ASSERT_NE(0,
               memcmp(result1.token.mac.data(), result2.token.mac.data(), result1.token.mac.size()));
@@ -172,14 +172,14 @@
 
     EXPECT_GE(host_time_delta, time_to_sleep)
             << "We slept for " << time_to_sleep << " ms, the clock must have advanced by that much";
-    EXPECT_LE(host_time_delta, time_to_sleep + 20)
+    EXPECT_LE(host_time_delta, time_to_sleep + 100)
             << "The verifyAuthorization call took " << (host_time_delta - time_to_sleep)
             << " ms?  That's awful!";
 
     auto km_time_delta = result2.token.timestamp - result1.token.timestamp;
 
-    EXPECT_LE(host_time_delta, km_time_delta + 2);
-    EXPECT_LE(km_time_delta, host_time_delta + 2);
+    EXPECT_LE(host_time_delta, km_time_delta + 20);
+    EXPECT_LE(km_time_delta, host_time_delta + 20);
     ASSERT_EQ(result1.token.mac.size(), result2.token.mac.size());
     ASSERT_NE(0,
               memcmp(result1.token.mac.data(), result2.token.mac.data(), result1.token.mac.size()));
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index aa2de2a..d669667 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -17,9 +17,12 @@
 #define LOG_TAG "keymaster_hidl_hal_test"
 #include <cutils/log.h>
 
-#include <iostream>
 #include <signal.h>
 
+#include <functional>
+#include <iostream>
+#include <string>
+
 #include <openssl/evp.h>
 #include <openssl/mem.h>
 #include <openssl/x509.h>
@@ -32,6 +35,8 @@
 
 #include "KeymasterHidlTest.h"
 
+using namespace std::string_literals;
+
 static bool arm_deleteAllKeys = false;
 static bool dump_Attestations = false;
 
@@ -315,6 +320,12 @@
     return property_get("ro.boot.vbmeta.device_state", value, "") != 0;
 }
 
+bool is_gsi() {
+    char property_value[PROPERTY_VALUE_MAX] = {};
+    EXPECT_NE(property_get("ro.product.system.name", property_value, ""), 0);
+    return "mainline"s == property_value;
+}
+
 }  // namespace
 
 bool verify_attestation_record(const string& challenge, const string& app_id,
@@ -512,9 +523,25 @@
         EXPECT_TRUE(auths.Contains(TAG_OS_VERSION, os_version()))
             << "OS version is " << os_version() << " key reported "
             << auths.GetTagValue(TAG_OS_VERSION);
-        EXPECT_TRUE(auths.Contains(TAG_OS_PATCHLEVEL, os_patch_level()))
-            << "OS patch level is " << os_patch_level() << " key reported "
-            << auths.GetTagValue(TAG_OS_PATCHLEVEL);
+
+        if (is_gsi()) {
+            // In general, TAG_OS_PATCHLEVEL should be equal to os_patch_level()
+            // reported from the system.img in use. But it is allowed to boot a
+            // GSI system.img with newer patch level, which means TAG_OS_PATCHLEVEL
+            // might be less than or equal to os_patch_level() in this case.
+            EXPECT_TRUE(auths.Contains(TAG_OS_PATCHLEVEL,  // vbmeta.img patch level
+                                       os_patch_level(),   // system.img patch level
+                                       std::less_equal<>()))
+                    << "OS patch level is " << os_patch_level()
+                    << ", which is less than key reported " << auths.GetTagValue(TAG_OS_PATCHLEVEL);
+        } else {
+            EXPECT_TRUE(auths.Contains(TAG_OS_PATCHLEVEL,  // vbmeta.img patch level
+                                       os_patch_level(),   // system.img patch level
+                                       std::equal_to<>()))
+                    << "OS patch level is " << os_patch_level()
+                    << ", which is not equal to key reported "
+                    << auths.GetTagValue(TAG_OS_PATCHLEVEL);
+        }
     }
 
     void CheckCharacteristics(const HidlBuf& key_blob,
diff --git a/keymaster/4.1/support/attestation_record.cpp b/keymaster/4.1/support/attestation_record.cpp
index 598b6b5..207a7e8 100644
--- a/keymaster/4.1/support/attestation_record.cpp
+++ b/keymaster/4.1/support/attestation_record.cpp
@@ -102,6 +102,7 @@
     ASN1_INTEGER* boot_patchlevel;
     ASN1_NULL* early_boot_only;
     ASN1_NULL* device_unique_attestation;
+    ASN1_NULL* identity_credential_key;
 } KM_AUTH_LIST;
 
 ASN1_SEQUENCE(KM_AUTH_LIST) = {
@@ -145,6 +146,8 @@
         ASN1_EXP_OPT(KM_AUTH_LIST, early_boot_only, ASN1_NULL, TAG_EARLY_BOOT_ONLY.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, device_unique_attestation, ASN1_NULL,
                      TAG_DEVICE_UNIQUE_ATTESTATION.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, identity_credential_key, ASN1_NULL,
+                     TAG_IDENTITY_CREDENTIAL_KEY.maskedTag()),
 } ASN1_SEQUENCE_END(KM_AUTH_LIST);
 IMPLEMENT_ASN1_FUNCTIONS(KM_AUTH_LIST);
 
@@ -285,6 +288,7 @@
     copyAuthTag(record->unlocked_device_required, TAG_UNLOCKED_DEVICE_REQUIRED, auth_list);
     copyAuthTag(record->early_boot_only, TAG_EARLY_BOOT_ONLY, auth_list);
     copyAuthTag(record->device_unique_attestation, TAG_DEVICE_UNIQUE_ATTESTATION, auth_list);
+    copyAuthTag(record->identity_credential_key, TAG_IDENTITY_CREDENTIAL_KEY, auth_list);
 
     return ErrorCode::OK;
 }
@@ -327,7 +331,10 @@
 
     p = attest_rec->data;
     KM_KEY_DESCRIPTION_Ptr record(d2i_KM_KEY_DESCRIPTION(nullptr, &p, attest_rec->length));
-    if (!record.get()) return {ErrorCode::UNKNOWN_ERROR, {}};
+    if (!record.get()) {
+        LOG(ERROR) << "Unable to get key description";
+        return {ErrorCode::UNKNOWN_ERROR, {}};
+    }
 
     AttestationRecord result;
 
@@ -352,10 +359,12 @@
     if (error != ErrorCode::OK) return {error, {}};
 
     KM_ROOT_OF_TRUST* root_of_trust = nullptr;
+    SecurityLevel root_of_trust_security_level = SecurityLevel::TRUSTED_ENVIRONMENT;
     if (record->tee_enforced && record->tee_enforced->root_of_trust) {
         root_of_trust = record->tee_enforced->root_of_trust;
     } else if (record->software_enforced && record->software_enforced->root_of_trust) {
         root_of_trust = record->software_enforced->root_of_trust;
+        root_of_trust_security_level = SecurityLevel::SOFTWARE;
     } else {
         LOG(ERROR) << AT << " Failed root of trust parsing";
         return {ErrorCode::INVALID_ARGUMENT, {}};
@@ -373,6 +382,7 @@
     rot.verified_boot_state = static_cast<keymaster_verified_boot_t>(
             ASN1_ENUMERATED_get(root_of_trust->verified_boot_state));
     rot.device_locked = root_of_trust->device_locked;
+    rot.security_level = root_of_trust_security_level;
 
     auto& vb_hash = root_of_trust->verified_boot_hash;
     if (!vb_hash) {
diff --git a/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp b/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
index 495de0f..728a523 100644
--- a/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
+++ b/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
@@ -212,9 +212,11 @@
     EXPECT_EQ(ErrorCode::UNIMPLEMENTED,
               convert(AttestKey(
                       AuthorizationSetBuilder()
+                              .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
                               .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
                               .Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo")),
                       &cert_chain)));
+    CheckedDeleteKey();
 }
 
 TEST_P(DeviceUniqueAttestationTest, Rsa) {
diff --git a/light/2.0/default/Android.bp b/light/2.0/default/Android.bp
index ed48825..32fcaaf 100644
--- a/light/2.0/default/Android.bp
+++ b/light/2.0/default/Android.bp
@@ -41,10 +41,18 @@
         "libbase",
         "libdl",
         "libutils",
+        "libhwbinder",
         "libhardware",
         "libhidlbase",
         "android.hardware.light@2.0",
     ],
+    arch: {
+        arm: {
+            cflags: [
+                "-DARCH_ARM_32"
+            ],
+        },
+    },
 }
 
 cc_binary {
diff --git a/light/2.0/default/service.cpp b/light/2.0/default/service.cpp
index 20f0578..b50a203 100644
--- a/light/2.0/default/service.cpp
+++ b/light/2.0/default/service.cpp
@@ -16,10 +16,14 @@
 
 #include <android/hardware/light/2.0/ILight.h>
 #include <hidl/LegacySupport.h>
+#include <hwbinder/ProcessState.h>
 
 using android::hardware::light::V2_0::ILight;
 using android::hardware::defaultPassthroughServiceImplementation;
 
 int main() {
+#ifdef ARCH_ARM_32
+    android::hardware::ProcessState::initWithMmapSize((size_t)(32768));
+#endif
     return defaultPassthroughServiceImplementation<ILight>();
 }
diff --git a/media/omx/1.0/vts/functional/common/Android.bp b/media/omx/1.0/vts/functional/common/Android.bp
index 720ea9f..064aaa5 100644
--- a/media/omx/1.0/vts/functional/common/Android.bp
+++ b/media/omx/1.0/vts/functional/common/Android.bp
@@ -22,28 +22,24 @@
     export_header_lib_headers: ["media_plugin_headers"],
     export_include_dirs: ["."],
 
+    shared_libs: [
+        "libui",
+    ],
+
     static_libs: [
         "libgtest",
         "libhidlmemory",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
         "android.hardware.media.omx@1.0",
-        "android.hardware.graphics.allocator@2.0",
-        "android.hardware.graphics.allocator@3.0",
         "android.hardware.graphics.common@1.0",
         "android.hardware.graphics.common@1.1",
         "android.hardware.graphics.common@1.2",
-        "android.hardware.graphics.mapper@2.0",
-        "android.hardware.graphics.mapper@3.0",
     ],
     export_static_lib_headers: [
-        "android.hardware.graphics.allocator@2.0",
-        "android.hardware.graphics.allocator@3.0",
         "android.hardware.graphics.common@1.0",
         "android.hardware.graphics.common@1.1",
         "android.hardware.graphics.common@1.2",
-        "android.hardware.graphics.mapper@2.0",
-        "android.hardware.graphics.mapper@3.0",
     ],
 }
 
@@ -54,15 +50,10 @@
     // Link to these statically as they are not guaranteed to be on the device.
     static_libs: [
         "VtsHalMediaOmxV1_0CommonUtil",
-        "android.hardware.graphics.allocator@2.0",
-        "android.hardware.graphics.allocator@3.0",
         "android.hardware.graphics.common@1.0",
         "android.hardware.graphics.common@1.1",
         "android.hardware.graphics.common@1.2",
-        "android.hardware.graphics.mapper@2.0",
-        "android.hardware.graphics.mapper@3.0",
         "android.hardware.graphics.bufferqueue@1.0",
-        "android.hardware.graphics.common@1.0",
         "android.hardware.media.omx@1.0",
         "android.hardware.media@1.0",
         "android.hidl.allocator@1.0",
@@ -73,6 +64,7 @@
 
     // TODO(b/64437680): Assume these libs are always available on the device.
     shared_libs: [
+        "libui",
         "libstagefright_foundation",
         "libstagefright_omx_utils",
     ],
diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
index d9d1157..64f27e8 100644
--- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
+++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
@@ -21,12 +21,6 @@
 
 #include <android-base/logging.h>
 
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <android/hardware/graphics/mapper/2.0/types.h>
-#include <android/hardware/graphics/mapper/3.0/IMapper.h>
-#include <android/hardware/graphics/mapper/3.0/types.h>
 #include <android/hardware/media/omx/1.0/IOmx.h>
 #include <android/hardware/media/omx/1.0/IOmxNode.h>
 #include <android/hardware/media/omx/1.0/IOmxObserver.h>
@@ -199,42 +193,6 @@
                             BufferInfo* buffer, uint32_t nFrameWidth,
                             uint32_t nFrameHeight, int32_t* nStride,
                             int format) {
-    struct AllocatorV2 : public GrallocV2 {
-        sp<IAllocator> mAllocator;
-        sp<IMapper> mMapper;
-        AllocatorV2(sp<IAllocator>&& allocator, sp<IMapper>&& mapper)
-              : mAllocator{std::move(allocator)}, mMapper{std::move(mapper)} {}
-        AllocatorV2() = default;
-    };
-    struct AllocatorV3 : public GrallocV3 {
-        sp<IAllocator> mAllocator;
-        sp<IMapper> mMapper;
-        AllocatorV3(sp<IAllocator>&& allocator, sp<IMapper>&& mapper)
-              : mAllocator{std::move(allocator)}, mMapper{std::move(mapper)} {}
-        AllocatorV3() = default;
-    };
-    std::variant<AllocatorV2, AllocatorV3> grallocVar;
-
-    sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper2{};
-    sp<android::hardware::graphics::mapper::V3_0::IMapper> mapper3{};
-    sp<android::hardware::graphics::allocator::V2_0::IAllocator> allocator2{};
-    sp<android::hardware::graphics::allocator::V3_0::IAllocator> allocator3 =
-        android::hardware::graphics::allocator::V3_0::IAllocator::getService();
-    if (allocator3) {
-        mapper3 =
-            android::hardware::graphics::mapper::V3_0::IMapper::getService();
-        ASSERT_NE(nullptr, mapper3.get());
-        grallocVar.emplace<AllocatorV3>(std::move(allocator3), std::move(mapper3));
-    } else {
-        allocator2 =
-            android::hardware::graphics::allocator::V2_0::IAllocator::getService();
-        ASSERT_NE(nullptr, allocator2.get());
-        mapper2 =
-            android::hardware::graphics::mapper::V2_0::IMapper::getService();
-        ASSERT_NE(nullptr, allocator2.get());
-        grallocVar.emplace<AllocatorV2>(std::move(allocator2), std::move(mapper2));
-    }
-
     android::hardware::media::omx::V1_0::Status status{};
     uint64_t usage{};
     ASSERT_TRUE(omxNode->getGraphicBufferUsage(
@@ -246,57 +204,27 @@
         }).isOk());
     ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
 
+    uint32_t stride;
+    buffer_handle_t handle = nullptr;
+    android::GraphicBufferAllocator& allocator = android::GraphicBufferAllocator::get();
+    android::status_t error = allocator.allocate(
+            nFrameWidth, nFrameHeight, static_cast<android::PixelFormat>(format), 1,
+            usage | BufferUsage::CPU_READ_OFTEN, &handle, &stride, "omx_vts_common");
+
+    ASSERT_EQ(error, android::NO_ERROR);
+    ASSERT_NE(handle, nullptr);
+
+    *nStride = static_cast<int32_t>(stride);
+    buffer->omxBuffer.nativeHandle = handle;
+    buffer->omxBuffer.attr.anwBuffer.width = nFrameWidth;
+    buffer->omxBuffer.attr.anwBuffer.height = nFrameHeight;
+    buffer->omxBuffer.attr.anwBuffer.stride = stride;
+    buffer->omxBuffer.attr.anwBuffer.format = static_cast<PixelFormat>(format);
+    buffer->omxBuffer.attr.anwBuffer.usage = usage | BufferUsage::CPU_READ_OFTEN;
+    buffer->omxBuffer.attr.anwBuffer.layerCount = 1;
     static std::atomic_int32_t bufferIdCounter{0};
-
-    std::visit([buffer, nFrameWidth, nFrameHeight, format, usage, nStride](auto&& gralloc) {
-            using Gralloc = std::remove_reference_t<decltype(gralloc)>;
-            using Descriptor = typename Gralloc::Descriptor;
-            using DescriptorInfo = typename Gralloc::DescriptorInfo;
-            using Error = typename Gralloc::Error;
-            using Format = typename Gralloc::Format;
-            using Usage = typename Gralloc::Usage;
-
-            Error error{};
-            Descriptor descriptor{};
-
-            DescriptorInfo descriptorInfo{};
-            descriptorInfo.width = nFrameWidth;
-            descriptorInfo.height = nFrameHeight;
-            descriptorInfo.layerCount = 1;
-            descriptorInfo.format = static_cast<Format>(format);
-            descriptorInfo.usage = usage | Usage(BufferUsage::CPU_READ_OFTEN);
-
-            gralloc.mMapper->createDescriptor(descriptorInfo,
-                    [&error, &descriptor](
-                        Error _s,
-                        const Descriptor& _n1) {
-                    error = _s;
-                    descriptor = _n1;
-                });
-            ASSERT_EQ(error, Error::NONE);
-
-            gralloc.mAllocator->allocate(
-                descriptor, 1,
-                [&](Error _s, uint32_t _n1,
-                    const ::android::hardware::hidl_vec<
-                        ::android::hardware::hidl_handle>& _n2) {
-                    ASSERT_EQ(Error::NONE, _s);
-                    *nStride = _n1;
-                    buffer->omxBuffer.nativeHandle = _n2[0];
-                    buffer->omxBuffer.attr.anwBuffer.width = nFrameWidth;
-                    buffer->omxBuffer.attr.anwBuffer.height = nFrameHeight;
-                    buffer->omxBuffer.attr.anwBuffer.stride = _n1;
-                    buffer->omxBuffer.attr.anwBuffer.format =
-                        static_cast<PixelFormat>(descriptorInfo.format);
-                    buffer->omxBuffer.attr.anwBuffer.usage =
-                        static_cast<uint32_t>(descriptorInfo.usage);
-                    buffer->omxBuffer.attr.anwBuffer.layerCount =
-                        descriptorInfo.layerCount;
-                    buffer->omxBuffer.attr.anwBuffer.id =
-                        (static_cast<uint64_t>(getpid()) << 32) |
-                        bufferIdCounter.fetch_add(1, std::memory_order_relaxed);
-                });
-        }, grallocVar);
+    buffer->omxBuffer.attr.anwBuffer.id = (static_cast<uint64_t>(getpid()) << 32) |
+                                          bufferIdCounter.fetch_add(1, std::memory_order_relaxed);
 }
 
 // allocate buffers needed on a component port
diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.h b/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
index bb03dd0..044408d 100644
--- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
+++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
@@ -22,16 +22,6 @@
 #endif
 
 #include <getopt.h>
-
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
-#include <android/hardware/graphics/common/1.0/types.h>
-#include <android/hardware/graphics/common/1.1/types.h>
-#include <android/hardware/graphics/common/1.2/types.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <android/hardware/graphics/mapper/2.0/types.h>
-#include <android/hardware/graphics/mapper/3.0/IMapper.h>
-#include <android/hardware/graphics/mapper/3.0/types.h>
 #include <gtest/gtest.h>
 #include <hidl/ServiceManagement.h>
 #include <media/stagefright/foundation/ALooper.h>
@@ -46,6 +36,9 @@
 #include <media/openmax/OMX_AudioExt.h>
 #include <media/openmax/OMX_VideoExt.h>
 
+#include <ui/GraphicBufferAllocator.h>
+#include <ui/GraphicBufferMapper.h>
+
 /* TIME OUTS (Wait time in dequeueMessage()) */
 
 /* As component is switching states (loaded<->idle<->execute), dequeueMessage()
@@ -312,35 +305,6 @@
 /*
  * common functions declarations
  */
-struct GrallocV2 {
-    using Format = android::hardware::graphics::common::V1_0::PixelFormat;
-    using Usage = android::hardware::hidl_bitfield<
-            android::hardware::graphics::common::V1_0::BufferUsage>;
-
-    using IAllocator = android::hardware::graphics::allocator::V2_0::IAllocator;
-
-    using IMapper = android::hardware::graphics::mapper::V2_0::IMapper;
-    using Error = android::hardware::graphics::mapper::V2_0::Error;
-    using Descriptor = android::hardware::graphics::mapper::V2_0::BufferDescriptor;
-    using YCbCrLayout = android::hardware::graphics::mapper::V2_0::YCbCrLayout;
-    using DescriptorInfo = IMapper::BufferDescriptorInfo;
-    using Rect = IMapper::Rect;
-};
-
-struct GrallocV3 {
-    using Format = android::hardware::graphics::common::V1_2::PixelFormat;
-    using Usage = android::hardware::hidl_bitfield<
-            android::hardware::graphics::common::V1_2::BufferUsage>;
-
-    using IAllocator = android::hardware::graphics::allocator::V3_0::IAllocator;
-
-    using IMapper = android::hardware::graphics::mapper::V3_0::IMapper;
-    using Error = android::hardware::graphics::mapper::V3_0::Error;
-    using Descriptor = android::hardware::graphics::mapper::V3_0::BufferDescriptor;
-    using YCbCrLayout = android::hardware::graphics::mapper::V3_0::YCbCrLayout;
-    using DescriptorInfo = IMapper::BufferDescriptorInfo;
-    using Rect = IMapper::Rect;
-};
 
 Return<android::hardware::media::omx::V1_0::Status> setRole(sp<IOmxNode> omxNode,
                                                             const std::string& role);
diff --git a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
index 4b469e6..7519f2f 100644
--- a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
+++ b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
@@ -23,8 +23,6 @@
 
 #include <android/hardware/graphics/bufferqueue/1.0/IGraphicBufferProducer.h>
 #include <android/hardware/graphics/bufferqueue/1.0/IProducerListener.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <android/hardware/graphics/mapper/2.0/types.h>
 #include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
 #include <android/hardware/media/omx/1.0/IOmx.h>
 #include <android/hardware/media/omx/1.0/IOmxBufferSource.h>
@@ -364,61 +362,6 @@
     return Void();
 };
 
-// Variant of mappers
-struct MapperV2 : public GrallocV2 {
-    sp<IMapper> mMapper;
-    MapperV2(sp<IMapper>&& mapper): mMapper{std::move(mapper)} {}
-    MapperV2() = default;
-    android::hardware::Return<void> lock(
-            void* buffer,
-            Usage usage,
-            const Rect& rect,
-            const android::hardware::hidl_handle& handle,
-            Error* error,
-            void** data) {
-        return mMapper->lock(buffer, usage, rect, handle,
-                             [error, data](Error e, void* d) {
-                                *error = e;
-                                *data = d;
-                             });
-    }
-};
-struct MapperV3 : public GrallocV3 {
-    sp<IMapper> mMapper;
-    MapperV3(sp<IMapper>&& mapper): mMapper{std::move(mapper)} {}
-    MapperV3() = default;
-    android::hardware::Return<void> lock(
-            void* buffer,
-            Usage usage,
-            const Rect& rect,
-            const android::hardware::hidl_handle& handle,
-            Error* error,
-            void** data) {
-        return mMapper->lock(buffer, usage, rect, handle,
-                             [error, data](Error e, void* d, int32_t, int32_t) {
-                                *error = e;
-                                *data = d;
-                             });
-    }
-};
-using MapperVar = std::variant<MapperV2, MapperV3>;
-// Initializes the MapperVar by trying services of different versions.
-bool initialize(MapperVar& mapperVar) {
-    sp<android::hardware::graphics::mapper::V3_0::IMapper> mapper3 =
-        android::hardware::graphics::mapper::V3_0::IMapper::getService();
-    if (mapper3) {
-        mapperVar.emplace<MapperV3>(std::move(mapper3));
-        return true;
-    }
-    sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper2 =
-        android::hardware::graphics::mapper::V2_0::IMapper::getService();
-    if (mapper2) {
-        mapperVar.emplace<MapperV2>(std::move(mapper2));
-        return true;
-    }
-    return false;
-}
-
 // request VOP refresh
 void requestIDR(sp<IOmxNode> omxNode, OMX_U32 portIndex) {
     android::hardware::media::omx::V1_0::Status status;
@@ -627,168 +570,113 @@
     }
 }
 
-int colorFormatConversion(BufferInfo* buffer, void* buff, PixelFormat format,
+int colorFormatConversion(BufferInfo* buffer, buffer_handle_t buff, PixelFormat format,
                           std::ifstream& eleStream) {
-    MapperVar mapperVar;
-    if (!initialize(mapperVar)) {
-        EXPECT_TRUE(false) << "failed to obtain mapper service";
-        return 1;
+    android::GraphicBufferMapper& gbmapper = android::GraphicBufferMapper::get();
+
+    android::Rect rect(0, 0, buffer->omxBuffer.attr.anwBuffer.width,
+                       buffer->omxBuffer.attr.anwBuffer.height);
+    android_ycbcr ycbcrLayout;
+    android::status_t error = android::NO_ERROR;
+
+    if (format == PixelFormat::YV12 || format == PixelFormat::YCRCB_420_SP ||
+        format == PixelFormat::YCBCR_420_888) {
+        error = gbmapper.lockYCbCr(buff, buffer->omxBuffer.attr.anwBuffer.usage, rect,
+                                   &ycbcrLayout);
+        EXPECT_EQ(error, android::NO_ERROR);
+        if (error != android::NO_ERROR) return 1;
+
+        int size = ((rect.getWidth() * rect.getHeight() * 3) >> 1);
+        char* img = new char[size];
+        if (img == nullptr) return 1;
+        eleStream.read(img, size);
+        if (eleStream.gcount() != size) {
+            delete[] img;
+            return 1;
+        }
+
+        char* imgTmp = img;
+        char* ipBuffer = static_cast<char*>(ycbcrLayout.y);
+        for (size_t y = rect.getHeight(); y > 0; --y) {
+            memcpy(ipBuffer, imgTmp, rect.getWidth());
+            ipBuffer += ycbcrLayout.ystride;
+            imgTmp += rect.getWidth();
+        }
+
+        if (format == PixelFormat::YV12)
+            EXPECT_EQ(ycbcrLayout.chroma_step, 1U);
+        else if (format == PixelFormat::YCRCB_420_SP)
+            EXPECT_EQ(ycbcrLayout.chroma_step, 2U);
+
+        ipBuffer = static_cast<char*>(ycbcrLayout.cb);
+        for (size_t y = rect.getHeight() >> 1; y > 0; --y) {
+            for (int32_t x = 0; x < (rect.getWidth() >> 1); ++x) {
+                ipBuffer[ycbcrLayout.chroma_step * x] = *imgTmp++;
+            }
+            ipBuffer += ycbcrLayout.cstride;
+        }
+        ipBuffer = static_cast<char*>(ycbcrLayout.cr);
+        for (size_t y = rect.getHeight() >> 1; y > 0; --y) {
+            for (int32_t x = 0; x < (rect.getWidth() >> 1); ++x) {
+                ipBuffer[ycbcrLayout.chroma_step * x] = *imgTmp++;
+            }
+            ipBuffer += ycbcrLayout.cstride;
+        }
+
+        delete[] img;
+
+        error = gbmapper.unlock(buff);
+        EXPECT_EQ(error, android::NO_ERROR);
+        if (error != android::NO_ERROR) return 1;
+    } else {
+        void* data;
+        int32_t outBytesPerPixel;
+        int32_t outBytesPerStride;
+        error = gbmapper.lock(buff, buffer->omxBuffer.attr.anwBuffer.usage, rect, &data,
+                              &outBytesPerPixel, &outBytesPerStride);
+        EXPECT_EQ(error, android::NO_ERROR);
+        if (error != android::NO_ERROR) return 1;
+
+        if (format == PixelFormat::BGRA_8888) {
+            char* ipBuffer = static_cast<char*>(data);
+            for (size_t y = rect.getHeight(); y > 0; --y) {
+                eleStream.read(ipBuffer, rect.getWidth() * 4);
+                if (eleStream.gcount() != rect.getWidth() * 4) return 1;
+                ipBuffer += buffer->omxBuffer.attr.anwBuffer.stride * 4;
+            }
+        } else {
+            EXPECT_TRUE(false) << "un expected pixel format";
+            return 1;
+        }
+
+        error = gbmapper.unlock(buff);
+        EXPECT_EQ(error, android::NO_ERROR);
+        if (error != android::NO_ERROR) return 1;
     }
 
-    return std::visit([buffer, buff, format, &eleStream](auto&& mapper) -> int {
-            using Gralloc = std::remove_reference_t<decltype(mapper)>;
-            using Error = typename Gralloc::Error;
-            using Rect = typename Gralloc::Rect;
-            using Usage = typename Gralloc::Usage;
-            using YCbCrLayout = typename Gralloc::YCbCrLayout;
-
-            android::hardware::hidl_handle fence;
-            Rect rect;
-            YCbCrLayout ycbcrLayout;
-            Error error;
-            rect.left = 0;
-            rect.top = 0;
-            rect.width = buffer->omxBuffer.attr.anwBuffer.width;
-            rect.height = buffer->omxBuffer.attr.anwBuffer.height;
-
-            if (format == PixelFormat::YV12 || format == PixelFormat::YCRCB_420_SP ||
-                format == PixelFormat::YCBCR_420_888) {
-                mapper.mMapper->lockYCbCr(
-                        buff,
-                        static_cast<Usage>(
-                            buffer->omxBuffer.attr.anwBuffer.usage),
-                        rect,
-                        fence,
-                        [&](Error _e,
-                            const YCbCrLayout& _n1) {
-                            error = _e;
-                            ycbcrLayout = _n1;
-                        });
-                EXPECT_EQ(error, Error::NONE);
-                if (error != Error::NONE)
-                    return 1;
-
-                int size = ((rect.width * rect.height * 3) >> 1);
-                char* img = new char[size];
-                if (img == nullptr) return 1;
-                eleStream.read(img, size);
-                if (eleStream.gcount() != size) {
-                    delete[] img;
-                    return 1;
-                }
-
-                char* imgTmp = img;
-                char* ipBuffer = static_cast<char*>(ycbcrLayout.y);
-                for (size_t y = rect.height; y > 0; --y) {
-                    memcpy(ipBuffer, imgTmp, rect.width);
-                    ipBuffer += ycbcrLayout.yStride;
-                    imgTmp += rect.width;
-                }
-
-                if (format == PixelFormat::YV12)
-                    EXPECT_EQ(ycbcrLayout.chromaStep, 1U);
-                else if (format == PixelFormat::YCRCB_420_SP)
-                    EXPECT_EQ(ycbcrLayout.chromaStep, 2U);
-
-                ipBuffer = static_cast<char*>(ycbcrLayout.cb);
-                for (size_t y = rect.height >> 1; y > 0; --y) {
-                    for (int32_t x = 0; x < (rect.width >> 1); ++x) {
-                        ipBuffer[ycbcrLayout.chromaStep * x] = *imgTmp++;
-                    }
-                    ipBuffer += ycbcrLayout.cStride;
-                }
-                ipBuffer = static_cast<char*>(ycbcrLayout.cr);
-                for (size_t y = rect.height >> 1; y > 0; --y) {
-                    for (int32_t x = 0; x < (rect.width >> 1); ++x) {
-                        ipBuffer[ycbcrLayout.chromaStep * x] = *imgTmp++;
-                    }
-                    ipBuffer += ycbcrLayout.cStride;
-                }
-
-                delete[] img;
-
-                mapper.mMapper->unlock(buff,
-                               [&](Error _e,
-                                   const android::hardware::hidl_handle& _n1) {
-                                   error = _e;
-                                   fence = _n1;
-                               });
-                EXPECT_EQ(error, Error::NONE);
-                if (error != Error::NONE)
-                    return 1;
-            } else {
-                void* data;
-                mapper.lock(
-                        buff,
-                        buffer->omxBuffer.attr.anwBuffer.usage,
-                        rect,
-                        fence,
-                        &error,
-                        &data);
-                EXPECT_EQ(error, Error::NONE);
-                if (error != Error::NONE)
-                    return 1;
-
-                if (format == PixelFormat::BGRA_8888) {
-                    char* ipBuffer = static_cast<char*>(data);
-                    for (size_t y = rect.height; y > 0; --y) {
-                        eleStream.read(ipBuffer, rect.width * 4);
-                        if (eleStream.gcount() != rect.width * 4) return 1;
-                        ipBuffer += buffer->omxBuffer.attr.anwBuffer.stride * 4;
-                    }
-                } else {
-                    EXPECT_TRUE(false) << "un expected pixel format";
-                    return 1;
-                }
-
-                mapper.mMapper->unlock(
-                        buff,
-                        [&](Error _e, const android::hardware::hidl_handle& _n1) {
-                            error = _e;
-                            fence = _n1;
-                        });
-                EXPECT_EQ(error, Error::NONE);
-                if (error != Error::NONE)
-                    return 1;
-            }
-
-            return 0;
-        }, mapperVar);
+    return 0;
 }
 
 int fillGraphicBuffer(BufferInfo* buffer, PixelFormat format,
                       std::ifstream& eleStream) {
-    MapperVar mapperVar;
-    if (!initialize(mapperVar)) {
-        EXPECT_TRUE(false) << "failed to obtain mapper service";
-        return 1;
-    }
+    android::GraphicBufferMapper& gbmapper = android::GraphicBufferMapper::get();
+    buffer_handle_t buff;
+    android::status_t error = android::NO_ERROR;
+    gbmapper.importBuffer(
+            buffer->omxBuffer.nativeHandle, buffer->omxBuffer.attr.anwBuffer.width,
+            buffer->omxBuffer.attr.anwBuffer.height, buffer->omxBuffer.attr.anwBuffer.layerCount,
+            static_cast<android::PixelFormat>(format), buffer->omxBuffer.attr.anwBuffer.usage,
+            buffer->omxBuffer.attr.anwBuffer.stride, &buff);
+    EXPECT_EQ(error, android::NO_ERROR);
+    if (error != android::NO_ERROR) return 1;
 
-    return std::visit([buffer, format, &eleStream](auto&& mapper) -> int {
-            using Gralloc = std::remove_reference_t<decltype(mapper)>;
-            using Error = typename Gralloc::Error;
+    if (colorFormatConversion(buffer, buff, format, eleStream)) return 1;
 
-            void* buff = nullptr;
-            Error error;
-            mapper.mMapper->importBuffer(
-                buffer->omxBuffer.nativeHandle,
-                [&](Error _e, void* _n1) {
-                    error = _e;
-                    buff = _n1;
-                });
-            EXPECT_EQ(error, Error::NONE);
-            if (error != Error::NONE)
-                return 1;
+    error = gbmapper.freeBuffer(buff);
+    EXPECT_EQ(error, android::NO_ERROR);
+    if (error != android::NO_ERROR) return 1;
 
-            if (colorFormatConversion(buffer, buff, format, eleStream)) return 1;
-
-            error = mapper.mMapper->freeBuffer(buff);
-            EXPECT_EQ(error, Error::NONE);
-            if (error != Error::NONE)
-                return 1;
-
-            return 0;
-        }, mapperVar);
+    return 0;
 }
 
 int dispatchGraphicBuffer(sp<IOmxNode> omxNode,
diff --git a/power/1.0/default/Android.bp b/power/1.0/default/Android.bp
index 1d152ee..74fb13f 100644
--- a/power/1.0/default/Android.bp
+++ b/power/1.0/default/Android.bp
@@ -54,6 +54,12 @@
         "libhardware",
         "libhidlbase",
         "android.hardware.power@1.0",
+        "libhwbinder"
     ],
 
+    arch: {
+        arm: {
+            cflags: ["-DARCH_ARM_32"],
+        },
+    },
 }
diff --git a/power/1.0/default/service.cpp b/power/1.0/default/service.cpp
index e8618b8..d561919 100644
--- a/power/1.0/default/service.cpp
+++ b/power/1.0/default/service.cpp
@@ -18,10 +18,16 @@
 
 #include <android/hardware/power/1.0/IPower.h>
 #include <hidl/LegacySupport.h>
+#ifdef ARCH_ARM_32
+#include <hwbinder/ProcessState.h>
+#endif
 
 using android::hardware::power::V1_0::IPower;
 using android::hardware::defaultPassthroughServiceImplementation;
 
 int main() {
+    #ifdef ARCH_ARM_32
+        android::hardware::ProcessState::initWithMmapSize((size_t)16384);
+    #endif
     return defaultPassthroughServiceImplementation<IPower>();
 }
diff --git a/radio/1.0/vts/functional/vts_test_util.cpp b/radio/1.0/vts/functional/vts_test_util.cpp
index 7a21a40..9a2d089 100644
--- a/radio/1.0/vts/functional/vts_test_util.cpp
+++ b/radio/1.0/vts/functional/vts_test_util.cpp
@@ -17,6 +17,7 @@
 
 #include <vts_test_util.h>
 #include <iostream>
+#include "VtsCoreUtil.h"
 
 int GetRandomSerialNumber() {
     return rand();
@@ -78,4 +79,24 @@
     __android_log_print(ANDROID_LOG_INFO, LOG_TAG, "Feature %s: %ssupported", feature,
                         hasFeature ? "" : "not ");
     return hasFeature;
+}
+
+bool isDsDsEnabled() {
+    return testing::checkSubstringInCommandOutput("getprop persist.radio.multisim.config", "dsds");
+}
+
+bool isTsTsEnabled() {
+    return testing::checkSubstringInCommandOutput("getprop persist.radio.multisim.config", "tsts");
+}
+
+bool isVoiceInService(RegState state) {
+    return ::android::hardware::radio::V1_0::RegState::REG_HOME == state ||
+           ::android::hardware::radio::V1_0::RegState::REG_ROAMING == state;
+}
+
+bool isVoiceEmergencyOnly(RegState state) {
+    return ::android::hardware::radio::V1_0::RegState::NOT_REG_MT_NOT_SEARCHING_OP_EM == state ||
+           ::android::hardware::radio::V1_0::RegState::NOT_REG_MT_SEARCHING_OP_EM == state ||
+           ::android::hardware::radio::V1_0::RegState::REG_DENIED_EM == state ||
+           ::android::hardware::radio::V1_0::RegState::UNKNOWN_EM == state;
 }
\ No newline at end of file
diff --git a/radio/1.0/vts/functional/vts_test_util.h b/radio/1.0/vts/functional/vts_test_util.h
index df8dd77..1625f11 100644
--- a/radio/1.0/vts/functional/vts_test_util.h
+++ b/radio/1.0/vts/functional/vts_test_util.h
@@ -21,6 +21,7 @@
 #include <gtest/gtest.h>
 
 using ::android::hardware::radio::V1_0::RadioError;
+using ::android::hardware::radio::V1_0::RegState;
 using ::android::hardware::radio::V1_0::SapResultCode;
 using namespace std;
 
@@ -55,3 +56,23 @@
  * Check if device supports feature.
  */
 bool deviceSupportsFeature(const char* feature);
+
+/*
+ * Check if device is in DSDS.
+ */
+bool isDsDsEnabled();
+
+/*
+ * Check if device is in TSTS.
+ */
+bool isTsTsEnabled();
+
+/*
+ * Check if voice status is in emergency only.
+ */
+bool isVoiceEmergencyOnly(RegState state);
+
+/*
+ * Check if voice status is in service.
+ */
+bool isVoiceInService(RegState state);
\ No newline at end of file
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
index 3ba9b9d..1b254a1 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
@@ -56,7 +56,21 @@
     EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial);
 
     ALOGI("emergencyDial, rspInfo.error = %s\n", toString(radioRsp_v1_4->rspInfo.error).c_str());
-    EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error);
+
+    ::android::hardware::radio::V1_0::RadioError rspEmergencyDial = radioRsp_v1_4->rspInfo.error;
+    // In DSDS or TSTS, we only check the result if the current slot is IN_SERVICE
+    // or Emergency_Only.
+    if (isDsDsEnabled() || isTsTsEnabled()) {
+        serial = GetRandomSerialNumber();
+        radio_v1_4->getVoiceRegistrationState(serial);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        if (isVoiceEmergencyOnly(radioRsp_v1_4->voiceRegResp.regState) ||
+            isVoiceInService(radioRsp_v1_4->voiceRegResp.regState)) {
+            EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
+        }
+    } else {
+        EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
+    }
 
     // Give some time for modem to establish the emergency call channel.
     sleep(MODEM_EMERGENCY_CALL_ESTABLISH_TIME);
@@ -95,8 +109,21 @@
 
     ALOGI("emergencyDial_withServices, rspInfo.error = %s\n",
           toString(radioRsp_v1_4->rspInfo.error).c_str());
-    EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error);
+    ::android::hardware::radio::V1_0::RadioError rspEmergencyDial = radioRsp_v1_4->rspInfo.error;
 
+    // In DSDS or TSTS, we only check the result if the current slot is IN_SERVICE
+    // or Emergency_Only.
+    if (isDsDsEnabled() || isTsTsEnabled()) {
+        serial = GetRandomSerialNumber();
+        radio_v1_4->getVoiceRegistrationState(serial);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        if (isVoiceEmergencyOnly(radioRsp_v1_4->voiceRegResp.regState) ||
+            isVoiceInService(radioRsp_v1_4->voiceRegResp.regState)) {
+            EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
+        }
+    } else {
+        EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
+    }
     // Give some time for modem to establish the emergency call channel.
     sleep(MODEM_EMERGENCY_CALL_ESTABLISH_TIME);
 
@@ -134,7 +161,21 @@
 
     ALOGI("emergencyDial_withEmergencyRouting, rspInfo.error = %s\n",
           toString(radioRsp_v1_4->rspInfo.error).c_str());
-    EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error);
+    ::android::hardware::radio::V1_0::RadioError rspEmergencyDial = radioRsp_v1_4->rspInfo.error;
+
+    // In DSDS or TSTS, we only check the result if the current slot is IN_SERVICE
+    // or Emergency_Only.
+    if (isDsDsEnabled() || isTsTsEnabled()) {
+        serial = GetRandomSerialNumber();
+        radio_v1_4->getVoiceRegistrationState(serial);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        if (isVoiceEmergencyOnly(radioRsp_v1_4->voiceRegResp.regState) ||
+            isVoiceInService(radioRsp_v1_4->voiceRegResp.regState)) {
+            EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
+        }
+    } else {
+        EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
+    }
 
     // Give some time for modem to establish the emergency call channel.
     sleep(MODEM_EMERGENCY_CALL_ESTABLISH_TIME);
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h b/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
index 53a5845..8eee811 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
+++ b/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
@@ -64,6 +64,7 @@
 
     // Call
     hidl_vec<::android::hardware::radio::V1_2::Call> currentCalls;
+    ::android::hardware::radio::V1_2::VoiceRegStateResult voiceRegResp;
 
     // Modem
     bool isModemEnabled;
diff --git a/radio/1.4/vts/functional/radio_response.cpp b/radio/1.4/vts/functional/radio_response.cpp
index d0aae47..3e93bf4 100644
--- a/radio/1.4/vts/functional/radio_response.cpp
+++ b/radio/1.4/vts/functional/radio_response.cpp
@@ -762,8 +762,9 @@
 
 Return<void> RadioResponse_v1_4::getVoiceRegistrationStateResponse_1_2(
         const RadioResponseInfo& info,
-        const ::android::hardware::radio::V1_2::VoiceRegStateResult& /*voiceRegResponse*/) {
+        const ::android::hardware::radio::V1_2::VoiceRegStateResult& voiceRegResponse) {
     rspInfo = info;
+    voiceRegResp = voiceRegResponse;
     parent_v1_4.notify(info.serial);
     return Void();
 }
diff --git a/sensors/1.0/default/Android.bp b/sensors/1.0/default/Android.bp
index d5c1b23..98f46ae 100644
--- a/sensors/1.0/default/Android.bp
+++ b/sensors/1.0/default/Android.bp
@@ -46,6 +46,7 @@
     relative_install_path: "hw",
     vendor: true,
     init_rc: ["android.hardware.sensors@1.0-service.rc"],
+    defaults: ["hidl_defaults"],
     srcs: ["service.cpp"],
 
     shared_libs: [
@@ -56,5 +57,11 @@
         "libutils",
         "libhidlbase",
         "android.hardware.sensors@1.0",
+        "libhwbinder",
     ],
+    arch: {
+        arm: {
+            cflags: ["-DARCH_ARM_32"],
+        },
+    },
 }
diff --git a/sensors/1.0/default/android.hardware.sensors@1.0-service.rc b/sensors/1.0/default/android.hardware.sensors@1.0-service.rc
index 1af6d0b..e029bb8 100644
--- a/sensors/1.0/default/android.hardware.sensors@1.0-service.rc
+++ b/sensors/1.0/default/android.hardware.sensors@1.0-service.rc
@@ -2,6 +2,6 @@
     interface android.hardware.sensors@1.0::ISensors default
     class hal
     user system
-    group system wakelock uhid context_hub
+    group system wakelock uhid input context_hub
     capabilities BLOCK_SUSPEND
     rlimit rtprio 10 10
diff --git a/sensors/1.0/default/service.cpp b/sensors/1.0/default/service.cpp
index 65f6d81..c413d1a 100644
--- a/sensors/1.0/default/service.cpp
+++ b/sensors/1.0/default/service.cpp
@@ -19,10 +19,30 @@
 #include <android/hardware/sensors/1.0/ISensors.h>
 #include <hidl/LegacySupport.h>
 
+#ifdef ARCH_ARM_32
+#include <hwbinder/ProcessState.h>
+#include <cutils/properties.h>
+#endif
+
 using android::hardware::sensors::V1_0::ISensors;
 using android::hardware::defaultPassthroughServiceImplementation;
 
+#ifdef ARCH_ARM_32
+//default h/w binder memsize for sensors is 8 KB
+#define DEFAULT_SENSORS_HW_BINDER_MEM_SIZE_KB 8
+size_t getHWBinderMmapSize() {
+    int32_t value = DEFAULT_SENSORS_HW_BINDER_MEM_SIZE_KB;
+
+    value = property_get_int32("persist.vendor.sensor.hw.binder.size", value);
+    ALOGD("Init hw binder with mem size = %d", value);
+    return 1024 * value;
+}
+#endif
+
 int main() {
+#ifdef ARCH_ARM_32
+    android::hardware::ProcessState::initWithMmapSize((size_t)getHWBinderMmapSize());
+#endif
     /* Sensors framework service needs at least two threads.
      * One thread blocks on a "poll"
      * The second thread is needed for all other HAL methods.
diff --git a/sensors/common/default/2.X/multihal/HalProxy.cpp b/sensors/common/default/2.X/multihal/HalProxy.cpp
index 75ffc17..fe3fc84 100644
--- a/sensors/common/default/2.X/multihal/HalProxy.cpp
+++ b/sensors/common/default/2.X/multihal/HalProxy.cpp
@@ -693,6 +693,10 @@
                                                         int64_t timeoutStart /* = -1 */) {
     if (!mThreadsRun.load()) return;
     std::lock_guard<std::recursive_mutex> lockGuard(mWakelockMutex);
+    if (delta > mWakelockRefCount) {
+        ALOGE("Decrementing wakelock ref count by %zu when count is %zu",
+              delta, mWakelockRefCount);
+    }
     if (timeoutStart == -1) timeoutStart = mWakelockTimeoutResetTime;
     if (mWakelockRefCount == 0 || timeoutStart < mWakelockTimeoutResetTime) return;
     mWakelockRefCount -= std::min(mWakelockRefCount, delta);
diff --git a/sensors/common/default/2.X/multihal/ScopedWakelock.cpp b/sensors/common/default/2.X/multihal/ScopedWakelock.cpp
index bf2ad35..2a2baa2 100644
--- a/sensors/common/default/2.X/multihal/ScopedWakelock.cpp
+++ b/sensors/common/default/2.X/multihal/ScopedWakelock.cpp
@@ -28,6 +28,21 @@
             .count();
 }
 
+ScopedWakelock::ScopedWakelock(ScopedWakelock&& other) {
+    *this = std::move(other);
+}
+
+ScopedWakelock& ScopedWakelock::operator=(ScopedWakelock&& other) {
+    mRefCounter = other.mRefCounter;
+    mCreatedAtTimeNs = other.mCreatedAtTimeNs;
+    mLocked = other.mLocked;
+
+    other.mRefCounter = nullptr;
+    other.mCreatedAtTimeNs = 0;
+    other.mLocked = false;
+    return *this;
+}
+
 ScopedWakelock::ScopedWakelock(IScopedWakelockRefCounter* refCounter, bool locked)
     : mRefCounter(refCounter), mLocked(locked) {
     if (mLocked) {
diff --git a/sensors/common/default/2.X/multihal/include/V2_0/ScopedWakelock.h b/sensors/common/default/2.X/multihal/include/V2_0/ScopedWakelock.h
index 1cc5cd5..b3f398c 100644
--- a/sensors/common/default/2.X/multihal/include/V2_0/ScopedWakelock.h
+++ b/sensors/common/default/2.X/multihal/include/V2_0/ScopedWakelock.h
@@ -81,14 +81,15 @@
  */
 class ScopedWakelock {
   public:
-    ScopedWakelock(ScopedWakelock&&) = default;
-    ScopedWakelock& operator=(ScopedWakelock&&) = default;
+    ScopedWakelock(ScopedWakelock&& other);
+    ScopedWakelock& operator=(ScopedWakelock&& other);
     virtual ~ScopedWakelock();
 
     bool isLocked() const { return mLocked; }
 
   private:
     friend class HalProxyCallbackBase;
+    friend class ScopedWakelockTest;
     IScopedWakelockRefCounter* mRefCounter;
     int64_t mCreatedAtTimeNs;
     bool mLocked;
diff --git a/sensors/common/default/2.X/multihal/tests/Android.bp b/sensors/common/default/2.X/multihal/tests/Android.bp
index a15faed..1b60f4b 100644
--- a/sensors/common/default/2.X/multihal/tests/Android.bp
+++ b/sensors/common/default/2.X/multihal/tests/Android.bp
@@ -90,7 +90,10 @@
 
 cc_test {
     name: "android.hardware.sensors@2.X-halproxy-unit-tests",
-    srcs: ["HalProxy_test.cpp"],
+    srcs: [
+        "HalProxy_test.cpp",
+        "ScopedWakelock_test.cpp",
+    ],
     vendor: true,
     header_libs: [
         "android.hardware.sensors@2.X-shared-utils",
diff --git a/sensors/common/default/2.X/multihal/tests/ScopedWakelock_test.cpp b/sensors/common/default/2.X/multihal/tests/ScopedWakelock_test.cpp
new file mode 100644
index 0000000..133d9e8
--- /dev/null
+++ b/sensors/common/default/2.X/multihal/tests/ScopedWakelock_test.cpp
@@ -0,0 +1,110 @@
+//
+// 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.
+
+#include <gtest/gtest.h>
+
+#include "V2_0/ScopedWakelock.h"
+
+namespace android {
+namespace hardware {
+namespace sensors {
+namespace V2_0 {
+namespace implementation {
+
+class RefCounter : public IScopedWakelockRefCounter {
+  public:
+    size_t incCount = 0;
+    size_t decCount = 0;
+
+    bool incrementRefCountAndMaybeAcquireWakelock(size_t /* delta */,
+                                                  int64_t* /* timeoutStart */) override {
+        incCount++;
+        return true;
+    }
+
+    void decrementRefCountAndMaybeReleaseWakelock(size_t /* delta */,
+                                                  int64_t /* timeoutStart */) override {
+        decCount++;
+    }
+};
+
+class ScopedWakelockTest : public testing::Test {
+  public:
+    ScopedWakelock createScopedWakelock(bool locked) {
+        return ScopedWakelock(&mRefCounter, locked);
+    }
+
+    RefCounter mRefCounter;
+};
+
+TEST_F(ScopedWakelockTest, UnlockedAfterMoved) {
+    ScopedWakelock wakelock = createScopedWakelock(false /* locked */);
+
+    ScopedWakelock movedWakelock(std::move(wakelock));
+
+    EXPECT_FALSE(wakelock.isLocked());
+    EXPECT_FALSE(movedWakelock.isLocked());
+}
+
+TEST_F(ScopedWakelockTest, LockedAfterMoved) {
+    ScopedWakelock wakelock = createScopedWakelock(true /* locked */);
+
+    ScopedWakelock movedWakelock(std::move(wakelock));
+
+    EXPECT_FALSE(wakelock.isLocked());
+    EXPECT_TRUE(movedWakelock.isLocked());
+}
+
+TEST_F(ScopedWakelockTest, Locked) {
+    ScopedWakelock wakelock = createScopedWakelock(true /* locked */);
+
+    EXPECT_TRUE(wakelock.isLocked());
+}
+
+TEST_F(ScopedWakelockTest, Unlocked) {
+    ScopedWakelock wakelock = createScopedWakelock(false /* locked */);
+
+    EXPECT_FALSE(wakelock.isLocked());
+}
+
+TEST_F(ScopedWakelockTest, ScopedLocked) {
+    { createScopedWakelock(true /* locked */); }
+
+    EXPECT_EQ(mRefCounter.incCount, 1);
+    EXPECT_EQ(mRefCounter.decCount, 1);
+}
+
+TEST_F(ScopedWakelockTest, ScopedUnlockIsNoop) {
+    { createScopedWakelock(false /* locked */); }
+
+    EXPECT_EQ(mRefCounter.incCount, 0);
+    EXPECT_EQ(mRefCounter.decCount, 0);
+}
+
+TEST_F(ScopedWakelockTest, ScopedLockedMove) {
+    {
+        ScopedWakelock wakelock = createScopedWakelock(true /* locked */);
+        ScopedWakelock movedWakelock(std::move(wakelock));
+    }
+
+    EXPECT_EQ(mRefCounter.incCount, 1);
+    EXPECT_EQ(mRefCounter.decCount, 1);
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace sensors
+}  // namespace hardware
+}  // namespace android
\ No newline at end of file
diff --git a/tv/tuner/1.0/vts/functional/DescramblerTests.cpp b/tv/tuner/1.0/vts/functional/DescramblerTests.cpp
index d7440bc..2e27475 100644
--- a/tv/tuner/1.0/vts/functional/DescramblerTests.cpp
+++ b/tv/tuner/1.0/vts/functional/DescramblerTests.cpp
@@ -102,13 +102,13 @@
 
 AssertionResult DescramblerTests::setKeyToken(TunerKeyToken token) {
     Result status;
-    if (mDescrambler) {
+    if (!mDescrambler) {
         ALOGW("[vts] Descrambler is not opened yet.");
         return failure();
     }
 
     status = mDescrambler->setKeyToken(token);
-    if (status == Result::SUCCESS) {
+    if (status != Result::SUCCESS) {
         ALOGW("[vts] setKeyToken failed.");
         return failure();
     }
@@ -118,13 +118,13 @@
 
 AssertionResult DescramblerTests::addPid(DemuxPid pid, sp<IFilter> optionalSourceFilter) {
     Result status;
-    if (mDescrambler) {
+    if (!mDescrambler) {
         ALOGW("[vts] Descrambler is not opened yet.");
         return failure();
     }
 
     status = mDescrambler->addPid(pid, optionalSourceFilter);
-    if (status == Result::SUCCESS) {
+    if (status != Result::SUCCESS) {
         ALOGW("[vts] addPid failed.");
         return failure();
     }
@@ -134,13 +134,13 @@
 
 AssertionResult DescramblerTests::removePid(DemuxPid pid, sp<IFilter> optionalSourceFilter) {
     Result status;
-    if (mDescrambler) {
+    if (!mDescrambler) {
         ALOGW("[vts] Descrambler is not opened yet.");
         return failure();
     }
 
     status = mDescrambler->removePid(pid, optionalSourceFilter);
-    if (status == Result::SUCCESS) {
+    if (status != Result::SUCCESS) {
         ALOGW("[vts] removePid failed.");
         return failure();
     }
@@ -150,14 +150,14 @@
 
 AssertionResult DescramblerTests::closeDescrambler() {
     Result status;
-    if (mDescrambler) {
+    if (!mDescrambler) {
         ALOGW("[vts] Descrambler is not opened yet.");
         return failure();
     }
 
     status = mDescrambler->close();
     mDescrambler = nullptr;
-    if (status == Result::SUCCESS) {
+    if (status != Result::SUCCESS) {
         ALOGW("[vts] close Descrambler failed.");
         return failure();
     }
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
index 6819659..2be68b8 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
@@ -292,18 +292,18 @@
         ASSERT_TRUE(mFilterTests.configFilter((*config).settings, filterId));
         filterIds.insert(filterId);
     }
-    mDescramblerTests.openDescrambler(demuxId);
+    ASSERT_TRUE(mDescramblerTests.openDescrambler(demuxId));
     TunerKeyToken token;
     ASSERT_TRUE(mDescramblerTests.getKeyToken(descConfig.casSystemId, descConfig.provisionStr,
                                               descConfig.hidlPvtData, token));
-    mDescramblerTests.setKeyToken(token);
+    ASSERT_TRUE(mDescramblerTests.setKeyToken(token));
     vector<DemuxPid> pids;
     DemuxPid pid;
     for (config = mediaFilterConfs.begin(); config != mediaFilterConfs.end(); config++) {
         ASSERT_TRUE(mDescramblerTests.getDemuxPidFromFilterSettings((*config).type,
                                                                     (*config).settings, pid));
         pids.push_back(pid);
-        mDescramblerTests.addPid(pid, nullptr);
+        ASSERT_TRUE(mDescramblerTests.addPid(pid, nullptr));
     }
     for (id = filterIds.begin(); id != filterIds.end(); id++) {
         ASSERT_TRUE(mFilterTests.startFilter(*id));
@@ -316,9 +316,9 @@
         ASSERT_TRUE(mFilterTests.stopFilter(*id));
     }
     for (auto pid : pids) {
-        mDescramblerTests.removePid(pid, nullptr);
+        ASSERT_TRUE(mDescramblerTests.removePid(pid, nullptr));
     }
-    mDescramblerTests.closeDescrambler();
+    ASSERT_TRUE(mDescramblerTests.closeDescrambler());
     for (id = filterIds.begin(); id != filterIds.end(); id++) {
         ASSERT_TRUE(mFilterTests.closeFilter(*id));
     }
@@ -410,9 +410,9 @@
                                                filterArray[TS_PCR0].bufferSize));
     ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(pcrFilterId));
     ASSERT_TRUE(mFilterTests.configFilter(filterArray[TS_PCR0].settings, pcrFilterId));
-    mDemuxTests.getAvSyncId(mediaFilter, avSyncHwId);
+    ASSERT_TRUE(mDemuxTests.getAvSyncId(mediaFilter, avSyncHwId));
     ASSERT_TRUE(pcrFilterId == avSyncHwId);
-    mDemuxTests.getAvSyncTime(pcrFilterId);
+    ASSERT_TRUE(mDemuxTests.getAvSyncTime(pcrFilterId));
     ASSERT_TRUE(mFilterTests.closeFilter(pcrFilterId));
     ASSERT_TRUE(mFilterTests.closeFilter(mediaFilterId));
     ASSERT_TRUE(mDemuxTests.closeDemux());
@@ -519,8 +519,8 @@
     ASSERT_TRUE(mFrontendTests.setFrontendCallback());
     ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
     ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
-    mDescramblerTests.openDescrambler(demuxId);
-    mDescramblerTests.closeDescrambler();
+    ASSERT_TRUE(mDescramblerTests.openDescrambler(demuxId));
+    ASSERT_TRUE(mDescramblerTests.closeDescrambler());
     ASSERT_TRUE(mDemuxTests.closeDemux());
     ASSERT_TRUE(mFrontendTests.closeFrontend());
 }
diff --git a/usb/1.0/default/Usb.cpp b/usb/1.0/default/Usb.cpp
index 6eb8842..f72ab9c 100644
--- a/usb/1.0/default/Usb.cpp
+++ b/usb/1.0/default/Usb.cpp
@@ -206,6 +206,19 @@
 
 bool canSwitchRoleHelper(const std::string portName, PortRoleType type)  {
     std::string filename = appendRoleNodeHelper(portName, type);
+
+    if (type == PortRoleType::DATA_ROLE || type == PortRoleType::POWER_ROLE) {
+        std::string pd_filename = "/sys/class/power_supply/usb/pd_active";
+        std::string pd_active;
+
+        if (!readFile(pd_filename, pd_active)) {
+            if (pd_active == "0")
+                return false;
+        } else {
+            ALOGE("canSwitchRoleHelper: couldn't read %s", pd_filename.c_str());
+        }
+    }
+
     std::ofstream file(filename);
 
     if (file.is_open()) {
@@ -396,7 +409,7 @@
 
         for (int n = 0; n < nevents; ++n) {
             if (events[n].data.ptr)
-                (*(void (*)(int, struct data *payload))events[n].data.ptr)
+                (*(void (*)(uint32_t, struct data *payload))events[n].data.ptr)
                     (events[n].events, &payload);
         }
     }
diff --git a/vibrator/1.0/default/Android.bp b/vibrator/1.0/default/Android.bp
index b0d0986..1385eac 100644
--- a/vibrator/1.0/default/Android.bp
+++ b/vibrator/1.0/default/Android.bp
@@ -42,5 +42,13 @@
         "libutils",
         "libhardware",
         "android.hardware.vibrator@1.0",
+        "libhwbinder",
     ],
+    arch: {
+        arm: {
+            cflags: [
+                "-DARCH_ARM_32"
+            ],
+        },
+    },
 }
diff --git a/vibrator/1.0/default/service.cpp b/vibrator/1.0/default/service.cpp
index 7cc0744..b626056 100644
--- a/vibrator/1.0/default/service.cpp
+++ b/vibrator/1.0/default/service.cpp
@@ -17,10 +17,14 @@
 
 #include <android/hardware/vibrator/1.0/IVibrator.h>
 #include <hidl/LegacySupport.h>
+#include <hwbinder/ProcessState.h>
 
 using android::hardware::vibrator::V1_0::IVibrator;
 using android::hardware::defaultPassthroughServiceImplementation;
 
 int main() {
+#ifdef ARCH_ARM_32
+    android::hardware::ProcessState::initWithMmapSize((size_t)8192);
+#endif
     return defaultPassthroughServiceImplementation<IVibrator>();
 }
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index 8340517..4967d71 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -95,7 +95,7 @@
 }
 
 TEST_P(VibratorAidl, OnWithCallback) {
-    if (!(capabilities & IVibrator::CAP_PERFORM_CALLBACK)) return;
+    if (!(capabilities & IVibrator::CAP_ON_CALLBACK)) return;
 
     std::promise<void> completionPromise;
     std::future<void> completionFuture{completionPromise.get_future()};
@@ -109,7 +109,7 @@
 }
 
 TEST_P(VibratorAidl, OnCallbackNotSupported) {
-    if (!(capabilities & IVibrator::CAP_PERFORM_CALLBACK)) {
+    if (!(capabilities & IVibrator::CAP_ON_CALLBACK)) {
         sp<CompletionCallback> callback = new CompletionCallback([] {});
         EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, vibrator->on(250, callback).exceptionCode());
     }
diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
index 3ff33a5..5b11dd3 100644
--- a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
+++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
@@ -89,8 +89,12 @@
 }
 }  // namespace
 
+sp<IWifi> getWifi(const std::string& instance_name) {
+    return IWifi::getService(instance_name);
+}
+
 sp<IWifiChip> getWifiChip(const std::string& instance_name) {
-    sp<IWifi> wifi = IWifi::getService(instance_name);
+    sp<IWifi> wifi = getWifi(instance_name);
     if (!wifi.get()) {
         return nullptr;
     }
diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.h b/wifi/1.0/vts/functional/wifi_hidl_test_utils.h
index d22ed77..5c78637 100644
--- a/wifi/1.0/vts/functional/wifi_hidl_test_utils.h
+++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.h
@@ -31,6 +31,8 @@
 // Note: We only have a single instance of each of these objects currently.
 // These helper functions should be modified to return vectors if we support
 // multiple instances.
+android::sp<android::hardware::wifi::V1_0::IWifi> getWifi(
+    const std::string& instance_name);
 android::sp<android::hardware::wifi::V1_0::IWifiChip> getWifiChip(
     const std::string& instance_name);
 android::sp<android::hardware::wifi::V1_0::IWifiApIface> getWifiApIface(
diff --git a/wifi/1.4/default/Android.mk b/wifi/1.4/default/Android.mk
index 6be7dad..e7fde844 100644
--- a/wifi/1.4/default/Android.mk
+++ b/wifi/1.4/default/Android.mk
@@ -39,6 +39,12 @@
 ifdef WIFI_AVOID_IFACE_RESET_MAC_CHANGE
 LOCAL_CPPFLAGS += -DWIFI_AVOID_IFACE_RESET_MAC_CHANGE
 endif
+ifdef QC_WIFI_HIDL_FEATURE_DUAL_AP
+LOCAL_CPPFLAGS += -DQC_WIFI_HIDL_FEATURE_DUAL_AP
+endif
+ifdef QC_WIFI_HIDL_FEATURE_DUAL_STA
+LOCAL_CPPFLAGS += -DQC_WIFI_HIDL_FEATURE_DUAL_STA
+endif
 # Allow implicit fallthroughs in wifi_legacy_hal.cpp until they are fixed.
 LOCAL_CFLAGS += -Wno-error=implicit-fallthrough
 LOCAL_SRC_FILES := \
@@ -84,6 +90,10 @@
 LOCAL_MODULE_RELATIVE_PATH := hw
 LOCAL_PROPRIETARY_MODULE := true
 LOCAL_CPPFLAGS := -Wall -Werror -Wextra
+ifeq ($(TARGET_ARCH),arm)
+    LOCAL_CPPFLAGS += -DARCH_ARM_32
+endif
+
 LOCAL_SRC_FILES := \
     service.cpp
 LOCAL_SHARED_LIBRARIES := \
@@ -93,6 +103,7 @@
     liblog \
     libnl \
     libutils \
+    libhwbinder \
     libwifi-hal \
     libwifi-system-iface \
     android.hardware.wifi@1.0 \
diff --git a/wifi/1.4/default/android.hardware.wifi@1.0-service-lazy.rc b/wifi/1.4/default/android.hardware.wifi@1.0-service-lazy.rc
index cf917b5..061689d 100644
--- a/wifi/1.4/default/android.hardware.wifi@1.0-service-lazy.rc
+++ b/wifi/1.4/default/android.hardware.wifi@1.0-service-lazy.rc
@@ -1,5 +1,9 @@
 service vendor.wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi@1.0-service-lazy
     interface android.hardware.wifi@1.0::IWifi default
+    interface android.hardware.wifi@1.1::IWifi default
+    interface android.hardware.wifi@1.2::IWifi default
+    interface android.hardware.wifi@1.3::IWifi default
+    interface android.hardware.wifi@1.4::IWifi default
     oneshot
     disabled
     class hal
diff --git a/wifi/1.4/default/hidl_struct_util.cpp b/wifi/1.4/default/hidl_struct_util.cpp
index fd1d5b1..87c0708 100644
--- a/wifi/1.4/default/hidl_struct_util.cpp
+++ b/wifi/1.4/default/hidl_struct_util.cpp
@@ -52,7 +52,7 @@
         case legacy_hal::WIFI_LOGGER_POWER_EVENT_SUPPORTED:
             return HidlChipCaps::DEBUG_RING_BUFFER_POWER_EVENT;
         case legacy_hal::WIFI_LOGGER_WAKE_LOCK_SUPPORTED:
-            return HidlChipCaps::DEBUG_RING_BUFFER_WAKELOCK_EVENT;
+            return HidlChipCaps::DEBUG_HOST_WAKE_REASON_STATS;
     };
     CHECK(false) << "Unknown legacy feature: " << feature;
     return {};
@@ -155,10 +155,8 @@
         }
     }
 
-    // There are no flags for these 3 in the legacy feature set. Adding them to
+    // There are no flags for these in the legacy feature set. Adding this to
     // the set because all the current devices support it.
-    *hidl_caps |= HidlChipCaps::DEBUG_RING_BUFFER_VENDOR_DATA;
-    *hidl_caps |= HidlChipCaps::DEBUG_HOST_WAKE_REASON_STATS;
     *hidl_caps |= HidlChipCaps::DEBUG_ERROR_ALERTS;
     return true;
 }
diff --git a/wifi/1.4/default/service.cpp b/wifi/1.4/default/service.cpp
index 3f7f609..a959571 100644
--- a/wifi/1.4/default/service.cpp
+++ b/wifi/1.4/default/service.cpp
@@ -19,6 +19,9 @@
 #include <hidl/HidlTransportSupport.h>
 #include <utils/Looper.h>
 #include <utils/StrongPointer.h>
+#include <hwbinder/ProcessState.h>
+#include <cutils/properties.h>
+#include <signal.h>
 
 #include "wifi.h"
 #include "wifi_feature_flags.h"
@@ -35,6 +38,17 @@
 using android::hardware::wifi::V1_4::implementation::mode_controller::
     WifiModeController;
 
+#ifdef ARCH_ARM_32
+#define DEFAULT_WIFIHAL_HW_BINDER_SIZE_KB 16
+size_t getHWBinderMmapSize() {
+    size_t value = 0;
+    value = property_get_int32("persist.vendor.wifi.wifihal.hw.binder.size", DEFAULT_WIFIHAL_HW_BINDER_SIZE_KB);
+    if (!value) value = DEFAULT_WIFIHAL_HW_BINDER_SIZE_KB; // deafult to 1 page of 4 Kb
+
+    return 1024 * value;
+}
+#endif /* ARCH_ARM_32 */
+
 #ifdef LAZY_SERVICE
 const bool kLazyService = true;
 #else
@@ -42,6 +56,10 @@
 #endif
 
 int main(int /*argc*/, char** argv) {
+#ifdef ARCH_ARM_32
+    android::hardware::ProcessState::initWithMmapSize(getHWBinderMmapSize());
+#endif /* ARCH_ARM_32 */
+    signal(SIGPIPE, SIG_IGN);
     android::base::InitLogging(
         argv, android::base::LogdLogger(android::base::SYSTEM));
     LOG(INFO) << "Wifi Hal is booting up...";
diff --git a/wifi/1.4/default/wifi_ap_iface.cpp b/wifi/1.4/default/wifi_ap_iface.cpp
index 8777a4c..6218d0f 100644
--- a/wifi/1.4/default/wifi_ap_iface.cpp
+++ b/wifi/1.4/default/wifi_ap_iface.cpp
@@ -113,7 +113,23 @@
 
 WifiStatus WifiApIface::setMacAddressInternal(
     const std::array<uint8_t, 6>& mac) {
+#ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE
+    if (!iface_util_.lock()->setUpState(ifname_, false)) {
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+#endif
     bool status = iface_util_.lock()->setMacAddress(ifname_, mac);
+#ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE
+    if (!iface_util_.lock()->setUpState(ifname_, true)) {
+        LOG(INFO) << "Wait for driver ready and try to set iface UP again";
+        if (legacy_hal_.lock()->waitForDriverReady() !=
+                legacy_hal::WIFI_SUCCESS ||
+            !iface_util_.lock()->setUpState(ifname_, true)) {
+            return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+        }
+    }
+    iface_util_.lock()->onStateToggleOffOn(ifname_);
+#endif
     if (!status) {
         return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
     }
diff --git a/wifi/1.4/default/wifi_chip.cpp b/wifi/1.4/default/wifi_chip.cpp
old mode 100644
new mode 100755
index 8747e61..16f9f26
--- a/wifi/1.4/default/wifi_chip.cpp
+++ b/wifi/1.4/default/wifi_chip.cpp
@@ -21,6 +21,7 @@
 #include <cutils/properties.h>
 #include <sys/stat.h>
 #include <sys/sysmacros.h>
+#include <net/if.h>
 
 #include "hidl_return_util.h"
 #include "hidl_struct_util.h"
@@ -624,6 +625,15 @@
 Return<void> WifiChip::debug(const hidl_handle& handle,
                              const hidl_vec<hidl_string>&) {
     if (handle != nullptr && handle->numFds >= 1) {
+        {
+            std::unique_lock<std::mutex> lk(lock_t);
+            for (const auto& item : ringbuffer_map_) {
+                forceDumpToDebugRingBufferInternal(item.first);
+            }
+            // unique_lock unlocked here
+        }
+        usleep(100 * 1000);  // sleep for 100 milliseconds to wait for
+                             // ringbuffer updates.
         int fd = handle->data[0];
         if (!writeRingbufferFilesInternal()) {
             LOG(ERROR) << "Error writing files to flash";
@@ -655,7 +665,36 @@
                            hidl_status_cb, event_callback);
 }
 
+void WifiChip::QcRemoveAndClearDynamicIfaces() {
+    for (const auto& iface : created_ap_ifaces_) {
+        std::string ifname = iface->getName();
+        legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->deleteVirtualInterface(ifname);
+        if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+            LOG(ERROR) << "Failed to remove interface: " << ifname << " "
+                       << legacyErrorToString(legacy_status);
+        }
+    }
+
+    for (const auto& iface : created_sta_ifaces_) {
+        std::string ifname = iface->getName();
+        legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->deleteVirtualInterface(ifname);
+        if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+            LOG(ERROR) << "Failed to remove interface: " << ifname << " "
+                       << legacyErrorToString(legacy_status);
+        }
+    }
+
+    // created_ap/sta_ifaces are also part of sta/ap_ifaces.
+    // Do no invalidate here.
+
+    created_ap_ifaces_.clear();
+    created_sta_ifaces_.clear();
+}
+
 void WifiChip::invalidateAndRemoveAllIfaces() {
+    QcRemoveAndClearDynamicIfaces();
     invalidateAndClearAll(ap_ifaces_);
     invalidateAndClearAll(nan_ifaces_);
     invalidateAndClearAll(p2p_ifaces_);
@@ -815,18 +854,25 @@
     if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::AP)) {
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
     }
+
+    bool iface_created = false;
     std::string ifname = allocateApIfaceName();
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->createVirtualInterface(
-            ifname,
-            hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::AP));
-    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        LOG(ERROR) << "Failed to add interface: " << ifname << " "
-                   << legacyErrorToString(legacy_status);
-        return {createWifiStatusFromLegacyError(legacy_status), {}};
+    if (!if_nametoindex(ifname.c_str())) {
+        legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->createVirtualInterface(
+                ifname,
+                hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::AP));
+        if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+            LOG(ERROR) << "Failed to add interface: " << ifname << " "
+                       << legacyErrorToString(legacy_status);
+            return {createWifiStatusFromLegacyError(legacy_status), {}};
+        }
+        iface_created = true;
     }
+    iface_util_.lock()->setRandomMacAddressIndex(ap_ifaces_.size());
     sp<WifiApIface> iface = new WifiApIface(ifname, legacy_hal_, iface_util_);
     ap_ifaces_.push_back(iface);
+    if (iface_created) created_ap_ifaces_.push_back(iface);
     for (const auto& callback : event_cb_handler_.getCallbacks()) {
         if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) {
             LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
@@ -863,11 +909,15 @@
     // nan/rtt objects over AP iface. But, there is no harm to do it
     // here and not make that assumption all over the place.
     invalidateAndRemoveDependencies(ifname);
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->deleteVirtualInterface(ifname);
-    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        LOG(ERROR) << "Failed to remove interface: " << ifname << " "
-                   << legacyErrorToString(legacy_status);
+    if (findUsingName(created_ap_ifaces_, ifname) != nullptr) {
+        iface_util_.lock()->setUpState(ifname, false);
+        legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->deleteVirtualInterface(ifname);
+        if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+            LOG(ERROR) << "Failed to remove interface: " << ifname << " "
+                       << legacyErrorToString(legacy_status);
+        }
+        invalidateAndClear(created_ap_ifaces_, iface);
     }
     invalidateAndClear(ap_ifaces_, iface);
     for (const auto& callback : event_cb_handler_.getCallbacks()) {
@@ -984,18 +1034,23 @@
     if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::STA)) {
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
     }
+    bool iface_created = false;
     std::string ifname = allocateStaIfaceName();
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->createVirtualInterface(
-            ifname,
-            hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::STA));
-    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        LOG(ERROR) << "Failed to add interface: " << ifname << " "
-                   << legacyErrorToString(legacy_status);
-        return {createWifiStatusFromLegacyError(legacy_status), {}};
+    if (!if_nametoindex(ifname.c_str())) {
+        legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->createVirtualInterface(
+                ifname,
+                hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::STA));
+        if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+            LOG(ERROR) << "Failed to add interface: " << ifname << " "
+                       << legacyErrorToString(legacy_status);
+            return {createWifiStatusFromLegacyError(legacy_status), {}};
+        }
+        iface_created = true;
     }
     sp<WifiStaIface> iface = new WifiStaIface(ifname, legacy_hal_, iface_util_);
     sta_ifaces_.push_back(iface);
+    if (iface_created) created_sta_ifaces_.push_back(iface);
     for (const auto& callback : event_cb_handler_.getCallbacks()) {
         if (!callback->onIfaceAdded(IfaceType::STA, ifname).isOk()) {
             LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
@@ -1029,11 +1084,15 @@
     }
     // Invalidate & remove any dependent objects first.
     invalidateAndRemoveDependencies(ifname);
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->deleteVirtualInterface(ifname);
-    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        LOG(ERROR) << "Failed to remove interface: " << ifname << " "
-                   << legacyErrorToString(legacy_status);
+    if (findUsingName(created_sta_ifaces_, ifname) != nullptr) {
+        iface_util_.lock()->setUpState(ifname, false);
+        legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->deleteVirtualInterface(ifname);
+        if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+            LOG(ERROR) << "Failed to remove interface: " << ifname << " "
+                       << legacyErrorToString(legacy_status);
+        }
+        invalidateAndClear(created_sta_ifaces_, iface);
     }
     invalidateAndClear(sta_ifaces_, iface);
     for (const auto& callback : event_cb_handler_.getCallbacks()) {
@@ -1120,6 +1179,9 @@
     legacy_hal::wifi_error legacy_status =
         legacy_hal_.lock()->deregisterRingBufferCallbackHandler(
             getFirstActiveWlanIfaceName());
+    if (legacy_status == legacy_hal::WIFI_SUCCESS) {
+        debug_ring_buffer_cb_registered_ = false;
+    }
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
@@ -1335,7 +1397,7 @@
                     LOG(ERROR) << "Ringname " << name << " not found";
                     return;
                 }
-                // unlock
+                // unique_lock unlocked here
             }
         };
     legacy_hal::wifi_error legacy_status =
@@ -1558,13 +1620,6 @@
     return canCurrentModeSupportIfaceCombo(req_iface_combo);
 }
 
-bool WifiChip::isDualApAllowedInCurrentMode() {
-    // Check if we can support atleast 1 STA & 1 AP concurrently.
-    std::map<IfaceType, size_t> req_iface_combo;
-    req_iface_combo[IfaceType::AP] = 2;
-    return canCurrentModeSupportIfaceCombo(req_iface_combo);
-}
-
 std::string WifiChip::getFirstActiveWlanIfaceName() {
     if (sta_ifaces_.size() > 0) return sta_ifaces_[0]->getName();
     if (ap_ifaces_.size() > 0) return ap_ifaces_[0]->getName();
@@ -1590,17 +1645,15 @@
 }
 
 // AP iface names start with idx 1 for modes supporting
-// concurrent STA and not dual AP, else start with idx 0.
+// concurrent STA, else start with idx 0.
 std::string WifiChip::allocateApIfaceName() {
     // Check if we have a dedicated iface for AP.
     std::string ifname = getApIfaceName();
     if (!ifname.empty()) {
         return ifname;
     }
-    return allocateApOrStaIfaceName((isStaApConcurrencyAllowedInCurrentMode() &&
-                                     !isDualApAllowedInCurrentMode())
-                                        ? 1
-                                        : 0);
+    return allocateApOrStaIfaceName(
+        isStaApConcurrencyAllowedInCurrentMode() ? 1 : 0);
 }
 
 // STA iface names start with idx 0.
@@ -1637,7 +1690,7 @@
                 }
             }
         }
-        // unlock
+        // unique_lock unlocked here
     }
     return true;
 }
diff --git a/wifi/1.4/default/wifi_chip.h b/wifi/1.4/default/wifi_chip.h
index 98e18bb..abe025c 100644
--- a/wifi/1.4/default/wifi_chip.h
+++ b/wifi/1.4/default/wifi_chip.h
@@ -253,12 +253,12 @@
     bool canCurrentModeSupportIfaceOfType(IfaceType requested_type);
     bool isValidModeId(ChipModeId mode_id);
     bool isStaApConcurrencyAllowedInCurrentMode();
-    bool isDualApAllowedInCurrentMode();
     std::string getFirstActiveWlanIfaceName();
     std::string allocateApOrStaIfaceName(uint32_t start_idx);
     std::string allocateApIfaceName();
     std::string allocateStaIfaceName();
     bool writeRingbufferFilesInternal();
+    void QcRemoveAndClearDynamicIfaces();
 
     ChipId chip_id_;
     std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
@@ -282,6 +282,9 @@
     hidl_callback_util::HidlCallbackHandler<IWifiChipEventCallback>
         event_cb_handler_;
 
+    std::vector<sp<WifiApIface>> created_ap_ifaces_;
+    std::vector<sp<WifiStaIface>> created_sta_ifaces_;
+
     DISALLOW_COPY_AND_ASSIGN(WifiChip);
 };
 
diff --git a/wifi/1.4/default/wifi_feature_flags.cpp b/wifi/1.4/default/wifi_feature_flags.cpp
index 195b460..515386e 100644
--- a/wifi/1.4/default/wifi_feature_flags.cpp
+++ b/wifi/1.4/default/wifi_feature_flags.cpp
@@ -79,14 +79,44 @@
 #      define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P}, 1}}
 #    endif
 #  else
-#    ifdef WIFI_HIDL_FEATURE_AWARE
-//     (1 STA + 1 AP) or (1 STA + 1 of (P2P or NAN))
-#      define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\
-                                              {{{STA}, 1}, {{P2P, NAN}, 1}}
+#    ifdef QC_WIFI_HIDL_FEATURE_DUAL_AP
+#      ifdef QC_WIFI_HIDL_FEATURE_DUAL_STA
+#        ifdef WIFI_HIDL_FEATURE_AWARE
+//         (1 STA + 1 AP) or (1 STA + 1 of (P2P or NAN)) or (2 AP) or (2 STA)
+#          define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\
+                                                  {{{STA}, 1}, {{P2P, NAN}, 1}},\
+                                                  {{{AP}, 2}},\
+                                                  {{{STA}, 2}}
+#        else
+//         (1 STA + 1 AP) or (1 STA + 1 P2P) or (2 AP) or (2 STA)
+#          define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\
+                                                  {{{STA}, 1}, {{P2P}, 1}},\
+                                                  {{{AP}, 2}},\
+                                                  {{{STA}, 2}}
+#        endif
+#      else
+#        ifdef WIFI_HIDL_FEATURE_AWARE
+//         (1 STA + 1 AP) or (1 STA + 1 of (P2P or NAN)) or (2 AP)
+#          define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\
+                                                  {{{STA}, 1}, {{P2P, NAN}, 1}},\
+                                                  {{{AP}, 2}}
+#        else
+//         (1 STA + 1 AP) or (1 STA + 1 P2P) or (2 AP)
+#          define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\
+                                                  {{{STA}, 1}, {{P2P}, 1}},\
+                                                  {{{AP}, 2}}
+#        endif
+#      endif
 #    else
-//     (1 STA + 1 AP) or (1 STA + 1 P2P)
-#      define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\
-                                              {{{STA}, 1}, {{P2P}, 1}}
+#      ifdef WIFI_HIDL_FEATURE_AWARE
+//       (1 STA + 1 AP) or (1 STA + 1 of (P2P or NAN))
+#        define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\
+                                                {{{STA}, 1}, {{P2P, NAN}, 1}}
+#      else
+//       (1 STA + 1 AP) or (1 STA + 1 P2P)
+#        define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\
+                                                {{{STA}, 1}, {{P2P}, 1}}
+#      endif
 #    endif
 #  endif
 #else
diff --git a/wifi/1.4/default/wifi_iface_util.cpp b/wifi/1.4/default/wifi_iface_util.cpp
index 49b7674..97c2f6a 100644
--- a/wifi/1.4/default/wifi_iface_util.cpp
+++ b/wifi/1.4/default/wifi_iface_util.cpp
@@ -43,8 +43,11 @@
 WifiIfaceUtil::WifiIfaceUtil(
     const std::weak_ptr<wifi_system::InterfaceTool> iface_tool)
     : iface_tool_(iface_tool),
-      random_mac_address_(nullptr),
-      event_handlers_map_() {}
+      random_mac_address_index_(0),
+      event_handlers_map_() {
+    for (int i=0; i < MAX_RANDOM_MAC_ADDR_INDEX; i++)
+        random_mac_address_[i] = nullptr;
+}
 
 std::array<uint8_t, 6> WifiIfaceUtil::getFactoryMacAddress(
     const std::string& iface_name) {
@@ -53,22 +56,15 @@
 
 bool WifiIfaceUtil::setMacAddress(const std::string& iface_name,
                                   const std::array<uint8_t, 6>& mac) {
-#ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE
-    if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), false)) {
-        LOG(ERROR) << "SetUpState(false) failed.";
-        return false;
-    }
-#endif
     if (!iface_tool_.lock()->SetMacAddress(iface_name.c_str(), mac)) {
         LOG(ERROR) << "SetMacAddress failed.";
         return false;
     }
-#ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE
-    if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), true)) {
-        LOG(ERROR) << "SetUpState(true) failed.";
-        return false;
-    }
-#endif
+    LOG(DEBUG) << "Successfully SetMacAddress.";
+    return true;
+}
+
+void WifiIfaceUtil::onStateToggleOffOn(const std::string& iface_name) {
     IfaceEventHandlers event_handlers = {};
     const auto it = event_handlers_map_.find(iface_name);
     if (it != event_handlers_map_.end()) {
@@ -77,17 +73,24 @@
     if (event_handlers.on_state_toggle_off_on != nullptr) {
         event_handlers.on_state_toggle_off_on(iface_name);
     }
-    LOG(DEBUG) << "Successfully SetMacAddress.";
-    return true;
+}
+
+void WifiIfaceUtil::setRandomMacAddressIndex(int idx) {
+    if (idx >= MAX_RANDOM_MAC_ADDR_INDEX) {
+        LOG(ERROR) << "Requested random mac address index crossed max limit!!";
+        return;
+    }
+
+    random_mac_address_index_ = idx;
 }
 
 std::array<uint8_t, 6> WifiIfaceUtil::getOrCreateRandomMacAddress() {
-    if (random_mac_address_) {
-        return *random_mac_address_.get();
+    if (random_mac_address_[random_mac_address_index_]) {
+        return *random_mac_address_[random_mac_address_index_].get();
     }
-    random_mac_address_ =
+    random_mac_address_[random_mac_address_index_] =
         std::make_unique<std::array<uint8_t, 6>>(createRandomMacAddress());
-    return *random_mac_address_.get();
+    return *random_mac_address_[random_mac_address_index_].get();
 }
 
 void WifiIfaceUtil::registerIfaceEventHandlers(const std::string& iface_name,
diff --git a/wifi/1.4/default/wifi_iface_util.h b/wifi/1.4/default/wifi_iface_util.h
index 126b6ca..a7274a1 100644
--- a/wifi/1.4/default/wifi_iface_util.h
+++ b/wifi/1.4/default/wifi_iface_util.h
@@ -17,6 +17,8 @@
 #ifndef WIFI_IFACE_UTIL_H_
 #define WIFI_IFACE_UTIL_H_
 
+#define MAX_RANDOM_MAC_ADDR_INDEX 5
+
 #include <wifi_system/interface_tool.h>
 
 #include <android/hardware/wifi/1.0/IWifi.h>
@@ -52,18 +54,22 @@
     // daemon. (So, changes on every reboot)
     virtual std::array<uint8_t, 6> getOrCreateRandomMacAddress();
 
+    virtual void setRandomMacAddressIndex(int idx);
     // Register for any iface event callbacks for the provided interface.
     virtual void registerIfaceEventHandlers(const std::string& iface_name,
                                             IfaceEventHandlers handlers);
     virtual void unregisterIfaceEventHandlers(const std::string& iface_name);
     virtual bool setUpState(const std::string& iface_name, bool request_up);
     virtual unsigned ifNameToIndex(const std::string& iface_name);
+    virtual void onStateToggleOffOn(const std::string& iface_name);
 
    private:
     std::array<uint8_t, 6> createRandomMacAddress();
 
     std::weak_ptr<wifi_system::InterfaceTool> iface_tool_;
-    std::unique_ptr<std::array<uint8_t, 6>> random_mac_address_;
+    std::unique_ptr<std::array<uint8_t, 6>> random_mac_address_[MAX_RANDOM_MAC_ADDR_INDEX];
+
+    int random_mac_address_index_;
     std::map<std::string, IfaceEventHandlers> event_handlers_map_;
 };
 
diff --git a/wifi/1.4/default/wifi_legacy_hal.cpp b/wifi/1.4/default/wifi_legacy_hal.cpp
index 29123bf..5678848 100644
--- a/wifi/1.4/default/wifi_legacy_hal.cpp
+++ b/wifi/1.4/default/wifi_legacy_hal.cpp
@@ -36,7 +36,7 @@
 static constexpr uint32_t kLinkLayerStatsDataMpduSizeThreshold = 128;
 static constexpr uint32_t kMaxWakeReasonStatsArraySize = 32;
 static constexpr uint32_t kMaxRingBuffers = 10;
-static constexpr uint32_t kMaxStopCompleteWaitMs = 100;
+static constexpr uint32_t kMaxStopCompleteWaitMs = 2000;
 static constexpr char kDriverPropName[] = "wlan.driver.status";
 
 // Helper function to create a non-const char* for legacy Hal API's.
@@ -367,8 +367,8 @@
     }
     LOG(DEBUG) << "Waiting for the driver ready";
     wifi_error status = global_func_table_.wifi_wait_for_driver_ready();
-    if (status == WIFI_ERROR_TIMED_OUT) {
-        LOG(ERROR) << "Timed out awaiting driver ready";
+    if (status == WIFI_ERROR_TIMED_OUT || status == WIFI_ERROR_UNKNOWN) {
+        LOG(ERROR) << "Failed or timed out awaiting driver ready";
         return status;
     }
     property_set(kDriverPropName, "ok");
@@ -402,7 +402,7 @@
         on_stop_complete_user_callback();
         return WIFI_SUCCESS;
     }
-    LOG(DEBUG) << "Stopping legacy HAL";
+    LOG(ERROR) << "Stopping legacy HAL";
     on_stop_complete_internal_callback = [on_stop_complete_user_callback,
                                           this](wifi_handle handle) {
         CHECK_EQ(global_handle_, handle) << "Handle mismatch";
@@ -411,10 +411,12 @@
         // stopped.
         invalidate();
         iface_tool_.lock()->SetWifiUpState(false);
+        LOG(ERROR) << "SetWifiUpState(false) completed";
         on_stop_complete_user_callback();
         is_started_ = false;
     };
     awaiting_event_loop_termination_ = true;
+    LOG(ERROR) << "Legacy HAL trigger wifi cleanup";
     global_func_table_.wifi_cleanup(global_handle_, onAsyncStopComplete);
     const auto status = stop_wait_cv_.wait_for(
         *lock, std::chrono::milliseconds(kMaxStopCompleteWaitMs),
@@ -1390,12 +1392,13 @@
 void WifiLegacyHal::runEventLoop() {
     LOG(DEBUG) << "Starting legacy HAL event loop";
     global_func_table_.wifi_event_loop(global_handle_);
+    LOG(ERROR) << "Legacy HAL Wifi event loop exited";
     const auto lock = hidl_sync_util::acquireGlobalLock();
     if (!awaiting_event_loop_termination_) {
         LOG(FATAL)
             << "Legacy HAL event loop terminated, but HAL was not stopping";
     }
-    LOG(DEBUG) << "Legacy HAL event loop terminated";
+    LOG(ERROR) << "Legacy HAL event loop terminated";
     awaiting_event_loop_termination_ = false;
     stop_wait_cv_.notify_one();
 }
@@ -1459,6 +1462,10 @@
     return status;
 }
 
+wifi_error WifiLegacyHal::waitForDriverReady() {
+    return global_func_table_.wifi_wait_for_driver_ready();
+}
+
 void WifiLegacyHal::invalidate() {
     global_handle_ = nullptr;
     iface_name_to_handle_.clear();
diff --git a/wifi/1.4/default/wifi_legacy_hal.h b/wifi/1.4/default/wifi_legacy_hal.h
index 9964460..03035ec 100644
--- a/wifi/1.4/default/wifi_legacy_hal.h
+++ b/wifi/1.4/default/wifi_legacy_hal.h
@@ -375,6 +375,8 @@
                                               wifi_interface_type iftype);
     virtual wifi_error deleteVirtualInterface(const std::string& ifname);
 
+    virtual wifi_error waitForDriverReady();
+
    private:
     // Retrieve interface handles for all the available interfaces.
     wifi_error retrieveIfaceHandles();
diff --git a/wifi/1.4/default/wifi_nan_iface.cpp b/wifi/1.4/default/wifi_nan_iface.cpp
index 5764d35..24ffb17 100644
--- a/wifi/1.4/default/wifi_nan_iface.cpp
+++ b/wifi/1.4/default/wifi_nan_iface.cpp
@@ -534,6 +534,9 @@
 }
 
 void WifiNanIface::invalidate() {
+    if (!isValid()) {
+        return;
+    }
     // send commands to HAL to actually disable and destroy interfaces
     legacy_hal_.lock()->nanDisableRequest(ifname_, 0xFFFF);
     legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFE, "aware_data0");
diff --git a/wifi/1.4/default/wifi_sta_iface.cpp b/wifi/1.4/default/wifi_sta_iface.cpp
index 49f383a..ee70461 100644
--- a/wifi/1.4/default/wifi_sta_iface.cpp
+++ b/wifi/1.4/default/wifi_sta_iface.cpp
@@ -625,7 +625,23 @@
 
 WifiStatus WifiStaIface::setMacAddressInternal(
     const std::array<uint8_t, 6>& mac) {
+#ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE
+    if (!iface_util_.lock()->setUpState(ifname_, false)) {
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+#endif
     bool status = iface_util_.lock()->setMacAddress(ifname_, mac);
+#ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE
+    if (!iface_util_.lock()->setUpState(ifname_, true)) {
+        LOG(INFO) << "Wait for driver ready and try to set iface UP again";
+        if (legacy_hal_.lock()->waitForDriverReady() !=
+                legacy_hal::WIFI_SUCCESS ||
+            !iface_util_.lock()->setUpState(ifname_, true)) {
+            return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+        }
+    }
+    iface_util_.lock()->onStateToggleOffOn(ifname_);
+#endif
     if (!status) {
         return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
     }
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
index d4063fe..75d6252 100644
--- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
@@ -17,7 +17,6 @@
 #include <android-base/logging.h>
 
 #include <android/hidl/manager/1.0/IServiceManager.h>
-#include <android/hidl/manager/1.0/IServiceNotification.h>
 #include <hidl/HidlTransportSupport.h>
 
 #include <wifi_system/hostapd_manager.h>
@@ -39,7 +38,6 @@
 using ::android::hardware::wifi::hostapd::V1_0::IHostapd;
 using ::android::hardware::wifi::V1_0::ChipModeId;
 using ::android::hardware::wifi::V1_0::IWifiChip;
-using ::android::hidl::manager::V1_0::IServiceNotification;
 using ::android::wifi_system::HostapdManager;
 using ::android::wifi_system::SupplicantManager;
 
@@ -47,68 +45,27 @@
 // Helper function to initialize the driver and firmware to AP mode
 // using the vendor HAL HIDL interface.
 void initilializeDriverAndFirmware(const std::string& wifi_instance_name) {
-    sp<IWifiChip> wifi_chip = getWifiChip(wifi_instance_name);
-    ChipModeId mode_id;
-    EXPECT_TRUE(configureChipToSupportIfaceType(
-        wifi_chip, ::android::hardware::wifi::V1_0::IfaceType::AP, &mode_id));
+    if (getWifi(wifi_instance_name) != nullptr) {
+        sp<IWifiChip> wifi_chip = getWifiChip(wifi_instance_name);
+        ChipModeId mode_id;
+        EXPECT_TRUE(configureChipToSupportIfaceType(
+            wifi_chip, ::android::hardware::wifi::V1_0::IfaceType::AP, &mode_id));
+    } else {
+        LOG(WARNING) << __func__ << ": Vendor HAL not supported";
+    }
 }
 
 // Helper function to deinitialize the driver and firmware
 // using the vendor HAL HIDL interface.
 void deInitilializeDriverAndFirmware(const std::string& wifi_instance_name) {
-    stopWifi(wifi_instance_name);
+    if (getWifi(wifi_instance_name) != nullptr) {
+        stopWifi(wifi_instance_name);
+    } else {
+        LOG(WARNING) << __func__ << ": Vendor HAL not supported";
+    }
 }
 }  // namespace
 
-// Utility class to wait for wpa_hostapd's HIDL service registration.
-class ServiceNotificationListener : public IServiceNotification {
-   public:
-    Return<void> onRegistration(const hidl_string& fully_qualified_name,
-                                const hidl_string& instance_name,
-                                bool pre_existing) override {
-        if (pre_existing) {
-            return Void();
-        }
-        std::unique_lock<std::mutex> lock(mutex_);
-        registered_.push_back(std::string(fully_qualified_name.c_str()) + "/" +
-                              instance_name.c_str());
-        lock.unlock();
-        condition_.notify_one();
-        return Void();
-    }
-
-    bool registerForHidlServiceNotifications(const std::string& instance_name) {
-        if (!IHostapd::registerForNotifications(instance_name, this)) {
-            return false;
-        }
-        configureRpcThreadpool(2, false);
-        return true;
-    }
-
-    bool waitForHidlService(uint32_t timeout_in_millis,
-                            const std::string& instance_name) {
-        std::unique_lock<std::mutex> lock(mutex_);
-        condition_.wait_for(lock, std::chrono::milliseconds(timeout_in_millis),
-                            [&]() { return registered_.size() >= 1; });
-        if (registered_.size() != 1) {
-            return false;
-        }
-        std::string expected_registered =
-            std::string(IHostapd::descriptor) + "/" + instance_name;
-        if (registered_[0] != expected_registered) {
-            LOG(ERROR) << "Expected: " << expected_registered
-                       << ", Got: " << registered_[0];
-            return false;
-        }
-        return true;
-    }
-
-   private:
-    std::vector<std::string> registered_{};
-    std::mutex mutex_;
-    std::condition_variable condition_;
-};
-
 void stopSupplicantIfNeeded(const std::string& instance_name) {
     SupplicantManager supplicant_manager;
     if (supplicant_manager.IsSupplicantRunning()) {
@@ -131,16 +88,11 @@
     const std::string& hostapd_instance_name) {
     initilializeDriverAndFirmware(wifi_instance_name);
 
-    android::sp<ServiceNotificationListener> notification_listener =
-        new ServiceNotificationListener();
-    ASSERT_TRUE(notification_listener->registerForHidlServiceNotifications(
-        hostapd_instance_name));
-
     HostapdManager hostapd_manager;
     ASSERT_TRUE(hostapd_manager.StartHostapd());
 
-    ASSERT_TRUE(
-        notification_listener->waitForHidlService(500, hostapd_instance_name));
+    // Wait for hostapd service to come up.
+    IHostapd::getService(hostapd_instance_name);
 }
 
 bool is_1_1(const sp<IHostapd>& hostapd) {
diff --git a/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp
index 2715891..a39f064 100644
--- a/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp
+++ b/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp
@@ -72,7 +72,7 @@
             "wifi_softap_wpa3_sae_supported");
     }
 
-    virtual void TearDown() override { stopHostapd(hostapd_instance_name_); }
+    virtual void TearDown() override { stopHostapd(wifi_instance_name_); }
 
    protected:
     bool isWpa3SaeSupport_ = false;
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test.cpp
index 4f25465..47f0394 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test.cpp
@@ -40,16 +40,22 @@
     virtual void SetUp() override {
         wifi_instance_name_ = std::get<0>(GetParam());
         supplicant_instance_name_ = std::get<1>(GetParam());
+        isP2pOn_ =
+            testing::deviceSupportsFeature("android.hardware.wifi.direct");
+        // Stop Framework
+        std::system("/system/bin/stop");
         stopSupplicant(wifi_instance_name_);
         startSupplicantAndWaitForHidlService(wifi_instance_name_,
                                              supplicant_instance_name_);
-        isP2pOn_ =
-            testing::deviceSupportsFeature("android.hardware.wifi.direct");
         supplicant_ = getSupplicant(supplicant_instance_name_, isP2pOn_);
         ASSERT_NE(supplicant_.get(), nullptr);
     }
 
-    virtual void TearDown() override { stopSupplicant(wifi_instance_name_); }
+    virtual void TearDown() override {
+        stopSupplicant(wifi_instance_name_);
+        // Start Framework
+        std::system("/system/bin/start");
+    }
 
    protected:
     // ISupplicant object used for all tests in this fixture.
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
index 3815323..5e7a371 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
@@ -18,7 +18,6 @@
 #include <cutils/properties.h>
 
 #include <android/hidl/manager/1.0/IServiceManager.h>
-#include <android/hidl/manager/1.0/IServiceNotification.h>
 #include <hidl/HidlTransportSupport.h>
 
 #include <wifi_system/interface_tool.h>
@@ -45,7 +44,6 @@
 using ::android::hardware::wifi::supplicant::V1_0::IfaceType;
 using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
 using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
-using ::android::hidl::manager::V1_0::IServiceNotification;
 using ::android::wifi_system::InterfaceTool;
 using ::android::wifi_system::SupplicantManager;
 
@@ -58,11 +56,14 @@
     if (wifi_instance_name == "") {
         return;
     }
-
-    sp<IWifiChip> wifi_chip = getWifiChip(wifi_instance_name);
-    ChipModeId mode_id;
-    EXPECT_TRUE(configureChipToSupportIfaceType(
-        wifi_chip, ::android::hardware::wifi::V1_0::IfaceType::STA, &mode_id));
+    if (getWifi(wifi_instance_name) != nullptr) {
+        sp<IWifiChip> wifi_chip = getWifiChip(wifi_instance_name);
+        ChipModeId mode_id;
+        EXPECT_TRUE(configureChipToSupportIfaceType(
+            wifi_chip, ::android::hardware::wifi::V1_0::IfaceType::STA, &mode_id));
+    } else {
+        LOG(WARNING) << __func__ << ": Vendor HAL not supported";
+    }
 }
 
 // Helper function to deinitialize the driver and firmware
@@ -72,8 +73,11 @@
     if (wifi_instance_name == "") {
         return;
     }
-
-    stopWifi(wifi_instance_name);
+    if (getWifi(wifi_instance_name) != nullptr) {
+        stopWifi(wifi_instance_name);
+    } else {
+        LOG(WARNING) << __func__ << ": Vendor HAL not supported";
+    }
 }
 
 // Helper function to find any iface of the desired type exposed.
@@ -114,55 +118,6 @@
 }
 }  // namespace
 
-// Utility class to wait for wpa_supplicant's HIDL service registration.
-class ServiceNotificationListener : public IServiceNotification {
-   public:
-    Return<void> onRegistration(const hidl_string& fully_qualified_name,
-                                const hidl_string& instance_name,
-                                bool pre_existing) override {
-        if (pre_existing) {
-            return Void();
-        }
-        std::unique_lock<std::mutex> lock(mutex_);
-        registered_.push_back(std::string(fully_qualified_name.c_str()) + "/" +
-                              instance_name.c_str());
-        lock.unlock();
-        condition_.notify_one();
-        return Void();
-    }
-
-    bool registerForHidlServiceNotifications(const std::string& instance_name) {
-        if (!ISupplicant::registerForNotifications(instance_name, this)) {
-            return false;
-        }
-        configureRpcThreadpool(2, false);
-        return true;
-    }
-
-    bool waitForHidlService(uint32_t timeout_in_millis,
-                            const std::string& instance_name) {
-        std::unique_lock<std::mutex> lock(mutex_);
-        condition_.wait_for(lock, std::chrono::milliseconds(timeout_in_millis),
-                            [&]() { return registered_.size() >= 1; });
-        if (registered_.size() != 1) {
-            return false;
-        }
-        std::string exptected_registered =
-            std::string(ISupplicant::descriptor) + "/" + instance_name;
-        if (registered_[0] != exptected_registered) {
-            LOG(ERROR) << "Expected: " << exptected_registered
-                       << ", Got: " << registered_[0];
-            return false;
-        }
-        return true;
-    }
-
-   private:
-    std::vector<std::string> registered_{};
-    std::mutex mutex_;
-    std::condition_variable condition_;
-};
-
 void stopSupplicant() { stopSupplicant(""); }
 
 void stopSupplicant(const std::string& wifi_instance_name) {
@@ -178,17 +133,12 @@
     const std::string& supplicant_instance_name) {
     initilializeDriverAndFirmware(wifi_instance_name);
 
-    android::sp<ServiceNotificationListener> notification_listener =
-        new ServiceNotificationListener();
-    ASSERT_TRUE(notification_listener->registerForHidlServiceNotifications(
-        supplicant_instance_name));
-
     SupplicantManager supplicant_manager;
     ASSERT_TRUE(supplicant_manager.StartSupplicant());
     ASSERT_TRUE(supplicant_manager.IsSupplicantRunning());
 
-    ASSERT_TRUE(notification_listener->waitForHidlService(
-        500, supplicant_instance_name));
+    // Wait for supplicant service to come up.
+    ISupplicant::getService(supplicant_instance_name);
 }
 
 bool is_1_1(const sp<ISupplicant>& supplicant) {
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp
index 8d6f38d..c333c4f 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp
@@ -77,11 +77,13 @@
     virtual void SetUp() override {
         wifi_instance_name_ = std::get<0>(GetParam());
         supplicant_instance_name_ = std::get<1>(GetParam());
+        isP2pOn_ =
+            testing::deviceSupportsFeature("android.hardware.wifi.direct");
+        // Stop Framework
+        std::system("/system/bin/stop");
         stopSupplicant(wifi_instance_name_);
         startSupplicantAndWaitForHidlService(wifi_instance_name_,
                                              supplicant_instance_name_);
-        isP2pOn_ =
-            testing::deviceSupportsFeature("android.hardware.wifi.direct");
         supplicant_ = getSupplicant(supplicant_instance_name_, isP2pOn_);
         EXPECT_TRUE(turnOnExcessiveLogging(supplicant_));
         p2p_iface_ = getSupplicantP2pIface(supplicant_);
@@ -91,7 +93,11 @@
         memcpy(peer_mac_addr_.data(), kTestPeerMacAddr, peer_mac_addr_.size());
     }
 
-    virtual void TearDown() override { stopSupplicant(wifi_instance_name_); }
+    virtual void TearDown() override {
+        stopSupplicant(wifi_instance_name_);
+        // Start Framework
+        std::system("/system/bin/start");
+    }
 
    protected:
     bool isP2pOn_ = false;
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp
index 089b3cd..ff28754 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp
@@ -72,11 +72,13 @@
     virtual void SetUp() override {
         wifi_instance_name_ = std::get<0>(GetParam());
         supplicant_instance_name_ = std::get<1>(GetParam());
+        isP2pOn_ =
+            testing::deviceSupportsFeature("android.hardware.wifi.direct");
+        // Stop Framework
+        std::system("/system/bin/stop");
         stopSupplicant(wifi_instance_name_);
         startSupplicantAndWaitForHidlService(wifi_instance_name_,
                                              supplicant_instance_name_);
-        isP2pOn_ =
-            testing::deviceSupportsFeature("android.hardware.wifi.direct");
         supplicant_ = getSupplicant(supplicant_instance_name_, isP2pOn_);
         EXPECT_TRUE(turnOnExcessiveLogging(supplicant_));
         sta_iface_ = getSupplicantStaIface(supplicant_);
@@ -85,7 +87,11 @@
         memcpy(mac_addr_.data(), kTestMacAddr, mac_addr_.size());
     }
 
-    virtual void TearDown() override { stopSupplicant(wifi_instance_name_); }
+    virtual void TearDown() override {
+        stopSupplicant(wifi_instance_name_);
+        // Start Framework
+        std::system("/system/bin/start");
+    }
 
    protected:
     bool isP2pOn_ = false;
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_sta_network_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_sta_network_hidl_test.cpp
index 5467e02..295ebfb 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_sta_network_hidl_test.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_sta_network_hidl_test.cpp
@@ -85,11 +85,13 @@
     virtual void SetUp() override {
         wifi_instance_name_ = std::get<0>(GetParam());
         supplicant_instance_name_ = std::get<1>(GetParam());
+        isP2pOn_ =
+            testing::deviceSupportsFeature("android.hardware.wifi.direct");
+        // Stop Framework
+        std::system("/system/bin/stop");
         stopSupplicant(wifi_instance_name_);
         startSupplicantAndWaitForHidlService(wifi_instance_name_,
                                              supplicant_instance_name_);
-        isP2pOn_ =
-            testing::deviceSupportsFeature("android.hardware.wifi.direct");
         supplicant_ = getSupplicant(supplicant_instance_name_, isP2pOn_);
         EXPECT_TRUE(turnOnExcessiveLogging(supplicant_));
         sta_network_ = createSupplicantStaNetwork(supplicant_);
@@ -103,7 +105,11 @@
         ssid_.assign(kTestSsidStr, kTestSsidStr + strlen(kTestSsidStr));
     }
 
-    virtual void TearDown() override { stopSupplicant(wifi_instance_name_); }
+    virtual void TearDown() override {
+        stopSupplicant(wifi_instance_name_);
+        // Start Framework
+        std::system("/system/bin/start");
+    }
 
    protected:
     void removeNetwork() {
diff --git a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.h b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.h
index 3629882..2104794 100644
--- a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.h
+++ b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.h
@@ -44,6 +44,8 @@
         supplicant_v1_1_instance_name_ = std::get<1>(GetParam());
         isP2pOn_ =
             testing::deviceSupportsFeature("android.hardware.wifi.direct");
+        // Stop Framework
+        std::system("/system/bin/stop");
         stopSupplicant(wifi_v1_0_instance_name_);
         startSupplicantAndWaitForHidlService(wifi_v1_0_instance_name_,
                                              supplicant_v1_1_instance_name_);
@@ -54,6 +56,8 @@
 
     virtual void TearDown() override {
         stopSupplicant(wifi_v1_0_instance_name_);
+        // Start Framework
+        std::system("/system/bin/start");
     }
 
    protected:
diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_hidl_test_utils_1_2.h b/wifi/supplicant/1.2/vts/functional/supplicant_hidl_test_utils_1_2.h
index 5ecfdd4..2a432d0 100644
--- a/wifi/supplicant/1.2/vts/functional/supplicant_hidl_test_utils_1_2.h
+++ b/wifi/supplicant/1.2/vts/functional/supplicant_hidl_test_utils_1_2.h
@@ -50,6 +50,8 @@
         supplicant_v1_2_instance_name_ = std::get<1>(GetParam());
         isP2pOn_ =
             testing::deviceSupportsFeature("android.hardware.wifi.direct");
+        // Stop Framework
+        std::system("/system/bin/stop");
         stopSupplicant(wifi_v1_0_instance_name_);
         startSupplicantAndWaitForHidlService(wifi_v1_0_instance_name_,
                                              supplicant_v1_2_instance_name_);
@@ -61,6 +63,8 @@
 
     virtual void TearDown() override {
         stopSupplicant(wifi_v1_0_instance_name_);
+        // Start Framework
+        std::system("/system/bin/start");
     }
 
    protected:
diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp b/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp
index 1eb8eea..cab160b 100644
--- a/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp
@@ -43,7 +43,7 @@
     virtual void SetUp() override {
         SupplicantHidlTestBase::SetUp();
         EXPECT_TRUE(turnOnExcessiveLogging(supplicant_));
-        if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct")) {
+        if (!isP2pOn_) {
             GTEST_SKIP() << "Wi-Fi Direct is not supported, skip this test.";
         }
         p2p_iface_ = getSupplicantP2pIface_1_2(supplicant_);
diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp
index f38dda4..7377f78 100644
--- a/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp
@@ -302,7 +302,8 @@
     }
 
     hidl_string uri =
-        "DPP:C:81/1;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
+        "DPP:C:81/1,117/"
+        "40;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
         "0DAQcDIgAD0edY4X3N//HhMFYsZfMbQJTiNFtNIWF/cIwMB/gzqOM=;;";
     uint32_t peer_id = 0;
 
@@ -347,7 +348,8 @@
     }
 
     hidl_string uri =
-        "DPP:C:81/1;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
+        "DPP:C:81/1,117/"
+        "40;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
         "0DAQcDIgAD0edY4X3N//HhMFYsZfMbQJTiNFtNIWF/cIwMB/gzqOM=;;";
     uint32_t peer_id = 0;
 
@@ -413,7 +415,8 @@
     }
 
     hidl_string uri =
-        "DPP:C:81/1;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
+        "DPP:C:81/1,117/"
+        "40;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
         "0DAQcDIgAD0edY4X3N//HhMFYsZfMbQJTiNFtNIWF/cIwMB/gzqOM=;;";
     uint32_t peer_id = 0;
 
diff --git a/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp
index 4020298..011a955 100644
--- a/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp
@@ -63,6 +63,8 @@
         supplicant_v1_3_instance_name_ = std::get<1>(GetParam());
         isP2pOn_ =
             testing::deviceSupportsFeature("android.hardware.wifi.direct");
+        // Stop Framework
+        std::system("/system/bin/stop");
 
         stopSupplicant(wifi_v1_0_instance_name_);
         startSupplicantAndWaitForHidlService(wifi_v1_0_instance_name_,
@@ -76,6 +78,8 @@
 
     virtual void TearDown() override {
         stopSupplicant(wifi_v1_0_instance_name_);
+        // Start Framework
+        std::system("/system/bin/start");
     }
 
     int64_t pmkCacheExpirationTimeInSec;
@@ -419,7 +423,8 @@
     }
 
     hidl_string uri =
-        "DPP:C:81/1;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
+        "DPP:C:81/1,117/"
+        "40;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
         "0DAQcDIgAD0edY4X3N//HhMFYsZfMbQJTiNFtNIWF/cIwMB/gzqOM=;;";
     uint32_t peer_id = 0;
 
@@ -470,7 +475,8 @@
     }
 
     hidl_string uri =
-        "DPP:C:81/1;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
+        "DPP:C:81/1,117/"
+        "40;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
         "0DAQcDIgAD0edY4X3N//HhMFYsZfMbQJTiNFtNIWF/cIwMB/gzqOM=;;";
     uint32_t peer_id = 0;
 
diff --git a/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp b/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp
index 25091a5..5f60746 100644
--- a/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp
+++ b/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp
@@ -51,6 +51,8 @@
         supplicant_v1_3_instance_name_ = std::get<1>(GetParam());
         isP2pOn_ =
             testing::deviceSupportsFeature("android.hardware.wifi.direct");
+        // Stop Framework
+        std::system("/system/bin/stop");
 
         stopSupplicant(wifi_v1_0_instance_name_);
         startSupplicantAndWaitForHidlService(wifi_v1_0_instance_name_,
@@ -66,6 +68,8 @@
 
     virtual void TearDown() override {
         stopSupplicant(wifi_v1_0_instance_name_);
+        // Start Framework
+        std::system("/system/bin/start");
     }
 
    protected: