Extract logic of storing values to separate class

Also rename DefaultVehicleHal to EmulatedVehicleHal and
extract emulator related code to VehicleEmulator class

Test: mm -j32 ; verified Car Service worked

Change-Id: I34361fdec6f94629cf7ef6c35ff56ef9ce78b855
diff --git a/automotive/vehicle/2.0/default/Android.mk b/automotive/vehicle/2.0/default/Android.mk
index b8535bd..3c56159 100644
--- a/automotive/vehicle/2.0/default/Android.mk
+++ b/automotive/vehicle/2.0/default/Android.mk
@@ -25,6 +25,7 @@
     common/src/SubscriptionManager.cpp \
     common/src/VehicleHalManager.cpp \
     common/src/VehicleObjectPool.cpp \
+    common/src/VehiclePropertyStore.cpp \
     common/src/VehicleUtils.cpp \
 
 LOCAL_C_INCLUDES := \
@@ -72,9 +73,10 @@
 
 LOCAL_MODULE:= $(vhal_v2_0)-default-impl-lib
 LOCAL_SRC_FILES:= \
-    impl/vhal_v2_0/DefaultVehicleHal.cpp \
+    impl/vhal_v2_0/EmulatedVehicleHal.cpp \
+    impl/vhal_v2_0/VehicleEmulator.cpp \
     impl/vhal_v2_0/PipeComm.cpp \
-    impl/vhal_v2_0/SocketComm.cpp
+    impl/vhal_v2_0/SocketComm.cpp \
 
 LOCAL_C_INCLUDES := \
     $(LOCAL_PATH)/impl/vhal_v2_0
diff --git a/automotive/vehicle/2.0/default/VehicleService.cpp b/automotive/vehicle/2.0/default/VehicleService.cpp
index 95057cc..e6d292e 100644
--- a/automotive/vehicle/2.0/default/VehicleService.cpp
+++ b/automotive/vehicle/2.0/default/VehicleService.cpp
@@ -21,14 +21,16 @@
 #include <iostream>
 
 #include <vhal_v2_0/VehicleHalManager.h>
-#include <vhal_v2_0/DefaultVehicleHal.h>
+#include <vhal_v2_0/EmulatedVehicleHal.h>
 
 using namespace android;
 using namespace android::hardware;
 using namespace android::hardware::automotive::vehicle::V2_0;
 
 int main(int /* argc */, char* /* argv */ []) {
-    auto hal = std::make_unique<impl::DefaultVehicleHal>();
+    auto store = std::make_unique<VehiclePropertyStore>();
+    auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get());
+    auto emulator = std::make_unique<impl::VehicleEmulator>(hal.get());
     auto service = std::make_unique<VehicleHalManager>(hal.get());
 
     configureRpcThreadpool(1, true /* callerWillJoin */);
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehiclePropertyStore.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehiclePropertyStore.h
new file mode 100644
index 0000000..eda94b7
--- /dev/null
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehiclePropertyStore.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_automotive_vehicle_V2_0_impl_PropertyDb_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_PropertyDb_H_
+
+#include <cstdint>
+#include <unordered_map>
+#include <memory>
+#include <mutex>
+
+#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+/**
+ * Encapsulates work related to storing and accessing configuration, storing and modifying
+ * vehicle property values.
+ *
+ * VehiclePropertyValues stored in a sorted map thus it makes easier to get range of values, e.g.
+ * to get value for all areas for particular property.
+ *
+ * This class is thread-safe, however it uses blocking synchronization across all methods.
+ */
+class VehiclePropertyStore {
+public:
+    /* Function that used to calculate unique token for given VehiclePropValue */
+    using TokenFunction = std::function<int64_t(const VehiclePropValue& value)>;
+
+private:
+    struct RecordConfig {
+        VehiclePropConfig propConfig;
+        TokenFunction tokenFunction;
+    };
+
+    struct RecordId {
+        int32_t prop;
+        int32_t area;
+        int64_t token;
+
+        bool operator==(const RecordId& other) const;
+        bool operator<(const RecordId& other) const;
+    };
+
+    using PropertyMap = std::map<RecordId, VehiclePropValue>;
+    using PropertyMapRange = std::pair<PropertyMap::const_iterator, PropertyMap::const_iterator>;
+
+public:
+    void registerProperty(const VehiclePropConfig& config, TokenFunction tokenFunc = nullptr);
+
+    /* Stores provided value. Returns true if value was written returns false if config for
+     * example wasn't registered. */
+    bool writeValue(const VehiclePropValue& propValue);
+
+    void removeValue(const VehiclePropValue& propValue);
+    void removeValuesForProperty(int32_t propId);
+
+    std::vector<VehiclePropValue> readAllValues() const;
+    std::vector<VehiclePropValue> readValuesForProperty(int32_t propId) const;
+    std::unique_ptr<VehiclePropValue> readValueOrNull(const VehiclePropValue& request) const;
+    std::unique_ptr<VehiclePropValue> readValueOrNull(int32_t prop, int32_t area = 0,
+                                                      int64_t token = 0) const;
+
+    std::vector<VehiclePropConfig> getAllConfigs() const;
+    const VehiclePropConfig* getConfigOrNull(int32_t propId) const;
+    const VehiclePropConfig* getConfigOrDie(int32_t propId) const;
+
+private:
+    RecordId getRecordIdLocked(const VehiclePropValue& valuePrototype) const;
+    const VehiclePropValue* getValueOrNullLocked(const RecordId& recId) const;
+    PropertyMapRange findRangeLocked(int32_t propId) const;
+
+private:
+    using MuxGuard = std::lock_guard<std::mutex>;
+    mutable std::mutex mLock;
+    std::unordered_map<int32_t /* VehicleProperty */, RecordConfig> mConfigs;
+
+    PropertyMap mPropertyValues;  // Sorted map of RecordId : VehiclePropValue.
+};
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif //android_hardware_automotive_vehicle_V2_0_impl_PropertyDb_H_
diff --git a/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp b/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp
new file mode 100644
index 0000000..0e6b776
--- /dev/null
+++ b/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "VehiclePropertyStore"
+#include <android/log.h>
+
+#include <common/include/vhal_v2_0/VehicleUtils.h>
+#include "VehiclePropertyStore.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+bool VehiclePropertyStore::RecordId::operator==(const VehiclePropertyStore::RecordId& other) const {
+    return prop == other.prop && area == other.area && token == other.token;
+}
+
+bool VehiclePropertyStore::RecordId::operator<(const VehiclePropertyStore::RecordId& other) const  {
+    return prop < other.prop
+           || (prop == other.prop && area < other.area)
+           || (prop == other.prop && area == other.area && token < other.token);
+}
+
+void VehiclePropertyStore::registerProperty(const VehiclePropConfig& config,
+                                            VehiclePropertyStore::TokenFunction tokenFunc) {
+    MuxGuard g(mLock);
+    mConfigs.insert({ config.prop, RecordConfig { config, tokenFunc } });
+}
+
+bool VehiclePropertyStore::writeValue(const VehiclePropValue& propValue) {
+    MuxGuard g(mLock);
+    if (!mConfigs.count(propValue.prop)) return false;
+
+    RecordId recId = getRecordIdLocked(propValue);
+    VehiclePropValue* valueToUpdate = const_cast<VehiclePropValue*>(getValueOrNullLocked(recId));
+    if (valueToUpdate == nullptr) {
+        mPropertyValues.insert({ recId, propValue });
+    } else {
+        valueToUpdate->timestamp = propValue.timestamp;
+        valueToUpdate->value = propValue.value;
+    }
+    return true;
+}
+
+void VehiclePropertyStore::removeValue(const VehiclePropValue& propValue) {
+    MuxGuard g(mLock);
+    RecordId recId = getRecordIdLocked(propValue);
+    auto it = mPropertyValues.find(recId);
+    if (it != mPropertyValues.end()) {
+        mPropertyValues.erase(it);
+    }
+}
+
+void VehiclePropertyStore::removeValuesForProperty(int32_t propId) {
+    MuxGuard g(mLock);
+    auto range = findRangeLocked(propId);
+    mPropertyValues.erase(range.first, range.second);
+}
+
+std::vector<VehiclePropValue> VehiclePropertyStore::readAllValues() const {
+    MuxGuard g(mLock);
+    std::vector<VehiclePropValue> allValues;
+    allValues.reserve(mPropertyValues.size());
+    for (auto&& it : mPropertyValues) {
+        allValues.push_back(it.second);
+    }
+    return allValues;
+}
+
+std::vector<VehiclePropValue> VehiclePropertyStore::readValuesForProperty(int32_t propId) const {
+    std::vector<VehiclePropValue> values;
+    MuxGuard g(mLock);
+    auto range = findRangeLocked(propId);
+    for (auto it = range.first; it != range.second; ++it) {
+        values.push_back(it->second);
+    }
+
+    return values;
+}
+
+std::unique_ptr<VehiclePropValue> VehiclePropertyStore::readValueOrNull(
+        const VehiclePropValue& request) const {
+    MuxGuard g(mLock);
+    RecordId recId = getRecordIdLocked(request);
+    const VehiclePropValue* internalValue = getValueOrNullLocked(recId);
+    return internalValue ? std::make_unique<VehiclePropValue>(*internalValue) : nullptr;
+}
+
+std::unique_ptr<VehiclePropValue> VehiclePropertyStore::readValueOrNull(
+        int32_t prop, int32_t area, int64_t token) const {
+    RecordId recId = {prop, isGlobalProp(prop) ? 0 : area, token };
+    MuxGuard g(mLock);
+    const VehiclePropValue* internalValue = getValueOrNullLocked(recId);
+    return internalValue ? std::make_unique<VehiclePropValue>(*internalValue) : nullptr;
+}
+
+
+std::vector<VehiclePropConfig> VehiclePropertyStore::getAllConfigs() const {
+    MuxGuard g(mLock);
+    std::vector<VehiclePropConfig> configs;
+    configs.reserve(mConfigs.size());
+    for (auto&& recordConfigIt: mConfigs) {
+        configs.push_back(recordConfigIt.second.propConfig);
+    }
+    return configs;
+}
+
+const VehiclePropConfig* VehiclePropertyStore::getConfigOrNull(int32_t propId) const {
+    MuxGuard g(mLock);
+    auto recordConfigIt = mConfigs.find(propId);
+    return recordConfigIt != mConfigs.end() ? &recordConfigIt->second.propConfig : nullptr;
+}
+
+const VehiclePropConfig* VehiclePropertyStore::getConfigOrDie(int32_t propId) const {
+    auto cfg = getConfigOrNull(propId);
+    if (!cfg) {
+        ALOGW("%s: config not found for property: 0x%x", __func__, propId);
+        abort();
+    }
+    return cfg;
+}
+
+VehiclePropertyStore::RecordId VehiclePropertyStore::getRecordIdLocked(
+        const VehiclePropValue& valuePrototype) const {
+    RecordId recId = {
+        .prop = valuePrototype.prop,
+        .area = isGlobalProp(valuePrototype.prop) ? 0 : valuePrototype.areaId,
+        .token = 0
+    };
+
+    auto it = mConfigs.find(recId.prop);
+    if (it == mConfigs.end()) return {};
+
+    if (it->second.tokenFunction != nullptr) {
+        recId.token = it->second.tokenFunction(valuePrototype);
+    }
+    return recId;
+}
+
+const VehiclePropValue* VehiclePropertyStore::getValueOrNullLocked(
+        const VehiclePropertyStore::RecordId& recId) const  {
+    auto it = mPropertyValues.find(recId);
+    return it == mPropertyValues.end() ? nullptr : &it->second;
+}
+
+VehiclePropertyStore::PropertyMapRange VehiclePropertyStore::findRangeLocked(int32_t propId) const {
+    // Based on the fact that mPropertyValues is a sorted map by RecordId.
+    auto beginIt = mPropertyValues.lower_bound( RecordId { propId, INT32_MIN, 0 });
+    auto endIt = mPropertyValues.lower_bound( RecordId { propId + 1, INT32_MIN, 0 });
+
+    return  PropertyMapRange { beginIt, endIt };
+}
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
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 b7ef896..bf16a9b 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
@@ -59,7 +59,7 @@
             .access = VehiclePropertyAccess::READ,
             .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
         },
