Teach Vehicle HAL a way to indicate which subset of OBD2 sensors are valid for a given frame.

We are now using the "bytes" element of VehiclePropValue::RawValue as a storage place for a bitmask that indicates
which sensor indices, among those defined, actually map to valid values in the int32Values and floatValues respectively.

Test: make vts BUILD_GOOGLE_VTS=true -j32 && vts-tradefed run commandAndExit vts --skip-all-system-status-check --primary-abi-only --skip-preconditions --module VehicleHidlTest -l INFO
Test: adb root && adb push out/target/product/bat/data/nativetest/android.hardware.vehicle@2.0-manager-unit-tests/android.hardware.vehicle@2.0-manager-unit-tests /data/nativetest/android.hardware.vehicle@2.0-manager-unit-tests/android.hardware.vehicle@2.0-manager-unit-tests && adb shell /data/nativetest/android.hardware.vehicle@2.0-manager-unit-tests/android.hardware.vehicle@2.0-manager-unit-tests | grep Obd2
Change-Id: I4e9a116555001d2577d50d50009f75d8f78603b0
diff --git a/vehicle/2.0/default/Android.mk b/vehicle/2.0/default/Android.mk
index 4a27eeb..9c75006 100644
--- a/vehicle/2.0/default/Android.mk
+++ b/vehicle/2.0/default/Android.mk
@@ -23,6 +23,7 @@
 LOCAL_MODULE := $(module_prefix)-manager-lib
 LOCAL_SRC_FILES := \
     vehicle_hal_manager/AccessControlConfigParser.cpp \
+    vehicle_hal_manager/Obd2SensorStore.cpp \
     vehicle_hal_manager/SubscriptionManager.cpp \
     vehicle_hal_manager/VehicleHalManager.cpp \
     vehicle_hal_manager/VehicleObjectPool.cpp \
@@ -71,6 +72,7 @@
 
 LOCAL_SRC_FILES:= \
     tests/AccessControlConfigParser_test.cpp \
+    tests/Obd2SensorStore_test.cpp \
     tests/SubscriptionManager_test.cpp \
     tests/VehicleHalManager_test.cpp \
     tests/VehicleObjectPool_test.cpp \
diff --git a/vehicle/2.0/default/impl/DefaultConfig.h b/vehicle/2.0/default/impl/DefaultConfig.h
index 12c1c1b..f4e1e53 100644
--- a/vehicle/2.0/default/impl/DefaultConfig.h
+++ b/vehicle/2.0/default/impl/DefaultConfig.h
@@ -165,12 +165,14 @@
         .prop = VehicleProperty::OBD2_LIVE_FRAME,
         .access = VehiclePropertyAccess::READ,
         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        .configArray = {0,0}
     },
 
     {
         .prop = VehicleProperty::OBD2_FREEZE_FRAME,
         .access = VehiclePropertyAccess::READ,
         .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        .configArray = {0,0}
     }
 };
 
diff --git a/vehicle/2.0/default/impl/DefaultVehicleHal.cpp b/vehicle/2.0/default/impl/DefaultVehicleHal.cpp
index 4541168..73789e1 100644
--- a/vehicle/2.0/default/impl/DefaultVehicleHal.cpp
+++ b/vehicle/2.0/default/impl/DefaultVehicleHal.cpp
@@ -16,6 +16,8 @@
 
 #include "DefaultVehicleHal.h"
 
+#include <algorithm>
+
 #define LOG_TAG "default_vehicle"
 #include <android/log.h>
 
@@ -153,6 +155,96 @@
     return status;
 }
 
