Merge "wifi: Update wifi_wait_for_driver_ready return status handling" into rvc-qpr-dev
diff --git a/audio/4.0/Android.bp b/audio/4.0/Android.bp
index 862c711..bc695c8 100644
--- a/audio/4.0/Android.bp
+++ b/audio/4.0/Android.bp
@@ -3,6 +3,8 @@
 hidl_interface {
     name: "android.hardware.audio@4.0",
     root: "android.hardware",
+    // TODO(b/153609531): remove when no longer needed.
+    native_bridge_supported: true,
     vndk: {
         enabled: true,
     },
diff --git a/audio/common/2.0/Android.bp b/audio/common/2.0/Android.bp
index bd3b069..56b43ff 100644
--- a/audio/common/2.0/Android.bp
+++ b/audio/common/2.0/Android.bp
@@ -3,6 +3,8 @@
 hidl_interface {
     name: "android.hardware.audio.common@2.0",
     root: "android.hardware",
+    // TODO(b/153609531): remove when no longer needed.
+    native_bridge_supported: true,
     vndk: {
         enabled: true,
     },
diff --git a/audio/common/4.0/Android.bp b/audio/common/4.0/Android.bp
index c01c486..e4676ec 100644
--- a/audio/common/4.0/Android.bp
+++ b/audio/common/4.0/Android.bp
@@ -3,6 +3,8 @@
 hidl_interface {
     name: "android.hardware.audio.common@4.0",
     root: "android.hardware",
+    // TODO(b/153609531): remove when no longer needed.
+    native_bridge_supported: true,
     vndk: {
         enabled: true,
     },
diff --git a/audio/effect/2.0/Android.bp b/audio/effect/2.0/Android.bp
index d4482c2..7b37260 100644
--- a/audio/effect/2.0/Android.bp
+++ b/audio/effect/2.0/Android.bp
@@ -3,6 +3,8 @@
 hidl_interface {
     name: "android.hardware.audio.effect@2.0",
     root: "android.hardware",
+    // TODO(b/153609531): remove when no longer needed.
+    native_bridge_supported: true,
     vndk: {
         enabled: true,
     },
diff --git a/audio/effect/4.0/Android.bp b/audio/effect/4.0/Android.bp
index 8c1900f..2242d6d 100644
--- a/audio/effect/4.0/Android.bp
+++ b/audio/effect/4.0/Android.bp
@@ -3,6 +3,8 @@
 hidl_interface {
     name: "android.hardware.audio.effect@4.0",
     root: "android.hardware",
+    // TODO(b/153609531): remove when no longer needed.
+    native_bridge_supported: true,
     vndk: {
         enabled: true,
     },
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 b8a606a..16c33b9 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
@@ -1039,6 +1039,22 @@
         {
                 .config =
                         {
+                                .prop = toInt(VehicleProperty::CREATE_USER),
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::REMOVE_USER),
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
                                 .prop = toInt(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION),
                                 .access = VehiclePropertyAccess::READ_WRITE,
                                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
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 6a6b12f..d0011a8 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
@@ -30,11 +30,18 @@
 
 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);
 
 bool EmulatedUserHal::isSupported(int32_t prop) {
     switch (prop) {
         case INITIAL_USER_INFO:
         case SWITCH_USER:
+        case CREATE_USER:
+        case REMOVE_USER:
+        case USER_IDENTIFICATION_ASSOCIATION:
             return true;
         default:
             return false;
@@ -50,12 +57,58 @@
             return onSetInitialUserInfoResponse(value);
         case SWITCH_USER:
             return onSetSwitchUserResponse(value);
+        case CREATE_USER:
+            return onSetCreateUserResponse(value);
+        case REMOVE_USER:
+            ALOGI("REMOVE_USER is FYI only, nothing to do...");
+            return {};
+        case USER_IDENTIFICATION_ASSOCIATION:
+            return onSetUserIdentificationAssociation(value);
         default:
             return android::base::Error(static_cast<int>(StatusCode::INVALID_ARG))
                    << "Unsupported property: " << toString(value);
     }
 }
 
+android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onGetProperty(
+        const VehiclePropValue& value) {
+    ALOGV("onGetProperty(%s)", toString(value).c_str());
+    switch (value.prop) {
+        case INITIAL_USER_INFO:
+        case SWITCH_USER:
+        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";
+        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";
+    }
+}
+
+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));
+        // 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;
+    }
+    return defaultUserIdentificationAssociation(value);
+}
+
 android::base::Result<std::unique_ptr<VehiclePropValue>>
 EmulatedUserHal::onSetInitialUserInfoResponse(const VehiclePropValue& value) {
     if (value.value.int32Values.size() == 0) {
@@ -102,6 +155,15 @@
     }
 
     if (value.areaId != 0) {
+        if (value.value.int32Values.size() >= 2 &&
+            static_cast<SwitchUserMessageType>(value.value.int32Values[1]) ==
+                    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 {};
@@ -144,6 +206,79 @@
     return updatedValue;
 }
 
+android::base::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);
+    }
+
+    if (value.areaId != 0) {
+        ALOGD("set(CREATE_USER) called from lshal; storing it: %s", toString(value).c_str());
+        mCreateUserResponseFromCmd.reset(new VehiclePropValue(value));
+        return {};
+    }
+    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);
+    }
+
+    // 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;
+
+    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);
+    }
+
+    if (value.areaId != 0) {
+        ALOGD("set(USER_IDENTIFICATION_ASSOCIATION) called from lshal; storing it: %s",
+              toString(value).c_str());
+        mSetUserIdentificationAssociationResponseFromCmd.reset(new VehiclePropValue(value));
+        return {};
+    }
+    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);
+    }
+
+    // Returns default response
+    return defaultUserIdentificationAssociation(value);
+}
+
+android::base::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";
+}
+
 android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::sendUserHalResponse(
         std::unique_ptr<VehiclePropValue> response, int32_t requestId) {
     switch (response->areaId) {
@@ -189,6 +324,18 @@
     } else {
         dprintf(fd, "%sNo SwitchUser response\n", indent.c_str());
     }
+    if (mCreateUserResponseFromCmd != nullptr) {
+        dprintf(fd, "%sCreateUser response: %s\n", indent.c_str(),
+                toString(*mCreateUserResponseFromCmd).c_str());
+    } else {
+        dprintf(fd, "%sNo CreateUser response\n", indent.c_str());
+    }
+    if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) {
+        dprintf(fd, "%sSetUserIdentificationAssociation response: %s\n", indent.c_str(),
+                toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str());
+    } else {
+        dprintf(fd, "%sNo SetUserIdentificationAssociation response\n", indent.c_str());
+    }
 }
 
 }  // namespace impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h
