Support vendor override in default VHAL.

Move vendor override property logic from emulated VHAL to
default VHAL. If system property
"persist.vendor.vhal_init_value_override" is set, then we would
try to parse JSON files in "/vendor/etc/vhaloverride/" and use the
values there to override the default initial values.

Test: unit test
Bug: 193831021
Change-Id: I6823aab3de284d5b1d96186bc9f1325d868fd8d6
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index 2e8ca66..3be460c 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -144,7 +144,6 @@
     ],
     whole_static_libs: [
         "android.hardware.automotive.vehicle@2.0-server-common-lib",
-        "android.hardware.automotive.vehicle@2.0-user-hal-helper-lib",
     ],
     static_libs: [
         "android.hardware.automotive.vehicle@2.0-libproto-native",
@@ -213,7 +212,10 @@
         "android.hardware.automotive.vehicle@2.0-default-impl-lib",
         "android.hardware.automotive.vehicle@2.0-libproto-native",
     ],
-    data: [":vhal_test_json"],
+    data: [
+        ":vhal_test_override_json",
+        ":vhal_test_json",
+    ],
     test_suites: ["general-tests"],
 }
 
diff --git a/automotive/vehicle/2.0/default/VehicleService.cpp b/automotive/vehicle/2.0/default/VehicleService.cpp
index ba2a606..fae6e43 100644
--- a/automotive/vehicle/2.0/default/VehicleService.cpp
+++ b/automotive/vehicle/2.0/default/VehicleService.cpp
@@ -20,7 +20,6 @@
 
 #include <iostream>
 
-#include <EmulatedUserHal.h>
 #include <EmulatedVehicleConnector.h>
 #include <EmulatedVehicleHal.h>
 #include <vhal_v2_0/VehicleHalManager.h>
@@ -32,8 +31,7 @@
 int main(int /* argc */, char* /* argv */ []) {
     auto store = std::make_unique<VehiclePropertyStore>();
     auto connector = std::make_unique<impl::EmulatedVehicleConnector>();
-    auto userHal = connector->getEmulatedUserHal();
-    auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get(), connector.get(), userHal);
+    auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get(), connector.get());
     auto emulator = connector->getEmulator();
     auto service = std::make_unique<VehicleHalManager>(hal.get());
     connector->setValuePool(hal->getValuePool());
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp
index 1b37cbd..51ba6fd 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp
@@ -17,10 +17,13 @@
 
 #include <android-base/chrono_utils.h>
 #include <assert.h>
+#include <stdio.h>
 #include <utils/Log.h>
 #include <utils/SystemClock.h>
 #include <vhal_v2_0/RecurrentTimer.h>
+#include <unordered_set>
 
+#include "PropertyUtils.h"
 #include "VehicleUtils.h"
 
 #include "DefaultVehicleHal.h"
@@ -52,8 +55,30 @@
     }
     return nullptr;
 }
+
+VehicleHal::VehiclePropValuePtr addTimestamp(VehicleHal::VehiclePropValuePtr v) {
+    if (v.get()) {
+        v->timestamp = elapsedRealtimeNano();
+    }
+    return v;
+}
+
+bool isDebugProperty(int propId) {
+    return (propId == kGenerateFakeDataControllingProperty ||
+            propId == kSetIntPropertyFromVehicleForTest ||
+            propId == kSetFloatPropertyFromVehicleForTest ||
+            propId == kSetBooleanPropertyFromVehicleForTest);
+}
 }  // namespace
 
+VehicleHal::VehiclePropValuePtr DefaultVehicleHal::createVhalHeartBeatProp() {
+    VehicleHal::VehiclePropValuePtr v = getValuePool()->obtainInt64(uptimeMillis());
+    v->prop = static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT);
+    v->areaId = 0;
+    v->status = VehiclePropertyStatus::AVAILABLE;
+    return v;
+}
+
 DefaultVehicleHal::DefaultVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client)
     : mPropStore(propStore), mRecurrentTimer(getTimerAction()), mVehicleClient(client) {
     initStaticConfig();
@@ -69,6 +94,7 @@
     ALOGV("get(%d)", propId);
 
     VehiclePropValuePtr v = nullptr;
+
     auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue);
     if (internalPropValue != nullptr) {
         v = getValuePool()->obtain(*internalPropValue);
@@ -81,10 +107,7 @@
     } else {
         *outStatus = StatusCode::TRY_AGAIN;
     }
