Merge "Add soft_audio_configuration_changed_cb_ to handle the streamMap changed" am: a59abdd935 am: bc3373c88e am: 5319e263ed am: 0eb8e2b453

Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2193731

Change-Id: Iee617749667b8872d5449bfec2c4634529e044e3
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/audio/effect/all-versions/default/Effect.cpp b/audio/effect/all-versions/default/Effect.cpp
index 3baafc9..b57dc63 100644
--- a/audio/effect/all-versions/default/Effect.cpp
+++ b/audio/effect/all-versions/default/Effect.cpp
@@ -238,12 +238,27 @@
 }
 
 // static
-std::vector<uint8_t> Effect::parameterToHal(uint32_t paramSize, const void* paramData,
-                                            uint32_t valueSize, const void** valueData) {
+bool Effect::parameterToHal(uint32_t paramSize, const void* paramData, uint32_t valueSize,
+                            const void** valueData, std::vector<uint8_t>* halParamBuffer) {
+    constexpr size_t kMaxSize = EFFECT_PARAM_SIZE_MAX - sizeof(effect_param_t);
+    if (paramSize > kMaxSize) {
+        ALOGE("%s: Parameter size is too big: %" PRIu32, __func__, paramSize);
+        return false;
+    }
     size_t valueOffsetFromData = alignedSizeIn<uint32_t>(paramSize) * sizeof(uint32_t);
+    if (valueOffsetFromData > kMaxSize) {
+        ALOGE("%s: Aligned parameter size is too big: %zu", __func__, valueOffsetFromData);
+        return false;
+    }
+    if (valueSize > kMaxSize - valueOffsetFromData) {
+        ALOGE("%s: Value size is too big: %" PRIu32 ", max size is %zu", __func__, valueSize,
+              kMaxSize - valueOffsetFromData);
+        android_errorWriteLog(0x534e4554, "237291425");
+        return false;
+    }
     size_t halParamBufferSize = sizeof(effect_param_t) + valueOffsetFromData + valueSize;
-    std::vector<uint8_t> halParamBuffer(halParamBufferSize, 0);
-    effect_param_t* halParam = reinterpret_cast<effect_param_t*>(&halParamBuffer[0]);
+    halParamBuffer->resize(halParamBufferSize, 0);
+    effect_param_t* halParam = reinterpret_cast<effect_param_t*>(halParamBuffer->data());
     halParam->psize = paramSize;
     halParam->vsize = valueSize;
     memcpy(halParam->data, paramData, paramSize);
@@ -256,7 +271,7 @@
             *valueData = halParam->data + valueOffsetFromData;
         }
     }
