OSDN Git Service

Post-O. Finalize Vehicle HAL support for OBD2 diagnostics.
authorEnrico Granata <egranata@google.com>
Thu, 9 Feb 2017 02:09:45 +0000 (18:09 -0800)
committerEnrico Granata <egranata@google.com>
Fri, 10 Feb 2017 01:12:12 +0000 (17:12 -0800)
Add OBD2_DTC_INFO property to VHAL. This property returns a list of timestamps for which freeze frames are available to be read.
Make OBD2_FREEZE_FRAME indexed on timestamp, such that one has to pass a timestamp to retrieve the freeze frame at that timestamp.
Add OBD2_DTC_CLEAR to delete some or all of the freeze frames stored.

Test: build
Change-Id: I30344ffd6e7527f076b3382c32f5507973c9985b

automotive/vehicle/2.0/default/impl/DefaultConfig.h
automotive/vehicle/2.0/default/impl/DefaultVehicleHal.cpp
automotive/vehicle/2.0/default/impl/DefaultVehicleHal.h
automotive/vehicle/2.0/default/vehicle_hal_manager/Obd2SensorStore.cpp
automotive/vehicle/2.0/default/vehicle_hal_manager/Obd2SensorStore.h
automotive/vehicle/2.0/types.hal

index 270bf8c..0c549b9 100644 (file)
@@ -174,6 +174,18 @@ const VehiclePropConfig kVehicleProperties[] = {
         .access = VehiclePropertyAccess::READ,
         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
         .configArray = {0,0}
+    },
+
+    {
+        .prop = toInt(VehicleProperty::OBD2_FREEZE_FRAME_INFO),
+        .access = VehiclePropertyAccess::READ,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE
+    },
+
+    {
+        .prop = toInt(VehicleProperty::OBD2_FREEZE_FRAME_CLEAR),
+        .access = VehiclePropertyAccess::WRITE,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE
     }
 };
 
index 88717a9..312f118 100644 (file)
@@ -181,87 +181,113 @@ VehiclePropValue* DefaultVehicleHal::getVehiclePropValueLocked(int32_t propId, i
     return nullptr;
 }
 
