Add special logic handle setting some props.
Add special logic to handle setting OBD2 properties and
VEHICLE_MAP_SERVICE.
Test: atest FakeVehicleHardwareTest
Bug: 201830716
Change-Id: I9b136efc452944e6c393c12feca14942919993c7
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/Android.bp b/automotive/vehicle/aidl/impl/fake_impl/hardware/Android.bp
index 210f316..f59a6ed 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/Android.bp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/Android.bp
@@ -34,6 +34,7 @@
static_libs: [
"VehicleHalUtils",
"FakeVehicleHalValueGenerators",
+ "FakeObd2Frame",
],
shared_libs: [
"libjsoncpp",
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 b2d813f..e1cd8bd 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
@@ -18,9 +18,11 @@
#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_hardware_include_FakeVehicleHardware_H_
#include <DefaultConfig.h>
+#include <FakeObd2Frame.h>
#include <IVehicleHardware.h>
#include <VehicleHalTypes.h>
#include <VehiclePropertyStore.h>
+#include <android-base/result.h>
#include <android-base/thread_annotations.h>
#include <map>
@@ -85,14 +87,15 @@
// Expose private methods to unit test.
friend class FakeVehicleHardwareTestHelper;
- std::unique_ptr<VehiclePropertyStore> mServerSidePropStore;
// mValuePool is also used in mServerSidePropStore.
- std::shared_ptr<VehiclePropValuePool> mValuePool;
+ const std::shared_ptr<VehiclePropValuePool> mValuePool;
+ const std::shared_ptr<VehiclePropertyStore> mServerSidePropStore;
+ const std::unique_ptr<obd2frame::FakeObd2Frame> mFakeObd2Frame;
std::mutex mCallbackLock;
OnPropertyChangeCallback mOnPropertyChangeCallback GUARDED_BY(mCallbackLock);
OnPropertySetErrorCallback mOnPropertySetErrorCallback GUARDED_BY(mCallbackLock);
- void init(std::shared_ptr<VehiclePropValuePool> valuePool);
+ void init();
// Stores the initial value to property store.
void storePropInitialValue(const defaultconfig::ConfigDeclaration& config);
// The callback that would be called when a vehicle property value change happens.
@@ -107,6 +110,9 @@
::aidl::android::hardware::automotive::vehicle::StatusCode maybeSetSpecialValue(
const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
bool* isSpecialValue);
+ ::android::base::Result<VehiclePropValuePool::RecyclableType> maybeGetSpecialValue(
+ const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
+ bool* isSpecialValue) const;
::aidl::android::hardware::automotive::vehicle::StatusCode setApPowerStateReport(
const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
VehiclePropValuePool::RecyclableType createApPowerStateReq(
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 94791da..15db767 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -17,7 +17,9 @@
#include "FakeVehicleHardware.h"
#include <DefaultConfig.h>
+#include <FakeObd2Frame.h>
#include <JsonFakeValueGenerator.h>
+#include <PropertyUtils.h>
#include <VehicleHalTypes.h>
#include <VehicleUtils.h>
#include <android-base/properties.h>
@@ -53,9 +55,27 @@
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+using ::android::base::Result;
+
const char* VENDOR_OVERRIDE_DIR = "/vendor/etc/automotive/vhaloverride/";
const char* OVERRIDE_PROPERTY = "persist.vendor.vhal_init_value_override";
+template <class T>
+StatusCode getErrorCode(const Result<T>& result) {
+ if (result.ok()) {
+ return StatusCode::OK;
+ }
+ return static_cast<StatusCode>(result.error().code());
+}
+
+template <class T>
+std::string getErrorMsg(const Result<T>& result) {
+ if (result.ok()) {
+ return "";
+ }
+ return result.error().message();
+}
+
} // namespace
void FakeVehicleHardware::storePropInitialValue(const defaultconfig::ConfigDeclaration& config) {
@@ -93,32 +113,51 @@
auto result =
mServerSidePropStore->writeValue(mValuePool->obtain(prop), /*updateStatus=*/true);
if (!result.ok()) {
- ALOGE("failed to write default config value, error: %s",
- result.error().message().c_str());
+ ALOGE("failed to write default config value, error: %s, status: %d",
+ getErrorMsg(result).c_str(), getErrorCode(result));
}
}
}
-FakeVehicleHardware::FakeVehicleHardware() {
- mValuePool = std::make_shared<VehiclePropValuePool>();
- init(mValuePool);
+FakeVehicleHardware::FakeVehicleHardware()
+ : mValuePool(new VehiclePropValuePool),
+ mServerSidePropStore(new VehiclePropertyStore(mValuePool)),
+ mFakeObd2Frame(new obd2frame::FakeObd2Frame(mServerSidePropStore)) {
+ init();
}
FakeVehicleHardware::FakeVehicleHardware(std::unique_ptr<VehiclePropValuePool> valuePool)
- : mValuePool(std::move(valuePool)) {
- init(mValuePool);
+ : mValuePool(std::move(valuePool)),
+ mServerSidePropStore(new VehiclePropertyStore(mValuePool)),
+ mFakeObd2Frame(new obd2frame::FakeObd2Frame(mServerSidePropStore)) {
+ init();
}
-void FakeVehicleHardware::init(std::shared_ptr<VehiclePropValuePool> valuePool) {
- mServerSidePropStore.reset(new VehiclePropertyStore(valuePool));
+void FakeVehicleHardware::init() {
for (auto& it : defaultconfig::getDefaultConfigs()) {
VehiclePropConfig cfg = it.config;
- mServerSidePropStore->registerProperty(cfg);
+ VehiclePropertyStore::TokenFunction tokenFunction = nullptr;
+
+ if (cfg.prop == OBD2_FREEZE_FRAME) {
+ tokenFunction = [](const VehiclePropValue& propValue) { return propValue.timestamp; };
+ }
+
+ mServerSidePropStore->registerProperty(cfg, tokenFunction);
+ if (obd2frame::FakeObd2Frame::isDiagnosticProperty(cfg)) {
+ // Ignore storing default value for diagnostic property. They have special get/set
+ // logic.
+ continue;
+ }
storePropInitialValue(it);
}
maybeOverrideProperties(VENDOR_OVERRIDE_DIR);
+ // OBD2_LIVE_FRAME and OBD2_FREEZE_FRAME must be configured in default configs.
+ mFakeObd2Frame->initObd2LiveFrame(*mServerSidePropStore->getConfig(OBD2_LIVE_FRAME).value());
+ mFakeObd2Frame->initObd2FreezeFrame(
+ *mServerSidePropStore->getConfig(OBD2_FREEZE_FRAME).value());
+
mServerSidePropStore->setOnValueChangeCallback(
[this](const VehiclePropValue& value) { return onValueChangeCallback(value); });
}
@@ -146,9 +185,10 @@
if (auto writeResult = mServerSidePropStore->writeValue(std::move(updatedValue));
!writeResult.ok()) {
- ALOGE("failed to write value into property store, error: %s",
- writeResult.error().message().c_str());
- return StatusCode::INVALID_ARG;
+ StatusCode errorCode = getErrorCode(writeResult);
+ ALOGE("failed to write value into property store, error: %s, code: %d",
+ getErrorMsg(writeResult).c_str(), errorCode);
+ return errorCode;
}
VehiclePropValuePool::RecyclableType prop;
@@ -168,9 +208,10 @@
if (auto writeResult =
mServerSidePropStore->writeValue(std::move(prop), /*updateStatus=*/true);
!writeResult.ok()) {
- ALOGE("failed to write AP_POWER_STATE_REQ into property store, error: %s",
- writeResult.error().message().c_str());
- return StatusCode::INTERNAL_ERROR;
+ StatusCode errorCode = getErrorCode(writeResult);
+ ALOGE("failed to write AP_POWER_STATE_REQ into property store, error: %s, code: %d",
+ getErrorMsg(writeResult).c_str(), errorCode);
+ return errorCode;
}
break;
case toInt(VehicleApPowerStateReport::DEEP_SLEEP_ENTRY):
@@ -185,9 +226,10 @@
if (auto writeResult =
mServerSidePropStore->writeValue(std::move(prop), /*updateStatus=*/true);
!writeResult.ok()) {
- ALOGE("failed to write AP_POWER_STATE_REQ into property store, error: %s",
- writeResult.error().message().c_str());
- return StatusCode::INTERNAL_ERROR;
+ StatusCode errorCode = getErrorCode(writeResult);
+ ALOGE("failed to write AP_POWER_STATE_REQ into property store, error: %s, code: %d",
+ getErrorMsg(writeResult).c_str(), errorCode);
+ return errorCode;
}
break;
default:
@@ -197,6 +239,35 @@
return StatusCode::OK;
}
+Result<VehiclePropValuePool::RecyclableType> FakeVehicleHardware::maybeGetSpecialValue(
+ const VehiclePropValue& value, bool* isSpecialValue) const {
+ *isSpecialValue = false;
+ int32_t propId = value.prop;
+ Result<VehiclePropValuePool::RecyclableType> result;
+
+ switch (propId) {
+ case OBD2_FREEZE_FRAME:
+ *isSpecialValue = true;
+ result = mFakeObd2Frame->getObd2FreezeFrame(value);
+ if (result.ok()) {
+ result.value()->timestamp = elapsedRealtimeNano();
+ }
+ return result;
+ case OBD2_FREEZE_FRAME_INFO:
+ *isSpecialValue = true;
+ result = mFakeObd2Frame->getObd2DtcInfo();
+ if (result.ok()) {
+ result.value()->timestamp = elapsedRealtimeNano();
+ }
+ return result;
+ default:
+ // Do nothing.
+ break;
+ }
+
+ return nullptr;
+}
+
StatusCode FakeVehicleHardware::maybeSetSpecialValue(const VehiclePropValue& value,
bool* isSpecialValue) {
*isSpecialValue = false;
@@ -206,6 +277,14 @@
case toInt(VehicleProperty::AP_POWER_STATE_REPORT):
*isSpecialValue = true;
return setApPowerStateReport(value);
+ case toInt(VehicleProperty::VEHICLE_MAP_SERVICE):
+ // Placeholder for future implementation of VMS property in the default hal. For
+ // now, just returns OK; otherwise, hal clients crash with property not supported.
+ *isSpecialValue = true;
+ return StatusCode::OK;
+ case OBD2_FREEZE_FRAME_CLEAR:
+ *isSpecialValue = true;
+ return mFakeObd2Frame->clearObd2FreezeFrames(value);
#ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
case toInt(VehicleProperty::CLUSTER_REPORT_STATE):
@@ -230,9 +309,10 @@
updatedValue->areaId = value.areaId;
if (auto writeResult = mServerSidePropStore->writeValue(std::move(updatedValue));
!writeResult.ok()) {
- ALOGE("failed to write value into property store, error: %s",
- writeResult.error().message().c_str());
- return StatusCode::INVALID_ARG;
+ StatusCode errorCode = getErrorCode(writeResult);
+ ALOGE("failed to write value into property store, error: %s, code: %d",
+ getErrorMsg(writeResult).c_str(), errorCode);
+ return errorCode;
}
return StatusCode::OK;
#endif // ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
@@ -278,9 +358,10 @@
auto writeResult = mServerSidePropStore->writeValue(std::move(updatedValue));
if (!writeResult.ok()) {
+ StatusCode errorCode = getErrorCode(writeResult);
ALOGE("failed to write value into property store, error: %s, code: %d",
- writeResult.error().message().c_str(), writeResult.error().code());
- setValueResult.status = StatusCode::INVALID_ARG;
+ getErrorMsg(writeResult).c_str(), errorCode);
+ setValueResult.status = errorCode;
}
results.push_back(std::move(setValueResult));
}
@@ -296,22 +377,38 @@
const std::vector<GetValueRequest>& requests) const {
std::vector<GetValueResult> results;
for (auto& request : requests) {
- const VehiclePropValue* value = &request.prop;
- ALOGD("getValues(%d)", value->prop);
+ const VehiclePropValue& value = request.prop;
+ ALOGD("getValues(%d)", value.prop);
- auto readResult = mServerSidePropStore->readValue(*value);
GetValueResult getValueResult;
getValueResult.requestId = request.requestId;
- if (!readResult.ok()) {
- auto error = readResult.error();
- if (error.code() == toInt(StatusCode::NOT_AVAILABLE)) {
- ALOGW("%s", "value has not been set yet");
- getValueResult.status = StatusCode::NOT_AVAILABLE;
+ bool isSpecialValue = false;
+
+ auto result = maybeGetSpecialValue(value, &isSpecialValue);
+ if (isSpecialValue) {
+ if (!result.ok()) {
+ StatusCode errorCode = getErrorCode(result);
+ ALOGE("failed to get special value: %d, error: %s, code: %d", value.prop,
+ getErrorMsg(result).c_str(), errorCode);
+ getValueResult.status = errorCode;
} else {
- ALOGE("failed to get value, error: %s, code: %d", error.message().c_str(),
- error.code());
- getValueResult.status = StatusCode::INVALID_ARG;
+ getValueResult.status = StatusCode::OK;
+ getValueResult.prop = *result.value();
}
+ results.push_back(std::move(getValueResult));
+ continue;
+ }
+
+ auto readResult = mServerSidePropStore->readValue(value);
+ if (!readResult.ok()) {
+ StatusCode errorCode = getErrorCode(readResult);
+ if (errorCode == StatusCode::NOT_AVAILABLE) {
+ ALOGW("%s", "value has not been set yet");
+ } else {
+ ALOGE("failed to get value, error: %s, code: %d", getErrorMsg(readResult).c_str(),
+ errorCode);
+ }
+ getValueResult.status = errorCode;
} else {
getValueResult.status = StatusCode::OK;
getValueResult.prop = *readResult.value();
@@ -378,8 +475,8 @@
if (auto result = mServerSidePropStore->writeValue(std::move(propToStore),
/*updateStatus=*/true);
!result.ok()) {
- ALOGW("failed to write vendor override properties: %d, error: %s", prop.prop,
- result.error().message().c_str());
+ ALOGW("failed to write vendor override properties: %d, error: %s, code: %d",
+ prop.prop, getErrorMsg(result).c_str(), getErrorCode(result));
}
}
}
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/Android.bp b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/Android.bp
index 3399317..b40c906 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/Android.bp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/Android.bp
@@ -32,6 +32,7 @@
"VehicleHalUtils",
"FakeVehicleHardware",
"FakeVehicleHalValueGenerators",
+ "FakeObd2Frame",
"libgtest",
"libgmock",
],
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 523214c..6f59ce7 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
@@ -17,6 +17,8 @@
#include <FakeVehicleHardware.h>
#include <DefaultConfig.h>
+#include <FakeObd2Frame.h>
+#include <PropertyUtils.h>
#include <TestPropertyUtils.h>
#include <android-base/expected.h>
@@ -249,6 +251,12 @@
int64_t requestId = 1;
for (auto& config : defaultconfig::getDefaultConfigs()) {
+ if (obd2frame::FakeObd2Frame::isDiagnosticProperty(config.config)) {
+ // Ignore storing default value for diagnostic property. They have special get/set
+ // logic.
+ continue;
+ }
+
int propId = config.config.prop;
if (isGlobalProp(propId)) {
if (config.initialValue == RawPropValues{}) {
@@ -901,6 +909,67 @@
return info.param.name;
});
+TEST_F(FakeVehicleHardwareTest, testGetObd2FreezeFrame) {
+ int64_t timestamp = elapsedRealtimeNano();
+
+ auto result = getValue(VehiclePropValue{.prop = OBD2_FREEZE_FRAME_INFO});
+
+ ASSERT_TRUE(result.ok());
+
+ auto propValue = result.value();
+ ASSERT_GE(propValue.timestamp, timestamp);
+ ASSERT_EQ(propValue.value.int64Values.size(), static_cast<size_t>(3))
+ << "expect 3 obd2 freeze frames stored";
+
+ for (int64_t timestamp : propValue.value.int64Values) {
+ auto freezeFrameResult = getValue(VehiclePropValue{
+ .prop = OBD2_FREEZE_FRAME,
+ .value.int64Values = {timestamp},
+ });
+
+ EXPECT_TRUE(result.ok()) << "expect to get freeze frame for timestamp " << timestamp
+ << " ok";
+ EXPECT_GE(freezeFrameResult.value().timestamp, timestamp);
+ }
+}
+
+TEST_F(FakeVehicleHardwareTest, testClearObd2FreezeFrame) {
+ int64_t timestamp = elapsedRealtimeNano();
+
+ auto getValueResult = getValue(VehiclePropValue{.prop = OBD2_FREEZE_FRAME_INFO});
+
+ ASSERT_TRUE(getValueResult.ok());
+
+ auto propValue = getValueResult.value();
+ ASSERT_GE(propValue.timestamp, timestamp);
+ ASSERT_EQ(propValue.value.int64Values.size(), static_cast<size_t>(3))
+ << "expect 3 obd2 freeze frames stored";
+
+ // No int64Values should clear all freeze frames.
+ StatusCode status = setValue(VehiclePropValue{.prop = OBD2_FREEZE_FRAME_CLEAR});
+
+ ASSERT_EQ(status, StatusCode::OK);
+
+ getValueResult = getValue(VehiclePropValue{.prop = OBD2_FREEZE_FRAME_INFO});
+
+ ASSERT_TRUE(getValueResult.ok());
+ ASSERT_EQ(getValueResult.value().value.int64Values.size(), static_cast<size_t>(0))
+ << "expect 0 obd2 freeze frames after cleared";
+}
+
+TEST_F(FakeVehicleHardwareTest, testSetVehicleMapService) {
+ StatusCode status =
+ setValue(VehiclePropValue{.prop = toInt(VehicleProperty::VEHICLE_MAP_SERVICE)});
+
+ EXPECT_EQ(status, StatusCode::OK);
+
+ auto getValueResult =
+ getValue(VehiclePropValue{.prop = toInt(VehicleProperty::VEHICLE_MAP_SERVICE)});
+
+ EXPECT_FALSE(getValueResult.ok());
+ EXPECT_EQ(getValueResult.error(), StatusCode::NOT_AVAILABLE);
+}
+
} // namespace fake
} // namespace vehicle
} // namespace automotive