Merge changes from topic "rvc-dev-trout" into rvc-dev

* changes:
  Merge nested namesapces
  Split client and server impl
  Split vehicle client and server interface header
  Add headers and macros for building VHAL server for AGL
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index 8e57901..e529675 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -63,6 +63,8 @@
         "impl/vhal_v2_0/CommConn.cpp",
         "impl/vhal_v2_0/EmulatedVehicleConnector.cpp",
         "impl/vhal_v2_0/EmulatedVehicleHal.cpp",
+        "impl/vhal_v2_0/VehicleHalClient.cpp",
+        "impl/vhal_v2_0/VehicleHalServer.cpp",
         "impl/vhal_v2_0/VehicleEmulator.cpp",
         "impl/vhal_v2_0/PipeComm.cpp",
         "impl/vhal_v2_0/ProtoMessageConverter.cpp",
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleClient.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleClient.h
new file mode 100644
index 0000000..5e4bf27
--- /dev/null
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleClient.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <vector>
+
+#include <android/hardware/automotive/vehicle/2.0/types.h>
+
+namespace android::hardware::automotive::vehicle::V2_0 {
+
+/**
+ *  Vehicle HAL talks to the vehicle through a client, instead of accessing
+ *  the car bus directly, to give us more flexibility on the implementation.
+ *  Android OS do not need direct access to the vehicle, and the communication
+ *  channel is also customizable.
+ *
+ *  Client lives on the Android (HAL) side to talk to the vehicle
+ */
+class IVehicleClient {
+  public:
+    IVehicleClient() = default;
+
+    IVehicleClient(const IVehicleClient&) = delete;
+
+    IVehicleClient& operator=(const IVehicleClient&) = delete;
+
+    IVehicleClient(IVehicleClient&&) = default;
+
+    virtual ~IVehicleClient() = default;
+
+    // Get configuration of all properties from server
+    virtual std::vector<VehiclePropConfig> getAllPropertyConfig() const = 0;
+
+    // Send the set property request to server
+    // updateStatus indicate if VHal should change the status of the value
+    // it should be false except injecting values for e2e tests
+    virtual StatusCode setProperty(const VehiclePropValue& value, bool updateStatus) = 0;
+
+    // Receive a new property value from server
+    // updateStatus is true if and only if the value is
+    // generated by car (ECU/fake generator/injected)
+    virtual void onPropertyValue(const VehiclePropValue& value, bool updateStatus) = 0;
+
+    // Dump method forwarded from HIDL's debug()
+    // If implemented, it must return whether the caller should dump its state.
+    virtual bool dump(const hidl_handle& /* handle */, const hidl_vec<hidl_string>& /* options */) {
+        return true;
+    }
+};
+
+}  // namespace android::hardware::automotive::vehicle::V2_0
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h
index 00b5afe..2908a55 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h
@@ -21,6 +21,9 @@
 
 #include <android/hardware/automotive/vehicle/2.0/types.h>
 
+#include "VehicleClient.h"
+#include "VehicleServer.h"
+
 namespace android {
 namespace hardware {
 namespace automotive {
@@ -34,85 +37,6 @@
  */
 
 /**
- *  Vehicle HAL talks to the vehicle through a client, instead of accessing
- *  the car bus directly, to give us more flexibility on the implementation.
- *  Android OS do not need direct access to the vehicle, and the communication
- *  channel is also customizable.
- *
- *  Client lives on the Android (HAL) side to talk to the vehicle
- */
-class IVehicleClient {
-  public:
-    IVehicleClient() = default;
-
-    IVehicleClient(const IVehicleClient&) = delete;
-
-    IVehicleClient& operator=(const IVehicleClient&) = delete;
-
-    IVehicleClient(IVehicleClient&&) = default;
-
-    virtual ~IVehicleClient() = default;
-
-    // Get configuration of all properties from server
-    virtual std::vector<VehiclePropConfig> getAllPropertyConfig() const = 0;
-
-    // Send the set property request to server
-    // updateStatus indicate if VHal should change the status of the value
-    // it should be false except injecting values for e2e tests
-    virtual StatusCode setProperty(const VehiclePropValue& value, bool updateStatus) = 0;
-
-    // Receive a new property value from server
-    // updateStatus is true if and only if the value is
-    // generated by car (ECU/fake generator/injected)
-    virtual void onPropertyValue(const VehiclePropValue& value, bool updateStatus) = 0;
-
-    // Dump method forwarded from HIDL's debug()
-    // If implemented, it must return whether the caller should dump its state.
-    virtual bool dump(const hidl_handle& /* handle */, const hidl_vec<hidl_string>& /* options */) {
-        return true;
-    }
-};
-
-/**
- *  Server lives on the vehicle side to talk to Android HAL
- */
-class IVehicleServer {
-  public:
-    IVehicleServer() = default;
-
-    IVehicleServer(const IVehicleServer&) = delete;
-
-    IVehicleServer& operator=(const IVehicleServer&) = delete;
-
-    IVehicleServer(IVehicleServer&&) = default;
-
-    virtual ~IVehicleServer() = default;
-
-    // Receive the get property configuration request from HAL.
-    // Return a list of all property config
-    virtual std::vector<VehiclePropConfig> onGetAllPropertyConfig() const = 0;
-
-    // Receive the set property request from HAL.
-    // Process the setting and return the status code
-    // updateStatus indicate if VHal should change the status of the value
-    // it should be false except injecting values for e2e tests
-    virtual StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) = 0;
-
-    // Receive a new property value from car (via direct connection to the car bus or the emulator)
-    // and forward the value to HAL
-    // updateStatus is true if and only if the value is
-    // generated by car (ECU/fake generator/injected)
-    virtual void onPropertyValueFromCar(const VehiclePropValue& value, bool updateStatus) = 0;
-
-    // Dump method forwarded from HIDL's debug()
-    // If implemented, it must return whether the caller should dump its state.
-    virtual bool onDump(const hidl_handle& /* handle */,
-                        const hidl_vec<hidl_string>& /* options */) {
-        return true;
-    }
-};
-
-/**
  *  If Android has direct access to the vehicle, then the client and
  *  the server may act in passthrough mode to avoid extra IPC
  *
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h
index 946e74d..e3cbf2e 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h
@@ -21,6 +21,7 @@
 #include <deque>
 #include <map>
 #include <mutex>
+#include <memory>
 
 #include <android/hardware/automotive/vehicle/2.0/types.h>
 
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleServer.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleServer.h
new file mode 100644
index 0000000..ba9799a
--- /dev/null
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleServer.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <vector>
+
+#include <android/hardware/automotive/vehicle/2.0/types.h>
+
+namespace android::hardware::automotive::vehicle::V2_0 {
+
+/**
+ *  Server lives on the vehicle side to talk to Android HAL.
+ *  Note that the server may not be run on Android
+ */
+class IVehicleServer {
+  public:
+    IVehicleServer() = default;
+
+    IVehicleServer(const IVehicleServer&) = delete;
+
+    IVehicleServer& operator=(const IVehicleServer&) = delete;
+
+    IVehicleServer(IVehicleServer&&) = default;
+
+    virtual ~IVehicleServer() = default;
+
+    // Receive the get property configuration request from HAL.
+    // Return a list of all property config
+    virtual std::vector<VehiclePropConfig> onGetAllPropertyConfig() const = 0;
+
+    // Receive the set property request from HAL.
+    // Process the setting and return the status code
+    // updateStatus indicate if VHal should change the status of the value
+    // it should be false except injecting values for e2e tests
+    virtual StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) = 0;
+
+    // Receive a new property value from car (via direct connection to the car bus or the emulator)
+    // and forward the value to HAL
+    // updateStatus is true if and only if the value is
+    // generated by car (ECU/fake generator/injected)
+    virtual void onPropertyValueFromCar(const VehiclePropValue& value, bool updateStatus) = 0;
+
+    // TODO (chenhaosjtuacm): fix this since there are no HIDL in non-Android OS
+#ifdef __ANDROID__
+    // Dump method forwarded from HIDL's debug()
+    // If implemented, it must return whether the caller should dump its state.
+    virtual bool onDump(const hidl_handle& /* handle */,
+                        const hidl_vec<hidl_string>& /* options */) {
+        return true;
+    }
+#endif  // __ANDROID__
+};
+
+}  // namespace android::hardware::automotive::vehicle::V2_0
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleUtils.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleUtils.h
index f97dfa1..9553415 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleUtils.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleUtils.h
@@ -19,7 +19,9 @@
 
 #include <memory>
 
