Migrate fake value generator.
Test: atest FakeVehicleHalValueGeneratorsTest
Bug: 201830716
Change-Id: Ic113c9b189a07140a288d6d03d3a8a2b9061881f
diff --git a/automotive/vehicle/TEST_MAPPING b/automotive/vehicle/TEST_MAPPING
index c5702aa..9924581 100644
--- a/automotive/vehicle/TEST_MAPPING
+++ b/automotive/vehicle/TEST_MAPPING
@@ -11,6 +11,9 @@
},
{
"name": "FakeVehicleHardwareTest"
+ },
+ {
+ "name": "FakeVehicleHalValueGeneratorsTest"
}
]
}
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/JsonFakeValueGenerator.h b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/JsonFakeValueGenerator.h
new file mode 100644
index 0000000..8116ed2
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/JsonFakeValueGenerator.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2021 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_aidl_impl_fake_impl_GeneratorHub_include_JsonFakeValueGenerator_H_
+#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_JsonFakeValueGenerator_H_
+
+#include "FakeValueGenerator.h"
+
+#include <json/json.h>
+
+#include <iostream>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+class JsonFakeValueGenerator : public FakeValueGenerator {
+ public:
+ // Create a new JSON fake value generator. {@code request.value.stringValue} is the JSON file
+ // name. {@code request.value.int32Values[1]} if exists, is the number of iterations. If
+ // {@code int32Values} has less than 2 elements, number of iterations would be set to -1, which
+ // means iterate indefinitely.
+ explicit JsonFakeValueGenerator(
+ const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& request);
+ // Create a new JSON fake value generator using the specified JSON file path. All the events
+ // in the JSON file would be generated for number of {@code iteration}. If iteration is 0, no
+ // value would be generated. If iteration is less than 0, it would iterate indefinitely.
+ explicit JsonFakeValueGenerator(const std::string& path, int32_t iteration);
+ // Create a new JSON fake value generator using the specified JSON file path. All the events
+ // in the JSON file would be generated once.
+ explicit JsonFakeValueGenerator(const std::string& path);
+
+ ~JsonFakeValueGenerator() = default;
+
+ std::optional<::aidl::android::hardware::automotive::vehicle::VehiclePropValue> nextEvent()
+ override;
+ const std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>&
+ getAllEvents();
+
+ private:
+ size_t mEventIndex = 0;
+ std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropValue> mEvents;
+ long mLastEventTimestamp = 0;
+ int32_t mNumOfIterations = 0;
+
+ void setBit(std::vector<uint8_t>& bytes, size_t idx);
+ void init(const std::string& path, int32_t iteration);
+};
+
+} // namespace fake
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_JsonFakeValueGenerator_H_
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h
new file mode 100644
index 0000000..bd004f3
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/LinearFakeValueGenerator.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2021 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_aidl_impl_fake_impl_GeneratorHub_include_LinearFakeValueGenerator_H_
+#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_LinearFakeValueGenerator_H_
+
+#include "FakeValueGenerator.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+class LinearFakeValueGenerator : public FakeValueGenerator {
+ public:
+ // A linear value generator initialized using values in request.
+ // int32Values[1]: propId
+ // floatValues[0]: middleValue and currentValue
+ // floatValues[1]: dispersion
+ // floatValues[2]: increment
+ // int64Values[0]: interval
+ // {@code propId} must be INT32 or INT64 or FLOAT type.
+ explicit LinearFakeValueGenerator(
+ const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& request);
+ // A linear value generator in range [middleValue - dispersion, middleValue + dispersion),
+ // starts at 'currentValue' and at each 'interval', increase by 'increment' and loop back if
+ // exceeds middleValue + dispersion. {@code propId} must be INT32 or INT64 or FLOAT type.
+ explicit LinearFakeValueGenerator(int32_t propId, float middleValue, float initValue,
+ float dispersion, float increment, int64_t interval);
+ ~LinearFakeValueGenerator() = default;
+
+ std::optional<::aidl::android::hardware::automotive::vehicle::VehiclePropValue> nextEvent()
+ override;
+
+ private:
+ // In every timer tick we may want to generate new value based on initial value for debug
+ // purpose. It's better to have sequential values to see if events gets delivered in order
+ // to the client.
+ struct GeneratorCfg {
+ int32_t propId;
+ float middleValue;
+ float currentValue; // Should be in range (middleValue +/- dispersion).
+ float dispersion; // Defines minimum and maximum value based on initial value.
+ float increment; // Value that we will be added to currentValue with each timer tick.
+ int64_t interval;
+ long lastEventTimestamp;
+ };
+
+ GeneratorCfg mGenCfg;
+
+ void initGenCfg(int32_t propId, float middleValue, float initValue, float dispersion,
+ float increment, int64_t interval);
+};
+
+} // namespace fake
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_automotive_vehicle_aidl_impl_fake_impl_GeneratorHub_include_LinearFakeValueGenerator_H_
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/JsonFakeValueGenerator.cpp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/JsonFakeValueGenerator.cpp
new file mode 100644
index 0000000..521ce45
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/JsonFakeValueGenerator.cpp
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2021 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 "JsonFakeValueGenerator"
+
+#include "JsonFakeValueGenerator.h"
+
+#include <fstream>
+#include <type_traits>
+#include <typeinfo>
+
+#include <VehicleUtils.h>
+#include <android/binder_enums.h>
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+namespace {
+
+using ::aidl::android::hardware::automotive::vehicle::DiagnosticFloatSensorIndex;
+using ::aidl::android::hardware::automotive::vehicle::DiagnosticIntegerSensorIndex;
+using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+
+template <class T>
+int getLastIndex() {
+ auto range = ::ndk::enum_range<T>();
+ auto it = range.begin();
+ while (std::next(it) != range.end()) {
+ it++;
+ }
+ return toInt(*it);
+}
+
+bool isDiagnosticProperty(int32_t prop) {
+ return prop == toInt(VehicleProperty::OBD2_LIVE_FRAME) ||
+ prop == toInt(VehicleProperty::OBD2_FREEZE_FRAME);
+}
+
+void setBit(std::vector<uint8_t>& bytes, size_t idx) {
+ uint8_t mask = 1 << (idx % 8);
+ bytes[idx / 8] |= mask;
+}
+
+template <typename T>
+void copyJsonArray(const Json::Value& jsonArray, std::vector<T>& dest) {
+ dest.resize(jsonArray.size());
+ for (Json::Value::ArrayIndex i = 0; i < jsonArray.size(); i++) {
+ if (std::is_same<T, int32_t>::value) {
+ dest[i] = jsonArray[i].asInt();
+ } else if (std::is_same<T, int64_t>::value) {
+ dest[i] = jsonArray[i].asInt64();
+ } else if (std::is_same<T, float>::value) {
+ dest[i] = jsonArray[i].asFloat();
+ }
+ }
+}
+
+void copyMixedValueJson(const Json::Value& jsonValue, RawPropValues& dest) {
+ copyJsonArray(jsonValue["int32Values"], dest.int32Values);
+ copyJsonArray(jsonValue["int64Values"], dest.int64Values);
+ copyJsonArray(jsonValue["floatValues"], dest.floatValues);
+ dest.stringValue = jsonValue["stringValue"].asString();
+}
+
+std::vector<uint8_t> generateDiagnosticBytes(const RawPropValues& diagnosticValue) {
+ size_t lastIntegerSensorIndex =
+ static_cast<size_t>(getLastIndex<DiagnosticIntegerSensorIndex>());
+ size_t lastFloatSensorIndex = static_cast<size_t>(getLastIndex<DiagnosticFloatSensorIndex>());
+
+ size_t byteSize = (lastIntegerSensorIndex + lastFloatSensorIndex + 2);
+ std::vector<uint8_t> bytes((byteSize + 7) / 8);
+
+ auto& int32Values = diagnosticValue.int32Values;
+ for (size_t i = 0; i < int32Values.size(); i++) {
+ if (int32Values[i] != 0) {
+ setBit(bytes, i);
+ }
+ }
+
+ auto& floatValues = diagnosticValue.floatValues;
+ for (size_t i = 0; i < floatValues.size(); i++) {
+ if (floatValues[i] != 0.0) {
+ setBit(bytes, i + lastIntegerSensorIndex + 1);
+ }
+ }
+ return bytes;
+}
+
+std::vector<VehiclePropValue> parseFakeValueJson(std::istream& is) {
+ std::vector<VehiclePropValue> fakeVhalEvents;
+
+ Json::CharReaderBuilder builder;
+ Json::Value rawEvents;
+ std::string errorMessage;
+ if (!Json::parseFromStream(builder, is, &rawEvents, &errorMessage)) {
+ ALOGE("%s: Failed to parse fake data JSON file. Error: %s", __func__, errorMessage.c_str());
+ return fakeVhalEvents;
+ }
+
+ for (Json::Value::ArrayIndex i = 0; i < rawEvents.size(); i++) {
+ Json::Value rawEvent = rawEvents[i];
+ if (!rawEvent.isObject()) {
+ ALOGE("%s: VHAL JSON event should be an object, %s", __func__,
+ rawEvent.toStyledString().c_str());
+ continue;
+ }
+ if (rawEvent["prop"].empty() || rawEvent["areaId"].empty() || rawEvent["value"].empty() ||
+ rawEvent["timestamp"].empty()) {
+ ALOGE("%s: VHAL JSON event has missing fields, skip it, %s", __func__,
+ rawEvent.toStyledString().c_str());
+ continue;
+ }
+ VehiclePropValue event = {
+ .timestamp = rawEvent["timestamp"].asInt64(),
+ .areaId = rawEvent["areaId"].asInt(),
+ .prop = rawEvent["prop"].asInt(),
+ };
+
+ Json::Value rawEventValue = rawEvent["value"];
+ auto& value = event.value;
+ int32_t count;
+ switch (getPropType(event.prop)) {
+ case VehiclePropertyType::BOOLEAN:
+ case VehiclePropertyType::INT32:
+ value.int32Values.resize(1);
+ value.int32Values[0] = rawEventValue.asInt();
+ break;
+ case VehiclePropertyType::INT64:
+ value.int64Values.resize(1);
+ value.int64Values[0] = rawEventValue.asInt64();
+ break;
+ case VehiclePropertyType::FLOAT:
+ value.floatValues.resize(1);
+ value.floatValues[0] = rawEventValue.asFloat();
+ break;
+ case VehiclePropertyType::STRING:
+ value.stringValue = rawEventValue.asString();
+ break;
+ case VehiclePropertyType::INT32_VEC:
+ value.int32Values.resize(rawEventValue.size());
+ count = 0;
+ for (auto& it : rawEventValue) {
+ value.int32Values[count++] = it.asInt();
+ }
+ break;
+ case VehiclePropertyType::MIXED:
+ copyMixedValueJson(rawEventValue, value);
+ if (isDiagnosticProperty(event.prop)) {
+ value.byteValues = generateDiagnosticBytes(value);
+ }
+ break;
+ default:
+ ALOGE("%s: unsupported type for property: 0x%x", __func__, event.prop);
+ continue;
+ }
+ fakeVhalEvents.push_back(event);
+ }
+ return fakeVhalEvents;
+}
+
+} // namespace
+
+JsonFakeValueGenerator::JsonFakeValueGenerator(const std::string& path) {
+ init(path, 1);
+}
+
+JsonFakeValueGenerator::JsonFakeValueGenerator(const std::string& path, int32_t iteration) {
+ init(path, iteration);
+}
+
+JsonFakeValueGenerator::JsonFakeValueGenerator(const VehiclePropValue& request) {
+ const auto& v = request.value;
+ // Iterate infinitely if iteration number is not provided
+ int32_t numOfIterations = v.int32Values.size() < 2 ? -1 : v.int32Values[1];
+
+ init(v.stringValue, numOfIterations);
+}
+
+void JsonFakeValueGenerator::init(const std::string& path, int32_t iteration) {
+ std::ifstream ifs(path);
+ if (!ifs) {
+ ALOGE("%s: couldn't open %s for parsing.", __func__, path.c_str());
+ return;
+ }
+ mEvents = parseFakeValueJson(ifs);
+ mNumOfIterations = iteration;
+}
+
+const std::vector<VehiclePropValue>& JsonFakeValueGenerator::getAllEvents() {
+ return mEvents;
+}
+
+std::optional<VehiclePropValue> JsonFakeValueGenerator::nextEvent() {
+ if (mNumOfIterations == 0 || mEvents.size() == 0) {
+ return std::nullopt;
+ }
+
+ VehiclePropValue generatedValue = mEvents[mEventIndex];
+
+ if (mLastEventTimestamp == 0) {
+ mLastEventTimestamp = elapsedRealtimeNano();
+ } else {
+ long nextEventTime = 0;
+ if (mEventIndex > 0) {
+ // All events (start from 2nd one) are supposed to happen in the future with a delay
+ // equals to the duration between previous and current event.
+ nextEventTime = mLastEventTimestamp +
+ (mEvents[mEventIndex].timestamp - mEvents[mEventIndex - 1].timestamp);
+ } else {
+ // We are starting another iteration, immediately send the next event after 1ms.
+ nextEventTime = mLastEventTimestamp + 1000000;
+ }
+ // Prevent overflow.
+ assert(nextEventTime > mLastEventTimestamp);
+ mLastEventTimestamp = nextEventTime;
+ }
+
+ mEventIndex++;
+ if (mEventIndex == mEvents.size()) {
+ mEventIndex = 0;
+ if (mNumOfIterations > 0) {
+ mNumOfIterations--;
+ }
+ }
+
+ generatedValue.timestamp = mLastEventTimestamp;
+
+ return generatedValue;
+}
+
+} // namespace fake
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp
new file mode 100644
index 0000000..9133144
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/LinearFakeValueGenerator.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2021 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 "LinearFakeValueGenerator"
+
+#include "LinearFakeValueGenerator.h"
+
+#include <VehicleUtils.h>
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace fake {
+
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+
+LinearFakeValueGenerator::LinearFakeValueGenerator(int32_t propId, float middleValue,
+ float initValue, float dispersion,
+ float increment, int64_t interval) {
+ initGenCfg(propId, middleValue, initValue, dispersion, increment, interval);
+}
+
+LinearFakeValueGenerator::LinearFakeValueGenerator(const VehiclePropValue& request) {
+ const auto& v = request.value;
+ initGenCfg(v.int32Values[1], v.floatValues[0], v.floatValues[0], v.floatValues[1],
+ v.floatValues[2], v.int64Values[0]);
+}
+
+void LinearFakeValueGenerator::initGenCfg(int32_t propId, float middleValue, float initValue,
+ float dispersion, float increment, int64_t interval) {
+ // Other types are not supported.
+ assert(getPropType(propId) == VehicleProperty::INT32 ||
+ getPropType(propId) == VehicleProperty::INT64 ||
+ getPropType(propId) == VehicleProperty::FLOAT);
+
+ if (initValue < middleValue - dispersion || initValue >= middleValue + dispersion) {
+ ALOGW("%s: invalid initValue: %f, out of range, default to %f", __func__, initValue,
+ middleValue);
+ initValue = middleValue;
+ }
+ mGenCfg = GeneratorCfg{
+ .propId = propId,
+ .middleValue = middleValue,
+ .currentValue = initValue,
+ .dispersion = dispersion,
+ .increment = increment,
+ .interval = interval,
+ };
+}
+
+std::optional<VehiclePropValue> LinearFakeValueGenerator::nextEvent() {
+ VehiclePropValue event = {
+ .prop = mGenCfg.propId,
+ };
+ auto& value = event.value;
+ switch (getPropType(event.prop)) {
+ case VehiclePropertyType::INT32:
+ value.int32Values = {static_cast<int32_t>(mGenCfg.currentValue)};
+ break;
+ case VehiclePropertyType::INT64:
+ value.int64Values = {static_cast<int64_t>(mGenCfg.currentValue)};
+ break;
+ case VehiclePropertyType::FLOAT:
+ value.floatValues = {mGenCfg.currentValue};
+ break;
+ default:
+ ALOGE("%s: unsupported property type for 0x%x", __func__, event.prop);
+ }
+ if (mGenCfg.lastEventTimestamp == 0) {
+ mGenCfg.lastEventTimestamp = elapsedRealtimeNano();
+ } else {
+ long nextEventTime = mGenCfg.lastEventTimestamp + mGenCfg.interval;
+ // Prevent overflow.
+ assert(nextEventTime > mGenCfg.lastEventTimestamp);
+ mGenCfg.lastEventTimestamp = nextEventTime;
+ }
+ event.timestamp = mGenCfg.lastEventTimestamp;
+
+ mGenCfg.currentValue += mGenCfg.increment;
+ if (mGenCfg.currentValue >= mGenCfg.middleValue + mGenCfg.dispersion) {
+ // Wrap around, (i - d) + c - (i + d) = c - 2 * d
+ mGenCfg.currentValue = mGenCfg.currentValue - 2 * mGenCfg.dispersion;
+ }
+ return event;
+}
+
+} // namespace fake
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/Android.bp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/Android.bp
index 981a077..d3d3a10 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/Android.bp
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/Android.bp
@@ -27,5 +27,19 @@
"VehicleHalUtils",
"FakeVehicleHalValueGenerators",
],
+ shared_libs: [
+ "libjsoncpp",
+ ],
+ data: [
+ ":FakeVehicleHalValueGeneratorsTestFiles",
+ ],
test_suites: ["device-tests"],
}
+
+filegroup {
+ name: "FakeVehicleHalValueGeneratorsTestFiles",
+ srcs: [
+ "prop.json",
+ "prop_invalid.json",
+ ],
+}
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/FakeVehicleHalValueGeneratorsTest.cpp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/FakeVehicleHalValueGeneratorsTest.cpp
index abb3da2..929d9b3 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/FakeVehicleHalValueGeneratorsTest.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/FakeVehicleHalValueGeneratorsTest.cpp
@@ -15,6 +15,8 @@
*/
#include <GeneratorHub.h>
+#include <JsonFakeValueGenerator.h>
+#include <LinearFakeValueGenerator.h>
#include <VehicleUtils.h>
#include <android-base/file.h>
#include <android-base/thread_annotations.h>
@@ -61,6 +63,11 @@
mHub.reset();
}
+ static std::string getTestFilePath(const char* filename) {
+ static std::string baseDir = android::base::GetExecutableDirectory();
+ return baseDir + "/" + filename;
+ }
+
private:
void onHalEvent(const VehiclePropValue& event) {
VehiclePropValue eventCopy = event;
@@ -138,6 +145,271 @@
<< "Must stop generating event after generator is unregistered";
}
+TEST_F(FakeVehicleHalValueGeneratorsTest, testLinerFakeValueGeneratorFloat) {
+ std::unique_ptr<LinearFakeValueGenerator> generator =
+ std::make_unique<LinearFakeValueGenerator>(toInt(VehicleProperty::PERF_VEHICLE_SPEED),
+ /*middleValue=*/50.0,
+ /*initValue=*/30.0,
+ /*dispersion=*/50.0,
+ /*increment=*/20.0,
+ /*interval=*/10000000);
+ getHub()->registerGenerator(0, std::move(generator));
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ auto events = getEvents();
+ // We should get 10 events ideally, but let's be safe here.
+ ASSERT_LE((size_t)5, events.size());
+ int value = 30;
+ for (size_t i = 0; i < 5; i++) {
+ EXPECT_EQ(std::vector<float>({static_cast<float>(value)}), events[i].value.floatValues);
+ value = (value + 20) % 100;
+ }
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testLinerFakeValueGeneratorInt32) {
+ std::unique_ptr<LinearFakeValueGenerator> generator =
+ std::make_unique<LinearFakeValueGenerator>(toInt(VehicleProperty::INFO_MODEL_YEAR),
+ /*middleValue=*/50.0,
+ /*initValue=*/30.0,
+ /*dispersion=*/50.0,
+ /*increment=*/20.0,
+ /*interval=*/10000000);
+ getHub()->registerGenerator(0, std::move(generator));
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ auto events = getEvents();
+ // We should get 10 events ideally, but let's be safe here.
+ ASSERT_LE((size_t)5, events.size());
+ int value = 30;
+ for (size_t i = 0; i < 5; i++) {
+ EXPECT_EQ(std::vector<int32_t>({value}), events[i].value.int32Values);
+ value = (value + 20) % 100;
+ }
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testLinerFakeValueGeneratorInt64) {
+ std::unique_ptr<LinearFakeValueGenerator> generator =
+ std::make_unique<LinearFakeValueGenerator>(toInt(VehicleProperty::EPOCH_TIME),
+ /*middleValue=*/50.0,
+ /*initValue=*/30.0,
+ /*dispersion=*/50.0,
+ /*increment=*/20.0,
+ /*interval=*/10000000);
+ getHub()->registerGenerator(0, std::move(generator));
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ auto events = getEvents();
+ // We should get 10 events ideally, but let's be safe here.
+ ASSERT_LE((size_t)5, events.size());
+ int value = 30;
+ for (size_t i = 0; i < 5; i++) {
+ EXPECT_EQ(std::vector<int64_t>({value}), events[i].value.int64Values);
+ value = (value + 20) % 100;
+ }
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testLinerFakeValueGeneratorUsingRequest) {
+ VehiclePropValue request;
+ request.value.int32Values = {0, toInt(VehicleProperty::PERF_VEHICLE_SPEED)};
+ request.value.floatValues = {/*middleValue=*/50.0, /*dispersion=*/50.0, /*increment=*/20.0};
+ request.value.int64Values = {/*interval=*/10000000};
+
+ std::unique_ptr<LinearFakeValueGenerator> generator =
+ std::make_unique<LinearFakeValueGenerator>(request);
+ getHub()->registerGenerator(0, std::move(generator));
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ auto events = getEvents();
+ // We should get 10 events ideally, but let's be safe here.
+ ASSERT_LE((size_t)5, events.size());
+ int value = 50;
+ for (size_t i = 0; i < 5; i++) {
+ EXPECT_EQ(std::vector<float>({static_cast<float>(value)}), events[i].value.floatValues);
+ value = (value + 20) % 100;
+ }
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testLinerFakeValueGeneratorInvalidInitValue) {
+ std::unique_ptr<LinearFakeValueGenerator> generator =
+ std::make_unique<LinearFakeValueGenerator>(toInt(VehicleProperty::PERF_VEHICLE_SPEED),
+ /*middleValue=*/50.0,
+ // Out of range
+ /*initValue=*/110.0,
+ /*dispersion=*/50.0,
+ /*increment=*/20.0,
+ /*interval=*/10000000);
+ getHub()->registerGenerator(0, std::move(generator));
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ auto events = getEvents();
+ // We should get 10 events ideally, but let's be safe here.
+ ASSERT_LE((size_t)5, events.size());
+
+ // Init value would be set to middleValue if given initValue is not valid.
+ int value = 50;
+ for (size_t i = 0; i < 5; i++) {
+ EXPECT_EQ(std::vector<float>({static_cast<float>(value)}), events[i].value.floatValues);
+ value = (value + 20) % 100;
+ }
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testJsonFakeValueGenerator) {
+ long currentTime = elapsedRealtimeNano();
+
+ std::unique_ptr<JsonFakeValueGenerator> generator =
+ std::make_unique<JsonFakeValueGenerator>(getTestFilePath("prop.json"), 2);
+ getHub()->registerGenerator(0, std::move(generator));
+
+ // wait for some time.
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ std::vector<VehiclePropValue> expectedValues = {
+ VehiclePropValue{
+ .areaId = 0,
+ .value.int32Values = {8},
+ .prop = 289408000,
+ },
+ VehiclePropValue{
+ .areaId = 0,
+ .value.int32Values = {4},
+ .prop = 289408000,
+ },
+ VehiclePropValue{
+ .areaId = 0,
+ .value.int32Values = {16},
+ .prop = 289408000,
+ },
+ VehiclePropValue{
+ .areaId = 0,
+ .value.int32Values = {10},
+ .prop = 289408000,
+ },
+ };
+
+ // We have two iterations.
+ for (size_t i = 0; i < 4; i++) {
+ expectedValues.push_back(expectedValues[i]);
+ }
+
+ auto events = getEvents();
+
+ long lastEventTime = currentTime;
+ for (auto& event : events) {
+ EXPECT_GT(event.timestamp, lastEventTime);
+ lastEventTime = event.timestamp;
+ event.timestamp = 0;
+ }
+
+ EXPECT_EQ(events, expectedValues);
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testJsonFakeValueGeneratorIterateIndefinitely) {
+ std::unique_ptr<JsonFakeValueGenerator> generator =
+ std::make_unique<JsonFakeValueGenerator>(getTestFilePath("prop.json"), -1);
+ getHub()->registerGenerator(0, std::move(generator));
+
+ // wait for some time.
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ auto events = getEvents();
+
+ // Send 1 iteration takes 4ms + 1ms interval between iteration, so for 100ms we should get about
+ // 20 iteration, which is 80 events.
+ EXPECT_GT(events.size(), static_cast<size_t>(50));
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testJsonFakeValueGeneratorUsingRequest) {
+ long currentTime = elapsedRealtimeNano();
+
+ VehiclePropValue request = {.value = {
+ .stringValue = getTestFilePath("prop.json"),
+ .int32Values = {0, 2},
+ }};
+
+ std::unique_ptr<JsonFakeValueGenerator> generator =
+ std::make_unique<JsonFakeValueGenerator>(request);
+ getHub()->registerGenerator(0, std::move(generator));
+
+ // wait for some time.
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ std::vector<VehiclePropValue> expectedValues = {
+ VehiclePropValue{
+ .areaId = 0,
+ .value.int32Values = {8},
+ .prop = 289408000,
+ },
+ VehiclePropValue{
+ .areaId = 0,
+ .value.int32Values = {4},
+ .prop = 289408000,
+ },
+ VehiclePropValue{
+ .areaId = 0,
+ .value.int32Values = {16},
+ .prop = 289408000,
+ },
+ VehiclePropValue{
+ .areaId = 0,
+ .value.int32Values = {10},
+ .prop = 289408000,
+ },
+ };
+
+ // We have two iterations.
+ for (size_t i = 0; i < 4; i++) {
+ expectedValues.push_back(expectedValues[i]);
+ }
+
+ auto events = getEvents();
+
+ long lastEventTime = currentTime;
+ for (auto& event : events) {
+ EXPECT_GT(event.timestamp, lastEventTime);
+ lastEventTime = event.timestamp;
+ event.timestamp = 0;
+ }
+
+ EXPECT_EQ(events, expectedValues);
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testJsonFakeValueGeneratorInvalidFile) {
+ VehiclePropValue request = {.value = {
+ .stringValue = getTestFilePath("prop_invalid.json"),
+ .int32Values = {0, 2},
+ }};
+
+ std::unique_ptr<JsonFakeValueGenerator> generator =
+ std::make_unique<JsonFakeValueGenerator>(request);
+ getHub()->registerGenerator(0, std::move(generator));
+
+ // wait for some time.
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ ASSERT_TRUE(getEvents().empty());
+}
+
+TEST_F(FakeVehicleHalValueGeneratorsTest, testJsonFakeValueGeneratorNonExistingFile) {
+ VehiclePropValue request = {.value = {
+ .stringValue = "non_existing_file",
+ .int32Values = {0, 2},
+ }};
+
+ std::unique_ptr<JsonFakeValueGenerator> generator =
+ std::make_unique<JsonFakeValueGenerator>(request);
+ getHub()->registerGenerator(0, std::move(generator));
+
+ // wait for some time.
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ ASSERT_TRUE(getEvents().empty());
+}
+
} // namespace fake
} // namespace vehicle
} // namespace automotive
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop.json b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop.json
new file mode 100644
index 0000000..b881109
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop.json
@@ -0,0 +1,26 @@
+[
+ {
+ "timestamp": 1000000,
+ "areaId": 0,
+ "value": 8,
+ "prop": 289408000
+ },
+ {
+ "timestamp": 2000000,
+ "areaId": 0,
+ "value": 4,
+ "prop": 289408000
+ },
+ {
+ "timestamp": 3000000,
+ "areaId": 0,
+ "value": 16,
+ "prop": 289408000
+ },
+ {
+ "timestamp": 4000000,
+ "areaId": 0,
+ "value": 10,
+ "prop": 289408000
+ }
+]
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop_invalid.json b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop_invalid.json
new file mode 100644
index 0000000..98232c6
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/test/prop_invalid.json
@@ -0,0 +1 @@
+{
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
index 2aa949a..dee36f4 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
@@ -32,6 +32,7 @@
namespace hardware {
namespace automotive {
namespace vehicle {
+namespace fake {
class FakeVehicleHardware final : public IVehicleHardware {
public:
@@ -94,6 +95,7 @@
OnPropertySetErrorCallback mOnPropertySetErrorCallback GUARDED_BY(mCallbackLock);
};
+} // namespace fake
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
index 1c06ba0..f8bf7de 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -28,6 +28,7 @@
namespace hardware {
namespace automotive {
namespace vehicle {
+namespace fake {
using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
@@ -200,6 +201,7 @@
}
}
+} // namespace fake
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
index 650a131..53e647d 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
@@ -24,6 +24,7 @@
namespace hardware {
namespace automotive {
namespace vehicle {
+namespace fake {
namespace {
@@ -423,6 +424,7 @@
ASSERT_EQ(getGetValueResults()[1].prop->status, VehiclePropertyStatus::AVAILABLE);
}
+} // namespace fake
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h
index 545cf6a..9da2b14 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h
@@ -17,6 +17,8 @@
#ifndef android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleHalTypes_H_
#define android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleHalTypes_H_
+#include <aidl/android/hardware/automotive/vehicle/DiagnosticFloatSensorIndex.h>
+#include <aidl/android/hardware/automotive/vehicle/DiagnosticIntegerSensorIndex.h>
#include <aidl/android/hardware/automotive/vehicle/EvConnectorType.h>
#include <aidl/android/hardware/automotive/vehicle/EvsServiceState.h>
#include <aidl/android/hardware/automotive/vehicle/EvsServiceType.h>