+void DefaultVehicleHal::onCreate() {
+    const auto& propConfigs(listProperties());
+    auto obd2LiveFramePropConfig = std::find_if(
+        propConfigs.begin(),
+        propConfigs.end(),
+        [] (VehiclePropConfig config) -> bool {
+            return (config.prop == VehicleProperty::OBD2_LIVE_FRAME);
+        });
+    mObd2SensorStore.reset(new Obd2SensorStore(
+        obd2LiveFramePropConfig->configArray[0],
+        obd2LiveFramePropConfig->configArray[1]));
+    // precalculate OBD2 sensor values
+    mObd2SensorStore->setIntegerSensor(
+        Obd2IntegerSensorIndex::FUEL_SYSTEM_STATUS,
+        toInt(FuelSystemStatus::CLOSED_LOOP));
+    mObd2SensorStore->setIntegerSensor(
+        Obd2IntegerSensorIndex::MALFUNCTION_INDICATOR_LIGHT_ON, 0);
+    mObd2SensorStore->setIntegerSensor(
+        Obd2IntegerSensorIndex::IGNITION_MONITORS_SUPPORTED,
+        toInt(IgnitionMonitorKind::SPARK));
+    mObd2SensorStore->setIntegerSensor(Obd2IntegerSensorIndex::IGNITION_SPECIFIC_MONITORS,
+        CommonIgnitionMonitors::COMPONENTS_AVAILABLE |
+        CommonIgnitionMonitors::MISFIRE_AVAILABLE |
+        SparkIgnitionMonitors::AC_REFRIGERANT_AVAILABLE |
+        SparkIgnitionMonitors::EVAPORATIVE_SYSTEM_AVAILABLE);
+    mObd2SensorStore->setIntegerSensor(
+        Obd2IntegerSensorIndex::INTAKE_AIR_TEMPERATURE, 35);
+    mObd2SensorStore->setIntegerSensor(
+        Obd2IntegerSensorIndex::COMMANDED_SECONDARY_AIR_STATUS,
+        toInt(SecondaryAirStatus::FROM_OUTSIDE_OR_OFF));
+    mObd2SensorStore->setIntegerSensor(
+        Obd2IntegerSensorIndex::NUM_OXYGEN_SENSORS_PRESENT, 1);
+    mObd2SensorStore->setIntegerSensor(
+        Obd2IntegerSensorIndex::RUNTIME_SINCE_ENGINE_START, 500);
+    mObd2SensorStore->setIntegerSensor(
+        Obd2IntegerSensorIndex::DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON, 0);
+    mObd2SensorStore->setIntegerSensor(
+        Obd2IntegerSensorIndex::WARMUPS_SINCE_CODES_CLEARED, 51);
+    mObd2SensorStore->setIntegerSensor(
+        Obd2IntegerSensorIndex::DISTANCE_TRAVELED_SINCE_CODES_CLEARED, 365);
+    mObd2SensorStore->setIntegerSensor(
+        Obd2IntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE, 30);
+    mObd2SensorStore->setIntegerSensor(
+        Obd2IntegerSensorIndex::CONTROL_MODULE_VOLTAGE, 12);
+    mObd2SensorStore->setIntegerSensor(
+        Obd2IntegerSensorIndex::AMBIENT_AIR_TEMPERATURE, 18);
+    mObd2SensorStore->setIntegerSensor(
+        Obd2IntegerSensorIndex::MAX_FUEL_AIR_EQUIVALENCE_RATIO, 1);
+    mObd2SensorStore->setIntegerSensor(
+        Obd2IntegerSensorIndex::FUEL_TYPE, toInt(FuelType::GASOLINE));
+    mObd2SensorStore->setFloatSensor(
+        Obd2FloatSensorIndex::CALCULATED_ENGINE_LOAD, 0.153);
+    mObd2SensorStore->setFloatSensor(
+        Obd2FloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK1, -0.16);
+    mObd2SensorStore->setFloatSensor(
+        Obd2FloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK1, -0.16);
+    mObd2SensorStore->setFloatSensor(
+        Obd2FloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK2, -0.16);
+    mObd2SensorStore->setFloatSensor(
+        Obd2FloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK2, -0.16);
+    mObd2SensorStore->setFloatSensor(
+        Obd2FloatSensorIndex::INTAKE_MANIFOLD_ABSOLUTE_PRESSURE, 7.5);
+    mObd2SensorStore->setFloatSensor(
+        Obd2FloatSensorIndex::ENGINE_RPM, 1250.);
+    mObd2SensorStore->setFloatSensor(
+        Obd2FloatSensorIndex::VEHICLE_SPEED, 40.);
+    mObd2SensorStore->setFloatSensor(
+        Obd2FloatSensorIndex::TIMING_ADVANCE, 2.5);
+    mObd2SensorStore->setFloatSensor(
+        Obd2FloatSensorIndex::THROTTLE_POSITION, 19.75);
+    mObd2SensorStore->setFloatSensor(
+        Obd2FloatSensorIndex::OXYGEN_SENSOR1_VOLTAGE, 0.265);
+    mObd2SensorStore->setFloatSensor(
+        Obd2FloatSensorIndex::FUEL_TANK_LEVEL_INPUT, 0.824);
+    mObd2SensorStore->setFloatSensor(
+        Obd2FloatSensorIndex::EVAPORATION_SYSTEM_VAPOR_PRESSURE, -0.373);
+    mObd2SensorStore->setFloatSensor(
+        Obd2FloatSensorIndex::CATALYST_TEMPERATURE_BANK1_SENSOR1, 190.);
+    mObd2SensorStore->setFloatSensor(
+        Obd2FloatSensorIndex::RELATIVE_THROTTLE_POSITION, 3.);
+    mObd2SensorStore->setFloatSensor(
+        Obd2FloatSensorIndex::ABSOLUTE_THROTTLE_POSITION_B, 0.306);
+    mObd2SensorStore->setFloatSensor(
+        Obd2FloatSensorIndex::ACCELERATOR_PEDAL_POSITION_D, 0.188);
+    mObd2SensorStore->setFloatSensor(
+        Obd2FloatSensorIndex::ACCELERATOR_PEDAL_POSITION_E, 0.094);
+    mObd2SensorStore->setFloatSensor(
+        Obd2FloatSensorIndex::COMMANDED_THROTTLE_ACTUATOR, 0.024);
+}
+
 StatusCode DefaultVehicleHal::getHvacTemperature(int32_t areaId,
                                                  float* outValue)  {
     if (areaId == toInt(VehicleAreaZone::ROW_1_LEFT)) {
@@ -205,73 +297,17 @@
     return StatusCode::OK;
 }
 
-static std::vector<int32_t> fillObd2IntValues() {
-    std::vector<int32_t> intValues(toInt(Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX));
-#define SENSOR(name) toInt(Obd2IntegerSensorIndex:: name)
-    intValues[SENSOR(FUEL_SYSTEM_STATUS)] = toInt(FuelSystemStatus::CLOSED_LOOP);
-    intValues[SENSOR(MALFUNCTION_INDICATOR_LIGHT_ON)] = 0;
-    intValues[SENSOR(IGNITION_MONITORS_SUPPORTED)] = toInt(IgnitionMonitorKind::SPARK);
-    intValues[SENSOR(IGNITION_SPECIFIC_MONITORS)] =
-        CommonIgnitionMonitors::COMPONENTS_AVAILABLE |
-        CommonIgnitionMonitors::MISFIRE_AVAILABLE |
-        SparkIgnitionMonitors::AC_REFRIGERANT_AVAILABLE |
-        SparkIgnitionMonitors::EVAPORATIVE_SYSTEM_AVAILABLE;
-    intValues[SENSOR(INTAKE_AIR_TEMPERATURE)] = 35;
-    intValues[SENSOR(COMMANDED_SECONDARY_AIR_STATUS)] =
-        toInt(SecondaryAirStatus::FROM_OUTSIDE_OR_OFF);
-    intValues[SENSOR(NUM_OXYGEN_SENSORS_PRESENT)] = 1;
-    intValues[SENSOR(RUNTIME_SINCE_ENGINE_START)] = 500;
-    intValues[SENSOR(DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON)] = 0;
-    intValues[SENSOR(WARMUPS_SINCE_CODES_CLEARED)] = 51;
-    intValues[SENSOR(DISTANCE_TRAVELED_SINCE_CODES_CLEARED)] = 365;
-    intValues[SENSOR(ABSOLUTE_BAROMETRIC_PRESSURE)] = 30;
-    intValues[SENSOR(CONTROL_MODULE_VOLTAGE)] = 12;
-    intValues[SENSOR(AMBIENT_AIR_TEMPERATURE)] = 18;
-    intValues[SENSOR(MAX_FUEL_AIR_EQUIVALENCE_RATIO)] = 1;
-    intValues[SENSOR(FUEL_TYPE)] = toInt(FuelType::GASOLINE);
-#undef SENSOR
-    return intValues;
-}
-
-static std::vector<float> fillObd2FloatValues() {
-    std::vector<float> floatValues(toInt(Obd2FloatSensorIndex::LAST_SYSTEM_INDEX));
-#define SENSOR(name) toInt(Obd2FloatSensorIndex:: name)
-    floatValues[SENSOR(CALCULATED_ENGINE_LOAD)] = 0.153;
-    floatValues[SENSOR(SHORT_TERM_FUEL_TRIM_BANK1)] = -0.16;
-    floatValues[SENSOR(LONG_TERM_FUEL_TRIM_BANK1)] = -0.16;
-    floatValues[SENSOR(SHORT_TERM_FUEL_TRIM_BANK2)] = -0.16;
-    floatValues[SENSOR(LONG_TERM_FUEL_TRIM_BANK2)] = -0.16;
-    floatValues[SENSOR(INTAKE_MANIFOLD_ABSOLUTE_PRESSURE)] = 7.5;
-    floatValues[SENSOR(ENGINE_RPM)] = 1250.;
-    floatValues[SENSOR(VEHICLE_SPEED)] = 40.;
-    floatValues[SENSOR(TIMING_ADVANCE)] = 2.5;
-    floatValues[SENSOR(THROTTLE_POSITION)] = 19.75;
-    floatValues[SENSOR(OXYGEN_SENSOR1_VOLTAGE)] = 0.265;
-    floatValues[SENSOR(FUEL_TANK_LEVEL_INPUT)] = 0.824;
-    floatValues[SENSOR(EVAPORATION_SYSTEM_VAPOR_PRESSURE)] = -0.373;
-    floatValues[SENSOR(CATALYST_TEMPERATURE_BANK1_SENSOR1)] = 190.;
-    floatValues[SENSOR(RELATIVE_THROTTLE_POSITION)] = 3.;
-    floatValues[SENSOR(ABSOLUTE_THROTTLE_POSITION_B)] = 0.306;
-    floatValues[SENSOR(ACCELERATOR_PEDAL_POSITION_D)] = 0.188;
-    floatValues[SENSOR(ACCELERATOR_PEDAL_POSITION_E)] = 0.094;
-    floatValues[SENSOR(COMMANDED_THROTTLE_ACTUATOR)] = 0.024;
-#undef SENSOR
-    return floatValues;
-}
-
 StatusCode DefaultVehicleHal::fillObd2LiveFrame(VehiclePropValuePtr* v) {
-    static std::vector<int32_t> intValues(fillObd2IntValues());
-    static std::vector<float> floatValues(fillObd2FloatValues());
-    (*v)->value.int32Values = intValues;
-    (*v)->value.floatValues = floatValues;
+    (*v)->value.int32Values = mObd2SensorStore->getIntegerSensors();
+    (*v)->value.floatValues = mObd2SensorStore->getFloatSensors();
+    (*v)->value.bytes = mObd2SensorStore->getSensorsBitmask();
     return StatusCode::OK;
 }
 
 StatusCode DefaultVehicleHal::fillObd2FreezeFrame(VehiclePropValuePtr* v) {
-    static std::vector<int32_t> intValues(fillObd2IntValues());
-    static std::vector<float> floatValues(fillObd2FloatValues());
-    (*v)->value.int32Values = intValues;
-    (*v)->value.floatValues = floatValues;
+    (*v)->value.int32Values = mObd2SensorStore->getIntegerSensors();
+    (*v)->value.floatValues = mObd2SensorStore->getFloatSensors();
+    (*v)->value.bytes = mObd2SensorStore->getSensorsBitmask();
     (*v)->value.stringValue = "P0010";
     return StatusCode::OK;
 }
diff --git a/vehicle/2.0/default/impl/DefaultVehicleHal.h b/vehicle/2.0/default/impl/DefaultVehicleHal.h
index 15a4789..165324e 100644
--- a/vehicle/2.0/default/impl/DefaultVehicleHal.h
+++ b/vehicle/2.0/default/impl/DefaultVehicleHal.h
@@ -17,8 +17,11 @@
 #ifndef android_hardware_vehicle_V2_0_impl_DefaultVehicleHal_H_
 #define android_hardware_vehicle_V2_0_impl_DefaultVehicleHal_H_
 
+#include <memory>
+
 #include <VehicleHal.h>
 #include <impl/DefaultConfig.h>
+#include <vehicle_hal_manager/Obd2SensorStore.h>
 #include <utils/SystemClock.h>
 
 namespace android {
@@ -38,6 +41,8 @@
     VehiclePropValuePtr get(const VehiclePropValue& requestedPropValue,
                             StatusCode* outStatus) override;
 
+    void onCreate() override;
+
     StatusCode set(const VehiclePropValue& propValue) override;
 
     StatusCode subscribe(VehicleProperty property,
@@ -57,8 +62,8 @@
     StatusCode setHvacTemperature(int32_t areaId, float value);
     StatusCode getHvacDefroster(int32_t areaId, bool* outValue);
     StatusCode setHvacDefroster(int32_t areaId, bool value);
-    StatusCode fillObd2LiveFrame (VehiclePropValuePtr* v);
-    StatusCode fillObd2FreezeFrame (VehiclePropValuePtr* v);
+    StatusCode fillObd2LiveFrame(VehiclePropValuePtr* v);
+    StatusCode fillObd2FreezeFrame(VehiclePropValuePtr* v);
 private:
     int32_t mFanSpeed = 3;
     int32_t mBrightness = 7;
@@ -71,6 +76,7 @@
     bool mHvacAcOn = true;
     bool mHvacAutoOn = true;
     VehicleHvacFanDirection mFanDirection = VehicleHvacFanDirection::FACE;
+    std::unique_ptr<Obd2SensorStore> mObd2SensorStore{nullptr};
 };
 
 }  // impl
diff --git a/vehicle/2.0/default/tests/Obd2SensorStore_test.cpp b/vehicle/2.0/default/tests/Obd2SensorStore_test.cpp
new file mode 100644
index 0000000..6866454
--- /dev/null
+++ b/vehicle/2.0/default/tests/Obd2SensorStore_test.cpp
@@ -0,0 +1,283 @@
+/*
+ * 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 "vehicle_hal_manager/Obd2SensorStore.h"
+#include "vehicle_hal_manager/VehicleUtils.h"
+
+namespace android {
+namespace hardware {
+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 hardware
+}  // namespace android
diff --git a/vehicle/2.0/default/vehicle_hal_manager/Obd2SensorStore.cpp b/vehicle/2.0/default/vehicle_hal_manager/Obd2SensorStore.cpp
new file mode 100644
index 0000000..7be2662
--- /dev/null
+++ b/vehicle/2.0/default/vehicle_hal_manager/Obd2SensorStore.cpp
@@ -0,0 +1,104 @@
+/*
+ * 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 <vehicle_hal_manager/VehicleUtils.h>
+
+namespace android {
+namespace hardware {
+namespace vehicle {
+namespace V2_0 {
+
+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 = toInt(Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX)+1;
+        const size_t numSystemFloatSensors = 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());
+}
+
+StatusCode Obd2SensorStore::setIntegerSensor(Obd2IntegerSensorIndex index,
+    int32_t value) {
+    return setIntegerSensor(toInt(index), value);
+}
+StatusCode Obd2SensorStore::setFloatSensor(Obd2FloatSensorIndex index,
+    float value) {
+    return setFloatSensor(toInt(index), value);
+}
+
+StatusCode Obd2SensorStore::setIntegerSensor(size_t index, int32_t value) {
+    mIntegerSensors[index] = value;
+    mSensorsBitmask.set(index, true);
+    return StatusCode::OK;
+}
+
+StatusCode Obd2SensorStore::setFloatSensor(size_t index, float value) {
+    mFloatSensors[index] = value;
+    mSensorsBitmask.set(index + mIntegerSensors.size(), true);
+    return 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();
+}
+
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace hardware
+}  // namespace android
diff --git a/vehicle/2.0/default/vehicle_hal_manager/Obd2SensorStore.h b/vehicle/2.0/default/vehicle_hal_manager/Obd2SensorStore.h
new file mode 100644
index 0000000..b18f5d4
--- /dev/null
+++ b/vehicle/2.0/default/vehicle_hal_manager/Obd2SensorStore.h
@@ -0,0 +1,80 @@
+/*
+ * 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_vehicle_V2_0_Obd2SensorStore_H_
+#define android_hardware_vehicle_V2_0_Obd2SensorStore_H_
+
+#include <vector>
+
+#include <VehicleHal.h>
+
+namespace android {
+namespace hardware {
+namespace vehicle {
+namespace V2_0 {
+
+// 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.
+    StatusCode setIntegerSensor(Obd2IntegerSensorIndex index, int32_t value);
+    // Stores an integer-valued sensor.
+    StatusCode setIntegerSensor(size_t index, int32_t value);
+
+    // Stores a float-valued sensor.
+    StatusCode setFloatSensor(Obd2FloatSensorIndex index, float value);
+    // Stores a float-valued sensor.
+    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;
+
+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_0
+}  // namespace vehicle
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_vehicle_V2_0_Obd2SensorStore_H_