-    return halParamBuffer;
+    return true;
 }
 
 Result Effect::analyzeCommandStatus(const char* commandName, const char* context, status_t status) {
@@ -301,6 +316,11 @@
 
 Result Effect::getCurrentConfigImpl(uint32_t featureId, uint32_t configSize,
                                     GetCurrentConfigSuccessCallback onSuccess) {
+    if (configSize > kMaxDataSize - sizeof(uint32_t)) {
+        ALOGE("%s: Config size is too big: %" PRIu32, __func__, configSize);
+        android_errorWriteLog(0x534e4554, "240266798");
+        return Result::INVALID_ARGUMENTS;
+    }
     uint32_t halCmd = featureId;
     std::vector<uint32_t> halResult(alignedSizeIn<uint32_t>(sizeof(uint32_t) + configSize), 0);
     uint32_t halResultSize = 0;
@@ -314,11 +334,15 @@
                                 GetParameterSuccessCallback onSuccess) {
     // As it is unknown what method HAL uses for copying the provided parameter data,
     // it is safer to make sure that input and output buffers do not overlap.
-    std::vector<uint8_t> halCmdBuffer =
-        parameterToHal(paramSize, paramData, requestValueSize, nullptr);
+    std::vector<uint8_t> halCmdBuffer;
+    if (!parameterToHal(paramSize, paramData, requestValueSize, nullptr, &halCmdBuffer)) {
+        return Result::INVALID_ARGUMENTS;
+    }
     const void* valueData = nullptr;
-    std::vector<uint8_t> halParamBuffer =
-        parameterToHal(paramSize, paramData, replyValueSize, &valueData);
+    std::vector<uint8_t> halParamBuffer;
+    if (!parameterToHal(paramSize, paramData, replyValueSize, &valueData, &halParamBuffer)) {
+        return Result::INVALID_ARGUMENTS;
+    }
     uint32_t halParamBufferSize = halParamBuffer.size();
 
     return sendCommandReturningStatusAndData(
@@ -331,8 +355,12 @@
 
 Result Effect::getSupportedConfigsImpl(uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
                                        GetSupportedConfigsSuccessCallback onSuccess) {
+    if (maxConfigs != 0 && configSize > (kMaxDataSize - 2 * sizeof(uint32_t)) / maxConfigs) {
+        ALOGE("%s: Config size is too big: %" PRIu32, __func__, configSize);
+        return Result::INVALID_ARGUMENTS;
+    }
     uint32_t halCmd[2] = {featureId, maxConfigs};
-    uint32_t halResultSize = 2 * sizeof(uint32_t) + maxConfigs * sizeof(configSize);
+    uint32_t halResultSize = 2 * sizeof(uint32_t) + maxConfigs * configSize;
     std::vector<uint8_t> halResult(static_cast<size_t>(halResultSize), 0);
     return sendCommandReturningStatusAndData(
         EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS, "GET_FEATURE_SUPPORTED_CONFIGS", sizeof(halCmd),
@@ -472,8 +500,10 @@
 
 Result Effect::setParameterImpl(uint32_t paramSize, const void* paramData, uint32_t valueSize,
                                 const void* valueData) {
-    std::vector<uint8_t> halParamBuffer =
-        parameterToHal(paramSize, paramData, valueSize, &valueData);
+    std::vector<uint8_t> halParamBuffer;
+    if (!parameterToHal(paramSize, paramData, valueSize, &valueData, &halParamBuffer)) {
+        return Result::INVALID_ARGUMENTS;
+    }
     return sendCommandReturningStatus(EFFECT_CMD_SET_PARAM, "SET_PARAM", halParamBuffer.size(),
                                       &halParamBuffer[0]);
 }
diff --git a/audio/effect/all-versions/default/Effect.h b/audio/effect/all-versions/default/Effect.h
index 011544d..5d8dccc 100644
--- a/audio/effect/all-versions/default/Effect.h
+++ b/audio/effect/all-versions/default/Effect.h
@@ -184,6 +184,9 @@
     using GetSupportedConfigsSuccessCallback =
         std::function<void(uint32_t supportedConfigs, void* configsData)>;
 
+    // Sets the limit on the maximum size of vendor-provided data structures.
+    static constexpr size_t kMaxDataSize = 1 << 20;
+
     static const char* sContextResultOfCommand;
     static const char* sContextCallToCommand;
     static const char* sContextCallFunction;
@@ -211,8 +214,8 @@
                                              channel_config_t* halConfig);
     static void effectOffloadParamToHal(const EffectOffloadParameter& offload,
                                         effect_offload_param_t* halOffload);
-    static std::vector<uint8_t> parameterToHal(uint32_t paramSize, const void* paramData,
-                                               uint32_t valueSize, const void** valueData);
+    static bool parameterToHal(uint32_t paramSize, const void* paramData, uint32_t valueSize,
+                               const void** valueData, std::vector<uint8_t>* halParamBuffer);
 
     Result analyzeCommandStatus(const char* commandName, const char* context, status_t status);
     void getConfigImpl(int commandCode, const char* commandName, GetConfigCallback cb);
diff --git a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
index e59423f..d95bb06 100644
--- a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
@@ -35,6 +35,7 @@
 
 #include <common/all-versions/VersionUtils.h>
 
+#include <cutils/properties.h>
 #include <gtest/gtest.h>
 #include <hidl/GtestPrinter.h>
 #include <hidl/ServiceManagement.h>
@@ -623,6 +624,27 @@
     EXPECT_TRUE(ret.isOk());
 }
 
+TEST_P(AudioEffectHidlTest, GetParameterInvalidMaxReplySize) {
+    description("Verify that GetParameter caps the maximum reply size");
+    const bool isNewDeviceLaunchingOnTPlus = property_get_int32("ro.vendor.api_level", 0) >= 33;
+    if (!isNewDeviceLaunchingOnTPlus) {
+        GTEST_SKIP() << "The test only applies to devices launching on T or later";
+    }
+    // Use a non-empty parameter to avoid being rejected by any earlier checks.
+    hidl_vec<uint8_t> parameter;
+    parameter.resize(16);
+    // Use very large size to ensure that the service does not crash. Since parameters
+    // are specific to each effect, and some effects may not have parameters at all,
+    // simply checking the return value would not reveal an issue of using an uncapped value.
+    const uint32_t veryLargeReplySize = std::numeric_limits<uint32_t>::max() - 100;
+    Result retval = Result::OK;
+    Return<void> ret =
+            effect->getParameter(parameter, veryLargeReplySize,
+                                 [&](Result r, const hidl_vec<uint8_t>&) { retval = r; });
+    EXPECT_TRUE(ret.isOk());
+    EXPECT_EQ(Result::INVALID_ARGUMENTS, retval);
+}
+
 TEST_P(AudioEffectHidlTest, GetSupportedConfigsForFeature) {
     description("Verify that GetSupportedConfigsForFeature does not crash");
     Return<void> ret = effect->getSupportedConfigsForFeature(
@@ -643,6 +665,37 @@
     EXPECT_TRUE(ret.isOk());
 }
 
+TEST_P(AudioEffectHidlTest, GetSupportedConfigsForFeatureInvalidConfigSize) {
+    description("Verify that GetSupportedConfigsForFeature caps the maximum config size");
+    const bool isNewDeviceLaunchingOnTPlus = property_get_int32("ro.vendor.api_level", 0) >= 33;
+    if (!isNewDeviceLaunchingOnTPlus) {
+        GTEST_SKIP() << "The test only applies to devices launching on T or later";
+    }
+    // Use very large size to ensure that the service does not crash.
+    const uint32_t veryLargeConfigSize = std::numeric_limits<uint32_t>::max() - 100;
+    Result retval = Result::OK;
+    Return<void> ret = effect->getSupportedConfigsForFeature(
+            0, 1, veryLargeConfigSize,
+            [&](Result r, uint32_t, const hidl_vec<uint8_t>&) { retval = r; });
+    EXPECT_TRUE(ret.isOk());
+    EXPECT_EQ(Result::INVALID_ARGUMENTS, retval);
+}
+
+TEST_P(AudioEffectHidlTest, GetCurrentConfigForFeatureInvalidConfigSize) {
+    description("Verify that GetCurrentConfigForFeature caps the maximum config size");
+    const bool isNewDeviceLaunchingOnTPlus = property_get_int32("ro.vendor.api_level", 0) >= 33;
+    if (!isNewDeviceLaunchingOnTPlus) {
+        GTEST_SKIP() << "The test only applies to devices launching on T or later";
+    }
+    // Use very large size to ensure that the service does not crash.
+    const uint32_t veryLargeConfigSize = std::numeric_limits<uint32_t>::max() - 100;
+    Result retval = Result::OK;
+    Return<void> ret = effect->getCurrentConfigForFeature(
+            0, veryLargeConfigSize, [&](Result r, const hidl_vec<uint8_t>&) { retval = r; });
+    EXPECT_TRUE(ret.isOk());
+    EXPECT_EQ(Result::INVALID_ARGUMENTS, retval);
+}
+
 // The main test class for Equalizer Audio Effect HIDL HAL.
 class EqualizerAudioEffectHidlTest : public AudioEffectHidlTest {
   public:
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/EvsEventDesc.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/EvsEventDesc.aidl
index ebff98f..3abdb54 100644
--- a/automotive/evs/aidl/android/hardware/automotive/evs/EvsEventDesc.aidl
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/EvsEventDesc.aidl
@@ -33,7 +33,9 @@
     @utf8InCpp
     String deviceId;
     /**
-     * Possible additional vendor information that is opaque to the EvsManager
+     * Possible additional vendor information that is opaque to the EvsManager.
+     * The size of the payload must not exceed 16-byte if the HIDL recipients are
+     * expected to exist.
      */
     int[] payload;
 }
diff --git a/automotive/evs/aidl/android/hardware/automotive/evs/IEvsCameraStream.aidl b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsCameraStream.aidl
index 2c2b44c..c599d58 100644
--- a/automotive/evs/aidl/android/hardware/automotive/evs/IEvsCameraStream.aidl
+++ b/automotive/evs/aidl/android/hardware/automotive/evs/IEvsCameraStream.aidl
@@ -47,7 +47,10 @@
     /**
      * Receives calls from the HAL each time an event happens.
      *
-     * @param in event EVS event with possible event information.
+     * @param in event EVS event with possible event information.  If ths HIDL
+     *                 recipients are expected to exist, the size of the event
+     *                 payload must not exceed 16 bytes; otherwise, a notification
+     *                 will not reach them.
      */
     void notify(in EvsEventDesc event);
 }
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index 0d3253b..33e211c 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -84,7 +84,10 @@
     name: "android.hardware.automotive.vehicle@2.0-default-impl-lib",
     vendor: true,
     defaults: ["vhal_v2_0_target_defaults"],
-    cflags: ["-DENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING"],
+    cflags: [
+        "-DENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING",
+        "-DENABLE_GET_PROP_CONFIGS_BY_MULTIPLE_REQUESTS",
+    ],
     srcs: [
         "impl/vhal_v2_0/DefaultVehicleHal.cpp",
         "impl/vhal_v2_0/VehicleHalClient.cpp",
@@ -225,6 +228,25 @@
     test_suites: ["general-tests"],
 }
 
+cc_test {
+    name: "android.hardware.automotive.vehicle@2.0-default-config-test",
+    vendor: true,
+    defaults: ["vhal_v2_0_target_defaults"],
+    srcs: [
+        "impl/vhal_v2_0/tests/DefaultConfigSupportedPropertyIds_test.cpp",
+    ],
+    cflags: [
+        "-DENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING",
+        "-DENABLE_GET_PROP_CONFIGS_BY_MULTIPLE_REQUESTS",
+    ],
+    static_libs: [
+        "android.hardware.automotive.vehicle@2.0-default-impl-lib",
+        "libgtest",
+        "libgmock",
+    ],
+    test_suites: ["general-tests"],
+}
+
 cc_binary {
     name: "android.hardware.automotive.vehicle@2.0-default-service",
     defaults: ["vhal_v2_0_target_defaults"],
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 cfbbbd3..55a7720 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
@@ -1109,6 +1109,19 @@
                         },
                 .initialValue = {.stringValue = {"Test"}},
         },
+        // This property is later defined in the AIDL VHAL interface. However, HIDL VHAL might
+        // require support for this property to meet EU regulation.
+        {
+                .config =
+                        {
+                                // GENERAL_SAFETY_REGULATION_COMPLIANCE_REQUIREMENT
+                                .prop = 0x11400F47,
+                                .access = VehiclePropertyAccess::READ,
+                                .changeMode = VehiclePropertyChangeMode::STATIC,
+                        },
+                // GsrComplianceRequirementType::GSR_COMPLIANCE_REQUIRED_V1
+                .initialValue = {.int32Values = {1}},
+        },
 #ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
         // Vendor propetry for E2E ClusterHomeService testing.
         {
@@ -1157,6 +1170,46 @@
                         },
         },
 #endif  // ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
+#ifdef ENABLE_GET_PROP_CONFIGS_BY_MULTIPLE_REQUESTS
+        {
+                .config =
+                        {
+                                // VHAL_SUPPORTED_PROPERTY_IDS
+                                .prop = 289476424,
+                                .access = VehiclePropertyAccess::READ,
+                                .changeMode = VehiclePropertyChangeMode::STATIC,
+                                // Fetch 100 configs in one request. This number is just arbitrarily
+                                // chosen here. But some HAL impl with bigger config data may need a
+                                // smaller number.
+                                .configArray = {100},
+                        },
+                // All supported property IDs. This list is checked by
+                // DefaultConfigSupportedPropertyIds_test.
+                .initialValue =
+                        {.int32Values =
+                                 {291504388, 289472773, 291504390, 289472775, 289407240, 289407241,
+                                  289472780, 286261505, 286261506, 289407235, 289472779, 291504647,
+                                  289408517, 356518832, 356516106, 291504644, 291504649, 291504656,
+                                  291504901, 291504903, 287310600, 291504905, 287310602, 287310603,
+                                  291504908, 291504904, 392168201, 392168202, 289408514, 289408001,
+                                  287310850, 287310851, 287310853, 289475088, 289475104, 289475120,
+                                  354419984, 320865540, 320865556, 354419975, 354419976, 354419986,
+                                  354419973, 354419974, 354419978, 354419977, 356517120, 356517121,
+                                  356582673, 356517139, 289408269, 356517131, 358614275, 291570965,
+                                  291505923, 289408270, 289408512, 287310855, 289408000, 289408008,
+                                  289408009, 289407747, 291504900, 568332561, 371198722, 373295872,
+                                  320867268, 322964416, 290521862, 287310858, 287310859, 289475072,
+                                  289475073, 289409539, 299896064, 299896065, 299896066, 299896067,
+                                  289410560, 289410561, 289410562, 289410563, 289410576, 289410577,
+                                  289410578, 289410579, 289476368, 299895808, 639631617, 627048706,
+                                  591397123, 554696964, 289410873, 289410874, 287313669, 299896583,
+                                  299896584, 299896585, 299896586, 299896587, 286265121, 286265122,
+                                  286265123, 290457094, 290459441, 299896626, 290459443, 289410868,
+                                  289476405, 299896630, 289410871, 292556600, 557853201, 559950353,
+                                  555756049, 554707473, 289410887, 557846324, 557911861, 568332086,
+                                  557846327, 560992056, 289476424}},
+        },
+#endif  // ENABLE_GET_PROP_CONFIGS_BY_MULTIPLE_REQUESTS
 };
 
 }  // impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/DefaultConfigSupportedPropertyIds_test.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/DefaultConfigSupportedPropertyIds_test.cpp