+#ifdef __ANDROID__
 #include <hidl/HidlSupport.h>
+#endif
 
 #include <android/hardware/automotive/vehicle/2.0/types.h>
 
@@ -69,6 +71,8 @@
 void copyVehicleRawValue(VehiclePropValue::RawValue* dest,
                                 const VehiclePropValue::RawValue& src);
 
+#ifdef __ANDROID__
+
 template<typename T>
 void shallowCopyHidlVec(hidl_vec<T>* dest, const hidl_vec<T>& src);
 
@@ -76,6 +80,8 @@
 
 void shallowCopy(VehiclePropValue* dest, const VehiclePropValue& src);
 
+#endif  // __ANDROID__
+
 }  // namespace V2_0
 }  // namespace vehicle
 }  // namespace automotive
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleObjectPool.cpp b/automotive/vehicle/2.0/default/common/src/VehicleObjectPool.cpp
index 40dd56e..0947c9f 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleObjectPool.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleObjectPool.cpp
@@ -131,7 +131,7 @@
         ALOGE("Discarding value for prop 0x%x because it contains "
                   "data that is not consistent with this pool. "
                   "Expected type: %d, vector size: %zu",
-              o->prop, mPropType, mVectorSize);
+              o->prop, toInt(mPropType), mVectorSize);
         delete o;
     } else {
         ObjectPool<VehiclePropValue>::recycle(o);
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleUtils.cpp b/automotive/vehicle/2.0/default/common/src/VehicleUtils.cpp
index 5b6816e..c16b29a 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleUtils.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleUtils.cpp
@@ -52,7 +52,7 @@
         case VehiclePropertyType::MIXED:
             break; // Valid, but nothing to do.
         default:
-            ALOGE("createVehiclePropValue: unknown type: %d", type);
+            ALOGE("createVehiclePropValue: unknown type: %d", toInt(type));
             val.reset(nullptr);
     }
     return val;
@@ -78,13 +78,6 @@
     }
 }
 
-template<typename T>
-inline void copyHidlVec(hidl_vec <T>* dest, const hidl_vec <T>& src) {
-    for (size_t i = 0; i < std::min(dest->size(), src.size()); i++) {
-        (*dest)[i] = src[i];
-    }
-}
-
 void copyVehicleRawValue(VehiclePropValue::RawValue* dest,
                          const VehiclePropValue::RawValue& src) {
     dest->int32Values = src.int32Values;
@@ -94,6 +87,15 @@
     dest->stringValue = src.stringValue;
 }
 
+#ifdef __ANDROID__
+
+template<typename T>
+inline void copyHidlVec(hidl_vec <T>* dest, const hidl_vec <T>& src) {
+    for (size_t i = 0; i < std::min(dest->size(), src.size()); i++) {
+        (*dest)[i] = src[i];
+    }
+}
+
 template<typename T>
 void shallowCopyHidlVec(hidl_vec <T>* dest, const hidl_vec <T>& src) {
     if (src.size() > 0) {
@@ -123,6 +125,7 @@
     shallowCopyHidlStr(&dest->value.stringValue, src.value.stringValue);
 }
 
+#endif  // __ANDROID__
 
 //}  // namespace utils
 
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 4b94800..53c9ffb 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
@@ -17,9 +17,11 @@
 #ifndef android_hardware_automotive_vehicle_V2_0_impl_DefaultConfig_H_
 #define android_hardware_automotive_vehicle_V2_0_impl_DefaultConfig_H_
 
-#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
+#include <android/hardware/automotive/vehicle/2.0/types.h>
 #include <vhal_v2_0/VehicleUtils.h>
 
+#include <map>
+
 namespace android {
 namespace hardware {
 namespace automotive {
@@ -1017,7 +1019,6 @@
                                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                         },
         },
-
 };
 
 }  // impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
