Merge changes Ifd7ec3dc,Ia28c9217

* changes:
  audio: Clarify documentation for some methods
  audio: Provide documentation for enums in 'common' package
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 0e18f48..543acf6 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -7,7 +7,7 @@
       "name": "vts_treble_vintf_vendor_test"
     },
     {
-      "name": "hidl_implementation_test"
+      "name": "hal_implementation_test"
     }
   ]
 }
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index a94a37e..e325889 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -47,6 +47,9 @@
         "common/src/VehicleUtils.cpp",
         "common/src/VmsUtils.cpp",
     ],
+    shared_libs: [
+        "libbase",
+    ],
     local_include_dirs: ["common/include/vhal_v2_0"],
     export_include_dirs: ["common/include"],
 }
@@ -109,6 +112,9 @@
         "tests/VehiclePropConfigIndex_test.cpp",
         "tests/VmsUtils_test.cpp",
     ],
+    shared_libs: [
+        "libbase",
+    ],
     header_libs: ["libbase_headers"],
     test_suites: ["general-tests"],
 }
@@ -173,7 +179,7 @@
         "libqemu_pipe",
     ],
     cflags: [
-        "-Wno-unused-parameter"
+        "-Wno-unused-parameter",
     ],
 }
 
@@ -200,6 +206,6 @@
         "android.hardware.automotive.vehicle@2.0-virtualization-utils",
     ],
     cflags: [
-        "-Wno-unused-parameter"
+        "-Wno-unused-parameter",
     ],
 }
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h
index c1e9e88..fcfe761 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h
@@ -73,7 +73,9 @@
                                    int32_t propId)  override;
     Return<void> debugDump(debugDump_cb _hidl_cb = nullptr) override;
 
-private:
+    Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
+
+  private:
     using VehiclePropValuePtr = VehicleHal::VehiclePropValuePtr;
     // Returns true if needs to call again shortly.
     using RetriableAction = std::function<bool()>;
@@ -96,6 +98,22 @@
     bool checkReadPermission(const VehiclePropConfig &config) const;
     void onAllClientsUnsubscribed(int32_t propertyId);
 
+    // Dump and commands
+    // TODO: most functions below (exception dump() and cmdSetOne()) should be const, but they rely
+    // on IVehicle.get(), which isn't...
+    void cmdDump(int fd, const hidl_vec<hidl_string>& options);
+    void cmdDumpOneProperty(int fd, int32_t prop, int32_t areaId);
+    void cmdDumpOneProperty(int fd, int rowNumber, const VehiclePropConfig& config);
+
+    static bool checkArgumentsSize(int fd, const hidl_vec<hidl_string>& options, size_t minSize);
+    static bool checkCallerHasWritePermissions(int fd);
+    static bool safelyParseInt(int fd, int index, std::string s, int* out);
+    void cmdHelp(int fd) const;
+    void cmdListAllProperties(int fd) const;
+    void cmdDumpAllProperties(int fd);
+    void cmdDumpSpecificProperties(int fd, const hidl_vec<hidl_string>& options);
+    void cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options);
+
     static bool isSubscribable(const VehiclePropConfig& config,
                                SubscribeFlags flags);
     static bool isSampleRateFixed(VehiclePropertyChangeMode mode);
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
index 393d3ec..4249a61 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
@@ -21,11 +21,18 @@
 #include <cmath>
 #include <fstream>
 
-#include <android/log.h>
+#include <android-base/parseint.h>
+#include <android-base/strings.h>
 #include <android/hardware/automotive/vehicle/2.0/BpHwVehicleCallback.h>
+#include <android/log.h>
+
+#include <hwbinder/IPCThreadState.h>
 
 #include "VehicleUtils.h"
 