-        .initialValue = { .int32Values = {0} }
+        .initialValue = { .floatValues = {0.0f} }
     },
 
     {
@@ -195,10 +195,10 @@
         .initialAreaValues = {
             {
                 toInt(VehicleAreaZone::ROW_1_LEFT),
-                { .int32Values = {16} }
+                { .floatValues = {16} }
             }, {
                 toInt(VehicleAreaZone::ROW_1_RIGHT),
-                {.int32Values = {20} }
+                { .floatValues = {20} }
             }
         }
     },
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
deleted file mode 100644
index e174932..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp
+++ /dev/null
@@ -1,600 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "DefaultVehicleHal_v2_0"
-#include <android/log.h>
-
-#include <algorithm>
-#include <android-base/properties.h>
-#include <cstdio>
-
-#include "DefaultVehicleHal.h"
-#include "PipeComm.h"
-#include "SocketComm.h"
-#include "VehicleHalProto.pb.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-void DefaultVehicleHal::doGetConfig(emulator::EmulatorMessage& rxMsg,
-                                    emulator::EmulatorMessage& respMsg) {
-    std::vector<VehiclePropConfig> configs = listProperties();
-    emulator::VehiclePropGet getProp = rxMsg.prop(0);
-
-    respMsg.set_msg_type(emulator::GET_CONFIG_RESP);
-    respMsg.set_status(emulator::ERROR_INVALID_PROPERTY);
-
-    for (auto& config : configs) {
-        // Find the config we are looking for
-        if (config.prop == getProp.prop()) {
-            emulator::VehiclePropConfig* protoCfg = respMsg.add_config();
-            populateProtoVehicleConfig(protoCfg, config);
-            respMsg.set_status(emulator::RESULT_OK);
-            break;
-        }
-    }
-}
-
-void DefaultVehicleHal::doGetConfigAll(emulator::EmulatorMessage& /* rxMsg */,
-                                       emulator::EmulatorMessage& respMsg) {
-    std::vector<VehiclePropConfig> configs = listProperties();
-
-    respMsg.set_msg_type(emulator::GET_CONFIG_ALL_RESP);
-    respMsg.set_status(emulator::RESULT_OK);
-
-    for (auto& config : configs) {
-        emulator::VehiclePropConfig* protoCfg = respMsg.add_config();
-        populateProtoVehicleConfig(protoCfg, config);
-    }
-}
-
-void DefaultVehicleHal::doGetProperty(emulator::EmulatorMessage& rxMsg,
-                                      emulator::EmulatorMessage& respMsg) {
-    int32_t areaId = 0;
-    emulator::VehiclePropGet getProp = rxMsg.prop(0);
-    int32_t propId = getProp.prop();
-    emulator::Status status = emulator::ERROR_INVALID_PROPERTY;
-    VehiclePropValue* val;
-
-    respMsg.set_msg_type(emulator::GET_PROPERTY_RESP);
-
-    if (getProp.has_area_id()) {
-        areaId = getProp.area_id();
-    }
-
-    {
-        std::lock_guard<std::mutex> lock(mPropsMutex);
-
-        val = getVehiclePropValueLocked(propId, areaId);
-        if (val != nullptr) {
-            emulator::VehiclePropValue* protoVal = respMsg.add_value();
-            populateProtoVehiclePropValue(protoVal, val);
-            status = emulator::RESULT_OK;
-        }
-    }
-
-    respMsg.set_status(status);
-}
-
-void DefaultVehicleHal::doGetPropertyAll(emulator::EmulatorMessage& /* rxMsg */,
-                                         emulator::EmulatorMessage& respMsg) {
-    respMsg.set_msg_type(emulator::GET_PROPERTY_ALL_RESP);
-    respMsg.set_status(emulator::RESULT_OK);
-
-    {
-        std::lock_guard<std::mutex> lock(mPropsMutex);
-
-        for (auto& prop : mProps) {
-            emulator::VehiclePropValue* protoVal = respMsg.add_value();
-            populateProtoVehiclePropValue(protoVal, prop.second->get());
-        }
-    }
-}
-
-void DefaultVehicleHal::doSetProperty(emulator::EmulatorMessage& rxMsg,
-                                      emulator::EmulatorMessage& respMsg) {
-    emulator::VehiclePropValue protoVal = rxMsg.value(0);
-    VehiclePropValue val;
-
-    respMsg.set_msg_type(emulator::SET_PROPERTY_RESP);
-
-    val.prop = protoVal.prop();
-    val.areaId = protoVal.area_id();
-    val.timestamp = elapsedRealtimeNano();
-
-    // Copy value data if it is set.  This automatically handles complex data types if needed.
-    if (protoVal.has_string_value()) {
-        val.value.stringValue = protoVal.string_value().c_str();
-    }
-
-    if (protoVal.has_bytes_value()) {
-        std::vector<uint8_t> tmp(protoVal.bytes_value().begin(), protoVal.bytes_value().end());
-        val.value.bytes = tmp;
-    }
-
-    if (protoVal.int32_values_size() > 0) {
-        std::vector<int32_t> int32Values = std::vector<int32_t>(protoVal.int32_values_size());
-        for (int i=0; i<protoVal.int32_values_size(); i++) {
-            int32Values[i] = protoVal.int32_values(i);
-        }
-        val.value.int32Values = int32Values;
-    }
-
-    if (protoVal.int64_values_size() > 0) {
-        std::vector<int64_t> int64Values = std::vector<int64_t>(protoVal.int64_values_size());
-        for (int i=0; i<protoVal.int64_values_size(); i++) {
-            int64Values[i] = protoVal.int64_values(i);
-        }
-        val.value.int64Values = int64Values;
-    }
-
-    if (protoVal.float_values_size() > 0) {
-        std::vector<float> floatValues = std::vector<float>(protoVal.float_values_size());
-        for (int i=0; i<protoVal.float_values_size(); i++) {
-            floatValues[i] = protoVal.float_values(i);
-        }
-        val.value.floatValues = floatValues;
-    }
-
-    if (updateProperty(val) == StatusCode::OK) {
-        // Send property up to VehicleHalManager via callback
-        auto& pool = *getValuePool();
-        VehiclePropValuePtr v = pool.obtain(val);
-
-        doHalEvent(std::move(v));
-        respMsg.set_status(emulator::RESULT_OK);
-    } else {
-        respMsg.set_status(emulator::ERROR_INVALID_PROPERTY);
-    }
-}
-
-// This function should only be called while mPropsMutex is locked.
-VehiclePropValue* DefaultVehicleHal::getVehiclePropValueLocked(int32_t propId, int32_t areaId) {
-    if (getPropArea(propId) == VehicleArea::GLOBAL) {
-        // In VehicleHal, global properties have areaId = -1.  We use 0.
-        areaId = 0;
-    }
-
-    auto prop = mProps.find(std::make_pair(propId, areaId));
-    if (prop != mProps.end()) {
-        return prop->second->get();
-    }
-    ALOGW("%s: Property not found:  propId = 0x%x, areaId = 0x%x", __func__, propId, areaId);
-    return nullptr;
-}
-
-void DefaultVehicleHal::parseRxProtoBuf(std::vector<uint8_t>& msg) {
-    emulator::EmulatorMessage rxMsg;
-    emulator::EmulatorMessage respMsg;
-
-    if (rxMsg.ParseFromArray(msg.data(), msg.size())) {
-        switch (rxMsg.msg_type()) {
-        case emulator::GET_CONFIG_CMD:
-            doGetConfig(rxMsg, respMsg);
-            break;
-        case emulator::GET_CONFIG_ALL_CMD:
-            doGetConfigAll(rxMsg, respMsg);
-            break;
-        case emulator::GET_PROPERTY_CMD:
-            doGetProperty(rxMsg, respMsg);
-            break;
-        case emulator::GET_PROPERTY_ALL_CMD:
-            doGetPropertyAll(rxMsg, respMsg);
-            break;
-        case emulator::SET_PROPERTY_CMD:
-            doSetProperty(rxMsg, respMsg);
-            break;
-        default:
-            ALOGW("%s: Unknown message received, type = %d", __func__, rxMsg.msg_type());
-            respMsg.set_status(emulator::ERROR_UNIMPLEMENTED_CMD);
-            break;
-        }
-
-        // Send the reply
-        txMsg(respMsg);
-    } else {
-        ALOGE("%s: ParseFromString() failed. msgSize=%d", __func__, static_cast<int>(msg.size()));
-    }
-}
-
-// Copies internal VehiclePropConfig data structure to protobuf VehiclePropConfig
-void DefaultVehicleHal::populateProtoVehicleConfig(emulator::VehiclePropConfig* protoCfg,
-                                                   const VehiclePropConfig& cfg) {
-    protoCfg->set_prop(cfg.prop);
-    protoCfg->set_access(toInt(cfg.access));
-    protoCfg->set_change_mode(toInt(cfg.changeMode));
-    protoCfg->set_value_type(toInt(getPropType(cfg.prop)));
-
-    if (!isGlobalProp(cfg.prop)) {
-        protoCfg->set_supported_areas(cfg.supportedAreas);
-    }
-
-    for (auto& configElement : cfg.configArray) {
-        protoCfg->add_config_array(configElement);
-    }
-
-    if (cfg.configString.size() > 0) {
-        protoCfg->set_config_string(cfg.configString.c_str(), cfg.configString.size());
-    }
-
-    // Populate the min/max values based on property type
-    switch (getPropType(cfg.prop)) {
-    case VehiclePropertyType::STRING:
-    case VehiclePropertyType::BOOLEAN:
-    case VehiclePropertyType::INT32_VEC:
-    case VehiclePropertyType::FLOAT_VEC:
-    case VehiclePropertyType::BYTES:
-    case VehiclePropertyType::COMPLEX:
-        // Do nothing.  These types don't have min/max values
-        break;
-    case VehiclePropertyType::INT64:
-        if (cfg.areaConfigs.size() > 0) {
-            emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
-            aCfg->set_min_int64_value(cfg.areaConfigs[0].minInt64Value);
-            aCfg->set_max_int64_value(cfg.areaConfigs[0].maxInt64Value);
-        }
-        break;
-    case VehiclePropertyType::FLOAT:
-        if (cfg.areaConfigs.size() > 0) {
-            emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
-            aCfg->set_min_float_value(cfg.areaConfigs[0].minFloatValue);
-            aCfg->set_max_float_value(cfg.areaConfigs[0].maxFloatValue);
-        }
-        break;
-    case VehiclePropertyType::INT32:
-        if (cfg.areaConfigs.size() > 0) {
-            emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
-            aCfg->set_min_int32_value(cfg.areaConfigs[0].minInt32Value);
-            aCfg->set_max_int32_value(cfg.areaConfigs[0].maxInt32Value);
-        }
-        break;
-    default:
-        ALOGW("%s: Unknown property type:  0x%x", __func__, toInt(getPropType(cfg.prop)));
-        break;
-    }
-
-    protoCfg->set_min_sample_rate(cfg.minSampleRate);
-    protoCfg->set_max_sample_rate(cfg.maxSampleRate);
-}
-
-// Copies internal VehiclePropValue data structure to protobuf VehiclePropValue
-void DefaultVehicleHal::populateProtoVehiclePropValue(emulator::VehiclePropValue* protoVal,
-                                                      const VehiclePropValue* val) {
-    protoVal->set_prop(val->prop);
-    protoVal->set_value_type(toInt(getPropType(val->prop)));
-    protoVal->set_timestamp(val->timestamp);
-    protoVal->set_area_id(val->areaId);
-
-    // Copy value data if it is set.
-    //  - for bytes and strings, this is indicated by size > 0
-    //  - for int32, int64, and float, copy the values if vectors have data
-    if (val->value.stringValue.size() > 0) {
-        protoVal->set_string_value(val->value.stringValue.c_str(), val->value.stringValue.size());
-    }
-
-    if (val->value.bytes.size() > 0) {
-        protoVal->set_bytes_value(val->value.bytes.data(), val->value.bytes.size());
-    }
-
-    for (auto& int32Value : val->value.int32Values) {
-        protoVal->add_int32_values(int32Value);
-    }
-
-    for (auto& int64Value : val->value.int64Values) {
-        protoVal->add_int64_values(int64Value);
-    }
-
-    for (auto& floatValue : val->value.floatValues) {
-        protoVal->add_float_values(floatValue);
-    }
-}
-
-void DefaultVehicleHal::rxMsg() {
-    int  numBytes = 0;
-
-    while (mExit == 0) {
-        std::vector<uint8_t> msg = mComm->read();
-
-        if (msg.size() > 0) {
-            // Received a message.
-            parseRxProtoBuf(msg);
-        } else {
-            // This happens when connection is closed
-            ALOGD("%s: numBytes=%d, msgSize=%d", __func__, numBytes,
-                  static_cast<int32_t>(msg.size()));
-            break;
-        }
-    }
-}
-
-void DefaultVehicleHal::rxThread() {
-    bool isEmulator = android::base::GetBoolProperty("ro.kernel.qemu", false);
-
-    if (isEmulator) {
-        // Initialize pipe to Emulator
-        mComm.reset(new PipeComm);
-    } else {
-        // Initialize socket over ADB
-        mComm.reset(new SocketComm);
-    }
-
-    int retVal = mComm->open();
-
-    if (retVal == 0) {
-        // Comms are properly opened
-        while (mExit == 0) {
-            retVal = mComm->connect();
-
-            if (retVal >= 0) {
-                rxMsg();
-            }
-
-            // Check every 100ms for a new connection
-            std::this_thread::sleep_for(std::chrono::milliseconds(100));
-        }
-    }
-}
-
-// Transmit a reply back to the emulator
-void DefaultVehicleHal::txMsg(emulator::EmulatorMessage& txMsg) {
-    int numBytes = txMsg.ByteSize();
-    std::vector<uint8_t> msg(numBytes);
-
-    if (txMsg.SerializeToArray(msg.data(), msg.size())) {
-        int retVal = 0;
-
-        // Send the message
-        if (mExit == 0) {
-            mComm->write(msg);
-        }
-
-        if (retVal < 0) {
-            ALOGE("%s: Failed to tx message: retval=%d, errno=%d", __func__, retVal, errno);
-        }
-    } else {
-        ALOGE("%s: SerializeToString failed!", __func__);
-    }
-}
-
-// Updates the property value held in the HAL
-StatusCode DefaultVehicleHal::updateProperty(const VehiclePropValue& propValue) {
-    auto propId = propValue.prop;
-    auto areaId = propValue.areaId;
-    StatusCode status = StatusCode::INVALID_ARG;
-
-    {
-        std::lock_guard<std::mutex> lock(mPropsMutex);
-
-        VehiclePropValue* internalPropValue = getVehiclePropValueLocked(propId, areaId);
-        if (internalPropValue != nullptr) {
-            internalPropValue->value = propValue.value;
-            internalPropValue->timestamp = propValue.timestamp;
-            status = StatusCode::OK;
-        }
-    }
-    return status;
-}
-
-VehicleHal::VehiclePropValuePtr DefaultVehicleHal::get(
-        const VehiclePropValue& requestedPropValue, StatusCode* outStatus) {
-    auto areaId = requestedPropValue.areaId;
-    auto& pool = *getValuePool();
-    auto propId = requestedPropValue.prop;
-    StatusCode status;
-    VehiclePropValuePtr v = nullptr;
-
-    switch (propId) {
-    default:
-        {
-            std::lock_guard<std::mutex> lock(mPropsMutex);
-
-            VehiclePropValue *internalPropValue = getVehiclePropValueLocked(propId, areaId);
-            if (internalPropValue != nullptr) {
-                v = pool.obtain(*internalPropValue);
-            }
-        }
-
-        if (v != nullptr) {
-            status = StatusCode::OK;
-        } else {
-            status = StatusCode::INVALID_ARG;
-        }
-        break;
-    }
-
-    *outStatus = status;
-    return v;
-}
-
-StatusCode DefaultVehicleHal::set(const VehiclePropValue& propValue) {
-    auto propId = propValue.prop;
-    StatusCode status;
-    switch (propId) {
-        default:
-            if (mHvacPowerProps.count(propId)) {
-                std::lock_guard<std::mutex> lock(mPropsMutex);
-                auto hvacPowerOn = getVehiclePropValueLocked(toInt(VehicleProperty::HVAC_POWER_ON),
-                                                             toInt(VehicleAreaZone::ROW_1));
-
-                if (hvacPowerOn && hvacPowerOn->value.int32Values.size() == 1
-                        && hvacPowerOn->value.int32Values[0] == 0) {
-                    status = StatusCode::NOT_AVAILABLE;
-                    break;
-                }
-            }
-            status = updateProperty(propValue);
-            if (status == StatusCode::OK) {
-                // Send property update to emulator
-                emulator::EmulatorMessage msg;
-                emulator::VehiclePropValue *val = msg.add_value();
-                populateProtoVehiclePropValue(val, &propValue);
-                msg.set_status(emulator::RESULT_OK);
-                msg.set_msg_type(emulator::SET_PROPERTY_ASYNC);
-                txMsg(msg);
-            }
-            break;
-    }
-
-    return status;
-}
-
-V2_0::StatusCode DefaultVehicleHal::addCustomProperty(int32_t property,
-    std::unique_ptr<CustomVehiclePropertyHandler>&& handler) {
-    mProps[std::make_pair(property, 0)] = std::move(handler);
-    ALOGW("%s: Added custom property: propId = 0x%x", __func__, property);
-    return StatusCode::OK;
-}
-
-// Parse supported properties list and generate vector of property values to hold current values.
-void DefaultVehicleHal::onCreate() {
-    // Initialize member variables
-    mExit = 0;
-
-    for (auto& prop : kHvacPowerProperties) {
-        mHvacPowerProps.insert(prop);
-    }
-
-    for (auto& it : kVehicleProperties) {
-        VehiclePropConfig cfg = it.config;
-        int32_t supportedAreas = cfg.supportedAreas;
-
-        //  A global property will have supportedAreas = 0
-        if (getPropArea(cfg.prop) == VehicleArea::GLOBAL) {
-            supportedAreas = 0;
-        }
-
-        // This loop is a do-while so it executes at least once to handle global properties
-        do {
-            int32_t curArea = supportedAreas;
-            supportedAreas &= supportedAreas - 1;  // Clear the right-most bit of supportedAreas.
-            curArea ^= supportedAreas;  // Set curArea to the previously cleared bit.
-
-            // Create a separate instance for each individual zone
-            VehiclePropValue prop = {
-                .prop = cfg.prop,
-                .areaId = curArea,
-            };
-            if (it.initialAreaValues.size() > 0) {
-                auto valueForAreaIt = it.initialAreaValues.find(curArea);
-                if (valueForAreaIt != it.initialAreaValues.end()) {
-                    prop.value = valueForAreaIt->second;
-                } else {
-                    ALOGW("%s failed to get default value for prop 0x%x area 0x%x",
-                            __func__, cfg.prop, curArea);
-                }
-            } else {
-                prop.value = it.initialValue;
-            }
-
-            auto handler = std::make_unique<StoredValueCustomVehiclePropertyHandler>();
-            handler->set(prop);
-            mProps[std::make_pair(prop.prop, prop.areaId)] = std::move(handler);
-        } while (supportedAreas != 0);
-    }
-
-    // Start rx thread
-    mThread = std::thread(&DefaultVehicleHal::rxThread, this);
-}
-
-std::vector<VehiclePropConfig> DefaultVehicleHal::listProperties()  {
-    std::vector<VehiclePropConfig> configs(mPropConfigMap.size());
-    for (auto&& it : mPropConfigMap) {
-        configs.push_back(*it.second);
-    }
-    return configs;
-}
-
-void DefaultVehicleHal::onContinuousPropertyTimer(const std::vector<int32_t>& properties) {
-    VehiclePropValuePtr v;
-
-    auto& pool = *getValuePool();
-
-    for (int32_t property : properties) {
-        if (isContinuousProperty(property)) {
-            // In real implementation this value should be read from sensor, random
-            // value used for testing purpose only.
-            std::lock_guard<std::mutex> lock(mPropsMutex);
-
-            VehiclePropValue *internalPropValue = getVehiclePropValueLocked(property);
-            if (internalPropValue != nullptr) {
-                v = pool.obtain(*internalPropValue);
-            }
-            if (VehiclePropertyType::FLOAT == getPropType(property)) {
-                // Just get some randomness to continuous properties to see slightly differnt values
-                // on the other end.
-                if (v->value.floatValues.size() == 0) {
-                    ALOGW("continuous property 0x%x is of type float but does not have a"
-                          " float value. defaulting to zero",
-                          property);
-                    v->value.floatValues = android::hardware::hidl_vec<float>{0.0f};
-                }
-                v->value.floatValues[0] = v->value.floatValues[0] + std::rand() % 5;
-            }
-        } else {
-            ALOGE("Unexpected onContinuousPropertyTimer for property: 0x%x", property);
-        }
-
-        if (v.get()) {
-            v->timestamp = elapsedRealtimeNano();
-            doHalEvent(std::move(v));
-        }
-    }
-}
-
-StatusCode DefaultVehicleHal::subscribe(int32_t property, int32_t,
-                                        float sampleRate) {
-    ALOGI("subscribe called for property: 0x%x, sampleRate: %f", property, sampleRate);
-
-    if (isContinuousProperty(property)) {
-        mRecurrentTimer.registerRecurrentEvent(hertzToNanoseconds(sampleRate), property);
-    }
-    return StatusCode::OK;
-}
-
-StatusCode DefaultVehicleHal::unsubscribe(int32_t property) {
-    ALOGI("%s propId: 0x%x", __func__, property);
-    if (isContinuousProperty(property)) {
-        mRecurrentTimer.unregisterRecurrentEvent(property);
-    }
-    return StatusCode::OK;
-}
-
-const VehiclePropConfig* DefaultVehicleHal::getPropConfig(int32_t propId) const {
-    auto it = mPropConfigMap.find(propId);
-    return it == mPropConfigMap.end() ? nullptr : it->second;
-}
-
-bool DefaultVehicleHal::isContinuousProperty(int32_t propId) const {
-    const VehiclePropConfig* config = getPropConfig(propId);
-    if (config == nullptr) {
-        ALOGW("Config not found for property: 0x%x", propId);
-        return false;
-    }
-    return config->changeMode == VehiclePropertyChangeMode::CONTINUOUS;
-}
-
-}  // impl
-
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
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
deleted file mode 100644
index cdbaf48..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef android_hardware_automotive_vehicle_V2_0_impl_DefaultVehicleHal_H_
-#define android_hardware_automotive_vehicle_V2_0_impl_DefaultVehicleHal_H_
-
-#include <map>
-#include <memory>
-#include <sys/socket.h>
-#include <thread>
-#include <unordered_set>
-
-#include <utils/SystemClock.h>
-
-#include "CommBase.h"
-#include "VehicleHalProto.pb.h"
-
-#include <vhal_v2_0/RecurrentTimer.h>
-#include <vhal_v2_0/VehicleHal.h>
-
-#include "DefaultConfig.h"
-#include "VehicleHalProto.pb.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-class DefaultVehicleHal : public VehicleHal {
-public:
-    class CustomVehiclePropertyHandler {
-    public:
-        virtual VehiclePropValue* get() = 0;
-        virtual StatusCode set(const VehiclePropValue& propValue) = 0;
-        virtual ~CustomVehiclePropertyHandler() = default;
-    };
-
-protected:
-    class StoredValueCustomVehiclePropertyHandler :
-        public CustomVehiclePropertyHandler {
-    public:
-        VehiclePropValue* get() override {
-            return mPropValue.get();
-        }
-
-        StatusCode set(const VehiclePropValue& propValue) {
-            *mPropValue = propValue;
-            return StatusCode::OK;
-        }
-private:
-    std::unique_ptr<VehiclePropValue> mPropValue{new VehiclePropValue()};
-};
-
-public:
-  DefaultVehicleHal() : mRecurrentTimer(
-            std::bind(&DefaultVehicleHal::onContinuousPropertyTimer, this, std::placeholders::_1)) {
-        for (size_t i = 0; i < arraysize(kVehicleProperties); i++) {
-            const auto* config = &kVehicleProperties[i].config;
-            mPropConfigMap[config->prop] = config;
-        }
-    }
-
-    ~DefaultVehicleHal() override {
-        // Notify thread to finish and wait for it to terminate
-        mExit = 1;
-
-        // Close emulator socket if it is open
-        mComm->stop();
-
-        mThread.join();
-    }
-
-    void onCreate() override;
-    std::vector<VehiclePropConfig> listProperties() override;
-    VehiclePropValuePtr get(const VehiclePropValue& requestedPropValue,
-                            StatusCode* outStatus) override;
-    StatusCode set(const VehiclePropValue& propValue) override;
-    StatusCode subscribe(int32_t property, int32_t areas, float sampleRate) override;
-    StatusCode unsubscribe(int32_t property) override;
-
-    /**
-     * Add custom property information to this HAL instance.
-     *
-     * This is useful for allowing later versions of Vehicle HAL to coalesce
-     * the list of properties they support with a previous version of the HAL.
-     *
-     * @param property The identifier of the new property
-     * @param handler The object that will handle get/set requests
-     * @return OK on success, an error code on failure
-     */
-    virtual StatusCode addCustomProperty(int32_t,
-        std::unique_ptr<CustomVehiclePropertyHandler>&&);
-
-    /**
-     * Add custom property information to this HAL instance.
-     *
-     * This is useful for allowing later versions of Vehicle HAL to coalesce
-     * the list of properties they support with a previous version of the HAL.
-     *
-     * @param initialValue The initial value for the new property. This is not
-     *                     constant data, as later set() operations can change
-     *                     this value at will
-     * @return OK on success, an error code on failure
-     */
-    virtual StatusCode addCustomProperty(const VehiclePropValue& initialValue) {
-        auto handler = std::make_unique<StoredValueCustomVehiclePropertyHandler>();
-        StatusCode response = handler->set(initialValue);
-        return StatusCode::OK == response
-               ? addCustomProperty(initialValue.prop, std::move(handler))
-               : response;
-    }
-
-private:
-    void doGetConfig(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
-    void doGetConfigAll(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
-    void doGetProperty(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
-    void doGetPropertyAll(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
-    void doSetProperty(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
-    VehiclePropValue* getVehiclePropValueLocked(int32_t propId, int32_t areaId = 0);
-    const VehiclePropConfig* getPropConfig(int32_t propId) const;
-    bool isContinuousProperty(int32_t propId) const;
-    void parseRxProtoBuf(std::vector<uint8_t>& msg);
-    void populateProtoVehicleConfig(emulator::VehiclePropConfig* protoCfg,
-                                    const VehiclePropConfig& cfg);
-    void populateProtoVehiclePropValue(emulator::VehiclePropValue* protoVal,
-                                       const VehiclePropValue* val);
-    void rxMsg();
-    void rxThread();
-    void txMsg(emulator::EmulatorMessage& txMsg);
-    StatusCode updateProperty(const VehiclePropValue& propValue);
-
-    constexpr std::chrono::nanoseconds hertzToNanoseconds(float hz) const {
-        return std::chrono::nanoseconds(static_cast<int64_t>(1000000000L / hz));
-    }
-
-    void onContinuousPropertyTimer(const std::vector<int32_t>& properties);
-
-private:
-    std::map<
-        std::pair<int32_t /*VehicleProperty*/, int32_t /*areaId*/>,
-        std::unique_ptr<CustomVehiclePropertyHandler>> mProps;
-    std::atomic<int> mExit;
-    std::unordered_set<int32_t> mHvacPowerProps;
-    std::mutex mPropsMutex;
-    std::thread mThread;
-    std::unique_ptr<CommBase> mComm{nullptr};
-    RecurrentTimer mRecurrentTimer;
-    std::unordered_map<int32_t, const VehiclePropConfig*> mPropConfigMap;
-};
-
-}  // impl
-
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
-
-
-#endif  // android_hardware_automotive_vehicle_V2_0_impl_DefaultVehicleHal_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
new file mode 100644
index 0000000..0ac6ada
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "DefaultVehicleHal_v2_0"
+#include <android/log.h>
+
+#include "EmulatedVehicleHal.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore)
+    : mPropStore(propStore),
+      mHvacPowerProps(std::begin(kHvacPowerProperties), std::end(kHvacPowerProperties)),
+      mRecurrentTimer(std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer,
+                                  this, std::placeholders::_1)) {
+
+    for (size_t i = 0; i < arraysize(kVehicleProperties); i++) {
+        mPropStore->registerProperty(kVehicleProperties[i].config);
+    }
+}
+
+VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
+        const VehiclePropValue& requestedPropValue, StatusCode* outStatus) {
+    VehiclePropValuePtr v = nullptr;
+
+    auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue);
+    if (internalPropValue != nullptr) {
+        v = getValuePool()->obtain(*internalPropValue);
+    }
+
+    *outStatus = v != nullptr ? StatusCode::OK : StatusCode::INVALID_ARG;
+    return v;
+}
+
+StatusCode EmulatedVehicleHal::set(const VehiclePropValue& propValue) {
+    if (mHvacPowerProps.count(propValue.prop)) {
+        auto hvacPowerOn = mPropStore->readValueOrNull(toInt(VehicleProperty::HVAC_POWER_ON),
+                                                      toInt(VehicleAreaZone::ROW_1));
+
+        if (hvacPowerOn && hvacPowerOn->value.int32Values.size() == 1
+                && hvacPowerOn->value.int32Values[0] == 0) {
+            return StatusCode::NOT_AVAILABLE;
+        }
+    }
+
+    if (!mPropStore->writeValue(propValue)) {
+        return StatusCode::INVALID_ARG;
+    }
+
+    getEmulatorOrDie()->doSetValueFromClient(propValue);
+
+    return StatusCode::OK;
+}
+
+// Parse supported properties list and generate vector of property values to hold current values.
+void EmulatedVehicleHal::onCreate() {
+    for (auto& it : kVehicleProperties) {
+        VehiclePropConfig cfg = it.config;
+        int32_t supportedAreas = cfg.supportedAreas;
+
+        //  A global property will have supportedAreas = 0
+        if (isGlobalProp(cfg.prop)) {
+            supportedAreas = 0;
+        }
+
+        // This loop is a do-while so it executes at least once to handle global properties
+        do {
+            int32_t curArea = supportedAreas;
+            supportedAreas &= supportedAreas - 1;  // Clear the right-most bit of supportedAreas.
+            curArea ^= supportedAreas;  // Set curArea to the previously cleared bit.
+
+            // Create a separate instance for each individual zone
+            VehiclePropValue prop = {
+                .prop = cfg.prop,
+                .areaId = curArea,
+            };
+            if (it.initialAreaValues.size() > 0) {
+                auto valueForAreaIt = it.initialAreaValues.find(curArea);
+                if (valueForAreaIt != it.initialAreaValues.end()) {
+                    prop.value = valueForAreaIt->second;
+                } else {
+                    ALOGW("%s failed to get default value for prop 0x%x area 0x%x",
+                            __func__, cfg.prop, curArea);
+                }
+            } else {
+                prop.value = it.initialValue;
+            }
+            mPropStore->writeValue(prop);
+
+        } while (supportedAreas != 0);
+    }
+}
+
+std::vector<VehiclePropConfig> EmulatedVehicleHal::listProperties()  {
+    return mPropStore->getAllConfigs();
+}
+
+void EmulatedVehicleHal::onContinuousPropertyTimer(const std::vector<int32_t>& properties) {
+    VehiclePropValuePtr v;
+
+    auto& pool = *getValuePool();
+
+    for (int32_t property : properties) {
+        if (isContinuousProperty(property)) {
+            auto internalPropValue = mPropStore->readValueOrNull(property);
+            if (internalPropValue != nullptr) {
+                v = pool.obtain(*internalPropValue);
+            }
+        } else {
+            ALOGE("Unexpected onContinuousPropertyTimer for property: 0x%x", property);
+        }
+
+        if (v.get()) {
+            v->timestamp = elapsedRealtimeNano();
+            doHalEvent(std::move(v));
+        }
+    }
+}
+
+StatusCode EmulatedVehicleHal::subscribe(int32_t property, int32_t,
+                                        float sampleRate) {
+    ALOGI("%s propId: 0x%x, sampleRate: %f", __func__, property, sampleRate);
+
+    if (isContinuousProperty(property)) {
+        mRecurrentTimer.registerRecurrentEvent(hertzToNanoseconds(sampleRate), property);
+    }
+    return StatusCode::OK;
+}
+
+StatusCode EmulatedVehicleHal::unsubscribe(int32_t property) {
+    ALOGI("%s propId: 0x%x", __func__, property);
+    if (isContinuousProperty(property)) {
+        mRecurrentTimer.unregisterRecurrentEvent(property);
+    }
+    return StatusCode::OK;
+}
+
+bool EmulatedVehicleHal::isContinuousProperty(int32_t propId) const {
+    const VehiclePropConfig* config = mPropStore->getConfigOrNull(propId);
+    if (config == nullptr) {
+        ALOGW("Config not found for property: 0x%x", propId);
+        return false;
+    }
+    return config->changeMode == VehiclePropertyChangeMode::CONTINUOUS;
+}
+
+bool EmulatedVehicleHal::setPropertyFromVehicle(const VehiclePropValue& propValue) {
+    if (mPropStore->writeValue(propValue)) {
+        doHalEvent(getValuePool()->obtain(propValue));
+        return true;
+    } else {
+        return false;
+    }
+}
+
+std::vector<VehiclePropValue> EmulatedVehicleHal::getAllProperties() const  {
+    return mPropStore->readAllValues();
+}
+
+}  // impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
new file mode 100644
index 0000000..e0874e2
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_
+
+#include <map>
+#include <memory>
+#include <sys/socket.h>
+#include <thread>
+#include <unordered_set>
+
+#include <utils/SystemClock.h>
+
+#include "VehicleHalProto.pb.h"
+
+#include <vhal_v2_0/RecurrentTimer.h>
+#include <vhal_v2_0/VehicleHal.h>
+#include "vhal_v2_0/VehiclePropertyStore.h"
+
+#include "DefaultConfig.h"
+#include "VehicleHalProto.pb.h"
+#include "VehicleEmulator.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+/** Implementation of VehicleHal that connected to emulator instead of real vehicle network. */
+class EmulatedVehicleHal : public EmulatedVehicleHalIface {
+public:
+    EmulatedVehicleHal(VehiclePropertyStore* propStore);
+    ~EmulatedVehicleHal() = default;
+
+    //  Methods from VehicleHal
+    void onCreate() override;
+    std::vector<VehiclePropConfig> listProperties() override;
+    VehiclePropValuePtr get(const VehiclePropValue& requestedPropValue,
+                            StatusCode* outStatus) override;
+    StatusCode set(const VehiclePropValue& propValue) override;
+    StatusCode subscribe(int32_t property, int32_t areas, float sampleRate) override;
+    StatusCode unsubscribe(int32_t property) override;
+
+    //  Methods from EmulatedVehicleHalIface
+    bool setPropertyFromVehicle(const VehiclePropValue& propValue) override;
+    std::vector<VehiclePropValue> getAllProperties() const override;
+
+private:
+    constexpr std::chrono::nanoseconds hertzToNanoseconds(float hz) const {
+        return std::chrono::nanoseconds(static_cast<int64_t>(1000000000L / hz));
+    }
+
+    void onContinuousPropertyTimer(const std::vector<int32_t>& properties);
+    bool isContinuousProperty(int32_t propId) const;
+
+private:
+    VehiclePropertyStore* mPropStore;
+    std::unordered_set<int32_t> mHvacPowerProps;
+    RecurrentTimer mRecurrentTimer;
+};
+
+}  // impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+
+#endif  // android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp
new file mode 100644
index 0000000..38cb743
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "VehicleEmulator_v2_0"
+#include <android/log.h>
+
+#include <algorithm>
+#include <android-base/properties.h>
+#include <utils/SystemClock.h>
+
+#include <vhal_v2_0/VehicleUtils.h>
+
+#include "PipeComm.h"
+#include "SocketComm.h"
+
+#include "VehicleEmulator.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+std::unique_ptr<CommBase> CommFactory::create() {
+    bool isEmulator = android::base::GetBoolProperty("ro.kernel.qemu", false);
+
+    if (isEmulator) {
+        return std::make_unique<PipeComm>();
+    } else {
+        return std::make_unique<SocketComm>();
+    }
+}
+
+VehicleEmulator::~VehicleEmulator() {
+    mExit = true;   // Notify thread to finish and wait for it to terminate.
+    mComm->stop();  // Close emulator socket if it is open.
+    if (mThread.joinable()) mThread.join();
+}
+
+void VehicleEmulator::doSetValueFromClient(const VehiclePropValue& propValue) {
+    emulator::EmulatorMessage msg;
+    emulator::VehiclePropValue *val = msg.add_value();
+    populateProtoVehiclePropValue(val, &propValue);
+    msg.set_status(emulator::RESULT_OK);
+    msg.set_msg_type(emulator::SET_PROPERTY_ASYNC);
+    txMsg(msg);
+}
+
+void VehicleEmulator::doGetConfig(VehicleEmulator::EmulatorMessage& rxMsg,
+                                  VehicleEmulator::EmulatorMessage& respMsg) {
+    std::vector<VehiclePropConfig> configs = mHal->listProperties();
+    emulator::VehiclePropGet getProp = rxMsg.prop(0);
+
+    respMsg.set_msg_type(emulator::GET_CONFIG_RESP);
+    respMsg.set_status(emulator::ERROR_INVALID_PROPERTY);
+
+    for (auto& config : configs) {
+        // Find the config we are looking for
+        if (config.prop == getProp.prop()) {
+            emulator::VehiclePropConfig* protoCfg = respMsg.add_config();
+            populateProtoVehicleConfig(protoCfg, config);
+            respMsg.set_status(emulator::RESULT_OK);
+            break;
+        }
+    }
+}
+
+void VehicleEmulator::doGetConfigAll(VehicleEmulator::EmulatorMessage& /* rxMsg */,
+                                     VehicleEmulator::EmulatorMessage& respMsg) {
+    std::vector<VehiclePropConfig> configs = mHal->listProperties();
+
+    respMsg.set_msg_type(emulator::GET_CONFIG_ALL_RESP);
+    respMsg.set_status(emulator::RESULT_OK);
+
+    for (auto& config : configs) {
+        emulator::VehiclePropConfig* protoCfg = respMsg.add_config();
+        populateProtoVehicleConfig(protoCfg, config);
+    }
+}
+
+void VehicleEmulator::doGetProperty(VehicleEmulator::EmulatorMessage& rxMsg,
+                                    VehicleEmulator::EmulatorMessage& respMsg)  {
+    int32_t areaId = 0;
+    emulator::VehiclePropGet getProp = rxMsg.prop(0);
+    int32_t propId = getProp.prop();
+    emulator::Status status = emulator::ERROR_INVALID_PROPERTY;
+
+    respMsg.set_msg_type(emulator::GET_PROPERTY_RESP);
+
+    if (getProp.has_area_id()) {
+        areaId = getProp.area_id();
+    }
+
+    {
+        VehiclePropValue request = { .prop = propId, .areaId = areaId };
+        StatusCode halStatus;
+        auto val = mHal->get(request, &halStatus);
+        if (val != nullptr) {
+            emulator::VehiclePropValue* protoVal = respMsg.add_value();
+            populateProtoVehiclePropValue(protoVal, val.get());
+            status = emulator::RESULT_OK;
+        }
+    }
+
+    respMsg.set_status(status);
+}
+
+void VehicleEmulator::doGetPropertyAll(VehicleEmulator::EmulatorMessage& /* rxMsg */,
+                                       VehicleEmulator::EmulatorMessage& respMsg)  {
+    respMsg.set_msg_type(emulator::GET_PROPERTY_ALL_RESP);
+    respMsg.set_status(emulator::RESULT_OK);
+
+    {
+        for (const auto& prop : mHal->getAllProperties()) {
+            emulator::VehiclePropValue* protoVal = respMsg.add_value();
+            populateProtoVehiclePropValue(protoVal, &prop);
+        }
+    }
+}
+
+void VehicleEmulator::doSetProperty(VehicleEmulator::EmulatorMessage& rxMsg,
+                                    VehicleEmulator::EmulatorMessage& respMsg) {
+    emulator::VehiclePropValue protoVal = rxMsg.value(0);
+    VehiclePropValue val = {
+        .prop = protoVal.prop(),
+        .areaId = protoVal.area_id(),
+        .timestamp = elapsedRealtimeNano(),
+    };
+
+    respMsg.set_msg_type(emulator::SET_PROPERTY_RESP);
+
+    // Copy value data if it is set.  This automatically handles complex data types if needed.
+    if (protoVal.has_string_value()) {
+        val.value.stringValue = protoVal.string_value().c_str();
+    }
+
+    if (protoVal.has_bytes_value()) {
+        val.value.bytes = std::vector<uint8_t> { protoVal.bytes_value().begin(),
+                                                 protoVal.bytes_value().end() };
+    }
+
+    if (protoVal.int32_values_size() > 0) {
+        val.value.int32Values = std::vector<int32_t> { protoVal.int32_values().begin(),
+                                                       protoVal.int32_values().end() };
+    }
+
+    if (protoVal.int64_values_size() > 0) {
+        val.value.int64Values = std::vector<int64_t> { protoVal.int64_values().begin(),
+                                                       protoVal.int64_values().end() };
+    }
+
+    if (protoVal.float_values_size() > 0) {
+        val.value.floatValues = std::vector<float> { protoVal.float_values().begin(),
+                                                     protoVal.float_values().end() };
+    }
+
+    bool halRes = mHal->setPropertyFromVehicle(val);
+    respMsg.set_status(halRes ? emulator::RESULT_OK : emulator::ERROR_INVALID_PROPERTY);
+}
+
+void VehicleEmulator::txMsg(emulator::EmulatorMessage& txMsg) {
+    int numBytes = txMsg.ByteSize();
+    std::vector<uint8_t> msg(static_cast<size_t>(numBytes));
+
+    if (!txMsg.SerializeToArray(msg.data(), static_cast<int32_t>(msg.size()))) {
+        ALOGE("%s: SerializeToString failed!", __func__);
+        return;
+    }
+
+    if (mExit) {
+        ALOGW("%s: unable to transmit a message, connection closed", __func__);
+        return;
+    }
+
+    // Send the message
+    int retVal = mComm->write(msg);
+    if (retVal < 0) {
+        ALOGE("%s: Failed to tx message: retval=%d, errno=%d", __func__, retVal, errno);
+    }
+}
+
+void VehicleEmulator::parseRxProtoBuf(std::vector<uint8_t>& msg) {
+    emulator::EmulatorMessage rxMsg;
+    emulator::EmulatorMessage respMsg;
+
+    if (rxMsg.ParseFromArray(msg.data(), static_cast<int32_t>(msg.size()))) {
+        switch (rxMsg.msg_type()) {
+            case emulator::GET_CONFIG_CMD:
+                doGetConfig(rxMsg, respMsg);
+                break;
+            case emulator::GET_CONFIG_ALL_CMD:
+                doGetConfigAll(rxMsg, respMsg);
+                break;
+            case emulator::GET_PROPERTY_CMD:
+                doGetProperty(rxMsg, respMsg);
+                break;
+            case emulator::GET_PROPERTY_ALL_CMD:
+                doGetPropertyAll(rxMsg, respMsg);
+                break;
+            case emulator::SET_PROPERTY_CMD:
+                doSetProperty(rxMsg, respMsg);
+                break;
+            default:
+                ALOGW("%s: Unknown message received, type = %d", __func__, rxMsg.msg_type());
+                respMsg.set_status(emulator::ERROR_UNIMPLEMENTED_CMD);
+                break;
+        }
+
+        // Send the reply
+        txMsg(respMsg);
+    } else {
+        ALOGE("%s: ParseFromString() failed. msgSize=%d", __func__, static_cast<int>(msg.size()));
+    }
+}
+
+void VehicleEmulator::populateProtoVehicleConfig(emulator::VehiclePropConfig* protoCfg,
+                                                 const VehiclePropConfig& cfg) {
+    protoCfg->set_prop(cfg.prop);
+    protoCfg->set_access(toInt(cfg.access));
+    protoCfg->set_change_mode(toInt(cfg.changeMode));
+    protoCfg->set_value_type(toInt(getPropType(cfg.prop)));
+
+    if (!isGlobalProp(cfg.prop)) {
+        protoCfg->set_supported_areas(cfg.supportedAreas);
+    }
+
+    for (auto& configElement : cfg.configArray) {
+        protoCfg->add_config_array(configElement);
+    }
+
+    if (cfg.configString.size() > 0) {
+        protoCfg->set_config_string(cfg.configString.c_str(), cfg.configString.size());
+    }
+
+    // Populate the min/max values based on property type
+    switch (getPropType(cfg.prop)) {
+        case VehiclePropertyType::STRING:
+        case VehiclePropertyType::BOOLEAN:
+        case VehiclePropertyType::INT32_VEC:
+        case VehiclePropertyType::FLOAT_VEC:
+        case VehiclePropertyType::BYTES:
+        case VehiclePropertyType::COMPLEX:
+            // Do nothing.  These types don't have min/max values
+            break;
+        case VehiclePropertyType::INT64:
+            if (cfg.areaConfigs.size() > 0) {
+                emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
+                aCfg->set_min_int64_value(cfg.areaConfigs[0].minInt64Value);
+                aCfg->set_max_int64_value(cfg.areaConfigs[0].maxInt64Value);
+            }
+            break;
+        case VehiclePropertyType::FLOAT:
+            if (cfg.areaConfigs.size() > 0) {
+                emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
+                aCfg->set_min_float_value(cfg.areaConfigs[0].minFloatValue);
+                aCfg->set_max_float_value(cfg.areaConfigs[0].maxFloatValue);
+            }
+            break;
+        case VehiclePropertyType::INT32:
+            if (cfg.areaConfigs.size() > 0) {
+                emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
+                aCfg->set_min_int32_value(cfg.areaConfigs[0].minInt32Value);
+                aCfg->set_max_int32_value(cfg.areaConfigs[0].maxInt32Value);
+            }
+            break;
+        default:
+            ALOGW("%s: Unknown property type:  0x%x", __func__, toInt(getPropType(cfg.prop)));
+            break;
+    }
+
+    protoCfg->set_min_sample_rate(cfg.minSampleRate);
+    protoCfg->set_max_sample_rate(cfg.maxSampleRate);
+}
+
+void VehicleEmulator::populateProtoVehiclePropValue(emulator::VehiclePropValue* protoVal,
+                                                    const VehiclePropValue* val) {
+    protoVal->set_prop(val->prop);
+    protoVal->set_value_type(toInt(getPropType(val->prop)));
+    protoVal->set_timestamp(val->timestamp);
+    protoVal->set_area_id(val->areaId);
+
+    // Copy value data if it is set.
+    //  - for bytes and strings, this is indicated by size > 0
+    //  - for int32, int64, and float, copy the values if vectors have data
+    if (val->value.stringValue.size() > 0) {
+        protoVal->set_string_value(val->value.stringValue.c_str(), val->value.stringValue.size());
+    }
+
+    if (val->value.bytes.size() > 0) {
+        protoVal->set_bytes_value(val->value.bytes.data(), val->value.bytes.size());
+    }
+
+    for (auto& int32Value : val->value.int32Values) {
+        protoVal->add_int32_values(int32Value);
+    }
+
+    for (auto& int64Value : val->value.int64Values) {
+        protoVal->add_int64_values(int64Value);
+    }
+
+    for (auto& floatValue : val->value.floatValues) {
+        protoVal->add_float_values(floatValue);
+    }
+}
+
+void VehicleEmulator::rxMsg() {
+    while (!mExit) {
+        std::vector<uint8_t> msg = mComm->read();
+
+        if (msg.size() > 0) {
+            // Received a message.
+            parseRxProtoBuf(msg);
+        } else {
+            // This happens when connection is closed
+            ALOGD("%s: msgSize=%zu", __func__, msg.size());
+            break;
+        }
+    }
+}
+
+void VehicleEmulator::rxThread() {
+    if (mExit) return;
+
+    int retVal = mComm->open();
+    if (retVal != 0) mExit = true;
+
+    // Comms are properly opened
+    while (!mExit) {
+        retVal = mComm->connect();
+
+        if (retVal >= 0) {
+            rxMsg();
+        }
+
+        // Check every 100ms for a new connection
+        std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    }
+}
+
+}  // impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h
new file mode 100644
index 0000000..9a75ddc
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_automotive_vehicle_V2_0_impl_VehicleHalEmulator_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_VehicleHalEmulator_H_
+
+#include <memory>
+#include <thread>
+#include <vector>
+#include "vhal_v2_0/VehicleHal.h"
+
+#include "CommBase.h"
+#include "VehicleHalProto.pb.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+class VehicleEmulator;  // Forward declaration.
+
+/** Extension of VehicleHal that used by VehicleEmulator. */
+class EmulatedVehicleHalIface : public VehicleHal {
+public:
+    virtual bool setPropertyFromVehicle(const VehiclePropValue& propValue) = 0;
+    virtual std::vector<VehiclePropValue> getAllProperties() const = 0;
+
+    void registerEmulator(VehicleEmulator* emulator) {
+        ALOGI("%s, emulator: %p", __func__, emulator);
+        std::lock_guard<std::mutex> g(mEmulatorLock);
+        mEmulator = emulator;
+    }
+
+protected:
+    VehicleEmulator* getEmulatorOrDie() {
+        std::lock_guard<std::mutex> g(mEmulatorLock);
+        ALOGI("%s, emulator: %p", __func__, mEmulator);
+        assert(mEmulator != nullptr);
+        return mEmulator;
+    }
+
+private:
+    mutable std::mutex mEmulatorLock;
+    VehicleEmulator* mEmulator;
+};
+
+struct CommFactory {
+    static std::unique_ptr<CommBase> create();
+};
+
+/**
+ * Emulates vehicle by providing controlling interface from host side either through ADB or Pipe.
+ */
+class VehicleEmulator {
+public:
+    VehicleEmulator(EmulatedVehicleHalIface* hal,
+                    std::unique_ptr<CommBase> comm = CommFactory::create())
+            : mHal { hal },
+              mComm(comm.release()),
+              mThread { &VehicleEmulator::rxThread, this} {
+        mHal->registerEmulator(this);
+    }
+    virtual ~VehicleEmulator();
+
+    void doSetValueFromClient(const VehiclePropValue& propValue);
+
+private:
+    using EmulatorMessage = emulator::EmulatorMessage;
+
+    void doGetConfig(EmulatorMessage& rxMsg, EmulatorMessage& respMsg);
+    void doGetConfigAll(EmulatorMessage& rxMsg, EmulatorMessage& respMsg);
+    void doGetProperty(EmulatorMessage& rxMsg, EmulatorMessage& respMsg);
+    void doGetPropertyAll(EmulatorMessage& rxMsg, EmulatorMessage& respMsg);
+    void doSetProperty(EmulatorMessage& rxMsg, EmulatorMessage& respMsg);
+    void txMsg(emulator::EmulatorMessage& txMsg);
+    void parseRxProtoBuf(std::vector<uint8_t>& msg);
+    void populateProtoVehicleConfig(emulator::VehiclePropConfig* protoCfg,
+                                    const VehiclePropConfig& cfg);
+    void populateProtoVehiclePropValue(emulator::VehiclePropValue* protoVal,
+                                       const VehiclePropValue* val);
+    void rxMsg();
+    void rxThread();
+
+private:
+    std::atomic<bool> mExit { false };
+    EmulatedVehicleHalIface* mHal;
+    std::unique_ptr<CommBase> mComm;
+    std::thread mThread;
+};
+
+}  // impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif // android_hardware_automotive_vehicle_V2_0_impl_VehicleHalEmulator_H_