new file mode 100644
index 0000000..aa05daa
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/DefaultConfigSupportedPropertyIds_test.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 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 <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <vector>
+
+#include "vhal_v2_0/DefaultConfig.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+namespace impl {
+
+using ::testing::ElementsAreArray;
+
+// Test that VHAL_SUPPORTED_PROPERTY_IDS contains all supported property IDs.
+TEST(DefaultConfigSupportedPropertyIdsTest, testIncludeAllSupportedIds) {
+    const int32_t vhalSupportedPropertyIdsPropId = 289476424;
+
+    std::vector<int32_t> allSupportedIds;
+    std::vector<int32_t> configuredSupportedIds;
+
+    for (const auto& property : impl::kVehicleProperties) {
+        int propId = property.config.prop;
+        allSupportedIds.push_back(propId);
+
+        if (propId == vhalSupportedPropertyIdsPropId) {
+            configuredSupportedIds = property.initialValue.int32Values;
+        }
+    }
+
+    ASSERT_THAT(allSupportedIds, ElementsAreArray(configuredSupportedIds));
+}
+
+}  // namespace impl
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/DefaultVhalImpl_test.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/DefaultVhalImpl_test.cpp
index e3c8dd6..25a1940 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/DefaultVhalImpl_test.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/DefaultVhalImpl_test.cpp
@@ -141,7 +141,7 @@
 TEST_F(DefaultVhalImplTest, testListProperties) {
     std::vector<VehiclePropConfig> configs = mHal->listProperties();
 
-    EXPECT_EQ((size_t)121, configs.size());
+    EXPECT_EQ((size_t)123, configs.size());
 }
 
 TEST_F(DefaultVhalImplTest, testGetDefaultPropertyFloat) {
diff --git a/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h b/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h
index e00f775..9a93e1a 100644
--- a/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h
+++ b/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h
@@ -40,6 +40,7 @@
 using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReport;
 using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq;
 using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaMirror;
 using ::aidl::android::hardware::automotive::vehicle::VehicleAreaWindow;
 using ::aidl::android::hardware::automotive::vehicle::VehicleGear;
 using ::aidl::android::hardware::automotive::vehicle::VehicleHvacFanDirection;
@@ -124,6 +125,13 @@
 
         {.config =
                  {
+                         .prop = toInt(VehicleProperty::INFO_VIN),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::STATIC,
+                 },
+         .initialValue = {.stringValue = "1GCARVIN123456789"}},
+        {.config =
+                 {
                          .prop = toInt(VehicleProperty::INFO_MAKE),
                          .access = VehiclePropertyAccess::READ,
                          .changeMode = VehiclePropertyChangeMode::STATIC,
@@ -173,6 +181,523 @@
 
         {.config =
                  {
+                         .prop = toInt(VehicleProperty::EV_BATTERY_DISPLAY_UNITS),
+                         .access = VehiclePropertyAccess::READ_WRITE,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                         .configArray = {toInt(VehicleUnit::WATT_HOUR),
+                                         toInt(VehicleUnit::AMPERE_HOURS),
+                                         toInt(VehicleUnit::KILOWATT_HOUR)},
+                 },
+         .initialValue = {.int32Values = {toInt(VehicleUnit::KILOWATT_HOUR)}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_BELT_BUCKLED),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER}}},
+         .initialAreaValues = {{SEAT_1_LEFT, {.int32Values = {0}}},
+                               {SEAT_1_RIGHT, {.int32Values = {0}}},
+                               {SEAT_2_LEFT, {.int32Values = {0}}},
+                               {SEAT_2_RIGHT, {.int32Values = {0}}},
+                               {SEAT_2_CENTER, {.int32Values = {0}}}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_BELT_HEIGHT_POS),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10}}},
+         .initialAreaValues = {{SEAT_1_LEFT, {.int32Values = {10}}},
+                               {SEAT_1_RIGHT, {.int32Values = {10}}},
+                               {SEAT_2_LEFT, {.int32Values = {10}}},
+                               {SEAT_2_RIGHT, {.int32Values = {10}}},
+                               {SEAT_2_CENTER, {.int32Values = {10}}}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_BELT_HEIGHT_MOVE),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1}}},
+         .initialAreaValues = {{SEAT_1_LEFT, {.int32Values = {0}}},
+                               {SEAT_1_RIGHT, {.int32Values = {0}}},
+                               {SEAT_2_LEFT, {.int32Values = {0}}},
+                               {SEAT_2_RIGHT, {.int32Values = {0}}},
+                               {SEAT_2_CENTER, {.int32Values = {0}}}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_FORE_AFT_POS),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10}}},
+         .initialAreaValues = {{SEAT_1_LEFT, {.int32Values = {0}}},
+                               {SEAT_1_RIGHT, {.int32Values = {0}}},
+                               {SEAT_2_LEFT, {.int32Values = {0}}},
+                               {SEAT_2_RIGHT, {.int32Values = {0}}},
+                               {SEAT_2_CENTER, {.int32Values = {0}}}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_FORE_AFT_MOVE),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1}}},
+         .initialAreaValues = {{SEAT_1_LEFT, {.int32Values = {0}}},
+                               {SEAT_1_RIGHT, {.int32Values = {0}}},
+                               {SEAT_2_LEFT, {.int32Values = {0}}},
+                               {SEAT_2_RIGHT, {.int32Values = {0}}},
+                               {SEAT_2_CENTER, {.int32Values = {0}}}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_BACKREST_ANGLE_1_POS),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10}}},
+         .initialAreaValues = {{SEAT_1_LEFT, {.int32Values = {0}}},
+                               {SEAT_1_RIGHT, {.int32Values = {0}}},
+                               {SEAT_2_LEFT, {.int32Values = {0}}},
+                               {SEAT_2_RIGHT, {.int32Values = {0}}},
+                               {SEAT_2_CENTER, {.int32Values = {0}}}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_BACKREST_ANGLE_1_MOVE),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1}}},
+         .initialAreaValues = {{SEAT_1_LEFT, {.int32Values = {0}}},
+                               {SEAT_1_RIGHT, {.int32Values = {0}}},
+                               {SEAT_2_LEFT, {.int32Values = {0}}},
+                               {SEAT_2_RIGHT, {.int32Values = {0}}},
+                               {SEAT_2_CENTER, {.int32Values = {0}}}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_BACKREST_ANGLE_2_POS),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10}}},
+         .initialAreaValues = {{SEAT_1_LEFT, {.int32Values = {0}}},
+                               {SEAT_1_RIGHT, {.int32Values = {0}}},
+                               {SEAT_2_LEFT, {.int32Values = {0}}},
+                               {SEAT_2_RIGHT, {.int32Values = {0}}},
+                               {SEAT_2_CENTER, {.int32Values = {0}}}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_BACKREST_ANGLE_2_MOVE),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1}}},
+         .initialAreaValues = {{SEAT_1_LEFT, {.int32Values = {0}}},
+                               {SEAT_1_RIGHT, {.int32Values = {0}}},
+                               {SEAT_2_LEFT, {.int32Values = {0}}},
+                               {SEAT_2_RIGHT, {.int32Values = {0}}},
+                               {SEAT_2_CENTER, {.int32Values = {0}}}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_HEIGHT_POS),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_HEIGHT_MOVE),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_DEPTH_POS),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_DEPTH_MOVE),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_TILT_POS),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_TILT_MOVE),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_LUMBAR_FORE_AFT_POS),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = -10,
+                                                      .maxInt32Value = 10}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_LUMBAR_FORE_AFT_MOVE),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_LUMBAR_SIDE_SUPPORT_POS),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_LUMBAR_SIDE_SUPPORT_MOVE),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_HEADREST_HEIGHT_MOVE),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_HEADREST_ANGLE_POS),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_HEADREST_ANGLE_MOVE),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_HEADREST_FORE_AFT_POS),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = 0,
+                                                      .maxInt32Value = 10}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::SEAT_HEADREST_FORE_AFT_MOVE),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config =
+                 {
                          .prop = toInt(VehicleProperty::SEAT_OCCUPANCY),
                          .access = VehiclePropertyAccess::READ,
                          .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -352,8 +877,9 @@
                          .prop = toInt(VehicleProperty::VEHICLE_CURB_WEIGHT),
                          .access = VehiclePropertyAccess::READ,
                          .changeMode = VehiclePropertyChangeMode::STATIC,
+                         .configArray = {/*gross weight kg=*/2948},
                  },