+// TODO: figure out how to include private/android_filesystem_config.h instead...
+#define AID_ROOT 0 /* traditional unix root user */
+
 namespace android {
 namespace hardware {
 namespace automotive {
@@ -34,6 +41,10 @@
 
 using namespace std::placeholders;
 
+using ::android::base::EqualsIgnoreCase;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_string;
+
 constexpr std::chrono::milliseconds kHalEventBatchingTimeWindow(10);
 
 const VehiclePropValue kEmptyValue{};
@@ -172,6 +183,231 @@
     return Void();
 }
 
+Return<void> VehicleHalManager::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
+    if (fd.getNativeHandle() != nullptr && fd->numFds > 0) {
+        cmdDump(fd->data[0], options);
+    } else {
+        ALOGE("Invalid parameters passed to debug()");
+    }
+    return Void();
+}
+
+void VehicleHalManager::cmdDump(int fd, const hidl_vec<hidl_string>& options) {
+    if (options.size() == 0) {
+        cmdDumpAllProperties(fd);
+        return;
+    }
+    std::string option = options[0];
+    if (EqualsIgnoreCase(option, "--help")) {
+        cmdHelp(fd);
+    } else if (EqualsIgnoreCase(option, "--list")) {
+        cmdListAllProperties(fd);
+    } else if (EqualsIgnoreCase(option, "--get")) {
+        cmdDumpSpecificProperties(fd, options);
+    } else if (EqualsIgnoreCase(option, "--set")) {
+        cmdSetOneProperty(fd, options);
+    } else {
+        dprintf(fd, "Invalid option: %s\n", option.c_str());
+    }
+}
+
+bool VehicleHalManager::checkCallerHasWritePermissions(int fd) {
+    // Double check that's only called by root - it should be be blocked at the HIDL debug() level,
+    // but it doesn't hurt to make sure...
+    if (hardware::IPCThreadState::self()->getCallingUid() != AID_ROOT) {
+        dprintf(fd, "Must be root\n");
+        return false;
+    }
+    return true;
+}
+
+bool VehicleHalManager::checkArgumentsSize(int fd, const hidl_vec<hidl_string>& options,
+                                           size_t minSize) {
+    size_t size = options.size();
+    if (size >= minSize) {
+        return true;
+    }
+    dprintf(fd, "Invalid number of arguments: required at least %zu, got %zu\n", minSize, size);
+    return false;
+}
+
+bool VehicleHalManager::safelyParseInt(int fd, int index, std::string s, int* out) {
+    if (!android::base::ParseInt(s, out)) {
+        dprintf(fd, "non-integer argument at index %d: %s\n", index, s.c_str());
+        return false;
+    }
+    return true;
+}
+
+void VehicleHalManager::cmdHelp(int fd) const {
+    dprintf(fd, "Usage: \n\n");
+    dprintf(fd, "[no args]: dumps (id and value) all supported properties \n");
+    dprintf(fd, "--help: shows this help\n");
+    dprintf(fd, "--list: lists the ids of all supported properties\n");
+    dprintf(fd, "--get <PROP1> [PROP2] [PROPN]: dumps the value of specific properties \n");
+    // TODO: support other formats (int64, float, bytes)
+    dprintf(fd,
+            "--set <PROP> <i|s> <VALUE_1> [<i|s> <VALUE_N>]: sets the value of property PROP, using"
+            " arbitrary number of key/value parameters (i for int32, s for string). Notice that "
+            "the string value can be set just once, while the other can have multiple values "
+            "(so they're used in the respective array)\n");
+}
+
+void VehicleHalManager::cmdListAllProperties(int fd) const {
+    auto& halConfig = mConfigIndex->getAllConfigs();
+    size_t size = halConfig.size();
+    if (size == 0) {
+        dprintf(fd, "no properties to list\n");
+        return;
+    }
+    int i = 0;
+    dprintf(fd, "listing %zu properties\n", size);
+    for (const auto& config : halConfig) {
+        dprintf(fd, "%d: %d\n", ++i, config.prop);
+    }
+}
+
+void VehicleHalManager::cmdDumpAllProperties(int fd) {
+    auto& halConfig = mConfigIndex->getAllConfigs();
+    size_t size = halConfig.size();
+    if (size == 0) {
+        dprintf(fd, "no properties to dump\n");
+        return;
+    }
+    int rowNumber = 0;
+    dprintf(fd, "dumping %zu properties\n", size);
+    for (auto& config : halConfig) {
+        cmdDumpOneProperty(fd, ++rowNumber, config);
+    }
+}
+
+void VehicleHalManager::cmdDumpOneProperty(int fd, int rowNumber, const VehiclePropConfig& config) {
+    size_t numberAreas = config.areaConfigs.size();
+    if (numberAreas == 0) {
+        if (rowNumber > 0) {
+            dprintf(fd, "%d: ", rowNumber);
+        }
+        cmdDumpOneProperty(fd, config.prop, /* areaId= */ 0);
+        return;
+    }
+    for (size_t j = 0; j < numberAreas; ++j) {
+        if (rowNumber > 0) {
+            if (numberAreas > 1) {
+                dprintf(fd, "%d/%zu: ", rowNumber, j);
+            } else {
+                dprintf(fd, "%d: ", rowNumber);
+            }
+        }
+        cmdDumpOneProperty(fd, config.prop, config.areaConfigs[j].areaId);
+    }
+}
+
+void VehicleHalManager::cmdDumpSpecificProperties(int fd, const hidl_vec<hidl_string>& options) {
+    if (!checkArgumentsSize(fd, options, 2)) return;
+
+    // options[0] is the command itself...
+    int rowNumber = 0;
+    size_t size = options.size();
+    for (size_t i = 1; i < size; ++i) {
+        int prop;
+        if (!safelyParseInt(fd, i, options[i], &prop)) return;
+        const auto* config = getPropConfigOrNull(prop);
+        if (config == nullptr) {
+            dprintf(fd, "No property %d\n", prop);
+            continue;
+        }
+        if (size > 2) {
+            // Only show row number if there's more than 1
+            rowNumber++;
+        }
+        cmdDumpOneProperty(fd, rowNumber, *config);
+    }
+}
+
+void VehicleHalManager::cmdDumpOneProperty(int fd, int32_t prop, int32_t areaId) {
+    VehiclePropValue input;
+    input.prop = prop;
+    input.areaId = areaId;
+    auto callback = [&](StatusCode status, const VehiclePropValue& output) {
+        if (status == StatusCode::OK) {
+            dprintf(fd, "%s\n", toString(output).c_str());
+        } else {
+            dprintf(fd, "Could not get property %d. Error: %s\n", prop, toString(status).c_str());
+        }
+    };
+    get(input, callback);
+}
+
+void VehicleHalManager::cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
+    if (!checkCallerHasWritePermissions(fd) || !checkArgumentsSize(fd, options, 3)) return;
+
+    size_t size = options.size();
+
+    // Syntax is --set PROP Type1 Value1 TypeN ValueN, so number of arguments must be even
+    if (size % 2 != 0) {
+        dprintf(fd, "must pass even number of arguments (passed %zu)\n", size);
+        return;
+    }
+    int numberValues = (size - 2) / 2;
+
+    VehiclePropValue prop;
+    if (!safelyParseInt(fd, 1, options[1], &prop.prop)) return;
+    prop.timestamp = 0;
+    prop.areaId = 0;  // TODO: add option to pass areaId as parameter
+    prop.status = VehiclePropertyStatus::AVAILABLE;
+
+    // First pass calculate sizes
+    int sizeInt32 = 0;
+    int stringIndex = 0;
+    for (int i = 2, kv = 1; kv <= numberValues; kv++) {
+        // iterate through the kv=1..n key/value pairs, accessing indexes i / i+1 at each step
+        std::string type = options[i];
+        std::string value = options[i + 1];
+        if (EqualsIgnoreCase(type, "i")) {
+            sizeInt32++;
+        } else if (EqualsIgnoreCase(type, "s")) {
+            if (stringIndex != 0) {
+                dprintf(fd,
+                        "defining string value (%s) again at index %d (already defined at %d=%s"
+                        ")\n",
+                        value.c_str(), i, stringIndex, options[stringIndex + 1].c_str());
+                return;
+            }
+            stringIndex = i;
+        } else {
+            dprintf(fd, "invalid (%s) type at index %d\n", type.c_str(), i);
+            return;
+        }
+        i += 2;
+    }
+    prop.value.int32Values.resize(sizeInt32);
+
+    // Second pass: populate it
+    int indexInt32 = 0;
+    for (int i = 2, kv = 1; kv <= numberValues; kv++) {
+        // iterate through the kv=1..n key/value pairs, accessing indexes i / i+1 at each step
+        int valueIndex = i + 1;
+        std::string type = options[i];
+        std::string value = options[valueIndex];
+        if (EqualsIgnoreCase(type, "i")) {
+            int safeInt;
+            if (!safelyParseInt(fd, valueIndex, value, &safeInt)) return;
+            prop.value.int32Values[indexInt32++] = safeInt;
+        } else if (EqualsIgnoreCase(type, "s")) {
+            prop.value.stringValue = value;
+        }
+        i += 2;
+    }
+    ALOGD("Setting prop %s", toString(prop).c_str());
+    auto status = set(prop);
+    if (status == StatusCode::OK) {
+        dprintf(fd, "Set property %s\n", toString(prop).c_str());
+    } else {
+        dprintf(fd, "Failed to set property %s: %s\n", toString(prop).c_str(),
+                toString(status).c_str());
+    }
+}
+
 void VehicleHalManager::init() {
     ALOGI("VehicleHalManager::init");
 
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 bf85da2..e19987c 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
@@ -87,23 +87,23 @@
 /**
  * This property is used for test purpose to set properties' value from vehicle.
  * For example: Mocking hard button press triggering a HVAC fan speed change.
- * Android set kSetPropertyFromVehcileForTest with an array of integer {HVAC_FAN_SPEED, value of
+ * Android set kSetPropertyFromVehicleForTest with an array of integer {HVAC_FAN_SPEED, value of
  * fan speed} and a long value indicates the timestamp of the events .
  * It only works with integer type properties.
  */
-const int32_t kSetIntPropertyFromVehcileForTest =
+const int32_t kSetIntPropertyFromVehicleForTest =
         0x1112 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED;
 /**
  * This property is used for test purpose to set properties' value from vehicle.
  * It only works with float type properties.
  */
-const int32_t kSetFloatPropertyFromVehcileForTest =
+const int32_t kSetFloatPropertyFromVehicleForTest =
         0x1113 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED;
 /**
  * This property is used for test purpose to set properties' value from vehicle.
  * It only works with boolean type properties.
  */
-const int32_t kSetBooleanPropertyFromVehcileForTest =
+const int32_t kSetBooleanPropertyFromVehicleForTest =
         0x1114 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED;
 
 /**
@@ -695,7 +695,7 @@
         {
                 .config =
                         {
-                                .prop = kSetIntPropertyFromVehcileForTest,
+                                .prop = kSetIntPropertyFromVehicleForTest,
                                 .access = VehiclePropertyAccess::WRITE,
                                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                                 .configArray = {0, 0, 0, 2, 1, 0, 0, 0, 0},
@@ -705,7 +705,7 @@
         {
                 .config =
                         {
-                                .prop = kSetFloatPropertyFromVehcileForTest,
+                                .prop = kSetFloatPropertyFromVehicleForTest,
                                 .access = VehiclePropertyAccess::WRITE,
                                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                                 .configArray = {0, 0, 1, 0, 1, 0, 1, 0, 0},
@@ -715,7 +715,7 @@
         {
                 .config =
                         {
-                                .prop = kSetBooleanPropertyFromVehcileForTest,
+                                .prop = kSetBooleanPropertyFromVehicleForTest,
                                 .access = VehiclePropertyAccess::WRITE,
                                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                                 .configArray = {0, 1, 1, 0, 1, 0, 0, 0, 0},
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
index 222fe5e..d9867bd 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
@@ -202,8 +202,8 @@
         case kGenerateFakeDataControllingProperty:
             return handleGenerateFakeDataRequest(value);
 
-        // set the value from vehcile side, used in end to end test.
-        case kSetIntPropertyFromVehcileForTest: {
+        // set the value from vehicle side, used in end to end test.
+        case kSetIntPropertyFromVehicleForTest: {
             auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::INT32, 1);
             updatedPropValue->prop = value.value.int32Values[0];
             updatedPropValue->value.int32Values[0] = value.value.int32Values[1];
@@ -212,7 +212,7 @@
             onPropertyValueFromCar(*updatedPropValue, updateStatus);
             return StatusCode::OK;
         }
-        case kSetFloatPropertyFromVehcileForTest: {
+        case kSetFloatPropertyFromVehicleForTest: {
             auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::FLOAT, 1);
             updatedPropValue->prop = value.value.int32Values[0];
             updatedPropValue->value.floatValues[0] = value.value.floatValues[0];
@@ -221,7 +221,7 @@
             onPropertyValueFromCar(*updatedPropValue, updateStatus);
             return StatusCode::OK;
         }
-        case kSetBooleanPropertyFromVehcileForTest: {
+        case kSetBooleanPropertyFromVehicleForTest: {
             auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::BOOLEAN, 1);
             updatedPropValue->prop = value.value.int32Values[1];
             updatedPropValue->value.int32Values[0] = value.value.int32Values[0];
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index a91bd88..7a5f2d2 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -2473,7 +2473,8 @@
      * which in turn would disable the other user-related properties (for example, the Android
      * system would never issue them and user-related requests from the HAL layer would be ignored
      * by the Android System). But if it supports user management, then it must support all
-     * user-related properties (INITIAL_USER_INFO, SWITCH_USER, TODO(b/146207078):others).
+     * user-related properties (INITIAL_USER_INFO, SWITCH_USER, CREATE_USER, REMOVE_USER,
+     *       and USER_IDENTIFICATION_ASSOCIATION).
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
@@ -2649,6 +2650,161 @@
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:MIXED
         | VehicleArea:GLOBAL),
+
+    /**
+     * Called by the Android System after an Android user was created.
+     *
+     * The HAL can use this property to create its equivalent user.
+     *
+     * This is an async request: Android makes the request by setting a VehiclePropValue, and HAL
+     * must respond with a property change indicating whether the request succeeded or failed. If
+     * it failed, the Android system will remove the user.
+     *
+     * The format of the request is defined by CreateUserRequest and the format of the response by
+     * CreateUserResponse.
+     *
+     * For example, if system had 2 users (0 and 10) and a 3rd one (which is an ephemeral guest) was
+     * created, the request would be:
+     *
+     * int32[0]: 42  // request id
+     * int32[1]: 11  // Android id of the created user
+     * int32[2]: 3   // Android flags (ephemeral guest) of the created user
+     * int32[3]: 10  // current user
+     * int32[4]: 0   // current user flags (none)
+     * int32[5]: 3   // number of users
+     * int32[6]: 0   // 1st user (user 0)
+     * int32[7]: 0   // 1st user flags (none)
+     * int32[8]: 10  // 2nd user (user 10)
+     * int32[9]: 0   // 2nd user flags (none)
+     * int32[19]: 11 // 3rd user (user 11)
+     * int32[11]: 3  // 3rd user flags (ephemeral guest)
+     * string: "ElGuesto" // name of the new user
+     *
+     * Then if the request succeeded, the HAL would return:
+     *
+     * int32[0]: 42  // request id
+     * int32[1]: 1   // CreateUserStatus::SUCCESS
+     *
+     * But if it failed:
+     *
+     * int32[0]: 42  // request id
+     * int32[1]: 2   // CreateUserStatus::FAILURE
+     * string: "D'OH!" // The meaning is a blackbox - it's passed to the caller (like Settings UI),
+     *                 // which in turn can take the proper action.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    CREATE_USER = (
+        0x0F09
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:MIXED
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Called by the Android System after an Android user was removed.
+     *
+     * The HAL can use this property to remove its equivalent user.
+     *
+     * This is write-only call - the Android System is not expecting a reply from the HAL. Hence,
+     * this request should not fail - if the equivalent HAL user cannot be removed, then HAL should
+     * mark it as inactive or recover in some other way.
+     *
+     * The request is made by setting the VehiclePropValue with the contents defined by
+     * RemoveUserRequest.
+     *
+     * For example, if system had 3 users (0, 10, and 11) and user 11 was removed, the request
+     * would be:
+     *
+     * int32[0]: 42  // request id
+     * int32[1]: 11  // (Android user id of the removed user)
+     * int32[2]: 0   // (Android user flags of the removed user)
+     * int32[3]: 10  // current user
+     * int32[4]: 0   // current user flags (none)
+     * int32[5]: 2   // number of users
+     * int32[6]: 0   // 1st user (user 0)
+     * int32[7]: 0   // 1st user flags (none)
+     * int32[8]: 10  // 2nd user (user 10)
+     * int32[9]: 0   // 2nd user flags (none)
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:WRITE
+     */
+    REMOVE_USER = (
+        0x0F0A
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:MIXED
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Property used to associate (or query the association) the current user with vehicle-specific
+     * identification mechanisms (such as key FOB).
+     *
+     * To query the association, the Android system gets the property, passing a VehiclePropValue
+     * containing the types of associations are being queried, as defined by
+     * UserIdentificationGetRequest. The HAL must return right away, updating the VehiclePropValue
+     * with a UserIdentificationResponse. Notice that user identification should have already
+     * happened while system is booting up and the VHAL implementation should only return the
+     * already identified association (like the key FOB used to unlock the car), instead of starting
+     * a new association from the get call.
+     *
+     * To associate types, the Android system sets the property, passing a VehiclePropValue
+     * containing the types and values of associations being set, as defined by the
+     * UserIdentificationSetRequest. The HAL will then use a property change event (whose
+     * VehiclePropValue is defined by UserIdentificationResponse) indicating the current status of
+     * the types after the request.
+     *
+     * For example, to query if the current user (10) is associated with the FOB that unlocked the
+     * car and a custom mechanism provided by the OEM, the request would be:
+     *
+     * int32[0]: 10  (Android user id)
+     * int32[1]: 0   (Android user flags)
+     * int32[2]: 2   (number of types queried)
+     * int32[3]: 1   (1st type queried, UserIdentificationAssociationType::KEY_FOB)
+     * int32[4]: 101 (2nd type queried, UserIdentificationAssociationType::CUSTOM_1)
+     *
+     * If the user is associated with the FOB but not with the custom mechanism, the response would
+     * be:
+     *
+     * int32[9]: 2   (number of associations in the response)
+     * int32[1]: 1   (1st type: UserIdentificationAssociationType::KEY_FOB)
+     * int32[2]: 2   (1st value: UserIdentificationAssociationValue::ASSOCIATED_CURRENT_USER)
+     * int32[3]: 101 (2st type: UserIdentificationAssociationType::CUSTOM_1)
+     * int32[4]: 4   (2nd value: UserIdentificationAssociationValue::NOT_ASSOCIATED_ANY_USER)
+     *
+     * Then to associate the user with the custom mechanism, a set request would be made:
+     *
+     * int32[0]: 10  (Android user id)
+     * int32[0]: 0   (Android user flags)
+     * int32[1]: 1   (number of associations being set)
+     * int32[2]: 101 (1st type: UserIdentificationAssociationType::CUSTOM_1)
+     * int32[3]: 1   (1st value: UserIdentificationAssociationSETValue::ASSOCIATE_CURRENT_USER)
+     *
+     * If the request succeeded, the response would be simply:
+     *
+     * int32[0]: 2   (number of associations in the response)
+     * int32[1]: 101 (1st type: UserIdentificationAssociationType::CUSTOM_1)
+     * int32[2]: 1   (1st value: UserIdentificationAssociationValue::ASSOCIATED_CURRENT_USER)
+     *
+     * Notice that the set request adds associations, but doesn't remove the existing ones. In the
+     * example above, the end state would be 2 associations (FOB and CUSTOM_1). If we wanted to
+     * associate the user with just CUSTOM_1 but not FOB, then the request should have been:
+     *
+     * int32[0]: 10  (Android user id)
+     * int32[1]: 2   (number of types set)
+     * int32[2]: 1   (1st type: UserIdentificationAssociationType::KEY_FOB)
+     * int32[3]: 2   (1st value: UserIdentificationAssociationValue::DISASSOCIATE_CURRENT_USER)
+     * int32[3]: 101 (2nd type: UserIdentificationAssociationType::CUSTOM_1)
+     * int32[5]: 1   (2nd value: UserIdentificationAssociationValue::ASSOCIATE_CURRENT_USER)
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    USER_IDENTIFICATION_ASSOCIATION = (
+        0x0F0B
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:MIXED
+        | VehicleArea:GLOBAL),
 };
 
 /**
@@ -4184,10 +4340,10 @@
     /**
      * HAL-specific error message.
      *
-     * This argument is optional, and when defined (and the status is FAILURE), it's passed "as-is"
-     * to the caller. It could be used to show custom error messages to the end user.
+     * This argument is optional, and when defined, it's passed "as-is" to the caller. It could be
+     * used to show custom error messages to the end user.
      */
-    string failureMessage;
+    string errorMessage;
 };
 
 /**
@@ -4199,3 +4355,253 @@
    /** The request failed and the HAL user remained the same. */
    FAILURE = 2,
 };
