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/Android.mk b/automotive/vehicle/2.1/Android.mk
index 2a8d1dd..f5a121d 100644
--- a/automotive/vehicle/2.1/Android.mk
+++ b/automotive/vehicle/2.1/Android.mk
@@ -18,6 +18,177 @@
 
 
 #
+# Build types.hal (CommonIgnitionMonitors)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/CommonIgnitionMonitors.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.1::types.CommonIgnitionMonitors
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CompressionIgnitionMonitors)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/CompressionIgnitionMonitors.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.1::types.CompressionIgnitionMonitors
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (FuelSystemStatus)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/FuelSystemStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.1::types.FuelSystemStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (FuelType)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/FuelType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.1::types.FuelType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (IgnitionMonitorKind)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/IgnitionMonitorKind.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.1::types.IgnitionMonitorKind
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2FloatSensorIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/Obd2FloatSensorIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.1::types.Obd2FloatSensorIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2IntegerSensorIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/Obd2IntegerSensorIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.1::types.Obd2IntegerSensorIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (SecondaryAirStatus)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/SecondaryAirStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.1::types.SecondaryAirStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (SparkIgnitionMonitors)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/SparkIgnitionMonitors.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.1::types.SparkIgnitionMonitors
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
 # Build types.hal (VehicleProperty)
 #
 GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VehicleProperty.java
@@ -73,6 +244,177 @@
 
 
 #
+# Build types.hal (CommonIgnitionMonitors)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/CommonIgnitionMonitors.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.1::types.CommonIgnitionMonitors
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CompressionIgnitionMonitors)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/CompressionIgnitionMonitors.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.1::types.CompressionIgnitionMonitors
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (FuelSystemStatus)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/FuelSystemStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.1::types.FuelSystemStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (FuelType)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/FuelType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.1::types.FuelType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (IgnitionMonitorKind)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/IgnitionMonitorKind.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.1::types.IgnitionMonitorKind
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2FloatSensorIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/Obd2FloatSensorIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.1::types.Obd2FloatSensorIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2IntegerSensorIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/Obd2IntegerSensorIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.1::types.Obd2IntegerSensorIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (SecondaryAirStatus)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/SecondaryAirStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.1::types.SecondaryAirStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (SparkIgnitionMonitors)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/SparkIgnitionMonitors.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.1::types.SparkIgnitionMonitors
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
 # Build types.hal (VehicleProperty)
 #
 GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VehicleProperty.java
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
diff --git a/automotive/vehicle/2.1/types.hal b/automotive/vehicle/2.1/types.hal
index 5df1fbc..f0dd95f 100644
--- a/automotive/vehicle/2.1/types.hal
+++ b/automotive/vehicle/2.1/types.hal
@@ -43,4 +43,511 @@
       | VehiclePropertyGroup:SYSTEM
       | VehiclePropertyType:FLOAT_VEC
       | VehicleArea:GLOBAL),