-         .initialValue = {.int32Values = {30}}},
+         .initialValue = {.int32Values = {2211 /*kg*/}}},
 
         {.config =
                  {
@@ -460,6 +986,24 @@
 
         {.config =
                  {
+                         .prop = toInt(VehicleProperty::FUEL_VOLUME_DISPLAY_UNITS),
+                         .access = VehiclePropertyAccess::READ_WRITE,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                         .configArray = {(int)VehicleUnit::LITER, (int)VehicleUnit::US_GALLON},
+                 },
+         .initialValue = {.int32Values = {(int)VehicleUnit::LITER}}},
+
+        {.config =
+                 {
+                         .prop = toInt(
+                                 VehicleProperty::FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME),
+                         .access = VehiclePropertyAccess::READ_WRITE,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {1}}},
+
+        {.config =
+                 {
                          .prop = toInt(VehicleProperty::HW_KEY_INPUT),
                          .access = VehiclePropertyAccess::READ,
                          .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -486,6 +1030,12 @@
                          .int32Values = {0, 0, 0},
                  }},
 
+        {.config = {.prop = toInt(VehicleProperty::HVAC_ACTUAL_FAN_SPEED_RPM),
+                    .access = VehiclePropertyAccess::READ,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
+         .initialValue = {.int32Values = {50}}},
+
         {.config = {.prop = toInt(VehicleProperty::HVAC_POWER_ON),
                     .access = VehiclePropertyAccess::READ_WRITE,
                     .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -623,6 +1173,25 @@
                                     }}},
          .initialValue = {.int32Values = {0}}},  // +ve values for heating and -ve for cooling
 
+        {.config = {.prop = toInt(VehicleProperty::HVAC_SIDE_MIRROR_HEAT),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{
+                            .areaId = toInt(VehicleAreaMirror::DRIVER_LEFT) |
+                                      toInt(VehicleAreaMirror::DRIVER_RIGHT),
+                            .minInt32Value = 0,
+                            .maxInt32Value = 2,
+                    }}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_CURRENT),
+                    .access = VehiclePropertyAccess::READ,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_LEFT},
+                                    VehicleAreaConfig{.areaId = HVAC_RIGHT}}},
+         .initialAreaValues = {{HVAC_LEFT, {.floatValues = {17.3f}}},
+                               {HVAC_RIGHT, {.floatValues = {19.1f}}}}},
+
         {.config = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET),
                     .access = VehiclePropertyAccess::READ_WRITE,
                     .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -715,6 +1284,16 @@
 
         {.config =
                  {
+                         .prop = toInt(VehicleProperty::ENGINE_COOLANT_TEMP),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+                         .minSampleRate = 1.0f,
+                         .maxSampleRate = 10.0f,
+                 },
+         .initialValue = {.floatValues = {75.0f}}},
+
+        {.config =
+                 {
                          .prop = toInt(VehicleProperty::ENGINE_OIL_LEVEL),
                          .access = VehiclePropertyAccess::READ,
                          .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -774,6 +1353,76 @@
                                      .areaId = DOOR_REAR, .minInt32Value = 0, .maxInt32Value = 1}}},
          .initialValue = {.int32Values = {0}}},
 