-    if (v.get()) {
-        v->timestamp = elapsedRealtimeNano();
-    }
-    return v;
+    return addTimestamp(std::move(v));
 }
 
 std::vector<VehiclePropConfig> DefaultVehicleHal::listProperties() {
@@ -258,6 +281,32 @@
         return StatusCode::INVALID_ARG;
     }
 
+    std::unordered_set<int32_t> powerProps(std::begin(kHvacPowerProperties),
+                                           std::end(kHvacPowerProperties));
+    if (powerProps.count(propValue.prop)) {
+        auto hvacPowerOn = mPropStore->readValueOrNull(
+                toInt(VehicleProperty::HVAC_POWER_ON),
+                (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT |
+                 VehicleAreaSeat::ROW_2_LEFT | VehicleAreaSeat::ROW_2_CENTER |
+                 VehicleAreaSeat::ROW_2_RIGHT));
+
+        if (hvacPowerOn && hvacPowerOn->value.int32Values.size() == 1 &&
+            hvacPowerOn->value.int32Values[0] == 0) {
+            return StatusCode::NOT_AVAILABLE;
+        }
+    }
+
+    if (propValue.prop == VEHICLE_MAP_SERVICE) {
+        // Placeholder for future implementation of VMS property in the default hal. For
+        // now, just returns OK; otherwise, hal clients crash with property not supported.
+        return StatusCode::OK;
+    }
+    if (isDebugProperty(propValue.prop)) {
+        // These are special debug properties and do not need a config or check.
+        // TODO(shanyu): Remove this after we remove debug properties.
+        return mVehicleClient->setProperty(propValue, /*updateStatus=*/false);
+    }
+
     int32_t property = propValue.prop;
     const VehiclePropConfig* config = mPropStore->getConfigOrNull(property);
     if (config == nullptr) {
@@ -298,7 +347,7 @@
     auto configs = mVehicleClient->getAllPropertyConfig();
 
     for (const auto& cfg : configs) {
-        int32_t numAreas = isGlobalProp(cfg.prop) ? 0 : cfg.areaConfigs.size();
+        int32_t numAreas = isGlobalProp(cfg.prop) ? 1 : cfg.areaConfigs.size();
 
         for (int i = 0; i < numAreas; i++) {
             int32_t curArea = isGlobalProp(cfg.prop) ? 0 : cfg.areaConfigs[i].areaId;
@@ -315,6 +364,7 @@
     }
 
     mVehicleClient->triggerSendAllValues();
+
     registerHeartBeatEvent();
 }
 
@@ -344,14 +394,6 @@
     return v;
 }
 