+
+/**
+ * Defines the format of a CREATE_USER property.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+struct CreateUserRequest {
+    /**
+     * Arbitrary id used to map the response to the request.
+     */
+    UserRequestId requestId;
+
+    /**
+     * Basic information about Android user that was created.
+     */
+    UserInfo newUserInfo;
+
+    /**
+     * Name of the new Android user.
+     */
+     string newUserName;
+
+    /**
+     * Information about the current state of the Android system.
+     */
+    UsersInfo usersInfo;
+};
+
+/**
+ * Defines the result of a CreateUserRequest.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+struct CreateUserResponse {
+    /**
+     * Id of the request being responded.
+     */
+    UserRequestId requestId;
+
+    /**
+     * Status of the request.
+     */
+    CreateUserStatus status;
+
+    /**
+     * HAL-specific error message.
+     *
+     * This argument is optional, and when defined, it's passed "as-is" to the caller. It could be
+     * used to show custom error messages to the end user.
+     */
+    string errorMessage;
+};
+
+/**
+ * Status of the response to a CreateUserRequest.
+ */
+enum CreateUserStatus : int32_t {
+   /**
+    * The request succeeded (for example, HAL created a new internal user, or associated the
+    * Android user to an existing internal user).
+    */
+   SUCCESS = 1,
+
+   /**
+     * The request failed (and Android will remove the Android user).
+     */
+   FAILURE = 2,
+};
+
+/**
+ * Defines the format of a REMOVE_USER property.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+struct RemoveUserRequest {
+    /**
+     * Arbitrary id used to map the response to the request.
+     */
+    UserRequestId requestId;
+
+    /**
+     * Information about the Android user that was removed.
+     */
+    UserInfo removedUserInfo;
+
+    /**
+     * Information about the current state of the Android system.
+     */
+    UsersInfo usersInfo;
+};
+
+/**
+  * Types of mechanisms used to identify an Android user.
+  *
+  * See USER_IDENTIFICATION_ASSOCIATION for more details and example.
+  */
+enum UserIdentificationAssociationType: int32_t {
+   /** Key used to unlock the car. */
+   KEY_FOB = 1,
+   /** Custom mechanism defined by the OEM. */
+   CUSTOM_1 = 101,
+   /** Custom mechanism defined by the OEM. */
+   CUSTOM_2 = 102,
+   /** Custom mechanism defined by the OEM. */
+   CUSTOM_3 = 103,
+   /** Custom mechanism defined by the OEM. */
+   CUSTOM_4 = 104,
+};
+
+/**
+ * Whether a UserIdentificationAssociationType is associate with an Android user.
+ */
+enum UserIdentificationAssociationValue : int32_t {
+   /**
+    * Used when the status of an association could not be determined.
+    *
+    * For example, in a set() request, it would indicate a failure to set the given type.
+    */
+   UNKNOWN = 1,
+
+   /**
+    * The identification type is associated with the current foreground Android user.
+    */
+   ASSOCIATED_CURRENT_USER = 2,
+
+   /**
+    * The identification type is associated with another Android user.
+    */
+   ASSOCIATED_ANOTHER_USER = 3,
+
+   /**
+    * The identification type is not associated with any Android user.
+    */
+   NOT_ASSOCIATED_ANY_USER = 4,
+};
+
+/**
+ * Used to set a UserIdentificationAssociationType with an Android user.
+ */
+enum UserIdentificationAssociationSetValue : int32_t {
+   /**
+    * Associate the identification type with the current foreground Android user.
+    */
+   ASSOCIATE_CURRENT_USER = 1,
+
+   /**
+    * Disassociate the identification type from the current foreground Android user.
+    */
+   DISASSOCIATE_CURRENT_USER = 2,
+
+   /**
+    * Disassociate the identification type from all Android users.
+    */
+   DISASSOCIATE_ALL_USERS = 3,
+};
+
+/**
+ * Defines the format of a get() call to USER_IDENTIFICATION_ASSOCIATION.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+struct UserIdentificationGetRequest {
+    /**
+     * Information about the current foreground Android user.
+     */
+    UserInfo userInfo;
+
+    /**
+     * Number of association being queried.
+     */
+    int32_t numberAssociationTypes;
+
+    /**
+     * Types of association being queried.
+     */
+    vec<UserIdentificationAssociationType> associationTypes;
+};
+
+/**
+ * Defines the format of a set() call to USER_IDENTIFICATION_ASSOCIATION.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+struct UserIdentificationSetRequest {
+    /**
+     * Information about the current foreground Android user.
+     */
+    UserInfo userInfo;
+
+    /**
+     * Number of association being set.
+     */
+    int32_t numberAssociations;
+
+    /**
+     * Associations being set.
+     */
+    vec<UserIdentificationAssociationSetValue> associations;
+};
+
+/**
+ * Defines the result of a USER_IDENTIFICATION_ASSOCIATION - both for get() and set().
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+struct UserIdentificationResponse {
+    /**
+     * Number of associations being returned.
+     */
+    int32_t numberAssociation;
+
+    /**
+     * Values associated with the user.
+     */
+    vec<UserIdentificationAssociation> associations;
+
+    /**
+     * HAL-specific error message.
+     *
+     * This argument is optional, and when defined, it's passed "as-is" to the caller. It could be
+     * used to show custom error messages to the end user.
+     */
+    string errorMessage;
+};
+
+/**
+ * Helper struct used when getting a user/identification association type.
+ */
+struct UserIdentificationAssociation {
+
+    UserIdentificationAssociationType type;
+
+    UserIdentificationAssociationValue value;
+};
+
+/**
+ * Helper struct used when setting a user/identification association type.
+ */
+struct UserIdentificationSetAssociation {
+
+    UserIdentificationAssociationType type;
+
+    UserIdentificationAssociationSetValue value;
+};
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 9a8f336..8eb7587 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -161,7 +161,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.drm</name>
-        <version>1.0-3</version>
+        <version>1.3</version>
         <interface>
             <name>ICryptoFactory</name>
             <regex-instance>.*</regex-instance>
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
index ba9fb45..03af671 100644
--- a/neuralnetworks/1.0/vts/functional/Android.bp
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -14,13 +14,30 @@
 // limitations under the License.
 //
 