+        {.config = {.prop = toInt(VehicleProperty::MIRROR_Z_POS),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs =
+                            {VehicleAreaConfig{.areaId = toInt(VehicleAreaMirror::DRIVER_LEFT),
+                                               .minInt32Value = -3,
+                                               .maxInt32Value = 3},
+                             VehicleAreaConfig{.areaId = toInt(VehicleAreaMirror::DRIVER_RIGHT),
+                                               .minInt32Value = -3,
+                                               .maxInt32Value = 3},
+                             VehicleAreaConfig{.areaId = toInt(VehicleAreaMirror::DRIVER_CENTER),
+                                               .minInt32Value = -3,
+                                               .maxInt32Value = 3}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::MIRROR_Z_MOVE),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs =
+                            {VehicleAreaConfig{.areaId = toInt(VehicleAreaMirror::DRIVER_LEFT),
+                                               .minInt32Value = -1,
+                                               .maxInt32Value = 1},
+                             VehicleAreaConfig{.areaId = toInt(VehicleAreaMirror::DRIVER_RIGHT),
+                                               .minInt32Value = -1,
+                                               .maxInt32Value = 1},
+                             VehicleAreaConfig{.areaId = toInt(VehicleAreaMirror::DRIVER_CENTER),
+                                               .minInt32Value = -1,
+                                               .maxInt32Value = 1}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::MIRROR_Y_POS),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs =
+                            {VehicleAreaConfig{.areaId = toInt(VehicleAreaMirror::DRIVER_LEFT),
+                                               .minInt32Value = -3,
+                                               .maxInt32Value = 3},
+                             VehicleAreaConfig{.areaId = toInt(VehicleAreaMirror::DRIVER_RIGHT),
+                                               .minInt32Value = -3,
+                                               .maxInt32Value = 3},
+                             VehicleAreaConfig{.areaId = toInt(VehicleAreaMirror::DRIVER_CENTER),
+                                               .minInt32Value = -3,
+                                               .maxInt32Value = 3}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::MIRROR_Y_MOVE),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs =
+                            {VehicleAreaConfig{.areaId = toInt(VehicleAreaMirror::DRIVER_LEFT),
+                                               .minInt32Value = -1,
+                                               .maxInt32Value = 1},
+                             VehicleAreaConfig{.areaId = toInt(VehicleAreaMirror::DRIVER_RIGHT),
+                                               .minInt32Value = -1,
+                                               .maxInt32Value = 1},
+                             VehicleAreaConfig{.areaId = toInt(VehicleAreaMirror::DRIVER_CENTER),
+                                               .minInt32Value = -1,
+                                               .maxInt32Value = 1}}},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::MIRROR_LOCK),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
+         .initialValue = {.int32Values = {1}}},
+
+        {.config = {.prop = toInt(VehicleProperty::MIRROR_FOLD),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
+         .initialValue = {.int32Values = {1}}},
+
         {.config = {.prop = toInt(VehicleProperty::WINDOW_LOCK),
                     .access = VehiclePropertyAccess::READ_WRITE,
                     .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -802,6 +1451,26 @@
                                                       .maxInt32Value = 10}}},
          .initialValue = {.int32Values = {0}}},
 
