Add logic for VHAL versions > 2.0 to forward property information to 2.0
Use this infrastructure to move OBD2_LIVE_FRAME support over to the Vehicle HAL 2.0 layer.

This is useful in DefaultVehicleHal 2.0 to let the Emulator layer send/receive information about properties defined by later VehicleHal versions.
Additionally, support the notion that a custom property thusly defined might have logic more intricate than simply a property Id and an area Id,
via a custom handler object that supports get() and set() operations. A default handler object simply falls back to a stored VehiclePropValue, but
more complex implementations are possible.

Test: manual testing in Python:
import vhal_consts_2_0 as c
from vhal_emulator import Vhal

v = Vhal(c.vhal_types_2_0)

v.getConfig(c.VEHICLE_PROPERTY_HVAC_TEMPERATURE_SET)
print v.rxMsg()

v.setProperty(c.VEHICLE_PROPERTY_HVAC_TEMPERATURE_SET, c.VEHICLE_ZONE_ROW_1_LEFT, 70)
print v.rxMsg()

v.getProperty(c.VEHICLE_PROPERTY_HVAC_TEMPERATURE_SET, c.VEHICLE_ZONE_ROW_1_LEFT)
print v.rxMsg()

v.getProperty(0x11e00d00, 0)
print v.rxMsg()

plus

runtest Obd2LiveFrame.java

Change-Id: I9c342e6e2c9ff581beacd238a42780ca10f96d9c
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp
index e6a3e56..03a65f3 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp
@@ -104,7 +104,7 @@
 
         for (auto& prop : mProps) {
             emulator::VehiclePropValue* protoVal = respMsg.add_value();
-            populateProtoVehiclePropValue(protoVal, prop.second.get());
+            populateProtoVehiclePropValue(protoVal, prop.second->get());
         }
     }
 }
@@ -175,7 +175,7 @@
 
     auto prop = mProps.find(std::make_pair(propId, areaId));
     if (prop != mProps.end()) {
-        return prop->second.get();
+        return prop->second->get();
     }
     ALOGW("%s: Property not found:  propId = 0x%x, areaId = 0x%x", __func__, propId, areaId);
     return nullptr;
@@ -530,6 +530,13 @@
     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
@@ -598,7 +605,11 @@
             prop->areaId = curArea;
             prop->prop = cfg.prop;
             setDefaultValue(prop.get());