index 7f90914..9c3c95f 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
@@ -35,346 +35,16 @@
 
 namespace impl {
 
-void EmulatedVehicleClient::onPropertyValue(const VehiclePropValue& value, bool updateStatus) {
-    if (!mPropCallback) {
-        LOG(ERROR) << __func__ << ": PropertyCallBackType is not registered!";
-        return;
-    }
-    return mPropCallback(value, updateStatus);
-}
+class EmulatedPassthroughConnector : public PassthroughConnector {
+  public:
+    bool onDump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
 
-void EmulatedVehicleClient::registerPropertyValueCallback(PropertyCallBackType&& callback) {
-    if (mPropCallback) {
-        LOG(ERROR) << __func__ << ": Cannot register multiple callbacks!";
-        return;
-    }
-    mPropCallback = std::move(callback);
-}
+  private:
+    void dumpUserHal(int fd, std::string indent);
+};
 
-GeneratorHub* EmulatedVehicleServer::getGenerator() {
-    return &mGeneratorHub;
-}
-
-VehiclePropValuePool* EmulatedVehicleServer::getValuePool() const {
-    if (!mValuePool) {
-        LOG(WARNING) << __func__ << ": Value pool not set!";
-    }
-    return mValuePool;
-}
-
-void EmulatedVehicleServer::setValuePool(VehiclePropValuePool* valuePool) {
-    if (!valuePool) {
-        LOG(WARNING) <<  __func__ << ": Setting value pool to nullptr!";
-    }
-    mValuePool = valuePool;
-}
-
-void EmulatedVehicleServer::onFakeValueGenerated(const VehiclePropValue& value) {
-    constexpr bool updateStatus = true;
-    LOG(DEBUG) << __func__ << ": " << toString(value);
-    auto updatedPropValue = getValuePool()->obtain(value);
-    if (updatedPropValue) {
-        updatedPropValue->timestamp = value.timestamp;
-        updatedPropValue->status = VehiclePropertyStatus::AVAILABLE;
-        onPropertyValueFromCar(*updatedPropValue, updateStatus);
-    }
-}
-
-std::vector<VehiclePropConfig> EmulatedVehicleServer::onGetAllPropertyConfig() const {
-    std::vector<VehiclePropConfig> vehiclePropConfigs;
-    constexpr size_t numOfVehiclePropConfigs =
-            sizeof(kVehicleProperties) / sizeof(kVehicleProperties[0]);
-    vehiclePropConfigs.reserve(numOfVehiclePropConfigs);
-    for (auto& it : kVehicleProperties) {
-        vehiclePropConfigs.emplace_back(it.config);
-    }
-    return vehiclePropConfigs;
-}
-
-StatusCode EmulatedVehicleServer::handleGenerateFakeDataRequest(const VehiclePropValue& request) {
-    constexpr bool updateStatus = true;
-
-    LOG(INFO) << __func__;
-    const auto& v = request.value;
-    if (!v.int32Values.size()) {
-        LOG(ERROR) << __func__ << ": expected at least \"command\" field in int32Values";
-        return StatusCode::INVALID_ARG;
-    }
-
-    FakeDataCommand command = static_cast<FakeDataCommand>(v.int32Values[0]);
-
-    switch (command) {
-        case FakeDataCommand::StartLinear: {
-            LOG(INFO) << __func__ << ", FakeDataCommand::StartLinear";
-            if (v.int32Values.size() < 2) {
-                LOG(ERROR) << __func__ << ": expected property ID in int32Values";
-                return StatusCode::INVALID_ARG;
-            }
-            if (!v.int64Values.size()) {
-                LOG(ERROR) << __func__ << ": interval is not provided in int64Values";
-                return StatusCode::INVALID_ARG;
-            }
-            if (v.floatValues.size() < 3) {
-                LOG(ERROR) << __func__ << ": expected at least 3 elements in floatValues, got: "
-                      << v.floatValues.size();
-                return StatusCode::INVALID_ARG;
-            }
-            int32_t cookie = v.int32Values[1];
-            getGenerator()->registerGenerator(cookie,
-                                              std::make_unique<LinearFakeValueGenerator>(request));
-            break;
-        }
-        case FakeDataCommand::StartJson: {
-            LOG(INFO) << __func__ << ", FakeDataCommand::StartJson";
-            if (v.stringValue.empty()) {
-                LOG(ERROR) << __func__ << ": path to JSON file is missing";
-                return StatusCode::INVALID_ARG;
-            }
-            int32_t cookie = std::hash<std::string>()(v.stringValue);
-            getGenerator()->registerGenerator(cookie,
-                                              std::make_unique<JsonFakeValueGenerator>(request));
-            break;
-        }
-        case FakeDataCommand::StopLinear: {
-            LOG(INFO) << __func__ << ", FakeDataCommand::StopLinear";
-            if (v.int32Values.size() < 2) {
-                LOG(ERROR) << __func__ << ": expected property ID in int32Values";
-                return StatusCode::INVALID_ARG;
-            }
-            int32_t cookie = v.int32Values[1];
-            getGenerator()->unregisterGenerator(cookie);
-            break;
-        }
-        case FakeDataCommand::StopJson: {
-            LOG(INFO) << __func__ << ", FakeDataCommand::StopJson";
-            if (v.stringValue.empty()) {
-                LOG(ERROR) << __func__ << ": path to JSON file is missing";
-                return StatusCode::INVALID_ARG;
-            }
-            int32_t cookie = std::hash<std::string>()(v.stringValue);
-            getGenerator()->unregisterGenerator(cookie);
-            break;
-        }
-        case FakeDataCommand::KeyPress: {
-            LOG(INFO) << __func__ << ", FakeDataCommand::KeyPress";
-            int32_t keyCode = request.value.int32Values[2];
-            int32_t display = request.value.int32Values[3];
-            // Send back to HAL
-            onPropertyValueFromCar(
-                    *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_DOWN, keyCode, display),
-                    updateStatus);
-            onPropertyValueFromCar(
-                    *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display),
-                    updateStatus);
-            break;
-        }
-        default: {
-            LOG(ERROR) << __func__ << ": unexpected command: " << toInt(command);
-            return StatusCode::INVALID_ARG;
-        }
-    }
-    return StatusCode::OK;
-}
-
-VehicleHal::VehiclePropValuePtr EmulatedVehicleServer::createApPowerStateReq(
-    VehicleApPowerStateReq state, int32_t param) {
-    auto req = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 2);
-    req->prop = toInt(VehicleProperty::AP_POWER_STATE_REQ);
-    req->areaId = 0;
-    req->timestamp = elapsedRealtimeNano();
-    req->status = VehiclePropertyStatus::AVAILABLE;
-    req->value.int32Values[0] = toInt(state);
-    req->value.int32Values[1] = param;
-    return req;
-}
-
-VehicleHal::VehiclePropValuePtr EmulatedVehicleServer::createHwInputKeyProp(
-        VehicleHwKeyInputAction action, int32_t keyCode, int32_t targetDisplay) {
-    auto keyEvent = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 3);
-    keyEvent->prop = toInt(VehicleProperty::HW_KEY_INPUT);
-    keyEvent->areaId = 0;
-    keyEvent->timestamp = elapsedRealtimeNano();
-    keyEvent->status = VehiclePropertyStatus::AVAILABLE;
-    keyEvent->value.int32Values[0] = toInt(action);
-    keyEvent->value.int32Values[1] = keyCode;
-    keyEvent->value.int32Values[2] = targetDisplay;
-    return keyEvent;
-}
-
-StatusCode EmulatedVehicleServer::onSetProperty(const VehiclePropValue& value, bool updateStatus) {
-    // Some properties need to be treated non-trivially
-    switch (value.prop) {
-        case kGenerateFakeDataControllingProperty:
-            return handleGenerateFakeDataRequest(value);
-
-        // set the value from vehicle side, used in end to end test.
-        case kSetIntPropertyFromVehicleForTest: {
-            auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::INT32, 1);
-            updatedPropValue->prop = value.value.int32Values[0];
-            updatedPropValue->value.int32Values[0] = value.value.int32Values[1];
-            updatedPropValue->timestamp = value.value.int64Values[0];
-            updatedPropValue->areaId = value.areaId;
-            onPropertyValueFromCar(*updatedPropValue, updateStatus);
-            return StatusCode::OK;
-        }
-        case kSetFloatPropertyFromVehicleForTest: {
-            auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::FLOAT, 1);
-            updatedPropValue->prop = value.value.int32Values[0];
-            updatedPropValue->value.floatValues[0] = value.value.floatValues[0];
-            updatedPropValue->timestamp = value.value.int64Values[0];
-            updatedPropValue->areaId = value.areaId;
-            onPropertyValueFromCar(*updatedPropValue, updateStatus);
-            return StatusCode::OK;
-        }
-        case kSetBooleanPropertyFromVehicleForTest: {
-            auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::BOOLEAN, 1);
-            updatedPropValue->prop = value.value.int32Values[1];
-            updatedPropValue->value.int32Values[0] = value.value.int32Values[0];
-            updatedPropValue->timestamp = value.value.int64Values[0];
-            updatedPropValue->areaId = value.areaId;
-            onPropertyValueFromCar(*updatedPropValue, updateStatus);
-            return StatusCode::OK;
-        }
-
-        case AP_POWER_STATE_REPORT:
-            switch (value.value.int32Values[0]) {
-                case toInt(VehicleApPowerStateReport::DEEP_SLEEP_EXIT):
-                case toInt(VehicleApPowerStateReport::SHUTDOWN_CANCELLED):
-                case toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL):
-                    // CPMS is in WAIT_FOR_VHAL state, simply move to ON
-                    // Send back to HAL
-                    // ALWAYS update status for generated property value
-                    onPropertyValueFromCar(*createApPowerStateReq(VehicleApPowerStateReq::ON, 0),
-                                           true /* updateStatus */);
-                    break;
-                case toInt(VehicleApPowerStateReport::DEEP_SLEEP_ENTRY):
-                case toInt(VehicleApPowerStateReport::SHUTDOWN_START):
-                    // CPMS is in WAIT_FOR_FINISH state, send the FINISHED command
-                    // Send back to HAL
-                    // ALWAYS update status for generated property value
-                    onPropertyValueFromCar(
-                            *createApPowerStateReq(VehicleApPowerStateReq::FINISHED, 0),
-                            true /* updateStatus */);
-                    break;
-                case toInt(VehicleApPowerStateReport::ON):
-                case toInt(VehicleApPowerStateReport::SHUTDOWN_POSTPONE):
-                case toInt(VehicleApPowerStateReport::SHUTDOWN_PREPARE):
-                    // Do nothing
-                    break;
-                default:
-                    // Unknown state
-                    break;
-            }
-            break;
-        case INITIAL_USER_INFO:
-            return onSetInitialUserInfo(value, updateStatus);
-        default:
-            break;
-    }
-
-    // In the real vhal, the value will be sent to Car ECU.
-    // We just pretend it is done here and send back to HAL
-    auto updatedPropValue = getValuePool()->obtain(value);
-    updatedPropValue->timestamp = elapsedRealtimeNano();
-
-    onPropertyValueFromCar(*updatedPropValue, updateStatus);
-    return StatusCode::OK;
-}
-
-/**
- * INITIAL_USER_INFO is called by Android when it starts, and it's expecting a property change
- * indicating what the initial user should be.
- *
- * During normal circumstances, the emulator will reply right away, passing a response if
- * InitialUserInfoResponseAction::DEFAULT (so Android could use its own logic to decide which user
- * to boot).
- *
- * But during development / testing, the behavior can be changed using lshal dump, which must use
- * the areaId to indicate what should happen next.
- *
- * So, the behavior of set(INITIAL_USER_INFO) is:
- *
- * - if it has an areaId, store the property into mInitialUserResponseFromCmd (as it was called by
- *   lshal).
- * - else if mInitialUserResponseFromCmd is not set, return a response with the same request id and
- *   InitialUserInfoResponseAction::DEFAULT
- * - else the behavior is defined by the areaId on mInitialUserResponseFromCmd:
- * - if it's 1, reply with mInitialUserResponseFromCmd and the right request id
- * - if it's 2, reply with mInitialUserResponseFromCmd but a wrong request id (so Android can test
- *   this error scenario)
- * - if it's 3, then don't send a property change (so Android can emulate a timeout)
- *
- */
-StatusCode EmulatedVehicleServer::onSetInitialUserInfo(const VehiclePropValue& value,
-                                                       bool updateStatus) {
-    // TODO: LOG calls below might be more suited to be DEBUG, but those are not being logged
-    // (even when explicitly calling setprop log.tag. As this class should be using ALOG instead of
-    // LOG, it's not worth investigating why...
-
-    if (value.value.int32Values.size() == 0) {
-        LOG(ERROR) << "set(INITIAL_USER_INFO): no int32values, ignoring it: " << toString(value);
-        return StatusCode::INVALID_ARG;
-    }
-
-    if (value.areaId != 0) {
-        LOG(INFO) << "set(INITIAL_USER_INFO) called from lshal; storing it: " << toString(value);
-        mInitialUserResponseFromCmd.reset(new VehiclePropValue(value));
-        return StatusCode::OK;
-    }
-    LOG(INFO) << "set(INITIAL_USER_INFO) called from Android: " << toString(value);
-
-    int32_t requestId = value.value.int32Values[0];
-
-    // Create the update property and set common values
-    auto updatedValue = createVehiclePropValue(VehiclePropertyType::MIXED, 0);
-    updatedValue->prop = INITIAL_USER_INFO;
-    updatedValue->timestamp = elapsedRealtimeNano();
-
-    if (mInitialUserResponseFromCmd == nullptr) {
-        updatedValue->value.int32Values.resize(2);
-        updatedValue->value.int32Values[0] = requestId;
-        updatedValue->value.int32Values[1] = (int32_t)InitialUserInfoResponseAction::DEFAULT;
-        LOG(INFO) << "no lshal response; returning InitialUserInfoResponseAction::DEFAULT: "
-                  << toString(*updatedValue);
-        onPropertyValueFromCar(*updatedValue, updateStatus);
-        return StatusCode::OK;
-    }
-
-    // mInitialUserResponseFromCmd is used for just one request
-    std::unique_ptr<VehiclePropValue> response = std::move(mInitialUserResponseFromCmd);
-
-    // TODO(b/138709788): rather than populate the raw values directly, it should use the
-    // libraries that convert a InitialUserInfoResponse into a VehiclePropValue)
-
-    switch (response->areaId) {
-        case 1:
-            LOG(INFO) << "returning response with right request id";
-            *updatedValue = *response;
-            updatedValue->areaId = 0;
-            updatedValue->value.int32Values[0] = requestId;
-            break;
-        case 2:
-            LOG(INFO) << "returning response with wrong request id";
-            *updatedValue = *response;
-            updatedValue->areaId = 0;
-            updatedValue->value.int32Values[0] = -requestId;
-            break;
-        case 3:
-            LOG(INFO) << "not generating a property change event because of lshal prop: "
-                      << toString(*response);
-            return StatusCode::OK;
-        default:
-            LOG(ERROR) << "invalid action on lshal response: " << toString(*response);
-            return StatusCode::INTERNAL_ERROR;
-    }
-
-    LOG(INFO) << "updating property to: " << toString(*updatedValue);
-    onPropertyValueFromCar(*updatedValue, updateStatus);
-    return StatusCode::OK;
-}
-
-bool EmulatedVehicleServer::onDump(const hidl_handle& handle,
-                                   const hidl_vec<hidl_string>& options) {
+bool EmulatedPassthroughConnector::onDump(const hidl_handle& handle,
+                                          const hidl_vec<hidl_string>& options) {
     int fd = handle->data[0];
 
     if (options.size() > 0) {
@@ -401,7 +71,7 @@
     return true;
 }
 
-void EmulatedVehicleServer::dumpUserHal(int fd, std::string indent) {
+void EmulatedPassthroughConnector::dumpUserHal(int fd, std::string indent) {
     if (mInitialUserResponseFromCmd != nullptr) {
         dprintf(fd, "%sInitial User Info: %s\n", indent.c_str(),
                 toString(*mInitialUserResponseFromCmd).c_str());
@@ -410,7 +80,7 @@
     }
 }
 
-EmulatedPassthroughConnectorPtr makeEmulatedPassthroughConnector() {
+PassthroughConnectorPtr makeEmulatedPassthroughConnector() {
     return std::make_unique<EmulatedPassthroughConnector>();
 }
 
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
index 4850d32..57cbb8b 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
@@ -18,9 +18,9 @@
 #define android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleConnector_H_
 
 #include <vhal_v2_0/VehicleConnector.h>
-#include <vhal_v2_0/VehicleHal.h>
 
-#include "GeneratorHub.h"
+#include "VehicleHalClient.h"
+#include "VehicleHalServer.h"
 
 namespace android {
 namespace hardware {
@@ -30,69 +30,10 @@
 
 namespace impl {
 
-// Extension of the client/server interfaces for emulated vehicle
+using PassthroughConnector = IPassThroughConnector<VehicleHalClient, VehicleHalServer>;
+using PassthroughConnectorPtr = std::unique_ptr<PassthroughConnector>;
 
-class EmulatedVehicleClient : public IVehicleClient {
-  public:
-    // Type of callback function for handling the new property values
-    using PropertyCallBackType = std::function<void(const VehiclePropValue&, bool updateStatus)>;
-
-    // Method from IVehicleClient
-    void onPropertyValue(const VehiclePropValue& value, bool updateStatus) override;
-
-    void registerPropertyValueCallback(PropertyCallBackType&& callback);
-
-  private:
-    PropertyCallBackType mPropCallback;
-};
-
-class EmulatedVehicleServer : public IVehicleServer {
-  public:
-    // Methods from IVehicleServer
-
-    std::vector<VehiclePropConfig> onGetAllPropertyConfig() const override;
-
-    StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) override;
-
-    bool onDump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
-
-    // Set the Property Value Pool used in this server
-    void setValuePool(VehiclePropValuePool* valuePool);
-
-  private:
-    GeneratorHub* getGenerator();
-
-    VehiclePropValuePool* getValuePool() const;
-
-    void onFakeValueGenerated(const VehiclePropValue& value);
-
-    StatusCode handleGenerateFakeDataRequest(const VehiclePropValue& request);
-
-    VehicleHal::VehiclePropValuePtr createApPowerStateReq(VehicleApPowerStateReq req, int32_t param);
-
-    VehicleHal::VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action,
-                                                         int32_t keyCode, int32_t targetDisplay);
-
-    // private data members
-
-    GeneratorHub mGeneratorHub{
-            std::bind(&EmulatedVehicleServer::onFakeValueGenerated, this, std::placeholders::_1)};
-
-    VehiclePropValuePool* mValuePool{nullptr};
-
-    // TODO(b/146207078): it might be clearer to move members below to an EmulatedUserHal class
-    std::unique_ptr<VehiclePropValue> mInitialUserResponseFromCmd;
-    StatusCode onSetInitialUserInfo(const VehiclePropValue& value, bool updateStatus);
-    void dumpUserHal(int fd, std::string indent);
-};
-
-// Helper functions
-
-using EmulatedPassthroughConnector =
-        IPassThroughConnector<EmulatedVehicleClient, EmulatedVehicleServer>;
-using EmulatedPassthroughConnectorPtr = std::unique_ptr<EmulatedPassthroughConnector>;
-
-EmulatedPassthroughConnectorPtr makeEmulatedPassthroughConnector();
+PassthroughConnectorPtr makeEmulatedPassthroughConnector();
 
 }  // namespace impl
 
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
index 692c7f7..6d5f23f 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
@@ -87,12 +87,11 @@
     return sensorStore;
 }
 
-EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore,
-                                       EmulatedVehicleClient* client)
+EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client)
     : mPropStore(propStore),
       mHvacPowerProps(std::begin(kHvacPowerProperties), std::end(kHvacPowerProperties)),
-      mRecurrentTimer(
-          std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer, this, std::placeholders::_1)),
+      mRecurrentTimer(std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer, this,
+                                std::placeholders::_1)),
       mVehicleClient(client) {
     initStaticConfig();
     for (size_t i = 0; i < arraysize(kVehicleProperties); i++) {
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
index ebc405e..ebf1995 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
@@ -46,7 +46,7 @@
 class EmulatedVehicleHal : public EmulatedVehicleHalIface {
 public:
     EmulatedVehicleHal(VehiclePropertyStore* propStore,
-                       EmulatedVehicleClient* client);
+                       VehicleHalClient* client);
     ~EmulatedVehicleHal() = default;
 
     //  Methods from VehicleHal
@@ -85,7 +85,7 @@
     VehiclePropertyStore* mPropStore;
     std::unordered_set<int32_t> mHvacPowerProps;
     RecurrentTimer mRecurrentTimer;
-    EmulatedVehicleClient* mVehicleClient;
+    VehicleHalClient* mVehicleClient;
 };
 
 }  // impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h