+        {.config = {.prop = toInt(VehicleProperty::WINDOW_MOVE),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = WINDOW_1_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = WINDOW_1_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = WINDOW_2_LEFT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = WINDOW_2_RIGHT,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1},
+                                    VehicleAreaConfig{.areaId = WINDOW_ROOF_TOP_1,
+                                                      .minInt32Value = -1,
+                                                      .maxInt32Value = 1}}},
+         .initialValue = {.int32Values = {0}}},
+
         {.config =
                  {
                          .prop = WHEEL_TICK,
@@ -884,14 +1553,6 @@
 
         {.config =
                  {
-                         .prop = toInt(VehicleProperty::FOG_LIGHTS_STATE),
-                         .access = VehiclePropertyAccess::READ,
-                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-                 },
-         .initialValue = {.int32Values = {LIGHT_STATE_ON}}},
-
-        {.config =
-                 {
                          .prop = toInt(VehicleProperty::FRONT_FOG_LIGHTS_STATE),
                          .access = VehiclePropertyAccess::READ,
                          .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -916,6 +1577,24 @@
 
         {.config =
                  {
+                         .prop = toInt(VehicleProperty::CABIN_LIGHTS_STATE),
+                         .access = VehiclePropertyAccess::READ,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {LIGHT_STATE_ON}}},
+
+        {.config = {.prop = toInt(VehicleProperty::READING_LIGHTS_STATE),
+                    .access = VehiclePropertyAccess::READ,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER}}},
+         .initialValue = {.int32Values = {LIGHT_STATE_ON}}},
+
+        {.config =
+                 {
                          .prop = toInt(VehicleProperty::HEADLIGHTS_SWITCH),
                          .access = VehiclePropertyAccess::READ_WRITE,
                          .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -930,14 +1609,7 @@
                  },
          .initialValue = {.int32Values = {LIGHT_SWITCH_AUTO}}},
 
-        {.config =
-                 {
-                         .prop = toInt(VehicleProperty::FOG_LIGHTS_SWITCH),
-                         .access = VehiclePropertyAccess::READ_WRITE,
-                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-                 },
-         .initialValue = {.int32Values = {LIGHT_SWITCH_AUTO}}},
-
+        // FOG_LIGHTS_SWITCH must not be implemented when FRONT_FOG_LIGHTS_SWITCH is implemented
         {.config =
                  {
                          .prop = toInt(VehicleProperty::FRONT_FOG_LIGHTS_SWITCH),
@@ -946,6 +1618,7 @@
                  },
          .initialValue = {.int32Values = {LIGHT_SWITCH_AUTO}}},
 
+        // FOG_LIGHTS_SWITCH must not be implemented when REAR_FOG_LIGHTS_SWITCH is implemented
         {.config =
                  {
                          .prop = toInt(VehicleProperty::REAR_FOG_LIGHTS_SWITCH),
@@ -964,6 +1637,24 @@
 
         {.config =
                  {
+                         .prop = toInt(VehicleProperty::CABIN_LIGHTS_SWITCH),
+                         .access = VehiclePropertyAccess::READ_WRITE,
+                         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                 },
+         .initialValue = {.int32Values = {LIGHT_STATE_ON}}},
+
+        {.config = {.prop = toInt(VehicleProperty::READING_LIGHTS_SWITCH),
+                    .access = VehiclePropertyAccess::READ_WRITE,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                    .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT},
+                                    VehicleAreaConfig{.areaId = SEAT_1_RIGHT},
+                                    VehicleAreaConfig{.areaId = SEAT_2_LEFT},
+                                    VehicleAreaConfig{.areaId = SEAT_2_RIGHT},
+                                    VehicleAreaConfig{.areaId = SEAT_2_CENTER}}},
+         .initialValue = {.int32Values = {LIGHT_STATE_ON}}},
+
+        {.config =
+                 {
                          .prop = toInt(VehicleProperty::EVS_SERVICE_REQUEST),
                          .access = VehiclePropertyAccess::READ,
                          .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
index b64c1a6..20c34aa 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -217,17 +217,16 @@
             [[fallthrough]];
         case toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL):
             // CPMS is in WAIT_FOR_VHAL state, simply move to ON and send back to HAL.
-            // Must erase existing state because in the case when Car Service crashes, the power
-            // state would already be ON when we receive WAIT_FOR_VHAL and thus new property change
-            // event would be generated. However, Car Service always expect a property change event
-            // even though there is not actual state change.
-            mServerSidePropStore->removeValuesForProperty(
-                    toInt(VehicleProperty::AP_POWER_STATE_REQ));
             prop = createApPowerStateReq(VehicleApPowerStateReq::ON);
 
-            // ALWAYS update status for generated property value
+            // ALWAYS update status for generated property value, and force a property update event
+            // because in the case when Car Service crashes, the power state would already be ON
+            // when we receive WAIT_FOR_VHAL and thus new property change event would be generated.
+            // However, Car Service always expect a property change event even though there is no
+            // actual state change.
             if (auto writeResult =
-                        mServerSidePropStore->writeValue(std::move(prop), /*updateStatus=*/true);
+                        mServerSidePropStore->writeValue(std::move(prop), /*updateStatus=*/true,
+                                                         VehiclePropertyStore::EventMode::ALWAYS);
                 !writeResult.ok()) {
                 return StatusError(getErrorCode(writeResult))
                        << "failed to write AP_POWER_STATE_REQ into property store, error: "
@@ -894,10 +893,10 @@
             return;
         }
         result.value()->timestamp = elapsedRealtimeNano();
-        // Must remove the value before writing, otherwise, we would generate no update event since
-        // the value is the same.
-        mServerSidePropStore->removeValue(*result.value());
-        mServerSidePropStore->writeValue(std::move(result.value()));
+        // For continuous properties, we must generate a new onPropertyChange event periodically
+        // according to the sample rate.
+        mServerSidePropStore->writeValue(std::move(result.value()), /*updateStatus=*/true,
+                                         VehiclePropertyStore::EventMode::ALWAYS);
     });
     mRecurrentTimer->registerTimerCallback(interval, action);
     mRecurrentActions[propIdAreaId] = action;
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h
index a7fcdcf..8bc3c20 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h
@@ -42,6 +42,7 @@
 #include <aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReq.h>
 #include <aidl/android/hardware/automotive/vehicle/VehicleArea.h>
 #include <aidl/android/hardware/automotive/vehicle/VehicleAreaDoor.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleAreaMirror.h>
 #include <aidl/android/hardware/automotive/vehicle/VehicleAreaSeat.h>
 #include <aidl/android/hardware/automotive/vehicle/VehicleAreaWheel.h>
 #include <aidl/android/hardware/automotive/vehicle/VehicleAreaWindow.h>
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehiclePropertyStore.h b/automotive/vehicle/aidl/impl/utils/common/include/VehiclePropertyStore.h
index ddc4f68..3d25cd3 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehiclePropertyStore.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehiclePropertyStore.h
@@ -46,6 +46,33 @@
     using ValueResultType = VhalResult<VehiclePropValuePool::RecyclableType>;
     using ValuesResultType = VhalResult<std::vector<VehiclePropValuePool::RecyclableType>>;
 
+    enum class EventMode : uint8_t {
+        /**
+         * Only invoke OnValueChangeCallback if the new property value (ignoring timestamp) is
+         * different than the existing value.
+         *
+         * This should be used for regular cases.
+         */
+        ON_VALUE_CHANGE,
+        /**
+         * Always invoke OnValueChangeCallback.
+         *
+         * This should be used for the special properties that are used for delivering event, e.g.
+         * HW_KEY_INPUT.
+         */
+        ALWAYS,
+        /**
+         * Never invoke OnValueChangeCallback.
+         *
+         * This should be used for continuous property subscription when the sample rate for the
+         * subscription is smaller than the refresh rate for the property. E.g., the vehicle speed
+         * is refreshed at 20hz, but we are only subscribing at 10hz. In this case, we want to
+         * generate the property change event at 10hz, not 20hz, but we still want to refresh the
+         * timestamp (via writeValue) at 20hz.
+         */
+        NEVER,
+    };
+
     explicit VehiclePropertyStore(std::shared_ptr<VehiclePropValuePool> valuePool)
         : mValuePool(valuePool) {}
 
@@ -72,8 +99,10 @@
     // 'status' would be initialized to {@code VehiclePropertyStatus::AVAILABLE}, if this is to
     // override an existing value, the status for the existing value would be used for the
     // overridden value.
+    // 'EventMode' controls whether the 'OnValueChangeCallback' will be called for this operation.
     VhalResult<void> writeValue(VehiclePropValuePool::RecyclableType propValue,
-                                bool updateStatus = false);
+                                bool updateStatus = false,
+                                EventMode mode = EventMode::ON_VALUE_CHANGE);
 
     // Remove a given property value from the property store. The 'propValue' would be used to
     // generate the key for the value to remove.
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp b/automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp
index 8521c4d..2eca6b7 100644
--- a/automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp
@@ -48,7 +48,7 @@
         std::scoped_lock<std::mutex> lockGuard(mLock);
 
         // Aligns the nextTime to multiply of interval.