-void DefaultVehicleHal::initObd2LiveFrame(VehiclePropConfig& obd2LiveFramePropConfig) {
-    mObd2SensorStore.reset(new Obd2SensorStore(
-        obd2LiveFramePropConfig.configArray[0],
-        obd2LiveFramePropConfig.configArray[1]));
-    // precalculate OBD2 sensor values
-    mObd2SensorStore->setIntegerSensor(
+static std::unique_ptr<Obd2SensorStore> fillDefaultObd2Frame(
+        size_t numVendorIntegerSensors,
+        size_t numVendorFloatSensors) {
+    std::unique_ptr<Obd2SensorStore> sensorStore(new Obd2SensorStore(
+            numVendorIntegerSensors, numVendorFloatSensors));
+
+    sensorStore->setIntegerSensor(
         Obd2IntegerSensorIndex::FUEL_SYSTEM_STATUS,
         toInt(FuelSystemStatus::CLOSED_LOOP));
-    mObd2SensorStore->setIntegerSensor(
+    sensorStore->setIntegerSensor(
         Obd2IntegerSensorIndex::MALFUNCTION_INDICATOR_LIGHT_ON, 0);
-    mObd2SensorStore->setIntegerSensor(
+    sensorStore->setIntegerSensor(
         Obd2IntegerSensorIndex::IGNITION_MONITORS_SUPPORTED,
         toInt(IgnitionMonitorKind::SPARK));
-    mObd2SensorStore->setIntegerSensor(Obd2IntegerSensorIndex::IGNITION_SPECIFIC_MONITORS,
+    sensorStore->setIntegerSensor(Obd2IntegerSensorIndex::IGNITION_SPECIFIC_MONITORS,
         CommonIgnitionMonitors::COMPONENTS_AVAILABLE |
         CommonIgnitionMonitors::MISFIRE_AVAILABLE |
         SparkIgnitionMonitors::AC_REFRIGERANT_AVAILABLE |
         SparkIgnitionMonitors::EVAPORATIVE_SYSTEM_AVAILABLE);
-    mObd2SensorStore->setIntegerSensor(
+    sensorStore->setIntegerSensor(
         Obd2IntegerSensorIndex::INTAKE_AIR_TEMPERATURE, 35);
-    mObd2SensorStore->setIntegerSensor(
+    sensorStore->setIntegerSensor(
         Obd2IntegerSensorIndex::COMMANDED_SECONDARY_AIR_STATUS,
         toInt(SecondaryAirStatus::FROM_OUTSIDE_OR_OFF));
-    mObd2SensorStore->setIntegerSensor(
+    sensorStore->setIntegerSensor(
         Obd2IntegerSensorIndex::NUM_OXYGEN_SENSORS_PRESENT, 1);
-    mObd2SensorStore->setIntegerSensor(
+    sensorStore->setIntegerSensor(
         Obd2IntegerSensorIndex::RUNTIME_SINCE_ENGINE_START, 500);
-    mObd2SensorStore->setIntegerSensor(
+    sensorStore->setIntegerSensor(
         Obd2IntegerSensorIndex::DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON, 0);
-    mObd2SensorStore->setIntegerSensor(
+    sensorStore->setIntegerSensor(
         Obd2IntegerSensorIndex::WARMUPS_SINCE_CODES_CLEARED, 51);
-    mObd2SensorStore->setIntegerSensor(
+    sensorStore->setIntegerSensor(
         Obd2IntegerSensorIndex::DISTANCE_TRAVELED_SINCE_CODES_CLEARED, 365);
-    mObd2SensorStore->setIntegerSensor(
+    sensorStore->setIntegerSensor(
         Obd2IntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE, 30);
-    mObd2SensorStore->setIntegerSensor(
+    sensorStore->setIntegerSensor(
         Obd2IntegerSensorIndex::CONTROL_MODULE_VOLTAGE, 12);
-    mObd2SensorStore->setIntegerSensor(
+    sensorStore->setIntegerSensor(
         Obd2IntegerSensorIndex::AMBIENT_AIR_TEMPERATURE, 18);
-    mObd2SensorStore->setIntegerSensor(
+    sensorStore->setIntegerSensor(
         Obd2IntegerSensorIndex::MAX_FUEL_AIR_EQUIVALENCE_RATIO, 1);
-    mObd2SensorStore->setIntegerSensor(
+    sensorStore->setIntegerSensor(
         Obd2IntegerSensorIndex::FUEL_TYPE, toInt(FuelType::GASOLINE));
-    mObd2SensorStore->setFloatSensor(
+    sensorStore->setFloatSensor(
         Obd2FloatSensorIndex::CALCULATED_ENGINE_LOAD, 0.153);
-    mObd2SensorStore->setFloatSensor(
+    sensorStore->setFloatSensor(
         Obd2FloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK1, -0.16);
-    mObd2SensorStore->setFloatSensor(
+    sensorStore->setFloatSensor(
         Obd2FloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK1, -0.16);
-    mObd2SensorStore->setFloatSensor(
+    sensorStore->setFloatSensor(
         Obd2FloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK2, -0.16);
-    mObd2SensorStore->setFloatSensor(
+    sensorStore->setFloatSensor(
         Obd2FloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK2, -0.16);
-    mObd2SensorStore->setFloatSensor(
+    sensorStore->setFloatSensor(
         Obd2FloatSensorIndex::INTAKE_MANIFOLD_ABSOLUTE_PRESSURE, 7.5);
-    mObd2SensorStore->setFloatSensor(
+    sensorStore->setFloatSensor(
         Obd2FloatSensorIndex::ENGINE_RPM, 1250.);
-    mObd2SensorStore->setFloatSensor(
+    sensorStore->setFloatSensor(
         Obd2FloatSensorIndex::VEHICLE_SPEED, 40.);
-    mObd2SensorStore->setFloatSensor(
+    sensorStore->setFloatSensor(
         Obd2FloatSensorIndex::TIMING_ADVANCE, 2.5);
-    mObd2SensorStore->setFloatSensor(
+    sensorStore->setFloatSensor(
         Obd2FloatSensorIndex::THROTTLE_POSITION, 19.75);
-    mObd2SensorStore->setFloatSensor(
+    sensorStore->setFloatSensor(
         Obd2FloatSensorIndex::OXYGEN_SENSOR1_VOLTAGE, 0.265);
-    mObd2SensorStore->setFloatSensor(
+    sensorStore->setFloatSensor(
         Obd2FloatSensorIndex::FUEL_TANK_LEVEL_INPUT, 0.824);
-    mObd2SensorStore->setFloatSensor(
+    sensorStore->setFloatSensor(
         Obd2FloatSensorIndex::EVAPORATION_SYSTEM_VAPOR_PRESSURE, -0.373);
-    mObd2SensorStore->setFloatSensor(
+    sensorStore->setFloatSensor(
         Obd2FloatSensorIndex::CATALYST_TEMPERATURE_BANK1_SENSOR1, 190.);
-    mObd2SensorStore->setFloatSensor(
+    sensorStore->setFloatSensor(
         Obd2FloatSensorIndex::RELATIVE_THROTTLE_POSITION, 3.);
-    mObd2SensorStore->setFloatSensor(
+    sensorStore->setFloatSensor(
         Obd2FloatSensorIndex::ABSOLUTE_THROTTLE_POSITION_B, 0.306);
-    mObd2SensorStore->setFloatSensor(
+    sensorStore->setFloatSensor(
         Obd2FloatSensorIndex::ACCELERATOR_PEDAL_POSITION_D, 0.188);
-    mObd2SensorStore->setFloatSensor(
+    sensorStore->setFloatSensor(
         Obd2FloatSensorIndex::ACCELERATOR_PEDAL_POSITION_E, 0.094);
-    mObd2SensorStore->setFloatSensor(
+    sensorStore->setFloatSensor(
         Obd2FloatSensorIndex::COMMANDED_THROTTLE_ACTUATOR, 0.024);
+
+    return sensorStore;
+}
+
+void DefaultVehicleHal::initObd2LiveFrame(VehiclePropConfig& propConfig) {
+    auto sensorStore = fillDefaultObd2Frame(propConfig.configArray[0],
+            propConfig.configArray[1]);
+    mLiveObd2Frame = createVehiclePropValue(VehiclePropertyType::COMPLEX, 0);
+    sensorStore->fillPropValue(mLiveObd2Frame.get(), "");
+}
+
+void DefaultVehicleHal::initObd2FreezeFrame(VehiclePropConfig& propConfig) {
+    auto sensorStore = fillDefaultObd2Frame(propConfig.configArray[0],
+            propConfig.configArray[1]);
+
+    mFreezeObd2Frames.push_back(
+            createVehiclePropValue(VehiclePropertyType::COMPLEX,0));
+    mFreezeObd2Frames.push_back(
+            createVehiclePropValue(VehiclePropertyType::COMPLEX,0));
+    mFreezeObd2Frames.push_back(
+            createVehiclePropValue(VehiclePropertyType::COMPLEX,0));
+
+    sensorStore->fillPropValue(mFreezeObd2Frames[0].get(), "P0070");
+    sensorStore->fillPropValue(mFreezeObd2Frames[1].get(), "P0102");
+    sensorStore->fillPropValue(mFreezeObd2Frames[2].get(), "P0123");
 }
 
 void DefaultVehicleHal::parseRxProtoBuf(std::vector<uint8_t>& msg) {
@@ -598,11 +624,15 @@ VehicleHal::VehiclePropValuePtr DefaultVehicleHal::get(
     switch (propId) {
     case toInt(VehicleProperty::OBD2_LIVE_FRAME):
         v = pool.obtainComplex();
-        status = fillObd2LiveFrame(&v);
+        status = fillObd2LiveFrame(v.get());
         break;
     case toInt(VehicleProperty::OBD2_FREEZE_FRAME):
         v = pool.obtainComplex();
-        status = fillObd2FreezeFrame(&v);
+        status = fillObd2FreezeFrame(requestedPropValue, v.get());
+        break;
+    case toInt(VehicleProperty::OBD2_FREEZE_FRAME_INFO):
+        v = pool.obtainComplex();
+        status = fillObd2DtcInfo(v.get());
         break;
     default:
         {
@@ -627,16 +657,24 @@ VehicleHal::VehiclePropValuePtr DefaultVehicleHal::get(
 }
 
 StatusCode DefaultVehicleHal::set(const VehiclePropValue& propValue) {
-    StatusCode 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);
+    auto propId = propValue.prop;
+    StatusCode status;
+    switch (propId) {
+        case toInt(VehicleProperty::OBD2_FREEZE_FRAME_CLEAR):
+            status = clearObd2FreezeFrames(propValue);
+            break;
+        default:
+            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;
@@ -680,6 +718,9 @@ void DefaultVehicleHal::onCreate() {
             case toInt(VehicleProperty::OBD2_LIVE_FRAME):
                 initObd2LiveFrame(cfg);
                 break;
+            case toInt(VehicleProperty::OBD2_FREEZE_FRAME):
+                initObd2FreezeFrame(cfg);
+                break;
             default:
                 // Need to handle each complex property separately
                 break;
@@ -721,21 +762,78 @@ void DefaultVehicleHal::onCreate() {
     mThread = std::thread(&DefaultVehicleHal::rxThread, this);
 }
 
-StatusCode DefaultVehicleHal::fillObd2LiveFrame(VehiclePropValuePtr* v) {
-    (*v)->value.int32Values = mObd2SensorStore->getIntegerSensors();
-    (*v)->value.floatValues = mObd2SensorStore->getFloatSensors();
-    (*v)->value.bytes = mObd2SensorStore->getSensorsBitmask();
+StatusCode DefaultVehicleHal::fillObd2LiveFrame(VehiclePropValue* v) {
+    v->prop = toInt(VehicleProperty::OBD2_LIVE_FRAME);
+    v->value.int32Values = mLiveObd2Frame->value.int32Values;
+    v->value.floatValues = mLiveObd2Frame->value.floatValues;
+    v->value.bytes = mLiveObd2Frame->value.bytes;
     return StatusCode::OK;
 }
 
-StatusCode DefaultVehicleHal::fillObd2FreezeFrame(VehiclePropValuePtr* v) {
-    (*v)->value.int32Values = mObd2SensorStore->getIntegerSensors();
-    (*v)->value.floatValues = mObd2SensorStore->getFloatSensors();
-    (*v)->value.bytes = mObd2SensorStore->getSensorsBitmask();
-    (*v)->value.stringValue = "P0010";
+template<typename Iterable>
+typename Iterable::const_iterator findPropValueAtTimestamp(
+        const Iterable& frames,
+        int64_t timestamp) {
+    return std::find_if(frames.begin(),
+            frames.end(),
+            [timestamp] (const std::unique_ptr<VehiclePropValue>&
+                         propValue) -> bool {
+                             return propValue->timestamp == timestamp;
+            });
+}
+
+StatusCode DefaultVehicleHal::fillObd2FreezeFrame(
+        const VehiclePropValue& requestedPropValue, VehiclePropValue* v) {
+    if (requestedPropValue.value.int64Values.size() != 1) {
+        ALOGE("asked for OBD2_FREEZE_FRAME without valid timestamp");
+        return StatusCode::INVALID_ARG;
+    }
+    auto timestamp = requestedPropValue.value.int64Values[0];
+    auto freezeFrameIter = findPropValueAtTimestamp(mFreezeObd2Frames,
+            timestamp);
+    if(mFreezeObd2Frames.end() == freezeFrameIter) {
+        ALOGE("asked for OBD2_FREEZE_FRAME at invalid timestamp");
+        return StatusCode::INVALID_ARG;
+    }
+    const std::unique_ptr<VehiclePropValue>& freezeFrame = *freezeFrameIter;
+    v->prop = toInt(VehicleProperty::OBD2_FREEZE_FRAME);
+    v->value.int32Values = freezeFrame->value.int32Values;
+    v->value.floatValues = freezeFrame->value.floatValues;
+    v->value.bytes = freezeFrame->value.bytes;
+    v->value.stringValue = freezeFrame->value.stringValue;
+    v->timestamp = freezeFrame->timestamp;
     return StatusCode::OK;
 }
 
+StatusCode DefaultVehicleHal::clearObd2FreezeFrames(
+    const VehiclePropValue& propValue) {
+    if (propValue.value.int64Values.size() == 0) {
+        mFreezeObd2Frames.clear();
+        return StatusCode::OK;
+    } else {
+        for(int64_t timestamp: propValue.value.int64Values) {
+            auto freezeFrameIter = findPropValueAtTimestamp(mFreezeObd2Frames,
+                    timestamp);
+            if(mFreezeObd2Frames.end() == freezeFrameIter) {
+                ALOGE("asked for OBD2_FREEZE_FRAME at invalid timestamp");
+                return StatusCode::INVALID_ARG;
+            }
+            mFreezeObd2Frames.erase(freezeFrameIter);
+        }
+    }
+    return StatusCode::OK;
+}
+
+StatusCode DefaultVehicleHal::fillObd2DtcInfo(VehiclePropValue* v) {
+    std::vector<int64_t> timestamps;
+    for(const auto& freezeFrame: mFreezeObd2Frames) {
+        timestamps.push_back(freezeFrame->timestamp);
+    }
+    v->value.int64Values = timestamps;
+    return StatusCode::OK;
+}
+
+
 
 }  // impl
 
index edfc224..4b89f55 100644 (file)
@@ -85,7 +85,8 @@ private:
     void doGetPropertyAll(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
     void doSetProperty(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
     VehiclePropValue* getVehiclePropValueLocked(int32_t propId, int32_t areaId);
-    void initObd2LiveFrame(VehiclePropConfig& obd2LiveFramePropConfig);
+    void initObd2LiveFrame(VehiclePropConfig& propConfig);
+    void initObd2FreezeFrame(VehiclePropConfig& propConfig);
     void parseRxProtoBuf(std::vector<uint8_t>& msg);
     void populateProtoVehicleConfig(emulator::VehiclePropConfig* protoCfg,
                                     const VehiclePropConfig& cfg);
@@ -96,14 +97,18 @@ private:
     void rxThread(void);
     void txMsg(emulator::EmulatorMessage& txMsg);
     StatusCode updateProperty(const VehiclePropValue& propValue);
-    StatusCode fillObd2LiveFrame(VehiclePropValuePtr* v);
-    StatusCode fillObd2FreezeFrame(VehiclePropValuePtr* v);
+    StatusCode fillObd2LiveFrame(VehiclePropValue* v);
+    StatusCode fillObd2FreezeFrame(const VehiclePropValue& requestedPropValue,
+            VehiclePropValue* v);
+    StatusCode fillObd2DtcInfo(VehiclePropValue *v);
+    StatusCode clearObd2FreezeFrames(const VehiclePropValue& propValue);
 private:
     // TODO:  Use a hashtable to support indexing props
     std::vector<std::unique_ptr<VehiclePropValue>> mProps;
     std::atomic<int> mCurSocket;
     std::atomic<int> mExit;
-    std::unique_ptr<Obd2SensorStore> mObd2SensorStore{nullptr};
+    std::unique_ptr<VehiclePropValue> mLiveObd2Frame {nullptr};
+    std::vector<std::unique_ptr<VehiclePropValue>> mFreezeObd2Frames;
     std::mutex mPropsMutex;
     int mSocket;
     std::mutex mTxMutex;
index 3a252af..761e550 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "Obd2SensorStore.h"
 
+#include <utils/SystemClock.h>
 #include <vehicle_hal_manager/VehicleUtils.h>
 
 namespace android {
@@ -98,6 +99,16 @@ const std::vector<uint8_t>& Obd2SensorStore::getSensorsBitmask() const {
     return mSensorsBitmask.getBitmask();
 }
 
+void Obd2SensorStore::fillPropValue(VehiclePropValue *propValue,
+                                    std::string dtc) const {
+    propValue->timestamp = elapsedRealtimeNano();
+    propValue->value.int32Values = getIntegerSensors();
+    propValue->value.floatValues = getFloatSensors();
+    propValue->value.bytes = getSensorsBitmask();
+    propValue->value.stringValue = dtc;
+}
+
+
 
 }  // namespace V2_0
 }  // namespace vehicle
index cbe9893..3e2a08e 100644 (file)
@@ -54,6 +54,10 @@ public:
     // Returns a vector that contains a bitmask for all stored sensors.
     const std::vector<uint8_t>& getSensorsBitmask() const;
 
+    // Given a stringValue, fill in a VehiclePropValue
+    void fillPropValue(VehiclePropValue *propValue,
+            std::string dtc) const;
+
 private:
     class BitmaskInVector {
     public:
index 05e10be..fa432f4 100644 (file)
@@ -1829,6 +1829,10 @@ enum VehicleProperty: int32_t {
      *   configArray[1] : number of vendor-specific float-valued sensors
      *                    that can be returned in a frame.
      *
+     * A get of this property must take the following form:
+     *   int64Values[0]: timestamp of the freeze frame to retrieve.
+     *                   Valid timestamps are given by OBD2_DTC_INFO.
+     *
      * The values are to be interpreted as follows:
      * the indices defined in Obd2IntegerSensorIndex are to be used to
      * read from int32Values;
@@ -1860,8 +1864,49 @@ enum VehicleProperty: int32_t {
         | VehiclePropertyType:COMPLEX
         | VehicleArea:GLOBAL),
 
-};
+    /*
+     * OBD2 Freeze Frame Information
+     *
+     * This property describes the current freeze frames stored in vehicle
+     * memory and available for retrieval via OBD2_FREEZE_FRAME.
+     *
+     * The values are to be interpreted as follows:
+     * each element of int64Values is the timestamp at which a a fault code
+     * has been detected and the corresponding freeze frame stored, and each
+     * such element can be used as the key to OBD2_FREEZE_FRAME to retrieve
+     * the corresponding freeze frame.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    OBD2_FREEZE_FRAME_INFO = (
+        0x0D02
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:COMPLEX
+        | VehicleArea:GLOBAL),
 
+    /*
+     * OBD2 Freeze Frame Clear
+     *
+     * This property allows deletion of any of the freeze frames stored in
+     * vehicle memory, as described by OBD2_DTC_INFO.
+     *
+     * A set of this property is to be interpreted as follows:
+     * if int64Values contains no elements, then all DTCs stored will be cleared;
+     * if int64Values contains one or more elements, then DTCs at the timestamps
+     * stored in int64Values will be cleared, and the others not cleared, except
+     * the memory will be compacted so that all remaining DTCs are stored
+     * contiguously.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:WRITE
+     */
+    OBD2_FREEZE_FRAME_CLEAR = (
+        0x0D03
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:COMPLEX
+        | VehicleArea:GLOBAL),
+};
 /*
  * Bit flags for fan direction
  */