index d6ad77d..2dc502b 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h
@@ -19,6 +19,8 @@
 
 #include <android/hardware/automotive/vehicle/2.0/types.h>
 
+#include <chrono>
+
 namespace android {
 namespace hardware {
 namespace automotive {
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp
index 7bdc97c..96aaafe 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp
@@ -46,7 +46,8 @@
     if (mGenCfg.currentValue > mGenCfg.initialValue + mGenCfg.dispersion) {
         mGenCfg.currentValue = mGenCfg.initialValue - mGenCfg.dispersion;
     }
-    VehiclePropValue event = {.prop = mGenCfg.propId};
+    // TODO: (chenhaosjtuacm) remove "{}" if AGL compiler updated
+    VehiclePropValue event = {.timestamp = {}, .areaId = {}, .prop = mGenCfg.propId};
     auto& value = event.value;
     switch (getPropType(event.prop)) {
         case VehiclePropertyType::INT32:
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.cpp
new file mode 100644
index 0000000..25ffc6d
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "VehicleHalClient.h"
+
+#include <android-base/logging.h>
+
+namespace android::hardware::automotive::vehicle::V2_0::impl {
+
+void VehicleHalClient::onPropertyValue(const VehiclePropValue& value, bool updateStatus) {
+    if (!mPropCallback) {
+        LOG(ERROR) << __func__ << ": PropertyCallBackType is not registered!";
+        return;
+    }
+    return mPropCallback(value, updateStatus);
+}
+
+void VehicleHalClient::registerPropertyValueCallback(PropertyCallBackType&& callback) {
+    if (mPropCallback) {
+        LOG(ERROR) << __func__ << ": Cannot register multiple callbacks!";
+        return;
+    }
+    mPropCallback = std::move(callback);
+}
+
+}  // namespace android::hardware::automotive::vehicle::V2_0::impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.h
new file mode 100644
index 0000000..6559e2a
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <vhal_v2_0/VehicleClient.h>
+
+namespace android::hardware::automotive::vehicle::V2_0::impl {
+
+// The common client operations that may be used by both native and
+// virtualized VHAL clients.
+class VehicleHalClient : public IVehicleClient {
+  public:
+    // Type of callback function for handling the new property values
+    using PropertyCallBackType = std::function<void(const VehiclePropValue&, bool updateStatus)>;
+
+    // Method from IVehicleClient
+    void onPropertyValue(const VehiclePropValue& value, bool updateStatus) override;
+
+    void registerPropertyValueCallback(PropertyCallBackType&& callback);
+
+  private:
+    PropertyCallBackType mPropCallback;
+};
+
+}  // namespace android::hardware::automotive::vehicle::V2_0::impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
new file mode 100644
index 0000000..a91ca8e
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "VehicleHalServer.h"
+
+#include <fstream>
+
+#include <android-base/logging.h>
+#include <utils/SystemClock.h>
+
+#include "DefaultConfig.h"
+#include "JsonFakeValueGenerator.h"
+#include "LinearFakeValueGenerator.h"
+#include "Obd2SensorStore.h"
+
+namespace android::hardware::automotive::vehicle::V2_0::impl {
+
+GeneratorHub* VehicleHalServer::getGenerator() {
+    return &mGeneratorHub;
+}
+
+VehiclePropValuePool* VehicleHalServer::getValuePool() const {
+    if (!mValuePool) {
+        LOG(WARNING) << __func__ << ": Value pool not set!";
+    }
+    return mValuePool;
+}
+
+void VehicleHalServer::setValuePool(VehiclePropValuePool* valuePool) {
+    if (!valuePool) {
+        LOG(WARNING) << __func__ << ": Setting value pool to nullptr!";
+    }
+    mValuePool = valuePool;
+}
+
+void VehicleHalServer::onFakeValueGenerated(const VehiclePropValue& value) {
+    constexpr bool updateStatus = true;
+    LOG(DEBUG) << __func__ << ": " << toString(value);
+    auto updatedPropValue = getValuePool()->obtain(value);
+    if (updatedPropValue) {
+        updatedPropValue->timestamp = value.timestamp;
+        updatedPropValue->status = VehiclePropertyStatus::AVAILABLE;
+        onPropertyValueFromCar(*updatedPropValue, updateStatus);
+    }
+}
+
+std::vector<VehiclePropConfig> VehicleHalServer::onGetAllPropertyConfig() const {
+    std::vector<VehiclePropConfig> vehiclePropConfigs;
+    constexpr size_t numOfVehiclePropConfigs =
+            sizeof(kVehicleProperties) / sizeof(kVehicleProperties[0]);
+    vehiclePropConfigs.reserve(numOfVehiclePropConfigs);
+    for (auto& it : kVehicleProperties) {
+        vehiclePropConfigs.emplace_back(it.config);
+    }
+    return vehiclePropConfigs;
+}
+
+StatusCode VehicleHalServer::handleGenerateFakeDataRequest(const VehiclePropValue& request) {
+    constexpr bool updateStatus = true;
+
+    LOG(INFO) << __func__;
+    const auto& v = request.value;
+    if (!v.int32Values.size()) {
+        LOG(ERROR) << __func__ << ": expected at least \"command\" field in int32Values";
+        return StatusCode::INVALID_ARG;
+    }
+
+    FakeDataCommand command = static_cast<FakeDataCommand>(v.int32Values[0]);
+
+    switch (command) {
+        case FakeDataCommand::StartLinear: {
+            LOG(INFO) << __func__ << ", FakeDataCommand::StartLinear";
+            if (v.int32Values.size() < 2) {
+                LOG(ERROR) << __func__ << ": expected property ID in int32Values";
+                return StatusCode::INVALID_ARG;
+            }
+            if (!v.int64Values.size()) {
+                LOG(ERROR) << __func__ << ": interval is not provided in int64Values";
+                return StatusCode::INVALID_ARG;
+            }
+            if (v.floatValues.size() < 3) {
+                LOG(ERROR) << __func__ << ": expected at least 3 elements in floatValues, got: "
+                           << v.floatValues.size();
+                return StatusCode::INVALID_ARG;
+            }
+            int32_t cookie = v.int32Values[1];
+            getGenerator()->registerGenerator(cookie,
+                                              std::make_unique<LinearFakeValueGenerator>(request));
+            break;
+        }
+        case FakeDataCommand::StartJson: {
+            LOG(INFO) << __func__ << ", FakeDataCommand::StartJson";
+            if (v.stringValue.empty()) {
+                LOG(ERROR) << __func__ << ": path to JSON file is missing";
+                return StatusCode::INVALID_ARG;
+            }
+            int32_t cookie = std::hash<std::string>()(v.stringValue);
+            getGenerator()->registerGenerator(cookie,
+                                              std::make_unique<JsonFakeValueGenerator>(request));
+            break;
+        }
+        case FakeDataCommand::StopLinear: {
+            LOG(INFO) << __func__ << ", FakeDataCommand::StopLinear";
+            if (v.int32Values.size() < 2) {
+                LOG(ERROR) << __func__ << ": expected property ID in int32Values";
+                return StatusCode::INVALID_ARG;
+            }
+            int32_t cookie = v.int32Values[1];
+            getGenerator()->unregisterGenerator(cookie);
+            break;
+        }
+        case FakeDataCommand::StopJson: {
+            LOG(INFO) << __func__ << ", FakeDataCommand::StopJson";
+            if (v.stringValue.empty()) {
+                LOG(ERROR) << __func__ << ": path to JSON file is missing";
+                return StatusCode::INVALID_ARG;
+            }
+            int32_t cookie = std::hash<std::string>()(v.stringValue);
+            getGenerator()->unregisterGenerator(cookie);
+            break;
+        }
+        case FakeDataCommand::KeyPress: {
+            LOG(INFO) << __func__ << ", FakeDataCommand::KeyPress";
+            int32_t keyCode = request.value.int32Values[2];
+            int32_t display = request.value.int32Values[3];
+            // Send back to HAL
+            onPropertyValueFromCar(
+                    *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_DOWN, keyCode, display),
+                    updateStatus);
+            onPropertyValueFromCar(
+                    *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display),
+                    updateStatus);
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << ": unexpected command: " << toInt(command);
+            return StatusCode::INVALID_ARG;
+        }
+    }
+    return StatusCode::OK;
+}
+
+VehicleHalServer::VehiclePropValuePtr VehicleHalServer::createApPowerStateReq(
+        VehicleApPowerStateReq state, int32_t param) {
+    auto req = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 2);
+    req->prop = toInt(VehicleProperty::AP_POWER_STATE_REQ);
+    req->areaId = 0;
+    req->timestamp = elapsedRealtimeNano();
+    req->status = VehiclePropertyStatus::AVAILABLE;
+    req->value.int32Values[0] = toInt(state);
+    req->value.int32Values[1] = param;
+    return req;
+}
+
+VehicleHalServer::VehiclePropValuePtr VehicleHalServer::createHwInputKeyProp(
+        VehicleHwKeyInputAction action, int32_t keyCode, int32_t targetDisplay) {
+    auto keyEvent = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 3);
+    keyEvent->prop = toInt(VehicleProperty::HW_KEY_INPUT);
+    keyEvent->areaId = 0;
+    keyEvent->timestamp = elapsedRealtimeNano();
+    keyEvent->status = VehiclePropertyStatus::AVAILABLE;
+    keyEvent->value.int32Values[0] = toInt(action);
+    keyEvent->value.int32Values[1] = keyCode;
+    keyEvent->value.int32Values[2] = targetDisplay;
+    return keyEvent;
+}
+
+StatusCode VehicleHalServer::onSetProperty(const VehiclePropValue& value, bool updateStatus) {
+    // Some properties need to be treated non-trivially
+    switch (value.prop) {
+        case kGenerateFakeDataControllingProperty:
+            return handleGenerateFakeDataRequest(value);
+
+        // set the value from vehicle side, used in end to end test.
+        case kSetIntPropertyFromVehicleForTest: {
+            auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::INT32, 1);
+            updatedPropValue->prop = value.value.int32Values[0];
+            updatedPropValue->value.int32Values[0] = value.value.int32Values[1];
+            updatedPropValue->timestamp = value.value.int64Values[0];
+            updatedPropValue->areaId = value.areaId;
+            onPropertyValueFromCar(*updatedPropValue, updateStatus);
+            return StatusCode::OK;
+        }
+        case kSetFloatPropertyFromVehicleForTest: {
+            auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::FLOAT, 1);
+            updatedPropValue->prop = value.value.int32Values[0];
+            updatedPropValue->value.floatValues[0] = value.value.floatValues[0];
+            updatedPropValue->timestamp = value.value.int64Values[0];
+            updatedPropValue->areaId = value.areaId;
+            onPropertyValueFromCar(*updatedPropValue, updateStatus);
+            return StatusCode::OK;
+        }
+        case kSetBooleanPropertyFromVehicleForTest: {
+            auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::BOOLEAN, 1);
+            updatedPropValue->prop = value.value.int32Values[1];
+            updatedPropValue->value.int32Values[0] = value.value.int32Values[0];
+            updatedPropValue->timestamp = value.value.int64Values[0];
+            updatedPropValue->areaId = value.areaId;
+            onPropertyValueFromCar(*updatedPropValue, updateStatus);
+            return StatusCode::OK;
+        }
+
+        case AP_POWER_STATE_REPORT:
+            switch (value.value.int32Values[0]) {
+                case toInt(VehicleApPowerStateReport::DEEP_SLEEP_EXIT):
+                case toInt(VehicleApPowerStateReport::SHUTDOWN_CANCELLED):
+                case toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL):
+                    // CPMS is in WAIT_FOR_VHAL state, simply move to ON
+                    // Send back to HAL
+                    // ALWAYS update status for generated property value
+                    onPropertyValueFromCar(*createApPowerStateReq(VehicleApPowerStateReq::ON, 0),
+                                           true /* updateStatus */);
+                    break;
+                case toInt(VehicleApPowerStateReport::DEEP_SLEEP_ENTRY):
+                case toInt(VehicleApPowerStateReport::SHUTDOWN_START):
+                    // CPMS is in WAIT_FOR_FINISH state, send the FINISHED command
+                    // Send back to HAL
+                    // ALWAYS update status for generated property value
+                    onPropertyValueFromCar(
+                            *createApPowerStateReq(VehicleApPowerStateReq::FINISHED, 0),
+                            true /* updateStatus */);
+                    break;
+                case toInt(VehicleApPowerStateReport::ON):
+                case toInt(VehicleApPowerStateReport::SHUTDOWN_POSTPONE):
+                case toInt(VehicleApPowerStateReport::SHUTDOWN_PREPARE):
+                    // Do nothing
+                    break;
+                default:
+                    // Unknown state
+                    break;
+            }
+            break;
+        case INITIAL_USER_INFO:
+            return onSetInitialUserInfo(value, updateStatus);
+        default:
+            break;
+    }
+
+    // In the real vhal, the value will be sent to Car ECU.
+    // We just pretend it is done here and send back to HAL
+    auto updatedPropValue = getValuePool()->obtain(value);
+    updatedPropValue->timestamp = elapsedRealtimeNano();
+
+    onPropertyValueFromCar(*updatedPropValue, updateStatus);
+    return StatusCode::OK;
+}
+
+/**
+ * INITIAL_USER_INFO is called by Android when it starts, and it's expecting a property change
+ * indicating what the initial user should be.
+ *
+ * During normal circumstances, the emulator will reply right away, passing a response if
+ * InitialUserInfoResponseAction::DEFAULT (so Android could use its own logic to decide which user
+ * to boot).
+ *
+ * But during development / testing, the behavior can be changed using lshal dump, which must use
+ * the areaId to indicate what should happen next.
+ *
+ * So, the behavior of set(INITIAL_USER_INFO) is:
+ *
+ * - if it has an areaId, store the property into mInitialUserResponseFromCmd (as it was called by
+ *   lshal).
+ * - else if mInitialUserResponseFromCmd is not set, return a response with the same request id and
+ *   InitialUserInfoResponseAction::DEFAULT
+ * - else the behavior is defined by the areaId on mInitialUserResponseFromCmd:
+ * - if it's 1, reply with mInitialUserResponseFromCmd and the right request id
+ * - if it's 2, reply with mInitialUserResponseFromCmd but a wrong request id (so Android can test
+ *   this error scenario)
+ * - if it's 3, then don't send a property change (so Android can emulate a timeout)
+ *
+ */
+StatusCode VehicleHalServer::onSetInitialUserInfo(const VehiclePropValue& value,
+                                                  bool updateStatus) {
+    // TODO: LOG calls below might be more suited to be DEBUG, but those are not being logged
+    // (even when explicitly calling setprop log.tag. As this class should be using ALOG instead of
+    // LOG, it's not worth investigating why...
+
+    if (value.value.int32Values.size() == 0) {
+        LOG(ERROR) << "set(INITIAL_USER_INFO): no int32values, ignoring it: " << toString(value);
+        return StatusCode::INVALID_ARG;
+    }
+
+    if (value.areaId != 0) {
+        LOG(INFO) << "set(INITIAL_USER_INFO) called from lshal; storing it: " << toString(value);
+        mInitialUserResponseFromCmd.reset(new VehiclePropValue(value));
+        return StatusCode::OK;
+    }
+    LOG(INFO) << "set(INITIAL_USER_INFO) called from Android: " << toString(value);
+
+    int32_t requestId = value.value.int32Values[0];
+
+    // Create the update property and set common values
+    auto updatedValue = createVehiclePropValue(VehiclePropertyType::MIXED, 0);
+    updatedValue->prop = INITIAL_USER_INFO;
+    updatedValue->timestamp = elapsedRealtimeNano();
+
+    if (mInitialUserResponseFromCmd == nullptr) {
+        updatedValue->value.int32Values.resize(2);
+        updatedValue->value.int32Values[0] = requestId;
+        updatedValue->value.int32Values[1] = (int32_t)InitialUserInfoResponseAction::DEFAULT;
+        LOG(INFO) << "no lshal response; returning InitialUserInfoResponseAction::DEFAULT: "
+                  << toString(*updatedValue);
+        onPropertyValueFromCar(*updatedValue, updateStatus);
+        return StatusCode::OK;
+    }
+
+    // mInitialUserResponseFromCmd is used for just one request
+    std::unique_ptr<VehiclePropValue> response = std::move(mInitialUserResponseFromCmd);
+
+    // TODO(b/138709788): rather than populate the raw values directly, it should use the
+    // libraries that convert a InitialUserInfoResponse into a VehiclePropValue)
+
+    switch (response->areaId) {
+        case 1:
+            LOG(INFO) << "returning response with right request id";
+            *updatedValue = *response;
+            updatedValue->areaId = 0;
+            updatedValue->value.int32Values[0] = requestId;
+            break;
+        case 2:
+            LOG(INFO) << "returning response with wrong request id";
+            *updatedValue = *response;
+            updatedValue->areaId = 0;
+            updatedValue->value.int32Values[0] = -requestId;
+            break;
+        case 3:
+            LOG(INFO) << "not generating a property change event because of lshal prop: "
+                      << toString(*response);
+            return StatusCode::OK;
+        default:
+            LOG(ERROR) << "invalid action on lshal response: " << toString(*response);
+            return StatusCode::INTERNAL_ERROR;
+    }
+
+    LOG(INFO) << "updating property to: " << toString(*updatedValue);
+    onPropertyValueFromCar(*updatedValue, updateStatus);
+    return StatusCode::OK;
+}
+
+}  // namespace android::hardware::automotive::vehicle::V2_0::impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h
new file mode 100644
index 0000000..b1ae106
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <vhal_v2_0/VehicleObjectPool.h>
+#include <vhal_v2_0/VehicleServer.h>
+
+#include "GeneratorHub.h"
+
+namespace android::hardware::automotive::vehicle::V2_0::impl {
+
+// This contains the common server operations that will be used by
+// both native and virtualized VHAL server. Notice that in the virtualized
+// scenario, the server may be run on a different OS than Android.
+class VehicleHalServer : public IVehicleServer {
+  public:
+    // Methods from IVehicleServer
+
+    std::vector<VehiclePropConfig> onGetAllPropertyConfig() const override;
+
+    StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) override;
+
+    // Set the Property Value Pool used in this server
+    void setValuePool(VehiclePropValuePool* valuePool);
+
+  private:
+    using VehiclePropValuePtr = recyclable_ptr<VehiclePropValue>;
+
+    GeneratorHub* getGenerator();
+
+    VehiclePropValuePool* getValuePool() const;
+
+    void onFakeValueGenerated(const VehiclePropValue& value);
+
+    StatusCode handleGenerateFakeDataRequest(const VehiclePropValue& request);
+
+    VehiclePropValuePtr createApPowerStateReq(VehicleApPowerStateReq req, int32_t param);
+
+    VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action, int32_t keyCode,
+                                             int32_t targetDisplay);
+
+    StatusCode onSetInitialUserInfo(const VehiclePropValue& value, bool updateStatus);
+
+  // data members
+
+  protected:
+    // TODO(b/146207078): it might be clearer to move members below to an EmulatedUserHal class
+    std::unique_ptr<VehiclePropValue> mInitialUserResponseFromCmd;
+
+  private:
+    GeneratorHub mGeneratorHub{
+            std::bind(&VehicleHalServer::onFakeValueGenerated, this, std::placeholders::_1)};
+
+    VehiclePropValuePool* mValuePool{nullptr};
+};
+
+}  // namespace android::hardware::automotive::vehicle::V2_0::impl