Move OBD2 support to Vehicle HAL 2.1.
For O-MR1.
Test: build
Bug: 34746908
Change-Id: I369e6531b8957d8e03154fdf5d732e8242a3c245
diff --git a/automotive/vehicle/2.1/default/Android.mk b/automotive/vehicle/2.1/default/Android.mk
index 1874cb3..4ace48c 100644
--- a/automotive/vehicle/2.1/default/Android.mk
+++ b/automotive/vehicle/2.1/default/Android.mk
@@ -18,17 +18,47 @@
vhal_v2_1 = android.hardware.automotive.vehicle@2.1
###############################################################################
+# Vehicle reference implementation lib
+###############################################################################
+include $(CLEAR_VARS)
+LOCAL_MODULE := $(vhal_v2_1)-manager-lib
+LOCAL_SRC_FILES := \
+ common/src/Obd2SensorStore.cpp
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/common/include/vhal_v2_1 \
+ $(LOCAL_PATH)/../../2.0/default/common/include/vhal_v2_0 \
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := \
+ $(LOCAL_PATH)/common/include
+
+LOCAL_SHARED_LIBRARIES := \
+ libbinder \
+ libhidlbase \
+ libhidltransport \
+ libhwbinder \
+ liblog \
+ libutils \
+ $(vhal_v2_1) \
+
+include $(BUILD_STATIC_LIBRARY)
+
+###############################################################################
# Vehicle default VehicleHAL implementation
###############################################################################
include $(CLEAR_VARS)
LOCAL_MODULE:= $(vhal_v2_1)-default-impl-lib
+LOCAL_SRC_FILES:= \
+ impl/vhal_v2_1/DefaultVehicleHal.cpp \
LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/impl/vhal_v2_1
+ $(LOCAL_PATH)/impl/vhal_v2_1 \
+ $(LOCAL_PATH)/common/include
LOCAL_EXPORT_C_INCLUDE_DIRS := \
- $(LOCAL_PATH)/impl
+ $(LOCAL_PATH)/impl \
+ $(LOCAL_PATH)/common/include
# LOCAL_WHOLE_STATIC_LIBRARIES := \
@@ -36,6 +66,7 @@
LOCAL_STATIC_LIBRARIES := \
$(vhal_v2_0)-default-impl-lib \
$(vhal_v2_0)-manager-lib \
+ $(vhal_v2_1)-manager-lib \
$(vhal_v2_0)-libproto-native
LOCAL_SHARED_LIBRARIES := \
@@ -69,6 +100,7 @@
$(vhal_v2_0)-manager-lib \
$(vhal_v2_0)-default-impl-lib \
$(vhal_v2_1)-default-impl-lib \
+ $(vhal_v2_1)-manager-lib \
LOCAL_SHARED_LIBRARIES := \
libbinder \
diff --git a/automotive/vehicle/2.1/default/common/include/vhal_v2_1/Obd2SensorStore.h b/automotive/vehicle/2.1/default/common/include/vhal_v2_1/Obd2SensorStore.h
new file mode 100644
index 0000000..945e3e0
--- /dev/null
+++ b/automotive/vehicle/2.1/default/common/include/vhal_v2_1/Obd2SensorStore.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_automotive_vehicle_V2_1_Obd2SensorStore_H_
+#define android_hardware_automotive_vehicle_V2_1_Obd2SensorStore_H_
+
+#include <vector>
+
+#include <android/hardware/automotive/vehicle/2.1/types.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_1 {
+
+// This class wraps all the logic required to create an OBD2 frame.
+// It allows storing sensor values, setting appropriate bitmasks as needed,
+// and returning appropriately laid out storage of sensor values suitable
+// for being returned via a VehicleHal implementation.
+class Obd2SensorStore {
+public:
+ // Creates a sensor storage with a given number of vendor-specific sensors.
+ Obd2SensorStore(size_t numVendorIntegerSensors,
+ size_t numVendorFloatSensors);
+
+ // Stores an integer-valued sensor.
+ V2_0::StatusCode setIntegerSensor(Obd2IntegerSensorIndex index, int32_t value);
+ // Stores an integer-valued sensor.
+ V2_0::StatusCode setIntegerSensor(size_t index, int32_t value);
+
+ // Stores a float-valued sensor.
+ V2_0::StatusCode setFloatSensor(Obd2FloatSensorIndex index, float value);
+ // Stores a float-valued sensor.
+ V2_0::StatusCode setFloatSensor(size_t index, float value);
+
+ // Returns a vector that contains all integer sensors stored.
+ const std::vector<int32_t>& getIntegerSensors() const;
+ // Returns a vector that contains all float sensors stored.
+ const std::vector<float>& getFloatSensors() const;
+ // 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(V2_0::VehiclePropValue *propValue,
+ std::string dtc) const;
+
+private:
+ class BitmaskInVector {
+ public:
+ BitmaskInVector(size_t numBits = 0);
+ void resize(size_t numBits);
+ bool get(size_t index) const;
+ void set(size_t index, bool value);
+
+ const std::vector<uint8_t>& getBitmask() const;
+
+ private:
+ std::vector<uint8_t> mStorage;
+ };
+
+ std::vector<int32_t> mIntegerSensors;
+ std::vector<float> mFloatSensors;
+ BitmaskInVector mSensorsBitmask;
+};
+
+} // namespace V2_1
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_automotive_vehicle_V2_0_Obd2SensorStore_H_
diff --git a/automotive/vehicle/2.1/default/common/src/Obd2SensorStore.cpp b/automotive/vehicle/2.1/default/common/src/Obd2SensorStore.cpp
new file mode 100644
index 0000000..b07717b
--- /dev/null
+++ b/automotive/vehicle/2.1/default/common/src/Obd2SensorStore.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Obd2SensorStore.h"
+
+#include <utils/SystemClock.h>
+#include "VehicleUtils.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_1 {
+
+Obd2SensorStore::BitmaskInVector::BitmaskInVector(size_t numBits)
+{
+ resize(numBits);
+}
+
+void Obd2SensorStore::BitmaskInVector::resize(size_t numBits) {
+ mStorage = std::vector<uint8_t>((numBits+7)/8, 0);
+}
+
+void Obd2SensorStore::BitmaskInVector::set(size_t index, bool value) {
+ const size_t byteIndex = index / 8;
+ const size_t bitIndex = index % 8;
+ const uint8_t byte = mStorage[byteIndex];
+ uint8_t newValue = value ? (byte | (1 << bitIndex)) :
+ (byte & ~(1 << bitIndex));
+ mStorage[byteIndex] = newValue;
+}
+
+bool Obd2SensorStore::BitmaskInVector::get(size_t index) const {
+ const size_t byteIndex = index / 8;
+ const size_t bitIndex = index % 8;
+ const uint8_t byte = mStorage[byteIndex];
+ return (byte & (1 << bitIndex)) != 0;
+}
+
+const std::vector<uint8_t>& Obd2SensorStore::BitmaskInVector::getBitmask() const {
+ return mStorage;
+}
+
+Obd2SensorStore::Obd2SensorStore(size_t numVendorIntegerSensors,
+ size_t numVendorFloatSensors) {
+ // because the last index is valid *inclusive*
+ const size_t numSystemIntegerSensors = V2_0::toInt(Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX)+1;
+ const size_t numSystemFloatSensors = V2_0::toInt(Obd2FloatSensorIndex::LAST_SYSTEM_INDEX)+1;
+ mIntegerSensors = std::vector<int32_t>(
+ numSystemIntegerSensors+numVendorIntegerSensors, 0);
+ mFloatSensors = std::vector<float>(
+ numSystemFloatSensors+numVendorFloatSensors, 0);
+ mSensorsBitmask.resize(mIntegerSensors.size()+mFloatSensors.size());
+}
+
+V2_0::StatusCode Obd2SensorStore::setIntegerSensor(Obd2IntegerSensorIndex index,
+ int32_t value) {
+ return setIntegerSensor(V2_0::toInt(index), value);
+}
+V2_0::StatusCode Obd2SensorStore::setFloatSensor(Obd2FloatSensorIndex index,
+ float value) {
+ return setFloatSensor(V2_0::toInt(index), value);
+}
+
+V2_0::StatusCode Obd2SensorStore::setIntegerSensor(size_t index, int32_t value) {
+ mIntegerSensors[index] = value;
+ mSensorsBitmask.set(index, true);
+ return V2_0::StatusCode::OK;
+}
+
+V2_0::StatusCode Obd2SensorStore::setFloatSensor(size_t index, float value) {
+ mFloatSensors[index] = value;
+ mSensorsBitmask.set(index + mIntegerSensors.size(), true);
+ return V2_0::StatusCode::OK;
+}
+
+const std::vector<int32_t>& Obd2SensorStore::getIntegerSensors() const {
+ return mIntegerSensors;
+}
+
+const std::vector<float>& Obd2SensorStore::getFloatSensors() const {
+ return mFloatSensors;
+}
+
+const std::vector<uint8_t>& Obd2SensorStore::getSensorsBitmask() const {
+ return mSensorsBitmask.getBitmask();
+}
+
+void Obd2SensorStore::fillPropValue(V2_0::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
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultConfig.h b/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultConfig.h
index ab08cec..769ae6d 100644
--- a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultConfig.h
+++ b/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultConfig.h
@@ -33,6 +33,32 @@
.prop = V2_0::toInt(V2_1::VehicleProperty::WHEEL_TICK),
.access = V2_0::VehiclePropertyAccess::READ,
.changeMode = V2_0::VehiclePropertyChangeMode::CONTINUOUS,
+ },
+
+ {
+ .prop = V2_0::toInt(V2_1::VehicleProperty::OBD2_LIVE_FRAME),
+ .access = V2_0::VehiclePropertyAccess::READ,
+ .changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE,
+ .configArray = {0,0}
+ },
+
+ {
+ .prop = V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME),
+ .access = V2_0::VehiclePropertyAccess::READ,
+ .changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE,
+ .configArray = {0,0}
+ },
+
+ {
+ .prop = V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME_INFO),
+ .access = V2_0::VehiclePropertyAccess::READ,
+ .changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE
+ },
+
+ {
+ .prop = V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME_CLEAR),
+ .access = V2_0::VehiclePropertyAccess::WRITE,
+ .changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE
}
};
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
new file mode 100644
index 0000000..dc96bf9
--- /dev/null
+++ b/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.cpp
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "DefaultVehicleHal_v2_1"
+#include <android/log.h>
+
+#include <algorithm>
+#include <netinet/in.h>
+#include <sys/socket.h>
+
+#include "DefaultVehicleHal.h"
+#include "VehicleHalProto.pb.h"
+
+#define DEBUG_SOCKET (33452)
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_1 {
+
+namespace impl {
+
+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,
+ V2_0::toInt(FuelSystemStatus::CLOSED_LOOP));
+ sensorStore->setIntegerSensor(
+ Obd2IntegerSensorIndex::MALFUNCTION_INDICATOR_LIGHT_ON, 0);
+ sensorStore->setIntegerSensor(
+ Obd2IntegerSensorIndex::IGNITION_MONITORS_SUPPORTED,
+ V2_0::toInt(IgnitionMonitorKind::SPARK));
+ sensorStore->setIntegerSensor(Obd2IntegerSensorIndex::IGNITION_SPECIFIC_MONITORS,
+ CommonIgnitionMonitors::COMPONENTS_AVAILABLE |
+ CommonIgnitionMonitors::MISFIRE_AVAILABLE |
+ SparkIgnitionMonitors::AC_REFRIGERANT_AVAILABLE |
+ SparkIgnitionMonitors::EVAPORATIVE_SYSTEM_AVAILABLE);
+ sensorStore->setIntegerSensor(
+ Obd2IntegerSensorIndex::INTAKE_AIR_TEMPERATURE, 35);
+ sensorStore->setIntegerSensor(
+ Obd2IntegerSensorIndex::COMMANDED_SECONDARY_AIR_STATUS,
+ V2_0::toInt(SecondaryAirStatus::FROM_OUTSIDE_OR_OFF));
+ sensorStore->setIntegerSensor(
+ Obd2IntegerSensorIndex::NUM_OXYGEN_SENSORS_PRESENT, 1);
+ sensorStore->setIntegerSensor(
+ Obd2IntegerSensorIndex::RUNTIME_SINCE_ENGINE_START, 500);
+ sensorStore->setIntegerSensor(
+ Obd2IntegerSensorIndex::DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON, 0);
+ sensorStore->setIntegerSensor(
+ Obd2IntegerSensorIndex::WARMUPS_SINCE_CODES_CLEARED, 51);
+ sensorStore->setIntegerSensor(
+ Obd2IntegerSensorIndex::DISTANCE_TRAVELED_SINCE_CODES_CLEARED, 365);
+ sensorStore->setIntegerSensor(
+ Obd2IntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE, 30);
+ sensorStore->setIntegerSensor(
+ Obd2IntegerSensorIndex::CONTROL_MODULE_VOLTAGE, 12);
+ sensorStore->setIntegerSensor(
+ Obd2IntegerSensorIndex::AMBIENT_AIR_TEMPERATURE, 18);
+ sensorStore->setIntegerSensor(
+ Obd2IntegerSensorIndex::MAX_FUEL_AIR_EQUIVALENCE_RATIO, 1);
+ sensorStore->setIntegerSensor(
+ Obd2IntegerSensorIndex::FUEL_TYPE, V2_0::toInt(FuelType::GASOLINE));
+ sensorStore->setFloatSensor(
+ Obd2FloatSensorIndex::CALCULATED_ENGINE_LOAD, 0.153);
+ sensorStore->setFloatSensor(
+ Obd2FloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK1, -0.16);
+ sensorStore->setFloatSensor(
+ Obd2FloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK1, -0.16);
+ sensorStore->setFloatSensor(
+ Obd2FloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK2, -0.16);
+ sensorStore->setFloatSensor(
+ Obd2FloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK2, -0.16);
+ sensorStore->setFloatSensor(
+ Obd2FloatSensorIndex::INTAKE_MANIFOLD_ABSOLUTE_PRESSURE, 7.5);
+ sensorStore->setFloatSensor(
+ Obd2FloatSensorIndex::ENGINE_RPM, 1250.);
+ sensorStore->setFloatSensor(
+ Obd2FloatSensorIndex::VEHICLE_SPEED, 40.);
+ sensorStore->setFloatSensor(
+ Obd2FloatSensorIndex::TIMING_ADVANCE, 2.5);
+ sensorStore->setFloatSensor(
+ Obd2FloatSensorIndex::THROTTLE_POSITION, 19.75);
+ sensorStore->setFloatSensor(
+ Obd2FloatSensorIndex::OXYGEN_SENSOR1_VOLTAGE, 0.265);
+ sensorStore->setFloatSensor(
+ Obd2FloatSensorIndex::FUEL_TANK_LEVEL_INPUT, 0.824);
+ sensorStore->setFloatSensor(
+ Obd2FloatSensorIndex::EVAPORATION_SYSTEM_VAPOR_PRESSURE, -0.373);
+ sensorStore->setFloatSensor(
+ Obd2FloatSensorIndex::CATALYST_TEMPERATURE_BANK1_SENSOR1, 190.);
+ sensorStore->setFloatSensor(
+ Obd2FloatSensorIndex::RELATIVE_THROTTLE_POSITION, 3.);
+ sensorStore->setFloatSensor(
+ Obd2FloatSensorIndex::ABSOLUTE_THROTTLE_POSITION_B, 0.306);
+ sensorStore->setFloatSensor(
+ Obd2FloatSensorIndex::ACCELERATOR_PEDAL_POSITION_D, 0.188);
+ sensorStore->setFloatSensor(
+ Obd2FloatSensorIndex::ACCELERATOR_PEDAL_POSITION_E, 0.094);
+ sensorStore->setFloatSensor(
+ Obd2FloatSensorIndex::COMMANDED_THROTTLE_ACTUATOR, 0.024);
+
+ return sensorStore;
+}
+
+void DefaultVehicleHal::initObd2LiveFrame(V2_0::VehiclePropConfig& propConfig) {
+ auto sensorStore = fillDefaultObd2Frame(propConfig.configArray[0],
+ propConfig.configArray[1]);
+ mLiveObd2Frame = createVehiclePropValue(
+ V2_0::VehiclePropertyType::COMPLEX, 0);
+ sensorStore->fillPropValue(mLiveObd2Frame.get(), "");
+}
+
+void DefaultVehicleHal::initObd2FreezeFrame(V2_0::VehiclePropConfig& propConfig) {
+ auto sensorStore = fillDefaultObd2Frame(propConfig.configArray[0],
+ propConfig.configArray[1]);
+
+ mFreezeObd2Frames.push_back(
+ createVehiclePropValue(V2_0::VehiclePropertyType::COMPLEX,0));
+ mFreezeObd2Frames.push_back(
+ createVehiclePropValue(V2_0::VehiclePropertyType::COMPLEX,0));
+ mFreezeObd2Frames.push_back(
+ createVehiclePropValue(V2_0::VehiclePropertyType::COMPLEX,0));
+
+ sensorStore->fillPropValue(mFreezeObd2Frames[0].get(), "P0070");
+ sensorStore->fillPropValue(mFreezeObd2Frames[1].get(), "P0102");
+ 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,
+ int64_t timestamp) {
+ return std::find_if(frames.begin(),
+ frames.end(),
+ [timestamp] (const std::unique_ptr<V2_0::VehiclePropValue>&
+ propValue) -> bool {
+ return propValue->timestamp == timestamp;
+ });
+}
+
+V2_0::StatusCode DefaultVehicleHal::fillObd2FreezeFrame(
+ const V2_0::VehiclePropValue& requestedPropValue,
+ V2_0::VehiclePropValue* v) {
+ if (requestedPropValue.value.int64Values.size() != 1) {
+ ALOGE("asked for OBD2_FREEZE_FRAME without valid timestamp");
+ return V2_0::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 V2_0::StatusCode::INVALID_ARG;
+ }
+ const auto& freezeFrame = *freezeFrameIter;
+ v->prop = V2_0::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 V2_0::StatusCode::OK;
+}
+
+V2_0::StatusCode DefaultVehicleHal::clearObd2FreezeFrames(
+ const V2_0::VehiclePropValue& propValue) {
+ if (propValue.value.int64Values.size() == 0) {
+ mFreezeObd2Frames.clear();
+ return V2_0::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 V2_0::StatusCode::INVALID_ARG;
+ }
+ mFreezeObd2Frames.erase(freezeFrameIter);
+ }
+ }
+ return V2_0::StatusCode::OK;
+}
+
+V2_0::StatusCode DefaultVehicleHal::fillObd2DtcInfo(V2_0::VehiclePropValue* v) {
+ std::vector<int64_t> timestamps;
+ for(const auto& freezeFrame: mFreezeObd2Frames) {
+ timestamps.push_back(freezeFrame->timestamp);
+ }
+ v->value.int64Values = timestamps;
+ return V2_0::StatusCode::OK;
+}
+
+void DefaultVehicleHal::onCreate() {
+ mVehicleHal20->init(getValuePool(),
+ std::bind(&DefaultVehicleHal::doHalEvent, this, _1),
+ std::bind(&DefaultVehicleHal::doHalPropertySetError, this, _1, _2, _3));
+
+ 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);
+ break;
+ case V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME):
+ initObd2FreezeFrame(cfg);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+DefaultVehicleHal::VehiclePropValuePtr DefaultVehicleHal::get(
+ const V2_0::VehiclePropValue& requestedPropValue,
+ V2_0::StatusCode* outStatus) {
+
+ auto propId = requestedPropValue.prop;
+ VehiclePropValuePtr v = nullptr;
+ 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());
+ return v;
+ case V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME_INFO):
+ v = pool.obtainComplex();
+ *outStatus = fillObd2DtcInfo(v.get());
+ return v;
+ default:
+ return mVehicleHal20->get(requestedPropValue, outStatus);
+ }
+}
+
+V2_0::StatusCode DefaultVehicleHal::set(
+ const V2_0::VehiclePropValue& propValue) {
+
+ auto propId = propValue.prop;
+ switch (propId) {
+ case V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME_CLEAR):
+ return clearObd2FreezeFrames(propValue);
+ break;
+ default:
+ return mVehicleHal20->set(propValue);
+ }
+}
+
+} // impl
+
+} // namespace V2_1
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
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 7ccb354..ac65fc6 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
@@ -23,6 +23,7 @@
#include <vhal_v2_0/VehicleHal.h>
#include <vhal_v2_0/DefaultVehicleHal.h>
+#include <vhal_v2_1/Obd2SensorStore.h>
#include "DefaultConfig.h"
@@ -52,14 +53,9 @@
}
VehiclePropValuePtr get(const V2_0::VehiclePropValue& requestedPropValue,
- V2_0::StatusCode* outStatus) override {
- // TODO(pavelm): put logic related to VHAL 2.1 here (OBD, VMS, etc)
- return mVehicleHal20->get(requestedPropValue, outStatus);
- }
+ V2_0::StatusCode* outStatus) override;
- V2_0::StatusCode set(const V2_0::VehiclePropValue& propValue) override {
- return mVehicleHal20->set(propValue);
- }
+ V2_0::StatusCode set(const V2_0::VehiclePropValue& propValue) override;
V2_0::StatusCode subscribe(int32_t property,
int32_t areas,
@@ -71,14 +67,21 @@
return mVehicleHal20->unsubscribe(property);
}
- void onCreate() override {
- mVehicleHal20->init(getValuePool(),
- std::bind(&DefaultVehicleHal::doHalEvent, this, _1),
- std::bind(&DefaultVehicleHal::doHalPropertySetError, this, _1, _2, _3));
- }
+ void onCreate() override;
+
+private:
+ void initObd2LiveFrame(V2_0::VehiclePropConfig& propConfig);
+ 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};
+ std::vector<std::unique_ptr<V2_0::VehiclePropValue>> mFreezeObd2Frames;
};
} // impl
diff --git a/automotive/vehicle/2.1/default/tests/Obd2SensorStore_test.cpp b/automotive/vehicle/2.1/default/tests/Obd2SensorStore_test.cpp
new file mode 100644
index 0000000..a01c0f4
--- /dev/null
+++ b/automotive/vehicle/2.1/default/tests/Obd2SensorStore_test.cpp
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ #include <gtest/gtest.h>
+
+#include "vhal_v2_0/Obd2SensorStore.h"
+#include "vhal_v2_0/VehicleUtils.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace {
+
+static constexpr size_t getNumVendorIntegerSensors() {
+ return 5;
+}
+static constexpr size_t getNumVendorFloatSensors() {
+ return 3;
+}
+
+// this struct holds information necessary for a test to be able to validate
+// that the sensor bitmask contains the right data:
+// - the index of the byte at which the bit for a given sensor lives
+// - the expected value of that byte given that a certain sensor is present
+class BitmaskIndexingInfo {
+public:
+ size_t mByteIndex;
+ uint8_t mExpectedByteValue;
+
+ // Returns the information required to validate the bitmask for an
+ // integer-valued sensor.
+ static BitmaskIndexingInfo getForIntegerSensor(size_t index) {
+ const size_t indexInBitstream = index;
+ return getForBitstreamIndex(indexInBitstream);
+ }
+
+ // Returns the information required to validate the bitmask for a
+ // float-valued sensor.
+ static BitmaskIndexingInfo getForFloatSensor(size_t index) {
+ const size_t indexInBitstream = toInt(Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX) +
+ 1 + getNumVendorIntegerSensors() + index;
+ return getForBitstreamIndex(indexInBitstream);
+ }
+
+private:
+ static BitmaskIndexingInfo getForBitstreamIndex(size_t indexInBitstream) {
+ BitmaskIndexingInfo indexingInfo;
+ indexingInfo.mByteIndex = indexInBitstream / 8;
+ indexingInfo.mExpectedByteValue = 1 << (indexInBitstream % 8);
+ return indexingInfo;
+ }
+};
+
+static Obd2SensorStore getSensorStore() {
+ return Obd2SensorStore(getNumVendorIntegerSensors(),
+ getNumVendorFloatSensors());
+}
+
+// Test that one can set and retrieve a value for the first integer sensor.
+TEST(Obd2SensorStoreTest, setFirstIntegerSensor) {
+ Obd2SensorStore sensorStore(getSensorStore());
+ sensorStore.setIntegerSensor(
+ Obd2IntegerSensorIndex::FUEL_SYSTEM_STATUS,
+ toInt(FuelSystemStatus::CLOSED_LOOP));
+ const auto& integerSensors(sensorStore.getIntegerSensors());
+ const auto& sensorBitmask(sensorStore.getSensorsBitmask());
+ ASSERT_EQ(
+ toInt(FuelSystemStatus::CLOSED_LOOP),
+ integerSensors[toInt(Obd2IntegerSensorIndex::FUEL_SYSTEM_STATUS)]);
+ const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForIntegerSensor(
+ toInt(Obd2IntegerSensorIndex::FUEL_SYSTEM_STATUS)));
+ ASSERT_EQ(
+ indexingInfo.mExpectedByteValue,
+ sensorBitmask[indexingInfo.mByteIndex]);
+}
+
+// Test that one can set and retrieve a value for the first float sensor.
+TEST(Obd2SensorStoreTest, setFirstFloatSensor) {
+ Obd2SensorStore sensorStore(getSensorStore());
+ sensorStore.setFloatSensor(
+ Obd2FloatSensorIndex::CALCULATED_ENGINE_LOAD,
+ 1.25f);
+ const auto& floatSensors(sensorStore.getFloatSensors());
+ const auto& sensorBitmask(sensorStore.getSensorsBitmask());
+ ASSERT_EQ(
+ 1.25f,
+ floatSensors[toInt(Obd2FloatSensorIndex::CALCULATED_ENGINE_LOAD)]);
+ const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForFloatSensor(
+ toInt(Obd2FloatSensorIndex::CALCULATED_ENGINE_LOAD)));
+ ASSERT_EQ(
+ indexingInfo.mExpectedByteValue,
+ sensorBitmask[indexingInfo.mByteIndex]);
+}
+
+// Test that one can set and retrieve a value for an integer sensor.
+TEST(Obd2SensorStoreTest, setAnyIntegerSensor) {
+ Obd2SensorStore sensorStore(getSensorStore());
+ sensorStore.setIntegerSensor(
+ Obd2IntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE,
+ 4000);
+ const auto& integerSensors(sensorStore.getIntegerSensors());
+ const auto& sensorBitmask(sensorStore.getSensorsBitmask());
+ ASSERT_EQ(4000,
+ integerSensors[toInt(Obd2IntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE)]);
+ const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForIntegerSensor(
+ toInt(Obd2IntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE)));
+ ASSERT_EQ(
+ indexingInfo.mExpectedByteValue,
+ sensorBitmask[indexingInfo.mByteIndex]);
+}
+
+// Test that one can set and retrieve a value for a float sensor.
+TEST(Obd2SensorStoreTest, setAnyFloatSensor) {
+ Obd2SensorStore sensorStore(getSensorStore());
+ sensorStore.setFloatSensor(
+ Obd2FloatSensorIndex::OXYGEN_SENSOR3_VOLTAGE,
+ 2.5f);
+ const auto& floatSensors(sensorStore.getFloatSensors());
+ const auto& sensorBitmask(sensorStore.getSensorsBitmask());
+ ASSERT_EQ(2.5f,
+ floatSensors[toInt(Obd2FloatSensorIndex::OXYGEN_SENSOR3_VOLTAGE)]);
+ const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForFloatSensor(
+ toInt(Obd2FloatSensorIndex::OXYGEN_SENSOR3_VOLTAGE)));
+ ASSERT_EQ(
+ indexingInfo.mExpectedByteValue,
+ sensorBitmask[indexingInfo.mByteIndex]);
+}
+
+// Test that one can set and retrieve a value for the last system integer sensor.
+TEST(Obd2SensorStoreTest, setLastSystemIntegerSensor) {
+ Obd2SensorStore sensorStore(getSensorStore());
+ sensorStore.setIntegerSensor(
+ Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX,
+ 30);
+ const auto& integerSensors(sensorStore.getIntegerSensors());
+ const auto& sensorBitmask(sensorStore.getSensorsBitmask());
+ ASSERT_EQ(30,
+ integerSensors[toInt(Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX)]);
+ const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForIntegerSensor(
+ toInt(Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX)));
+ ASSERT_EQ(
+ indexingInfo.mExpectedByteValue,
+ sensorBitmask[indexingInfo.mByteIndex]);
+}
+
+// Test that one can set and retrieve a value for the last system float sensor.
+TEST(Obd2SensorStoreTest, setLastSystemFloatSensor) {
+ Obd2SensorStore sensorStore(getSensorStore());
+ sensorStore.setFloatSensor(
+ Obd2FloatSensorIndex::LAST_SYSTEM_INDEX,
+ 2.5f);
+ const auto& floatSensors(sensorStore.getFloatSensors());
+ const auto& sensorBitmask(sensorStore.getSensorsBitmask());
+ ASSERT_EQ(2.5f,
+ floatSensors[toInt(Obd2FloatSensorIndex::LAST_SYSTEM_INDEX)]);
+ const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForFloatSensor(
+ toInt(Obd2FloatSensorIndex::LAST_SYSTEM_INDEX)));
+ ASSERT_EQ(
+ indexingInfo.mExpectedByteValue,
+ sensorBitmask[indexingInfo.mByteIndex]);
+}
+
+// Test that one can set and retrieve a value for two integer sensors at once.
+TEST(Obd2SensorStoreTest, setTwoIntegerSensors) {
+ Obd2SensorStore sensorStore(getSensorStore());
+ sensorStore.setIntegerSensor(
+ Obd2IntegerSensorIndex::CONTROL_MODULE_VOLTAGE,
+ 6);
+ sensorStore.setIntegerSensor(
+ Obd2IntegerSensorIndex::TIME_SINCE_TROUBLE_CODES_CLEARED,
+ 1245);
+ const auto& integerSensors(sensorStore.getIntegerSensors());
+ const auto& sensorBitmask(sensorStore.getSensorsBitmask());
+ ASSERT_EQ(6,
+ integerSensors[toInt(Obd2IntegerSensorIndex::CONTROL_MODULE_VOLTAGE)]);
+ ASSERT_EQ(1245,
+ integerSensors[toInt(Obd2IntegerSensorIndex::TIME_SINCE_TROUBLE_CODES_CLEARED)]);
+ const BitmaskIndexingInfo voltageIndexingInfo(BitmaskIndexingInfo::getForIntegerSensor(
+ toInt(Obd2IntegerSensorIndex::CONTROL_MODULE_VOLTAGE)));
+ const BitmaskIndexingInfo timeIndexingInfo(BitmaskIndexingInfo::getForIntegerSensor(
+ toInt(Obd2IntegerSensorIndex::TIME_SINCE_TROUBLE_CODES_CLEARED)));
+ if (voltageIndexingInfo.mByteIndex == timeIndexingInfo.mByteIndex) {
+ ASSERT_EQ(
+ voltageIndexingInfo.mExpectedByteValue |
+ timeIndexingInfo.mExpectedByteValue,
+ sensorBitmask[timeIndexingInfo.mByteIndex]);
+ }
+ else {
+ ASSERT_EQ(
+ timeIndexingInfo.mExpectedByteValue,
+ sensorBitmask[timeIndexingInfo.mByteIndex]);
+ ASSERT_EQ(
+ voltageIndexingInfo.mExpectedByteValue,
+ sensorBitmask[voltageIndexingInfo.mByteIndex]);
+ }
+}
+
+// Test that one can set and retrieve a value for two float sensors at once.
+TEST(Obd2SensorStoreTest, setTwoFloatSensors) {
+ Obd2SensorStore sensorStore(getSensorStore());
+ sensorStore.setFloatSensor(
+ Obd2FloatSensorIndex::VEHICLE_SPEED,
+ 1.25f);
+ sensorStore.setFloatSensor(
+ Obd2FloatSensorIndex::MAF_AIR_FLOW_RATE,
+ 2.5f);
+ const auto& floatSensors(sensorStore.getFloatSensors());
+ const auto& sensorBitmask(sensorStore.getSensorsBitmask());
+ ASSERT_EQ(1.25f,
+ floatSensors[toInt(Obd2FloatSensorIndex::VEHICLE_SPEED)]);
+ ASSERT_EQ(2.5f,
+ floatSensors[toInt(Obd2FloatSensorIndex::MAF_AIR_FLOW_RATE)]);
+ const BitmaskIndexingInfo speedIndexingInfo(BitmaskIndexingInfo::getForFloatSensor(
+ toInt(Obd2FloatSensorIndex::VEHICLE_SPEED)));
+ const BitmaskIndexingInfo airflowIndexingInfo(BitmaskIndexingInfo::getForFloatSensor(
+ toInt(Obd2FloatSensorIndex::MAF_AIR_FLOW_RATE)));
+ if (speedIndexingInfo.mByteIndex == airflowIndexingInfo.mByteIndex) {
+ ASSERT_EQ(
+ speedIndexingInfo.mExpectedByteValue |
+ airflowIndexingInfo.mExpectedByteValue,
+ sensorBitmask[airflowIndexingInfo.mByteIndex]);
+ }
+ else {
+ ASSERT_EQ(
+ speedIndexingInfo.mExpectedByteValue,
+ sensorBitmask[speedIndexingInfo.mByteIndex]);
+ ASSERT_EQ(
+ airflowIndexingInfo.mExpectedByteValue,
+ sensorBitmask[airflowIndexingInfo.mByteIndex]);
+ }
+}
+
+// Test that one can set and retrieve a value for a vendor integer sensor.
+TEST(Obd2SensorStoreTest, setVendorIntegerSensor) {
+ const size_t sensorIndex = toInt(Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX) + 2;
+ Obd2SensorStore sensorStore(getSensorStore());
+ sensorStore.setIntegerSensor(sensorIndex, 22);
+ const auto& integerSensors(sensorStore.getIntegerSensors());
+ const auto& sensorBitmask(sensorStore.getSensorsBitmask());
+ ASSERT_EQ(22, integerSensors[sensorIndex]);
+ const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForIntegerSensor(
+ sensorIndex));
+ ASSERT_EQ(
+ indexingInfo.mExpectedByteValue,
+ sensorBitmask[indexingInfo.mByteIndex]);
+}
+
+// Test that one can set and retrieve a value for a vendor float sensor.
+TEST(Obd2SensorStoreTest, setVendorFloatSensor) {
+ const size_t sensorIndex = toInt(Obd2FloatSensorIndex::LAST_SYSTEM_INDEX) + 2;
+ Obd2SensorStore sensorStore(getSensorStore());
+ sensorStore.setFloatSensor(sensorIndex, 1.25f);
+ const auto& floatSensors(sensorStore.getFloatSensors());
+ const auto& sensorBitmask(sensorStore.getSensorsBitmask());
+ ASSERT_EQ(1.25f, floatSensors[sensorIndex]);
+ const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForFloatSensor(
+ sensorIndex));
+ ASSERT_EQ(
+ indexingInfo.mExpectedByteValue,
+ sensorBitmask[indexingInfo.mByteIndex]);
+}
+
+} // namespace anonymous
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android