+
+    /*
+     * OBD2 Live Sensor Data
+     *
+     * This property uses COMPLEX data to send a snapshot of the current (live)
+     * values of the OBD2 sensors provided by the vehicle.
+     *
+     * VehiclePropConfig
+     *   configArray[0] : number of vendor-specific integer-valued sensors
+     *                    that can be returned in a frame.
+     *   configArray[1] : number of vendor-specific float-valued sensors
+     *                    that can be returned in a frame.
+     *
+     * The values are to be interpreted as follows:
+     * the indices defined in Obd2IntegerSensorIndex are to be used to
+     * read from int32Values;
+     * the indices defined in Obd2FloatSensorIndex are to be used to
+     * read from floatValues.
+     * the elements of bytes are to be interpreted as a bitmask, such that
+     * the bits 0 thru the integer value of
+     * Obd2IntegerSensorIndex.LAST_SYSTEM_INDEX + the value of configArray[0]
+     * are 1 if the corresponding index is a valid sensor index whose value can
+     * be read in the returned int32Values vector, 0 otherwise.
+     * the bits Obd2IntegerSensorIndex.LAST_SYSTEM_INDEX+1 thru
+     * Obd2FloatingSensorIndex.LAST_SYSTEM_INDEX + the value of configArray[1]
+     * are 1 if the corresponding index is a valid sensor index whose value
+     * can be read in the returned floatValues vector, 0 otherwise.
+     *
+     * For example, int32Values[0] corresponds to FUEL_SYSTEM_STATUS, and
+     * floatValues[0] corresponds to CALCULATED_ENGINE_LOAD, but that mapping
+     * is only valid if the corresponding bits in the bytes vector are set to 1.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    OBD2_LIVE_FRAME = (
+      0x0D00
+      | VehiclePropertyGroup:SYSTEM
+      | VehiclePropertyType:COMPLEX
+      | VehicleArea:GLOBAL),
+
+    /*
+     * OBD2 Freeze Frame Sensor Data
+     *
+     * This property uses COMPLEX data to send a snapshot of the values of the
+     * OBD2 sensors provided by the vehicle at the time that a diagnostic
+     * troubleshooting code (DTC) was recorded by the vehicle.
+     *
+     * VehiclePropConfig
+     *   configArray[0] : number of vendor-specific integer-valued sensors
+     *                    that can be returned in a frame.
+     *   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;
+     * the indices defined in Obd2FloatSensorIndex are to be used to
+     * read from floatValues;
+     * the elements of bytes are to be interpreted as a bitmask, such that
+     * the bits 0 thru the integer value of
+     * Obd2IntegerSensorIndex.LAST_SYSTEM_INDEX + the value of configArray[0]
+     * are 1 if the corresponding index is a valid sensor index whose value can
+     * be read in the returned int32Values vector, 0 otherwise.
+     * the bits Obd2IntegerSensorIndex.LAST_SYSTEM_INDEX+1 thru
+     * Obd2FloatingSensorIndex.LAST_SYSTEM_INDEX + the value of configArray[1]
+     * are 1 if the corresponding index is a valid sensor index whose value
+     * can be read in the returned floatValues vector, 0 otherwise.
+     * stringValue is the DTC that caused this freeze frame to be recorded.
+     *
+     * For example, int32Values[0] corresponds to FUEL_SYSTEM_STATUS, and
+     * floatValues[0] corresponds to CALCULATED_ENGINE_LOAD, but that mapping
+     * is only valid if the corresponding bits in the bytes vector are set to 1,
+     * and a possible valid stringValue is "P0176" to indicate a malfunction
+     * of the fuel composition sensor circuit.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    OBD2_FREEZE_FRAME = (
+      0x0D01
+      | VehiclePropertyGroup:SYSTEM
+      | 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),
+};
+
+/* The status of a fuel system as described by the OBD2 specification. */
+enum FuelSystemStatus : int32_t {
+  OPEN_INSUFFICIENT_ENGINE_TEMPERATURE = 1,
+
+  CLOSED_LOOP = 2,
+
+  OPEN_ENGINE_LOAD_OR_DECELERATION = 4,
+
+  OPEN_SYSTEM_FAILURE = 8,
+
+  CLOSED_LOOP_BUT_FEEDBACK_FAULT = 16,
+};
+
+/* Defines which ignition monitors are available to be read. */
+enum IgnitionMonitorKind : int32_t {
+  SPARK = 0,
+
+  COMPRESSION = 1,
+};
+
+/* These ignition monitors are common to both SPARK and COMPRESSION. */
+enum CommonIgnitionMonitors : int32_t {
+  COMPONENTS_AVAILABLE = 0x1 << 0,
+  COMPONENTS_INCOMPLETE = 0x1 << 1,
+
+  FUEL_SYSTEM_AVAILABLE = 0x1 << 2,
+  FUEL_SYSTEM_INCOMPLETE = 0x1 << 3,
+
+  MISFIRE_AVAILABLE = 0x1 << 4,
+  MISFIRE_INCOMPLETE = 0x1 << 5,
+};
+
+/* Ignition monitors available for SPARK vehicles. */
+enum SparkIgnitionMonitors : CommonIgnitionMonitors {
+  EGR_AVAILABLE = 0x1 << 6,
+  EGR_INCOMPLETE = 0x1 << 7,
+
+  OXYGEN_SENSOR_HEATER_AVAILABLE = 0x1 << 8,
+  OXYGEN_SENSOR_HEATER_INCOMPLETE = 0x1 << 9,
+
+  OXYGEN_SENSOR_AVAILABLE = 0x1 << 10,
+  OXYGEN_SENSOR_INCOMPLETE = 0x1 << 11,
+
+  AC_REFRIGERANT_AVAILABLE = 0x1 << 12,
+  AC_REFRIGERANT_INCOMPLETE = 0x1 << 13,
+
+  SECONDARY_AIR_SYSTEM_AVAILABLE = 0x1 << 14,
+  SECONDARY_AIR_SYSTEM_INCOMPLETE = 0x1 << 15,
+
+  EVAPORATIVE_SYSTEM_AVAILABLE = 0x1 << 16,
+  EVAPORATIVE_SYSTEM_INCOMPLETE = 0x1 << 17,
+
+  HEATED_CATALYST_AVAILABLE = 0x1 << 18,
+  HEATED_CATALYST_INCOMPLETE = 0x1 << 19,
+
+  CATALYST_AVAILABLE = 0x1 << 20,
+  CATALYST_INCOMPLETE = 0x1 << 21,
+};
+
+/* Ignition monitors only available for COMPRESSION vehicles. */
+enum CompressionIgnitionMonitors : CommonIgnitionMonitors {
+  EGR_OR_VVT_AVAILABLE = 0x1 << 6,
+  EGR_OR_VVT_INCOMPLETE = 0x1 << 7,
+
+  PM_FILTER_AVAILABLE = 0x1 << 8,
+  PM_FILTER_INCOMPLETE = 0x1 << 9,
+
+  EXHAUST_GAS_SENSOR_AVAILABLE = 0x1 << 10,
+  EXHAUST_GAS_SENSOR_INCOMPLETE = 0x1 << 11,
+
+  BOOST_PRESSURE_AVAILABLE = 0x1 << 12,
+  BOOST_PRESSURE_INCOMPLETE = 0x1 << 13,
+
+  NOx_SCR__AVAILABLE = 0x1 << 14,
+  NOx_SCR_INCOMPLETE = 0x1 << 15,
+
+  NMHC_CATALYST_AVAILABLE = 0x1 << 16,
+  NMHC_CATALYST_INCOMPLETE = 0x1 << 17,
+};
+
+enum SecondaryAirStatus : int32_t {
+  UPSTREAM = 1,
+
+  DOWNSTREAM_OF_CATALYCIC_CONVERTER = 2,
+
+  FROM_OUTSIDE_OR_OFF = 4,
+
+  PUMP_ON_FOR_DIAGNOSTICS = 8,
+};
+
+enum FuelType : int32_t {
+  NOT_AVAILABLE = 0,
+
+  GASOLINE = 1,
+
+  METHANOL = 2,
+
+  ETHANOL = 3,
+
+  DIESEL = 4,
+
+  LPG = 5,
+
+  CNG = 6,
+
+  PROPANE = 7,
+
+  ELECTRIC = 8,
+
+  BIFUEL_RUNNING_GASOLINE = 9,
+
+  BIFUEL_RUNNING_METHANOL = 10,
+
+  BIFUEL_RUNNING_ETHANOL = 11,
+
+  BIFUEL_RUNNING_LPG = 12,
+
+  BIFUEL_RUNNING_CNG = 13,
+
+  BIFUEL_RUNNING_PROPANE = 14,
+
+  BIFUEL_RUNNING_ELECTRIC = 15,
+
+  BIFUEL_RUNNING_ELECTRIC_AND_COMBUSTION = 16,
+
+  HYBRID_GASOLINE = 17,
+
+  HYBRID_ETHANOL = 18,
+
+  HYBRID_DIESEL = 19,
+
+  HYBRID_ELECTRIC = 20,
+
+  HYBRID_RUNNING_ELECTRIC_AND_COMBUSTION = 21,
+
+  HYBRID_REGENERATIVE = 22,
+
+  BIFUEL_RUNNING_DIESEL = 23,
+};
+
+/*
+ * This enum provides the canonical mapping for sensor properties that have an integer value.
+ * The ordering of the values is taken from the OBD2 specification.
+ * Some of the properties are represented as an integer mapping to another enum. In those cases
+ * expect a comment by the property definition describing the enum to look at for the mapping.
+ * Any value greater than the last reserved index is available to vendors to map their extensions.
+ */
+enum Obd2IntegerSensorIndex : int32_t {
+  /* refer to FuelSystemStatus for a description of this value. */
+  FUEL_SYSTEM_STATUS = 0,
+
+  MALFUNCTION_INDICATOR_LIGHT_ON = 1,
+
+  /* refer to IgnitionMonitorKind for a description of this value. */
+  IGNITION_MONITORS_SUPPORTED = 2,
+
+  /*
+   * The value of this sensor is a bitmask that specifies whether ignition-specific
+   * tests are available and whether they are complete. The semantics of the individual
+   * bits in this value are given by, respectively, SparkIgnitionMonitors and
+   * CompressionIgnitionMonitors depending on the value of IGNITION_MONITORS_SUPPORTED.
+   */
+  IGNITION_SPECIFIC_MONITORS = 3,
+
+  INTAKE_AIR_TEMPERATURE = 4,
+
+  /* refer to SecondaryAirStatus for a description of this value. */
+  COMMANDED_SECONDARY_AIR_STATUS = 5,
+
+  NUM_OXYGEN_SENSORS_PRESENT = 6,
+
+  RUNTIME_SINCE_ENGINE_START = 7,
+
+  DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON = 8,
+
+  WARMUPS_SINCE_CODES_CLEARED = 9,
+
+  DISTANCE_TRAVELED_SINCE_CODES_CLEARED = 10,
+
+  ABSOLUTE_BAROMETRIC_PRESSURE = 11,
+
+  CONTROL_MODULE_VOLTAGE = 12,
+
+  AMBIENT_AIR_TEMPERATURE = 13,
+
+  TIME_WITH_MALFUNCTION_LIGHT_ON = 14,
+
+  TIME_SINCE_TROUBLE_CODES_CLEARED = 15,
+
+  MAX_FUEL_AIR_EQUIVALENCE_RATIO = 16,
+
+  MAX_OXYGEN_SENSOR_VOLTAGE = 17,
+
+  MAX_OXYGEN_SENSOR_CURRENT = 18,
+
+  MAX_INTAKE_MANIFOLD_ABSOLUTE_PRESSURE = 19,
+
+  MAX_AIR_FLOW_RATE_FROM_MASS_AIR_FLOW_SENSOR = 20,
+
+  /* refer to FuelType for a description of this value. */
+  FUEL_TYPE = 21,
+
+  FUEL_RAIL_ABSOLUTE_PRESSURE = 22,
+
+  ENGINE_OIL_TEMPERATURE = 23,
+
+  DRIVER_DEMAND_PERCENT_TORQUE = 24,
+
+  ENGINE_ACTUAL_PERCENT_TORQUE = 25,
+
+  ENGINE_REFERENCE_PERCENT_TORQUE = 26,
+
+  ENGINE_PERCENT_TORQUE_DATA_IDLE = 27,
+
+  ENGINE_PERCENT_TORQUE_DATA_POINT1 = 28,
+
+  ENGINE_PERCENT_TORQUE_DATA_POINT2 = 29,
+
+  ENGINE_PERCENT_TORQUE_DATA_POINT3 = 30,
+
+  ENGINE_PERCENT_TORQUE_DATA_POINT4 = 31,
+
+  LAST_SYSTEM_INDEX = ENGINE_PERCENT_TORQUE_DATA_POINT4,
+};
+
+/*
+ * This enum provides the canonical mapping for sensor properties that have a floating-point value.
+ * The ordering of the values is taken from the OBD2 specification.
+ * Any value greater than the last reserved index is available to vendors to map their extensions.
+ */
+enum Obd2FloatSensorIndex : int32_t {
+  CALCULATED_ENGINE_LOAD = 0,
+
+  ENGINE_COOLANT_TEMPERATURE = 1,
+
+  SHORT_TERM_FUEL_TRIM_BANK1 = 2,
+
+  LONG_TERM_FUEL_TRIM_BANK1 = 3,
+
+  SHORT_TERM_FUEL_TRIM_BANK2 = 4,
+
+  LONG_TERM_FUEL_TRIM_BANK2 = 5,
+
+  FUEL_PRESSURE = 6,
+
+  INTAKE_MANIFOLD_ABSOLUTE_PRESSURE = 7,
+
+  ENGINE_RPM = 8,
+
+  VEHICLE_SPEED = 9,
+
+  TIMING_ADVANCE = 10,
+
+  MAF_AIR_FLOW_RATE = 11,
+
+  THROTTLE_POSITION = 12,
+
+  OXYGEN_SENSOR1_VOLTAGE = 13,
+
+  OXYGEN_SENSOR1_SHORT_TERM_FUEL_TRIM = 14,
+
+  OXYGEN_SENSOR1_FUEL_AIR_EQUIVALENCE_RATIO = 15,
+
+  OXYGEN_SENSOR2_VOLTAGE = 16,
+
+  OXYGEN_SENSOR2_SHORT_TERM_FUEL_TRIM = 17,
+
+  OXYGEN_SENSOR2_FUEL_AIR_EQUIVALENCE_RATIO = 18,
+
+  OXYGEN_SENSOR3_VOLTAGE = 19,
+
+  OXYGEN_SENSOR3_SHORT_TERM_FUEL_TRIM = 20,
+
+  OXYGEN_SENSOR3_FUEL_AIR_EQUIVALENCE_RATIO = 21,
+
+  OXYGEN_SENSOR4_VOLTAGE = 22,
+
+  OXYGEN_SENSOR4_SHORT_TERM_FUEL_TRIM = 23,
+
+  OXYGEN_SENSOR4_FUEL_AIR_EQUIVALENCE_RATIO = 24,
+
+  OXYGEN_SENSOR5_VOLTAGE = 25,
+
+  OXYGEN_SENSOR5_SHORT_TERM_FUEL_TRIM = 26,
+
+  OXYGEN_SENSOR5_FUEL_AIR_EQUIVALENCE_RATIO = 27,
+
+  OXYGEN_SENSOR6_VOLTAGE = 28,
+
+  OXYGEN_SENSOR6_SHORT_TERM_FUEL_TRIM = 29,
+
+  OXYGEN_SENSOR6_FUEL_AIR_EQUIVALENCE_RATIO = 30,
+
+  OXYGEN_SENSOR7_VOLTAGE = 31,
+
+  OXYGEN_SENSOR7_SHORT_TERM_FUEL_TRIM = 32,
+
+  OXYGEN_SENSOR7_FUEL_AIR_EQUIVALENCE_RATIO = 33,
+
+  OXYGEN_SENSOR8_VOLTAGE = 34,
+
+  OXYGEN_SENSOR8_SHORT_TERM_FUEL_TRIM = 35,
+
+  OXYGEN_SENSOR8_FUEL_AIR_EQUIVALENCE_RATIO = 36,
+
+  FUEL_RAIL_PRESSURE = 37,
+
+  FUEL_RAIL_GAUGE_PRESSURE = 38,
+
+  COMMANDED_EXHAUST_GAS_RECIRCULATION = 39,
+
+  EXHAUST_GAS_RECIRCULATION_ERROR = 40,
+
+  COMMANDED_EVAPORATIVE_PURGE = 41,
+
+  FUEL_TANK_LEVEL_INPUT = 42,
+
+  EVAPORATION_SYSTEM_VAPOR_PRESSURE = 43,
+
+  CATALYST_TEMPERATURE_BANK1_SENSOR1 = 44,
+
+  CATALYST_TEMPERATURE_BANK2_SENSOR1 = 45,
+
+  CATALYST_TEMPERATURE_BANK1_SENSOR2 = 46,
+
+  CATALYST_TEMPERATURE_BANK2_SENSOR2 = 47,
+
+  ABSOLUTE_LOAD_VALUE = 48,
+
+  FUEL_AIR_COMMANDED_EQUIVALENCE_RATIO = 49,
+
+  RELATIVE_THROTTLE_POSITION = 50,
+
+  ABSOLUTE_THROTTLE_POSITION_B = 51,
+
+  ABSOLUTE_THROTTLE_POSITION_C = 52,
+
+  ACCELERATOR_PEDAL_POSITION_D = 53,
+
+  ACCELERATOR_PEDAL_POSITION_E = 54,
+
+  ACCELERATOR_PEDAL_POSITION_F = 55,
+
+  COMMANDED_THROTTLE_ACTUATOR = 56,
+
+  ETHANOL_FUEL_PERCENTAGE = 57,
+
+  ABSOLUTE_EVAPORATION_SYSTEM_VAPOR_PRESSURE = 58,
+
+  SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1 = 59,
+
+  SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2 = 60,
+
+  SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3 = 61,
+
+  SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4 = 62,
+
+  LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1 = 63,
+
+  LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2 = 64,
+
+  LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3 = 65,
+
+  LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4 = 66,
+
+  RELATIVE_ACCELERATOR_PEDAL_POSITION = 67,
+
+  HYBRID_BATTERY_PACK_REMAINING_LIFE = 68,
+
+  FUEL_INJECTION_TIMING = 69,
+
+  ENGINE_FUEL_RATE = 70,
+
+  LAST_SYSTEM_INDEX = ENGINE_FUEL_RATE,
 };