-        int64_t nextTime = ceil(elapsedRealtimeNano() / intervalInNano) * intervalInNano;
+        int64_t nextTime = ceil(uptimeNanos() / intervalInNano) * intervalInNano;
 
         std::unique_ptr<CallbackInfo> info = std::make_unique<CallbackInfo>();
         info->callback = callback;
@@ -128,7 +128,7 @@
             }
             // The first element is the nearest next event.
             int64_t nextTime = mCallbackQueue[0]->nextTime;
-            int64_t now = elapsedRealtimeNano();
+            int64_t now = uptimeNanos();
             if (nextTime > now) {
                 interval = nextTime - now;
             } else {
@@ -146,7 +146,7 @@
 
         {
             ScopedLockAssertion lockAssertion(mLock);
-            int64_t now = elapsedRealtimeNano();
+            int64_t now = uptimeNanos();
             while (mCallbackQueue.size() > 0) {
                 int64_t nextTime = mCallbackQueue[0]->nextTime;
                 if (nextTime > now) {
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp b/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
index c8fb994..646dc0e 100644
--- a/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
@@ -106,7 +106,8 @@
 }
 
 VhalResult<void> VehiclePropertyStore::writeValue(VehiclePropValuePool::RecyclableType propValue,
-                                                  bool updateStatus) {
+                                                  bool updateStatus,
+                                                  VehiclePropertyStore::EventMode eventMode) {
     std::scoped_lock<std::mutex> g(mLock);
 
     int32_t propId = propValue->prop;
@@ -145,7 +146,12 @@
     }
 
     record->values[recId] = std::move(propValue);
-    if (valueUpdated && mOnValueChangeCallback != nullptr) {
+
+    if (eventMode == EventMode::NEVER) {
+        return {};
+    }
+
+    if ((eventMode == EventMode::ALWAYS || valueUpdated) && mOnValueChangeCallback != nullptr) {
         mOnValueChangeCallback(*(record->values[recId]));
     }
     return {};
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/VehiclePropertyStoreTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/VehiclePropertyStoreTest.cpp
index 4d6f811..fea5034 100644
--- a/automotive/vehicle/aidl/impl/utils/common/test/VehiclePropertyStoreTest.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/test/VehiclePropertyStoreTest.cpp
@@ -448,6 +448,67 @@
     ASSERT_EQ(updatedValue.prop, INVALID_PROP_ID);
 }
 
+TEST_F(VehiclePropertyStoreTest, testPropertyChangeCallbackNoUpdateForTimestampChange) {
+    VehiclePropValue updatedValue{
+            .prop = INVALID_PROP_ID,
+    };
+    VehiclePropValue fuelCapacity = {
+            .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+            .value = {.floatValues = {1.0}},
+    };
+    ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity)));
+
+    mStore->setOnValueChangeCallback(
+            [&updatedValue](const VehiclePropValue& value) { updatedValue = value; });
+
+    // Write the same value with different timestamp should succeed but should not trigger callback.
+    fuelCapacity.timestamp = 1;
+    ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity)));
+
+    ASSERT_EQ(updatedValue.prop, INVALID_PROP_ID);
+}
+
+TEST_F(VehiclePropertyStoreTest, testPropertyChangeCallbackForceUpdate) {
+    VehiclePropValue updatedValue{
+            .prop = INVALID_PROP_ID,
+    };
+    VehiclePropValue fuelCapacity = {
+            .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+            .value = {.floatValues = {1.0}},
+    };
+    ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity)));
+
+    mStore->setOnValueChangeCallback(
+            [&updatedValue](const VehiclePropValue& value) { updatedValue = value; });
+
+    fuelCapacity.timestamp = 1;
+    ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity), /*updateStatus=*/false,
+                                        VehiclePropertyStore::EventMode::ALWAYS));
+
+    ASSERT_EQ(updatedValue, fuelCapacity);
+}
+
+TEST_F(VehiclePropertyStoreTest, testPropertyChangeCallbackForceNoUpdate) {
+    VehiclePropValue updatedValue{
+            .prop = INVALID_PROP_ID,
+    };
+    VehiclePropValue fuelCapacity = {
+            .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+            .value = {.floatValues = {1.0}},
+    };
+    ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity)));
+
+    mStore->setOnValueChangeCallback(
+            [&updatedValue](const VehiclePropValue& value) { updatedValue = value; });
+    fuelCapacity.value.floatValues[0] = 2.0;
+    fuelCapacity.timestamp = 1;
+
+    ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity), /*updateStatus=*/false,
+                                        VehiclePropertyStore::EventMode::NEVER));
+
+    ASSERT_EQ(updatedValue.prop, INVALID_PROP_ID);
+}
+
 }  // namespace vehicle
 }  // namespace automotive
 }  // namespace hardware