-VehicleHal::VehiclePropValuePtr DefaultVehicleHal::createVhalHeartBeatProp() {
-    VehicleHal::VehiclePropValuePtr v = getValuePool()->obtainInt64(uptimeMillis());
-    v->prop = static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT);
-    v->areaId = 0;
-    v->status = VehiclePropertyStatus::AVAILABLE;
-    return v;
-}
-
 void DefaultVehicleHal::onContinuousPropertyTimer(const std::vector<int32_t>& properties) {
     auto& pool = *getValuePool();
 
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h
index af29143..027dc85 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h
@@ -19,7 +19,7 @@
 
 #include <vhal_v2_0/RecurrentTimer.h>
 #include <vhal_v2_0/VehicleHal.h>
-#include "vhal_v2_0/VehiclePropertyStore.h"
+#include <vhal_v2_0/VehiclePropertyStore.h>
 
 #include "VehicleHalClient.h"
 
@@ -55,10 +55,20 @@
     VehiclePropertyStore* mPropStore;
     RecurrentTimer mRecurrentTimer;
     VehicleHalClient* mVehicleClient;
-    virtual bool isContinuousProperty(int32_t propId) const;
-    virtual void initStaticConfig();
-    virtual void onContinuousPropertyTimer(const std::vector<int32_t>& properties);
+
+    // The callback that would be called when a property value is updated. This function could
+    // be extended to handle specific property update event.
     virtual void onPropertyValue(const VehiclePropValue& value, bool updateStatus);
+    // Do an internal health check, vendor should add health check logic in this function.
+    virtual VehicleHal::VehiclePropValuePtr doInternalHealthCheck();
+
+    // The callback that would be called for every event generated by 'subscribe' or heartbeat.
+    // Properties contains a list of properties that need to be handled.
+    void onContinuousPropertyTimer(const std::vector<int32_t>& properties);
+    // Initiate config for all properties, would be called during onCreate().
+    void initStaticConfig();
+    // Whether the property is a continuous property.
+    bool isContinuousProperty(int32_t propId) const;
     // Returns a lambda that could be used in mRecurrentTimer.
     RecurrentTimer::Action getTimerAction();
     // Check whether a propValue is valid according to its type.
@@ -69,8 +79,7 @@
     // Register the heart beat event to be sent every 3s. This is required to inform watch dog that
     // VHAL is alive. Subclasses should always calls this function during onCreate.
     void registerHeartBeatEvent();
-
-    VehicleHal::VehiclePropValuePtr doInternalHealthCheck();
+    // Create a VHAL heart beat property.
     VehicleHal::VehiclePropValuePtr createVhalHeartBeatProp();
 
   private:
@@ -78,6 +87,8 @@
     // See 'VehiclePropertyType' documentation in 'types.hal' for detail.
     StatusCode checkVendorMixedPropValue(const VehiclePropValue& value,
                                          const VehiclePropConfig* config);
+    // Read the override properties from a config file.
+    void getAllPropertiesOverride();
 };
 
 }  // namespace impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.cpp
index f61a93b..595a1d1 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.cpp
@@ -17,11 +17,13 @@
 #define LOG_TAG "DefaultVehicleHalServer"
 
 #include <fstream>
+#include <regex>
 
 #include <android-base/format.h>
 #include <android-base/logging.h>
 #include <android-base/parsedouble.h>
 #include <android-base/parseint.h>
+#include <android-base/properties.h>
 #include <utils/SystemClock.h>
 
 #include "DefaultConfig.h"
@@ -38,6 +40,10 @@
 
 namespace impl {
 
+namespace {
+const char* VENDOR_OVERRIDE_DIR = "/vendor/etc/vhaloverride/";
+}  // namespace
+
 void DefaultVehicleHalServer::storePropInitialValue(const ConfigDeclaration& config) {
     VehiclePropConfig cfg = config.config;
 
@@ -74,6 +80,7 @@
         mServerSidePropStore.registerProperty(cfg);
         storePropInitialValue(it);
     }
+    maybeOverrideProperties(VENDOR_OVERRIDE_DIR);
 }
 
 void DefaultVehicleHalServer::sendAllValuesToClient() {
@@ -559,6 +566,32 @@
     return result;
 }
 
+void DefaultVehicleHalServer::maybeOverrideProperties(const char* overrideDir) {
+    if (android::base::GetBoolProperty("persist.vendor.vhal_init_value_override", false)) {
+        overrideProperties(overrideDir);
+    }
+}
+
+void DefaultVehicleHalServer::overrideProperties(const char* overrideDir) {
+    LOG(INFO) << "loading vendor override properties from " << overrideDir;
+    if (auto dir = opendir(overrideDir)) {
+        std::regex reg_json(".*[.]json", std::regex::icase);
+        while (auto f = readdir(dir)) {
+            if (!regex_match(f->d_name, reg_json)) {
+                continue;
+            }
+            std::string file = overrideDir + std::string(f->d_name);
+            JsonFakeValueGenerator tmpGenerator(file);
+
+            std::vector<VehiclePropValue> propValues = tmpGenerator.getAllEvents();
+            for (const VehiclePropValue& prop : propValues) {
+                mServerSidePropStore.writeValue(prop, true);
+            }
+        }
+        closedir(dir);
+    }
+}
+
 }  // namespace impl
 
 }  // namespace V2_0
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.h
index aa6cf0b..5858325 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.h
@@ -72,6 +72,10 @@
     std::string getHelpInfo();
 
     DumpResult genFakeData(const std::vector<std::string>& options);