+cc_defaults {
+    name: "neuralnetworks_vts_functional_defaults",
+    defaults: ["VtsHalTargetTestDefaults"],
+    arch: {
+        x86: {
+            cflags: [ "-D_Float16=__fp16",
+                      "-Xclang", "-fnative-half-type",
+                      "-Xclang", "-fallow-half-arguments-and-returns" ],
+        },
+        x86_64: {
+            cflags: [ "-D_Float16=__fp16",
+                      "-Xclang", "-fnative-half-type",
+                      "-Xclang", "-fallow-half-arguments-and-returns" ],
+        },
+    },
+}
+
 cc_library_static {
     name: "VtsHalNeuralNetworksV1_0_utils",
     srcs: [
         "Callbacks.cpp",
         "Utils.cpp",
     ],
-    defaults: ["VtsHalTargetTestDefaults"],
+    defaults: ["neuralnetworks_vts_functional_defaults"],
     export_include_dirs: ["include"],
     shared_libs: [
         "libfmq",
@@ -42,7 +59,7 @@
 
 cc_test {
     name: "VtsHalNeuralnetworksV1_0TargetTest",
-    defaults: ["VtsHalTargetTestDefaults"],
+    defaults: ["neuralnetworks_vts_functional_defaults"],
     srcs: [
         "BasicTests.cpp",
         "TestAssertions.cpp",
diff --git a/neuralnetworks/1.1/vts/functional/Android.bp b/neuralnetworks/1.1/vts/functional/Android.bp
index 69e1761..9ba1925 100644
--- a/neuralnetworks/1.1/vts/functional/Android.bp
+++ b/neuralnetworks/1.1/vts/functional/Android.bp
@@ -16,7 +16,7 @@
 
 cc_test {
     name: "VtsHalNeuralnetworksV1_1TargetTest",
-    defaults: ["VtsHalTargetTestDefaults"],
+    defaults: ["neuralnetworks_vts_functional_defaults"],
     srcs: [
         "BasicTests.cpp",
         "TestAssertions.cpp",
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
index fc727b7..7886910 100644
--- a/neuralnetworks/1.2/vts/functional/Android.bp
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -16,7 +16,7 @@
 
 cc_library_static {
     name: "VtsHalNeuralNetworksV1_2Callbacks",
-    defaults: ["VtsHalTargetTestDefaults"],
+    defaults: ["neuralnetworks_vts_functional_defaults"],
     export_include_dirs: ["include"],
     srcs: [
         "Callbacks.cpp",
@@ -33,7 +33,7 @@
 
 cc_test {
     name: "VtsHalNeuralnetworksV1_2TargetTest",
-    defaults: ["VtsHalTargetTestDefaults"],
+    defaults: ["neuralnetworks_vts_functional_defaults"],
     srcs: [
         "BasicTests.cpp",
         "CompilationCachingTests.cpp",
diff --git a/neuralnetworks/1.3/vts/functional/Android.bp b/neuralnetworks/1.3/vts/functional/Android.bp
index 8e7e9b9..f936267 100644
--- a/neuralnetworks/1.3/vts/functional/Android.bp
+++ b/neuralnetworks/1.3/vts/functional/Android.bp
@@ -16,7 +16,7 @@
 
 cc_library_static {
     name: "VtsHalNeuralNetworksV1_3_utils",
-    defaults: ["VtsHalTargetTestDefaults"],
+    defaults: ["neuralnetworks_vts_functional_defaults"],
     export_include_dirs: ["include"],
     srcs: [
         "Callbacks.cpp",
@@ -35,7 +35,7 @@
 
 cc_test {
     name: "VtsHalNeuralnetworksV1_3TargetTest",
-    defaults: ["VtsHalTargetTestDefaults"],
+    defaults: ["neuralnetworks_vts_functional_defaults"],
     srcs: [
         "BasicTests.cpp",
         "CompilationCachingTests.cpp",
diff --git a/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp
index 9f57934..2715891 100644
--- a/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp
+++ b/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <VtsCoreUtil.h>
+
 #include <android-base/logging.h>
 #include <cutils/properties.h>
 
@@ -62,11 +64,19 @@
                                           hostapd_instance_name_);
         hostapd_ = IHostapd::getService(hostapd_instance_name_);
         ASSERT_NE(hostapd_.get(), nullptr);
+        isAcsSupport_ = testing::checkSubstringInCommandOutput(
+            "/system/bin/cmd wifi get-softap-supported-features",
+            "wifi_softap_acs_supported");
+        isWpa3SaeSupport_ = testing::checkSubstringInCommandOutput(
+            "/system/bin/cmd wifi get-softap-supported-features",
+            "wifi_softap_wpa3_sae_supported");
     }
 
     virtual void TearDown() override { stopHostapd(hostapd_instance_name_); }
 
    protected:
+    bool isWpa3SaeSupport_ = false;
+    bool isAcsSupport_ = false;
     std::string getPrimaryWlanIfaceName() {
         std::array<char, PROPERTY_VALUE_MAX> buffer;
         auto res = property_get("ro.vendor.wifi.sap.interface", buffer.data(),
@@ -208,10 +218,10 @@
  * Access point creation should pass.
  */
 TEST_P(HostapdHidlTest, AddPskAccessPointWithAcs) {
+    if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
     auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
                               getIfaceParamsWithAcs(), getPskNwParams());
-    // TODO: b/140172237, fix this in R.
-    // EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
 }
 
 /**
@@ -219,11 +229,11 @@
  * Access point creation should pass.
  */
 TEST_P(HostapdHidlTest, AddPskAccessPointWithAcsAndFreqRange) {
+    if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
     auto status =
         HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
                     getIfaceParamsWithAcsAndFreqRange(), getPskNwParams());
-    // TODO: b/140172237, fix this in R
-    // EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
 }
 
 /**
@@ -231,11 +241,11 @@
  * Access point creation should fail.
  */
 TEST_P(HostapdHidlTest, AddPskAccessPointWithAcsAndInvalidFreqRange) {
+    if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
     auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
                               getIfaceParamsWithAcsAndInvalidFreqRange(),
                               getPskNwParams());
-    // TODO: b/140172237, fix this in R
-    // EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
+    EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
 }
 
 /**
@@ -243,10 +253,10 @@
  * Access point creation should pass.
  */
 TEST_P(HostapdHidlTest, AddOpenAccessPointWithAcs) {
+    if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
     auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
                               getIfaceParamsWithAcs(), getOpenNwParams());
-    // TODO: b/140172237, fix this in R
-    // EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
 }
 
 /**
@@ -274,6 +284,7 @@
  * Access point creation should pass.
  */
 TEST_P(HostapdHidlTest, AddSaeTransitionAccessPointWithoutAcs) {
+    if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support";
     auto status =
         HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(),
                     getSaeTransitionNwParams());
@@ -285,6 +296,7 @@
  * Access point creation should pass.
  */
 TEST_P(HostapdHidlTest, AddSAEAccessPointWithoutAcs) {
+    if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support";
     auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
                               getIfaceParamsWithoutAcs(), getSaeNwParams());
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
@@ -295,16 +307,15 @@
  * Access point creation & removal should pass.
  */
 TEST_P(HostapdHidlTest, RemoveAccessPointWithAcs) {
+    if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
     auto status_1_2 = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
                                   getIfaceParamsWithAcs(), getPskNwParams());
-    // TODO: b/140172237, fix this in R
-    /*
     EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code);
     auto status =
         HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName());
-    EXPECT_EQ(android::hardware::wifi::hostapd::V1_0::HostapdStatusCode::SUCCESS,
-    status.code);
-    */
+    EXPECT_EQ(
+        android::hardware::wifi::hostapd::V1_0::HostapdStatusCode::SUCCESS,
+        status.code);
 }
 
 /**
@@ -349,6 +360,7 @@
  * Access point creation should fail.
  */
 TEST_P(HostapdHidlTest, AddInvalidSaeTransitionAccessPointWithoutAcs) {
+    if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support";
     auto status =
         HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(),
                     getInvalidSaeTransitionNwParams());
@@ -360,6 +372,7 @@
  * Access point creation should fail.
  */
 TEST_P(HostapdHidlTest, AddInvalidSaeAccessPointWithoutAcs) {
+    if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support";
     auto status =
         HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(),
                     getInvalidSaeNwParams());