diff --git a/contexthub/aidl/default/ContextHub.cpp b/contexthub/aidl/default/ContextHub.cpp
index 4c23cbc..35e4650 100644
--- a/contexthub/aidl/default/ContextHub.cpp
+++ b/contexthub/aidl/default/ContextHub.cpp
@@ -107,10 +107,9 @@
 ScopedAStatus ContextHub::onHostEndpointDisconnected(char16_t in_hostEndpointId) {
     if (mConnectedHostEndpoints.count(in_hostEndpointId) > 0) {
         mConnectedHostEndpoints.erase(in_hostEndpointId);
-        return ndk::ScopedAStatus::ok();
-    } else {
-        return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_ILLEGAL_ARGUMENT));
     }
+
+    return ndk::ScopedAStatus::ok();
 }
 
 }  // namespace contexthub
diff --git a/dumpstate/aidl/Android.bp b/dumpstate/aidl/Android.bp
index 63670bb..1eb8b32 100644
--- a/dumpstate/aidl/Android.bp
+++ b/dumpstate/aidl/Android.bp
@@ -31,7 +31,8 @@
             enabled: false,
         },
         java: {
-            enabled: false,
+            enabled: true,
+            sdk_version: "module_current",
         },
     },
     versions_with_info: [
diff --git a/vibrator/aidl/default/Vibrator.cpp b/vibrator/aidl/default/Vibrator.cpp
index ddc6ee0..01602ab 100644
--- a/vibrator/aidl/default/Vibrator.cpp
+++ b/vibrator/aidl/default/Vibrator.cpp
@@ -59,7 +59,10 @@
                                 const std::shared_ptr<IVibratorCallback>& callback) {
     LOG(VERBOSE) << "Vibrator on for timeoutMs: " << timeoutMs;
     if (callback != nullptr) {
-        std::thread([=] {
+        // Note that thread lambdas aren't using implicit capture [=], to avoid capturing "this",
+        // which may be asynchronously destructed.
+        // If "this" is needed, use [sharedThis = this->ref<Vibrator>()].
+        std::thread([timeoutMs, callback] {
             LOG(VERBOSE) << "Starting on on another thread";
             usleep(timeoutMs * 1000);
             LOG(VERBOSE) << "Notifying on complete";
@@ -87,7 +90,7 @@
     constexpr size_t kEffectMillis = 100;
 
     if (callback != nullptr) {
-        std::thread([=] {
+        std::thread([callback] {
             LOG(VERBOSE) << "Starting perform on another thread";
             usleep(kEffectMillis * 1000);
             LOG(VERBOSE) << "Notifying perform complete";
@@ -174,7 +177,8 @@
         }
     }
 
-    std::thread([=] {
+    // The thread may theoretically outlive the vibrator, so take a proper reference to it.
+    std::thread([sharedThis = this->ref<Vibrator>(), composite, callback] {
         LOG(VERBOSE) << "Starting compose on another thread";
 
         for (auto& e : composite) {
@@ -185,7 +189,7 @@
                          << e.scale;
 
             int32_t durationMs;
-            getPrimitiveDuration(e.primitive, &durationMs);
+            sharedThis->getPrimitiveDuration(e.primitive, &durationMs);
             usleep(durationMs * 1000);
         }
 
@@ -396,7 +400,7 @@
         }
     }
 
-    std::thread([=] {
+    std::thread([totalDuration, callback] {
         LOG(VERBOSE) << "Starting composePwle on another thread";
         usleep(totalDuration * 1000);
         if (callback != nullptr) {
diff --git a/vibrator/aidl/default/VibratorManager.cpp b/vibrator/aidl/default/VibratorManager.cpp
index 7cf9e6a..26edf5a 100644
--- a/vibrator/aidl/default/VibratorManager.cpp
+++ b/vibrator/aidl/default/VibratorManager.cpp
@@ -66,7 +66,7 @@
 ndk::ScopedAStatus VibratorManager::triggerSynced(
         const std::shared_ptr<IVibratorCallback>& callback) {
     LOG(INFO) << "Vibrator Manager trigger synced";
-    std::thread([=] {
+    std::thread([callback] {
         if (callback != nullptr) {
             LOG(INFO) << "Notifying perform complete";
             callback->onComplete();