index b25efcb..db2f117 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h
@@ -46,7 +46,7 @@
     bool isSupported(int32_t prop);
 
     /**
-     * Lets the emulator handle the property.
+     * Lets the emulator set the property.
      *
      * @return updated property and StatusCode
      */
@@ -54,6 +54,14 @@
             const VehiclePropValue& value);
 
     /**
+     * Gets the property value from the emulator.
+     *
+     * @return property value and StatusCode
+     */
+    android::base::Result<std::unique_ptr<VehiclePropValue>> onGetProperty(
+            const VehiclePropValue& value);
+
+    /**
      * Shows the User HAL emulation help.
      */
     void showDumpHelp(int fd);
@@ -97,11 +105,39 @@
     android::base::Result<std::unique_ptr<VehiclePropValue>> onSetSwitchUserResponse(
             const VehiclePropValue& value);
 
+    /**
+     * Used to emulate CREATE_USER - see onSetInitialUserInfoResponse() for usage.
+     */
+    android::base::Result<std::unique_ptr<VehiclePropValue>> onSetCreateUserResponse(
+            const VehiclePropValue& value);
+
+    /**
+     * Used to emulate set USER_IDENTIFICATION_ASSOCIATION - see onSetInitialUserInfoResponse() for
+     * usage.
+     */
+    android::base::Result<std::unique_ptr<VehiclePropValue>> onSetUserIdentificationAssociation(
+            const VehiclePropValue& value);
+
+    /**
+     * Used to emulate get USER_IDENTIFICATION_ASSOCIATION - see onSetInitialUserInfoResponse() for
+     * usage.
+     */
+    android::base::Result<std::unique_ptr<VehiclePropValue>> onGetUserIdentificationAssociation(
+            const VehiclePropValue& value);
+
+    /**
+     * Creates a default USER_IDENTIFICATION_ASSOCIATION when it was not set by lshal.
+     */
+    android::base::Result<std::unique_ptr<VehiclePropValue>> defaultUserIdentificationAssociation(
+            const VehiclePropValue& request);
+
     android::base::Result<std::unique_ptr<VehiclePropValue>> sendUserHalResponse(
             std::unique_ptr<VehiclePropValue> response, int32_t requestId);
 
     std::unique_ptr<VehiclePropValue> mInitialUserResponseFromCmd;
     std::unique_ptr<VehiclePropValue> mSwitchUserResponseFromCmd;