+    // If "persist.vendor.vhal_init_value_override" is true, try to override the properties default
+    // values according to JSON files in 'overrideDir'. Would be called in constructor using
+    // VENDOR_OVERRIDE_DIR as overrideDir.
+    void maybeOverrideProperties(const char* overrideDir);
 
   protected:
     GeneratorHub mGeneratorHub{
@@ -79,6 +83,12 @@
 
     VehiclePropValuePool* mValuePool{nullptr};
     VehiclePropertyStore mServerSidePropStore;
+
+  private:
+    // Expose protected methods to unit test.
+    friend class DefaultVhalImplTestHelper;
+    // Override the properties using config files in 'overrideDir'.
+    void overrideProperties(const char* overrideDir);
 };
 
 }  // namespace impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/Android.bp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/Android.bp
index 5762223..a7d5440 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/Android.bp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/Android.bp
@@ -16,3 +16,8 @@
     name: "vhal_test_json",
     srcs: ["prop.json"],
 }
+
+filegroup {
+    name: "vhal_test_override_json",
+    srcs: ["override/*"],
+}
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 891d8d6..4fb74f6 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
@@ -27,6 +27,32 @@
 #include <vhal_v2_0/VehicleObjectPool.h>
 #include <vhal_v2_0/VehiclePropertyStore.h>
 
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+namespace impl {
+
+class DefaultVhalImplTestHelper {
+  public:
+    DefaultVhalImplTestHelper(DefaultVehicleHalServer* server) { mServer = server; }
+
+    void overrideProperties(const char* overrideDir) {
+        mServer->overrideProperties(overrideDir);
+    }
+
+  private:
+    DefaultVehicleHalServer* mServer;
+};
+
+}  // namespace impl
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
 namespace {
 
 using ::android::hardware::hidl_handle;
@@ -44,9 +70,15 @@
 using ::android::hardware::automotive::vehicle::V2_0::VehiclePropValuePool;
 using ::android::hardware::automotive::vehicle::V2_0::impl::DefaultVehicleConnector;
 using ::android::hardware::automotive::vehicle::V2_0::impl::DefaultVehicleHal;
+using ::android::hardware::automotive::vehicle::V2_0::impl::DefaultVhalImplTestHelper;
 using ::android::hardware::automotive::vehicle::V2_0::impl::HVAC_ALL;
 using ::android::hardware::automotive::vehicle::V2_0::impl::HVAC_LEFT;
+using ::android::hardware::automotive::vehicle::V2_0::impl::HVAC_RIGHT;
 using ::android::hardware::automotive::vehicle::V2_0::impl::kMixedTypePropertyForTest;
+using ::android::hardware::automotive::vehicle::V2_0::impl::OBD2_FREEZE_FRAME;
+using ::android::hardware::automotive::vehicle::V2_0::impl::OBD2_FREEZE_FRAME_CLEAR;
+using ::android::hardware::automotive::vehicle::V2_0::impl::OBD2_FREEZE_FRAME_INFO;
+using ::android::hardware::automotive::vehicle::V2_0::impl::OBD2_LIVE_FRAME;
 
 using ::testing::HasSubstr;
 
@@ -72,12 +104,24 @@
         mConnector.reset(new DefaultVehicleConnector);
         mConnector->setValuePool(&mValueObjectPool);
         mHal.reset(new DefaultVehicleHal(mPropStore.get(), mConnector.get()));
+        initHal();
+    }
+
+    void initHal() {
         mHal->init(&mValueObjectPool,
                    std::bind(&DefaultVhalImplTest::onHalEvent, this, std::placeholders::_1),
                    std::bind(&DefaultVhalImplTest::onHalPropertySetError, this,
                              std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
     }
 
+  protected:
+    std::unique_ptr<DefaultVehicleHal> mHal;
+    std::unique_ptr<DefaultVehicleConnector> mConnector;
+    std::unique_ptr<VehiclePropertyStore> mPropStore;
+    VehiclePropValuePool mValueObjectPool;
+    android::ConcurrentQueue<VehiclePropValuePtr> mEventQueue;
+    android::ConcurrentQueue<VehiclePropValuePtr> mHeartBeatQueue;
+
   private:
     void onHalEvent(VehiclePropValuePtr v) {
         if (v->prop != toInt(VehicleProperty::VHAL_HEARTBEAT)) {
@@ -90,14 +134,6 @@
 
     void onHalPropertySetError(StatusCode /*errorCode*/, int32_t /*property*/, int32_t /*areaId*/) {
     }
-
-  protected:
-    std::unique_ptr<DefaultVehicleHal> mHal;
-    std::unique_ptr<DefaultVehicleConnector> mConnector;
-    std::unique_ptr<VehiclePropertyStore> mPropStore;
-    VehiclePropValuePool mValueObjectPool;
-    android::ConcurrentQueue<VehiclePropValuePtr> mEventQueue;
-    android::ConcurrentQueue<VehiclePropValuePtr> mHeartBeatQueue;
 };
 
 TEST_F(DefaultVhalImplTest, testListProperties) {
@@ -721,12 +757,12 @@
     EXPECT_EQ((size_t)1, events[0]->value.int32Values.size());
     EXPECT_EQ(8, events[0]->value.int32Values[0]);
     EXPECT_EQ((size_t)1, events[3]->value.int32Values.size());
-    EXPECT_EQ(4, events[3]->value.int32Values[0]);
+    EXPECT_EQ(10, events[3]->value.int32Values[0]);
     // Second set of the same events.
     EXPECT_EQ((size_t)1, events[4]->value.int32Values.size());
     EXPECT_EQ(8, events[4]->value.int32Values[0]);
     EXPECT_EQ((size_t)1, events[7]->value.int32Values.size());
-    EXPECT_EQ(4, events[7]->value.int32Values[0]);
+    EXPECT_EQ(10, events[7]->value.int32Values[0]);
 }
 
 TEST_F(DefaultVhalImplTest, testDebugGenFakeDataKeyPress) {
@@ -768,4 +804,106 @@
     ASSERT_EQ(toInt(VehicleProperty::VHAL_HEARTBEAT), events[0]->prop);
 }
 
+TEST_F(DefaultVhalImplTest, testVendorOverrideProperties) {
+    // Destroy the existing VHAL first to prevent it using destroyed connector or propstore.
+    mHal.reset();
+    // Create a new Default VHAL and reinitialize it to load the override properties.
+    std::string overrideDir = android::base::GetExecutableDirectory() + "/override/";
+    mPropStore.reset(new VehiclePropertyStore);
+    mConnector.reset(new DefaultVehicleConnector);
+    mConnector->setValuePool(&mValueObjectPool);
+    mHal.reset(new DefaultVehicleHal(mPropStore.get(), mConnector.get()));
+    // Set vendor override directory.
+    DefaultVhalImplTestHelper helper(mConnector.get());
+    helper.overrideProperties(overrideDir.c_str());
+
+    initHal();
+
+    VehiclePropValue value;
+    StatusCode status;
+    // This is the same as the prop in 'gear_selection.json'.
+    value.prop = toInt(VehicleProperty::GEAR_SELECTION);
+
+    auto gotValue = mHal->get(value, &status);
+
+    ASSERT_EQ(StatusCode::OK, status);
+    ASSERT_EQ((size_t)1, gotValue->value.int32Values.size());
+    ASSERT_EQ(8, gotValue->value.int32Values[0]);
+
+    // If we set the value, it should update despite the override.
+    value.prop = toInt(VehicleProperty::GEAR_SELECTION);
+    value.value.int32Values.resize(1);
+    value.value.int32Values[0] = 5;
+
+    status = mHal->set(value);
+    ASSERT_EQ(StatusCode::OK, status);
+
+    gotValue = mHal->get(value, &status);
+    ASSERT_EQ(StatusCode::OK, status);
+    ASSERT_EQ((size_t)1, gotValue->value.int32Values.size());
+    ASSERT_EQ(5, gotValue->value.int32Values[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testVendorOverridePropertiesMultipleAreas) {
+    // Destroy the existing VHAL first to prevent it using destroyed connector or propstore.
+    mHal.reset();
+    // Create a new Default VHAL and reinitialize it to load the override properties.
+    std::string overrideDir = android::base::GetExecutableDirectory() + "/override/";
+    mPropStore.reset(new VehiclePropertyStore);
+    mConnector.reset(new DefaultVehicleConnector);
+    mConnector->setValuePool(&mValueObjectPool);
+    mHal.reset(new DefaultVehicleHal(mPropStore.get(), mConnector.get()));
+    // Set vendor override directory.
+    DefaultVhalImplTestHelper helper(mConnector.get());
+    helper.overrideProperties(overrideDir.c_str());
+
+    initHal();
+
+    VehiclePropValue value;
+    StatusCode status;
+    // This is the same as the prop in 'hvac_temperature_set.json'.
+    value.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET);
+    value.areaId = HVAC_LEFT;
+
+    auto gotValue = mHal->get(value, &status);
+
+    ASSERT_EQ(StatusCode::OK, status);
+    ASSERT_EQ((size_t)1, gotValue->value.floatValues.size());
+    ASSERT_EQ(30.0f, gotValue->value.floatValues[0]);
+
+    // HVAC_RIGHT should not be affected and return the default value.
+    value.areaId = HVAC_RIGHT;
+
+    gotValue = mHal->get(value, &status);
+
+    ASSERT_EQ(StatusCode::OK, status);
+    ASSERT_EQ((size_t)1, gotValue->value.floatValues.size());
+    ASSERT_EQ(20.0f, gotValue->value.floatValues[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testVendorOverridePropertiesDirDoesNotExist) {
+    // Destroy the existing VHAL first to prevent it using destroyed connector or propstore.
+    mHal.reset();
+    // Create a new Default VHAL and reinitialize it to load the override properties.
+    mPropStore.reset(new VehiclePropertyStore);
+    mConnector.reset(new DefaultVehicleConnector);
+    mConnector->setValuePool(&mValueObjectPool);
+    mHal.reset(new DefaultVehicleHal(mPropStore.get(), mConnector.get()));
+    // Set vendor override directory to a non-existing dir
+    DefaultVhalImplTestHelper helper(mConnector.get());
+    helper.overrideProperties("123");
+    initHal();
+
+    VehiclePropValue value;
+    StatusCode status;
+    value.prop = toInt(VehicleProperty::GEAR_SELECTION);
+
+    auto gotValue = mHal->get(value, &status);
+
+    // We should get the default value.
+    ASSERT_EQ(StatusCode::OK, status);
+    ASSERT_EQ((size_t)1, gotValue->value.int32Values.size());
+    ASSERT_EQ(4, gotValue->value.int32Values[0]);
+}
+
 }  // namespace
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/override/gear_selection.json b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/override/gear_selection.json
new file mode 100644
index 0000000..59666b8
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/override/gear_selection.json
@@ -0,0 +1,9 @@
+[
+  {
+    "timestamp": 1000000,
+    "areaId": 0,
+    "value": 8,
+    // GEAR_SELECTION
+    "prop": 289408000
+  }
+]
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/override/hvac_temperature_set.json b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/override/hvac_temperature_set.json
new file mode 100644
index 0000000..93a97ed
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/override/hvac_temperature_set.json
@@ -0,0 +1,10 @@
+[
+  {
+    "timestamp": 1000000,
+    // HVAC_LEFT
+    "areaId": 49,
+    "value": 30,
+    // HVAC_TEMPERATURE_SET
+    "prop": 358614275
+  }
+]
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/prop.json b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/prop.json
index 2e77a44..b881109 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/prop.json
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/prop.json
@@ -20,7 +20,7 @@
   {
     "timestamp": 4000000,
     "areaId": 0,
-    "value": 4,
+    "value": 10,
     "prop": 289408000
   }
 ]