-            mProps[std::make_pair(prop->prop, prop->areaId)] = std::move(prop);
+            std::unique_ptr<CustomVehiclePropertyHandler> handler;
+            handler.reset(new StoredValueCustomVehiclePropertyHandler());
+            handler->set(*prop);
+            mProps[std::make_pair(prop->prop, prop->areaId)] =
+                    std::move(handler);
         } while (supportedAreas != 0);
     }
 
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h
index bbbe955..c8310b3 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h
@@ -44,7 +44,31 @@
 
 class DefaultVehicleHal : public VehicleHal {
 public:
-    DefaultVehicleHal() : mRecurrentTimer(
+    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++) {
             mPropConfigMap[kVehicleProperties[i].prop] = &kVehicleProperties[i];
@@ -77,6 +101,43 @@
 
     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) {
+        std::unique_ptr<CustomVehiclePropertyHandler> handler;
+        handler.reset(new StoredValueCustomVehiclePropertyHandler());
+        StatusCode setResponse = handler->set(initialValue);
+        if (StatusCode::OK == setResponse) {
+          return addCustomProperty(initialValue.prop,
+                                   std::move(handler));
+        } else {
+          return setResponse;
+        }
+    }
+
 private:
     void doGetConfig(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
     void doGetConfigAll(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
@@ -106,7 +167,7 @@
 private:
     std::map<
         std::pair<int32_t /*VehicleProperty*/, int32_t /*areaId*/>,
-        std::unique_ptr<VehiclePropValue>> mProps;
+        std::unique_ptr<CustomVehiclePropertyHandler>> mProps;
     std::atomic<int> mExit;
     std::unordered_set<int32_t> mHvacPowerProps;
     std::mutex mPropsMutex;
diff --git a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.cpp b/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.cpp
index d4eae7f..b147ce7 100644
--- a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.cpp
@@ -120,12 +120,12 @@
     return sensorStore;
 }
 
-void DefaultVehicleHal::initObd2LiveFrame(V2_0::VehiclePropConfig& propConfig) {
+void DefaultVehicleHal::initObd2LiveFrame(V2_0::VehiclePropConfig& propConfig,
+    V2_0::VehiclePropValue* liveObd2Frame) {
     auto sensorStore = fillDefaultObd2Frame(propConfig.configArray[0],
             propConfig.configArray[1]);
-    mLiveObd2Frame = createVehiclePropValue(
-            V2_0::VehiclePropertyType::COMPLEX, 0);
-    sensorStore->fillPropValue(mLiveObd2Frame.get(), "");
+    sensorStore->fillPropValue(liveObd2Frame, "");
+    liveObd2Frame->prop = V2_0::toInt(VehicleProperty::OBD2_LIVE_FRAME);
 }
 
 void DefaultVehicleHal::initObd2FreezeFrame(V2_0::VehiclePropConfig& propConfig) {
@@ -144,14 +144,6 @@
     sensorStore->fillPropValue(mFreezeObd2Frames[2].get(), "P0123");
 }
 
-V2_0::StatusCode DefaultVehicleHal::fillObd2LiveFrame(V2_0::VehiclePropValue* v) {
-    v->prop = V2_0::toInt(VehicleProperty::OBD2_LIVE_FRAME);
-    v->value.int32Values = mLiveObd2Frame->value.int32Values;
-    v->value.floatValues = mLiveObd2Frame->value.floatValues;
-    v->value.bytes = mLiveObd2Frame->value.bytes;
-    return V2_0::StatusCode::OK;
-}
-
 template<typename Iterable>
 typename Iterable::const_iterator findPropValueAtTimestamp(
         const Iterable& frames,
@@ -224,8 +216,11 @@
     std::vector<V2_0::VehiclePropConfig> configs = listProperties();
     for (auto& cfg : configs) {
         switch(cfg.prop) {
-            case V2_0::toInt(V2_1::VehicleProperty::OBD2_LIVE_FRAME):
-                initObd2LiveFrame(cfg);
+            case V2_0::toInt(V2_1::VehicleProperty::OBD2_LIVE_FRAME): {
+                auto liveObd2Frame = createVehiclePropValue(V2_0::VehiclePropertyType::COMPLEX, 0);
+                initObd2LiveFrame(cfg, liveObd2Frame.get());
+                mVehicleHal20->addCustomProperty(*liveObd2Frame);
+            }
                 break;
             case V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME):
                 initObd2FreezeFrame(cfg);
@@ -245,10 +240,6 @@
     auto& pool = *getValuePool();
 
     switch (propId) {
-    case V2_0::toInt(V2_1::VehicleProperty::OBD2_LIVE_FRAME):
-        v = pool.obtainComplex();
-        *outStatus = fillObd2LiveFrame(v.get());
-        return v;
     case V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME):
         v = pool.obtainComplex();
         *outStatus = fillObd2FreezeFrame(requestedPropValue, v.get());
diff --git a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.h b/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.h
index ac65fc6..af21138 100644
--- a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.h
+++ b/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.h
@@ -39,7 +39,8 @@
 
 class DefaultVehicleHal : public V2_0::VehicleHal {
 public:
-    DefaultVehicleHal(V2_0::VehicleHal* vhal20) : mVehicleHal20(vhal20) {}
+    DefaultVehicleHal(V2_0::impl::DefaultVehicleHal* vhal20) :
+          mVehicleHal20(vhal20) {}
 
     std::vector<V2_0::VehiclePropConfig> listProperties() override {
         std::vector<V2_0::VehiclePropConfig> propConfigs(mVehicleHal20->listProperties());
@@ -70,17 +71,16 @@
     void onCreate() override;
 
 private:
-    void initObd2LiveFrame(V2_0::VehiclePropConfig& propConfig);
+    void initObd2LiveFrame(V2_0::VehiclePropConfig& propConfig,
+        V2_0::VehiclePropValue* liveObd2Frame);
     void initObd2FreezeFrame(V2_0::VehiclePropConfig& propConfig);
-    V2_0::StatusCode fillObd2LiveFrame(V2_0::VehiclePropValue* v);
     V2_0::StatusCode fillObd2FreezeFrame(const V2_0::VehiclePropValue& requestedPropValue,
             V2_0::VehiclePropValue* v);
     V2_0::StatusCode fillObd2DtcInfo(V2_0::VehiclePropValue *v);
     V2_0::StatusCode clearObd2FreezeFrames(const V2_0::VehiclePropValue& propValue);
 
 private:
-    V2_0::VehicleHal* mVehicleHal20;
-    std::unique_ptr<V2_0::VehiclePropValue> mLiveObd2Frame {nullptr};
+    V2_0::impl::DefaultVehicleHal* mVehicleHal20;
     std::vector<std::unique_ptr<V2_0::VehiclePropValue>> mFreezeObd2Frames;
 };