+    std::unique_ptr<VehiclePropValue> mCreateUserResponseFromCmd;
+    std::unique_ptr<VehiclePropValue> mSetUserIdentificationAssociationResponseFromCmd;
 };
 
 }  // 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 a08d8e7..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
@@ -87,12 +87,14 @@
     return sensorStore;
 }
 
-EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client)
+EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client,
+                                       EmulatedUserHal* emulatedUserHal)
     : mPropStore(propStore),
       mHvacPowerProps(std::begin(kHvacPowerProperties), std::end(kHvacPowerProperties)),
       mRecurrentTimer(std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer, this,
                                 std::placeholders::_1)),
-      mVehicleClient(client) {
+      mVehicleClient(client),
+      mEmulatedUserHal(emulatedUserHal) {
     initStaticConfig();
     for (size_t i = 0; i < arraysize(kVehicleProperties); i++) {
         mPropStore->registerProperty(kVehicleProperties[i].config);
@@ -105,6 +107,8 @@
 VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
         const VehiclePropValue& requestedPropValue, StatusCode* outStatus) {
     auto propId = requestedPropValue.prop;
+    ALOGV("get(%d)", propId);
+
     auto& pool = *getValuePool();
     VehiclePropValuePtr v = nullptr;
 
@@ -118,6 +122,26 @@
             *outStatus = fillObd2DtcInfo(v.get());
             break;
         default:
+            if (mEmulatedUserHal != nullptr && mEmulatedUserHal->isSupported(propId)) {
+                ALOGI("get(): getting value for prop %d from User HAL", propId);
+                const auto& ret = mEmulatedUserHal->onGetProperty(requestedPropValue);
+                if (!ret.ok()) {
+                    ALOGE("get(): User HAL returned error: %s", ret.error().message().c_str());
+                    *outStatus = StatusCode(ret.error().code());
+                } else {
+                    auto value = ret.value().get();
+                    if (value != nullptr) {
+                        ALOGI("get(): User HAL returned value: %s", toString(*value).c_str());
+                        v = getValuePool()->obtain(*value);
+                        *outStatus = StatusCode::OK;
+                    } else {
+                        ALOGE("get(): User HAL returned null value");
+                        *outStatus = StatusCode::INTERNAL_ERROR;
+                    }
+                }
+                break;
+            }
+
             auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue);
             if (internalPropValue != nullptr) {
                 v = getValuePool()->obtain(*internalPropValue);
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 ebf1995..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
@@ -30,6 +30,7 @@
 #include "vhal_v2_0/VehiclePropertyStore.h"
 
 #include "DefaultConfig.h"
+#include "EmulatedUserHal.h"
 #include "EmulatedVehicleConnector.h"
 #include "GeneratorHub.h"
 #include "VehicleEmulator.h"
@@ -45,8 +46,8 @@
 /** Implementation of VehicleHal that connected to emulator instead of real vehicle network. */
 class EmulatedVehicleHal : public EmulatedVehicleHalIface {
 public:
-    EmulatedVehicleHal(VehiclePropertyStore* propStore,
-                       VehicleHalClient* client);
+    EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client,
+                       EmulatedUserHal* emulatedUserHal = nullptr);
     ~EmulatedVehicleHal() = default;
 
     //  Methods from VehicleHal
@@ -86,6 +87,7 @@
     std::unordered_set<int32_t> mHvacPowerProps;
     RecurrentTimer mRecurrentTimer;
     VehicleHalClient* mVehicleClient;
+    EmulatedUserHal* mEmulatedUserHal;
 };
 
 }  // impl
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 ad5096e..36f2534 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,6 +41,10 @@
     return mValuePool;
 }
 
+EmulatedUserHal* VehicleHalServer::getEmulatedUserHal() {
+    return &mEmulatedUserHal;
+}
+
 void VehicleHalServer::setValuePool(VehiclePropValuePool* valuePool) {
     if (!valuePool) {
         LOG(WARNING) << __func__ << ": Setting value pool to nullptr!";
@@ -197,6 +201,7 @@
         }
         return StatusCode::OK;
     }
+    LOG(DEBUG) << "onSetProperty(" << value.prop << ")";
 
     // Some properties need to be treated non-trivially
     switch (value.prop) {
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 2841fbe..fca78bc 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
@@ -38,6 +38,8 @@
     // Set the Property Value Pool used in this server
     void setValuePool(VehiclePropValuePool* valuePool);
 
+    EmulatedUserHal* getEmulatedUserHal();
+
   private:
     using VehiclePropValuePtr = recyclable_ptr<VehiclePropValue>;
 
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..33b3948
--- /dev/null
+++ b/automotive/vehicle/2.0/utils/UserHalHelper.cpp
@@ -0,0 +1,366 @@
+/*
+ * 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;
+
+template <typename T>
+Result<T> verifyAndCast(int32_t value) {
+    T castValue = static_cast<T>(value);
+    const auto iter = hidl_enum_range<T>();
+    if (castValue < *iter.begin() || castValue > *std::prev(iter.end())) {
+        return Error() << "Value " << value << " not in range [" << toString(*iter.begin()) << ", "
+                       << toString(*std::prev(iter.end())) << "]";
+    }
+    for (const auto& v : hidl_enum_range<T>()) {
+        if (castValue == v) {
+            return castValue;
+        }
+    }
+    return Error() << "Value " << value << " not in enum values";
+}
+
+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
+
+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) << " 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..bee34cf
--- /dev/null
+++ b/automotive/vehicle/2.0/utils/UserHalHelper.h
@@ -0,0 +1,62 @@
+/*
+ * 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 {
+
+// 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/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/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index f235235..b0aae8e 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -4453,9 +4453,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,
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..a3d2956 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) {
@@ -673,4 +675,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/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
index 00df7c7..f0de4f7 100644
--- a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
+++ b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
@@ -201,8 +201,12 @@
 
     void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
 
-    void Test_setActiveConfigWithConstraints(
-            const IComposerClient::VsyncPeriodChangeConstraints& constraints, bool refreshMiss);
+    struct TestParameters {
+        nsecs_t delayForChange;
+        bool refreshMiss;
+    };
+
+    void Test_setActiveConfigWithConstraints(const TestParameters& params);
 
     void sendRefreshFrame(const VsyncPeriodChangeTimeline*);
 
@@ -453,9 +457,7 @@
 }
 
 void GraphicsComposerHidlCommandTest::Test_setActiveConfigWithConstraints(
-        const IComposerClient::VsyncPeriodChangeConstraints& constraints, bool refreshMiss) {
-    VsyncPeriodChangeTimeline timeline = {};
-
+        const TestParameters& params) {
     for (Display display : mComposerCallback->getDisplays()) {
         forEachTwoConfigs(display, [&](Config config1, Config config2) {
             mComposerClient->setActiveConfig(display, config1);
@@ -470,6 +472,10 @@
                 return;  // continue
             }
 
+            VsyncPeriodChangeTimeline timeline;
+            IComposerClient::VsyncPeriodChangeConstraints constraints = {
+                    .desiredTimeNanos = systemTime() + params.delayForChange,
+                    .seamlessRequired = false};
             EXPECT_EQ(Error::NONE, mComposerClient->setActiveConfigWithConstraints(
                                            display, config2, constraints, &timeline));
 
@@ -480,7 +486,7 @@
                         kReasonableTimeForChange.count());
 
             if (timeline.refreshRequired) {
-                if (refreshMiss) {
+                if (params.refreshMiss) {
                     // Miss the refresh frame on purpose to make sure the implementation sends a
                     // callback
                     std::this_thread::sleep_until(toTimePoint(timeline.refreshTimeNanos) + 100ms);
@@ -493,16 +499,16 @@
             // At this point the refresh rate should have changed already, however in rare
             // cases the implementation might have missed the deadline. In this case a new
             // timeline should have been provided.
-            auto newTimelime = mComposerCallback->takeLastVsyncPeriodChangeTimeline();
-            if (timeline.refreshRequired && refreshMiss) {
-                EXPECT_TRUE(newTimelime.has_value());
+            auto newTimeline = mComposerCallback->takeLastVsyncPeriodChangeTimeline();
+            if (timeline.refreshRequired && params.refreshMiss) {
+                EXPECT_TRUE(newTimeline.has_value());
             }
 
-            if (newTimelime.has_value()) {
-                if (timeline.refreshRequired) {
-                    sendRefreshFrame(&newTimelime.value());
+            if (newTimeline.has_value()) {
+                if (newTimeline->refreshRequired) {
+                    sendRefreshFrame(&newTimeline.value());
                 }
-                waitForVsyncPeriodChange(display, newTimelime.value(), constraints.desiredTimeNanos,
+                waitForVsyncPeriodChange(display, newTimeline.value(), constraints.desiredTimeNanos,
                                          vsyncPeriod1, vsyncPeriod2);
             }
 
@@ -515,28 +521,16 @@
 }
 
 TEST_P(GraphicsComposerHidlCommandTest, setActiveConfigWithConstraints) {
-    IComposerClient::VsyncPeriodChangeConstraints constraints;
-
-    constraints.seamlessRequired = false;
-    constraints.desiredTimeNanos = systemTime();
-    Test_setActiveConfigWithConstraints(constraints, false);
+    Test_setActiveConfigWithConstraints({.delayForChange = 0, .refreshMiss = false});
 }
 
 TEST_P(GraphicsComposerHidlCommandTest, setActiveConfigWithConstraints_Delayed) {
-    IComposerClient::VsyncPeriodChangeConstraints constraints;
-
-    constexpr nsecs_t kDelayForChange = 300'000'000;  // 300ms
-    constraints.seamlessRequired = false;
-    constraints.desiredTimeNanos = systemTime() + kDelayForChange;
-    Test_setActiveConfigWithConstraints(constraints, false);
+    Test_setActiveConfigWithConstraints({.delayForChange = 300'000'000,  // 300ms
+                                         .refreshMiss = false});
 }
 
 TEST_P(GraphicsComposerHidlCommandTest, setActiveConfigWithConstraints_MissRefresh) {
-    IComposerClient::VsyncPeriodChangeConstraints constraints;
-
-    constraints.seamlessRequired = false;
-    constraints.desiredTimeNanos = systemTime();
-    Test_setActiveConfigWithConstraints(constraints, true);
+    Test_setActiveConfigWithConstraints({.delayForChange = 0, .refreshMiss = true});
 }
 
 TEST_P(GraphicsComposerHidlTest, setAutoLowLatencyModeBadDisplay) {
diff --git a/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp b/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
index 1577293..e347654 100644
--- a/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
+++ b/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
@@ -386,7 +386,7 @@
 
     vector<RequestNamespace> requestedNamespaces = test_utils::buildRequestNamespaces(testEntries);
     // OK to fail, not available in v1 HAL
-    credential->setRequestedNamespaces(requestedNamespaces).isOk();
+    credential->setRequestedNamespaces(requestedNamespaces);
     // OK to fail, not available in v1 HAL
     credential->setVerificationToken(verificationToken);
     ASSERT_TRUE(credential
@@ -446,7 +446,6 @@
     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());
@@ -469,6 +468,58 @@
                               deviceAuthenticationBytes);  // detached content
     ASSERT_TRUE(calculatedMac);
     EXPECT_EQ(mac, calculatedMac);
+
+    // Also perform an additional empty request. This is what mDL applications
+    // are envisioned to do - one call to get the data elements, another to get
+    // an empty DeviceSignedItems and corresponding MAC.
+    //
+    credential->setRequestedNamespaces({});  // OK to fail, not available in v1 HAL
+    ASSERT_TRUE(credential
+                        ->startRetrieval(
+                                secureProfiles.value(), authToken, {},         // itemsRequestBytes
+                                signingKeyBlob, sessionTranscriptEncoded, {},  // readerSignature,
+                                testEntriesEntryCounts)
+                        .isOk());
+    ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesBytes).isOk());
+    cborPretty = support::cborPrettyPrint(deviceNameSpacesBytes, 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
+    ASSERT_TRUE(calculatedMac);
+    EXPECT_EQ(mac, calculatedMac);
+
+    // Some mDL apps might send a request but with a single empty
+    // namespace. Check that too.
+    RequestNamespace emptyRequestNS;
+    emptyRequestNS.namespaceName = "PersonalData";
+    credential->setRequestedNamespaces({emptyRequestNS});  // OK to fail, not available in v1 HAL
+    ASSERT_TRUE(credential
+                        ->startRetrieval(
+                                secureProfiles.value(), authToken, {},         // itemsRequestBytes
+                                signingKeyBlob, sessionTranscriptEncoded, {},  // readerSignature,
+                                testEntriesEntryCounts)
+                        .isOk());
+    ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesBytes).isOk());
+    cborPretty = support::cborPrettyPrint(deviceNameSpacesBytes, 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
+    ASSERT_TRUE(calculatedMac);
+    EXPECT_EQ(mac, calculatedMac);
 }
 
 INSTANTIATE_TEST_SUITE_P(
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/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/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp b/media/omx/1.0/vts/functional/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp
index 4e25313..68ee900 100644
--- a/media/omx/1.0/vts/functional/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp
+++ b/media/omx/1.0/vts/functional/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp
@@ -251,7 +251,7 @@
     };
 
     // Matching rules for node names and owners
-    const testing::internal::RE nodeNamePattern = "[a-zA-Z0-9.-]+";
+    const testing::internal::RE nodeNamePattern = "[a-zA-Z0-9._-]+";
     const testing::internal::RE nodeOwnerPattern = "[a-zA-Z0-9._-]+";
 
     std::set<const std::string> roleKeys;
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/renderscript/1.0/Android.bp b/renderscript/1.0/Android.bp
index feae9f7..d3b5abe 100644
--- a/renderscript/1.0/Android.bp
+++ b/renderscript/1.0/Android.bp
@@ -3,6 +3,8 @@
 hidl_interface {
     name: "android.hardware.renderscript@1.0",
     root: "android.hardware",
+    // TODO(b/153609531): remove when no longer needed.
+    native_bridge_supported: true,
     vndk: {
         enabled: true,
         support_system_process: true,
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/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.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/wifi_chip.cpp b/wifi/1.4/default/wifi_chip.cpp
index 8747e61..8cba464 100644
--- a/wifi/1.4/default/wifi_chip.cpp
+++ b/wifi/1.4/default/wifi_chip.cpp
@@ -624,6 +624,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";
@@ -1120,6 +1129,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 +1347,7 @@
                     LOG(ERROR) << "Ringname " << name << " not found";
                     return;
                 }
-                // unlock
+                // unique_lock unlocked here
             }
         };
     legacy_hal::wifi_error legacy_status =
@@ -1637,7 +1649,7 @@
                 }
             }
         }
-        // unlock
+        // unique_lock unlocked here
     }
     return true;
 }
diff --git a/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp b/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp
index 9d84223..a099c8a 100644
--- a/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp
+++ b/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp
@@ -225,8 +225,8 @@
     int cmdId = 55;
     WifiChannelInfo channelInfo;
     channelInfo.width = WifiChannelWidthInMhz::WIDTH_80;
-    channelInfo.centerFreq = 5690;
-    channelInfo.centerFreq0 = 5690;
+    channelInfo.centerFreq = 5660;
+    channelInfo.centerFreq0 = 5660;
     channelInfo.centerFreq1 = 0;
 
     // Get the responder first
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/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.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..12bd122 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
@@ -419,7 +419,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 +471,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;