Merge Android U (ab/10368041)
Bug: 291102124
Merged-In: I7b6fffac2ada0e039f79bad8cc9b4d954e9c3460
Change-Id: I9466127d8d0fa38df36ca99f704853b2db871e67
diff --git a/automotive/vehicle/aidl/impl/Android.bp b/automotive/vehicle/aidl/impl/Android.bp
index d24a739..d2c5145 100644
--- a/automotive/vehicle/aidl/impl/Android.bp
+++ b/automotive/vehicle/aidl/impl/Android.bp
@@ -22,7 +22,6 @@
name: "VehicleHalDefaults",
static_libs: [
"android-automotive-large-parcelable-lib",
- "android.hardware.automotive.vehicle-V1-ndk",
"libmath",
],
shared_libs: [
@@ -37,6 +36,7 @@
"-Wthread-safety",
],
defaults: [
+ "VehicleHalInterfaceDefaults",
"android-automotive-large-parcelable-defaults",
],
}
diff --git a/automotive/vehicle/aidl/impl/README.md b/automotive/vehicle/aidl/impl/README.md
new file mode 100644
index 0000000..121ffd1
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/README.md
@@ -0,0 +1,58 @@
+# AIDL VHAL libraries and reference implementation.
+---
+
+This directory stores the libraries useful for implementing vendor AIDL VHAL.
+This directory also stores a reference fake implementation for AIDL VHAL.
+
+## default_config
+
+Stores the default vehicle property configurations for reference vehicle HAL.
+Vendor implementation could copy this library but must update the configuration
+to meet their own requirements, e.g. enable or disable certain properties or
+update the initial value for certain properties.
+
+## fake_impl
+
+Contains libraries used specifically for the fake reference VHAL implementation.
+These libraries are for test only and must not be directly used for vendor
+VHAL implementation.
+
+These libraries contain test-spcific logic and must not run directly on a real
+vehicle.
+
+## grpc
+
+Stores code for GRPC based VHAL implementation.
+
+## hardware
+
+Defines an interface `IVehicleHardware.h` which vendor must implement for
+vehicle-specific logic if they want to follow our reference VHAL design.
+
+## proto
+
+Stores Some protobuf files translated from AIDL VHAL interface types. These
+files are used in GRPC VHAL implementation.
+
+## utils
+
+Defines a library `VehicleHalUtils` which provides useful utility functions for
+VHAL implementation. Vendor VHAL could use this library.
+
+## vhal
+
+Defines a library `DefaultVehicleHal` which provides generic logic for all VHAL
+implementations (including reference VHAL). Vendor VHAL implementation could
+use this library, along with their own implementation for `IVehicleHardware`
+interface.
+
+Also defines a binary `android.hardware.automotive.vehicle@V1-default-service`
+which is the reference VHAL implementation. It implements `IVehicle.aidl`
+interface. It uses `DefaultVehicleHal`, along with `FakeVehicleHardware`
+(in fake_impl). It simulates the vehicle bus interaction by using an
+in-memory map. Meaning that all properties (except for some special ones) are
+just written into a hash map and read from a hash map without relying on any
+hardware. As a result, the reference implementation can run on emulator or
+any host environment.
+
+Vendor must not directly use the reference implementation for a real vehicle.
\ No newline at end of file
diff --git a/automotive/vehicle/aidl/impl/default_config/Android.bp b/automotive/vehicle/aidl/impl/default_config/Android.bp
deleted file mode 100644
index 0feaf23..0000000
--- a/automotive/vehicle/aidl/impl/default_config/Android.bp
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.
- */
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_library_headers {
- name: "VehicleHalDefaultConfig",
- vendor: true,
- local_include_dirs: ["include"],
- export_include_dirs: ["include"],
- defaults: ["VehicleHalDefaults"],
- static_libs: ["VehicleHalUtils"],
- header_libs: ["VehicleHalTestUtilHeaders"],
- export_static_lib_headers: ["VehicleHalUtils"],
- export_header_lib_headers: ["VehicleHalTestUtilHeaders"],
-}
diff --git a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/Android.bp b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/Android.bp
new file mode 100644
index 0000000..6984d5e
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/Android.bp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_library {
+ name: "VehicleHalJsonConfigLoader",
+ vendor: true,
+ srcs: ["src/*.cpp"],
+ local_include_dirs: ["include"],
+ export_include_dirs: ["include"],
+ defaults: ["VehicleHalDefaults"],
+ static_libs: ["VehicleHalUtils"],
+ header_libs: [
+ "IVehicleGeneratedHeaders",
+ ],
+ shared_libs: ["libjsoncpp"],
+}
+
+cc_library {
+ name: "VehicleHalJsonConfigLoaderEnableTestProperties",
+ vendor: true,
+ srcs: ["src/*.cpp"],
+ local_include_dirs: ["include"],
+ export_include_dirs: ["include"],
+ defaults: ["VehicleHalDefaults"],
+ static_libs: ["VehicleHalUtils"],
+ header_libs: [
+ "VehicleHalTestUtilHeaders",
+ "IVehicleGeneratedHeaders",
+ ],
+ cflags: ["-DENABLE_VEHICLE_HAL_TEST_PROPERTIES"],
+ shared_libs: ["libjsoncpp"],
+}
+
+cc_library_headers {
+ name: "VehicleHalJsonConfigLoaderHeaders",
+ vendor: true,
+ local_include_dirs: ["include"],
+ export_include_dirs: ["include"],
+ defaults: ["VehicleHalDefaults"],
+ static_libs: ["VehicleHalUtils"],
+ header_libs: [
+ "IVehicleGeneratedHeaders",
+ ],
+ shared_libs: ["libjsoncpp"],
+}
diff --git a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/include/ConfigDeclaration.h b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/include/ConfigDeclaration.h
new file mode 100644
index 0000000..40ac129
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/include/ConfigDeclaration.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2022 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_default_config_JsonConfigLoader_include_ConfigDeclaration_H_
+#define android_hardware_automotive_vehicle_aidl_impl_default_config_JsonConfigLoader_include_ConfigDeclaration_H_
+
+#include <VehicleHalTypes.h>
+
+#include <unordered_map>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+// ConfigDeclaration represents one property config, its optional initial value and its optional
+// area configs and initial values for each area.
+struct ConfigDeclaration {
+ aidl::android::hardware::automotive::vehicle::VehiclePropConfig config;
+
+ // This value will be used as an initial value for the property. If this field is specified for
+ // property that supports multiple areas then it will be used for all areas unless particular
+ // area is overridden in initialAreaValue field.
+ aidl::android::hardware::automotive::vehicle::RawPropValues initialValue;
+ // Use initialAreaValues if it is necessary to specify different values per each area.
+ std::unordered_map<int32_t, aidl::android::hardware::automotive::vehicle::RawPropValues>
+ initialAreaValues;
+
+ inline bool operator==(const ConfigDeclaration& other) const {
+ return (config == other.config && initialValue == other.initialValue &&
+ initialAreaValues == other.initialAreaValues);
+ }
+
+ friend std::ostream& operator<<(std::ostream& os, const ConfigDeclaration& c) {
+ return os << "Config Declaration for property: "
+ << aidl::android::hardware::automotive::vehicle::toString(
+ static_cast<
+ aidl::android::hardware::automotive::vehicle::VehicleProperty>(
+ c.config.prop));
+ }
+};
+
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_automotive_vehicle_aidl_impl_default_config_JsonConfigLoader_include_ConfigDeclaration_H_
diff --git a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/include/JsonConfigLoader.h b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/include/JsonConfigLoader.h
new file mode 100644
index 0000000..f3bdbd2
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/include/JsonConfigLoader.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2022 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_default_config_JsonConfigLoader_include_JsonConfigLoader_H_
+#define android_hardware_automotive_vehicle_aidl_impl_default_config_JsonConfigLoader_include_JsonConfigLoader_H_
+
+#include <ConfigDeclaration.h>
+#include <VehicleHalTypes.h>
+
+#include <android-base/result.h>
+#include <json/json.h>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+// private namespace
+namespace jsonconfigloader_impl {
+
+// An abstract interface that represents a ValueParser for any constant value types.
+class ConstantParserInterface {
+ public:
+ // Parses a constant variable name to its actual value.
+ virtual android::base::Result<int> parseValue(const std::string& name) const = 0;
+ virtual ~ConstantParserInterface() = default;
+};
+
+// A class to parse a value field in JSON config file.
+// If the field is a string and the field is in the format of "XX::XX", the value will be parsed
+// as a constant value in the format of "TYPE::NAME". Otherwise, the field will be return as is
+// converted to the expected type.
+class JsonValueParser final {
+ public:
+ JsonValueParser();
+
+ android::base::Result<std::string> parseStringValue(const std::string& fieldName,
+ const Json::Value& value) const;
+
+ template <class T>
+ android::base::Result<std::vector<T>> parseArray(const std::string& fieldName,
+ const Json::Value& value) const;
+
+ template <class T>
+ android::base::Result<T> parseValue(const std::string& fieldName,
+ const Json::Value& value) const;
+
+ private:
+ template <class T>
+ static android::base::Result<T> convertValueToType(const std::string& fieldName,
+ const Json::Value& value);
+
+ std::optional<std::pair<std::string, std::string>> maybeGetTypeAndValueName(
+ const std::string& jsonFieldValue) const;
+
+ android::base::Result<int> parseConstantValue(
+ const std::pair<std::string, std::string>& typeValueName) const;
+
+ const ConstantParserInterface* getParser(const std::string& type) const {
+ auto it = mConstantParsersByType.find(type);
+ if (it == mConstantParsersByType.end()) {
+ return nullptr;
+ }
+ return it->second.get();
+ }
+
+ private:
+ inline static const std::string DELIMITER = "::";
+ std::unordered_map<std::string, std::unique_ptr<ConstantParserInterface>>
+ mConstantParsersByType;
+};
+
+// The main class to parse a VHAL config file in JSON format.
+class JsonConfigParser {
+ public:
+ android::base::Result<std::unordered_map<int32_t, ConfigDeclaration>> parseJsonConfig(
+ std::istream& is);
+
+ private:
+ JsonValueParser mValueParser;
+
+ // Parses configuration for each property.
+ std::optional<ConfigDeclaration> parseEachProperty(const Json::Value& propJsonValue,
+ std::vector<std::string>* errors);
+ // Tries to parse a JSON value to a specific type.
+ //
+ // If fieldIsOptional is True, then if the field specified by "fieldName" does not exist,
+ // this method will return true without doing anything, otherwise, it will return false.
+ //
+ // @param parentJsonNode The parent node of the field you are going to parse.
+ // @param fieldName The name for the field.
+ // @param fieldIsOptional Whether the field is optional.
+ // @param outPtr The pointer to output to if the field exists and parsing succeeded.
+ // @param errors The error array to append error to if errors are found.
+ // @return true if the field is optional and does not exist or parsed successfully.
+ template <class T>
+ bool tryParseJsonValueToVariable(const Json::Value& parentJsonNode,
+ const std::string& fieldName, bool fieldIsOptional, T* outPtr,
+ std::vector<std::string>* errors);
+ // Tries to parse a JSON value to an array of specific type.
+ //
+ // If fieldIsOptional is True, then if the field specified by "fieldName" does not exist,
+ // this method will return true without doing anything, otherwise, it will return false.
+ //
+ // @param parentJsonNode The parent node of the field you are going to parse.
+ // @param fieldName The name for the field.
+ // @param fieldIsOptional Whether the field is optional.
+ // @param outPtr The pointer to output to if the field exists and parsing succeeded.
+ // @param errors The error array to append error to if errors are found.
+ // @return true if the field is optional and does not exist or parsed successfully.
+ template <class T>
+ bool tryParseJsonArrayToVariable(const Json::Value& parentJsonNode,
+ const std::string& fieldName, bool fieldIsOptional,
+ std::vector<T>* outPtr, std::vector<std::string>* errors);
+ // Parses a JSON field to VehiclePropertyAccess or VehiclePropertyChangeMode.
+ template <class T>
+ void parseAccessChangeMode(
+ const Json::Value& parentJsonNode, const std::string& fieldName, int propId,
+ const std::string& propStr,
+ const std::unordered_map<aidl::android::hardware::automotive::vehicle::VehicleProperty,
+ T>& defaultMap,
+ T* outPtr, std::vector<std::string>* errors);
+
+ // Parses a JSON field to RawPropValues.
+ //
+ // @return True if the field exist and can be parsed to a RawPropValues.
+ bool parsePropValues(const Json::Value& parentJsonNode, const std::string& fieldName,
+ aidl::android::hardware::automotive::vehicle::RawPropValues* outPtr,
+ std::vector<std::string>* errors);
+
+ // Prase a JSON field as an array of area configs.
+ void parseAreas(const Json::Value& parentJsonNode, const std::string& fieldName,
+ ConfigDeclaration* outPtr, std::vector<std::string>* errors);
+};
+
+} // namespace jsonconfigloader_impl
+
+// A class to load vehicle property configs and initial values in JSON format.
+class JsonConfigLoader final {
+ public:
+ JsonConfigLoader();
+
+ // Loads a JSON file stream and parses it to a map from propId to ConfigDeclarations.
+ android::base::Result<std::unordered_map<int32_t, ConfigDeclaration>> loadPropConfig(
+ std::istream& is);
+
+ // Loads a JSON config file and parses it to a map from propId to ConfigDeclarations.
+ android::base::Result<std::unordered_map<int32_t, ConfigDeclaration>> loadPropConfig(
+ const std::string& configPath);
+
+ private:
+ std::unique_ptr<jsonconfigloader_impl::JsonConfigParser> mParser;
+};
+
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_automotive_vehicle_aidl_impl_default_config_JsonConfigLoader_include_JsonConfigLoader_H_
diff --git a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp
new file mode 100644
index 0000000..0a1f904
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp
@@ -0,0 +1,631 @@
+/*
+ * Copyright (C) 2022 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 <JsonConfigLoader.h>
+
+#include <AccessForVehicleProperty.h>
+#include <ChangeModeForVehicleProperty.h>
+#include <PropertyUtils.h>
+
+#ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES
+#include <TestPropertyUtils.h>
+#endif // ENABLE_VEHICLE_HAL_TEST_PROPERTIES
+
+#include <android-base/strings.h>
+#include <fstream>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+namespace jsonconfigloader_impl {
+
+using ::aidl::android::hardware::automotive::vehicle::AccessForVehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::AutomaticEmergencyBrakingState;
+using ::aidl::android::hardware::automotive::vehicle::BlindSpotWarningState;
+using ::aidl::android::hardware::automotive::vehicle::ChangeModeForVehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::CruiseControlCommand;
+using ::aidl::android::hardware::automotive::vehicle::CruiseControlState;
+using ::aidl::android::hardware::automotive::vehicle::CruiseControlType;
+using ::aidl::android::hardware::automotive::vehicle::EmergencyLaneKeepAssistState;
+using ::aidl::android::hardware::automotive::vehicle::ErrorState;
+using ::aidl::android::hardware::automotive::vehicle::EvConnectorType;
+using ::aidl::android::hardware::automotive::vehicle::EvsServiceState;
+using ::aidl::android::hardware::automotive::vehicle::EvsServiceType;
+using ::aidl::android::hardware::automotive::vehicle::ForwardCollisionWarningState;
+using ::aidl::android::hardware::automotive::vehicle::FuelType;
+using ::aidl::android::hardware::automotive::vehicle::GsrComplianceRequirementType;
+using ::aidl::android::hardware::automotive::vehicle::HandsOnDetectionDriverState;
+using ::aidl::android::hardware::automotive::vehicle::HandsOnDetectionWarning;
+using ::aidl::android::hardware::automotive::vehicle::LaneCenteringAssistCommand;
+using ::aidl::android::hardware::automotive::vehicle::LaneCenteringAssistState;
+using ::aidl::android::hardware::automotive::vehicle::LaneDepartureWarningState;
+using ::aidl::android::hardware::automotive::vehicle::LaneKeepAssistState;
+using ::aidl::android::hardware::automotive::vehicle::LocationCharacterization;
+using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
+using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReport;
+using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaMirror;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaWindow;
+using ::aidl::android::hardware::automotive::vehicle::VehicleGear;
+using ::aidl::android::hardware::automotive::vehicle::VehicleHvacFanDirection;
+using ::aidl::android::hardware::automotive::vehicle::VehicleIgnitionState;
+using ::aidl::android::hardware::automotive::vehicle::VehicleOilLevel;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode;
+using ::aidl::android::hardware::automotive::vehicle::VehicleSeatOccupancyState;
+using ::aidl::android::hardware::automotive::vehicle::VehicleTurnSignal;
+using ::aidl::android::hardware::automotive::vehicle::VehicleUnit;
+using ::aidl::android::hardware::automotive::vehicle::VehicleVendorPermission;
+using ::aidl::android::hardware::automotive::vehicle::WindshieldWipersState;
+using ::aidl::android::hardware::automotive::vehicle::WindshieldWipersSwitch;
+
+using ::android::base::Error;
+using ::android::base::Result;
+
+// Defines a map from constant names to constant values, the values defined here corresponds to
+// the "Constants::XXXX" used in JSON config file.
+const std::unordered_map<std::string, int> CONSTANTS_BY_NAME = {
+ {"DOOR_1_RIGHT", DOOR_1_RIGHT},
+ {"DOOR_1_LEFT", DOOR_1_LEFT},
+ {"DOOR_2_RIGHT", DOOR_2_RIGHT},
+ {"DOOR_2_LEFT", DOOR_2_LEFT},
+ {"DOOR_REAR", DOOR_REAR},
+ {"HVAC_ALL", HVAC_ALL},
+ {"HVAC_LEFT", HVAC_LEFT},
+ {"HVAC_RIGHT", HVAC_RIGHT},
+ {"VENDOR_EXTENSION_INT_PROPERTY", VENDOR_EXTENSION_INT_PROPERTY},
+ {"VENDOR_EXTENSION_BOOLEAN_PROPERTY", VENDOR_EXTENSION_BOOLEAN_PROPERTY},
+ {"VENDOR_EXTENSION_STRING_PROPERTY", VENDOR_EXTENSION_STRING_PROPERTY},
+ {"VENDOR_EXTENSION_FLOAT_PROPERTY", VENDOR_EXTENSION_FLOAT_PROPERTY},
+ {"WINDOW_1_LEFT", WINDOW_1_LEFT},
+ {"WINDOW_1_RIGHT", WINDOW_1_RIGHT},
+ {"WINDOW_2_LEFT", WINDOW_2_LEFT},
+ {"WINDOW_2_RIGHT", WINDOW_2_RIGHT},
+ {"WINDOW_ROOF_TOP_1", WINDOW_ROOF_TOP_1},
+ {"WINDOW_1_RIGHT_2_LEFT_2_RIGHT", WINDOW_1_RIGHT | WINDOW_2_LEFT | WINDOW_2_RIGHT},
+ {"SEAT_1_LEFT", SEAT_1_LEFT},
+ {"SEAT_1_RIGHT", SEAT_1_RIGHT},
+ {"SEAT_2_LEFT", SEAT_2_LEFT},
+ {"SEAT_2_RIGHT", SEAT_2_RIGHT},
+ {"SEAT_2_CENTER", SEAT_2_CENTER},
+ {"SEAT_2_LEFT_2_RIGHT_2_CENTER", SEAT_2_LEFT | SEAT_2_RIGHT | SEAT_2_CENTER},
+ {"WHEEL_REAR_RIGHT", WHEEL_REAR_RIGHT},
+ {"WHEEL_REAR_LEFT", WHEEL_REAR_LEFT},
+ {"WHEEL_FRONT_RIGHT", WHEEL_FRONT_RIGHT},
+ {"WHEEL_FRONT_LEFT", WHEEL_FRONT_LEFT},
+ {"CHARGE_PORT_FRONT_LEFT", CHARGE_PORT_FRONT_LEFT},
+ {"CHARGE_PORT_REAR_LEFT", CHARGE_PORT_REAR_LEFT},
+ {"FAN_DIRECTION_UNKNOWN", toInt(VehicleHvacFanDirection::UNKNOWN)},
+ {"FAN_DIRECTION_FLOOR", FAN_DIRECTION_FLOOR},
+ {"FAN_DIRECTION_FACE", FAN_DIRECTION_FACE},
+ {"FAN_DIRECTION_DEFROST", FAN_DIRECTION_DEFROST},
+ {"FAN_DIRECTION_FACE_FLOOR", FAN_DIRECTION_FACE | FAN_DIRECTION_FLOOR},
+ {"FAN_DIRECTION_FACE_DEFROST", FAN_DIRECTION_FACE | FAN_DIRECTION_DEFROST},
+ {"FAN_DIRECTION_FLOOR_DEFROST", FAN_DIRECTION_FLOOR | FAN_DIRECTION_DEFROST},
+ {"FAN_DIRECTION_FLOOR_DEFROST_FACE",
+ FAN_DIRECTION_FLOOR | FAN_DIRECTION_DEFROST | FAN_DIRECTION_FACE},
+ {"FUEL_DOOR_REAR_LEFT", FUEL_DOOR_REAR_LEFT},
+ {"LIGHT_STATE_ON", LIGHT_STATE_ON},
+ {"LIGHT_STATE_OFF", LIGHT_STATE_OFF},
+ {"LIGHT_SWITCH_OFF", LIGHT_SWITCH_OFF},
+ {"LIGHT_SWITCH_ON", LIGHT_SWITCH_ON},
+ {"LIGHT_SWITCH_AUTO", LIGHT_SWITCH_AUTO},
+ {"EV_STOPPING_MODE_CREEP", EV_STOPPING_MODE_CREEP},
+ {"EV_STOPPING_MODE_ROLL", EV_STOPPING_MODE_ROLL},
+ {"EV_STOPPING_MODE_HOLD", EV_STOPPING_MODE_HOLD},
+ {"MIRROR_DRIVER_LEFT_RIGHT",
+ toInt(VehicleAreaMirror::DRIVER_LEFT) | toInt(VehicleAreaMirror::DRIVER_RIGHT)},
+#ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES
+ // Following are test properties:
+ {"ECHO_REVERSE_BYTES", ECHO_REVERSE_BYTES},
+ {"VENDOR_PROPERTY_ID", VENDOR_PROPERTY_ID},
+ {"kMixedTypePropertyForTest", kMixedTypePropertyForTest},
+ {"VENDOR_CLUSTER_NAVIGATION_STATE", VENDOR_CLUSTER_NAVIGATION_STATE},
+ {"VENDOR_CLUSTER_REQUEST_DISPLAY", VENDOR_CLUSTER_REQUEST_DISPLAY},
+ {"VENDOR_CLUSTER_SWITCH_UI", VENDOR_CLUSTER_SWITCH_UI},
+ {"VENDOR_CLUSTER_DISPLAY_STATE", VENDOR_CLUSTER_DISPLAY_STATE},
+ {"VENDOR_CLUSTER_REPORT_STATE", VENDOR_CLUSTER_REPORT_STATE},
+ {"PLACEHOLDER_PROPERTY_INT", PLACEHOLDER_PROPERTY_INT},
+ {"PLACEHOLDER_PROPERTY_FLOAT", PLACEHOLDER_PROPERTY_FLOAT},
+ {"PLACEHOLDER_PROPERTY_BOOLEAN", PLACEHOLDER_PROPERTY_BOOLEAN},
+ {"PLACEHOLDER_PROPERTY_STRING", PLACEHOLDER_PROPERTY_STRING}
+#endif // ENABLE_VEHICLE_HAL_TEST_PROPERTIES
+};
+
+// A class to parse constant values for type T.
+template <class T>
+class ConstantParser final : public ConstantParserInterface {
+ public:
+ ConstantParser() {
+ for (const T& v : ndk::enum_range<T>()) {
+ std::string name = aidl::android::hardware::automotive::vehicle::toString(v);
+ // We use the same constant for both VehicleUnit::GALLON and VehicleUnit::US_GALLON,
+ // which caused toString() not work properly for US_GALLON. So we explicitly add the
+ // map here.
+ if (name == "GALLON") {
+ mValueByName["US_GALLON"] = toInt(v);
+ }
+ mValueByName[name] = toInt(v);
+ }
+ }
+
+ ~ConstantParser() = default;
+
+ Result<int> parseValue(const std::string& name) const override {
+ auto it = mValueByName.find(name);
+ if (it == mValueByName.end()) {
+ return Error() << "Constant name: " << name << " is not defined";
+ }
+ return it->second;
+ }
+
+ private:
+ std::unordered_map<std::string, int> mValueByName;
+};
+
+// A class to parse constant values defined in CONSTANTS_BY_NAME map.
+class LocalVariableParser final : public ConstantParserInterface {
+ public:
+ ~LocalVariableParser() = default;
+
+ Result<int> parseValue(const std::string& name) const override {
+ auto constantsIt = CONSTANTS_BY_NAME.find(name);
+ if (constantsIt == CONSTANTS_BY_NAME.end()) {
+ return Error() << "Constant variable name: " << name << " is not defined";
+ }
+ return constantsIt->second;
+ }
+};
+
+JsonValueParser::JsonValueParser() {
+ mConstantParsersByType["VehiclePropertyAccess"] =
+ std::make_unique<ConstantParser<VehiclePropertyAccess>>();
+ mConstantParsersByType["VehiclePropertyChangeMode"] =
+ std::make_unique<ConstantParser<VehiclePropertyChangeMode>>();
+ mConstantParsersByType["LocationCharacterization"] =
+ std::make_unique<ConstantParser<LocationCharacterization>>();
+ mConstantParsersByType["VehicleGear"] = std::make_unique<ConstantParser<VehicleGear>>();
+ mConstantParsersByType["VehicleAreaWindow"] =
+ std::make_unique<ConstantParser<VehicleAreaWindow>>();
+ mConstantParsersByType["VehicleAreaMirror"] =
+ std::make_unique<ConstantParser<VehicleAreaMirror>>();
+ mConstantParsersByType["VehicleOilLevel"] = std::make_unique<ConstantParser<VehicleOilLevel>>();
+ mConstantParsersByType["VehicleUnit"] = std::make_unique<ConstantParser<VehicleUnit>>();
+ mConstantParsersByType["VehicleSeatOccupancyState"] =
+ std::make_unique<ConstantParser<VehicleSeatOccupancyState>>();
+ mConstantParsersByType["VehicleHvacFanDirection"] =
+ std::make_unique<ConstantParser<VehicleHvacFanDirection>>();
+ mConstantParsersByType["VehicleApPowerStateReport"] =
+ std::make_unique<ConstantParser<VehicleApPowerStateReport>>();
+ mConstantParsersByType["VehicleTurnSignal"] =
+ std::make_unique<ConstantParser<VehicleTurnSignal>>();
+ mConstantParsersByType["VehicleVendorPermission"] =
+ std::make_unique<ConstantParser<VehicleVendorPermission>>();
+ mConstantParsersByType["EvsServiceType"] = std::make_unique<ConstantParser<EvsServiceType>>();
+ mConstantParsersByType["EvsServiceState"] = std::make_unique<ConstantParser<EvsServiceState>>();
+ mConstantParsersByType["EvConnectorType"] = std::make_unique<ConstantParser<EvConnectorType>>();
+ mConstantParsersByType["VehicleProperty"] = std::make_unique<ConstantParser<VehicleProperty>>();
+ mConstantParsersByType["GsrComplianceRequirementType"] =
+ std::make_unique<ConstantParser<GsrComplianceRequirementType>>();
+ mConstantParsersByType["VehicleIgnitionState"] =
+ std::make_unique<ConstantParser<VehicleIgnitionState>>();
+ mConstantParsersByType["FuelType"] = std::make_unique<ConstantParser<FuelType>>();
+ mConstantParsersByType["WindshieldWipersState"] =
+ std::make_unique<ConstantParser<WindshieldWipersState>>();
+ mConstantParsersByType["WindshieldWipersSwitch"] =
+ std::make_unique<ConstantParser<WindshieldWipersSwitch>>();
+ mConstantParsersByType["EmergencyLaneKeepAssistState"] =
+ std::make_unique<ConstantParser<EmergencyLaneKeepAssistState>>();
+ mConstantParsersByType["CruiseControlType"] =
+ std::make_unique<ConstantParser<CruiseControlType>>();
+ mConstantParsersByType["CruiseControlState"] =
+ std::make_unique<ConstantParser<CruiseControlState>>();
+ mConstantParsersByType["CruiseControlCommand"] =
+ std::make_unique<ConstantParser<CruiseControlCommand>>();
+ mConstantParsersByType["HandsOnDetectionDriverState"] =
+ std::make_unique<ConstantParser<HandsOnDetectionDriverState>>();
+ mConstantParsersByType["HandsOnDetectionWarning"] =
+ std::make_unique<ConstantParser<HandsOnDetectionWarning>>();
+ mConstantParsersByType["ErrorState"] = std::make_unique<ConstantParser<ErrorState>>();
+ mConstantParsersByType["AutomaticEmergencyBrakingState"] =
+ std::make_unique<ConstantParser<AutomaticEmergencyBrakingState>>();
+ mConstantParsersByType["ForwardCollisionWarningState"] =
+ std::make_unique<ConstantParser<ForwardCollisionWarningState>>();
+ mConstantParsersByType["BlindSpotWarningState"] =
+ std::make_unique<ConstantParser<BlindSpotWarningState>>();
+ mConstantParsersByType["LaneDepartureWarningState"] =
+ std::make_unique<ConstantParser<LaneDepartureWarningState>>();
+ mConstantParsersByType["LaneKeepAssistState"] =
+ std::make_unique<ConstantParser<LaneKeepAssistState>>();
+ mConstantParsersByType["LaneCenteringAssistCommand"] =
+ std::make_unique<ConstantParser<LaneCenteringAssistCommand>>();
+ mConstantParsersByType["LaneCenteringAssistState"] =
+ std::make_unique<ConstantParser<LaneCenteringAssistState>>();
+ mConstantParsersByType["Constants"] = std::make_unique<LocalVariableParser>();
+}
+
+template <>
+Result<int32_t> JsonValueParser::convertValueToType<int32_t>(const std::string& fieldName,
+ const Json::Value& value) {
+ if (!value.isInt()) {
+ return Error() << "The value: " << value << " for field: " << fieldName
+ << " is not in correct type, expect int";
+ }
+ return static_cast<int32_t>(value.asInt());
+}
+
+template <>
+Result<float> JsonValueParser::convertValueToType<float>(const std::string& fieldName,
+ const Json::Value& value) {
+ // isFloat value does not exist, so we use isDouble here.
+ if (!value.isDouble()) {
+ return Error() << "The value: " << value << " for field: " << fieldName
+ << " is not in correct type, expect float";
+ }
+ return value.asFloat();
+}
+
+template <>
+Result<int64_t> JsonValueParser::convertValueToType<int64_t>(const std::string& fieldName,
+ const Json::Value& value) {
+ if (!value.isInt64()) {
+ return Error() << "The value: " << value << " for field: " << fieldName
+ << " is not in correct type, expect int64";
+ }
+ return static_cast<int64_t>(value.asInt64());
+}
+
+template <>
+Result<std::string> JsonValueParser::convertValueToType<std::string>(const std::string& fieldName,
+ const Json::Value& value) {
+ if (!value.isString()) {
+ return Error() << "The value: " << value << " for field: " << fieldName
+ << " is not in correct type, expect string";
+ }
+ return value.asString();
+}
+
+Result<std::string> JsonValueParser::parseStringValue(const std::string& fieldName,
+ const Json::Value& value) const {
+ return convertValueToType<std::string>(fieldName, value);
+}
+
+template <class T>
+Result<T> JsonValueParser::parseValue(const std::string& fieldName,
+ const Json::Value& value) const {
+ if (!value.isString()) {
+ return convertValueToType<T>(fieldName, value);
+ }
+ auto maybeTypeAndValue = maybeGetTypeAndValueName(value.asString());
+ if (!maybeTypeAndValue.has_value()) {
+ return Error() << "Invalid constant value: " << value << " for field: " << fieldName;
+ }
+ auto constantParseResult = parseConstantValue(maybeTypeAndValue.value());
+ if (!constantParseResult.ok()) {
+ return constantParseResult.error();
+ }
+ int constantValue = constantParseResult.value();
+ return static_cast<T>(constantValue);
+}
+
+template <>
+Result<std::string> JsonValueParser::parseValue<std::string>(const std::string& fieldName,
+ const Json::Value& value) const {
+ return parseStringValue(fieldName, value);
+}
+
+template <class T>
+Result<std::vector<T>> JsonValueParser::parseArray(const std::string& fieldName,
+ const Json::Value& value) const {
+ if (!value.isArray()) {
+ return Error() << "The value: " << value << " for field: " << fieldName
+ << " is not in correct type, expect array";
+ }
+ std::vector<T> parsedValues;
+ for (unsigned int i = 0; i < value.size(); i++) {
+ auto result = parseValue<T>(fieldName, value[i]);
+ if (!result.ok()) {
+ return result.error();
+ }
+ parsedValues.push_back(result.value());
+ }
+ return std::move(parsedValues);
+}
+
+std::optional<std::pair<std::string, std::string>> JsonValueParser::maybeGetTypeAndValueName(
+ const std::string& jsonFieldValue) const {
+ size_t pos = jsonFieldValue.find(DELIMITER);
+ if (pos == std::string::npos) {
+ return {};
+ }
+ std::string type = jsonFieldValue.substr(0, pos);
+ std::string valueName = jsonFieldValue.substr(pos + DELIMITER.length(), std::string::npos);
+ if (type != "Constants" && mConstantParsersByType.find(type) == mConstantParsersByType.end()) {
+ return {};
+ }
+ return std::make_pair(type, valueName);
+}
+
+Result<int> JsonValueParser::parseConstantValue(
+ const std::pair<std::string, std::string>& typeValueName) const {
+ const std::string& type = typeValueName.first;
+ const std::string& valueName = typeValueName.second;
+ auto it = mConstantParsersByType.find(type);
+ if (it == mConstantParsersByType.end()) {
+ return Error() << "Unrecognized type: " << type;
+ }
+ auto result = it->second->parseValue(valueName);
+ if (!result.ok()) {
+ return Error() << type << "::" << valueName << " undefined";
+ }
+ return result;
+}
+
+template <class T>
+bool JsonConfigParser::tryParseJsonValueToVariable(const Json::Value& parentJsonNode,
+ const std::string& fieldName,
+ bool fieldIsOptional, T* outPtr,
+ std::vector<std::string>* errors) {
+ if (!parentJsonNode.isObject()) {
+ errors->push_back("Node: " + parentJsonNode.toStyledString() + " is not an object");
+ return false;
+ }
+ if (!parentJsonNode.isMember(fieldName)) {
+ if (!fieldIsOptional) {
+ errors->push_back("Missing required field: " + fieldName +
+ " in node: " + parentJsonNode.toStyledString());
+ return false;
+ }
+ return true;
+ }
+ auto result = mValueParser.parseValue<T>(fieldName, parentJsonNode[fieldName]);
+ if (!result.ok()) {
+ errors->push_back(result.error().message());
+ return false;
+ }
+ *outPtr = std::move(result.value());
+ return true;
+}
+
+template <class T>
+bool JsonConfigParser::tryParseJsonArrayToVariable(const Json::Value& parentJsonNode,
+ const std::string& fieldName,
+ bool fieldIsOptional, std::vector<T>* outPtr,
+ std::vector<std::string>* errors) {
+ if (!parentJsonNode.isObject()) {
+ errors->push_back("Node: " + parentJsonNode.toStyledString() + " is not an object");
+ return false;
+ }
+ if (!parentJsonNode.isMember(fieldName)) {
+ if (!fieldIsOptional) {
+ errors->push_back("Missing required field: " + fieldName +
+ " in node: " + parentJsonNode.toStyledString());
+ return false;
+ }
+ return true;
+ }
+ auto result = mValueParser.parseArray<T>(fieldName, parentJsonNode[fieldName]);
+ if (!result.ok()) {
+ errors->push_back(result.error().message());
+ return false;
+ }
+ *outPtr = std::move(result.value());
+ return true;
+}
+
+template <class T>
+void JsonConfigParser::parseAccessChangeMode(
+ const Json::Value& parentJsonNode, const std::string& fieldName, int propId,
+ const std::string& propStr, const std::unordered_map<VehicleProperty, T>& defaultMap,
+ T* outPtr, std::vector<std::string>* errors) {
+ if (!parentJsonNode.isObject()) {
+ errors->push_back("Node: " + parentJsonNode.toStyledString() + " is not an object");
+ return;
+ }
+ if (parentJsonNode.isMember(fieldName)) {
+ auto result = mValueParser.parseValue<int32_t>(fieldName, parentJsonNode[fieldName]);
+ if (!result.ok()) {
+ errors->push_back(result.error().message());
+ return;
+ }
+ *outPtr = static_cast<T>(result.value());
+ return;
+ }
+ auto it = defaultMap.find(static_cast<VehicleProperty>(propId));
+ if (it == defaultMap.end()) {
+ errors->push_back("No " + fieldName + " specified for property: " + propStr);
+ return;
+ }
+ *outPtr = it->second;
+ return;
+}
+
+bool JsonConfigParser::parsePropValues(const Json::Value& parentJsonNode,
+ const std::string& fieldName, RawPropValues* outPtr,
+ std::vector<std::string>* errors) {
+ if (!parentJsonNode.isObject()) {
+ errors->push_back("Node: " + parentJsonNode.toStyledString() + " is not an object");
+ return false;
+ }
+ if (!parentJsonNode.isMember(fieldName)) {
+ return false;
+ }
+ const Json::Value& jsonValue = parentJsonNode[fieldName];
+ bool success = true;
+ success &= tryParseJsonArrayToVariable(jsonValue, "int32Values",
+ /*optional=*/true, &(outPtr->int32Values), errors);
+ success &= tryParseJsonArrayToVariable(jsonValue, "floatValues",
+ /*optional=*/true, &(outPtr->floatValues), errors);
+ success &= tryParseJsonArrayToVariable(jsonValue, "int64Values",
+ /*optional=*/true, &(outPtr->int64Values), errors);
+ // We don't support "byteValues" yet.
+ success &= tryParseJsonValueToVariable(jsonValue, "stringValue",
+ /*optional=*/true, &(outPtr->stringValue), errors);
+ return success;
+}
+
+void JsonConfigParser::parseAreas(const Json::Value& parentJsonNode, const std::string& fieldName,
+ ConfigDeclaration* config, std::vector<std::string>* errors) {
+ if (!parentJsonNode.isObject()) {
+ errors->push_back("Node: " + parentJsonNode.toStyledString() + " is not an object");
+ return;
+ }
+ if (!parentJsonNode.isMember(fieldName)) {
+ return;
+ }
+ const Json::Value& jsonValue = parentJsonNode[fieldName];
+
+ if (!jsonValue.isArray()) {
+ errors->push_back("Field: " + fieldName + " is not an array");
+ return;
+ }
+ for (unsigned int i = 0; i < jsonValue.size(); i++) {
+ int32_t areaId;
+ const Json::Value& jsonAreaConfig = jsonValue[i];
+ if (!tryParseJsonValueToVariable(jsonAreaConfig, "areaId",
+ /*optional=*/false, &areaId, errors)) {
+ continue;
+ }
+ VehicleAreaConfig areaConfig = {};
+ areaConfig.areaId = areaId;
+ tryParseJsonValueToVariable(jsonAreaConfig, "minInt32Value", /*optional=*/true,
+ &areaConfig.minInt32Value, errors);
+ tryParseJsonValueToVariable(jsonAreaConfig, "maxInt32Value", /*optional=*/true,
+ &areaConfig.maxInt32Value, errors);
+ tryParseJsonValueToVariable(jsonAreaConfig, "minInt64Value", /*optional=*/true,
+ &areaConfig.minInt64Value, errors);
+ tryParseJsonValueToVariable(jsonAreaConfig, "maxInt64Value", /*optional=*/true,
+ &areaConfig.maxInt64Value, errors);
+ tryParseJsonValueToVariable(jsonAreaConfig, "minFloatValue", /*optional=*/true,
+ &areaConfig.minFloatValue, errors);
+ tryParseJsonValueToVariable(jsonAreaConfig, "maxFloatValue", /*optional=*/true,
+ &areaConfig.maxFloatValue, errors);
+
+ std::vector<int64_t> supportedEnumValues;
+ tryParseJsonArrayToVariable(jsonAreaConfig, "supportedEnumValues", /*optional=*/true,
+ &supportedEnumValues, errors);
+ if (!supportedEnumValues.empty()) {
+ areaConfig.supportedEnumValues = std::move(supportedEnumValues);
+ }
+ config->config.areaConfigs.push_back(std::move(areaConfig));
+
+ RawPropValues areaValue = {};
+ if (parsePropValues(jsonAreaConfig, "defaultValue", &areaValue, errors)) {
+ config->initialAreaValues[areaId] = std::move(areaValue);
+ }
+ }
+}
+
+std::optional<ConfigDeclaration> JsonConfigParser::parseEachProperty(
+ const Json::Value& propJsonValue, std::vector<std::string>* errors) {
+ size_t initialErrorCount = errors->size();
+ ConfigDeclaration configDecl = {};
+ int32_t propId;
+
+ if (!tryParseJsonValueToVariable(propJsonValue, "property", /*optional=*/false, &propId,
+ errors)) {
+ return std::nullopt;
+ }
+
+ configDecl.config.prop = propId;
+ std::string propStr = propJsonValue["property"].toStyledString();
+
+ parseAccessChangeMode(propJsonValue, "access", propId, propStr, AccessForVehicleProperty,
+ &configDecl.config.access, errors);
+
+ parseAccessChangeMode(propJsonValue, "changeMode", propId, propStr,
+ ChangeModeForVehicleProperty, &configDecl.config.changeMode, errors);
+
+ tryParseJsonValueToVariable(propJsonValue, "configString", /*optional=*/true,
+ &configDecl.config.configString, errors);
+
+ tryParseJsonArrayToVariable(propJsonValue, "configArray", /*optional=*/true,
+ &configDecl.config.configArray, errors);
+
+ parsePropValues(propJsonValue, "defaultValue", &configDecl.initialValue, errors);
+
+ tryParseJsonValueToVariable(propJsonValue, "minSampleRate", /*optional=*/true,
+ &configDecl.config.minSampleRate, errors);
+
+ tryParseJsonValueToVariable(propJsonValue, "maxSampleRate", /*optional=*/true,
+ &configDecl.config.maxSampleRate, errors);
+
+ parseAreas(propJsonValue, "areas", &configDecl, errors);
+
+ if (errors->size() != initialErrorCount) {
+ return std::nullopt;
+ }
+ return configDecl;
+}
+
+Result<std::unordered_map<int32_t, ConfigDeclaration>> JsonConfigParser::parseJsonConfig(
+ std::istream& is) {
+ Json::CharReaderBuilder builder;
+ Json::Value root;
+ std::unordered_map<int32_t, ConfigDeclaration> configsByPropId;
+ std::string errs;
+ if (!Json::parseFromStream(builder, is, &root, &errs)) {
+ return Error() << "Failed to parse property config file as JSON, error: " << errs;
+ }
+ if (!root.isObject()) {
+ return Error() << "root element must be an object";
+ }
+ if (!root.isMember("properties") || !root["properties"].isArray()) {
+ return Error() << "Missing 'properties' field in root or the field is not an array";
+ }
+ Json::Value properties = root["properties"];
+ std::vector<std::string> errors;
+ for (unsigned int i = 0; i < properties.size(); i++) {
+ if (auto maybeConfig = parseEachProperty(properties[i], &errors); maybeConfig.has_value()) {
+ configsByPropId[maybeConfig.value().config.prop] = std::move(maybeConfig.value());
+ }
+ }
+ if (!errors.empty()) {
+ return Error() << android::base::Join(errors, '\n');
+ }
+ return configsByPropId;
+}
+
+} // namespace jsonconfigloader_impl
+
+JsonConfigLoader::JsonConfigLoader() {
+ mParser = std::make_unique<jsonconfigloader_impl::JsonConfigParser>();
+}
+
+android::base::Result<std::unordered_map<int32_t, ConfigDeclaration>>
+JsonConfigLoader::loadPropConfig(std::istream& is) {
+ return mParser->parseJsonConfig(is);
+}
+
+android::base::Result<std::unordered_map<int32_t, ConfigDeclaration>>
+JsonConfigLoader::loadPropConfig(const std::string& configPath) {
+ std::ifstream ifs(configPath.c_str());
+ if (!ifs) {
+ return android::base::Error() << "couldn't open " << configPath << " for parsing.";
+ }
+
+ return loadPropConfig(ifs);
+}
+
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/test/Android.bp b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/test/Android.bp
new file mode 100644
index 0000000..dae37b9
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/test/Android.bp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+ name: "JsonConfigLoaderUnitTest",
+ vendor: true,
+ srcs: ["*.cpp"],
+ static_libs: [
+ "VehicleHalJsonConfigLoader",
+ "VehicleHalUtils",
+ "libgtest",
+ ],
+ shared_libs: [
+ "libjsoncpp",
+ ],
+ defaults: ["VehicleHalDefaults"],
+ test_suites: ["device-tests"],
+}
+
+cc_test {
+ name: "JsonConfigLoaderUnitTestEnableTestProperties",
+ vendor: true,
+ srcs: ["*.cpp"],
+ static_libs: [
+ "VehicleHalJsonConfigLoaderEnableTestProperties",
+ "VehicleHalUtils",
+ "libgtest",
+ ],
+ shared_libs: [
+ "libjsoncpp",
+ ],
+ defaults: ["VehicleHalDefaults"],
+ test_suites: ["device-tests"],
+}
diff --git a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/test/JsonConfigLoaderUnitTest.cpp b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/test/JsonConfigLoaderUnitTest.cpp
new file mode 100644
index 0000000..9882653
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/test/JsonConfigLoaderUnitTest.cpp
@@ -0,0 +1,705 @@
+/*
+ * Copyright (C) 2022 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 <JsonConfigLoader.h>
+
+#include <PropertyUtils.h>
+
+#include <gtest/gtest.h>
+#include <sstream>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode;
+
+class JsonConfigLoaderUnitTest : public ::testing::Test {
+ protected:
+ JsonConfigLoader mLoader;
+};
+
+TEST_F(JsonConfigLoaderUnitTest, testBasic) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": 291504388
+ }]
+ }
+ )");
+
+ auto result = mLoader.loadPropConfig(iss);
+
+ ASSERT_TRUE(result.ok()) << result.error().message();
+
+ auto configs = result.value();
+ ASSERT_EQ(configs.size(), 1u);
+ ASSERT_EQ(configs.begin()->second.config.prop, 291504388);
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testRootNotObject) {
+ std::istringstream iss(R"(
+ []
+ )");
+
+ ASSERT_FALSE(mLoader.loadPropConfig(iss).ok()) << "root is not an object must cause error";
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testMissingPropertiesField) {
+ std::istringstream iss(R"(
+ {
+ "abcd": 1234
+ }
+ )");
+
+ ASSERT_FALSE(mLoader.loadPropConfig(iss).ok()) << "Missing 'properties' field must cause error";
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testPropertiesFieldNotArray) {
+ std::istringstream iss(R"(
+ {
+ "properties': {'a': 'b'}
+ }
+ )");
+
+ ASSERT_FALSE(mLoader.loadPropConfig(iss).ok())
+ << "'properties' field is not an array must cause error";
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testPropertyIsEnum) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY"
+ }]
+ }
+ )");
+
+ auto result = mLoader.loadPropConfig(iss);
+
+ ASSERT_TRUE(result.ok()) << result.error().message();
+
+ auto configs = result.value();
+ ASSERT_EQ(configs.size(), 1u);
+ ASSERT_EQ(configs.begin()->second.config.prop, toInt(VehicleProperty::INFO_FUEL_CAPACITY));
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testPropertyEnum_FailInvalidEnum) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::BLAH"
+ }]
+ }
+ )");
+
+ ASSERT_FALSE(mLoader.loadPropConfig(iss).ok())
+ << "Invalid VehicleProperty enum must cause error";
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testPropertyEnum_FailInvalidType) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "test"
+ }]
+ }
+ )");
+
+ ASSERT_FALSE(mLoader.loadPropConfig(iss).ok())
+ << "Invalid VehicleProperty type must cause error";
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testProperty_FailInvalidJson) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ }
+ )");
+
+ ASSERT_FALSE(mLoader.loadPropConfig(iss).ok()) << "Invalid JSON format must cause error";
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testConfigArray) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY",
+ "configArray": [1, 2, 3]
+ }]
+ }
+ )");
+
+ auto result = mLoader.loadPropConfig(iss);
+
+ ASSERT_TRUE(result.ok()) << result.error().message();
+
+ auto configs = result.value();
+ ASSERT_EQ(configs.size(), 1u);
+ ASSERT_EQ(configs.begin()->second.config.configArray, std::vector<int>({1, 2, 3}));
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testConfigArrayConstants) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY",
+ "configArray": [1, 2, "Constants::FUEL_DOOR_REAR_LEFT"]
+ }]
+ }
+ )");
+
+ auto result = mLoader.loadPropConfig(iss);
+
+ ASSERT_TRUE(result.ok()) << result.error().message();
+
+ auto configs = result.value();
+ ASSERT_EQ(configs.size(), 1u);
+ ASSERT_EQ(configs.begin()->second.config.configArray,
+ std::vector<int>({1, 2, FUEL_DOOR_REAR_LEFT}));
+}
+
+// We have special logic to deal with GALLON and US_GALLON since they share the same value.
+TEST_F(JsonConfigLoaderUnitTest, testConfigArrayUnitGallon) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY",
+ "configArray": [1, 2, "VehicleUnit::GALLON"]
+ }]
+ }
+ )");
+
+ auto result = mLoader.loadPropConfig(iss);
+
+ ASSERT_TRUE(result.ok()) << result.error().message();
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testConfigArrayUnitUsGallon) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY",
+ "configArray": [1, 2, "VehicleUnit::US_GALLON"]
+ }]
+ }
+ )");
+
+ auto result = mLoader.loadPropConfig(iss);
+
+ ASSERT_TRUE(result.ok()) << result.error().message();
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testConfigArray_FailInvalidEnum) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY",
+ "configArray": [1, 2, "VehicleUnits::BLAH"]
+ }]
+ }
+ )");
+
+ ASSERT_FALSE(mLoader.loadPropConfig(iss).ok())
+ << "Invalid enum in ConfigArray must cause error";
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testConfigArray_FailNotArray) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY",
+ "configArray": "123"
+ }]
+ }
+ )");
+
+ ASSERT_FALSE(mLoader.loadPropConfig(iss).ok())
+ << "ConfigArray is not an array must cause error";
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testConfigString) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY",
+ "configString": "test"
+ }]
+ }
+ )");
+
+ auto result = mLoader.loadPropConfig(iss);
+
+ ASSERT_TRUE(result.ok()) << result.error().message();
+
+ auto configs = result.value();
+ ASSERT_EQ(configs.size(), 1u);
+ ASSERT_EQ(configs.begin()->second.config.configString, "test");
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testConfigString_FailNotString) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY",
+ "configString": 1234
+ }]
+ }
+ )");
+
+ ASSERT_FALSE(mLoader.loadPropConfig(iss).ok())
+ << "ConfigString is not a String must cause error";
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testCheckDefaultAccessChangeMode) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY"
+ }]
+ }
+ )");
+
+ auto result = mLoader.loadPropConfig(iss);
+
+ ASSERT_TRUE(result.ok()) << result.error().message();
+ auto configs = result.value();
+ ASSERT_EQ(configs.size(), 1u);
+
+ const VehiclePropConfig& propConfig = configs.begin()->second.config;
+ ASSERT_EQ(propConfig.access, VehiclePropertyAccess::READ);
+ ASSERT_EQ(propConfig.changeMode, VehiclePropertyChangeMode::STATIC);
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testAccessOverride) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY",
+ "access": "VehiclePropertyAccess::WRITE"
+ }]
+ }
+ )");
+
+ auto result = mLoader.loadPropConfig(iss);
+
+ ASSERT_TRUE(result.ok()) << result.error().message();
+ auto configs = result.value();
+ ASSERT_EQ(configs.size(), 1u);
+
+ const VehiclePropConfig& propConfig = configs.begin()->second.config;
+ ASSERT_EQ(propConfig.access, VehiclePropertyAccess::WRITE);
+ ASSERT_EQ(propConfig.changeMode, VehiclePropertyChangeMode::STATIC);
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testChangeModeOverride) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY",
+ "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
+ }]
+ }
+ )");
+
+ auto result = mLoader.loadPropConfig(iss);
+
+ ASSERT_TRUE(result.ok()) << result.error().message();
+ auto configs = result.value();
+ ASSERT_EQ(configs.size(), 1u);
+
+ const VehiclePropConfig& propConfig = configs.begin()->second.config;
+ ASSERT_EQ(propConfig.access, VehiclePropertyAccess::READ);
+ ASSERT_EQ(propConfig.changeMode, VehiclePropertyChangeMode::ON_CHANGE);
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testCustomProp) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": 1234,
+ "access": "VehiclePropertyAccess::WRITE",
+ "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
+ }]
+ }
+ )");
+
+ auto result = mLoader.loadPropConfig(iss);
+
+ ASSERT_TRUE(result.ok()) << result.error().message();
+ auto configs = result.value();
+ ASSERT_EQ(configs.size(), 1u);
+
+ const VehiclePropConfig& propConfig = configs.begin()->second.config;
+ ASSERT_EQ(propConfig.access, VehiclePropertyAccess::WRITE);
+ ASSERT_EQ(propConfig.changeMode, VehiclePropertyChangeMode::ON_CHANGE);
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testCustomProp_FailMissingAccess) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": 1234,
+ "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
+ }]
+ }
+ )");
+
+ ASSERT_FALSE(mLoader.loadPropConfig(iss).ok())
+ << "Missing access for custom property must cause error";
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testCustomProp_FailMissingChangeMode) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": 1234,
+ "access": "VehiclePropertyAccess::WRITE"
+ }]
+ }
+ )");
+
+ ASSERT_FALSE(mLoader.loadPropConfig(iss).ok())
+ << "Missing change mode for custom property must cause error";
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testMinSampleRate) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY",
+ "minSampleRate": 1,
+ }]
+ }
+ )");
+
+ auto result = mLoader.loadPropConfig(iss);
+
+ ASSERT_TRUE(result.ok()) << result.error().message();
+
+ auto configs = result.value();
+ ASSERT_EQ(configs.size(), 1u);
+ ASSERT_EQ(configs.begin()->second.config.minSampleRate, 1);
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testMinSampleRate_FailInvalidType) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY",
+ "minSampleRate": "abcd",
+ }]
+ }
+ )");
+
+ ASSERT_FALSE(mLoader.loadPropConfig(iss).ok())
+ << "Wrong type for MinSampleRate must cause error";
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testMaxSampleRate) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY",
+ "maxSampleRate": 1,
+ }]
+ }
+ )");
+
+ auto result = mLoader.loadPropConfig(iss);
+
+ ASSERT_TRUE(result.ok()) << result.error().message();
+
+ auto configs = result.value();
+ ASSERT_EQ(configs.size(), 1u);
+ ASSERT_EQ(configs.begin()->second.config.maxSampleRate, 1);
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testMaxSampleRate_FailInvalidType) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY",
+ "maxSampleRate": "abcd",
+ }]
+ }
+ )");
+
+ ASSERT_FALSE(mLoader.loadPropConfig(iss).ok())
+ << "Wrong type for MaxSampleRate must cause error";
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testDefaultValue_Simple) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY",
+ "defaultValue": {
+ "int32Values": [1, 2]
+ }
+ }]
+ }
+ )");
+
+ auto result = mLoader.loadPropConfig(iss);
+
+ ASSERT_TRUE(result.ok()) << result.error().message();
+
+ auto configs = result.value();
+ ASSERT_EQ(configs.size(), 1u);
+ ASSERT_EQ(configs.begin()->second.initialValue.int32Values, std::vector<int32_t>({1, 2}));
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testDefaultValue_Mixed) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY",
+ "defaultValue": {
+ "int32Values": [1, "Constants::FUEL_DOOR_REAR_LEFT"],
+ "int64Values": [2, "Constants::FUEL_DOOR_REAR_LEFT"],
+ "floatValues": [3.0, "Constants::FUEL_DOOR_REAR_LEFT"],
+ "stringValue": "abcd"
+ }
+ }]
+ }
+ )");
+
+ auto result = mLoader.loadPropConfig(iss);
+
+ ASSERT_TRUE(result.ok()) << result.error().message();
+
+ auto configs = result.value();
+ ASSERT_EQ(configs.size(), 1u);
+
+ const RawPropValues& initialValue = configs.begin()->second.initialValue;
+ ASSERT_EQ(initialValue.int32Values, std::vector<int32_t>({1, FUEL_DOOR_REAR_LEFT}));
+ ASSERT_EQ(initialValue.int64Values,
+ std::vector<int64_t>({2, static_cast<int64_t>(FUEL_DOOR_REAR_LEFT)}));
+ ASSERT_EQ(initialValue.floatValues,
+ std::vector<float>({3.0, static_cast<float>(FUEL_DOOR_REAR_LEFT)}));
+ ASSERT_EQ(initialValue.stringValue, "abcd");
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testDefaultValue_FailNotObject) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY",
+ "defaultValue": []
+ }]
+ }
+ )");
+
+ ASSERT_FALSE(mLoader.loadPropConfig(iss).ok())
+ << "DefaultValue is not an object must cause error";
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testDefaultValue_FailInvalidType) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY",
+ "defaultValue": {
+ "int32Values": [1.1]
+ }
+ }]
+ }
+ )");
+
+ ASSERT_FALSE(mLoader.loadPropConfig(iss).ok())
+ << "Wrong type for DefaultValue must cause error";
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testAreas_Simple) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY",
+ "areas": [{
+ "areaId": "Constants::HVAC_ALL",
+ "minInt32Value": 1,
+ "maxInt32Value": 7
+ }]
+ }]
+ }
+ )");
+
+ auto result = mLoader.loadPropConfig(iss);
+
+ auto configs = result.value();
+ ASSERT_EQ(configs.size(), 1u);
+
+ const VehiclePropConfig& config = configs.begin()->second.config;
+ ASSERT_EQ(config.areaConfigs.size(), 1u);
+ const VehicleAreaConfig& areaConfig = config.areaConfigs[0];
+ ASSERT_EQ(areaConfig.minInt32Value, 1);
+ ASSERT_EQ(areaConfig.maxInt32Value, 7);
+ ASSERT_EQ(areaConfig.areaId, HVAC_ALL);
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testAreas_DefaultValueForEachArea) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY",
+ "areas": [{
+ "areaId": "Constants::HVAC_LEFT",
+ "defaultValue": {
+ "int32Values": [1]
+ }
+ }, {
+ "areaId": "Constants::HVAC_RIGHT",
+ "defaultValue": {
+ "int32Values": [2]
+ }
+ }]
+ }]
+ }
+ )");
+
+ auto result = mLoader.loadPropConfig(iss);
+
+ auto configs = result.value();
+ ASSERT_EQ(configs.size(), 1u);
+
+ const VehiclePropConfig& config = configs.begin()->second.config;
+ ASSERT_EQ(config.areaConfigs.size(), 2u);
+ ASSERT_EQ(config.areaConfigs[0].areaId, HVAC_LEFT);
+ ASSERT_EQ(config.areaConfigs[1].areaId, HVAC_RIGHT);
+ ASSERT_EQ(configs.begin()->second.initialAreaValues[HVAC_LEFT],
+ RawPropValues{.int32Values = {1}});
+ ASSERT_EQ(configs.begin()->second.initialAreaValues[HVAC_RIGHT],
+ RawPropValues{.int32Values = {2}});
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testAreas_FailInvalidTypeForOneAreaValue) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY",
+ "areas": [{
+ "areaId": "Constants::HVAC_LEFT",
+ "defaultValue": {
+ "int32Values": [1]
+ }
+ }, {
+ "areaId": "Constants::HVAC_RIGHT",
+ "defaultValue": {
+ "int32Values": [2.1]
+ }
+ }]
+ }]
+ }
+ )");
+
+ ASSERT_FALSE(mLoader.loadPropConfig(iss).ok())
+ << "Wrong type for DefaultValue for one area must cause error";
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testAreas_HandlesNoSupportedEnumValuesDeclared) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::CABIN_LIGHTS_STATE",
+ "areas": [{
+ "areaId": 0,
+ }]
+ }]
+ }
+ )");
+
+ auto result = mLoader.loadPropConfig(iss);
+ ASSERT_TRUE(result.ok());
+
+ auto configs = result.value();
+ ASSERT_EQ(configs.size(), 1u);
+
+ const VehiclePropConfig& config = configs.begin()->second.config;
+ ASSERT_EQ(config.areaConfigs.size(), 1u);
+
+ const VehicleAreaConfig& areaConfig = config.areaConfigs[0];
+ ASSERT_EQ(areaConfig.areaId, 0);
+ ASSERT_FALSE(areaConfig.supportedEnumValues);
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testAreas_HandlesSupportedEnumValues) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::CABIN_LIGHTS_STATE",
+ "areas": [{
+ "areaId": 0,
+ "supportedEnumValues": ["Constants::LIGHT_STATE_ON", "Constants::LIGHT_STATE_OFF"]
+ }]
+ }]
+ }
+ )");
+
+ auto result = mLoader.loadPropConfig(iss);
+ ASSERT_TRUE(result.ok());
+
+ auto configs = result.value();
+ ASSERT_EQ(configs.size(), 1u);
+
+ const VehiclePropConfig& config = configs.begin()->second.config;
+ ASSERT_EQ(config.areaConfigs.size(), 1u);
+
+ const VehicleAreaConfig& areaConfig = config.areaConfigs[0];
+ ASSERT_EQ(areaConfig.areaId, 0);
+ ASSERT_TRUE(areaConfig.supportedEnumValues);
+ ASSERT_EQ(areaConfig.supportedEnumValues.value().size(), 2u);
+ ASSERT_EQ(areaConfig.supportedEnumValues.value(),
+ std::vector<int64_t>({LIGHT_STATE_ON, LIGHT_STATE_OFF}));
+}
+
+TEST_F(JsonConfigLoaderUnitTest, testAreas_HandlesEmptySupportedEnumValues) {
+ std::istringstream iss(R"(
+ {
+ "properties": [{
+ "property": "VehicleProperty::CABIN_LIGHTS_STATE",
+ "areas": [{
+ "areaId": 0,
+ "supportedEnumValues": []
+ }]
+ }]
+ }
+ )");
+
+ auto result = mLoader.loadPropConfig(iss);
+ ASSERT_TRUE(result.ok());
+
+ auto configs = result.value();
+ ASSERT_EQ(configs.size(), 1u);
+
+ const VehiclePropConfig& config = configs.begin()->second.config;
+ ASSERT_EQ(config.areaConfigs.size(), 1u);
+
+ const VehicleAreaConfig& areaConfig = config.areaConfigs[0];
+ ASSERT_EQ(areaConfig.areaId, 0);
+ ASSERT_FALSE(areaConfig.supportedEnumValues);
+}
+
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/aidl/impl/default_config/config/Android.bp b/automotive/vehicle/aidl/impl/default_config/config/Android.bp
new file mode 100644
index 0000000..8f1c7d1
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/default_config/config/Android.bp
@@ -0,0 +1,47 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+filegroup {
+ name: "VehicleHalDefaultProperties_JSON",
+ srcs: ["DefaultProperties.json"],
+}
+
+filegroup {
+ name: "VehicleHalTestProperties_JSON",
+ srcs: ["TestProperties.json"],
+}
+
+filegroup {
+ name: "VehicleHalVendorClusterTestProperties_JSON",
+ srcs: ["VendorClusterTestProperties.json"],
+}
+
+prebuilt_etc {
+ name: "Prebuilt_VehicleHalDefaultProperties_JSON",
+ filename_from_src: true,
+ src: "DefaultProperties.json",
+ sub_dir: "automotive/vhalconfig/",
+ vendor: true,
+}
+
+prebuilt_etc {
+ name: "Prebuilt_VehicleHalTestProperties_JSON",
+ filename_from_src: true,
+ src: "TestProperties.json",
+ sub_dir: "automotive/vhalconfig/",
+ vendor: true,
+}
+
+prebuilt_etc {
+ name: "Prebuilt_VehicleHalVendorClusterTestProperties_JSON",
+ filename_from_src: true,
+ src: "VendorClusterTestProperties.json",
+ sub_dir: "automotive/vhalconfig/",
+ vendor: true,
+}
diff --git a/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json b/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
new file mode 100644
index 0000000..5503de2
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
@@ -0,0 +1,3831 @@
+{
+ "apiVersion": 1,
+ "properties": [
+ {
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY",
+ "defaultValue": {
+ "floatValues": [
+ 15000.0
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::INFO_FUEL_TYPE",
+ "defaultValue": {
+ "int32Values": [
+ "FuelType::FUEL_TYPE_UNLEADED"
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::INFO_EV_BATTERY_CAPACITY",
+ "defaultValue": {
+ "floatValues": [
+ 150000.0
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::INFO_EV_CONNECTOR_TYPE",
+ "defaultValue": {
+ "int32Values": [
+ "EvConnectorType::IEC_TYPE_1_AC"
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::INFO_FUEL_DOOR_LOCATION",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::FUEL_DOOR_REAR_LEFT"
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::INFO_EV_PORT_LOCATION",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::CHARGE_PORT_FRONT_LEFT"
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::INFO_MULTI_EV_PORT_LOCATIONS",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::CHARGE_PORT_FRONT_LEFT",
+ "Constants::CHARGE_PORT_REAR_LEFT"
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::INFO_VIN",
+ "defaultValue": {
+ "stringValue": "1GCARVIN123456789"
+ }
+ },
+ {
+ "property": "VehicleProperty::INFO_MAKE",
+ "defaultValue": {
+ "stringValue": "Toy Vehicle"
+ }
+ },
+ {
+ "property": "VehicleProperty::INFO_MODEL",
+ "defaultValue": {
+ "stringValue": "Speedy Model"
+ }
+ },
+ {
+ "property": "VehicleProperty::INFO_MODEL_YEAR",
+ "defaultValue": {
+ "int32Values": [
+ 2023
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::INFO_EXTERIOR_DIMENSIONS",
+ "defaultValue": {
+ "int32Values": [
+ 1776,
+ 4950,
+ 2008,
+ 2140,
+ 2984,
+ 1665,
+ 1667,
+ 11800
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::PERF_VEHICLE_SPEED",
+ "defaultValue": {
+ "floatValues": [
+ 0.0
+ ]
+ },
+ "maxSampleRate": 10.0,
+ "minSampleRate": 1.0
+ },
+ {
+ "property": "VehicleProperty::PERF_VEHICLE_SPEED_DISPLAY",
+ "defaultValue": {
+ "floatValues": [
+ 0.0
+ ]
+ },
+ "maxSampleRate": 10.0,
+ "minSampleRate": 1.0
+ },
+ {
+ "property": "VehicleProperty::VEHICLE_SPEED_DISPLAY_UNITS",
+ "defaultValue": {
+ "int32Values": [
+ "VehicleUnit::MILES_PER_HOUR"
+ ]
+ },
+ "configArray": [
+ "VehicleUnit::METER_PER_SEC",
+ "VehicleUnit::MILES_PER_HOUR",
+ "VehicleUnit::KILOMETERS_PER_HOUR"
+ ]
+ },
+ {
+ "property": "VehicleProperty::EV_BATTERY_DISPLAY_UNITS",
+ "defaultValue": {
+ "int32Values": [
+ "VehicleUnit::KILOWATT_HOUR"
+ ]
+ },
+ "configArray": [
+ "VehicleUnit::WATT_HOUR",
+ "VehicleUnit::AMPERE_HOURS",
+ "VehicleUnit::KILOWATT_HOUR"
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_MEMORY_SELECT",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": 0,
+ "maxInt32Value": 3
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": 0,
+ "maxInt32Value": 3
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": 0,
+ "maxInt32Value": 3
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": 0,
+ "maxInt32Value": 3
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_MEMORY_SET",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": 0,
+ "maxInt32Value": 3
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": 0,
+ "maxInt32Value": 3
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": 0,
+ "maxInt32Value": 3
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": 0,
+ "maxInt32Value": 3
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_BELT_BUCKLED",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_BELT_HEIGHT_POS",
+ "defaultValue": {
+ "int32Values": [
+ 10
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": 0,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": 0,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": 0,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": 0,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": 0,
+ "maxInt32Value": 10
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_BELT_HEIGHT_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_FORE_AFT_POS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_FORE_AFT_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_BACKREST_ANGLE_1_POS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_BACKREST_ANGLE_1_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_BACKREST_ANGLE_2_POS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_BACKREST_ANGLE_2_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_HEIGHT_POS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_HEIGHT_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_DEPTH_POS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_DEPTH_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_TILT_POS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_TILT_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_LUMBAR_FORE_AFT_POS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_LUMBAR_FORE_AFT_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_LUMBAR_SIDE_SUPPORT_POS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_LUMBAR_SIDE_SUPPORT_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_HEADREST_HEIGHT_POS_V2",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": 0,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": 0,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": 0,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": 0,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": 0,
+ "maxInt32Value": 10
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_HEADREST_HEIGHT_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_HEADREST_ANGLE_POS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_HEADREST_ANGLE_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_HEADREST_FORE_AFT_POS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_HEADREST_FORE_AFT_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_FOOTWELL_LIGHTS_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::LIGHT_STATE_OFF"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "supportedEnumValues": [
+ "Constants::LIGHT_STATE_OFF",
+ "Constants::LIGHT_STATE_ON"
+ ]
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "supportedEnumValues": [
+ "Constants::LIGHT_STATE_OFF",
+ "Constants::LIGHT_STATE_ON"
+ ]
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT_2_RIGHT_2_CENTER",
+ "supportedEnumValues": [
+ "Constants::LIGHT_STATE_OFF",
+ "Constants::LIGHT_STATE_ON"
+ ]
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_FOOTWELL_LIGHTS_SWITCH",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::LIGHT_SWITCH_OFF"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "supportedEnumValues": [
+ "Constants::LIGHT_SWITCH_OFF",
+ "Constants::LIGHT_SWITCH_ON",
+ "Constants::LIGHT_SWITCH_AUTO"
+ ]
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "supportedEnumValues": [
+ "Constants::LIGHT_SWITCH_OFF",
+ "Constants::LIGHT_SWITCH_ON",
+ "Constants::LIGHT_SWITCH_AUTO"
+ ]
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT_2_RIGHT_2_CENTER",
+ "supportedEnumValues": [
+ "Constants::LIGHT_SWITCH_OFF",
+ "Constants::LIGHT_SWITCH_ON",
+ "Constants::LIGHT_SWITCH_AUTO"
+ ]
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_EASY_ACCESS_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_AIRBAG_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_CUSHION_SIDE_SUPPORT_POS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_CUSHION_SIDE_SUPPORT_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_LUMBAR_VERTICAL_POS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_LUMBAR_VERTICAL_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_WALK_IN_POS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": 0,
+ "maxInt32Value": 5
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": 0,
+ "maxInt32Value": 5
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_OCCUPANCY",
+ "defaultValue": {
+ "int32Values": [
+ "VehicleSeatOccupancyState::VACANT"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::INFO_DRIVER_SEAT",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::SEAT_1_LEFT"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::PERF_ODOMETER",
+ "defaultValue": {
+ "floatValues": [
+ 0.0
+ ]
+ },
+ "maxSampleRate": 10.0,
+ "minSampleRate": 1.0
+ },
+ {
+ "property": "VehicleProperty::PERF_STEERING_ANGLE",
+ "defaultValue": {
+ "floatValues": [
+ 0.0
+ ]
+ },
+ "maxSampleRate": 10.0,
+ "minSampleRate": 1.0
+ },
+ {
+ "property": "VehicleProperty::PERF_REAR_STEERING_ANGLE",
+ "defaultValue": {
+ "floatValues": [
+ 0.0
+ ]
+ },
+ "maxSampleRate": 10.0,
+ "minSampleRate": 1.0
+ },
+ {
+ "property": "VehicleProperty::ENGINE_RPM",
+ "defaultValue": {
+ "floatValues": [
+ 0.0
+ ]
+ },
+ "maxSampleRate": 10.0,
+ "minSampleRate": 1.0
+ },
+ {
+ "property": "VehicleProperty::FUEL_LEVEL",
+ "defaultValue": {
+ "floatValues": [
+ 15000.0
+ ]
+ },
+ "maxSampleRate": 100.0,
+ "minSampleRate": 1.0
+ },
+ {
+ "property": "VehicleProperty::FUEL_DOOR_OPEN",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::EV_BATTERY_LEVEL",
+ "defaultValue": {
+ "floatValues": [
+ 150000.0
+ ]
+ },
+ "maxSampleRate": 100.0,
+ "minSampleRate": 1.0
+ },
+ {
+ "property": "VehicleProperty::EV_CURRENT_BATTERY_CAPACITY",
+ "defaultValue": {
+ "floatValues": [
+ 150000.0
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::EV_CHARGE_PORT_OPEN",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::EV_CHARGE_PORT_CONNECTED",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::EV_BATTERY_INSTANTANEOUS_CHARGE_RATE",
+ "defaultValue": {
+ "floatValues": [
+ 0.0
+ ]
+ },
+ "maxSampleRate": 10.0,
+ "minSampleRate": 1.0
+ },
+ {
+ "property": "VehicleProperty::EV_CHARGE_CURRENT_DRAW_LIMIT",
+ "defaultValue": {
+ "floatValues": [
+ 12.5
+ ]
+ },
+ "comment": "ConfigArray specifies Max current draw allowed by vehicle in amperes",
+ "configArray": [
+ 20
+ ]
+ },
+ {
+ "property": "VehicleProperty::EV_CHARGE_PERCENT_LIMIT",
+ "defaultValue": {
+ "floatValues": [
+ 40.0
+ ]
+ },
+ "configArray": [
+ 20,
+ 40,
+ 60,
+ 80,
+ 100
+ ]
+ },
+ {
+ "property": "VehicleProperty::EV_CHARGE_STATE",
+ "defaultValue": {
+ "int32Values": [
+ 2
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::EV_CHARGE_SWITCH",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::EV_CHARGE_TIME_REMAINING",
+ "defaultValue": {
+ "int32Values": [
+ 20
+ ]
+ },
+ "maxSampleRate": 10.0,
+ "minSampleRate": 1.0
+ },
+ {
+ "property": "VehicleProperty::EV_REGENERATIVE_BRAKING_STATE",
+ "defaultValue": {
+ "int32Values": [
+ 2
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::TRAILER_PRESENT",
+ "defaultValue": {
+ "int32Values": [
+ 2
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::VEHICLE_CURB_WEIGHT",
+ "defaultValue": {
+ "int32Values": [
+ 2211
+ ]
+ },
+ "configArray": [
+ 2948
+ ],
+ "comment": "unit is kg"
+ },
+ {
+ "property": "VehicleProperty::RANGE_REMAINING",
+ "defaultValue": {
+ "floatValues": [
+ 50000.0
+ ]
+ },
+ "comment": "units in meter",
+ "maxSampleRate": 2.0,
+ "minSampleRate": 1.0
+ },
+ {
+ "property": "VehicleProperty::TIRE_PRESSURE",
+ "defaultValue": {
+ "floatValues": [
+ 200.0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::WHEEL_FRONT_LEFT",
+ "minFloatValue": 193.0,
+ "maxFloatValue": 300.0
+ },
+ {
+ "areaId": "Constants::WHEEL_FRONT_RIGHT",
+ "minFloatValue": 193.0,
+ "maxFloatValue": 300.0
+ },
+ {
+ "areaId": "Constants::WHEEL_REAR_LEFT",
+ "minFloatValue": 193.0,
+ "maxFloatValue": 300.0
+ },
+ {
+ "areaId": "Constants::WHEEL_REAR_RIGHT",
+ "minFloatValue": 193.0,
+ "maxFloatValue": 300.0
+ }
+ ],
+ "comment": "Units in kpa",
+ "maxSampleRate": 2.0,
+ "minSampleRate": 1.0
+ },
+ {
+ "property": "VehicleProperty::CRITICALLY_LOW_TIRE_PRESSURE",
+ "areas": [
+ {
+ "defaultValue": {
+ "floatValues": [
+ 137.0
+ ]
+ },
+ "areaId": "Constants::WHEEL_FRONT_LEFT"
+ },
+ {
+ "defaultValue": {
+ "floatValues": [
+ 137.0
+ ]
+ },
+ "areaId": "Constants::WHEEL_FRONT_RIGHT"
+ },
+ {
+ "defaultValue": {
+ "floatValues": [
+ 137.0
+ ]
+ },
+ "areaId": "Constants::WHEEL_REAR_RIGHT"
+ },
+ {
+ "defaultValue": {
+ "floatValues": [
+ 137.0
+ ]
+ },
+ "areaId": "Constants::WHEEL_REAR_LEFT"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::TIRE_PRESSURE_DISPLAY_UNITS",
+ "defaultValue": {
+ "int32Values": [
+ "VehicleUnit::PSI"
+ ]
+ },
+ "configArray": [
+ "VehicleUnit::KILOPASCAL",
+ "VehicleUnit::PSI",
+ "VehicleUnit::BAR"
+ ]
+ },
+ {
+ "property": "VehicleProperty::CURRENT_GEAR",
+ "defaultValue": {
+ "int32Values": [
+ "VehicleGear::GEAR_PARK"
+ ]
+ },
+ "configArray": [
+ "VehicleGear::GEAR_PARK",
+ "VehicleGear::GEAR_NEUTRAL",
+ "VehicleGear::GEAR_REVERSE",
+ "VehicleGear::GEAR_1",
+ "VehicleGear::GEAR_2",
+ "VehicleGear::GEAR_3",
+ "VehicleGear::GEAR_4",
+ "VehicleGear::GEAR_5"
+ ]
+ },
+ {
+ "property": "VehicleProperty::PARKING_BRAKE_ON",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::PARKING_BRAKE_AUTO_APPLY",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::EV_BRAKE_REGENERATION_LEVEL",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "minInt32Value": 0,
+ "maxInt32Value": 3
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::EV_STOPPING_MODE",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::EV_STOPPING_MODE_CREEP"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "supportedEnumValues": [
+ "Constants::EV_STOPPING_MODE_CREEP",
+ "Constants::EV_STOPPING_MODE_ROLL",
+ "Constants::EV_STOPPING_MODE_HOLD"
+ ]
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::FUEL_LEVEL_LOW",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::FUEL_VOLUME_DISPLAY_UNITS",
+ "defaultValue": {
+ "int32Values": [
+ "VehicleUnit::US_GALLON"
+ ]
+ },
+ "configArray": [
+ "VehicleUnit::LITER",
+ "VehicleUnit::US_GALLON"
+ ]
+ },
+ {
+ "property": "VehicleProperty::FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::HW_KEY_INPUT",
+ "defaultValue": {
+ "int32Values": [
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::HW_KEY_INPUT_V2",
+ "defaultValue": {
+ "int32Values": [
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "int64Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::HW_MOTION_INPUT",
+ "defaultValue": {
+ "int32Values": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0
+ ],
+ "floatValues": [
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "int64Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::HW_ROTARY_INPUT",
+ "defaultValue": {
+ "int32Values": [
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::HW_CUSTOM_INPUT",
+ "defaultValue": {
+ "int32Values": [
+ 0,
+ 0,
+ 0
+ ]
+ },
+ "configArray": [
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "property": "VehicleProperty::HVAC_ACTUAL_FAN_SPEED_RPM",
+ "defaultValue": {
+ "int32Values": [
+ 50
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::HVAC_POWER_ON",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER"
+ }
+ ],
+ "configArray": [
+ "VehicleProperty::HVAC_FAN_SPEED",
+ "VehicleProperty::HVAC_FAN_DIRECTION"
+ ]
+ },
+ {
+ "property": "VehicleProperty::HVAC_DEFROSTER",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "VehicleAreaWindow::FRONT_WINDSHIELD"
+ },
+ {
+ "areaId": "VehicleAreaWindow::REAR_WINDSHIELD"
+ }
+ ],
+ "comment": "0 means using for all areas"
+ },
+ {
+ "property": "VehicleProperty::HVAC_ELECTRIC_DEFROSTER_ON",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "VehicleAreaWindow::FRONT_WINDSHIELD"
+ },
+ {
+ "areaId": "VehicleAreaWindow::REAR_WINDSHIELD"
+ }
+ ],
+ "comment": "0 means using for all areas"
+ },
+ {
+ "property": "VehicleProperty::HVAC_MAX_DEFROST_ON",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::HVAC_RECIRC_ON",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::HVAC_AUTO_RECIRC_ON",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::HVAC_AC_ON",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::HVAC_MAX_AC_ON",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::HVAC_AUTO_ON",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::HVAC_DUAL_ON",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::HVAC_ALL"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::HVAC_FAN_SPEED",
+ "defaultValue": {
+ "int32Values": [
+ 3
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": 1,
+ "maxInt32Value": 7
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": 1,
+ "maxInt32Value": 7
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": 1,
+ "maxInt32Value": 7
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": 1,
+ "maxInt32Value": 7
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": 1,
+ "maxInt32Value": 7
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::HVAC_FAN_DIRECTION",
+ "defaultValue": {
+ "int32Values": [
+ "VehicleHvacFanDirection::FACE"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::HVAC_FAN_DIRECTION_AVAILABLE",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::FAN_DIRECTION_UNKNOWN",
+ "Constants::FAN_DIRECTION_FACE",
+ "Constants::FAN_DIRECTION_FLOOR",
+ "Constants::FAN_DIRECTION_FACE_FLOOR",
+ "Constants::FAN_DIRECTION_DEFROST",
+ "Constants::FAN_DIRECTION_FACE_DEFROST",
+ "Constants::FAN_DIRECTION_FLOOR_DEFROST",
+ "Constants::FAN_DIRECTION_FLOOR_DEFROST_FACE"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::HVAC_SEAT_VENTILATION",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": 0,
+ "maxInt32Value": 3
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": 0,
+ "maxInt32Value": 3
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": 0,
+ "maxInt32Value": 3
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": 0,
+ "maxInt32Value": 3
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": 0,
+ "maxInt32Value": 3
+ }
+ ],
+ "comment": "0 is off and +ve values indicate ventilation level."
+ },
+ {
+ "property": "VehicleProperty::HVAC_STEERING_WHEEL_HEAT",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "minInt32Value": -2,
+ "maxInt32Value": 2
+ }
+ ],
+ "comment": "+ve values for heating and -ve for cooling"
+ },
+ {
+ "property": "VehicleProperty::HVAC_SEAT_TEMPERATURE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -2,
+ "maxInt32Value": 2
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -2,
+ "maxInt32Value": 2
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -2,
+ "maxInt32Value": 2
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -2,
+ "maxInt32Value": 2
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -2,
+ "maxInt32Value": 2
+ }
+ ],
+ "comment": "+ve values for heating and -ve for cooling"
+ },
+ {
+ "property": "VehicleProperty::HVAC_SIDE_MIRROR_HEAT",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::MIRROR_DRIVER_LEFT_RIGHT",
+ "minInt32Value": 0,
+ "maxInt32Value": 2
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::HVAC_TEMPERATURE_CURRENT",
+ "defaultValue": {
+ "floatValues": [
+ 19.1
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::HVAC_TEMPERATURE_SET",
+ "defaultValue": {
+ "floatValues": [
+ 17.0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minFloatValue": 16.0,
+ "maxFloatValue": 28.0
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minFloatValue": 16.0,
+ "maxFloatValue": 28.0
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minFloatValue": 16.0,
+ "maxFloatValue": 28.0
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minFloatValue": 16.0,
+ "maxFloatValue": 28.0
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minFloatValue": 16.0,
+ "maxFloatValue": 28.0
+ }
+ ],
+ "comment":
+ "minFloatValue and maxFloatValue in area config should match corresponding values in configArray",
+ "configArray": [
+ 160,
+ 280,
+ 5,
+ 600,
+ 840,
+ 10
+ ]
+ },
+ {
+ "property": "VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION",
+ "defaultValue": {
+ "floatValues": [
+ 66.19999694824219,
+ "VehicleUnit::FAHRENHEIT",
+ 19.0,
+ 66.0
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::ENV_OUTSIDE_TEMPERATURE",
+ "defaultValue": {
+ "floatValues": [
+ 25.0
+ ]
+ },
+ "maxSampleRate": 2.0,
+ "minSampleRate": 1.0
+ },
+ {
+ "property": "VehicleProperty::HVAC_TEMPERATURE_DISPLAY_UNITS",
+ "defaultValue": {
+ "int32Values": [
+ "VehicleUnit::FAHRENHEIT"
+ ]
+ },
+ "configArray": [
+ "VehicleUnit::FAHRENHEIT",
+ "VehicleUnit::CELSIUS"
+ ]
+ },
+ {
+ "property": "VehicleProperty::DISTANCE_DISPLAY_UNITS",
+ "defaultValue": {
+ "int32Values": [
+ "VehicleUnit::MILE"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0
+ }
+ ],
+ "configArray": [
+ "VehicleUnit::KILOMETER",
+ "VehicleUnit::MILE"
+ ]
+ },
+ {
+ "property": "VehicleProperty::NIGHT_MODE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::GEAR_SELECTION",
+ "defaultValue": {
+ "int32Values": [
+ "VehicleGear::GEAR_PARK"
+ ]
+ },
+ "configArray": [
+ "VehicleGear::GEAR_PARK",
+ "VehicleGear::GEAR_NEUTRAL",
+ "VehicleGear::GEAR_REVERSE",
+ "VehicleGear::GEAR_DRIVE",
+ "VehicleGear::GEAR_1",
+ "VehicleGear::GEAR_2",
+ "VehicleGear::GEAR_3",
+ "VehicleGear::GEAR_4",
+ "VehicleGear::GEAR_5"
+ ]
+ },
+ {
+ "property": "VehicleProperty::TURN_SIGNAL_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "VehicleTurnSignal::NONE"
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::IGNITION_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "VehicleIgnitionState::ON"
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::ENGINE_COOLANT_TEMP",
+ "defaultValue": {
+ "floatValues": [
+ 75.0
+ ]
+ },
+ "maxSampleRate": 10.0,
+ "minSampleRate": 1.0
+ },
+ {
+ "property": "VehicleProperty::ENGINE_OIL_LEVEL",
+ "defaultValue": {
+ "int32Values": [
+ "VehicleOilLevel::NORMAL"
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::ENGINE_OIL_TEMP",
+ "defaultValue": {
+ "floatValues": [
+ 101.0
+ ]
+ },
+ "maxSampleRate": 10.0,
+ "minSampleRate": 0.10000000149011612
+ },
+ {
+ "property": "VehicleProperty::ENGINE_IDLE_AUTO_STOP_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::DOOR_LOCK",
+ "areas": [
+ {
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ },
+ "areaId": "Constants::DOOR_1_LEFT"
+ },
+ {
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ },
+ "areaId": "Constants::DOOR_1_RIGHT"
+ },
+ {
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ },
+ "areaId": "Constants::DOOR_2_LEFT"
+ },
+ {
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ },
+ "areaId": "Constants::DOOR_2_RIGHT"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::DOOR_CHILD_LOCK_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::DOOR_2_LEFT"
+ },
+ {
+ "areaId": "Constants::DOOR_2_RIGHT"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::DOOR_POS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::DOOR_1_LEFT",
+ "minInt32Value": 0,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::DOOR_1_RIGHT",
+ "minInt32Value": 0,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::DOOR_2_LEFT",
+ "minInt32Value": 0,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::DOOR_2_RIGHT",
+ "minInt32Value": 0,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::DOOR_REAR",
+ "minInt32Value": 0,
+ "maxInt32Value": 1
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::DOOR_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::DOOR_1_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::DOOR_1_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::DOOR_2_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::DOOR_2_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::MIRROR_Z_POS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "VehicleAreaMirror::DRIVER_LEFT",
+ "minInt32Value": -3,
+ "maxInt32Value": 3
+ },
+ {
+ "areaId": "VehicleAreaMirror::DRIVER_RIGHT",
+ "minInt32Value": -3,
+ "maxInt32Value": 3
+ },
+ {
+ "areaId": "VehicleAreaMirror::DRIVER_CENTER",
+ "minInt32Value": -3,
+ "maxInt32Value": 3
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::MIRROR_Z_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "VehicleAreaMirror::DRIVER_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "VehicleAreaMirror::DRIVER_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "VehicleAreaMirror::DRIVER_CENTER",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::MIRROR_Y_POS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "VehicleAreaMirror::DRIVER_LEFT",
+ "minInt32Value": -3,
+ "maxInt32Value": 3
+ },
+ {
+ "areaId": "VehicleAreaMirror::DRIVER_RIGHT",
+ "minInt32Value": -3,
+ "maxInt32Value": 3
+ },
+ {
+ "areaId": "VehicleAreaMirror::DRIVER_CENTER",
+ "minInt32Value": -3,
+ "maxInt32Value": 3
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::MIRROR_Y_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "VehicleAreaMirror::DRIVER_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "VehicleAreaMirror::DRIVER_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "VehicleAreaMirror::DRIVER_CENTER",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::MIRROR_LOCK",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::MIRROR_FOLD",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::MIRROR_AUTO_FOLD_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::MIRROR_DRIVER_LEFT_RIGHT"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::MIRROR_AUTO_TILT_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::MIRROR_DRIVER_LEFT_RIGHT"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::WINDOW_LOCK",
+ "areas": [
+ {
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areaId": "Constants::WINDOW_1_RIGHT_2_LEFT_2_RIGHT"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::WINDOW_POS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::WINDOW_1_LEFT",
+ "minInt32Value": 0,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::WINDOW_1_RIGHT",
+ "minInt32Value": 0,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::WINDOW_2_LEFT",
+ "minInt32Value": 0,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::WINDOW_2_RIGHT",
+ "minInt32Value": 0,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::WINDOW_ROOF_TOP_1",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::WINDOW_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::WINDOW_1_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::WINDOW_1_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::WINDOW_2_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::WINDOW_2_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::WINDOW_ROOF_TOP_1",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::WINDSHIELD_WIPERS_PERIOD",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "VehicleAreaWindow::FRONT_WINDSHIELD",
+ "minInt32Value": 0,
+ "maxInt32Value": 3000
+ },
+ {
+ "areaId": "VehicleAreaWindow::REAR_WINDSHIELD",
+ "minInt32Value": 0,
+ "maxInt32Value": 3000
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::WINDSHIELD_WIPERS_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "WindshieldWipersState::OFF"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "VehicleAreaWindow::FRONT_WINDSHIELD",
+ "supportedEnumValues": [
+ "WindshieldWipersState::OFF",
+ "WindshieldWipersState::ON",
+ "WindshieldWipersState::SERVICE"
+ ]
+ },
+ {
+ "areaId": "VehicleAreaWindow::REAR_WINDSHIELD",
+ "supportedEnumValues": [
+ "WindshieldWipersState::OFF",
+ "WindshieldWipersState::ON"
+ ]
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::WINDSHIELD_WIPERS_SWITCH",
+ "defaultValue": {
+ "int32Values": [
+ "WindshieldWipersSwitch::OFF"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "VehicleAreaWindow::FRONT_WINDSHIELD",
+ "supportedEnumValues": [
+ "WindshieldWipersSwitch::OFF",
+ "WindshieldWipersSwitch::MIST",
+ "WindshieldWipersSwitch::INTERMITTENT_LEVEL_1",
+ "WindshieldWipersSwitch::INTERMITTENT_LEVEL_2",
+ "WindshieldWipersSwitch::INTERMITTENT_LEVEL_3",
+ "WindshieldWipersSwitch::INTERMITTENT_LEVEL_4",
+ "WindshieldWipersSwitch::INTERMITTENT_LEVEL_5",
+ "WindshieldWipersSwitch::CONTINUOUS_LEVEL_1",
+ "WindshieldWipersSwitch::CONTINUOUS_LEVEL_2",
+ "WindshieldWipersSwitch::CONTINUOUS_LEVEL_3",
+ "WindshieldWipersSwitch::CONTINUOUS_LEVEL_4",
+ "WindshieldWipersSwitch::CONTINUOUS_LEVEL_5",
+ "WindshieldWipersSwitch::AUTO",
+ "WindshieldWipersSwitch::SERVICE"
+ ]
+ },
+ {
+ "areaId": "VehicleAreaWindow::REAR_WINDSHIELD",
+ "supportedEnumValues": [
+ "WindshieldWipersSwitch::OFF",
+ "WindshieldWipersSwitch::INTERMITTENT_LEVEL_1",
+ "WindshieldWipersSwitch::INTERMITTENT_LEVEL_2",
+ "WindshieldWipersSwitch::CONTINUOUS_LEVEL_1",
+ "WindshieldWipersSwitch::CONTINUOUS_LEVEL_2",
+ "WindshieldWipersSwitch::AUTO",
+ "WindshieldWipersSwitch::SERVICE"
+ ]
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::STEERING_WHEEL_DEPTH_POS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "minInt32Value": 0,
+ "maxInt32Value": 10
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::STEERING_WHEEL_DEPTH_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "minInt32Value": -2,
+ "maxInt32Value": 2
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::STEERING_WHEEL_HEIGHT_POS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "minInt32Value": 0,
+ "maxInt32Value": 10
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::STEERING_WHEEL_HEIGHT_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "minInt32Value": -2,
+ "maxInt32Value": 2
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::STEERING_WHEEL_THEFT_LOCK_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::STEERING_WHEEL_LOCKED",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::STEERING_WHEEL_EASY_ACCESS_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::GLOVE_BOX_DOOR_POS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": 0,
+ "maxInt32Value": 10
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::GLOVE_BOX_LOCKED",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_RIGHT"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::WHEEL_TICK",
+ "defaultValue": {
+ "int64Values": [
+ 0,
+ 100000,
+ 200000,
+ 300000,
+ 400000
+ ]
+ },
+ "configArray": [
+ 15,
+ 50000,
+ 50000,
+ 50000,
+ 50000
+ ],
+ "maxSampleRate": 10.0,
+ "minSampleRate": 1.0
+ },
+ {
+ "property": "VehicleProperty::ABS_ACTIVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::TRACTION_CONTROL_ACTIVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::AP_POWER_STATE_REQ",
+ "configArray": [
+ 0
+ ]
+ },
+ {
+ "property": "VehicleProperty::AP_POWER_STATE_REPORT",
+ "defaultValue": {
+ "int32Values": [
+ "VehicleApPowerStateReport::WAIT_FOR_VHAL",
+ 0
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::DISPLAY_BRIGHTNESS",
+ "defaultValue": {
+ "int32Values": [
+ 100
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "minInt32Value": 0,
+ "maxInt32Value": 100
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::OBD2_LIVE_FRAME",
+ "configArray": [
+ 0,
+ 0
+ ]
+ },
+ {
+ "property": "VehicleProperty::OBD2_FREEZE_FRAME",
+ "configArray": [
+ 0,
+ 0
+ ]
+ },
+ {
+ "property": "VehicleProperty::OBD2_FREEZE_FRAME_INFO"
+ },
+ {
+ "property": "VehicleProperty::OBD2_FREEZE_FRAME_CLEAR",
+ "configArray": [
+ 1
+ ]
+ },
+ {
+ "property": "VehicleProperty::HEADLIGHTS_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::LIGHT_STATE_ON"
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::HIGH_BEAM_LIGHTS_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::LIGHT_STATE_ON"
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::FRONT_FOG_LIGHTS_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::LIGHT_STATE_ON"
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::REAR_FOG_LIGHTS_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::LIGHT_STATE_ON"
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::HAZARD_LIGHTS_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::LIGHT_STATE_ON"
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::CABIN_LIGHTS_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::LIGHT_STATE_ON"
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::READING_LIGHTS_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::LIGHT_STATE_ON"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::STEERING_WHEEL_LIGHTS_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::LIGHT_STATE_ON"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "supportedEnumValues": [
+ "Constants::LIGHT_STATE_OFF",
+ "Constants::LIGHT_STATE_ON"
+ ]
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::HEADLIGHTS_SWITCH",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::LIGHT_SWITCH_AUTO"
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::HIGH_BEAM_LIGHTS_SWITCH",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::LIGHT_SWITCH_AUTO"
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::FRONT_FOG_LIGHTS_SWITCH",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::LIGHT_SWITCH_AUTO"
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::REAR_FOG_LIGHTS_SWITCH",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::LIGHT_SWITCH_AUTO"
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::HAZARD_LIGHTS_SWITCH",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::LIGHT_SWITCH_AUTO"
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::CABIN_LIGHTS_SWITCH",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::LIGHT_SWITCH_OFF"
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::READING_LIGHTS_SWITCH",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::LIGHT_SWITCH_OFF"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT"
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::STEERING_WHEEL_LIGHTS_SWITCH",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::LIGHT_SWITCH_AUTO"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "supportedEnumValues": [
+ "Constants::LIGHT_SWITCH_OFF",
+ "Constants::LIGHT_SWITCH_ON",
+ "Constants::LIGHT_SWITCH_AUTO"
+ ]
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::EVS_SERVICE_REQUEST",
+ "defaultValue": {
+ "int32Values": [
+ "EvsServiceType::REARVIEW",
+ "EvsServiceState::OFF"
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::VEHICLE_MAP_SERVICE"
+ },
+ {
+ "property": "VehicleProperty::LOCATION_CHARACTERIZATION",
+ "defaultValue": {
+ "int32Values": [
+ "LocationCharacterization::RAW_GNSS_ONLY"
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::ELECTRONIC_TOLL_COLLECTION_CARD_TYPE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::ELECTRONIC_TOLL_COLLECTION_CARD_STATUS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "EmergencyLaneKeepAssistState::ENABLED"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "supportedEnumValues": [
+ "ErrorState::NOT_AVAILABLE_SAFETY",
+ "ErrorState::NOT_AVAILABLE_SPEED_HIGH",
+ "ErrorState::NOT_AVAILABLE_SPEED_LOW",
+ "ErrorState::NOT_AVAILABLE_DISABLED",
+ "EmergencyLaneKeepAssistState::ENABLED",
+ "EmergencyLaneKeepAssistState::WARNING_LEFT",
+ "EmergencyLaneKeepAssistState::WARNING_RIGHT",
+ "EmergencyLaneKeepAssistState::ACTIVATED_STEER_LEFT",
+ "EmergencyLaneKeepAssistState::ACTIVATED_STEER_RIGHT",
+ "EmergencyLaneKeepAssistState::USER_OVERRIDE"
+ ]
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::CRUISE_CONTROL_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::CRUISE_CONTROL_TYPE",
+ "defaultValue": {
+ "int32Values": [
+ "CruiseControlType::STANDARD"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "supportedEnumValues": [
+ "ErrorState::NOT_AVAILABLE_SAFETY",
+ "ErrorState::NOT_AVAILABLE_SPEED_HIGH",
+ "ErrorState::NOT_AVAILABLE_SPEED_LOW",
+ "ErrorState::NOT_AVAILABLE_DISABLED",
+ "CruiseControlType::STANDARD",
+ "CruiseControlType::ADAPTIVE",
+ "CruiseControlType::PREDICTIVE"
+ ]
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::CRUISE_CONTROL_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "CruiseControlState::ENABLED"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "supportedEnumValues": [
+ "ErrorState::NOT_AVAILABLE_SAFETY",
+ "ErrorState::NOT_AVAILABLE_SPEED_HIGH",
+ "ErrorState::NOT_AVAILABLE_SPEED_LOW",
+ "ErrorState::NOT_AVAILABLE_DISABLED",
+ "CruiseControlState::ENABLED",
+ "CruiseControlState::ACTIVATED",
+ "CruiseControlState::USER_OVERRIDE",
+ "CruiseControlState::SUSPENDED",
+ "CruiseControlState::FORCED_DEACTIVATION_WARNING"
+ ]
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::CRUISE_CONTROL_COMMAND",
+ "areas": [
+ {
+ "areaId": 0,
+ "supportedEnumValues": [
+ "CruiseControlCommand::ACTIVATE",
+ "CruiseControlCommand::SUSPEND",
+ "CruiseControlCommand::INCREASE_TARGET_SPEED",
+ "CruiseControlCommand::DECREASE_TARGET_SPEED",
+ "CruiseControlCommand::INCREASE_TARGET_TIME_GAP",
+ "CruiseControlCommand::DECREASE_TARGET_TIME_GAP"
+ ]
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::CRUISE_CONTROL_TARGET_SPEED",
+ "defaultValue": {
+ "floatValues": [
+ 25.0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "minFloatValue": 20.0,
+ "maxFloatValue": 35.0
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP",
+ "defaultValue": {
+ "int32Values": [
+ 1200
+ ]
+ },
+ "configArray": [
+ 1200,
+ 1400,
+ 1600,
+ 1800,
+ 2000,
+ 2200
+ ]
+ },
+ {
+ "property": "VehicleProperty::ADAPTIVE_CRUISE_CONTROL_LEAD_VEHICLE_MEASURED_DISTANCE",
+ "defaultValue": {
+ "int32Values": [
+ 100000
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "minInt32Value": 0,
+ "maxInt32Value": 200000
+ }
+ ],
+ "maxSampleRate": 10.0,
+ "minSampleRate": 1.0
+ },
+ {
+ "property": "VehicleProperty::HANDS_ON_DETECTION_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::HANDS_ON_DETECTION_DRIVER_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "HandsOnDetectionDriverState::HANDS_ON"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "supportedEnumValues": [
+ "ErrorState::NOT_AVAILABLE_DISABLED",
+ "HandsOnDetectionDriverState::HANDS_ON",
+ "HandsOnDetectionDriverState::HANDS_OFF"
+ ]
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::HANDS_ON_DETECTION_WARNING",
+ "defaultValue": {
+ "int32Values": [
+ "HandsOnDetectionWarning::NO_WARNING"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "supportedEnumValues": [
+ "ErrorState::NOT_AVAILABLE_DISABLED",
+ "HandsOnDetectionWarning::NO_WARNING",
+ "HandsOnDetectionWarning::WARNING"
+ ]
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::INITIAL_USER_INFO"
+ },
+ {
+ "property": "VehicleProperty::SWITCH_USER"
+ },
+ {
+ "property": "VehicleProperty::CREATE_USER"
+ },
+ {
+ "property": "VehicleProperty::REMOVE_USER"
+ },
+ {
+ "property": "VehicleProperty::USER_IDENTIFICATION_ASSOCIATION"
+ },
+ {
+ "property": "VehicleProperty::POWER_POLICY_REQ"
+ },
+ {
+ "property": "VehicleProperty::POWER_POLICY_GROUP_REQ"
+ },
+ {
+ "property": "VehicleProperty::CURRENT_POWER_POLICY"
+ },
+ {
+ "property": "VehicleProperty::ANDROID_EPOCH_TIME"
+ },
+ {
+ "property": "VehicleProperty::WATCHDOG_ALIVE"
+ },
+ {
+ "property": "VehicleProperty::WATCHDOG_TERMINATED_PROCESS"
+ },
+ {
+ "property": "VehicleProperty::VHAL_HEARTBEAT"
+ },
+ {
+ "property": "VehicleProperty::CLUSTER_SWITCH_UI",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "comment": "0 means ClusterHome"
+ },
+ {
+ "property": "VehicleProperty::CLUSTER_DISPLAY_STATE",
+ "defaultValue": {
+ "int32Values": [
+ 0,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1
+ ]
+ },
+ "comment":
+ "Value means: 0 /* Off */, -1, -1, -1, -1 /* Bounds */, -1, -1, -1, -1 /* Insets */"
+ },
+ {
+ "property": "VehicleProperty::CLUSTER_REPORT_STATE",
+ "configArray": [
+ 0,
+ 0,
+ 0,
+ 11,
+ 0,
+ 0,
+ 0,
+ 0,
+ 16
+ ]
+ },
+ {
+ "property": "VehicleProperty::CLUSTER_REQUEST_DISPLAY"
+ },
+ {
+ "property": "VehicleProperty::CLUSTER_NAVIGATION_STATE"
+ },
+ {
+ "property": "VehicleProperty::GENERAL_SAFETY_REGULATION_COMPLIANCE_REQUIREMENT",
+ "defaultValue": {
+ "int32Values": [
+ "GsrComplianceRequirementType::GSR_COMPLIANCE_REQUIRED_V1"
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "ErrorState::NOT_AVAILABLE_DISABLED"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "supportedEnumValues": [
+ "ErrorState::NOT_AVAILABLE_SAFETY",
+ "ErrorState::NOT_AVAILABLE_POOR_VISIBILITY",
+ "ErrorState::NOT_AVAILABLE_SPEED_HIGH",
+ "ErrorState::NOT_AVAILABLE_SPEED_LOW",
+ "ErrorState::NOT_AVAILABLE_DISABLED",
+ "AutomaticEmergencyBrakingState::ENABLED",
+ "AutomaticEmergencyBrakingState::ACTIVATED",
+ "AutomaticEmergencyBrakingState::USER_OVERRIDE"
+ ]
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::FORWARD_COLLISION_WARNING_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::FORWARD_COLLISION_WARNING_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "ForwardCollisionWarningState::NO_WARNING"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "supportedEnumValues": [
+ "ErrorState::NOT_AVAILABLE_SAFETY",
+ "ErrorState::NOT_AVAILABLE_POOR_VISIBILITY",
+ "ErrorState::NOT_AVAILABLE_SPEED_HIGH",
+ "ErrorState::NOT_AVAILABLE_SPEED_LOW",
+ "ErrorState::NOT_AVAILABLE_DISABLED",
+ "ForwardCollisionWarningState::NO_WARNING",
+ "ForwardCollisionWarningState::WARNING"
+ ]
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::BLIND_SPOT_WARNING_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::BLIND_SPOT_WARNING_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "BlindSpotWarningState::NO_WARNING"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "VehicleAreaMirror::DRIVER_LEFT",
+ "supportedEnumValues": [
+ "ErrorState::NOT_AVAILABLE_SAFETY",
+ "ErrorState::NOT_AVAILABLE_POOR_VISIBILITY",
+ "ErrorState::NOT_AVAILABLE_SPEED_HIGH",
+ "ErrorState::NOT_AVAILABLE_SPEED_LOW",
+ "ErrorState::NOT_AVAILABLE_DISABLED",
+ "BlindSpotWarningState::NO_WARNING",
+ "BlindSpotWarningState::WARNING"
+ ]
+ },
+ {
+ "areaId": "VehicleAreaMirror::DRIVER_RIGHT",
+ "supportedEnumValues": [
+ "ErrorState::NOT_AVAILABLE_SAFETY",
+ "ErrorState::NOT_AVAILABLE_POOR_VISIBILITY",
+ "ErrorState::NOT_AVAILABLE_SPEED_HIGH",
+ "ErrorState::NOT_AVAILABLE_SPEED_LOW",
+ "ErrorState::NOT_AVAILABLE_DISABLED",
+ "BlindSpotWarningState::NO_WARNING",
+ "BlindSpotWarningState::WARNING"
+ ]
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::LANE_DEPARTURE_WARNING_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::LANE_DEPARTURE_WARNING_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "LaneDepartureWarningState::NO_WARNING"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "supportedEnumValues": [
+ "ErrorState::NOT_AVAILABLE_SAFETY",
+ "ErrorState::NOT_AVAILABLE_SPEED_HIGH",
+ "ErrorState::NOT_AVAILABLE_SPEED_LOW",
+ "ErrorState::NOT_AVAILABLE_DISABLED",
+ "LaneDepartureWarningState::NO_WARNING",
+ "LaneDepartureWarningState::WARNING_LEFT",
+ "LaneDepartureWarningState::WARNING_RIGHT"
+ ]
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::LANE_KEEP_ASSIST_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::LANE_KEEP_ASSIST_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "LaneKeepAssistState::ENABLED"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "supportedEnumValues": [
+ "ErrorState::NOT_AVAILABLE_SAFETY",
+ "ErrorState::NOT_AVAILABLE_SPEED_HIGH",
+ "ErrorState::NOT_AVAILABLE_SPEED_LOW",
+ "ErrorState::NOT_AVAILABLE_DISABLED",
+ "LaneKeepAssistState::ENABLED",
+ "LaneKeepAssistState::ACTIVATED_STEER_LEFT",
+ "LaneKeepAssistState::ACTIVATED_STEER_RIGHT",
+ "LaneKeepAssistState::USER_OVERRIDE"
+ ]
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::LANE_CENTERING_ASSIST_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::LANE_CENTERING_ASSIST_COMMAND"
+ },
+ {
+ "property": "VehicleProperty::LANE_CENTERING_ASSIST_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "LaneCenteringAssistState::ENABLED"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "supportedEnumValues": [
+ "ErrorState::NOT_AVAILABLE_SAFETY",
+ "ErrorState::NOT_AVAILABLE_SPEED_HIGH",
+ "ErrorState::NOT_AVAILABLE_SPEED_LOW",
+ "ErrorState::NOT_AVAILABLE_DISABLED",
+ "LaneCenteringAssistState::ENABLED",
+ "LaneCenteringAssistState::ACTIVATION_REQUESTED",
+ "LaneCenteringAssistState::ACTIVATED",
+ "LaneCenteringAssistState::USER_OVERRIDE",
+ "LaneCenteringAssistState::FORCED_DEACTIVATION_WARNING"
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/automotive/vehicle/aidl/impl/default_config/config/README.md b/automotive/vehicle/aidl/impl/default_config/config/README.md
new file mode 100644
index 0000000..6e82de5
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/default_config/config/README.md
@@ -0,0 +1,171 @@
+# Property Configuration Files
+
+Each JSON file in this folder is a property configuration file for reference
+Vehicle HAL. They contain VehiclePropConfig information along with initial
+value information.
+
+## JSON schema
+
+Each JSON file must be in a schema like the following example:
+(The comment starting with "//" is for documentation only and must be removed
+from the actual JSON file. The "comment" field is used for comment in the
+actual JSON file and will be ignored by the parser)
+
+```
+{
+ // (number) The version for the JSON schema.
+ "apiVersion": 1,
+ // (non-empty array of objects) The property configuration list.
+ //
+ // Each object is a configuration for one property.
+ "properties": [
+ {
+ // (number/string) The ID for the property.
+ // This value is defined in a string value
+ // which represents a constant value, see the "JSON Number-type
+ // Field Values" section for detail.
+ "property": "VehicleProperty::INFO_FUEL_CAPACITY",
+ // (optional, number/string) The access mode for the property.
+ // If specified, this overwrite the default access mode specified in
+ // VehicleProperty.aidl. Must be specified for vendor properties.
+ "access": "VehiclePropertyAccess::READ",
+ // (optional, number/string) The change mode for the property.
+ // If specified, this overwrite the default change mode specified in
+ // VehicleProperty.aidl. Must be specified for vendor properties.
+ "changeMode": "VehiclePropertyChangeMode::STATIC",
+ // (optional, string) The config string.
+ "configString": "blahblah",
+ // (optional, array of number/string) The config array.
+ "configArray": [1, 2, "Constants::HVAC_ALL"],
+ // (optional, object) The default value for the property.
+ // If not specified, the property will be shown as unavailable
+ // until its value is set.
+ "defaultValue": {
+ // (optional, array of int number/string) Int values.
+ "int32Values": [1, 2, "Constants::HVAC_ALL"],
+ // (optional, array of int number/string) Long values.
+ "int64Values": [1, 2],
+ // (optional, array of float number/string) Float values.
+ "floatValues": [1.1, 2.2],
+ // (optional, string) String value.
+ "stringValue": "test"
+ },
+ // (optional, number/string) The minimum sample rate in HZ.
+ // Only work for VehiclePropertyChangeMode::CONTINUOUS property.
+ // Must be specified for continuous property.
+ "minSampleRate": 1,
+ // (optional, number/string) The maximum sample rate in HZ.
+ // Only work for VehiclePropertyChangeMode::CONTINUOUS property.
+ // Must be specified for continuous property.
+ "maxSampleRate": 10,
+ // (optional, array of objects) The area configs.
+ "areas:" [
+ {
+ // (number/string) The area ID.
+ "areaId": "Constants::DOOR_1_LEFT",
+ // (optional number/string) The minimum int value.
+ "minInt32Value": 1,
+ // (optional number/string) The maximum int value.
+ "maxInt32Value": 10,
+ // (optional number/string) The minimum long value.
+ "minInt64Value": 1,
+ // (optional number/string) The maximum long value.
+ "maxInt64Value": 10,
+ // (optional number/string) The minimum float value.
+ "minFloatValue": 1,
+ // (optional number/string) The maximum float value.
+ "maxFloatValue": 10,
+ // (optional object) The default value for this area.
+ // Uses the same format as the "defaultValue" field for
+ // property object. If specified, this overwrite the global
+ // defaultValue.
+ "defaultValue": {
+ "int32Values": [1, 2, "Constants::HVAC_ALL"],
+ "int64Values": [1, 2],
+ "floatValues": [1.1, 2.2],
+ "stringValue": "test"
+ }
+ }
+ ]
+ }
+ ]
+}
+```
+
+## JSON Number-type Field Values
+
+For number type field values, they can either be defined as a numeric number,
+e.g., `{"minInt32Value": 1}` or be defined as a string which represents a
+defined constant value, e.g.,
+`{"property": "VehicleProperty::INFO_FUEL_CAPACITY"}`.
+
+For constant values, they must be a string in the format of `XXX::XXX`, where
+the field before `::` is the constant type, and the field after `::` is the
+variable name.
+
+We support the following constant types:
+
+* VehiclePropertyAccess
+
+* VehiclePropertyChangeMode
+
+* VehicleGear
+
+* VehicleAreaWindow
+
+* VehicleOilLevel
+
+* VehicleUnit
+
+* VehicleSeatOccupancyState
+
+* VehicleHvacFanDirection
+
+* VehicleApPowerStateReport
+
+* VehicleTurnSignal
+
+* VehicleVendorPermission
+
+* EvsServiceType
+
+* EvsServiceState
+
+* EvConnectorType
+
+* VehicleProperty
+
+* GsrComplianceRequirementType
+
+* VehicleIgnitionState
+
+* FuelType
+
+* AutomaticEmergencyBrakingState
+
+* ForwardCollisionWarningState
+
+* BlindSpotWarningState
+
+* LaneDepartureWarningState
+
+* LaneKeepAssistState
+
+* LaneCenteringAssistCommand
+
+* LaneCenteringAssistState
+
+* ErrorState
+
+* WindshieldWipersState
+
+* WindshieldWipersSwitch
+
+* Constants
+
+Every constant type except "Constants" corresponds to a enum defined in Vehicle
+HAL interfac. E.g. "VehicleProperty" corresponds to the enums defined in
+"VehicleProperty.aidl".
+
+"Constants" type refers to the constant variables defined in the paresr.
+Specifically, the "CONSTANTS_BY_NAME" map defined in "JsonConfigLoader.cpp".
diff --git a/automotive/vehicle/aidl/impl/default_config/config/TestProperties.json b/automotive/vehicle/aidl/impl/default_config/config/TestProperties.json
new file mode 100644
index 0000000..fd4b002
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/default_config/config/TestProperties.json
@@ -0,0 +1,209 @@
+{
+ "properties": [
+ {
+ "property": "Constants::kMixedTypePropertyForTest",
+ "defaultValue": {
+ "floatValues": [
+ 4.5
+ ],
+ "int32Values": [
+ 1,
+ 2,
+ 3
+ ],
+ "stringValue": "MIXED property"
+ },
+ "configArray": [
+ 1,
+ 1,
+ 0,
+ 2,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0
+ ],
+ "access": "VehiclePropertyAccess::READ_WRITE",
+ "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
+ },
+ {
+ "property": "Constants::VENDOR_EXTENSION_BOOLEAN_PROPERTY",
+ "areas": [
+ {
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ },
+ "areaId": "Constants::DOOR_1_LEFT"
+ },
+ {
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ },
+ "areaId": "Constants::DOOR_1_RIGHT"
+ },
+ {
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areaId": "Constants::DOOR_2_LEFT"
+ },
+ {
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areaId": "Constants::DOOR_2_RIGHT"
+ }
+ ],
+ "access": "VehiclePropertyAccess::READ_WRITE",
+ "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
+ },
+ {
+ "property": "Constants::VENDOR_EXTENSION_FLOAT_PROPERTY",
+ "areas": [
+ {
+ "defaultValue": {
+ "floatValues": [
+ 1.0
+ ]
+ },
+ "areaId": "Constants::HVAC_LEFT",
+ "minFloatValue": -10.0,
+ "maxFloatValue": 10.0
+ },
+ {
+ "defaultValue": {
+ "floatValues": [
+ 2.0
+ ]
+ },
+ "areaId": "Constants::HVAC_RIGHT",
+ "minFloatValue": -10.0,
+ "maxFloatValue": 10.0
+ }
+ ],
+ "access": "VehiclePropertyAccess::READ_WRITE",
+ "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
+ },
+ {
+ "property": "Constants::VENDOR_EXTENSION_INT_PROPERTY",
+ "areas": [
+ {
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ },
+ "areaId": "VehicleAreaWindow::FRONT_WINDSHIELD",
+ "minInt32Value": -100,
+ "maxInt32Value": 100
+ },
+ {
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areaId": "VehicleAreaWindow::REAR_WINDSHIELD",
+ "minInt32Value": -100,
+ "maxInt32Value": 100
+ },
+ {
+ "defaultValue": {
+ "int32Values": [
+ -1
+ ]
+ },
+ "areaId": "VehicleAreaWindow::ROOF_TOP_1",
+ "minInt32Value": -100,
+ "maxInt32Value": 100
+ }
+ ],
+ "access": "VehiclePropertyAccess::READ_WRITE",
+ "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
+ },
+ {
+ "property": "Constants::VENDOR_EXTENSION_STRING_PROPERTY",
+ "defaultValue": {
+ "stringValue": "Vendor String Property"
+ },
+ "access": "VehiclePropertyAccess::READ_WRITE",
+ "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
+ },
+ {
+ "property": "Constants::PLACEHOLDER_PROPERTY_INT",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "access": "VehiclePropertyAccess::READ_WRITE",
+ "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
+ },
+ {
+ "property": "Constants::PLACEHOLDER_PROPERTY_FLOAT",
+ "defaultValue": {
+ "floatValues": [
+ 0.0
+ ]
+ },
+ "access": "VehiclePropertyAccess::READ_WRITE",
+ "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
+ },
+ {
+ "property": "Constants::PLACEHOLDER_PROPERTY_BOOLEAN",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "access": "VehiclePropertyAccess::READ_WRITE",
+ "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
+ },
+ {
+ "property": "Constants::PLACEHOLDER_PROPERTY_STRING",
+ "defaultValue": {
+ "stringValue": "Test"
+ },
+ "access": "VehiclePropertyAccess::READ_WRITE",
+ "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
+ },
+ {
+ "property": "Constants::ECHO_REVERSE_BYTES",
+ "access": "VehiclePropertyAccess::READ_WRITE",
+ "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
+ },
+ {
+ "property": "Constants::VENDOR_PROPERTY_ID",
+ "access": "VehiclePropertyAccess::READ_WRITE",
+ "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
+ },
+ {
+ "property": "VehicleProperty::SUPPORT_CUSTOMIZE_VENDOR_PERMISSION",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ },
+ "configArray": [
+ "Constants::kMixedTypePropertyForTest",
+ "VehicleVendorPermission::PERMISSION_GET_VENDOR_CATEGORY_INFO",
+ "VehicleVendorPermission::PERMISSION_SET_VENDOR_CATEGORY_INFO",
+ "Constants::VENDOR_EXTENSION_INT_PROPERTY",
+ "VehicleVendorPermission::PERMISSION_GET_VENDOR_CATEGORY_SEAT",
+ "VehicleVendorPermission::PERMISSION_NOT_ACCESSIBLE",
+ "Constants::VENDOR_EXTENSION_FLOAT_PROPERTY",
+ "VehicleVendorPermission::PERMISSION_DEFAULT",
+ "VehicleVendorPermission::PERMISSION_DEFAULT"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/automotive/vehicle/aidl/impl/default_config/config/VendorClusterTestProperties.json b/automotive/vehicle/aidl/impl/default_config/config/VendorClusterTestProperties.json
new file mode 100644
index 0000000..3a1a783
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/default_config/config/VendorClusterTestProperties.json
@@ -0,0 +1,63 @@
+{
+ "properties": [
+ {
+ "property": "Constants::VENDOR_CLUSTER_SWITCH_UI",
+ "access": "VehiclePropertyAccess::WRITE",
+ "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
+ },
+ {
+ "property": "Constants::VENDOR_CLUSTER_DISPLAY_STATE",
+ "access": "VehiclePropertyAccess::WRITE",
+ "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
+ },
+ {
+ "property": "Constants::VENDOR_CLUSTER_REPORT_STATE",
+ "defaultValue": {
+ "int32Values": [
+ 0,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ 0,
+ -1
+ ]
+ },
+ "configArray": [
+ 0,
+ 0,
+ 0,
+ 11,
+ 0,
+ 0,
+ 0,
+ 0,
+ 16
+ ],
+ "access": "VehiclePropertyAccess::READ",
+ "changeMode": "VehiclePropertyChangeMode::ON_CHANGE",
+ "comment":
+ "Value means 0 /* Off */, -1, -1, -1, -1 /* Bounds */, -1, -1, -1, -1 /* Insets */, 0 /* ClusterHome */, -1 /* ClusterNone */"
+ },
+ {
+ "property": "Constants::VENDOR_CLUSTER_REQUEST_DISPLAY",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "access": "VehiclePropertyAccess::READ",
+ "changeMode": "VehiclePropertyChangeMode::ON_CHANGE",
+ "comment": "0 means ClusterHome"
+ },
+ {
+ "property": "Constants::VENDOR_CLUSTER_NAVIGATION_STATE",
+ "access": "VehiclePropertyAccess::READ",
+ "changeMode": "VehiclePropertyChangeMode::ON_CHANGE"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h b/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h
deleted file mode 100644
index f023fd2..0000000
--- a/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h
+++ /dev/null
@@ -1,2040 +0,0 @@
-/*
- * 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_default_config_include_DefaultConfig_H_
-#define android_hardware_automotive_vehicle_aidl_impl_default_config_include_DefaultConfig_H_
-
-#include <PropertyUtils.h>
-#include <TestPropertyUtils.h>
-#include <VehicleHalTypes.h>
-
-#include <map>
-#include <vector>
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-
-// Types used in configs, not to be exposed as public API.
-namespace defaultconfig_impl {
-
-using ::aidl::android::hardware::automotive::vehicle::EvConnectorType;
-using ::aidl::android::hardware::automotive::vehicle::EvsServiceState;
-using ::aidl::android::hardware::automotive::vehicle::EvsServiceType;
-using ::aidl::android::hardware::automotive::vehicle::FuelType;
-using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
-using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReport;
-using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq;
-using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
-using ::aidl::android::hardware::automotive::vehicle::VehicleAreaMirror;
-using ::aidl::android::hardware::automotive::vehicle::VehicleAreaWindow;
-using ::aidl::android::hardware::automotive::vehicle::VehicleGear;
-using ::aidl::android::hardware::automotive::vehicle::VehicleHvacFanDirection;
-using ::aidl::android::hardware::automotive::vehicle::VehicleIgnitionState;
-using ::aidl::android::hardware::automotive::vehicle::VehicleOilLevel;
-using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
-using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
-using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
-using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode;
-using ::aidl::android::hardware::automotive::vehicle::VehicleSeatOccupancyState;
-using ::aidl::android::hardware::automotive::vehicle::VehicleTurnSignal;
-using ::aidl::android::hardware::automotive::vehicle::VehicleUnit;
-using ::aidl::android::hardware::automotive::vehicle::VehicleVendorPermission;
-
-struct ConfigDeclaration {
- VehiclePropConfig config;
-
- // This value will be used as an initial value for the property. If this field is specified for
- // property that supports multiple areas then it will be used for all areas unless particular
- // area is overridden in initialAreaValue field.
- RawPropValues initialValue;
- // Use initialAreaValues if it is necessary to specify different values per each area.
- std::map<int32_t, RawPropValues> initialAreaValues;
-};
-
-const std::vector<ConfigDeclaration> kVehicleProperties = {
- {.config =
- {
- .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::STATIC,
- },
- .initialValue = {.floatValues = {15000.0f}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::INFO_FUEL_TYPE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::STATIC,
- },
- .initialValue = {.int32Values = {toInt(FuelType::FUEL_TYPE_UNLEADED)}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::INFO_EV_BATTERY_CAPACITY),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::STATIC,
- },
- .initialValue = {.floatValues = {150000.0f}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::INFO_EV_CONNECTOR_TYPE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::STATIC,
- },
- .initialValue = {.int32Values = {toInt(EvConnectorType::IEC_TYPE_1_AC)}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::INFO_FUEL_DOOR_LOCATION),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::STATIC,
- },
- .initialValue = {.int32Values = {FUEL_DOOR_REAR_LEFT}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::INFO_EV_PORT_LOCATION),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::STATIC,
- },
- .initialValue = {.int32Values = {CHARGE_PORT_FRONT_LEFT}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::INFO_MULTI_EV_PORT_LOCATIONS),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::STATIC,
- },
- .initialValue = {.int32Values = {CHARGE_PORT_FRONT_LEFT, CHARGE_PORT_REAR_LEFT}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::INFO_VIN),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::STATIC,
- },
- .initialValue = {.stringValue = "1GCARVIN123456789"}},
- {.config =
- {
- .prop = toInt(VehicleProperty::INFO_MAKE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::STATIC,
- },
- .initialValue = {.stringValue = "Toy Vehicle"}},
- {.config =
- {
- .prop = toInt(VehicleProperty::INFO_MODEL),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::STATIC,
- },
- .initialValue = {.stringValue = "Speedy Model"}},
- {.config =
- {
- .prop = toInt(VehicleProperty::INFO_MODEL_YEAR),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::STATIC,
- },
- .initialValue = {.int32Values = {2020}}},
- {.config =
- {
- .prop = toInt(VehicleProperty::INFO_EXTERIOR_DIMENSIONS),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::STATIC,
- },
- .initialValue = {.int32Values = {1776, 4950, 2008, 2140, 2984, 1665, 1667, 11800}}},
- {.config =
- {
- .prop = toInt(VehicleProperty::PERF_VEHICLE_SPEED),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
- .minSampleRate = 1.0f,
- .maxSampleRate = 10.0f,
- },
- .initialValue = {.floatValues = {0.0f}}},
- {.config =
- {
- .prop = toInt(VehicleProperty::PERF_VEHICLE_SPEED_DISPLAY),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
- .minSampleRate = 1.0f,
- .maxSampleRate = 10.0f,
- },
- .initialValue = {.floatValues = {0.0f}}},
- {.config =
- {
- .prop = toInt(VehicleProperty::VEHICLE_SPEED_DISPLAY_UNITS),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .configArray = {toInt(VehicleUnit::METER_PER_SEC),
- toInt(VehicleUnit::MILES_PER_HOUR),
- toInt(VehicleUnit::KILOMETERS_PER_HOUR)},
- },
- .initialValue = {.int32Values = {toInt(VehicleUnit::MILES_PER_HOUR)}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::EV_BATTERY_DISPLAY_UNITS),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .configArray = {toInt(VehicleUnit::WATT_HOUR),
- toInt(VehicleUnit::AMPERE_HOURS),
- toInt(VehicleUnit::KILOWATT_HOUR)},
- },
- .initialValue = {.int32Values = {toInt(VehicleUnit::KILOWATT_HOUR)}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_MEMORY_SELECT),
- .access = VehiclePropertyAccess::WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = 0,
- .maxInt32Value = 3},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = 0,
- .maxInt32Value = 3},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = 0,
- .maxInt32Value = 3},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = 0,
- .maxInt32Value = 3}}},
- .initialValue = {.int32Values = {1}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_MEMORY_SET),
- .access = VehiclePropertyAccess::WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = 0,
- .maxInt32Value = 3},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = 0,
- .maxInt32Value = 3},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = 0,
- .maxInt32Value = 3},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = 0,
- .maxInt32Value = 3}}},
- .initialValue = {.int32Values = {1}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_BELT_BUCKLED),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER}}},
- .initialAreaValues = {{SEAT_1_LEFT, {.int32Values = {0}}},
- {SEAT_1_RIGHT, {.int32Values = {0}}},
- {SEAT_2_LEFT, {.int32Values = {0}}},
- {SEAT_2_RIGHT, {.int32Values = {0}}},
- {SEAT_2_CENTER, {.int32Values = {0}}}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_BELT_HEIGHT_POS),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = 0,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = 0,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = 0,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = 0,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER,
- .minInt32Value = 0,
- .maxInt32Value = 10}}},
- .initialAreaValues = {{SEAT_1_LEFT, {.int32Values = {10}}},
- {SEAT_1_RIGHT, {.int32Values = {10}}},
- {SEAT_2_LEFT, {.int32Values = {10}}},
- {SEAT_2_RIGHT, {.int32Values = {10}}},
- {SEAT_2_CENTER, {.int32Values = {10}}}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_BELT_HEIGHT_MOVE),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER,
- .minInt32Value = -1,
- .maxInt32Value = 1}}},
- .initialAreaValues = {{SEAT_1_LEFT, {.int32Values = {0}}},
- {SEAT_1_RIGHT, {.int32Values = {0}}},
- {SEAT_2_LEFT, {.int32Values = {0}}},
- {SEAT_2_RIGHT, {.int32Values = {0}}},
- {SEAT_2_CENTER, {.int32Values = {0}}}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_FORE_AFT_POS),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER,
- .minInt32Value = -10,
- .maxInt32Value = 10}}},
- .initialAreaValues = {{SEAT_1_LEFT, {.int32Values = {0}}},
- {SEAT_1_RIGHT, {.int32Values = {0}}},
- {SEAT_2_LEFT, {.int32Values = {0}}},
- {SEAT_2_RIGHT, {.int32Values = {0}}},
- {SEAT_2_CENTER, {.int32Values = {0}}}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_FORE_AFT_MOVE),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER,
- .minInt32Value = -1,
- .maxInt32Value = 1}}},
- .initialAreaValues = {{SEAT_1_LEFT, {.int32Values = {0}}},
- {SEAT_1_RIGHT, {.int32Values = {0}}},
- {SEAT_2_LEFT, {.int32Values = {0}}},
- {SEAT_2_RIGHT, {.int32Values = {0}}},
- {SEAT_2_CENTER, {.int32Values = {0}}}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_BACKREST_ANGLE_1_POS),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER,
- .minInt32Value = -10,
- .maxInt32Value = 10}}},
- .initialAreaValues = {{SEAT_1_LEFT, {.int32Values = {0}}},
- {SEAT_1_RIGHT, {.int32Values = {0}}},
- {SEAT_2_LEFT, {.int32Values = {0}}},
- {SEAT_2_RIGHT, {.int32Values = {0}}},
- {SEAT_2_CENTER, {.int32Values = {0}}}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_BACKREST_ANGLE_1_MOVE),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER,
- .minInt32Value = -1,
- .maxInt32Value = 1}}},
- .initialAreaValues = {{SEAT_1_LEFT, {.int32Values = {0}}},
- {SEAT_1_RIGHT, {.int32Values = {0}}},
- {SEAT_2_LEFT, {.int32Values = {0}}},
- {SEAT_2_RIGHT, {.int32Values = {0}}},
- {SEAT_2_CENTER, {.int32Values = {0}}}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_BACKREST_ANGLE_2_POS),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER,
- .minInt32Value = -10,
- .maxInt32Value = 10}}},
- .initialAreaValues = {{SEAT_1_LEFT, {.int32Values = {0}}},
- {SEAT_1_RIGHT, {.int32Values = {0}}},
- {SEAT_2_LEFT, {.int32Values = {0}}},
- {SEAT_2_RIGHT, {.int32Values = {0}}},
- {SEAT_2_CENTER, {.int32Values = {0}}}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_BACKREST_ANGLE_2_MOVE),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER,
- .minInt32Value = -1,
- .maxInt32Value = 1}}},
- .initialAreaValues = {{SEAT_1_LEFT, {.int32Values = {0}}},
- {SEAT_1_RIGHT, {.int32Values = {0}}},
- {SEAT_2_LEFT, {.int32Values = {0}}},
- {SEAT_2_RIGHT, {.int32Values = {0}}},
- {SEAT_2_CENTER, {.int32Values = {0}}}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_HEIGHT_POS),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER,
- .minInt32Value = -10,
- .maxInt32Value = 10}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_HEIGHT_MOVE),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER,
- .minInt32Value = -1,
- .maxInt32Value = 1}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_DEPTH_POS),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER,
- .minInt32Value = -10,
- .maxInt32Value = 10}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_DEPTH_MOVE),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER,
- .minInt32Value = -1,
- .maxInt32Value = 1}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_TILT_POS),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER,
- .minInt32Value = -10,
- .maxInt32Value = 10}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_TILT_MOVE),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER,
- .minInt32Value = -1,
- .maxInt32Value = 1}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_LUMBAR_FORE_AFT_POS),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = -10,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER,
- .minInt32Value = -10,
- .maxInt32Value = 10}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_LUMBAR_FORE_AFT_MOVE),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER,
- .minInt32Value = -1,
- .maxInt32Value = 1}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_LUMBAR_SIDE_SUPPORT_POS),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = 0,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = 0,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = 0,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = 0,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER,
- .minInt32Value = 0,
- .maxInt32Value = 10}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_LUMBAR_SIDE_SUPPORT_MOVE),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER,
- .minInt32Value = -1,
- .maxInt32Value = 1}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_HEADREST_HEIGHT_MOVE),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER,
- .minInt32Value = -1,
- .maxInt32Value = 1}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_HEADREST_ANGLE_POS),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = 0,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = 0,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = 0,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = 0,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER,
- .minInt32Value = 0,
- .maxInt32Value = 10}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_HEADREST_ANGLE_MOVE),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER,
- .minInt32Value = -1,
- .maxInt32Value = 1}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_HEADREST_FORE_AFT_POS),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = 0,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = 0,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = 0,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = 0,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER,
- .minInt32Value = 0,
- .maxInt32Value = 10}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::SEAT_HEADREST_FORE_AFT_MOVE),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER,
- .minInt32Value = -1,
- .maxInt32Value = 1}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::SEAT_OCCUPANCY),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = (SEAT_1_LEFT)},
- VehicleAreaConfig{.areaId = (SEAT_1_RIGHT)}},
- },
- .initialAreaValues = {{SEAT_1_LEFT,
- {.int32Values = {toInt(VehicleSeatOccupancyState::VACANT)}}},
- {SEAT_1_RIGHT,
- {.int32Values = {toInt(VehicleSeatOccupancyState::VACANT)}}}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::INFO_DRIVER_SEAT),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::STATIC,
- // this was a zoned property on an old vhal, but it is meant to be global
- .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
- },
- .initialValue = {.int32Values = {SEAT_1_LEFT}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::PERF_ODOMETER),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
- .minSampleRate = 1.0f,
- .maxSampleRate = 10.0f,
- },
- .initialValue = {.floatValues = {0.0f}}},
- {.config =
- {
- .prop = toInt(VehicleProperty::PERF_STEERING_ANGLE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
- .minSampleRate = 1.0f,
- .maxSampleRate = 10.0f,
- },
- .initialValue = {.floatValues = {0.0f}}},
- {.config =
- {
- .prop = toInt(VehicleProperty::PERF_REAR_STEERING_ANGLE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
- .minSampleRate = 1.0f,
- .maxSampleRate = 10.0f,
- },
- .initialValue = {.floatValues = {0.0f}}},
- {
- .config =
- {
- .prop = toInt(VehicleProperty::ENGINE_RPM),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
- .minSampleRate = 1.0f,
- .maxSampleRate = 10.0f,
- },
- .initialValue = {.floatValues = {0.0f}},
- },
-
- {.config =
- {
- .prop = toInt(VehicleProperty::FUEL_LEVEL),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
- .minSampleRate = 1.0f,
- .maxSampleRate = 100.0f,
- },
- .initialValue = {.floatValues = {15000.0f}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::FUEL_DOOR_OPEN),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {0}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::EV_BATTERY_LEVEL),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
- .minSampleRate = 1.0f,
- .maxSampleRate = 100.0f,
- },
- .initialValue = {.floatValues = {150000.0f}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::EV_CHARGE_PORT_OPEN),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {0}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::EV_CHARGE_PORT_CONNECTED),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {0}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::EV_BATTERY_INSTANTANEOUS_CHARGE_RATE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
- .minSampleRate = 1.0f,
- .maxSampleRate = 10.0f,
- },
- .initialValue = {.floatValues = {0.0f}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::EV_CHARGE_CURRENT_DRAW_LIMIT),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .configArray = {/*max current draw allowed by vehicle in amperes=*/20},
- },
- .initialValue = {.floatValues = {(float)12.5}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::EV_CHARGE_PERCENT_LIMIT),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .configArray = {20, 40, 60, 80, 100},
- },
- .initialValue = {.floatValues = {40}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::EV_CHARGE_STATE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {2}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::EV_CHARGE_SWITCH),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {0 /* false */}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::EV_CHARGE_TIME_REMAINING),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
- .minSampleRate = 1.0f,
- .maxSampleRate = 10.0f,
- },
- .initialValue = {.int32Values = {20}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::EV_REGENERATIVE_BRAKING_STATE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {2}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::TRAILER_PRESENT),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {2}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::VEHICLE_CURB_WEIGHT),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::STATIC,
- .configArray = {/*gross weight kg=*/2948},
- },
- .initialValue = {.int32Values = {2211 /*kg*/}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::RANGE_REMAINING),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
- .minSampleRate = 1.0f,
- .maxSampleRate = 2.0f,
- },
- .initialValue = {.floatValues = {50000.0f}}}, // units in meters
-
- {.config =
- {
- .prop = toInt(VehicleProperty::TIRE_PRESSURE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
- .areaConfigs = {VehicleAreaConfig{
- .areaId = WHEEL_FRONT_LEFT,
- .minFloatValue = 193.0f,
- .maxFloatValue = 300.0f,
- },
- VehicleAreaConfig{
- .areaId = WHEEL_FRONT_RIGHT,
- .minFloatValue = 193.0f,
- .maxFloatValue = 300.0f,
- },
- VehicleAreaConfig{
- .areaId = WHEEL_REAR_LEFT,
- .minFloatValue = 193.0f,
- .maxFloatValue = 300.0f,
- },
- VehicleAreaConfig{
- .areaId = WHEEL_REAR_RIGHT,
- .minFloatValue = 193.0f,
- .maxFloatValue = 300.0f,
- }},
- .minSampleRate = 1.0f,
- .maxSampleRate = 2.0f,
- },
- .initialValue = {.floatValues = {200.0f}}}, // units in kPa
-
- {.config =
- {
- .prop = toInt(VehicleProperty::CRITICALLY_LOW_TIRE_PRESSURE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::STATIC,
- .areaConfigs = {VehicleAreaConfig{.areaId = WHEEL_FRONT_LEFT},
- VehicleAreaConfig{.areaId = WHEEL_FRONT_RIGHT},
- VehicleAreaConfig{.areaId = WHEEL_REAR_RIGHT},
- VehicleAreaConfig{.areaId = WHEEL_REAR_LEFT}},
- },
- .initialAreaValues = {{WHEEL_FRONT_LEFT, {.floatValues = {137.0f}}},
- {WHEEL_FRONT_RIGHT, {.floatValues = {137.0f}}},
- {WHEEL_REAR_RIGHT, {.floatValues = {137.0f}}},
- {WHEEL_REAR_LEFT, {.floatValues = {137.0f}}}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::TIRE_PRESSURE_DISPLAY_UNITS),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .configArray = {toInt(VehicleUnit::KILOPASCAL), toInt(VehicleUnit::PSI),
- toInt(VehicleUnit::BAR)},
- },
- .initialValue = {.int32Values = {toInt(VehicleUnit::PSI)}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::CURRENT_GEAR),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .configArray = {toInt(VehicleGear::GEAR_PARK),
- toInt(VehicleGear::GEAR_NEUTRAL),
- toInt(VehicleGear::GEAR_REVERSE),
- toInt(VehicleGear::GEAR_1), toInt(VehicleGear::GEAR_2),
- toInt(VehicleGear::GEAR_3), toInt(VehicleGear::GEAR_4),
- toInt(VehicleGear::GEAR_5)},
- },
- .initialValue = {.int32Values = {toInt(VehicleGear::GEAR_PARK)}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::PARKING_BRAKE_ON),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {1}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::PARKING_BRAKE_AUTO_APPLY),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {1}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::FUEL_LEVEL_LOW),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {0}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::FUEL_VOLUME_DISPLAY_UNITS),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .configArray = {(int)VehicleUnit::LITER, (int)VehicleUnit::US_GALLON},
- },
- .initialValue = {.int32Values = {(int)VehicleUnit::US_GALLON}}},
-
- {.config =
- {
- .prop = toInt(
- VehicleProperty::FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {1}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::HW_KEY_INPUT),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {0, 0, 0}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::HW_ROTARY_INPUT),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {0, 0, 0}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::HW_CUSTOM_INPUT),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .configArray = {0, 0, 0, 3, 0, 0, 0, 0, 0},
- },
- .initialValue =
- {
- .int32Values = {0, 0, 0},
- }},
-
- {.config = {.prop = toInt(VehicleProperty::HVAC_ACTUAL_FAN_SPEED_RPM),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
- .initialValue = {.int32Values = {50}}},
-
- {.config = {.prop = toInt(VehicleProperty::HVAC_POWER_ON),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}},
- // TODO(bryaneyler): Ideally, this is generated dynamically from
- // kHvacPowerProperties.
- .configArray = {toInt(VehicleProperty::HVAC_FAN_SPEED),
- toInt(VehicleProperty::HVAC_FAN_DIRECTION)}},
- .initialValue = {.int32Values = {1}}},
-
- {
- .config = {.prop = toInt(VehicleProperty::HVAC_DEFROSTER),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs =
- {VehicleAreaConfig{
- .areaId = toInt(VehicleAreaWindow::FRONT_WINDSHIELD)},
- VehicleAreaConfig{
- .areaId = toInt(VehicleAreaWindow::REAR_WINDSHIELD)}}},
- .initialValue = {.int32Values = {0}} // Will be used for all areas.
- },
- {
- .config = {.prop = toInt(VehicleProperty::HVAC_ELECTRIC_DEFROSTER_ON),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs =
- {VehicleAreaConfig{
- .areaId = toInt(VehicleAreaWindow::FRONT_WINDSHIELD)},
- VehicleAreaConfig{
- .areaId = toInt(VehicleAreaWindow::REAR_WINDSHIELD)}}},
- .initialValue = {.int32Values = {0}} // Will be used for all areas.
- },
-
- {.config = {.prop = toInt(VehicleProperty::HVAC_MAX_DEFROST_ON),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::HVAC_RECIRC_ON),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
- .initialValue = {.int32Values = {1}}},
-
- {.config = {.prop = toInt(VehicleProperty::HVAC_AUTO_RECIRC_ON),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::HVAC_AC_ON),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
- .initialValue = {.int32Values = {1}}},
-
- {.config = {.prop = toInt(VehicleProperty::HVAC_MAX_AC_ON),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::HVAC_AUTO_ON),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
- .initialValue = {.int32Values = {1}}},
-
- {.config = {.prop = toInt(VehicleProperty::HVAC_DUAL_ON),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{
- .areaId = HVAC_ALL, .minInt32Value = 1, .maxInt32Value = 7}}},
- .initialValue = {.int32Values = {3}}},
-
- {.config = {.prop = toInt(VehicleProperty::HVAC_FAN_DIRECTION),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
- .initialValue = {.int32Values = {toInt(VehicleHvacFanDirection::FACE)}}},
-
- {.config = {.prop = toInt(VehicleProperty::HVAC_FAN_DIRECTION_AVAILABLE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::STATIC,
- .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
- .initialValue = {.int32Values = {FAN_DIRECTION_FACE, FAN_DIRECTION_FLOOR,
- FAN_DIRECTION_FACE | FAN_DIRECTION_FLOOR,
- FAN_DIRECTION_DEFROST,
- FAN_DIRECTION_FACE | FAN_DIRECTION_DEFROST,
- FAN_DIRECTION_FLOOR | FAN_DIRECTION_DEFROST,
- FAN_DIRECTION_FLOOR | FAN_DIRECTION_DEFROST |
- FAN_DIRECTION_FACE}}},
- {.config = {.prop = toInt(VehicleProperty::HVAC_SEAT_VENTILATION),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{
- .areaId = SEAT_1_LEFT,
- .minInt32Value = 0,
- .maxInt32Value = 3,
- },
- VehicleAreaConfig{
- .areaId = SEAT_1_RIGHT,
- .minInt32Value = 0,
- .maxInt32Value = 3,
- }}},
- .initialValue =
- {.int32Values = {0}}}, // 0 is off and +ve values indicate ventilation level.
-
- {.config = {.prop = toInt(VehicleProperty::HVAC_STEERING_WHEEL_HEAT),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{
- .areaId = (0), .minInt32Value = -2, .maxInt32Value = 2}}},
- .initialValue = {.int32Values = {0}}}, // +ve values for heating and -ve for cooling
-
- {.config = {.prop = toInt(VehicleProperty::HVAC_SEAT_TEMPERATURE),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{
- .areaId = SEAT_1_LEFT,
- .minInt32Value = -2,
- .maxInt32Value = 2,
- },
- VehicleAreaConfig{
- .areaId = SEAT_1_RIGHT,
- .minInt32Value = -2,
- .maxInt32Value = 2,
- }}},
- .initialValue = {.int32Values = {0}}}, // +ve values for heating and -ve for cooling
-
- {.config = {.prop = toInt(VehicleProperty::HVAC_SIDE_MIRROR_HEAT),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{
- .areaId = toInt(VehicleAreaMirror::DRIVER_LEFT) |
- toInt(VehicleAreaMirror::DRIVER_RIGHT),
- .minInt32Value = 0,
- .maxInt32Value = 2,
- }}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_CURRENT),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_LEFT},
- VehicleAreaConfig{.areaId = HVAC_RIGHT}}},
- .initialAreaValues = {{HVAC_LEFT, {.floatValues = {17.3f}}},
- {HVAC_RIGHT, {.floatValues = {19.1f}}}}},
-
- {.config = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .configArray = {160, 280, 5, 605, 825, 10},
- .areaConfigs = {VehicleAreaConfig{
- .areaId = HVAC_LEFT,
- .minFloatValue = 16,
- .maxFloatValue = 32,
- },
- VehicleAreaConfig{
- .areaId = HVAC_RIGHT,
- .minFloatValue = 16,
- .maxFloatValue = 32,
- }}},
- .initialAreaValues = {{HVAC_LEFT, {.floatValues = {16}}},
- {HVAC_RIGHT, {.floatValues = {20}}}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.floatValues = {66.2f, (float)VehicleUnit::FAHRENHEIT, 19.0f, 66.5f}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::ENV_OUTSIDE_TEMPERATURE),
- .access = VehiclePropertyAccess::READ,
- // TODO(bryaneyler): Support ON_CHANGE as well.
- .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
- .minSampleRate = 1.0f,
- .maxSampleRate = 2.0f,
- },
- .initialValue = {.floatValues = {25.0f}}},
-
- {.config = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_DISPLAY_UNITS),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .configArray = {toInt(VehicleUnit::FAHRENHEIT), toInt(VehicleUnit::CELSIUS)}},
- .initialValue = {.int32Values = {toInt(VehicleUnit::FAHRENHEIT)}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::DISTANCE_DISPLAY_UNITS),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
- .configArray = {toInt(VehicleUnit::KILOMETER), toInt(VehicleUnit::MILE)},
- },
- .initialValue = {.int32Values = {toInt(VehicleUnit::MILE)}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::NIGHT_MODE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {0}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::GEAR_SELECTION),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .configArray = {toInt(VehicleGear::GEAR_PARK),
- toInt(VehicleGear::GEAR_NEUTRAL),
- toInt(VehicleGear::GEAR_REVERSE),
- toInt(VehicleGear::GEAR_DRIVE), toInt(VehicleGear::GEAR_1),
- toInt(VehicleGear::GEAR_2), toInt(VehicleGear::GEAR_3),
- toInt(VehicleGear::GEAR_4), toInt(VehicleGear::GEAR_5)},
- },
- .initialValue = {.int32Values = {toInt(VehicleGear::GEAR_PARK)}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::TURN_SIGNAL_STATE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {toInt(VehicleTurnSignal::NONE)}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::IGNITION_STATE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {toInt(VehicleIgnitionState::ON)}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::ENGINE_COOLANT_TEMP),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
- .minSampleRate = 1.0f,
- .maxSampleRate = 10.0f,
- },
- .initialValue = {.floatValues = {75.0f}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::ENGINE_OIL_LEVEL),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {toInt(VehicleOilLevel::NORMAL)}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::ENGINE_OIL_TEMP),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
- .minSampleRate = 0.1, // 0.1 Hz, every 10 seconds
- .maxSampleRate = 10, // 10 Hz, every 100 ms
- },
- .initialValue = {.floatValues = {101.0f}}},
-
- {
- .config = {.prop = kMixedTypePropertyForTest,
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .configArray = {1, 1, 0, 2, 0, 0, 1, 0, 0}},
- .initialValue =
- {
- .int32Values = {1 /* indicate TRUE boolean value */, 2, 3},
- .floatValues = {4.5f},
- .stringValue = "MIXED property",
- },
- },
-
- {.config = {.prop = toInt(VehicleProperty::DOOR_LOCK),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = DOOR_1_LEFT},
- VehicleAreaConfig{.areaId = DOOR_1_RIGHT},
- VehicleAreaConfig{.areaId = DOOR_2_LEFT},
- VehicleAreaConfig{.areaId = DOOR_2_RIGHT}}},
- .initialAreaValues = {{DOOR_1_LEFT, {.int32Values = {1}}},
- {DOOR_1_RIGHT, {.int32Values = {1}}},
- {DOOR_2_LEFT, {.int32Values = {1}}},
- {DOOR_2_RIGHT, {.int32Values = {1}}}}},
-
- {.config = {.prop = toInt(VehicleProperty::DOOR_POS),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs =
- {VehicleAreaConfig{
- .areaId = DOOR_1_LEFT, .minInt32Value = 0, .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = DOOR_1_RIGHT,
- .minInt32Value = 0,
- .maxInt32Value = 1},
- VehicleAreaConfig{
- .areaId = DOOR_2_LEFT, .minInt32Value = 0, .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = DOOR_2_RIGHT,
- .minInt32Value = 0,
- .maxInt32Value = 1},
- VehicleAreaConfig{
- .areaId = DOOR_REAR, .minInt32Value = 0, .maxInt32Value = 1}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::MIRROR_Z_POS),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs =
- {VehicleAreaConfig{.areaId = toInt(VehicleAreaMirror::DRIVER_LEFT),
- .minInt32Value = -3,
- .maxInt32Value = 3},
- VehicleAreaConfig{.areaId = toInt(VehicleAreaMirror::DRIVER_RIGHT),
- .minInt32Value = -3,
- .maxInt32Value = 3},
- VehicleAreaConfig{.areaId = toInt(VehicleAreaMirror::DRIVER_CENTER),
- .minInt32Value = -3,
- .maxInt32Value = 3}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::MIRROR_Z_MOVE),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs =
- {VehicleAreaConfig{.areaId = toInt(VehicleAreaMirror::DRIVER_LEFT),
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = toInt(VehicleAreaMirror::DRIVER_RIGHT),
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = toInt(VehicleAreaMirror::DRIVER_CENTER),
- .minInt32Value = -1,
- .maxInt32Value = 1}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::MIRROR_Y_POS),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs =
- {VehicleAreaConfig{.areaId = toInt(VehicleAreaMirror::DRIVER_LEFT),
- .minInt32Value = -3,
- .maxInt32Value = 3},
- VehicleAreaConfig{.areaId = toInt(VehicleAreaMirror::DRIVER_RIGHT),
- .minInt32Value = -3,
- .maxInt32Value = 3},
- VehicleAreaConfig{.areaId = toInt(VehicleAreaMirror::DRIVER_CENTER),
- .minInt32Value = -3,
- .maxInt32Value = 3}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::MIRROR_Y_MOVE),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs =
- {VehicleAreaConfig{.areaId = toInt(VehicleAreaMirror::DRIVER_LEFT),
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = toInt(VehicleAreaMirror::DRIVER_RIGHT),
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = toInt(VehicleAreaMirror::DRIVER_CENTER),
- .minInt32Value = -1,
- .maxInt32Value = 1}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::MIRROR_LOCK),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
- .initialValue = {.int32Values = {1}}},
-
- {.config = {.prop = toInt(VehicleProperty::MIRROR_FOLD),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
- .initialValue = {.int32Values = {1}}},
-
- {.config = {.prop = toInt(VehicleProperty::WINDOW_LOCK),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = WINDOW_1_RIGHT | WINDOW_2_LEFT |
- WINDOW_2_RIGHT}}},
- .initialAreaValues = {{WINDOW_1_RIGHT | WINDOW_2_LEFT | WINDOW_2_RIGHT,
- {.int32Values = {0}}}}},
-
- {.config = {.prop = toInt(VehicleProperty::WINDOW_POS),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = WINDOW_1_LEFT,
- .minInt32Value = 0,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = WINDOW_1_RIGHT,
- .minInt32Value = 0,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = WINDOW_2_LEFT,
- .minInt32Value = 0,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = WINDOW_2_RIGHT,
- .minInt32Value = 0,
- .maxInt32Value = 10},
- VehicleAreaConfig{.areaId = WINDOW_ROOF_TOP_1,
- .minInt32Value = -10,
- .maxInt32Value = 10}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::WINDOW_MOVE),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = WINDOW_1_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = WINDOW_1_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = WINDOW_2_LEFT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = WINDOW_2_RIGHT,
- .minInt32Value = -1,
- .maxInt32Value = 1},
- VehicleAreaConfig{.areaId = WINDOW_ROOF_TOP_1,
- .minInt32Value = -1,
- .maxInt32Value = 1}}},
- .initialValue = {.int32Values = {0}}},
-
- {.config =
- {
- .prop = WHEEL_TICK,
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
- .configArray = {ALL_WHEELS, 50000, 50000, 50000, 50000},
- .minSampleRate = 1.0f,
- .maxSampleRate = 10.0f,
- },
- .initialValue = {.int64Values = {0, 100000, 200000, 300000, 400000}}},
-
- {.config = {.prop = ABS_ACTIVE,
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = TRACTION_CONTROL_ACTIVE,
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::AP_POWER_STATE_REQ),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .configArray = {3}}},
-
- {.config = {.prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
- .initialValue = {.int32Values = {toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL), 0}}},
-
- {.config = {.prop = toInt(VehicleProperty::DISPLAY_BRIGHTNESS),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.minInt32Value = 0, .maxInt32Value = 100}}},
- .initialValue = {.int32Values = {100}}},
-
- {
- .config = {.prop = OBD2_LIVE_FRAME,
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .configArray = {0, 0}},
- },
-
- {
- .config = {.prop = OBD2_FREEZE_FRAME,
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .configArray = {0, 0}},
- },
-
- {
- .config = {.prop = OBD2_FREEZE_FRAME_INFO,
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
- },
-
- {
- .config = {.prop = OBD2_FREEZE_FRAME_CLEAR,
- .access = VehiclePropertyAccess::WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .configArray = {1}},
- },
-
- {.config =
- {
- .prop = toInt(VehicleProperty::HEADLIGHTS_STATE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {LIGHT_STATE_ON}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::HIGH_BEAM_LIGHTS_STATE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {LIGHT_STATE_ON}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::FRONT_FOG_LIGHTS_STATE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {LIGHT_STATE_ON}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::REAR_FOG_LIGHTS_STATE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {LIGHT_STATE_ON}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::HAZARD_LIGHTS_STATE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {LIGHT_STATE_ON}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::CABIN_LIGHTS_STATE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {LIGHT_STATE_ON}}},
-
- {.config = {.prop = toInt(VehicleProperty::READING_LIGHTS_STATE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER}}},
- .initialValue = {.int32Values = {LIGHT_STATE_ON}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::HEADLIGHTS_SWITCH),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {LIGHT_SWITCH_AUTO}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::HIGH_BEAM_LIGHTS_SWITCH),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {LIGHT_SWITCH_AUTO}}},
-
- // FOG_LIGHTS_SWITCH must not be implemented when FRONT_FOG_LIGHTS_SWITCH is implemented
- {.config =
- {
- .prop = toInt(VehicleProperty::FRONT_FOG_LIGHTS_SWITCH),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {LIGHT_SWITCH_AUTO}}},
-
- // FOG_LIGHTS_SWITCH must not be implemented when REAR_FOG_LIGHTS_SWITCH is implemented
- {.config =
- {
- .prop = toInt(VehicleProperty::REAR_FOG_LIGHTS_SWITCH),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {LIGHT_SWITCH_AUTO}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::HAZARD_LIGHTS_SWITCH),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {LIGHT_SWITCH_AUTO}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::CABIN_LIGHTS_SWITCH),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {LIGHT_STATE_ON}}},
-
- {.config = {.prop = toInt(VehicleProperty::READING_LIGHTS_SWITCH),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT},
- VehicleAreaConfig{.areaId = SEAT_1_RIGHT},
- VehicleAreaConfig{.areaId = SEAT_2_LEFT},
- VehicleAreaConfig{.areaId = SEAT_2_RIGHT},
- VehicleAreaConfig{.areaId = SEAT_2_CENTER}}},
- .initialValue = {.int32Values = {LIGHT_STATE_ON}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::EVS_SERVICE_REQUEST),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {toInt(EvsServiceType::REARVIEW),
- toInt(EvsServiceState::OFF)}}},
-
- {.config = {.prop = VEHICLE_MAP_SERVICE,
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE}},
-
- // Example Vendor Extension properties for testing
- {.config = {.prop = VENDOR_EXTENSION_BOOLEAN_PROPERTY,
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = DOOR_1_LEFT},
- VehicleAreaConfig{.areaId = DOOR_1_RIGHT},
- VehicleAreaConfig{.areaId = DOOR_2_LEFT},
- VehicleAreaConfig{.areaId = DOOR_2_RIGHT}}},
- .initialAreaValues = {{DOOR_1_LEFT, {.int32Values = {1}}},
- {DOOR_1_RIGHT, {.int32Values = {1}}},
- {DOOR_2_LEFT, {.int32Values = {0}}},
- {DOOR_2_RIGHT, {.int32Values = {0}}}}},
-
- {.config = {.prop = VENDOR_EXTENSION_FLOAT_PROPERTY,
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_LEFT,
- .minFloatValue = -10,
- .maxFloatValue = 10},
- VehicleAreaConfig{.areaId = HVAC_RIGHT,
- .minFloatValue = -10,
- .maxFloatValue = 10}}},
- .initialAreaValues = {{HVAC_LEFT, {.floatValues = {1}}},
- {HVAC_RIGHT, {.floatValues = {2}}}}},
-
- {.config = {.prop = VENDOR_EXTENSION_INT_PROPERTY,
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs =
- {VehicleAreaConfig{.areaId = toInt(VehicleAreaWindow::FRONT_WINDSHIELD),
- .minInt32Value = -100,
- .maxInt32Value = 100},
- VehicleAreaConfig{.areaId = toInt(VehicleAreaWindow::REAR_WINDSHIELD),
- .minInt32Value = -100,
- .maxInt32Value = 100},
- VehicleAreaConfig{.areaId = toInt(VehicleAreaWindow::ROOF_TOP_1),
- .minInt32Value = -100,
- .maxInt32Value = 100}}},
- .initialAreaValues = {{toInt(VehicleAreaWindow::FRONT_WINDSHIELD), {.int32Values = {1}}},
- {toInt(VehicleAreaWindow::REAR_WINDSHIELD), {.int32Values = {0}}},
- {toInt(VehicleAreaWindow::ROOF_TOP_1), {.int32Values = {-1}}}}},
-
- {.config = {.prop = VENDOR_EXTENSION_STRING_PROPERTY,
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
- .initialValue = {.stringValue = "Vendor String Property"}},
-
- {.config = {.prop = toInt(VehicleProperty::ELECTRONIC_TOLL_COLLECTION_CARD_TYPE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
- .initialValue = {.int32Values = {0}}},
-
- {.config = {.prop = toInt(VehicleProperty::ELECTRONIC_TOLL_COLLECTION_CARD_STATUS),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
- .initialValue = {.int32Values = {0}}},
-
- {.config =
- {
- .prop = toInt(VehicleProperty::SUPPORT_CUSTOMIZE_VENDOR_PERMISSION),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .configArray = {kMixedTypePropertyForTest,
- toInt(VehicleVendorPermission::
- PERMISSION_GET_VENDOR_CATEGORY_INFO),
- toInt(VehicleVendorPermission::
- PERMISSION_SET_VENDOR_CATEGORY_INFO),
- VENDOR_EXTENSION_INT_PROPERTY,
- toInt(VehicleVendorPermission::
- PERMISSION_GET_VENDOR_CATEGORY_SEAT),
- toInt(VehicleVendorPermission::PERMISSION_NOT_ACCESSIBLE),
- VENDOR_EXTENSION_FLOAT_PROPERTY,
- toInt(VehicleVendorPermission::PERMISSION_DEFAULT),
- toInt(VehicleVendorPermission::PERMISSION_DEFAULT)},
- },
- .initialValue = {.int32Values = {1}}},
-
- {
- .config =
- {
- .prop = toInt(VehicleProperty::INITIAL_USER_INFO),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- },
- {
- .config =
- {
- .prop = toInt(VehicleProperty::SWITCH_USER),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- },
- {
- .config =
- {
- .prop = toInt(VehicleProperty::CREATE_USER),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- },
- {
- .config =
- {
- .prop = toInt(VehicleProperty::REMOVE_USER),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- },
- {
- .config =
- {
- .prop = toInt(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- },
- {
- .config =
- {
- .prop = toInt(VehicleProperty::POWER_POLICY_REQ),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- },
- {
- .config =
- {
- .prop = toInt(VehicleProperty::POWER_POLICY_GROUP_REQ),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- },
- {
- .config =
- {
- .prop = toInt(VehicleProperty::CURRENT_POWER_POLICY),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- },
- {
- .config =
- {
- .prop = toInt(VehicleProperty::ANDROID_EPOCH_TIME),
- .access = VehiclePropertyAccess::WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- },
- {
- .config =
- {
- .prop = toInt(VehicleProperty::WATCHDOG_ALIVE),
- .access = VehiclePropertyAccess::WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- },
- {
- .config =
- {
- .prop = toInt(VehicleProperty::WATCHDOG_TERMINATED_PROCESS),
- .access = VehiclePropertyAccess::WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- },
- {
- .config =
- {
- .prop = toInt(VehicleProperty::VHAL_HEARTBEAT),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- },
- {
- .config =
- {
- .prop = toInt(VehicleProperty::CLUSTER_SWITCH_UI),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {0 /* ClusterHome */}},
- },
- {
- .config =
- {
- .prop = toInt(VehicleProperty::CLUSTER_DISPLAY_STATE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {0 /* Off */, -1, -1, -1, -1 /* Bounds */, -1, -1,
- -1, -1 /* Insets */}},
- },
- {
- .config =
- {
- .prop = toInt(VehicleProperty::CLUSTER_REPORT_STATE),
- .access = VehiclePropertyAccess::WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .configArray = {0, 0, 0, 11, 0, 0, 0, 0, 16},
- },
- },
- {
- .config =
- {
- .prop = toInt(VehicleProperty::CLUSTER_REQUEST_DISPLAY),
- .access = VehiclePropertyAccess::WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- },
- {
- .config =
- {
- .prop = toInt(VehicleProperty::CLUSTER_NAVIGATION_STATE),
- .access = VehiclePropertyAccess::WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- },
- {
- .config =
- {
- .prop = PLACEHOLDER_PROPERTY_INT,
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {0}},
- },
- {
- .config =
- {
- .prop = PLACEHOLDER_PROPERTY_FLOAT,
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.floatValues = {0.0f}},
- },
- {
- .config =
- {
- .prop = PLACEHOLDER_PROPERTY_BOOLEAN,
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {0 /* false */}},
- },
- {
- .config =
- {
- .prop = PLACEHOLDER_PROPERTY_STRING,
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.stringValue = {"Test"}},
- },
- {
- .config =
- {
- .prop = ECHO_REVERSE_BYTES,
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- },
-#ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
- // Vendor propetry for E2E ClusterHomeService testing.
- {
- .config =
- {
- .prop = VENDOR_CLUSTER_SWITCH_UI,
- .access = VehiclePropertyAccess::WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- },
- {
- .config =
- {
- .prop = VENDOR_CLUSTER_DISPLAY_STATE,
- .access = VehiclePropertyAccess::WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- },
- {
- .config =
- {
- .prop = VENDOR_CLUSTER_REPORT_STATE,
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .configArray = {0, 0, 0, 11, 0, 0, 0, 0, 16},
- },
- .initialValue = {.int32Values = {0 /* Off */, -1, -1, -1, -1 /* Bounds */, -1, -1,
- -1, -1 /* Insets */, 0 /* ClusterHome */,
- -1 /* ClusterNone */}},
- },
- {
- .config =
- {
- .prop = VENDOR_CLUSTER_REQUEST_DISPLAY,
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- .initialValue = {.int32Values = {0 /* ClusterHome */}},
- },
- {
- .config =
- {
- .prop = VENDOR_CLUSTER_NAVIGATION_STATE,
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
- },
-#endif // ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
-};
-
-} // namespace defaultconfig_impl
-
-// public namespace
-namespace defaultconfig {
-
-typedef defaultconfig_impl::ConfigDeclaration ConfigDeclaration;
-
-inline constexpr const std::vector<ConfigDeclaration>& getDefaultConfigs() {
- return defaultconfig_impl::kVehicleProperties;
-}
-
-} // namespace defaultconfig
-
-} // namespace vehicle
-} // namespace automotive
-} // namespace hardware
-} // namespace android
-
-#endif // android_hardware_automotive_vehicle_aidl_impl_default_config_include_DefaultConfig_H_
diff --git a/automotive/vehicle/aidl/impl/default_config/test/Android.bp b/automotive/vehicle/aidl/impl/default_config/test/Android.bp
index 771472c..8702eae 100644
--- a/automotive/vehicle/aidl/impl/default_config/test/Android.bp
+++ b/automotive/vehicle/aidl/impl/default_config/test/Android.bp
@@ -24,11 +24,47 @@
defaults: ["VehicleHalDefaults"],
srcs: ["*.cpp"],
static_libs: [
+ "VehicleHalJsonConfigLoader",
"VehicleHalUtils",
+ "libgmock",
"libgtest",
],
header_libs: [
- "VehicleHalDefaultConfig",
+ "IVehicleGeneratedHeaders",
+ ],
+ shared_libs: [
+ "libjsoncpp",
+ ],
+ data: [
+ ":VehicleHalDefaultProperties_JSON",
+ ],
+ test_suites: ["device-tests"],
+}
+
+cc_test {
+ name: "VehicleHalDefaultConfigTestEnableTestProperties",
+ vendor: true,
+ defaults: ["VehicleHalDefaults"],
+ srcs: ["*.cpp"],
+ static_libs: [
+ "VehicleHalJsonConfigLoaderEnableTestProperties",
+ "VehicleHalUtils",
+ "libgmock",
+ "libgtest",
+ ],
+ cflags: [
+ "-DENABLE_VEHICLE_HAL_TEST_PROPERTIES",
+ ],
+ header_libs: [
+ "IVehicleGeneratedHeaders",
+ ],
+ shared_libs: [
+ "libjsoncpp",
+ ],
+ data: [
+ ":VehicleHalDefaultProperties_JSON",
+ ":VehicleHalTestProperties_JSON",
+ ":VehicleHalVendorClusterTestProperties_JSON",
],
test_suites: ["device-tests"],
}
diff --git a/automotive/vehicle/aidl/impl/default_config/test/DefaultConfigTest.cpp b/automotive/vehicle/aidl/impl/default_config/test/DefaultConfigTest.cpp
index baaae75..95fecfe 100644
--- a/automotive/vehicle/aidl/impl/default_config/test/DefaultConfigTest.cpp
+++ b/automotive/vehicle/aidl/impl/default_config/test/DefaultConfigTest.cpp
@@ -14,27 +14,75 @@
* limitations under the License.
*/
-#include <DefaultConfig.h>
+#include <JsonConfigLoader.h>
#include <VehicleUtils.h>
+#include <android-base/file.h>
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <fstream>
+#include <unordered_map>
namespace android {
namespace hardware {
namespace automotive {
namespace vehicle {
-namespace defaultconfig {
namespace test {
-TEST(DefaultConfigTest, loadDefaultConfigs) {
- for (ConfigDeclaration config : getDefaultConfigs()) {
- ASSERT_NE(0, config.config.prop);
- }
+using ::android::base::Error;
+using ::android::base::Result;
+using ::testing::UnorderedElementsAreArray;
+
+constexpr char kDefaultPropertiesConfigFile[] = "DefaultProperties.json";
+
+#ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES
+constexpr char kTestPropertiesConfigFile[] = "TestProperties.json";
+constexpr char kVendorClusterTestPropertiesConfigFile[] = "VendorClusterTestProperties.json";
+#endif // ENABLE_VEHICLE_HAL_TEST_PROPERTIES
+
+std::string getTestFilePath(const char* filename) {
+ static std::string baseDir = android::base::GetExecutableDirectory();
+ return baseDir + "/" + filename;
}
+Result<std::unordered_map<int32_t, ConfigDeclaration>> loadConfig(JsonConfigLoader& loader,
+ const char* path) {
+ std::string configPath = getTestFilePath(path);
+ std::ifstream ifs(configPath.c_str());
+ if (!ifs) {
+ return Error() << "couldn't open %s for parsing." << configPath;
+ }
+
+ return loader.loadPropConfig(ifs);
+}
+
+TEST(DefaultConfigTest, TestloadDefaultProperties) {
+ JsonConfigLoader loader;
+ auto result = loadConfig(loader, kDefaultPropertiesConfigFile);
+
+ ASSERT_TRUE(result.ok()) << result.error().message();
+}
+
+#ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES
+
+TEST(DefaultConfigTest, TestloadTestProperties) {
+ JsonConfigLoader loader;
+ auto result = loadConfig(loader, kTestPropertiesConfigFile);
+
+ ASSERT_TRUE(result.ok()) << result.error().message();
+}
+
+TEST(DefaultConfigTest, TestloadVendorClusterTestProperties) {
+ JsonConfigLoader loader;
+ auto result = loadConfig(loader, kVendorClusterTestPropertiesConfigFile);
+
+ ASSERT_TRUE(result.ok()) << result.error().message();
+}
+
+#endif // ENABLE_VEHICLE_HAL_TEST_PROPERTIES
+
} // namespace test
-} // namespace defaultconfig
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/GeneratorHub.h b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/GeneratorHub.h
index 9f112ae..f96b6ec 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/GeneratorHub.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/GeneratorHub.h
@@ -54,8 +54,8 @@
void registerGenerator(int32_t generatorId, std::unique_ptr<FakeValueGenerator> generator);
// Unregister a generator with the generatorId. If no registered generator is found, this
- // function does nothing.
- void unregisterGenerator(int32_t generatorId);
+ // function does nothing. Returns true if the generator is unregistered.
+ bool unregisterGenerator(int32_t generatorId);
private:
struct VhalEvent {
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/JsonFakeValueGenerator.h b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/JsonFakeValueGenerator.h
index d421ac5..42b1bd3 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/JsonFakeValueGenerator.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/include/JsonFakeValueGenerator.h
@@ -45,6 +45,9 @@
// 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);
+ // Create a new JSON fake value generator using the JSON content. The first argument is just
+ // used to differentiate this function with the one that takes path as input.
+ explicit JsonFakeValueGenerator(bool unused, const std::string& content, int32_t iteration);
~JsonFakeValueGenerator() = default;
@@ -53,6 +56,9 @@
const std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>&
getAllEvents();
+ // Whether there are events left to replay for this generator.
+ bool hasNext();
+
private:
size_t mEventIndex = 0;
std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue> mEvents;
@@ -60,7 +66,8 @@
int32_t mNumOfIterations = 0;
void setBit(std::vector<uint8_t>& bytes, size_t idx);
- void init(const std::string& path, int32_t iteration);
+ void initWithPath(const std::string& path, int32_t iteration);
+ void initWithStream(std::istream& is, int32_t iteration);
};
} // namespace fake
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/GeneratorHub.cpp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/GeneratorHub.cpp
index 0c182d9..d815456 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/GeneratorHub.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/GeneratorHub.cpp
@@ -29,11 +29,18 @@
using ::android::base::ScopedLockAssertion;
-GeneratorHub::GeneratorHub(OnHalEvent&& onHalEvent)
- : mOnHalEvent(onHalEvent), mThread(&GeneratorHub::run, this) {}
+GeneratorHub::GeneratorHub(OnHalEvent&& onHalEvent) : mOnHalEvent(onHalEvent) {
+ mThread = std::thread(&GeneratorHub::run, this);
+}
GeneratorHub::~GeneratorHub() {
- mShuttingDownFlag.store(true);
+ {
+ // Even if the shared variable is atomic, it must be modified under the
+ // mutex in order to correctly publish the modification to the waiting
+ // thread.
+ std::unique_lock<std::mutex> lock(mGeneratorsLock);
+ mShuttingDownFlag.store(true);
+ }
mCond.notify_all();
if (mThread.joinable()) {
mThread.join();
@@ -58,13 +65,15 @@
mCond.notify_one();
}
-void GeneratorHub::unregisterGenerator(int32_t id) {
+bool GeneratorHub::unregisterGenerator(int32_t id) {
+ bool removed;
{
std::scoped_lock<std::mutex> lockGuard(mGeneratorsLock);
- mGenerators.erase(id);
+ removed = mGenerators.erase(id);
}
mCond.notify_one();
ALOGI("%s: Unregistered generator, id: %d", __func__, id);
+ return removed;
}
void GeneratorHub::run() {
diff --git a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/JsonFakeValueGenerator.cpp b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/JsonFakeValueGenerator.cpp
index d4d52a5..cb42317 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/JsonFakeValueGenerator.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/GeneratorHub/src/JsonFakeValueGenerator.cpp
@@ -173,12 +173,11 @@
} // namespace
-JsonFakeValueGenerator::JsonFakeValueGenerator(const std::string& path) {
- init(path, 1);
-}
+JsonFakeValueGenerator::JsonFakeValueGenerator(const std::string& path)
+ : JsonFakeValueGenerator(path, /*iteration=*/1) {}
JsonFakeValueGenerator::JsonFakeValueGenerator(const std::string& path, int32_t iteration) {
- init(path, iteration);
+ initWithPath(path, iteration);
}
JsonFakeValueGenerator::JsonFakeValueGenerator(const VehiclePropValue& request) {
@@ -186,16 +185,26 @@
// Iterate infinitely if iteration number is not provided
int32_t numOfIterations = v.int32Values.size() < 2 ? -1 : v.int32Values[1];
- init(v.stringValue, numOfIterations);
+ initWithPath(v.stringValue, numOfIterations);
}
-void JsonFakeValueGenerator::init(const std::string& path, int32_t iteration) {
+JsonFakeValueGenerator::JsonFakeValueGenerator([[maybe_unused]] bool unused,
+ const std::string& content, int32_t iteration) {
+ std::istringstream iss(content);
+ initWithStream(iss, iteration);
+}
+
+void JsonFakeValueGenerator::initWithPath(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);
+ initWithStream(ifs, iteration);
+}
+
+void JsonFakeValueGenerator::initWithStream(std::istream& is, int32_t iteration) {
+ mEvents = parseFakeValueJson(is);
mNumOfIterations = iteration;
}
@@ -235,12 +244,15 @@
mNumOfIterations--;
}
}
-
generatedValue.timestamp = mLastEventTimestamp;
return generatedValue;
}
+bool JsonFakeValueGenerator::hasNext() {
+ return mNumOfIterations != 0 && mEvents.size() > 0;
+}
+
} // namespace fake
} // namespace vehicle
} // namespace automotive
diff --git a/automotive/vehicle/aidl/impl/fake_impl/README.md b/automotive/vehicle/aidl/impl/fake_impl/README.md
new file mode 100644
index 0000000..e86dcee
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/README.md
@@ -0,0 +1,28 @@
+# Fake reference AIDL VHAL implementation libraries
+---
+
+This directory stores libraries for implementing a fake reference AIDL VHAL.
+
+WARNING: All the libraries here are for TEST ONLY.
+
+## GeneratorHub
+
+Defines a library `FakeVehicleHalValueGenerators` that could generate fake
+vehicle property values for testing.
+
+## hardware
+
+Defines a fake implementation for device-specifc interface `IVehicleHardware`:
+`FakeVehicleHardware`. This implementation uses a in-memory map for storing
+property values and does not communicate with or depending on any specific
+vehicle bus.
+
+## obd2frame
+
+Defines a library `FakeObd2Frame` that generates fake OBD2 frame for OBD2
+properties.
+
+## userhal
+
+Defines a library `FakeUserHal` that emulates a real User HAL behavior by
+parsing debug commands.
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/Android.bp b/automotive/vehicle/aidl/impl/fake_impl/hardware/Android.bp
index dcd9208..4c17cde 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/Android.bp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/Android.bp
@@ -24,6 +24,7 @@
srcs: ["src/*.cpp"],
local_include_dirs: ["include"],
export_include_dirs: ["include"],
+ cflags: ["-DENABLE_VEHICLE_HAL_TEST_PROPERTIES"],
defaults: [
"VehicleHalDefaults",
"FakeVehicleHardwareDefaults",
@@ -32,18 +33,23 @@
cc_defaults {
name: "FakeVehicleHardwareDefaults",
- cflags: ["-DENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING"],
header_libs: [
"IVehicleHardware",
- "VehicleHalDefaultConfig",
+ "VehicleHalTestUtilHeaders",
],
export_header_lib_headers: ["IVehicleHardware"],
static_libs: [
+ "VehicleHalJsonConfigLoaderEnableTestProperties",
"VehicleHalUtils",
"FakeVehicleHalValueGenerators",
"FakeObd2Frame",
"FakeUserHal",
],
+ required: [
+ "Prebuilt_VehicleHalDefaultProperties_JSON",
+ "Prebuilt_VehicleHalTestProperties_JSON",
+ "Prebuilt_VehicleHalVendorClusterTestProperties_JSON",
+ ],
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 34b2b24..c3ebd3b 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
@@ -18,21 +18,24 @@
#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_hardware_include_FakeVehicleHardware_H_
#include <ConcurrentQueue.h>
-#include <DefaultConfig.h>
+#include <ConfigDeclaration.h>
#include <FakeObd2Frame.h>
#include <FakeUserHal.h>
+#include <GeneratorHub.h>
#include <IVehicleHardware.h>
+#include <JsonConfigLoader.h>
#include <RecurrentTimer.h>
#include <VehicleHalTypes.h>
#include <VehiclePropertyStore.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleHwKeyInputAction.h>
#include <android-base/parseint.h>
#include <android-base/result.h>
#include <android-base/stringprintf.h>
#include <android-base/thread_annotations.h>
-#include <map>
#include <memory>
#include <mutex>
+#include <unordered_map>
#include <vector>
namespace android {
@@ -47,7 +50,8 @@
FakeVehicleHardware();
- explicit FakeVehicleHardware(std::unique_ptr<VehiclePropValuePool> valuePool);
+ FakeVehicleHardware(std::string defaultConfigDir, std::string overrideConfigDir,
+ bool forceOverride);
~FakeVehicleHardware();
@@ -132,11 +136,18 @@
const std::unique_ptr<FakeUserHal> mFakeUserHal;
// RecurrentTimer is thread-safe.
std::unique_ptr<RecurrentTimer> mRecurrentTimer;
+ // GeneratorHub is thread-safe.
+ std::unique_ptr<GeneratorHub> mGeneratorHub;
+
+ // Only allowed to set once.
+ std::unique_ptr<const PropertyChangeCallback> mOnPropertyChangeCallback;
+ std::unique_ptr<const PropertySetErrorCallback> mOnPropertySetErrorCallback;
+
std::mutex mLock;
- std::unique_ptr<const PropertyChangeCallback> mOnPropertyChangeCallback GUARDED_BY(mLock);
- std::unique_ptr<const PropertySetErrorCallback> mOnPropertySetErrorCallback GUARDED_BY(mLock);
std::unordered_map<PropIdAreaId, std::shared_ptr<RecurrentTimer::Callback>, PropIdAreaIdHash>
mRecurrentActions GUARDED_BY(mLock);
+ std::unordered_map<PropIdAreaId, VehiclePropValuePool::RecyclableType, PropIdAreaIdHash>
+ mSavedProps GUARDED_BY(mLock);
// PendingRequestHandler is thread-safe.
mutable PendingRequestHandler<GetValuesCallback,
aidl::android::hardware::automotive::vehicle::GetValueRequest>
@@ -145,18 +156,36 @@
aidl::android::hardware::automotive::vehicle::SetValueRequest>
mPendingSetValueRequests;
+ const std::string mDefaultConfigDir;
+ const std::string mOverrideConfigDir;
+ const bool mForceOverride;
+ bool mAddExtraTestVendorConfigs;
+
+ // Only used during initialization.
+ JsonConfigLoader mLoader;
+
void init();
// Stores the initial value to property store.
- void storePropInitialValue(const defaultconfig::ConfigDeclaration& config);
+ void storePropInitialValue(const ConfigDeclaration& config);
// The callback that would be called when a vehicle property value change happens.
void onValueChangeCallback(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
- // If property "persist.vendor.vhal_init_value_override" is set to true, override the properties
- // using config files in 'overrideDir'.
- void maybeOverrideProperties(const char* overrideDir);
- // Override the properties using config files in 'overrideDir'.
- void overrideProperties(const char* overrideDir);
+ // Load the config files in format '*.json' from the directory and parse the config files
+ // into a map from property ID to ConfigDeclarations.
+ void loadPropConfigsFromDir(const std::string& dirPath,
+ std::unordered_map<int32_t, ConfigDeclaration>* configs);
+ // Function to be called when a value change event comes from vehicle bus. In our fake
+ // implementation, this function is only called during "--inject-event" dump command.
+ void eventFromVehicleBus(
+ const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
+ int getHvacTempNumIncrements(int requestedTemp, int minTemp, int maxTemp, int increment);
+ void updateHvacTemperatureValueSuggestionInput(
+ const std::vector<int>& hvacTemperatureSetConfigArray,
+ std::vector<float>* hvacTemperatureValueSuggestionInput);
+ VhalResult<void> setHvacTemperatureValueSuggestion(
+ const aidl::android::hardware::automotive::vehicle::VehiclePropValue&
+ hvacTemperatureValueSuggestion);
VhalResult<void> maybeSetSpecialValue(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
bool* isSpecialValue);
@@ -167,13 +196,18 @@
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
VehiclePropValuePool::RecyclableType createApPowerStateReq(
aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq state);
+ VehiclePropValuePool::RecyclableType createAdasStateReq(int32_t propertyId, int32_t areaId,
+ int32_t state);
VhalResult<void> setUserHalProp(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
ValueResultType getUserHalProp(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const;
ValueResultType getEchoReverseBytes(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const;
- bool isHvacPropAndHvacNotAvailable(int32_t propId);
+ bool isHvacPropAndHvacNotAvailable(int32_t propId, int32_t areaId) const;
+ VhalResult<void> isAdasPropertyAvailable(int32_t adasStatePropertyId) const;
+
+ std::unordered_map<int32_t, ConfigDeclaration> loadConfigDeclarations();
std::string dumpAllProperties();
std::string dumpOnePropertyByConfig(
@@ -184,6 +218,10 @@
std::string dumpListProperties();
std::string dumpSpecificProperty(const std::vector<std::string>& options);
std::string dumpSetProperties(const std::vector<std::string>& options);
+ std::string dumpGetPropertyWithArg(const std::vector<std::string>& options);
+ std::string dumpSaveProperty(const std::vector<std::string>& options);
+ std::string dumpRestoreProperty(const std::vector<std::string>& options);
+ std::string dumpInjectEvent(const std::vector<std::string>& options);
template <typename T>
android::base::Result<T> safelyParseInt(int index, const std::string& s) {
@@ -198,7 +236,7 @@
std::vector<std::string> getOptionValues(const std::vector<std::string>& options,
size_t* index);
android::base::Result<aidl::android::hardware::automotive::vehicle::VehiclePropValue>
- parseSetPropOptions(const std::vector<std::string>& options);
+ parsePropOptions(const std::vector<std::string>& options);
android::base::Result<std::vector<uint8_t>> parseHexString(const std::string& s);
android::base::Result<void> checkArgumentsSize(const std::vector<std::string>& options,
@@ -207,6 +245,26 @@
const aidl::android::hardware::automotive::vehicle::GetValueRequest& request);
aidl::android::hardware::automotive::vehicle::SetValueResult handleSetValueRequest(
const aidl::android::hardware::automotive::vehicle::SetValueRequest& request);
+
+ std::string genFakeDataCommand(const std::vector<std::string>& options);
+ void sendHvacPropertiesCurrentValues(int32_t areaId);
+ void sendAdasPropertiesState(int32_t propertyId, int32_t state);
+ void generateVendorConfigs(
+ std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>&) const;
+
+ static aidl::android::hardware::automotive::vehicle::VehiclePropValue createHwInputKeyProp(
+ aidl::android::hardware::automotive::vehicle::VehicleHwKeyInputAction action,
+ int32_t keyCode, int32_t targetDisplay);
+ static aidl::android::hardware::automotive::vehicle::VehiclePropValue createHwKeyInputV2Prop(
+ int32_t area, int32_t targetDisplay, int32_t keyCode, int32_t action,
+ int32_t repeatCount);
+ static aidl::android::hardware::automotive::vehicle::VehiclePropValue createHwMotionInputProp(
+ int32_t area, int32_t display, int32_t inputType, int32_t action, int32_t buttonState,
+ int32_t pointerCount, int32_t pointerId[], int32_t toolType[], float xData[],
+ float yData[], float pressure[], float size[]);
+
+ static std::string genFakeDataHelp();
+ static std::string parseErrMsg(std::string fieldName, std::string value, std::string type);
};
} // namespace fake
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 20c34aa..3f5e4c4 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -15,24 +15,29 @@
*/
#define LOG_TAG "FakeVehicleHardware"
+#define ATRACE_TAG ATRACE_TAG_HAL
#define FAKE_VEHICLEHARDWARE_DEBUG false // STOPSHIP if true.
#include "FakeVehicleHardware.h"
-#include <DefaultConfig.h>
#include <FakeObd2Frame.h>
#include <JsonFakeValueGenerator.h>
+#include <LinearFakeValueGenerator.h>
#include <PropertyUtils.h>
#include <TestPropertyUtils.h>
#include <VehicleHalTypes.h>
#include <VehicleUtils.h>
+
+#include <android-base/file.h>
#include <android-base/parsedouble.h>
#include <android-base/properties.h>
#include <android-base/strings.h>
#include <utils/Log.h>
#include <utils/SystemClock.h>
+#include <utils/Trace.h>
#include <dirent.h>
+#include <inttypes.h>
#include <sys/types.h>
#include <fstream>
#include <regex>
@@ -47,6 +52,7 @@
namespace {
+using ::aidl::android::hardware::automotive::vehicle::ErrorState;
using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
@@ -55,24 +61,50 @@
using ::aidl::android::hardware::automotive::vehicle::StatusCode;
using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReport;
using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq;
+using ::aidl::android::hardware::automotive::vehicle::VehicleHwKeyInputAction;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+using ::aidl::android::hardware::automotive::vehicle::VehicleUnit;
using ::android::base::EqualsIgnoreCase;
using ::android::base::Error;
+using ::android::base::GetIntProperty;
using ::android::base::ParseFloat;
using ::android::base::Result;
using ::android::base::ScopedLockAssertion;
using ::android::base::StartsWith;
using ::android::base::StringPrintf;
-const char* VENDOR_OVERRIDE_DIR = "/vendor/etc/automotive/vhaloverride/";
-const char* OVERRIDE_PROPERTY = "persist.vendor.vhal_init_value_override";
-
+// In order to test large number of vehicle property configs, we might generate additional fake
+// property config start from this ID. These fake properties are for getPropertyList,
+// getPropertiesAsync, and setPropertiesAsync.
+// 0x21403000
+constexpr int32_t STARTING_VENDOR_CODE_PROPERTIES_FOR_TEST =
+ 0x3000 | toInt(testpropertyutils_impl::VehiclePropertyGroup::VENDOR) |
+ toInt(testpropertyutils_impl::VehicleArea::GLOBAL) |
+ toInt(testpropertyutils_impl::VehiclePropertyType::INT32);
+// 0x21405000
+constexpr int32_t ENDING_VENDOR_CODE_PROPERTIES_FOR_TEST =
+ 0x5000 | toInt(testpropertyutils_impl::VehiclePropertyGroup::VENDOR) |
+ toInt(testpropertyutils_impl::VehicleArea::GLOBAL) |
+ toInt(testpropertyutils_impl::VehiclePropertyType::INT32);
+// The directory for default property configuration file.
+// For config file format, see impl/default_config/config/README.md.
+constexpr char DEFAULT_CONFIG_DIR[] = "/vendor/etc/automotive/vhalconfig/";
+// The directory for property configuration file that overrides the default configuration file.
+// For config file format, see impl/default_config/config/README.md.
+constexpr char OVERRIDE_CONFIG_DIR[] = "/vendor/etc/automotive/vhaloverride/";
+// If OVERRIDE_PROPERTY is set, we will use the configuration files from OVERRIDE_CONFIG_DIR to
+// overwrite the default configs.
+constexpr char OVERRIDE_PROPERTY[] = "persist.vendor.vhal_init_value_override";
+constexpr char POWER_STATE_REQ_CONFIG_PROPERTY[] = "ro.vendor.fake_vhal.ap_power_state_req.config";
+// The value to be returned if VENDOR_PROPERTY_ID is set as the property
+constexpr int VENDOR_ERROR_CODE = 0x00ab0005;
// A list of supported options for "--set" command.
const std::unordered_set<std::string> SET_PROP_OPTIONS = {
// integer.
@@ -86,11 +118,81 @@
// bytes in hex format, e.g. 0xDEADBEEF.
"-b",
// Area id in integer.
- "-a"};
+ "-a",
+ // Timestamp in int64.
+ "-t"};
+// ADAS _ENABLED property to list of ADAS state properties using ErrorState enum.
+const std::unordered_map<int32_t, std::vector<int32_t>> mAdasEnabledPropToAdasPropWithErrorState = {
+ // AEB
+ {
+ toInt(VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_ENABLED),
+ {
+ toInt(VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_STATE),
+ },
+ },
+ // FCW
+ {
+ toInt(VehicleProperty::FORWARD_COLLISION_WARNING_ENABLED),
+ {
+ toInt(VehicleProperty::FORWARD_COLLISION_WARNING_STATE),
+ },
+ },
+ // BSW
+ {
+ toInt(VehicleProperty::BLIND_SPOT_WARNING_ENABLED),
+ {
+ toInt(VehicleProperty::BLIND_SPOT_WARNING_STATE),
+ },
+ },
+ // LDW
+ {
+ toInt(VehicleProperty::LANE_DEPARTURE_WARNING_ENABLED),
+ {
+ toInt(VehicleProperty::LANE_DEPARTURE_WARNING_STATE),
+ },
+ },
+ // LKA
+ {
+ toInt(VehicleProperty::LANE_KEEP_ASSIST_ENABLED),
+ {
+ toInt(VehicleProperty::LANE_KEEP_ASSIST_STATE),
+ },
+ },
+ // LCA
+ {
+ toInt(VehicleProperty::LANE_CENTERING_ASSIST_ENABLED),
+ {
+ toInt(VehicleProperty::LANE_CENTERING_ASSIST_STATE),
+ },
+ },
+ // ELKA
+ {
+ toInt(VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_ENABLED),
+ {
+ toInt(VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_STATE),
+ },
+ },
+ // CC
+ {
+ toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
+ {
+ toInt(VehicleProperty::CRUISE_CONTROL_TYPE),
+ toInt(VehicleProperty::CRUISE_CONTROL_STATE),
+ },
+ },
+ // HOD
+ {
+ toInt(VehicleProperty::HANDS_ON_DETECTION_ENABLED),
+ {
+ toInt(VehicleProperty::HANDS_ON_DETECTION_DRIVER_STATE),
+ toInt(VehicleProperty::HANDS_ON_DETECTION_WARNING),
+ },
+ },
+};
} // namespace
-void FakeVehicleHardware::storePropInitialValue(const defaultconfig::ConfigDeclaration& config) {
+void FakeVehicleHardware::storePropInitialValue(const ConfigDeclaration& config) {
const VehiclePropConfig& vehiclePropConfig = config.config;
int propId = vehiclePropConfig.prop;
@@ -132,30 +234,50 @@
}
FakeVehicleHardware::FakeVehicleHardware()
- : FakeVehicleHardware(std::make_unique<VehiclePropValuePool>()) {}
+ : FakeVehicleHardware(DEFAULT_CONFIG_DIR, OVERRIDE_CONFIG_DIR, false) {}
-FakeVehicleHardware::FakeVehicleHardware(std::unique_ptr<VehiclePropValuePool> valuePool)
- : mValuePool(std::move(valuePool)),
+FakeVehicleHardware::FakeVehicleHardware(std::string defaultConfigDir,
+ std::string overrideConfigDir, bool forceOverride)
+ : mValuePool(std::make_unique<VehiclePropValuePool>()),
mServerSidePropStore(new VehiclePropertyStore(mValuePool)),
mFakeObd2Frame(new obd2frame::FakeObd2Frame(mServerSidePropStore)),
mFakeUserHal(new FakeUserHal(mValuePool)),
mRecurrentTimer(new RecurrentTimer()),
+ mGeneratorHub(new GeneratorHub(
+ [this](const VehiclePropValue& value) { eventFromVehicleBus(value); })),
mPendingGetValueRequests(this),
- mPendingSetValueRequests(this) {
+ mPendingSetValueRequests(this),
+ mDefaultConfigDir(defaultConfigDir),
+ mOverrideConfigDir(overrideConfigDir),
+ mForceOverride(forceOverride) {
init();
}
FakeVehicleHardware::~FakeVehicleHardware() {
mPendingGetValueRequests.stop();
mPendingSetValueRequests.stop();
+ mGeneratorHub.reset();
+}
+
+std::unordered_map<int32_t, ConfigDeclaration> FakeVehicleHardware::loadConfigDeclarations() {
+ std::unordered_map<int32_t, ConfigDeclaration> configsByPropId;
+ loadPropConfigsFromDir(mDefaultConfigDir, &configsByPropId);
+ if (mForceOverride ||
+ android::base::GetBoolProperty(OVERRIDE_PROPERTY, /*default_value=*/false)) {
+ loadPropConfigsFromDir(mOverrideConfigDir, &configsByPropId);
+ }
+ return configsByPropId;
}
void FakeVehicleHardware::init() {
- for (auto& it : defaultconfig::getDefaultConfigs()) {
- VehiclePropConfig cfg = it.config;
+ for (auto& [_, configDeclaration] : loadConfigDeclarations()) {
+ VehiclePropConfig cfg = configDeclaration.config;
VehiclePropertyStore::TokenFunction tokenFunction = nullptr;
- if (cfg.prop == OBD2_FREEZE_FRAME) {
+ if (cfg.prop == toInt(VehicleProperty::AP_POWER_STATE_REQ)) {
+ int config = GetIntProperty(POWER_STATE_REQ_CONFIG_PROPERTY, /*default_value=*/0);
+ cfg.configArray[0] = config;
+ } else if (cfg.prop == OBD2_FREEZE_FRAME) {
tokenFunction = [](const VehiclePropValue& propValue) { return propValue.timestamp; };
}
@@ -165,22 +287,29 @@
// logic.
continue;
}
- storePropInitialValue(it);
+ storePropInitialValue(configDeclaration);
}
- 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());
+ auto maybeObd2LiveFrame = mServerSidePropStore->getConfig(OBD2_LIVE_FRAME);
+ if (maybeObd2LiveFrame.has_value()) {
+ mFakeObd2Frame->initObd2LiveFrame(*maybeObd2LiveFrame.value());
+ }
+ auto maybeObd2FreezeFrame = mServerSidePropStore->getConfig(OBD2_FREEZE_FRAME);
+ if (maybeObd2FreezeFrame.has_value()) {
+ mFakeObd2Frame->initObd2FreezeFrame(*maybeObd2FreezeFrame.value());
+ }
mServerSidePropStore->setOnValueChangeCallback(
[this](const VehiclePropValue& value) { return onValueChangeCallback(value); });
}
std::vector<VehiclePropConfig> FakeVehicleHardware::getAllPropertyConfigs() const {
- return mServerSidePropStore->getAllConfigs();
+ std::vector<VehiclePropConfig> allConfigs = mServerSidePropStore->getAllConfigs();
+ if (mAddExtraTestVendorConfigs) {
+ generateVendorConfigs(/* outAllConfigs= */ allConfigs);
+ }
+ return allConfigs;
}
VehiclePropValuePool::RecyclableType FakeVehicleHardware::createApPowerStateReq(
@@ -196,6 +325,18 @@
return req;
}
+VehiclePropValuePool::RecyclableType FakeVehicleHardware::createAdasStateReq(int32_t propertyId,
+ int32_t areaId,
+ int32_t state) {
+ auto req = mValuePool->obtain(VehiclePropertyType::INT32);
+ req->prop = propertyId;
+ req->areaId = areaId;
+ req->timestamp = elapsedRealtimeNano();
+ req->status = VehiclePropertyStatus::AVAILABLE;
+ req->value.int32Values[0] = state;
+ return req;
+}
+
VhalResult<void> FakeVehicleHardware::setApPowerStateReport(const VehiclePropValue& value) {
auto updatedValue = mValuePool->obtain(value);
updatedValue->timestamp = elapsedRealtimeNano();
@@ -257,21 +398,155 @@
return {};
}
-bool FakeVehicleHardware::isHvacPropAndHvacNotAvailable(int32_t propId) {
+int FakeVehicleHardware::getHvacTempNumIncrements(int requestedTemp, int minTemp, int maxTemp,
+ int increment) {
+ requestedTemp = std::max(requestedTemp, minTemp);
+ requestedTemp = std::min(requestedTemp, maxTemp);
+ int numIncrements = (requestedTemp - minTemp) / increment;
+ return numIncrements;
+}
+
+void FakeVehicleHardware::updateHvacTemperatureValueSuggestionInput(
+ const std::vector<int>& hvacTemperatureSetConfigArray,
+ std::vector<float>* hvacTemperatureValueSuggestionInput) {
+ int minTempInCelsius = hvacTemperatureSetConfigArray[0];
+ int maxTempInCelsius = hvacTemperatureSetConfigArray[1];
+ int incrementInCelsius = hvacTemperatureSetConfigArray[2];
+
+ int minTempInFahrenheit = hvacTemperatureSetConfigArray[3];
+ int maxTempInFahrenheit = hvacTemperatureSetConfigArray[4];
+ int incrementInFahrenheit = hvacTemperatureSetConfigArray[5];
+
+ // The HVAC_TEMPERATURE_SET config array values are temperature values that have been multiplied
+ // by 10 and converted to integers. Therefore, requestedTemp must also be multiplied by 10 and
+ // converted to an integer in order for them to be the same units.
+ int requestedTemp = static_cast<int>((*hvacTemperatureValueSuggestionInput)[0] * 10.0f);
+ int numIncrements =
+ (*hvacTemperatureValueSuggestionInput)[1] == toInt(VehicleUnit::CELSIUS)
+ ? getHvacTempNumIncrements(requestedTemp, minTempInCelsius, maxTempInCelsius,
+ incrementInCelsius)
+ : getHvacTempNumIncrements(requestedTemp, minTempInFahrenheit,
+ maxTempInFahrenheit, incrementInFahrenheit);
+
+ int suggestedTempInCelsius = minTempInCelsius + incrementInCelsius * numIncrements;
+ int suggestedTempInFahrenheit = minTempInFahrenheit + incrementInFahrenheit * numIncrements;
+ // HVAC_TEMPERATURE_VALUE_SUGGESTION specifies the temperature values to be in the original
+ // floating point form so we divide by 10 and convert to float.
+ (*hvacTemperatureValueSuggestionInput)[2] = static_cast<float>(suggestedTempInCelsius) / 10.0f;
+ (*hvacTemperatureValueSuggestionInput)[3] =
+ static_cast<float>(suggestedTempInFahrenheit) / 10.0f;
+}
+
+VhalResult<void> FakeVehicleHardware::setHvacTemperatureValueSuggestion(
+ const VehiclePropValue& hvacTemperatureValueSuggestion) {
+ auto hvacTemperatureSetConfigResult =
+ mServerSidePropStore->getConfig(toInt(VehicleProperty::HVAC_TEMPERATURE_SET));
+
+ if (!hvacTemperatureSetConfigResult.ok()) {
+ return StatusError(getErrorCode(hvacTemperatureSetConfigResult)) << StringPrintf(
+ "Failed to set HVAC_TEMPERATURE_VALUE_SUGGESTION because"
+ " HVAC_TEMPERATURE_SET could not be retrieved. Error: %s",
+ getErrorMsg(hvacTemperatureSetConfigResult).c_str());
+ }
+
+ const auto& originalInput = hvacTemperatureValueSuggestion.value.floatValues;
+ if (originalInput.size() != 4) {
+ return StatusError(StatusCode::INVALID_ARG) << StringPrintf(
+ "Failed to set HVAC_TEMPERATURE_VALUE_SUGGESTION because float"
+ " array value is not size 4.");
+ }
+
+ bool isTemperatureUnitSpecified = originalInput[1] == toInt(VehicleUnit::CELSIUS) ||
+ originalInput[1] == toInt(VehicleUnit::FAHRENHEIT);
+ if (!isTemperatureUnitSpecified) {
+ return StatusError(StatusCode::INVALID_ARG) << StringPrintf(
+ "Failed to set HVAC_TEMPERATURE_VALUE_SUGGESTION because float"
+ " value at index 1 is not any of %d or %d, which corresponds to"
+ " VehicleUnit#CELSIUS and VehicleUnit#FAHRENHEIT respectively.",
+ toInt(VehicleUnit::CELSIUS), toInt(VehicleUnit::FAHRENHEIT));
+ }
+
+ auto updatedValue = mValuePool->obtain(hvacTemperatureValueSuggestion);
+ const auto& hvacTemperatureSetConfigArray = hvacTemperatureSetConfigResult.value()->configArray;
+ auto& hvacTemperatureValueSuggestionInput = updatedValue->value.floatValues;
+
+ updateHvacTemperatureValueSuggestionInput(hvacTemperatureSetConfigArray,
+ &hvacTemperatureValueSuggestionInput);
+
+ updatedValue->timestamp = elapsedRealtimeNano();
+ auto writeResult = mServerSidePropStore->writeValue(std::move(updatedValue),
+ /* updateStatus = */ true,
+ VehiclePropertyStore::EventMode::ALWAYS);
+ if (!writeResult.ok()) {
+ return StatusError(getErrorCode(writeResult))
+ << StringPrintf("failed to write value into property store, error: %s",
+ getErrorMsg(writeResult).c_str());
+ }
+
+ return {};
+}
+
+bool FakeVehicleHardware::isHvacPropAndHvacNotAvailable(int32_t propId, int32_t areaId) const {
std::unordered_set<int32_t> powerProps(std::begin(HVAC_POWER_PROPERTIES),
std::end(HVAC_POWER_PROPERTIES));
if (powerProps.count(propId)) {
- auto hvacPowerOnResult =
- mServerSidePropStore->readValue(toInt(VehicleProperty::HVAC_POWER_ON), HVAC_ALL);
-
- if (hvacPowerOnResult.ok() && hvacPowerOnResult.value()->value.int32Values.size() == 1 &&
- hvacPowerOnResult.value()->value.int32Values[0] == 0) {
- return true;
+ auto hvacPowerOnResults =
+ mServerSidePropStore->readValuesForProperty(toInt(VehicleProperty::HVAC_POWER_ON));
+ if (!hvacPowerOnResults.ok()) {
+ ALOGW("failed to get HVAC_POWER_ON 0x%x, error: %s",
+ toInt(VehicleProperty::HVAC_POWER_ON), getErrorMsg(hvacPowerOnResults).c_str());
+ return false;
+ }
+ auto& hvacPowerOnValues = hvacPowerOnResults.value();
+ for (size_t j = 0; j < hvacPowerOnValues.size(); j++) {
+ auto hvacPowerOnValue = std::move(hvacPowerOnValues[j]);
+ if ((hvacPowerOnValue->areaId & areaId) == areaId) {
+ if (hvacPowerOnValue->value.int32Values.size() == 1 &&
+ hvacPowerOnValue->value.int32Values[0] == 0) {
+ return true;
+ }
+ break;
+ }
}
}
return false;
}
+VhalResult<void> FakeVehicleHardware::isAdasPropertyAvailable(int32_t adasStatePropertyId) const {
+ auto adasStateResult = mServerSidePropStore->readValue(adasStatePropertyId);
+ if (!adasStateResult.ok()) {
+ ALOGW("Failed to get ADAS ENABLED property 0x%x, error: %s", adasStatePropertyId,
+ getErrorMsg(adasStateResult).c_str());
+ return {};
+ }
+
+ if (adasStateResult.value()->value.int32Values.size() == 1 &&
+ adasStateResult.value()->value.int32Values[0] < 0) {
+ auto errorState = adasStateResult.value()->value.int32Values[0];
+ switch (errorState) {
+ case toInt(ErrorState::NOT_AVAILABLE_DISABLED):
+ return StatusError(StatusCode::NOT_AVAILABLE_DISABLED)
+ << "ADAS feature is disabled.";
+ case toInt(ErrorState::NOT_AVAILABLE_SPEED_LOW):
+ return StatusError(StatusCode::NOT_AVAILABLE_SPEED_LOW)
+ << "ADAS feature is disabled because the vehicle speed is too low.";
+ case toInt(ErrorState::NOT_AVAILABLE_SPEED_HIGH):
+ return StatusError(StatusCode::NOT_AVAILABLE_SPEED_HIGH)
+ << "ADAS feature is disabled because the vehicle speed is too high.";
+ case toInt(ErrorState::NOT_AVAILABLE_POOR_VISIBILITY):
+ return StatusError(StatusCode::NOT_AVAILABLE_POOR_VISIBILITY)
+ << "ADAS feature is disabled because the visibility is too poor.";
+ case toInt(ErrorState::NOT_AVAILABLE_SAFETY):
+ return StatusError(StatusCode::NOT_AVAILABLE_SAFETY)
+ << "ADAS feature is disabled because of safety reasons.";
+ default:
+ return StatusError(StatusCode::NOT_AVAILABLE) << "ADAS feature is not available.";
+ }
+ }
+
+ return {};
+}
+
VhalResult<void> FakeVehicleHardware::setUserHalProp(const VehiclePropValue& value) {
auto result = mFakeUserHal->onSetProperty(value);
if (!result.ok()) {
@@ -282,7 +557,11 @@
if (updatedValue != nullptr) {
ALOGI("onSetProperty(): updating property returned by HAL: %s",
updatedValue->toString().c_str());
- if (auto writeResult = mServerSidePropStore->writeValue(std::move(result.value()));
+ // Update timestamp otherwise writeValue might fail because the timestamp is outdated.
+ updatedValue->timestamp = elapsedRealtimeNano();
+ if (auto writeResult = mServerSidePropStore->writeValue(
+ std::move(result.value()),
+ /*updateStatus=*/true, VehiclePropertyStore::EventMode::ALWAYS);
!writeResult.ok()) {
return StatusError(getErrorCode(writeResult))
<< "failed to write value into property store, error: "
@@ -319,11 +598,27 @@
int32_t propId = value.prop;
ValueResultType result;
+ if (propId >= STARTING_VENDOR_CODE_PROPERTIES_FOR_TEST &&
+ propId < ENDING_VENDOR_CODE_PROPERTIES_FOR_TEST) {
+ *isSpecialValue = true;
+ result = mValuePool->obtainInt32(/* value= */ 5);
+
+ result.value()->prop = propId;
+ result.value()->areaId = 0;
+ result.value()->timestamp = elapsedRealtimeNano();
+ return result;
+ }
+
if (mFakeUserHal->isSupported(propId)) {
*isSpecialValue = true;
return getUserHalProp(value);
}
+ if (isHvacPropAndHvacNotAvailable(propId, value.areaId)) {
+ *isSpecialValue = true;
+ return StatusError(StatusCode::NOT_AVAILABLE_DISABLED) << "hvac not available";
+ }
+
switch (propId) {
case OBD2_FREEZE_FRAME:
*isSpecialValue = true;
@@ -342,6 +637,22 @@
case ECHO_REVERSE_BYTES:
*isSpecialValue = true;
return getEchoReverseBytes(value);
+ case VENDOR_PROPERTY_ID:
+ *isSpecialValue = true;
+ return StatusError((StatusCode)VENDOR_ERROR_CODE);
+ case toInt(VehicleProperty::CRUISE_CONTROL_TARGET_SPEED):
+ [[fallthrough]];
+ case toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP):
+ [[fallthrough]];
+ case toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_LEAD_VEHICLE_MEASURED_DISTANCE): {
+ auto isAdasPropertyAvailableResult =
+ isAdasPropertyAvailable(toInt(VehicleProperty::CRUISE_CONTROL_STATE));
+ if (!isAdasPropertyAvailableResult.ok()) {
+ *isSpecialValue = true;
+ return isAdasPropertyAvailableResult.error();
+ }
+ return nullptr;
+ }
default:
// Do nothing.
break;
@@ -366,20 +677,85 @@
return std::move(gotValue);
}
+void FakeVehicleHardware::sendHvacPropertiesCurrentValues(int32_t areaId) {
+ for (size_t i = 0; i < sizeof(HVAC_POWER_PROPERTIES) / sizeof(int32_t); i++) {
+ int powerPropId = HVAC_POWER_PROPERTIES[i];
+ auto powerPropResults = mServerSidePropStore->readValuesForProperty(powerPropId);
+ if (!powerPropResults.ok()) {
+ ALOGW("failed to get power prop 0x%x, error: %s", powerPropId,
+ getErrorMsg(powerPropResults).c_str());
+ continue;
+ }
+ auto& powerPropValues = powerPropResults.value();
+ for (size_t j = 0; j < powerPropValues.size(); j++) {
+ auto powerPropValue = std::move(powerPropValues[j]);
+ if ((powerPropValue->areaId & areaId) == powerPropValue->areaId) {
+ powerPropValue->status = VehiclePropertyStatus::AVAILABLE;
+ powerPropValue->timestamp = elapsedRealtimeNano();
+ // This will trigger a property change event for the current hvac property value.
+ mServerSidePropStore->writeValue(std::move(powerPropValue), /*updateStatus=*/true,
+ VehiclePropertyStore::EventMode::ALWAYS);
+ }
+ }
+ }
+}
+
+void FakeVehicleHardware::sendAdasPropertiesState(int32_t propertyId, int32_t state) {
+ auto& adasDependentPropIds = mAdasEnabledPropToAdasPropWithErrorState.find(propertyId)->second;
+ for (auto dependentPropId : adasDependentPropIds) {
+ auto dependentPropConfigResult = mServerSidePropStore->getConfig(dependentPropId);
+ if (!dependentPropConfigResult.ok()) {
+ ALOGW("Failed to get config for ADAS property 0x%x, error: %s", dependentPropId,
+ getErrorMsg(dependentPropConfigResult).c_str());
+ continue;
+ }
+ auto& dependentPropConfig = dependentPropConfigResult.value();
+ for (auto& areaConfig : dependentPropConfig->areaConfigs) {
+ auto propValue = createAdasStateReq(dependentPropId, areaConfig.areaId, state);
+ // This will trigger a property change event for the current ADAS property value.
+ mServerSidePropStore->writeValue(std::move(propValue), /*updateStatus=*/true,
+ VehiclePropertyStore::EventMode::ALWAYS);
+ }
+ }
+}
+
VhalResult<void> FakeVehicleHardware::maybeSetSpecialValue(const VehiclePropValue& value,
bool* isSpecialValue) {
*isSpecialValue = false;
VehiclePropValuePool::RecyclableType updatedValue;
int32_t propId = value.prop;
+ if (propId >= STARTING_VENDOR_CODE_PROPERTIES_FOR_TEST &&
+ propId < ENDING_VENDOR_CODE_PROPERTIES_FOR_TEST) {
+ *isSpecialValue = true;
+ return {};
+ }
+
if (mFakeUserHal->isSupported(propId)) {
*isSpecialValue = true;
return setUserHalProp(value);
}
- if (isHvacPropAndHvacNotAvailable(propId)) {
+ if (propId == toInt(VehicleProperty::HVAC_POWER_ON) && value.value.int32Values.size() == 1 &&
+ value.value.int32Values[0] == 1) {
+ // If we are turning HVAC power on, send current hvac property values through on change
+ // event.
+ sendHvacPropertiesCurrentValues(value.areaId);
+ }
+
+ if (isHvacPropAndHvacNotAvailable(propId, value.areaId)) {
*isSpecialValue = true;
- return StatusError(StatusCode::NOT_AVAILABLE) << "hvac not available";
+ return StatusError(StatusCode::NOT_AVAILABLE_DISABLED) << "hvac not available";
+ }
+
+ if (mAdasEnabledPropToAdasPropWithErrorState.count(propId) &&
+ value.value.int32Values.size() == 1) {
+ if (value.value.int32Values[0] == 1) {
+ // Set default state to 1 when ADAS feature is enabled.
+ sendAdasPropertiesState(propId, /* state = */ 1);
+ } else {
+ sendAdasPropertiesState(propId, toInt(ErrorState::NOT_AVAILABLE_DISABLED));
+ }
}
switch (propId) {
@@ -394,8 +770,32 @@
case OBD2_FREEZE_FRAME_CLEAR:
*isSpecialValue = true;
return mFakeObd2Frame->clearObd2FreezeFrames(value);
+ case VENDOR_PROPERTY_ID:
+ *isSpecialValue = true;
+ return StatusError((StatusCode)VENDOR_ERROR_CODE);
+ case toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION):
+ *isSpecialValue = true;
+ return setHvacTemperatureValueSuggestion(value);
+ case toInt(VehicleProperty::LANE_CENTERING_ASSIST_COMMAND): {
+ auto isAdasPropertyAvailableResult =
+ isAdasPropertyAvailable(toInt(VehicleProperty::LANE_CENTERING_ASSIST_STATE));
+ if (!isAdasPropertyAvailableResult.ok()) {
+ *isSpecialValue = true;
+ }
+ return isAdasPropertyAvailableResult;
+ }
+ case toInt(VehicleProperty::CRUISE_CONTROL_COMMAND):
+ [[fallthrough]];
+ case toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP): {
+ auto isAdasPropertyAvailableResult =
+ isAdasPropertyAvailable(toInt(VehicleProperty::CRUISE_CONTROL_STATE));
+ if (!isAdasPropertyAvailableResult.ok()) {
+ *isSpecialValue = true;
+ }
+ return isAdasPropertyAvailableResult;
+ }
-#ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
+#ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES
case toInt(VehicleProperty::CLUSTER_REPORT_STATE):
[[fallthrough]];
case toInt(VehicleProperty::CLUSTER_REQUEST_DISPLAY):
@@ -423,7 +823,7 @@
<< getErrorMsg(writeResult);
}
return {};
-#endif // ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
+#endif // ENABLE_VEHICLE_HAL_TEST_PROPERTIES
default:
break;
@@ -454,7 +854,6 @@
// Here we are just updating mValuePool.
bool isSpecialValue = false;
auto setSpecialValueResult = maybeSetSpecialValue(value, &isSpecialValue);
-
if (isSpecialValue) {
if (!setSpecialValueResult.ok()) {
return StatusError(getErrorCode(setSpecialValueResult))
@@ -574,34 +973,447 @@
result.buffer = dumpListProperties();
} else if (EqualsIgnoreCase(option, "--get")) {
result.buffer = dumpSpecificProperty(options);
+ } else if (EqualsIgnoreCase(option, "--getWithArg")) {
+ result.buffer = dumpGetPropertyWithArg(options);
} else if (EqualsIgnoreCase(option, "--set")) {
result.buffer = dumpSetProperties(options);
+ } else if (EqualsIgnoreCase(option, "--save-prop")) {
+ result.buffer = dumpSaveProperty(options);
+ } else if (EqualsIgnoreCase(option, "--restore-prop")) {
+ result.buffer = dumpRestoreProperty(options);
+ } else if (EqualsIgnoreCase(option, "--inject-event")) {
+ result.buffer = dumpInjectEvent(options);
} else if (EqualsIgnoreCase(option, kUserHalDumpOption)) {
- if (options.size() == 1) {
- result.buffer = mFakeUserHal->showDumpHelp();
- } else {
- result.buffer = mFakeUserHal->dump(options[1]);
- }
+ result.buffer = mFakeUserHal->dump();
+ } else if (EqualsIgnoreCase(option, "--genfakedata")) {
+ result.buffer = genFakeDataCommand(options);
+ } else if (EqualsIgnoreCase(option, "--genTestVendorConfigs")) {
+ mAddExtraTestVendorConfigs = true;
+ result.refreshPropertyConfigs = true;
+ } else if (EqualsIgnoreCase(option, "--restoreVendorConfigs")) {
+ mAddExtraTestVendorConfigs = false;
+ result.refreshPropertyConfigs = true;
} else {
result.buffer = StringPrintf("Invalid option: %s\n", option.c_str());
}
return result;
}
+std::string FakeVehicleHardware::genFakeDataHelp() {
+ return R"(
+Generate Fake Data Usage:
+--genfakedata --startlinear [propID] [mValue] [cValue] [dispersion] [increment] [interval]: "
+Start a linear generator that generates event with floatValue within range:
+[mValue - disperson, mValue + dispersion].
+propID(int32): ID for the property to generate event for.
+mValue(float): The middle of the possible values for the property.
+cValue(float): The start value for the property, must be within the range.
+dispersion(float): The range the value can change.
+increment(float): The step the value would increase by for each generated event,
+if exceed the range, the value would loop back.
+interval(int64): The interval in nanoseconds the event would generate by.
+
+--genfakedata --stoplinear [propID(int32)]: Stop a linear generator
+
+--genfakedata --startjson --path [jsonFilePath] [repetition]:
+Start a JSON generator that would generate events according to a JSON file.
+jsonFilePath(string): The path to a JSON file. The JSON content must be in the format of
+[{
+ "timestamp": 1000000,
+ "areaId": 0,
+ "value": 8,
+ "prop": 289408000
+}, {...}]
+Each event in the JSON file would be generated by the same interval their timestamp is relative to
+the first event's timestamp.
+repetition(int32, optional): how many iterations the events would be generated. If it is not
+provided, it would iterate indefinitely.
+
+--genfakedata --startjson --content [jsonContent]: Start a JSON generator using the content.
+
+--genfakedata --stopjson [generatorID(string)]: Stop a JSON generator.
+
+--genfakedata --keypress [keyCode(int32)] [display[int32]]: Generate key press.
+
+--genfakedata --keyinputv2 [area(int32)] [display(int32)] [keyCode[int32]] [action[int32]]
+ [repeatCount(int32)]
+
+--genfakedata --motioninput [area(int32)] [display(int32)] [inputType[int32]] [action[int32]]
+ [buttonState(int32)] --pointer [pointerId(int32)] [toolType(int32)] [xData(float)] [yData(float)]
+ [pressure(float)] [size(float)]
+ Generate a motion input event. --pointer option can be specified multiple times.
+
+--genTestVendorConfigs: Generates fake VehiclePropConfig ranging from 0x5000 to 0x8000 all with
+ vendor property group, global vehicle area, and int32 vehicle property type. This is mainly used
+ for testing
+
+--restoreVendorConfigs: Restores to to the default state if genTestVendorConfigs was used.
+ Otherwise this will do nothing.
+
+)";
+}
+
+std::string FakeVehicleHardware::parseErrMsg(std::string fieldName, std::string value,
+ std::string type) {
+ return StringPrintf("failed to parse %s as %s: \"%s\"\n%s", fieldName.c_str(), type.c_str(),
+ value.c_str(), genFakeDataHelp().c_str());
+}
+
+void FakeVehicleHardware::generateVendorConfigs(
+ std::vector<VehiclePropConfig>& outAllConfigs) const {
+ for (int i = STARTING_VENDOR_CODE_PROPERTIES_FOR_TEST;
+ i < ENDING_VENDOR_CODE_PROPERTIES_FOR_TEST; i++) {
+ VehiclePropConfig config;
+ config.prop = i;
+ config.access = VehiclePropertyAccess::READ_WRITE;
+ outAllConfigs.push_back(config);
+ }
+}
+
+std::string FakeVehicleHardware::genFakeDataCommand(const std::vector<std::string>& options) {
+ if (options.size() < 2) {
+ return "No subcommand specified for genfakedata\n" + genFakeDataHelp();
+ }
+
+ std::string command = options[1];
+ if (command == "--startlinear") {
+ // --genfakedata --startlinear [propID(int32)] [middleValue(float)]
+ // [currentValue(float)] [dispersion(float)] [increment(float)] [interval(int64)]
+ if (options.size() != 8) {
+ return "incorrect argument count, need 8 arguments for --genfakedata --startlinear\n" +
+ genFakeDataHelp();
+ }
+ int32_t propId;
+ float middleValue;
+ float currentValue;
+ float dispersion;
+ float increment;
+ int64_t interval;
+ if (!android::base::ParseInt(options[2], &propId)) {
+ return parseErrMsg("propId", options[2], "int");
+ }
+ if (!android::base::ParseFloat(options[3], &middleValue)) {
+ return parseErrMsg("middleValue", options[3], "float");
+ }
+ if (!android::base::ParseFloat(options[4], ¤tValue)) {
+ return parseErrMsg("currentValue", options[4], "float");
+ }
+ if (!android::base::ParseFloat(options[5], &dispersion)) {
+ return parseErrMsg("dispersion", options[5], "float");
+ }
+ if (!android::base::ParseFloat(options[6], &increment)) {
+ return parseErrMsg("increment", options[6], "float");
+ }
+ if (!android::base::ParseInt(options[7], &interval)) {
+ return parseErrMsg("interval", options[7], "int");
+ }
+ auto generator = std::make_unique<LinearFakeValueGenerator>(
+ propId, middleValue, currentValue, dispersion, increment, interval);
+ mGeneratorHub->registerGenerator(propId, std::move(generator));
+ return "Linear event generator started successfully";
+ } else if (command == "--stoplinear") {
+ // --genfakedata --stoplinear [propID(int32)]
+ if (options.size() != 3) {
+ return "incorrect argument count, need 3 arguments for --genfakedata --stoplinear\n" +
+ genFakeDataHelp();
+ }
+ int32_t propId;
+ if (!android::base::ParseInt(options[2], &propId)) {
+ return parseErrMsg("propId", options[2], "int");
+ }
+ if (mGeneratorHub->unregisterGenerator(propId)) {
+ return "Linear event generator stopped successfully";
+ }
+ return StringPrintf("No linear event generator found for property: %d", propId);
+ } else if (command == "--startjson") {
+ // --genfakedata --startjson --path path repetition
+ // or
+ // --genfakedata --startjson --content content repetition.
+ if (options.size() != 4 && options.size() != 5) {
+ return "incorrect argument count, need 4 or 5 arguments for --genfakedata "
+ "--startjson\n";
+ }
+ // Iterate infinitely if repetition number is not provided
+ int32_t repetition = -1;
+ if (options.size() == 5) {
+ if (!android::base::ParseInt(options[4], &repetition)) {
+ return parseErrMsg("repetition", options[4], "int");
+ }
+ }
+ std::unique_ptr<JsonFakeValueGenerator> generator;
+ if (options[2] == "--path") {
+ const std::string& fileName = options[3];
+ generator = std::make_unique<JsonFakeValueGenerator>(fileName, repetition);
+ if (!generator->hasNext()) {
+ return "invalid JSON file, no events";
+ }
+ } else if (options[2] == "--content") {
+ const std::string& content = options[3];
+ generator =
+ std::make_unique<JsonFakeValueGenerator>(/*unused=*/true, content, repetition);
+ if (!generator->hasNext()) {
+ return "invalid JSON content, no events";
+ }
+ }
+ int32_t cookie = std::hash<std::string>()(options[3]);
+ mGeneratorHub->registerGenerator(cookie, std::move(generator));
+ return StringPrintf("JSON event generator started successfully, ID: %" PRId32, cookie);
+ } else if (command == "--stopjson") {
+ // --genfakedata --stopjson [generatorID(string)]
+ if (options.size() != 3) {
+ return "incorrect argument count, need 3 arguments for --genfakedata --stopjson\n";
+ }
+ int32_t cookie;
+ if (!android::base::ParseInt(options[2], &cookie)) {
+ return parseErrMsg("cookie", options[2], "int");
+ }
+ if (mGeneratorHub->unregisterGenerator(cookie)) {
+ return "JSON event generator stopped successfully";
+ } else {
+ return StringPrintf("No JSON event generator found for ID: %s", options[2].c_str());
+ }
+ } else if (command == "--keypress") {
+ int32_t keyCode;
+ int32_t display;
+ // --genfakedata --keypress [keyCode(int32)] [display[int32]]
+ if (options.size() != 4) {
+ return "incorrect argument count, need 4 arguments for --genfakedata --keypress\n";
+ }
+ if (!android::base::ParseInt(options[2], &keyCode)) {
+ return parseErrMsg("keyCode", options[2], "int");
+ }
+ if (!android::base::ParseInt(options[3], &display)) {
+ return parseErrMsg("display", options[3], "int");
+ }
+ // Send back to HAL
+ onValueChangeCallback(
+ createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_DOWN, keyCode, display));
+ onValueChangeCallback(
+ createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display));
+ return "keypress event generated successfully";
+ } else if (command == "--keyinputv2") {
+ int32_t area;
+ int32_t display;
+ int32_t keyCode;
+ int32_t action;
+ int32_t repeatCount;
+ // --genfakedata --keyinputv2 [area(int32)] [display(int32)] [keyCode[int32]]
+ // [action[int32]] [repeatCount(int32)]
+ if (options.size() != 7) {
+ return "incorrect argument count, need 7 arguments for --genfakedata --keyinputv2\n";
+ }
+ if (!android::base::ParseInt(options[2], &area)) {
+ return parseErrMsg("area", options[2], "int");
+ }
+ if (!android::base::ParseInt(options[3], &display)) {
+ return parseErrMsg("display", options[3], "int");
+ }
+ if (!android::base::ParseInt(options[4], &keyCode)) {
+ return parseErrMsg("keyCode", options[4], "int");
+ }
+ if (!android::base::ParseInt(options[5], &action)) {
+ return parseErrMsg("action", options[5], "int");
+ }
+ if (!android::base::ParseInt(options[6], &repeatCount)) {
+ return parseErrMsg("repeatCount", options[6], "int");
+ }
+ // Send back to HAL
+ onValueChangeCallback(createHwKeyInputV2Prop(area, display, keyCode, action, repeatCount));
+ return StringPrintf(
+ "keyinputv2 event generated successfully with area:%d, display:%d,"
+ " keyCode:%d, action:%d, repeatCount:%d",
+ area, display, keyCode, action, repeatCount);
+
+ } else if (command == "--motioninput") {
+ int32_t area;
+ int32_t display;
+ int32_t inputType;
+ int32_t action;
+ int32_t buttonState;
+ int32_t pointerCount;
+
+ // --genfakedata --motioninput [area(int32)] [display(int32)] [inputType[int32]]
+ // [action[int32]] [buttonState(int32)] [pointerCount(int32)]
+ // --pointer [pointerId(int32)] [toolType(int32)] [xData(float)] [yData(float)]
+ // [pressure(float)] [size(float)]
+ int optionsSize = (int)options.size();
+ if (optionsSize / 7 < 2) {
+ return "incorrect argument count, need at least 14 arguments for --genfakedata "
+ "--motioninput including at least 1 --pointer\n";
+ }
+
+ if (optionsSize % 7 != 0) {
+ return "incorrect argument count, need 6 arguments for every --pointer\n";
+ }
+ pointerCount = (int)optionsSize / 7 - 1;
+
+ if (!android::base::ParseInt(options[2], &area)) {
+ return parseErrMsg("area", options[2], "int");
+ }
+ if (!android::base::ParseInt(options[3], &display)) {
+ return parseErrMsg("display", options[3], "int");
+ }
+ if (!android::base::ParseInt(options[4], &inputType)) {
+ return parseErrMsg("inputType", options[4], "int");
+ }
+ if (!android::base::ParseInt(options[5], &action)) {
+ return parseErrMsg("action", options[5], "int");
+ }
+ if (!android::base::ParseInt(options[6], &buttonState)) {
+ return parseErrMsg("buttonState", options[6], "int");
+ }
+
+ int32_t pointerId[pointerCount];
+ int32_t toolType[pointerCount];
+ float xData[pointerCount];
+ float yData[pointerCount];
+ float pressure[pointerCount];
+ float size[pointerCount];
+
+ for (int i = 7, pc = 0; i < optionsSize; i += 7, pc += 1) {
+ int offset = i;
+ if (options[offset] != "--pointer") {
+ return "--pointer is needed for the motion input\n";
+ }
+ offset += 1;
+ if (!android::base::ParseInt(options[offset], &pointerId[pc])) {
+ return parseErrMsg("pointerId", options[offset], "int");
+ }
+ offset += 1;
+ if (!android::base::ParseInt(options[offset], &toolType[pc])) {
+ return parseErrMsg("toolType", options[offset], "int");
+ }
+ offset += 1;
+ if (!android::base::ParseFloat(options[offset], &xData[pc])) {
+ return parseErrMsg("xData", options[offset], "float");
+ }
+ offset += 1;
+ if (!android::base::ParseFloat(options[offset], &yData[pc])) {
+ return parseErrMsg("yData", options[offset], "float");
+ }
+ offset += 1;
+ if (!android::base::ParseFloat(options[offset], &pressure[pc])) {
+ return parseErrMsg("pressure", options[offset], "float");
+ }
+ offset += 1;
+ if (!android::base::ParseFloat(options[offset], &size[pc])) {
+ return parseErrMsg("size", options[offset], "float");
+ }
+ }
+
+ // Send back to HAL
+ onValueChangeCallback(createHwMotionInputProp(area, display, inputType, action, buttonState,
+ pointerCount, pointerId, toolType, xData,
+ yData, pressure, size));
+
+ std::string successMessage = StringPrintf(
+ "motion event generated successfully with area:%d, display:%d,"
+ " inputType:%d, action:%d, buttonState:%d, pointerCount:%d\n",
+ area, display, inputType, action, buttonState, pointerCount);
+ for (int i = 0; i < pointerCount; i++) {
+ successMessage += StringPrintf(
+ "Pointer #%d {\n"
+ " id:%d , tooltype:%d \n"
+ " x:%f , y:%f\n"
+ " pressure: %f, data: %f\n"
+ "}\n",
+ i, pointerId[i], toolType[i], xData[i], yData[i], pressure[i], size[i]);
+ }
+ return successMessage;
+ }
+
+ return StringPrintf("Unknown command: \"%s\"\n%s", command.c_str(), genFakeDataHelp().c_str());
+}
+
+VehiclePropValue FakeVehicleHardware::createHwInputKeyProp(VehicleHwKeyInputAction action,
+ int32_t keyCode, int32_t targetDisplay) {
+ VehiclePropValue value = {
+ .prop = toInt(VehicleProperty::HW_KEY_INPUT),
+ .areaId = 0,
+ .timestamp = elapsedRealtimeNano(),
+ .status = VehiclePropertyStatus::AVAILABLE,
+ .value.int32Values = {toInt(action), keyCode, targetDisplay},
+ };
+ return value;
+}
+
+VehiclePropValue FakeVehicleHardware::createHwKeyInputV2Prop(int32_t area, int32_t targetDisplay,
+ int32_t keyCode, int32_t action,
+ int32_t repeatCount) {
+ VehiclePropValue value = {.prop = toInt(VehicleProperty::HW_KEY_INPUT_V2),
+ .areaId = area,
+ .timestamp = elapsedRealtimeNano(),
+ .status = VehiclePropertyStatus::AVAILABLE,
+ .value.int32Values = {targetDisplay, keyCode, action, repeatCount},
+ .value.int64Values = {elapsedRealtimeNano()}};
+ return value;
+}
+
+VehiclePropValue FakeVehicleHardware::createHwMotionInputProp(
+ int32_t area, int32_t display, int32_t inputType, int32_t action, int32_t buttonState,
+ int32_t pointerCount, int32_t pointerId[], int32_t toolType[], float xData[], float yData[],
+ float pressure[], float size[]) {
+ std::vector<int> intValues;
+ intValues.push_back(display);
+ intValues.push_back(inputType);
+ intValues.push_back(action);
+ intValues.push_back(buttonState);
+ intValues.push_back(pointerCount);
+ for (int i = 0; i < pointerCount; i++) {
+ intValues.push_back(pointerId[i]);
+ }
+ for (int i = 0; i < pointerCount; i++) {
+ intValues.push_back(toolType[i]);
+ }
+
+ std::vector<float> floatValues;
+ for (int i = 0; i < pointerCount; i++) {
+ floatValues.push_back(xData[i]);
+ }
+ for (int i = 0; i < pointerCount; i++) {
+ floatValues.push_back(yData[i]);
+ }
+ for (int i = 0; i < pointerCount; i++) {
+ floatValues.push_back(pressure[i]);
+ }
+ for (int i = 0; i < pointerCount; i++) {
+ floatValues.push_back(size[i]);
+ }
+
+ VehiclePropValue value = {.prop = toInt(VehicleProperty::HW_MOTION_INPUT),
+ .areaId = area,
+ .timestamp = elapsedRealtimeNano(),
+ .status = VehiclePropertyStatus::AVAILABLE,
+ .value.int32Values = intValues,
+ .value.floatValues = floatValues,
+ .value.int64Values = {elapsedRealtimeNano()}};
+ return value;
+}
+
+void FakeVehicleHardware::eventFromVehicleBus(const VehiclePropValue& value) {
+ mServerSidePropStore->writeValue(mValuePool->obtain(value));
+}
+
std::string FakeVehicleHardware::dumpHelp() {
return "Usage: \n\n"
"[no args]: dumps (id and value) all supported properties \n"
"--help: shows this help\n"
"--list: lists the ids of all supported properties\n"
- "--get <PROP1> [PROP2] [PROPN]: dumps the value of specific properties \n"
- "--set <PROP> [-i INT_VALUE [INT_VALUE ...]] [-i64 INT64_VALUE [INT64_VALUE ...]] "
- "[-f FLOAT_VALUE [FLOAT_VALUE ...]] [-s STR_VALUE] "
- "[-b BYTES_VALUE] [-a AREA_ID] : sets the value of property PROP. "
+ "--get <PROP1> [PROP2] [PROPN]: dumps the value of specific properties. \n"
+ "--getWithArg <PROP> [ValueArguments]: gets the value for a specific property with "
+ "arguments. \n"
+ "--set <PROP> [ValueArguments]: sets the value of property PROP. \n"
+ "--save-prop <prop> [-a AREA_ID]: saves the current value for PROP, integration test"
+ " that modifies prop value must call this before test and restore-prop after test. \n"
+ "--restore-prop <prop> [-a AREA_ID]: restores a previously saved property value. \n"
+ "--inject-event <PROP> [ValueArguments]: inject a property update event from car\n\n"
+ "ValueArguments are in the format of [-i INT_VALUE [INT_VALUE ...]] "
+ "[-i64 INT64_VALUE [INT64_VALUE ...]] [-f FLOAT_VALUE [FLOAT_VALUE ...]] [-s STR_VALUE] "
+ "[-b BYTES_VALUE] [-a AREA_ID].\n"
"Notice that the string, bytes and area value can be set just once, while the other can"
" have multiple values (so they're used in the respective array), "
- "BYTES_VALUE is in the form of 0xXXXX, e.g. 0xdeadbeef.\n\n"
- "Fake user HAL usage: \n" +
- mFakeUserHal->showDumpHelp();
+ "BYTES_VALUE is in the form of 0xXXXX, e.g. 0xdeadbeef.\n" +
+ genFakeDataHelp() + "Fake user HAL usage: \n" + mFakeUserHal->showDumpHelp();
}
std::string FakeVehicleHardware::dumpAllProperties() {
@@ -719,10 +1531,11 @@
return std::move(values);
}
-Result<VehiclePropValue> FakeVehicleHardware::parseSetPropOptions(
+Result<VehiclePropValue> FakeVehicleHardware::parsePropOptions(
const std::vector<std::string>& options) {
// Options format:
- // --set PROP [-f f1 f2...] [-i i1 i2...] [-i64 i1 i2...] [-s s1 s2...] [-b b1 b2...] [-a a]
+ // --set/get/inject-event PROP [-f f1 f2...] [-i i1 i2...] [-i64 i1 i2...] [-s s1 s2...]
+ // [-b b1 b2...] [-a a] [-t timestamp]
size_t optionIndex = 1;
auto result = safelyParseInt<int32_t>(optionIndex, options[optionIndex]);
if (!result.ok()) {
@@ -736,83 +1549,98 @@
std::unordered_set<std::string> parsedOptions;
while (optionIndex < options.size()) {
- std::string type = options[optionIndex];
+ std::string argType = options[optionIndex];
optionIndex++;
+
size_t currentIndex = optionIndex;
- std::vector<std::string> values = getOptionValues(options, &optionIndex);
- if (parsedOptions.find(type) != parsedOptions.end()) {
- return Error() << StringPrintf("Duplicate \"%s\" options\n", type.c_str());
+ std::vector<std::string> argValues = getOptionValues(options, &optionIndex);
+ if (parsedOptions.find(argType) != parsedOptions.end()) {
+ return Error() << StringPrintf("Duplicate \"%s\" options\n", argType.c_str());
}
- parsedOptions.insert(type);
- if (EqualsIgnoreCase(type, "-i")) {
- if (values.size() == 0) {
+ parsedOptions.insert(argType);
+ size_t argValuesSize = argValues.size();
+ if (EqualsIgnoreCase(argType, "-i")) {
+ if (argValuesSize == 0) {
return Error() << "No values specified when using \"-i\"\n";
}
- prop.value.int32Values.resize(values.size());
- for (size_t i = 0; i < values.size(); i++) {
- auto int32Result = safelyParseInt<int32_t>(currentIndex + i, values[i]);
+ prop.value.int32Values.resize(argValuesSize);
+ for (size_t i = 0; i < argValuesSize; i++) {
+ auto int32Result = safelyParseInt<int32_t>(currentIndex + i, argValues[i]);
if (!int32Result.ok()) {
return Error()
<< StringPrintf("Value: \"%s\" is not a valid int: %s\n",
- values[i].c_str(), getErrorMsg(int32Result).c_str());
+ argValues[i].c_str(), getErrorMsg(int32Result).c_str());
}
prop.value.int32Values[i] = int32Result.value();
}
- } else if (EqualsIgnoreCase(type, "-i64")) {
- if (values.size() == 0) {
+ } else if (EqualsIgnoreCase(argType, "-i64")) {
+ if (argValuesSize == 0) {
return Error() << "No values specified when using \"-i64\"\n";
}
- prop.value.int64Values.resize(values.size());
- for (size_t i = 0; i < values.size(); i++) {
- auto int64Result = safelyParseInt<int64_t>(currentIndex + i, values[i]);
+ prop.value.int64Values.resize(argValuesSize);
+ for (size_t i = 0; i < argValuesSize; i++) {
+ auto int64Result = safelyParseInt<int64_t>(currentIndex + i, argValues[i]);
if (!int64Result.ok()) {
return Error()
<< StringPrintf("Value: \"%s\" is not a valid int64: %s\n",
- values[i].c_str(), getErrorMsg(int64Result).c_str());
+ argValues[i].c_str(), getErrorMsg(int64Result).c_str());
}
prop.value.int64Values[i] = int64Result.value();
}
- } else if (EqualsIgnoreCase(type, "-f")) {
- if (values.size() == 0) {
+ } else if (EqualsIgnoreCase(argType, "-f")) {
+ if (argValuesSize == 0) {
return Error() << "No values specified when using \"-f\"\n";
}
- prop.value.floatValues.resize(values.size());
- for (size_t i = 0; i < values.size(); i++) {
- auto floatResult = safelyParseFloat(currentIndex + i, values[i]);
+ prop.value.floatValues.resize(argValuesSize);
+ for (size_t i = 0; i < argValuesSize; i++) {
+ auto floatResult = safelyParseFloat(currentIndex + i, argValues[i]);
if (!floatResult.ok()) {
return Error()
<< StringPrintf("Value: \"%s\" is not a valid float: %s\n",
- values[i].c_str(), getErrorMsg(floatResult).c_str());
+ argValues[i].c_str(), getErrorMsg(floatResult).c_str());
}
prop.value.floatValues[i] = floatResult.value();
}
- } else if (EqualsIgnoreCase(type, "-s")) {
- if (values.size() != 1) {
+ } else if (EqualsIgnoreCase(argType, "-s")) {
+ if (argValuesSize != 1) {
return Error() << "Expect exact one value when using \"-s\"\n";
}
- prop.value.stringValue = values[0];
- } else if (EqualsIgnoreCase(type, "-b")) {
- if (values.size() != 1) {
+ prop.value.stringValue = argValues[0];
+ } else if (EqualsIgnoreCase(argType, "-b")) {
+ if (argValuesSize != 1) {
return Error() << "Expect exact one value when using \"-b\"\n";
}
- auto bytesResult = parseHexString(values[0]);
+ auto bytesResult = parseHexString(argValues[0]);
if (!bytesResult.ok()) {
return Error() << StringPrintf("value: \"%s\" is not a valid hex string: %s\n",
- values[0].c_str(), getErrorMsg(bytesResult).c_str());
+ argValues[0].c_str(),
+ getErrorMsg(bytesResult).c_str());
}
prop.value.byteValues = std::move(bytesResult.value());
- } else if (EqualsIgnoreCase(type, "-a")) {
- if (values.size() != 1) {
+ } else if (EqualsIgnoreCase(argType, "-a")) {
+ if (argValuesSize != 1) {
return Error() << "Expect exact one value when using \"-a\"\n";
}
- auto int32Result = safelyParseInt<int32_t>(currentIndex, values[0]);
+ auto int32Result = safelyParseInt<int32_t>(currentIndex, argValues[0]);
if (!int32Result.ok()) {
return Error() << StringPrintf("Area ID: \"%s\" is not a valid int: %s\n",
- values[0].c_str(), getErrorMsg(int32Result).c_str());
+ argValues[0].c_str(),
+ getErrorMsg(int32Result).c_str());
}
prop.areaId = int32Result.value();
+ } else if (EqualsIgnoreCase(argType, "-t")) {
+ if (argValuesSize != 1) {
+ return Error() << "Expect exact one value when using \"-t\"\n";
+ }
+ auto int64Result = safelyParseInt<int64_t>(currentIndex, argValues[0]);
+ if (!int64Result.ok()) {
+ return Error() << StringPrintf("Timestamp: \"%s\" is not a valid int64: %s\n",
+ argValues[0].c_str(),
+ getErrorMsg(int64Result).c_str());
+ }
+ prop.timestamp = int64Result.value();
} else {
- return Error() << StringPrintf("Unknown option: %s\n", type.c_str());
+ return Error() << StringPrintf("Unknown option: %s\n", argType.c_str());
}
}
@@ -824,7 +1652,7 @@
return getErrorMsg(result);
}
- auto parseResult = parseSetPropOptions(options);
+ auto parseResult = parsePropOptions(options);
if (!parseResult.ok()) {
return getErrorMsg(parseResult);
}
@@ -847,6 +1675,123 @@
getErrorMsg(setResult).c_str());
}
+std::string FakeVehicleHardware::dumpGetPropertyWithArg(const std::vector<std::string>& options) {
+ if (auto result = checkArgumentsSize(options, 3); !result.ok()) {
+ return getErrorMsg(result);
+ }
+
+ auto parseResult = parsePropOptions(options);
+ if (!parseResult.ok()) {
+ return getErrorMsg(parseResult);
+ }
+ VehiclePropValue prop = std::move(parseResult.value());
+ ALOGD("Dump: Getting property: %s", prop.toString().c_str());
+
+ bool isSpecialValue = false;
+ auto result = maybeGetSpecialValue(prop, &isSpecialValue);
+
+ if (!isSpecialValue) {
+ result = mServerSidePropStore->readValue(prop);
+ }
+
+ if (!result.ok()) {
+ return StringPrintf("failed to read property value: %d, error: %s, code: %d\n", prop.prop,
+ getErrorMsg(result).c_str(), getIntErrorCode(result));
+ }
+ return StringPrintf("Get property result: %s\n", result.value()->toString().c_str());
+}
+
+std::string FakeVehicleHardware::dumpSaveProperty(const std::vector<std::string>& options) {
+ // Format: --save-prop PROP [-a areaID]
+ if (auto result = checkArgumentsSize(options, 2); !result.ok()) {
+ return getErrorMsg(result);
+ }
+
+ auto parseResult = parsePropOptions(options);
+ if (!parseResult.ok()) {
+ return getErrorMsg(parseResult);
+ }
+ // We are only using the prop and areaId option.
+ VehiclePropValue value = std::move(parseResult.value());
+ int32_t propId = value.prop;
+ int32_t areaId = value.areaId;
+
+ auto readResult = mServerSidePropStore->readValue(value);
+ if (!readResult.ok()) {
+ return StringPrintf("Failed to save current property value, error: %s",
+ getErrorMsg(readResult).c_str());
+ }
+
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mSavedProps[PropIdAreaId{
+ .propId = propId,
+ .areaId = areaId,
+ }] = std::move(readResult.value());
+
+ return StringPrintf("Property: %" PRId32 ", areaID: %" PRId32 " saved", propId, areaId);
+}
+
+std::string FakeVehicleHardware::dumpRestoreProperty(const std::vector<std::string>& options) {
+ // Format: --restore-prop PROP [-a areaID]
+ if (auto result = checkArgumentsSize(options, 2); !result.ok()) {
+ return getErrorMsg(result);
+ }
+
+ auto parseResult = parsePropOptions(options);
+ if (!parseResult.ok()) {
+ return getErrorMsg(parseResult);
+ }
+ // We are only using the prop and areaId option.
+ VehiclePropValue value = std::move(parseResult.value());
+ int32_t propId = value.prop;
+ int32_t areaId = value.areaId;
+ VehiclePropValuePool::RecyclableType savedValue;
+
+ {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ auto it = mSavedProps.find(PropIdAreaId{
+ .propId = propId,
+ .areaId = areaId,
+ });
+ if (it == mSavedProps.end()) {
+ return StringPrintf("No saved property for property: %" PRId32 ", areaID: %" PRId32,
+ propId, areaId);
+ }
+
+ savedValue = std::move(it->second);
+ // Remove the saved property after restoring it.
+ mSavedProps.erase(it);
+ }
+
+ // Update timestamp.
+ savedValue->timestamp = elapsedRealtimeNano();
+
+ auto writeResult = mServerSidePropStore->writeValue(std::move(savedValue));
+ if (!writeResult.ok()) {
+ return StringPrintf("Failed to restore property value, error: %s",
+ getErrorMsg(writeResult).c_str());
+ }
+
+ return StringPrintf("Property: %" PRId32 ", areaID: %" PRId32 " restored", propId, areaId);
+}
+
+std::string FakeVehicleHardware::dumpInjectEvent(const std::vector<std::string>& options) {
+ if (auto result = checkArgumentsSize(options, 3); !result.ok()) {
+ return getErrorMsg(result);
+ }
+
+ auto parseResult = parsePropOptions(options);
+ if (!parseResult.ok()) {
+ return getErrorMsg(parseResult);
+ }
+ VehiclePropValue prop = std::move(parseResult.value());
+ ALOGD("Dump: Injecting event from vehicle bus: %s", prop.toString().c_str());
+
+ eventFromVehicleBus(prop);
+
+ return StringPrintf("Event for property: %d injected", prop.prop);
+}
+
StatusCode FakeVehicleHardware::checkHealth() {
// Always return OK for checkHealth.
return StatusCode::OK;
@@ -854,13 +1799,19 @@
void FakeVehicleHardware::registerOnPropertyChangeEvent(
std::unique_ptr<const PropertyChangeCallback> callback) {
- std::scoped_lock<std::mutex> lockGuard(mLock);
+ if (mOnPropertyChangeCallback != nullptr) {
+ ALOGE("registerOnPropertyChangeEvent must only be called once");
+ return;
+ }
mOnPropertyChangeCallback = std::move(callback);
}
void FakeVehicleHardware::registerOnPropertySetErrorEvent(
std::unique_ptr<const PropertySetErrorCallback> callback) {
- std::scoped_lock<std::mutex> lockGuard(mLock);
+ if (mOnPropertySetErrorCallback != nullptr) {
+ ALOGE("registerOnPropertySetErrorEvent must only be called once");
+ return;
+ }
mOnPropertySetErrorCallback = std::move(callback);
}
@@ -904,8 +1855,6 @@
}
void FakeVehicleHardware::onValueChangeCallback(const VehiclePropValue& value) {
- std::scoped_lock<std::mutex> lockGuard(mLock);
-
if (mOnPropertyChangeCallback == nullptr) {
return;
}
@@ -915,33 +1864,26 @@
(*mOnPropertyChangeCallback)(std::move(updatedValues));
}
-void FakeVehicleHardware::maybeOverrideProperties(const char* overrideDir) {
- if (android::base::GetBoolProperty(OVERRIDE_PROPERTY, false)) {
- overrideProperties(overrideDir);
- }
-}
-
-void FakeVehicleHardware::overrideProperties(const char* overrideDir) {
- ALOGI("loading vendor override properties from %s", overrideDir);
- if (auto dir = opendir(overrideDir); dir != NULL) {
+void FakeVehicleHardware::loadPropConfigsFromDir(
+ const std::string& dirPath,
+ std::unordered_map<int32_t, ConfigDeclaration>* configsByPropId) {
+ ALOGI("loading properties from %s", dirPath.c_str());
+ if (auto dir = opendir(dirPath.c_str()); dir != NULL) {
std::regex regJson(".*[.]json", std::regex::icase);
while (auto f = readdir(dir)) {
if (!std::regex_match(f->d_name, regJson)) {
continue;
}
- std::string file = overrideDir + std::string(f->d_name);
- JsonFakeValueGenerator tmpGenerator(file);
-
- std::vector<VehiclePropValue> propValues = tmpGenerator.getAllEvents();
- for (const VehiclePropValue& prop : propValues) {
- auto propToStore = mValuePool->obtain(prop);
- propToStore->timestamp = elapsedRealtimeNano();
- if (auto result = mServerSidePropStore->writeValue(std::move(propToStore),
- /*updateStatus=*/true);
- !result.ok()) {
- ALOGW("failed to write vendor override properties: %d, error: %s, code: %d",
- prop.prop, getErrorMsg(result).c_str(), getIntErrorCode(result));
- }
+ std::string filePath = dirPath + "/" + std::string(f->d_name);
+ ALOGI("loading properties from %s", filePath.c_str());
+ auto result = mLoader.loadPropConfig(filePath);
+ if (!result.ok()) {
+ ALOGE("failed to load config file: %s, error: %s", filePath.c_str(),
+ result.error().message().c_str());
+ continue;
+ }
+ for (auto& [propId, configDeclaration] : result.value()) {
+ (*configsByPropId)[propId] = std::move(configDeclaration);
}
}
closedir(dir);
@@ -1027,11 +1969,15 @@
std::unordered_map<std::shared_ptr<const GetValuesCallback>, std::vector<GetValueResult>>
callbackToResults;
for (const auto& rwc : mRequests.flush()) {
+ ATRACE_BEGIN("FakeVehicleHardware:handleGetValueRequest");
auto result = mHardware->handleGetValueRequest(rwc.request);
+ ATRACE_END();
callbackToResults[rwc.callback].push_back(std::move(result));
}
for (const auto& [callback, results] : callbackToResults) {
+ ATRACE_BEGIN("FakeVehicleHardware:call get value result callback");
(*callback)(std::move(results));
+ ATRACE_END();
}
}
@@ -1041,11 +1987,15 @@
std::unordered_map<std::shared_ptr<const SetValuesCallback>, std::vector<SetValueResult>>
callbackToResults;
for (const auto& rwc : mRequests.flush()) {
+ ATRACE_BEGIN("FakeVehicleHardware:handleSetValueRequest");
auto result = mHardware->handleSetValueRequest(rwc.request);
+ ATRACE_END();
callbackToResults[rwc.callback].push_back(std::move(result));
}
for (const auto& [callback, results] : callbackToResults) {
+ ATRACE_BEGIN("FakeVehicleHardware:call set value result callback");
(*callback)(std::move(results));
+ ATRACE_END();
}
}
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 90d1516..8d8fcf5 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/Android.bp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/Android.bp
@@ -22,13 +22,13 @@
name: "FakeVehicleHardwareTest",
vendor: true,
srcs: ["*.cpp"],
- cflags: ["-DENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING"],
+ cflags: ["-DENABLE_VEHICLE_HAL_TEST_PROPERTIES"],
header_libs: [
"IVehicleHardware",
- "VehicleHalDefaultConfig",
"VehicleHalTestUtilHeaders",
],
static_libs: [
+ "VehicleHalJsonConfigLoaderEnableTestProperties",
"VehicleHalUtils",
"FakeVehicleHardware",
"FakeVehicleHalValueGenerators",
@@ -41,7 +41,11 @@
"libjsoncpp",
],
data: [
+ ":VehicleHalDefaultProperties_JSON",
+ ":VehicleHalTestProperties_JSON",
+ ":VehicleHalVendorClusterTestProperties_JSON",
":FakeVehicleHardwareTestOverrideJson",
+ ":FakeVehicleHardwareTestPropJson",
],
defaults: ["VehicleHalDefaults"],
test_suites: ["device-tests"],
@@ -51,3 +55,8 @@
name: "FakeVehicleHardwareTestOverrideJson",
srcs: ["override/*"],
}
+
+filegroup {
+ name: "FakeVehicleHardwareTestPropJson",
+ srcs: ["fakedata/prop.json"],
+}
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 3e8f634..8d385dd 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
@@ -16,7 +16,6 @@
#include <FakeVehicleHardware.h>
-#include <DefaultConfig.h>
#include <FakeObd2Frame.h>
#include <FakeUserHal.h>
#include <PropertyUtils.h>
@@ -38,6 +37,22 @@
#include <unordered_set>
#include <vector>
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+void PrintTo(const VehiclePropValue& value, std::ostream* os) {
+ *os << "\n( " << value.toString() << " )\n";
+}
+
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
namespace android {
namespace hardware {
namespace automotive {
@@ -45,6 +60,7 @@
namespace fake {
namespace {
+using ::aidl::android::hardware::automotive::vehicle::ErrorState;
using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
@@ -53,17 +69,23 @@
using ::aidl::android::hardware::automotive::vehicle::StatusCode;
using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReport;
using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaMirror;
+using ::aidl::android::hardware::automotive::vehicle::VehicleHwKeyInputAction;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+using ::aidl::android::hardware::automotive::vehicle::VehicleUnit;
using ::android::base::expected;
using ::android::base::ScopedLockAssertion;
using ::android::base::StringPrintf;
using ::android::base::unexpected;
+using ::testing::AnyOfArray;
using ::testing::ContainerEq;
using ::testing::ContainsRegex;
using ::testing::Eq;
+using ::testing::HasSubstr;
+using ::testing::IsSubsetOf;
using ::testing::WhenSortedBy;
using std::chrono::milliseconds;
@@ -78,7 +100,9 @@
public:
FakeVehicleHardwareTestHelper(FakeVehicleHardware* hardware) { mHardware = hardware; }
- void overrideProperties(const char* overrideDir) { mHardware->overrideProperties(overrideDir); }
+ std::unordered_map<int32_t, ConfigDeclaration> loadConfigDeclarations() {
+ return mHardware->loadConfigDeclarations();
+ }
private:
FakeVehicleHardware* mHardware;
@@ -87,6 +111,9 @@
class FakeVehicleHardwareTest : public ::testing::Test {
protected:
void SetUp() override {
+ mHardware = std::make_unique<FakeVehicleHardware>(android::base::GetExecutableDirectory(),
+ /*overrideConfigDir=*/"",
+ /*forceOverride=*/false);
auto callback = std::make_unique<IVehicleHardware::PropertyChangeCallback>(
[this](const std::vector<VehiclePropValue>& values) {
onPropertyChangeEvent(values);
@@ -98,7 +125,17 @@
[this](std::vector<GetValueResult> results) { onGetValues(results); });
}
- FakeVehicleHardware* getHardware() { return &mHardware; }
+ void TearDown() override {
+ // mHardware uses callback which contains reference to 'this', so it has to be destroyed
+ // before 'this'.
+ mHardware.reset();
+ }
+
+ FakeVehicleHardware* getHardware() { return mHardware.get(); }
+
+ void setHardware(std::unique_ptr<FakeVehicleHardware> hardware) {
+ mHardware = std::move(hardware);
+ }
StatusCode setValues(const std::vector<SetValueRequest>& requests) {
{
@@ -251,6 +288,14 @@
return mChangedProperties;
}
+ bool waitForChangedProperties(size_t count, milliseconds timeout) {
+ std::unique_lock<std::mutex> lk(mLock);
+ return mCv.wait_for(lk, timeout, [this, count] {
+ ScopedLockAssertion lockAssertion(mLock);
+ return mChangedProperties.size() >= count;
+ });
+ }
+
bool waitForChangedProperties(int32_t propId, int32_t areaId, size_t count,
milliseconds timeout) {
PropIdAreaId propIdAreaId{
@@ -270,6 +315,15 @@
mChangedProperties.clear();
}
+ size_t getEventCount(int32_t propId, int32_t areaId) {
+ PropIdAreaId propIdAreaId{
+ .propId = propId,
+ .areaId = areaId,
+ };
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return mEventCount[propIdAreaId];
+ }
+
static void addSetValueRequest(std::vector<SetValueRequest>& requests,
std::vector<SetValueResult>& expectedResults, int64_t requestId,
const VehiclePropValue& value, StatusCode expectedStatus) {
@@ -332,7 +386,7 @@
} mPropValueCmp;
private:
- FakeVehicleHardware mHardware;
+ std::unique_ptr<FakeVehicleHardware> mHardware;
std::shared_ptr<IVehicleHardware::SetValuesCallback> mSetValuesCallback;
std::shared_ptr<IVehicleHardware::GetValuesCallback> mGetValuesCallback;
std::condition_variable mCv;
@@ -348,7 +402,8 @@
TEST_F(FakeVehicleHardwareTest, testGetAllPropertyConfigs) {
std::vector<VehiclePropConfig> configs = getHardware()->getAllPropertyConfigs();
- ASSERT_EQ(configs.size(), defaultconfig::getDefaultConfigs().size());
+ FakeVehicleHardwareTestHelper helper(getHardware());
+ ASSERT_EQ(configs.size(), helper.loadConfigDeclarations().size());
}
TEST_F(FakeVehicleHardwareTest, testGetDefaultValues) {
@@ -356,7 +411,8 @@
std::vector<GetValueResult> expectedGetValueResults;
int64_t requestId = 1;
- for (auto& config : defaultconfig::getDefaultConfigs()) {
+ FakeVehicleHardwareTestHelper helper(getHardware());
+ for (auto& [propId, config] : helper.loadConfigDeclarations()) {
if (obd2frame::FakeObd2Frame::isDiagnosticProperty(config.config)) {
// Ignore storing default value for diagnostic property. They have special get/set
// logic.
@@ -368,12 +424,16 @@
continue;
}
- if (config.config.prop == ECHO_REVERSE_BYTES) {
+ if (propId == ECHO_REVERSE_BYTES) {
// Ignore ECHO_REVERSE_BYTES, it has special logic.
continue;
}
- int propId = config.config.prop;
+ if (propId == VENDOR_PROPERTY_ID) {
+ // Ignore VENDOR_PROPERTY_ID, it has special logic.
+ continue;
+ }
+
if (isGlobalProp(propId)) {
if (config.initialValue == RawPropValues{}) {
addGetValueRequest(getValueRequests, expectedGetValueResults, requestId++,
@@ -631,10 +691,12 @@
}
TEST_F(FakeVehicleHardwareTest, testVendorOverrideProperties) {
- std::string overrideDir = android::base::GetExecutableDirectory() + "/override/";
+ std::string currentDir = android::base::GetExecutableDirectory();
+ std::string overrideDir = currentDir + "/override/";
// Set vendor override directory.
- FakeVehicleHardwareTestHelper helper(getHardware());
- helper.overrideProperties(overrideDir.c_str());
+ std::unique_ptr<FakeVehicleHardware> hardware =
+ std::make_unique<FakeVehicleHardware>(currentDir, overrideDir, /*forceOverride=*/true);
+ setHardware(std::move(hardware));
// This is the same as the prop in 'gear_selection.json'.
int gearProp = toInt(VehicleProperty::GEAR_SELECTION);
@@ -669,10 +731,12 @@
}
TEST_F(FakeVehicleHardwareTest, testVendorOverridePropertiesMultipleAreas) {
- std::string overrideDir = android::base::GetExecutableDirectory() + "/override/";
+ std::string currentDir = android::base::GetExecutableDirectory();
+ std::string overrideDir = currentDir + "/override/";
// Set vendor override directory.
- FakeVehicleHardwareTestHelper helper(getHardware());
- helper.overrideProperties(overrideDir.c_str());
+ std::unique_ptr<FakeVehicleHardware> hardware =
+ std::make_unique<FakeVehicleHardware>(currentDir, overrideDir, /*forceOverride=*/true);
+ setHardware(std::move(hardware));
// This is the same as the prop in 'hvac_temperature_set.json'.
int hvacProp = toInt(VehicleProperty::HVAC_TEMPERATURE_SET);
@@ -685,22 +749,16 @@
ASSERT_TRUE(result.ok()) << "expect to get the overridden property ok: " << getStatus(result);
ASSERT_EQ(static_cast<size_t>(1), result.value().value.floatValues.size());
ASSERT_EQ(30.0f, result.value().value.floatValues[0]);
-
- // HVAC_RIGHT should not be affected and return the default value.
- result = getValue(VehiclePropValue{
- .prop = hvacProp,
- .areaId = HVAC_RIGHT,
- });
-
- ASSERT_TRUE(result.ok()) << "expect to get the default property ok: " << getStatus(result);
- ASSERT_EQ(static_cast<size_t>(1), result.value().value.floatValues.size());
- ASSERT_EQ(20.0f, result.value().value.floatValues[0]);
}
TEST_F(FakeVehicleHardwareTest, testVendorOverridePropertiesDirDoesNotExist) {
- // Set vendor override directory to a non-existing dir
- FakeVehicleHardwareTestHelper helper(getHardware());
- helper.overrideProperties("123");
+ std::string currentDir = android::base::GetExecutableDirectory();
+ std::string overrideDir = currentDir + "/override/";
+ // Set vendor override directory to a non-existing dir.
+ std::unique_ptr<FakeVehicleHardware> hardware =
+ std::make_unique<FakeVehicleHardware>(currentDir, "1234", /*forceOverride=*/true);
+ setHardware(std::move(hardware));
+
auto result = getValue(VehiclePropValue{
.prop = toInt(VehicleProperty::GEAR_SELECTION),
});
@@ -979,6 +1037,488 @@
},
},
},
+ SetSpecialValueTestCase{
+ .name = "set_automatic_emergency_braking_enabled_false",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ AUTOMATIC_EMERGENCY_BRAKING_ENABLED),
+ .value.int32Values = {0},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ AUTOMATIC_EMERGENCY_BRAKING_ENABLED),
+ .value.int32Values = {0},
+ },
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ AUTOMATIC_EMERGENCY_BRAKING_STATE),
+ .value.int32Values = {toInt(
+ ErrorState::NOT_AVAILABLE_DISABLED)},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "set_automatic_emergency_braking_enabled_true",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ AUTOMATIC_EMERGENCY_BRAKING_ENABLED),
+ .value.int32Values = {1},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ AUTOMATIC_EMERGENCY_BRAKING_ENABLED),
+ .value.int32Values = {1},
+ },
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ AUTOMATIC_EMERGENCY_BRAKING_STATE),
+ .value.int32Values = {1},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "set_forward_collision_warning_enabled_false",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ FORWARD_COLLISION_WARNING_ENABLED),
+ .value.int32Values = {0},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ FORWARD_COLLISION_WARNING_ENABLED),
+ .value.int32Values = {0},
+ },
+ VehiclePropValue{
+ .prop = toInt(VehicleProperty::
+ FORWARD_COLLISION_WARNING_STATE),
+ .value.int32Values = {toInt(
+ ErrorState::NOT_AVAILABLE_DISABLED)},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "set_forward_collision_warning_enabled_true",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ FORWARD_COLLISION_WARNING_ENABLED),
+ .value.int32Values = {1},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ FORWARD_COLLISION_WARNING_ENABLED),
+ .value.int32Values = {1},
+ },
+ VehiclePropValue{
+ .prop = toInt(VehicleProperty::
+ FORWARD_COLLISION_WARNING_STATE),
+ .value.int32Values = {1},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "set_blind_spot_warning_enabled_false",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::BLIND_SPOT_WARNING_ENABLED),
+ .value.int32Values = {0},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::BLIND_SPOT_WARNING_ENABLED),
+ .value.int32Values = {0},
+ },
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::BLIND_SPOT_WARNING_STATE),
+ .areaId = toInt(VehicleAreaMirror::DRIVER_LEFT),
+ .value.int32Values = {toInt(
+ ErrorState::NOT_AVAILABLE_DISABLED)},
+ },
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::BLIND_SPOT_WARNING_STATE),
+ .areaId = toInt(VehicleAreaMirror::DRIVER_RIGHT),
+ .value.int32Values = {toInt(
+ ErrorState::NOT_AVAILABLE_DISABLED)},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "set_blind_spot_warning_enabled_true",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::BLIND_SPOT_WARNING_ENABLED),
+ .value.int32Values = {1},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::BLIND_SPOT_WARNING_ENABLED),
+ .value.int32Values = {1},
+ },
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::BLIND_SPOT_WARNING_STATE),
+ .areaId = toInt(VehicleAreaMirror::DRIVER_LEFT),
+ .value.int32Values = {1},
+ },
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::BLIND_SPOT_WARNING_STATE),
+ .areaId = toInt(VehicleAreaMirror::DRIVER_RIGHT),
+ .value.int32Values = {1},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "set_lane_departure_warning_enabled_false",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(VehicleProperty::
+ LANE_DEPARTURE_WARNING_ENABLED),
+ .value.int32Values = {0},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(VehicleProperty::
+ LANE_DEPARTURE_WARNING_ENABLED),
+ .value.int32Values = {0},
+ },
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::LANE_DEPARTURE_WARNING_STATE),
+ .value.int32Values = {toInt(
+ ErrorState::NOT_AVAILABLE_DISABLED)},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "set_lane_departure_warning_enabled_true",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(VehicleProperty::
+ LANE_DEPARTURE_WARNING_ENABLED),
+ .value.int32Values = {1},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(VehicleProperty::
+ LANE_DEPARTURE_WARNING_ENABLED),
+ .value.int32Values = {1},
+ },
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::LANE_DEPARTURE_WARNING_STATE),
+ .value.int32Values = {1},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "set_lane_keep_assist_enabled_false",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::LANE_KEEP_ASSIST_ENABLED),
+ .value.int32Values = {0},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::LANE_KEEP_ASSIST_ENABLED),
+ .value.int32Values = {0},
+ },
+ VehiclePropValue{
+ .prop = toInt(VehicleProperty::LANE_KEEP_ASSIST_STATE),
+ .value.int32Values = {toInt(
+ ErrorState::NOT_AVAILABLE_DISABLED)},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "set_lane_keep_assist_enabled_true",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::LANE_KEEP_ASSIST_ENABLED),
+ .value.int32Values = {1},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::LANE_KEEP_ASSIST_ENABLED),
+ .value.int32Values = {1},
+ },
+ VehiclePropValue{
+ .prop = toInt(VehicleProperty::LANE_KEEP_ASSIST_STATE),
+ .value.int32Values = {1},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "set_lane_centering_assist_enabled_false",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::LANE_CENTERING_ASSIST_ENABLED),
+ .value.int32Values = {0},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::LANE_CENTERING_ASSIST_ENABLED),
+ .value.int32Values = {0},
+ },
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::LANE_CENTERING_ASSIST_STATE),
+ .value.int32Values = {toInt(
+ ErrorState::NOT_AVAILABLE_DISABLED)},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "set_lane_centering_assist_enabled_true",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::LANE_CENTERING_ASSIST_ENABLED),
+ .value.int32Values = {1},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::LANE_CENTERING_ASSIST_ENABLED),
+ .value.int32Values = {1},
+ },
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::LANE_CENTERING_ASSIST_STATE),
+ .value.int32Values = {1},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "set_emergency_lane_keep_assist_enabled_false",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ EMERGENCY_LANE_KEEP_ASSIST_ENABLED),
+ .value.int32Values = {0},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ EMERGENCY_LANE_KEEP_ASSIST_ENABLED),
+ .value.int32Values = {0},
+ },
+ VehiclePropValue{
+ .prop = toInt(VehicleProperty::
+ EMERGENCY_LANE_KEEP_ASSIST_STATE),
+ .value.int32Values = {toInt(
+ ErrorState::NOT_AVAILABLE_DISABLED)},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "set_emergency_lane_keep_assist_enabled_true",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ EMERGENCY_LANE_KEEP_ASSIST_ENABLED),
+ .value.int32Values = {1},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ EMERGENCY_LANE_KEEP_ASSIST_ENABLED),
+ .value.int32Values = {1},
+ },
+ VehiclePropValue{
+ .prop = toInt(VehicleProperty::
+ EMERGENCY_LANE_KEEP_ASSIST_STATE),
+ .value.int32Values = {1},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "set_cruise_control_enabled_false",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
+ .value.int32Values = {0},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
+ .value.int32Values = {0},
+ },
+ VehiclePropValue{
+ .prop = toInt(VehicleProperty::CRUISE_CONTROL_TYPE),
+ .value.int32Values = {toInt(
+ ErrorState::NOT_AVAILABLE_DISABLED)},
+ },
+ VehiclePropValue{
+ .prop = toInt(VehicleProperty::CRUISE_CONTROL_STATE),
+ .value.int32Values = {toInt(
+ ErrorState::NOT_AVAILABLE_DISABLED)},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "set_cruise_control_enabled_true",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
+ .value.int32Values = {1},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
+ .value.int32Values = {1},
+ },
+ VehiclePropValue{
+ .prop = toInt(VehicleProperty::CRUISE_CONTROL_TYPE),
+ .value.int32Values = {1},
+ },
+ VehiclePropValue{
+ .prop = toInt(VehicleProperty::CRUISE_CONTROL_STATE),
+ .value.int32Values = {1},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "set_hands_on_detection_enabled_false",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::HANDS_ON_DETECTION_ENABLED),
+ .value.int32Values = {0},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::HANDS_ON_DETECTION_ENABLED),
+ .value.int32Values = {0},
+ },
+ VehiclePropValue{
+ .prop = toInt(VehicleProperty::
+ HANDS_ON_DETECTION_DRIVER_STATE),
+ .value.int32Values = {toInt(
+ ErrorState::NOT_AVAILABLE_DISABLED)},
+ },
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::HANDS_ON_DETECTION_WARNING),
+ .value.int32Values = {toInt(
+ ErrorState::NOT_AVAILABLE_DISABLED)},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "set_hands_on_detection_enabled_true",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::HANDS_ON_DETECTION_ENABLED),
+ .value.int32Values = {1},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::HANDS_ON_DETECTION_ENABLED),
+ .value.int32Values = {1},
+ },
+ VehiclePropValue{
+ .prop = toInt(VehicleProperty::
+ HANDS_ON_DETECTION_DRIVER_STATE),
+ .value.int32Values = {1},
+ },
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::HANDS_ON_DETECTION_WARNING),
+ .value.int32Values = {1},
+ },
+ },
+ },
};
}
@@ -996,7 +1536,7 @@
std::vector<VehiclePropValue> gotValues;
for (const auto& value : tc.expectedValuesToGet) {
- auto result = getValue(VehiclePropValue{.prop = value.prop});
+ auto result = getValue(VehiclePropValue{.prop = value.prop, .areaId = value.areaId});
ASSERT_TRUE(result.ok()) << "failed to get property " << value.prop
<< " status:" << getStatus(result);
@@ -1011,7 +1551,7 @@
// Some of the updated properties might be the same as default config, thus not causing
// a property change event. So the changed properties should be a subset of all the updated
// properties.
- ASSERT_THAT(getChangedProperties(), WhenSortedBy(mPropValueCmp, Eq(gotValues)));
+ ASSERT_THAT(getChangedProperties(), IsSubsetOf(gotValues));
}
INSTANTIATE_TEST_SUITE_P(
@@ -1040,11 +1580,12 @@
ASSERT_EQ(events.size(), 1u);
// Erase the timestamp for comparison.
events[0].timestamp = 0;
- ASSERT_EQ(events[0], (VehiclePropValue{
- .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ),
- .status = VehiclePropertyStatus::AVAILABLE,
- .value.int32Values = {toInt(VehicleApPowerStateReq::ON), 0},
- }));
+ auto expectedValue = VehiclePropValue{
+ .prop = toInt(VehicleProperty::AP_POWER_STATE_REQ),
+ .status = VehiclePropertyStatus::AVAILABLE,
+ .value.int32Values = {toInt(VehicleApPowerStateReq::ON), 0},
+ };
+ ASSERT_EQ(events[0], expectedValue);
}
TEST_F(FakeVehicleHardwareTest, testGetObd2FreezeFrame) {
@@ -1108,6 +1649,255 @@
EXPECT_EQ(getValueResult.error(), StatusCode::NOT_AVAILABLE);
}
+TEST_F(FakeVehicleHardwareTest, testGetHvacPropNotAvailable) {
+ int seatAreaIds[5] = {SEAT_1_LEFT, SEAT_1_RIGHT, SEAT_2_LEFT, SEAT_2_CENTER, SEAT_2_RIGHT};
+ for (int areaId : seatAreaIds) {
+ StatusCode status = setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON),
+ .areaId = areaId,
+ .value.int32Values = {0}});
+
+ ASSERT_EQ(status, StatusCode::OK);
+
+ for (size_t i = 0; i < sizeof(HVAC_POWER_PROPERTIES) / sizeof(int32_t); i++) {
+ int powerPropId = HVAC_POWER_PROPERTIES[i];
+ for (int powerDependentAreaId : seatAreaIds) {
+ auto getValueResult = getValue(VehiclePropValue{
+ .prop = powerPropId,
+ .areaId = powerDependentAreaId,
+ });
+
+ if (areaId == powerDependentAreaId) {
+ EXPECT_FALSE(getValueResult.ok());
+ EXPECT_EQ(getValueResult.error(), StatusCode::NOT_AVAILABLE_DISABLED);
+ } else {
+ EXPECT_TRUE(getValueResult.ok());
+ }
+ }
+ }
+
+ // Resetting HVAC_POWER_ON at areaId back to ON state to ensure that there's no dependence
+ // on this value from any power dependent property values other than those with the same
+ // areaId.
+ setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON),
+ .areaId = areaId,
+ .value.int32Values = {1}});
+ }
+}
+
+TEST_F(FakeVehicleHardwareTest, testSetHvacPropNotAvailable) {
+ int seatAreaIds[5] = {SEAT_1_LEFT, SEAT_1_RIGHT, SEAT_2_LEFT, SEAT_2_CENTER, SEAT_2_RIGHT};
+ for (int areaId : seatAreaIds) {
+ StatusCode status = setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON),
+ .areaId = areaId,
+ .value.int32Values = {0}});
+
+ ASSERT_EQ(status, StatusCode::OK);
+
+ for (size_t i = 0; i < sizeof(HVAC_POWER_PROPERTIES) / sizeof(int32_t); i++) {
+ int powerPropId = HVAC_POWER_PROPERTIES[i];
+ for (int powerDependentAreaId : seatAreaIds) {
+ StatusCode status = setValue(VehiclePropValue{.prop = powerPropId,
+ .areaId = powerDependentAreaId,
+ .value.int32Values = {1}});
+
+ if (areaId == powerDependentAreaId) {
+ EXPECT_EQ(status, StatusCode::NOT_AVAILABLE_DISABLED);
+ } else {
+ EXPECT_EQ(status, StatusCode::OK);
+ }
+ }
+ }
+
+ // Resetting HVAC_POWER_ON at areaId back to ON state to ensure that there's no dependence
+ // on this value from any power dependent property values other than those with the same
+ // areaId.
+ setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON),
+ .areaId = areaId,
+ .value.int32Values = {1}});
+ }
+}
+
+TEST_F(FakeVehicleHardwareTest, testHvacPowerOnSendCurrentHvacPropValues) {
+ int seatAreaIds[5] = {SEAT_1_LEFT, SEAT_1_RIGHT, SEAT_2_LEFT, SEAT_2_CENTER, SEAT_2_RIGHT};
+ for (int areaId : seatAreaIds) {
+ StatusCode status = setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON),
+ .areaId = areaId,
+ .value.int32Values = {0}});
+
+ ASSERT_EQ(status, StatusCode::OK);
+
+ clearChangedProperties();
+ setValue(VehiclePropValue{.prop = toInt(VehicleProperty::HVAC_POWER_ON),
+ .areaId = areaId,
+ .value.int32Values = {1}});
+
+ auto events = getChangedProperties();
+ // If we turn HVAC power on, we expect to receive one property event for every HVAC prop
+ // areas plus one event for HVAC_POWER_ON.
+ std::vector<int32_t> changedPropIds;
+ for (size_t i = 0; i < sizeof(HVAC_POWER_PROPERTIES) / sizeof(int32_t); i++) {
+ changedPropIds.push_back(HVAC_POWER_PROPERTIES[i]);
+ }
+ changedPropIds.push_back(toInt(VehicleProperty::HVAC_POWER_ON));
+
+ for (const auto& event : events) {
+ EXPECT_EQ(event.areaId, areaId);
+ EXPECT_THAT(event.prop, AnyOfArray(changedPropIds));
+ }
+ }
+}
+
+TEST_F(FakeVehicleHardwareTest, testGetAdasPropNotAvailable) {
+ std::unordered_map<int32_t, std::vector<int32_t>> adasEnabledPropToDependentProps = {
+ {
+ toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
+ {
+ toInt(VehicleProperty::CRUISE_CONTROL_TARGET_SPEED),
+ toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP),
+ toInt(VehicleProperty::
+ ADAPTIVE_CRUISE_CONTROL_LEAD_VEHICLE_MEASURED_DISTANCE),
+ },
+ },
+ };
+ for (auto& enabledToDependents : adasEnabledPropToDependentProps) {
+ int32_t adasEnabledPropertyId = enabledToDependents.first;
+ StatusCode status =
+ setValue(VehiclePropValue{.prop = adasEnabledPropertyId, .value.int32Values = {0}});
+ EXPECT_EQ(status, StatusCode::OK);
+
+ auto& dependentProps = enabledToDependents.second;
+ for (auto dependentProp : dependentProps) {
+ auto getValueResult = getValue(VehiclePropValue{.prop = dependentProp});
+ EXPECT_FALSE(getValueResult.ok());
+ EXPECT_EQ(getValueResult.error(), StatusCode::NOT_AVAILABLE_DISABLED);
+ }
+ }
+}
+
+TEST_F(FakeVehicleHardwareTest, testSetAdasPropNotAvailable) {
+ std::unordered_map<int32_t, std::vector<int32_t>> adasEnabledPropToDependentProps = {
+ {
+ toInt(VehicleProperty::LANE_CENTERING_ASSIST_ENABLED),
+ {
+ toInt(VehicleProperty::LANE_CENTERING_ASSIST_COMMAND),
+ },
+ },
+ {
+ toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
+ {
+ toInt(VehicleProperty::CRUISE_CONTROL_COMMAND),
+ toInt(VehicleProperty::ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP),
+ },
+ },
+ };
+ for (auto& enabledToDependents : adasEnabledPropToDependentProps) {
+ int32_t adasEnabledPropertyId = enabledToDependents.first;
+ StatusCode status =
+ setValue(VehiclePropValue{.prop = adasEnabledPropertyId, .value.int32Values = {0}});
+ EXPECT_EQ(status, StatusCode::OK);
+
+ auto& dependentProps = enabledToDependents.second;
+ for (auto dependentProp : dependentProps) {
+ StatusCode status = setValue(VehiclePropValue{.prop = dependentProp});
+ EXPECT_EQ(status, StatusCode::NOT_AVAILABLE_DISABLED);
+ }
+ }
+}
+
+TEST_F(FakeVehicleHardwareTest, testSendAdasPropertiesState) {
+ std::unordered_map<int32_t, std::vector<int32_t>> adasEnabledPropToAdasPropWithErrorState = {
+ // AEB
+ {
+ toInt(VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_ENABLED),
+ {
+ toInt(VehicleProperty::AUTOMATIC_EMERGENCY_BRAKING_STATE),
+ },
+ },
+ // FCW
+ {
+ toInt(VehicleProperty::FORWARD_COLLISION_WARNING_ENABLED),
+ {
+ toInt(VehicleProperty::FORWARD_COLLISION_WARNING_STATE),
+ },
+ },
+ // BSW
+ {
+ toInt(VehicleProperty::BLIND_SPOT_WARNING_ENABLED),
+ {
+ toInt(VehicleProperty::BLIND_SPOT_WARNING_STATE),
+ },
+ },
+ // LDW
+ {
+ toInt(VehicleProperty::LANE_DEPARTURE_WARNING_ENABLED),
+ {
+ toInt(VehicleProperty::LANE_DEPARTURE_WARNING_STATE),
+ },
+ },
+ // LKA
+ {
+ toInt(VehicleProperty::LANE_KEEP_ASSIST_ENABLED),
+ {
+ toInt(VehicleProperty::LANE_KEEP_ASSIST_STATE),
+ },
+ },
+ // LCA
+ {
+ toInt(VehicleProperty::LANE_CENTERING_ASSIST_ENABLED),
+ {
+ toInt(VehicleProperty::LANE_CENTERING_ASSIST_STATE),
+ },
+ },
+ // ELKA
+ {
+ toInt(VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_ENABLED),
+ {
+ toInt(VehicleProperty::EMERGENCY_LANE_KEEP_ASSIST_STATE),
+ },
+ },
+ // CC
+ {
+ toInt(VehicleProperty::CRUISE_CONTROL_ENABLED),
+ {
+ toInt(VehicleProperty::CRUISE_CONTROL_TYPE),
+ toInt(VehicleProperty::CRUISE_CONTROL_STATE),
+ },
+ },
+ // HOD
+ {
+ toInt(VehicleProperty::HANDS_ON_DETECTION_ENABLED),
+ {
+ toInt(VehicleProperty::HANDS_ON_DETECTION_DRIVER_STATE),
+ toInt(VehicleProperty::HANDS_ON_DETECTION_WARNING),
+ },
+ },
+ };
+ for (auto& enabledToErrorStateProps : adasEnabledPropToAdasPropWithErrorState) {
+ int32_t adasEnabledPropertyId = enabledToErrorStateProps.first;
+ StatusCode status =
+ setValue(VehiclePropValue{.prop = adasEnabledPropertyId, .value.int32Values = {0}});
+ EXPECT_EQ(status, StatusCode::OK);
+
+ clearChangedProperties();
+ status =
+ setValue(VehiclePropValue{.prop = adasEnabledPropertyId, .value.int32Values = {1}});
+ EXPECT_EQ(status, StatusCode::OK);
+
+ // If we enable the ADAS feature, we expect to receive one property event for every ADAS
+ // state property plus one event for enabling the feature.
+ std::unordered_set<int32_t> expectedChangedPropIds(enabledToErrorStateProps.second.begin(),
+ enabledToErrorStateProps.second.end());
+ expectedChangedPropIds.insert(adasEnabledPropertyId);
+
+ std::unordered_set<int32_t> changedPropIds;
+ auto events = getChangedProperties();
+ for (const auto& event : events) {
+ changedPropIds.insert(event.prop);
+ }
+ EXPECT_EQ(changedPropIds, expectedChangedPropIds);
+ }
+}
+
TEST_F(FakeVehicleHardwareTest, testGetUserPropertySetOnly) {
for (VehicleProperty prop : std::vector<VehicleProperty>({
VehicleProperty::INITIAL_USER_INFO,
@@ -1191,6 +1981,8 @@
ASSERT_EQ(events.size(), static_cast<size_t>(1));
events[0].timestamp = 0;
+ // The returned event will have area ID 0.
+ valueToSet.areaId = 0;
ASSERT_EQ(events[0], valueToSet);
// Try to get switch_user again, should return default value.
@@ -1201,19 +1993,20 @@
events = getChangedProperties();
ASSERT_EQ(events.size(), static_cast<size_t>(1));
events[0].timestamp = 0;
- ASSERT_EQ(events[0], (VehiclePropValue{
- .areaId = 0,
- .prop = toInt(VehicleProperty::SWITCH_USER),
- .value.int32Values =
- {
- // Request ID
- 666,
- // VEHICLE_RESPONSE
- 3,
- // SUCCESS
- 1,
- },
- }));
+ auto expectedValue = VehiclePropValue{
+ .areaId = 0,
+ .prop = toInt(VehicleProperty::SWITCH_USER),
+ .value.int32Values =
+ {
+ // Request ID
+ 666,
+ // VEHICLE_RESPONSE
+ 3,
+ // SUCCESS
+ 1,
+ },
+ };
+ ASSERT_EQ(events[0], expectedValue);
}
TEST_F(FakeVehicleHardwareTest, testCreateUser) {
@@ -1245,6 +2038,8 @@
auto events = getChangedProperties();
ASSERT_EQ(events.size(), static_cast<size_t>(1));
events[0].timestamp = 0;
+ // The returned event will have area ID 0.
+ valueToSet.areaId = 0;
EXPECT_EQ(events[0], valueToSet);
// Try to get create_user again, should return default value.
@@ -1255,17 +2050,18 @@
events = getChangedProperties();
ASSERT_EQ(events.size(), static_cast<size_t>(1));
events[0].timestamp = 0;
- ASSERT_EQ(events[0], (VehiclePropValue{
- .areaId = 0,
- .prop = toInt(VehicleProperty::CREATE_USER),
- .value.int32Values =
- {
- // Request ID
- 666,
- // SUCCESS
- 1,
- },
- }));
+ auto expectedValue = VehiclePropValue{
+ .areaId = 0,
+ .prop = toInt(VehicleProperty::CREATE_USER),
+ .value.int32Values =
+ {
+ // Request ID
+ 666,
+ // SUCCESS
+ 1,
+ },
+ };
+ ASSERT_EQ(events[0], expectedValue);
}
TEST_F(FakeVehicleHardwareTest, testInitialUserInfo) {
@@ -1297,11 +2093,12 @@
auto events = getChangedProperties();
ASSERT_EQ(events.size(), static_cast<size_t>(1));
events[0].timestamp = 0;
- EXPECT_EQ(events[0], (VehiclePropValue{
- .areaId = 1,
- .prop = toInt(VehicleProperty::INITIAL_USER_INFO),
- .value.int32Values = {3, 1, 11},
- }));
+ auto expectedValue = VehiclePropValue{
+ .areaId = 0,
+ .prop = toInt(VehicleProperty::INITIAL_USER_INFO),
+ .value.int32Values = {3, 1, 11},
+ };
+ EXPECT_EQ(events[0], expectedValue);
// Try to get create_user again, should return default value.
clearChangedProperties();
@@ -1311,22 +2108,23 @@
events = getChangedProperties();
ASSERT_EQ(events.size(), static_cast<size_t>(1));
events[0].timestamp = 0;
- EXPECT_EQ(events[0], (VehiclePropValue{
- .areaId = 0,
- .prop = toInt(VehicleProperty::INITIAL_USER_INFO),
- .value.int32Values =
- {
- // Request ID
- 3,
- // ACTION: DEFAULT
- 0,
- // User id: 0
- 0,
- // Flags: 0
- 0,
- },
- .value.stringValue = "||",
- }));
+ expectedValue = VehiclePropValue{
+ .areaId = 0,
+ .prop = toInt(VehicleProperty::INITIAL_USER_INFO),
+ .value.int32Values =
+ {
+ // Request ID
+ 3,
+ // ACTION: DEFAULT
+ 0,
+ // User id: 0
+ 0,
+ // Flags: 0
+ 0,
+ },
+ .value.stringValue = "||",
+ };
+ EXPECT_EQ(events[0], expectedValue);
}
TEST_F(FakeVehicleHardwareTest, testDumpAllProperties) {
@@ -1395,6 +2193,85 @@
ASSERT_THAT(result.buffer, ContainsRegex("Invalid number of arguments"));
}
+TEST_F(FakeVehicleHardwareTest, testDumpSpecificPropertyWithArg) {
+ auto getValueResult = getValue(VehiclePropValue{.prop = OBD2_FREEZE_FRAME_INFO});
+ ASSERT_TRUE(getValueResult.ok());
+ auto propValue = getValueResult.value();
+ ASSERT_EQ(propValue.value.int64Values.size(), static_cast<size_t>(3))
+ << "expect 3 obd2 freeze frames stored";
+
+ std::string propIdStr = StringPrintf("%d", OBD2_FREEZE_FRAME);
+ DumpResult result;
+ for (int64_t timestamp : propValue.value.int64Values) {
+ result = getHardware()->dump(
+ {"--getWithArg", propIdStr, "-i64", StringPrintf("%" PRId64, timestamp)});
+
+ ASSERT_FALSE(result.callerShouldDumpState);
+ ASSERT_NE(result.buffer, "");
+ ASSERT_THAT(result.buffer, ContainsRegex("Get property result:"));
+ }
+
+ // Set the timestamp argument to 0.
+ result = getHardware()->dump({"--getWithArg", propIdStr, "-i64", "0"});
+
+ ASSERT_FALSE(result.callerShouldDumpState);
+ // There is no freeze obd2 frame at timestamp 0.
+ ASSERT_THAT(result.buffer, ContainsRegex("failed to read property value"));
+}
+
+TEST_F(FakeVehicleHardwareTest, testSaveRestoreProp) {
+ int32_t prop = toInt(VehicleProperty::TIRE_PRESSURE);
+ std::string propIdStr = std::to_string(prop);
+ std::string areaIdStr = std::to_string(WHEEL_FRONT_LEFT);
+
+ DumpResult result = getHardware()->dump({"--save-prop", propIdStr, "-a", areaIdStr});
+
+ ASSERT_FALSE(result.callerShouldDumpState);
+ ASSERT_THAT(result.buffer, ContainsRegex("saved"));
+
+ ASSERT_EQ(setValue(VehiclePropValue{
+ .prop = prop,
+ .areaId = WHEEL_FRONT_LEFT,
+ .value =
+ {
+ .floatValues = {210.0},
+ },
+ }),
+ StatusCode::OK);
+
+ result = getHardware()->dump({"--restore-prop", propIdStr, "-a", areaIdStr});
+
+ ASSERT_FALSE(result.callerShouldDumpState);
+ ASSERT_THAT(result.buffer, ContainsRegex("restored"));
+
+ auto getResult = getValue(VehiclePropValue{.prop = prop, .areaId = WHEEL_FRONT_LEFT});
+
+ ASSERT_TRUE(getResult.ok());
+ // The default value is 200.0.
+ ASSERT_EQ(getResult.value().value.floatValues, std::vector<float>{200.0});
+}
+
+TEST_F(FakeVehicleHardwareTest, testDumpInjectEvent) {
+ int32_t prop = toInt(VehicleProperty::PERF_VEHICLE_SPEED);
+ std::string propIdStr = std::to_string(prop);
+
+ int64_t timestamp = elapsedRealtimeNano();
+ // Inject an event with float value 123.4 and timestamp.
+ DumpResult result = getHardware()->dump(
+ {"--inject-event", propIdStr, "-f", "123.4", "-t", std::to_string(timestamp)});
+
+ ASSERT_FALSE(result.callerShouldDumpState);
+ ASSERT_THAT(result.buffer,
+ ContainsRegex(StringPrintf("Event for property: %d injected", prop)));
+ ASSERT_TRUE(waitForChangedProperties(prop, 0, /*count=*/1, milliseconds(1000)))
+ << "No changed event received for injected event from vehicle bus";
+ auto events = getChangedProperties();
+ ASSERT_EQ(events.size(), 1u);
+ auto event = events[0];
+ ASSERT_EQ(event.timestamp, timestamp);
+ ASSERT_EQ(event.value.floatValues, std::vector<float>({123.4}));
+}
+
TEST_F(FakeVehicleHardwareTest, testDumpInvalidOptions) {
std::vector<std::string> options;
options.push_back("--invalid");
@@ -1405,26 +2282,16 @@
ASSERT_THAT(result.buffer, ContainsRegex("Invalid option: --invalid"));
}
-TEST_F(FakeVehicleHardwareTest, testDumpFakeUserHalHelp) {
- std::vector<std::string> options;
- options.push_back("--user-hal");
-
- DumpResult result = getHardware()->dump(options);
- ASSERT_FALSE(result.callerShouldDumpState);
- ASSERT_NE(result.buffer, "");
- ASSERT_THAT(result.buffer, ContainsRegex("dumps state used for user management"));
-}
-
TEST_F(FakeVehicleHardwareTest, testDumpFakeUserHal) {
std::vector<std::string> options;
options.push_back("--user-hal");
- // Indent: " ".
- options.push_back(" ");
DumpResult result = getHardware()->dump(options);
ASSERT_FALSE(result.callerShouldDumpState);
ASSERT_NE(result.buffer, "");
- ASSERT_THAT(result.buffer, ContainsRegex(" No InitialUserInfo response\n"));
+ ASSERT_THAT(result.buffer,
+ ContainsRegex("No InitialUserInfo response\nNo SwitchUser response\nNo CreateUser "
+ "response\nNo SetUserIdentificationAssociation response\n"));
}
struct SetPropTestCase {
@@ -1606,6 +2473,386 @@
ASSERT_EQ(3.402823466E+38f, value.value.floatValues[2]);
}
+struct OptionsTestCase {
+ std::string name;
+ std::vector<std::string> options;
+ std::string expectMsg;
+};
+
+class FakeVehicleHardwareOptionsTest : public FakeVehicleHardwareTest,
+ public testing::WithParamInterface<OptionsTestCase> {};
+
+std::vector<OptionsTestCase> GenInvalidOptions() {
+ return {{"unknown_command", {"--unknown"}, "Invalid option: --unknown"},
+ {"help", {"--help"}, "Usage:"},
+ {"genfakedata_no_subcommand",
+ {"--genfakedata"},
+ "No subcommand specified for genfakedata"},
+ {"genfakedata_unknown_subcommand",
+ {"--genfakedata", "--unknown"},
+ "Unknown command: \"--unknown\""},
+ {"genfakedata_start_linear_no_args",
+ {"--genfakedata", "--startlinear"},
+ "incorrect argument count"},
+ {"genfakedata_start_linear_invalid_propId",
+ {"--genfakedata", "--startlinear", "abcd", "0.1", "0.1", "0.1", "0.1", "100000000"},
+ "failed to parse propId as int: \"abcd\""},
+ {"genfakedata_start_linear_invalid_middleValue",
+ {"--genfakedata", "--startlinear", "1", "abcd", "0.1", "0.1", "0.1", "100000000"},
+ "failed to parse middleValue as float: \"abcd\""},
+ {"genfakedata_start_linear_invalid_currentValue",
+ {"--genfakedata", "--startlinear", "1", "0.1", "abcd", "0.1", "0.1", "100000000"},
+ "failed to parse currentValue as float: \"abcd\""},
+ {"genfakedata_start_linear_invalid_dispersion",
+ {"--genfakedata", "--startlinear", "1", "0.1", "0.1", "abcd", "0.1", "100000000"},
+ "failed to parse dispersion as float: \"abcd\""},
+ {"genfakedata_start_linear_invalid_increment",
+ {"--genfakedata", "--startlinear", "1", "0.1", "0.1", "0.1", "abcd", "100000000"},
+ "failed to parse increment as float: \"abcd\""},
+ {"genfakedata_start_linear_invalid_interval",
+ {"--genfakedata", "--startlinear", "1", "0.1", "0.1", "0.1", "0.1", "0.1"},
+ "failed to parse interval as int: \"0.1\""},
+ {"genfakedata_stop_linear_no_args",
+ {"--genfakedata", "--stoplinear"},
+ "incorrect argument count"},
+ {"genfakedata_stop_linear_invalid_propId",
+ {"--genfakedata", "--stoplinear", "abcd"},
+ "failed to parse propId as int: \"abcd\""},
+ {"genfakedata_startjson_no_args",
+ {"--genfakedata", "--startjson"},
+ "incorrect argument count"},
+ {"genfakedata_startjson_invalid_repetition",
+ {"--genfakedata", "--startjson", "--path", "file", "0.1"},
+ "failed to parse repetition as int: \"0.1\""},
+ {"genfakedata_startjson_invalid_json_file",
+ {"--genfakedata", "--startjson", "--path", "file", "1"},
+ "invalid JSON file"},
+ {"genfakedata_stopjson_no_args",
+ {"--genfakedata", "--stopjson"},
+ "incorrect argument count"},
+ {"genfakedata_keypress_no_args",
+ {"--genfakedata", "--keypress"},
+ "incorrect argument count"},
+ {"genfakedata_keypress_invalid_keyCode",
+ {"--genfakedata", "--keypress", "0.1", "1"},
+ "failed to parse keyCode as int: \"0.1\""},
+ {"genfakedata_keypress_invalid_display",
+ {"--genfakedata", "--keypress", "1", "0.1"},
+ "failed to parse display as int: \"0.1\""},
+ {"genfakedata_keyinputv2_incorrect_arguments",
+ {"--genfakedata", "--keyinputv2", "1", "1"},
+ "incorrect argument count, need 7 arguments for --genfakedata --keyinputv2\n"},
+ {"genfakedata_keyinputv2_invalid_area",
+ {"--genfakedata", "--keyinputv2", "0.1", "1", "1", "1", "1"},
+ "failed to parse area as int: \"0.1\""},
+ {"genfakedata_keyinputv2_invalid_display",
+ {"--genfakedata", "--keyinputv2", "1", "0.1", "1", "1", "1"},
+ "failed to parse display as int: \"0.1\""},
+ {"genfakedata_keyinputv2_invalid_keycode",
+ {"--genfakedata", "--keyinputv2", "1", "1", "0.1", "1", "1"},
+ "failed to parse keyCode as int: \"0.1\""},
+ {"genfakedata_keyinputv2_invalid_action",
+ {"--genfakedata", "--keyinputv2", "1", "1", "1", "0.1", "1"},
+ "failed to parse action as int: \"0.1\""},
+ {"genfakedata_keyinputv2_invalid_repeatcount",
+ {"--genfakedata", "--keyinputv2", "1", "1", "1", "1", "0.1"},
+ "failed to parse repeatCount as int: \"0.1\""},
+ {"genfakedata_motioninput_invalid_argument_count",
+ {"--genfakedata", "--motioninput", "1", "1", "1", "1", "1"},
+ "incorrect argument count, need at least 14 arguments for --genfakedata "
+ "--motioninput including at least 1 --pointer\n"},
+ {"genfakedata_motioninput_pointer_invalid_argument_count",
+ {"--genfakedata", "--motioninput", "1", "1", "1", "1", "1", "--pointer", "1", "1", "1",
+ "1", "1", "1", "--pointer"},
+ "incorrect argument count, need 6 arguments for every --pointer\n"},
+ {"genfakedata_motioninput_invalid_area",
+ {"--genfakedata", "--motioninput", "0.1", "1", "1", "1", "1", "--pointer", "1", "1",
+ "1", "1", "1", "1"},
+ "failed to parse area as int: \"0.1\""},
+ {"genfakedata_motioninput_invalid_display",
+ {"--genfakedata", "--motioninput", "1", "0.1", "1", "1", "1", "--pointer", "1", "1",
+ "1", "1", "1", "1"},
+ "failed to parse display as int: \"0.1\""},
+ {"genfakedata_motioninput_invalid_inputtype",
+ {"--genfakedata", "--motioninput", "1", "1", "0.1", "1", "1", "--pointer", "1", "1",
+ "1", "1", "1", "1"},
+ "failed to parse inputType as int: \"0.1\""},
+ {"genfakedata_motioninput_invalid_action",
+ {"--genfakedata", "--motioninput", "1", "1", "1", "0.1", "1", "--pointer", "1", "1",
+ "1", "1", "1", "1"},
+ "failed to parse action as int: \"0.1\""},
+ {"genfakedata_motioninput_invalid_buttonstate",
+ {"--genfakedata", "--motioninput", "1", "1", "1", "1", "0.1", "--pointer", "1", "1",
+ "1.2", "1.2", "1.2", "1.2"},
+ "failed to parse buttonState as int: \"0.1\""},
+ {"genfakedata_motioninput_invalid_pointerid",
+ {"--genfakedata", "--motioninput", "1", "1", "1", "1", "1", "--pointer", "0.1", "1",
+ "1.2", "1", "1", "1"},
+ "failed to parse pointerId as int: \"0.1\""},
+ {"genfakedata_motioninput_invalid_tooltype",
+ {"--genfakedata", "--motioninput", "1", "1", "1", "1", "1", "--pointer", "1", "0.1",
+ "1.2", "1", "1", "1"},
+ "failed to parse toolType as int: \"0.1\""}};
+}
+
+TEST_P(FakeVehicleHardwareOptionsTest, testInvalidOptions) {
+ auto tc = GetParam();
+
+ DumpResult result = getHardware()->dump(tc.options);
+
+ EXPECT_FALSE(result.callerShouldDumpState);
+ EXPECT_THAT(result.buffer, HasSubstr(tc.expectMsg));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ FakeVehicleHardwareOptionsTests, FakeVehicleHardwareOptionsTest,
+ testing::ValuesIn(GenInvalidOptions()),
+ [](const testing::TestParamInfo<FakeVehicleHardwareOptionsTest::ParamType>& info) {
+ return info.param.name;
+ });
+
+TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataLinear) {
+ // Start a fake linear data generator for vehicle speed at 0.1s interval.
+ // range: 0 - 100, current value: 30, step: 20.
+ std::string propIdString = StringPrintf("%d", toInt(VehicleProperty::PERF_VEHICLE_SPEED));
+ std::vector<std::string> options = {"--genfakedata", "--startlinear", propIdString,
+ /*middleValue=*/"50",
+ /*currentValue=*/"30",
+ /*dispersion=*/"50",
+ /*increment=*/"20",
+ /*interval=*/"100000000"};
+
+ DumpResult result = getHardware()->dump(options);
+
+ ASSERT_FALSE(result.callerShouldDumpState);
+ ASSERT_THAT(result.buffer, HasSubstr("successfully"));
+
+ ASSERT_TRUE(waitForChangedProperties(toInt(VehicleProperty::PERF_VEHICLE_SPEED), 0, /*count=*/5,
+ milliseconds(1000)))
+ << "not enough events generated for linear data generator";
+
+ int32_t value = 30;
+ auto events = getChangedProperties();
+ for (size_t i = 0; i < 5; i++) {
+ ASSERT_EQ(1u, events[i].value.floatValues.size());
+ EXPECT_EQ(static_cast<float>(value), events[i].value.floatValues[0]);
+ value = (value + 20) % 100;
+ }
+
+ // Stop the linear generator.
+ options = {"--genfakedata", "--stoplinear", propIdString};
+
+ result = getHardware()->dump(options);
+
+ ASSERT_FALSE(result.callerShouldDumpState);
+ ASSERT_THAT(result.buffer, HasSubstr("successfully"));
+
+ clearChangedProperties();
+ std::this_thread::sleep_for(std::chrono::milliseconds(200));
+
+ // There should be no new events generated.
+ EXPECT_EQ(0u, getEventCount(toInt(VehicleProperty::PERF_VEHICLE_SPEED), 0));
+}
+
+std::string getTestFilePath(const char* filename) {
+ static std::string baseDir = android::base::GetExecutableDirectory();
+ return baseDir + "/fakedata/" + filename;
+}
+
+TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJson) {
+ std::vector<std::string> options = {"--genfakedata", "--startjson", "--path",
+ getTestFilePath("prop.json"), "2"};
+
+ DumpResult result = getHardware()->dump(options);
+
+ ASSERT_FALSE(result.callerShouldDumpState);
+ ASSERT_THAT(result.buffer, HasSubstr("successfully"));
+
+ ASSERT_TRUE(waitForChangedProperties(/*count=*/8, milliseconds(1000)))
+ << "not enough events generated for JSON data generator";
+
+ auto events = getChangedProperties();
+ ASSERT_EQ(8u, events.size());
+ // First set of events, we test 1st and the last.
+ EXPECT_EQ(1u, events[0].value.int32Values.size());
+ EXPECT_EQ(8, events[0].value.int32Values[0]);
+ EXPECT_EQ(1u, events[3].value.int32Values.size());
+ EXPECT_EQ(10, events[3].value.int32Values[0]);
+ // Second set of the same events.
+ EXPECT_EQ(1u, events[4].value.int32Values.size());
+ EXPECT_EQ(8, events[4].value.int32Values[0]);
+ EXPECT_EQ(1u, events[7].value.int32Values.size());
+ EXPECT_EQ(10, events[7].value.int32Values[0]);
+}
+
+TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJsonByContent) {
+ std::vector<std::string> options = {
+ "--genfakedata", "--startjson", "--content",
+ "[{\"timestamp\":1000000,\"areaId\":0,\"value\":8,\"prop\":289408000}]", "1"};
+
+ DumpResult result = getHardware()->dump(options);
+
+ ASSERT_FALSE(result.callerShouldDumpState);
+ ASSERT_THAT(result.buffer, HasSubstr("successfully"));
+
+ ASSERT_TRUE(waitForChangedProperties(/*count=*/1, milliseconds(1000)))
+ << "not enough events generated for JSON data generator";
+
+ auto events = getChangedProperties();
+ ASSERT_EQ(1u, events.size());
+ EXPECT_EQ(1u, events[0].value.int32Values.size());
+ EXPECT_EQ(8, events[0].value.int32Values[0]);
+}
+
+TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJsonInvalidContent) {
+ std::vector<std::string> options = {"--genfakedata", "--startjson", "--content", "[{", "2"};
+
+ DumpResult result = getHardware()->dump(options);
+
+ ASSERT_FALSE(result.callerShouldDumpState);
+ ASSERT_THAT(result.buffer, HasSubstr("invalid JSON content"));
+}
+
+TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJsonInvalidFile) {
+ std::vector<std::string> options = {"--genfakedata", "--startjson", "--path",
+ getTestFilePath("blahblah.json"), "2"};
+
+ DumpResult result = getHardware()->dump(options);
+
+ ASSERT_FALSE(result.callerShouldDumpState);
+ ASSERT_THAT(result.buffer, HasSubstr("invalid JSON file"));
+}
+
+TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJsonStop) {
+ // No iteration number provided, would loop indefinitely.
+ std::vector<std::string> options = {"--genfakedata", "--startjson", "--path",
+ getTestFilePath("prop.json")};
+
+ DumpResult result = getHardware()->dump(options);
+
+ ASSERT_FALSE(result.callerShouldDumpState);
+ ASSERT_THAT(result.buffer, HasSubstr("successfully"));
+
+ std::string id = result.buffer.substr(result.buffer.find("ID: ") + 4);
+
+ result = getHardware()->dump({"--genfakedata", "--stopjson", id});
+
+ ASSERT_FALSE(result.callerShouldDumpState);
+ ASSERT_THAT(result.buffer, HasSubstr("successfully"));
+}
+
+TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJsonStopInvalidFile) {
+ // No iteration number provided, would loop indefinitely.
+ std::vector<std::string> options = {"--genfakedata", "--startjson", "--path",
+ getTestFilePath("prop.json")};
+
+ DumpResult result = getHardware()->dump(options);
+
+ ASSERT_FALSE(result.callerShouldDumpState);
+ ASSERT_THAT(result.buffer, HasSubstr("successfully"));
+
+ result = getHardware()->dump({"--genfakedata", "--stopjson", "1234"});
+
+ ASSERT_FALSE(result.callerShouldDumpState);
+ ASSERT_THAT(result.buffer, HasSubstr("No JSON event generator found"));
+
+ // TearDown function should destroy the generator which stops the iteration.
+}
+
+TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataKeyPress) {
+ std::vector<std::string> options = {"--genfakedata", "--keypress", "1", "2"};
+
+ DumpResult result = getHardware()->dump(options);
+
+ ASSERT_FALSE(result.callerShouldDumpState);
+ ASSERT_THAT(result.buffer, HasSubstr("successfully"));
+
+ auto events = getChangedProperties();
+ ASSERT_EQ(2u, events.size());
+ EXPECT_EQ(toInt(VehicleProperty::HW_KEY_INPUT), events[0].prop);
+ EXPECT_EQ(toInt(VehicleProperty::HW_KEY_INPUT), events[1].prop);
+ ASSERT_EQ(3u, events[0].value.int32Values.size());
+ ASSERT_EQ(3u, events[1].value.int32Values.size());
+ EXPECT_EQ(toInt(VehicleHwKeyInputAction::ACTION_DOWN), events[0].value.int32Values[0]);
+ EXPECT_EQ(1, events[0].value.int32Values[1]);
+ EXPECT_EQ(2, events[0].value.int32Values[2]);
+ EXPECT_EQ(toInt(VehicleHwKeyInputAction::ACTION_UP), events[1].value.int32Values[0]);
+ EXPECT_EQ(1, events[1].value.int32Values[1]);
+ EXPECT_EQ(2, events[1].value.int32Values[2]);
+}
+
+TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataKeyInputV2) {
+ std::vector<std::string> options = {"--genfakedata", "--keyinputv2", "1", "2", "3", "4", "5"};
+
+ DumpResult result = getHardware()->dump(options);
+
+ ASSERT_FALSE(result.callerShouldDumpState);
+ ASSERT_THAT(result.buffer, HasSubstr("successfully"));
+
+ auto events = getChangedProperties();
+ ASSERT_EQ(1u, events.size());
+ EXPECT_EQ(toInt(VehicleProperty::HW_KEY_INPUT_V2), events[0].prop);
+ ASSERT_EQ(4u, events[0].value.int32Values.size());
+ EXPECT_EQ(2, events[0].value.int32Values[0]);
+ EXPECT_EQ(3, events[0].value.int32Values[1]);
+ EXPECT_EQ(4, events[0].value.int32Values[2]);
+ EXPECT_EQ(5, events[0].value.int32Values[3]);
+ ASSERT_EQ(1u, events[0].value.int64Values.size());
+}
+
+TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataMotionInput) {
+ std::vector<std::string> options = {"--genfakedata",
+ "--motioninput",
+ "1",
+ "2",
+ "3",
+ "4",
+ "5",
+ "--pointer",
+ "11",
+ "22",
+ "33.3",
+ "44.4",
+ "55.5",
+ "66.6",
+ "--pointer",
+ "21",
+ "32",
+ "43.3",
+ "54.4",
+ "65.5",
+ "76.6"};
+
+ DumpResult result = getHardware()->dump(options);
+
+ ASSERT_FALSE(result.callerShouldDumpState);
+ ASSERT_THAT(result.buffer, HasSubstr("successfully"));
+
+ auto events = getChangedProperties();
+ ASSERT_EQ(1u, events.size());
+ EXPECT_EQ(toInt(VehicleProperty::HW_MOTION_INPUT), events[0].prop);
+ ASSERT_EQ(9u, events[0].value.int32Values.size());
+ EXPECT_EQ(2, events[0].value.int32Values[0]);
+ EXPECT_EQ(3, events[0].value.int32Values[1]);
+ EXPECT_EQ(4, events[0].value.int32Values[2]);
+ EXPECT_EQ(5, events[0].value.int32Values[3]);
+ EXPECT_EQ(2, events[0].value.int32Values[4]);
+ EXPECT_EQ(11, events[0].value.int32Values[5]);
+ EXPECT_EQ(21, events[0].value.int32Values[6]);
+ EXPECT_EQ(22, events[0].value.int32Values[7]);
+ EXPECT_EQ(32, events[0].value.int32Values[8]);
+ ASSERT_EQ(8u, events[0].value.floatValues.size());
+ EXPECT_FLOAT_EQ(33.3, events[0].value.floatValues[0]);
+ EXPECT_FLOAT_EQ(43.3, events[0].value.floatValues[1]);
+ EXPECT_FLOAT_EQ(44.4, events[0].value.floatValues[2]);
+ EXPECT_FLOAT_EQ(54.4, events[0].value.floatValues[3]);
+ EXPECT_FLOAT_EQ(55.5, events[0].value.floatValues[4]);
+ EXPECT_FLOAT_EQ(65.5, events[0].value.floatValues[5]);
+ EXPECT_FLOAT_EQ(66.6, events[0].value.floatValues[6]);
+ EXPECT_FLOAT_EQ(76.6, events[0].value.floatValues[7]);
+ ASSERT_EQ(1u, events[0].value.int64Values.size());
+}
+
TEST_F(FakeVehicleHardwareTest, testGetEchoReverseBytes) {
ASSERT_EQ(setValue(VehiclePropValue{
.prop = ECHO_REVERSE_BYTES,
@@ -1653,6 +2900,348 @@
}
}
+TEST_F(FakeVehicleHardwareTest, testSetHvacTemperatureValueSuggestion) {
+ float CELSIUS = static_cast<float>(toInt(VehicleUnit::CELSIUS));
+ float FAHRENHEIT = static_cast<float>(toInt(VehicleUnit::FAHRENHEIT));
+
+ VehiclePropValue floatArraySizeFour = {
+ .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = HVAC_ALL,
+ .value.floatValues = {0, CELSIUS, 0, 0},
+ };
+ StatusCode status = setValue(floatArraySizeFour);
+ EXPECT_EQ(status, StatusCode::OK);
+
+ VehiclePropValue floatArraySizeZero = {
+ .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = HVAC_ALL,
+ };
+ status = setValue(floatArraySizeZero);
+ EXPECT_EQ(status, StatusCode::INVALID_ARG);
+
+ VehiclePropValue floatArraySizeFive = {
+ .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = HVAC_ALL,
+ .value.floatValues = {0, CELSIUS, 0, 0, 0},
+ };
+ status = setValue(floatArraySizeFive);
+ EXPECT_EQ(status, StatusCode::INVALID_ARG);
+
+ VehiclePropValue invalidUnit = {
+ .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = HVAC_ALL,
+ .value.floatValues = {0, 0, 0, 0},
+ };
+ status = setValue(floatArraySizeFive);
+ EXPECT_EQ(status, StatusCode::INVALID_ARG);
+ clearChangedProperties();
+
+ // Config array values from HVAC_TEMPERATURE_SET in DefaultProperties.json
+ auto configs = getHardware()->getAllPropertyConfigs();
+ VehiclePropConfig* hvacTemperatureSetConfig = nullptr;
+ for (auto& config : configs) {
+ if (config.prop == toInt(VehicleProperty::HVAC_TEMPERATURE_SET)) {
+ hvacTemperatureSetConfig = &config;
+ break;
+ }
+ }
+ EXPECT_NE(hvacTemperatureSetConfig, nullptr);
+
+ auto& hvacTemperatureSetConfigArray = hvacTemperatureSetConfig->configArray;
+ // The HVAC_TEMPERATURE_SET config array values are temperature values that have been multiplied
+ // by 10 and converted to integers. HVAC_TEMPERATURE_VALUE_SUGGESTION specifies the temperature
+ // values to be in the original floating point form so we divide by 10 and convert to float.
+ float minTempInCelsius = hvacTemperatureSetConfigArray[0] / 10.0f;
+ float maxTempInCelsius = hvacTemperatureSetConfigArray[1] / 10.0f;
+ float incrementInCelsius = hvacTemperatureSetConfigArray[2] / 10.0f;
+ float minTempInFahrenheit = hvacTemperatureSetConfigArray[3] / 10.0f;
+ float maxTempInFahrenheit = hvacTemperatureSetConfigArray[4] / 10.0f;
+ float incrementInFahrenheit = hvacTemperatureSetConfigArray[5] / 10.0f;
+
+ auto testCases = {
+ SetSpecialValueTestCase{
+ .name = "min_celsius_temperature",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = HVAC_ALL,
+ .value.floatValues = {minTempInCelsius, CELSIUS, 0, 0},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = HVAC_ALL,
+ .value.floatValues = {minTempInCelsius, CELSIUS,
+ minTempInCelsius,
+ minTempInFahrenheit},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "min_fahrenheit_temperature",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = HVAC_ALL,
+ .value.floatValues = {minTempInFahrenheit, FAHRENHEIT,
+ 0, 0},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = HVAC_ALL,
+ .value.floatValues = {minTempInFahrenheit, FAHRENHEIT,
+ minTempInCelsius,
+ minTempInFahrenheit},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "max_celsius_temperature",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = HVAC_ALL,
+ .value.floatValues = {maxTempInCelsius, CELSIUS, 0, 0},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = HVAC_ALL,
+ .value.floatValues = {maxTempInCelsius, CELSIUS,
+ maxTempInCelsius,
+ maxTempInFahrenheit},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "max_fahrenheit_temperature",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = HVAC_ALL,
+ .value.floatValues = {maxTempInFahrenheit, FAHRENHEIT,
+ 0, 0},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = HVAC_ALL,
+ .value.floatValues = {maxTempInFahrenheit, FAHRENHEIT,
+ maxTempInCelsius,
+ maxTempInFahrenheit},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "below_min_celsius_temperature",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = HVAC_ALL,
+ .value.floatValues = {minTempInCelsius - 1, CELSIUS, 0,
+ 0},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = HVAC_ALL,
+ .value.floatValues = {minTempInCelsius - 1, CELSIUS,
+ minTempInCelsius,
+ minTempInFahrenheit},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "below_min_fahrenheit_temperature",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = HVAC_ALL,
+ .value.floatValues = {minTempInFahrenheit - 1,
+ FAHRENHEIT, 0, 0},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = HVAC_ALL,
+ .value.floatValues = {minTempInFahrenheit - 1,
+ FAHRENHEIT, minTempInCelsius,
+ minTempInFahrenheit},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "above_max_celsius_temperature",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = HVAC_ALL,
+ .value.floatValues = {maxTempInCelsius + 1, CELSIUS, 0,
+ 0},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = HVAC_ALL,
+ .value.floatValues = {maxTempInCelsius + 1, CELSIUS,
+ maxTempInCelsius,
+ maxTempInFahrenheit},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "above_max_fahrenheit_temperature",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = HVAC_ALL,
+ .value.floatValues = {maxTempInFahrenheit + 1,
+ FAHRENHEIT, 0, 0},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = HVAC_ALL,
+ .value.floatValues = {maxTempInFahrenheit + 1,
+ FAHRENHEIT, maxTempInCelsius,
+ maxTempInFahrenheit},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "inbetween_value_celsius",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = HVAC_ALL,
+ .value.floatValues = {minTempInCelsius +
+ incrementInCelsius * 2.5f,
+ CELSIUS, 0, 0},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = HVAC_ALL,
+ .value.floatValues =
+ {minTempInCelsius + incrementInCelsius * 2.5f,
+ CELSIUS,
+ minTempInCelsius + incrementInCelsius * 2,
+ minTempInFahrenheit +
+ incrementInFahrenheit * 2},
+ },
+ },
+ },
+ SetSpecialValueTestCase{
+ .name = "inbetween_value_fahrenheit",
+ .valuesToSet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = HVAC_ALL,
+ .value.floatValues = {minTempInFahrenheit +
+ incrementInFahrenheit *
+ 2.5f,
+ FAHRENHEIT, 0, 0},
+ },
+ },
+ .expectedValuesToGet =
+ {
+ VehiclePropValue{
+ .prop = toInt(
+ VehicleProperty::
+ HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = HVAC_ALL,
+ .value.floatValues =
+ {minTempInFahrenheit +
+ incrementInFahrenheit * 2.5f,
+ FAHRENHEIT,
+ minTempInCelsius + incrementInCelsius * 2,
+ minTempInFahrenheit +
+ incrementInFahrenheit * 2},
+ },
+ },
+ },
+ };
+
+ for (auto& tc : testCases) {
+ StatusCode status = setValue(tc.valuesToSet[0]);
+ EXPECT_EQ(status, StatusCode::OK);
+
+ auto events = getChangedProperties();
+ EXPECT_EQ(events.size(), static_cast<size_t>(1));
+ events[0].timestamp = 0;
+
+ EXPECT_EQ(events[0], tc.expectedValuesToGet[0]);
+ clearChangedProperties();
+ }
+}
+
} // namespace fake
} // namespace vehicle
} // namespace automotive
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/fakedata/prop.json b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/fakedata/prop.json
new file mode 100644
index 0000000..7123a00
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/fakedata/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/hardware/test/override/gear_selection.json b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/override/gear_selection.json
index 59666b8..693f1e2 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/override/gear_selection.json
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/override/gear_selection.json
@@ -1,9 +1,13 @@
-[
- {
- "timestamp": 1000000,
- "areaId": 0,
- "value": 8,
- // GEAR_SELECTION
- "prop": 289408000
- }
-]
+{
+ "apiVersion": 1,
+ "properties": [
+ {
+ "property": "VehicleProperty::GEAR_SELECTION",
+ "defaultValue": {
+ "int32Values": [
+ 8
+ ]
+ }
+ }
+ ]
+}
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/override/hvac_temperature_set.json b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/override/hvac_temperature_set.json
index 93a97ed..07cfebb 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/override/hvac_temperature_set.json
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/override/hvac_temperature_set.json
@@ -1,10 +1,20 @@
-[
- {
- "timestamp": 1000000,
- // HVAC_LEFT
- "areaId": 49,
- "value": 30,
- // HVAC_TEMPERATURE_SET
- "prop": 358614275
- }
-]
+{
+ "apiVersion": 1,
+ "properties": [
+ {
+ "property": "VehicleProperty::HVAC_TEMPERATURE_SET",
+ "areas": [
+ {
+ "defaultValue": {
+ "floatValues": [
+ 30.0
+ ]
+ },
+ "areaId": 49,
+ "minFloatValue": 16.0,
+ "maxFloatValue": 32.0
+ }
+ ]
+ }
+ ]
+}
diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/include/FakeUserHal.h b/automotive/vehicle/aidl/impl/fake_impl/userhal/include/FakeUserHal.h
index 4ae9c8c..fcbe8fd 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/userhal/include/FakeUserHal.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/userhal/include/FakeUserHal.h
@@ -64,7 +64,7 @@
std::string showDumpHelp() const;
// Dump its contents.
- std::string dump(std::string indent) const;
+ std::string dump() const;
private:
const std::shared_ptr<VehiclePropValuePool> mValuePool;
diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp b/automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp
index 7748fb6..878c2e7 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp
@@ -328,6 +328,9 @@
<< "invalid action on lshal response: " << response->toString();
}
+ // Update area ID to 0 since this is a global property (and the area ID was only set to emulate
+ // the request id behavior).
+ response->areaId = 0;
ALOGD("updating property to: %s", response->toString().c_str());
return response;
}
@@ -336,33 +339,31 @@
return fmt::format("{}: dumps state used for user management\n", kUserHalDumpOption);
}
-std::string FakeUserHal::dump(std::string indent) const {
+std::string FakeUserHal::dump() const {
std::scoped_lock<std::mutex> lockGuard(mLock);
std::string info;
if (mInitialUserResponseFromCmd != nullptr) {
- info += fmt::format("{}InitialUserInfo response: {}\n", indent,
+ info += fmt::format("InitialUserInfo response: {}\n",
mInitialUserResponseFromCmd->toString());
} else {
- info += fmt::format("{}No InitialUserInfo response\n", indent);
+ info += "No InitialUserInfo response\n";
}
if (mSwitchUserResponseFromCmd != nullptr) {
- info += fmt::format("{}SwitchUser response: {}\n", indent,
- mSwitchUserResponseFromCmd->toString());
+ info += fmt::format("SwitchUser response: {}\n", mSwitchUserResponseFromCmd->toString());
} else {
- info += fmt::format("{}No SwitchUser response\n", indent);
+ info += "No SwitchUser response\n";
}
if (mCreateUserResponseFromCmd != nullptr) {
- info += fmt::format("{}CreateUser response: {}\n", indent,
- mCreateUserResponseFromCmd->toString());
+ info += fmt::format("CreateUser response: {}\n", mCreateUserResponseFromCmd->toString());
} else {
- info += fmt::format("{}No CreateUser response\n", indent);
+ info += "No CreateUser response\n";
}
if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) {
- info += fmt::format("{}SetUserIdentificationAssociation response: {}\n", indent,
+ info += fmt::format("SetUserIdentificationAssociation response: {}\n",
mSetUserIdentificationAssociationResponseFromCmd->toString());
} else {
- info += fmt::format("{}No SetUserIdentificationAssociation response\n", indent);
+ info += "No SetUserIdentificationAssociation response\n";
}
return info;
}
diff --git a/automotive/vehicle/aidl/impl/grpc/Android.bp b/automotive/vehicle/aidl/impl/grpc/Android.bp
new file mode 100644
index 0000000..06c9600
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/grpc/Android.bp
@@ -0,0 +1,126 @@
+// Copyright (C) 2023 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.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+genrule {
+ name: "VehicleServerProtoStub_h@default-grpc",
+ tools: [
+ "aprotoc",
+ "protoc-gen-grpc-cpp-plugin",
+ ],
+ cmd: "$(location aprotoc) -I$$(dirname $(in)) -Ihardware/interfaces/automotive/vehicle/aidl/impl/proto -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)",
+ srcs: [
+ "proto/VehicleServer.proto",
+ ],
+ out: [
+ "VehicleServer.pb.h",
+ "VehicleServer.grpc.pb.h",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+genrule {
+ name: "VehicleServerProtoStub_cc@default-grpc",
+ tools: [
+ "aprotoc",
+ "protoc-gen-grpc-cpp-plugin",
+ ],
+ cmd: "$(location aprotoc) -I$$(dirname $(in)) -Ihardware/interfaces/automotive/vehicle/aidl/impl/proto -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)",
+ srcs: [
+ "proto/VehicleServer.proto",
+ ],
+ out: [
+ "VehicleServer.pb.cc",
+ "VehicleServer.grpc.pb.cc",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+cc_library_static {
+ name: "android.hardware.automotive.vehicle@default-grpc-libgrpc",
+ vendor: true,
+ host_supported: true,
+ include_dirs: [
+ "external/protobuf/src",
+ ],
+ generated_headers: [
+ "VehicleServerProtoStub_h@default-grpc",
+ ],
+ export_generated_headers: [
+ "VehicleServerProtoStub_h@default-grpc",
+ ],
+ generated_sources: [
+ "VehicleServerProtoStub_cc@default-grpc",
+ ],
+ whole_static_libs: [
+ "VehicleHalProtos",
+ ],
+ shared_libs: [
+ "libgrpc++",
+ ],
+ cflags: [
+ "-Wno-unused-parameter",
+ ],
+}
+
+cc_library_static {
+ name: "android.hardware.automotive.vehicle@default-grpc-hardware-lib",
+ defaults: ["VehicleHalDefaults"],
+ vendor: true,
+ srcs: [
+ "GRPCVehicleHardware.cpp",
+ ],
+ whole_static_libs: [
+ "android.hardware.automotive.vehicle@default-grpc-libgrpc",
+ "VehicleHalProtoMessageConverter",
+ ],
+ header_libs: [
+ "IVehicleHardware",
+ ],
+ shared_libs: [
+ "libgrpc++",
+ "libprotobuf-cpp-full",
+ ],
+ export_include_dirs: ["."],
+ cflags: [
+ "-Wno-unused-parameter",
+ ],
+}
+
+cc_library_static {
+ name: "android.hardware.automotive.vehicle@default-grpc-server-lib",
+ defaults: ["VehicleHalDefaults"],
+ vendor: true,
+ srcs: [
+ "GRPCVehicleProxyServer.cpp",
+ ],
+ whole_static_libs: [
+ "android.hardware.automotive.vehicle@default-grpc-libgrpc",
+ "VehicleHalProtoMessageConverter",
+ ],
+ header_libs: [
+ "IVehicleHardware",
+ ],
+ shared_libs: [
+ "libgrpc++",
+ "libprotobuf-cpp-full",
+ ],
+ export_include_dirs: ["."],
+ cflags: [
+ "-Wno-unused-parameter",
+ ],
+}
diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.cpp b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.cpp
new file mode 100644
index 0000000..0742283
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.cpp
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2023 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 <GRPCVehicleHardware.h>
+
+#include "ProtoMessageConverter.h"
+
+#include <android-base/logging.h>
+#include <grpc++/grpc++.h>
+
+#include <cstdlib>
+#include <mutex>
+#include <shared_mutex>
+#include <utility>
+
+namespace android::hardware::automotive::vehicle::virtualization {
+
+static std::shared_ptr<::grpc::ChannelCredentials> getChannelCredentials() {
+ // TODO(chenhaosjtuacm): get secured credentials here
+ return ::grpc::InsecureChannelCredentials();
+}
+
+GRPCVehicleHardware::GRPCVehicleHardware(std::string service_addr)
+ : mServiceAddr(std::move(service_addr)),
+ mGrpcChannel(::grpc::CreateChannel(mServiceAddr, getChannelCredentials())),
+ mGrpcStub(proto::VehicleServer::NewStub(mGrpcChannel)),
+ mValuePollingThread([this] { ValuePollingLoop(); }) {}
+
+GRPCVehicleHardware::~GRPCVehicleHardware() {
+ {
+ std::lock_guard lck(mShutdownMutex);
+ mShuttingDownFlag.store(true);
+ }
+ mShutdownCV.notify_all();
+ mValuePollingThread.join();
+}
+
+std::vector<aidlvhal::VehiclePropConfig> GRPCVehicleHardware::getAllPropertyConfigs() const {
+ std::vector<aidlvhal::VehiclePropConfig> configs;
+ ::grpc::ClientContext context;
+ auto config_stream = mGrpcStub->GetAllPropertyConfig(&context, ::google::protobuf::Empty());
+ proto::VehiclePropConfig protoConfig;
+ while (config_stream->Read(&protoConfig)) {
+ aidlvhal::VehiclePropConfig config;
+ proto_msg_converter::protoToAidl(protoConfig, &config);
+ configs.push_back(std::move(config));
+ }
+ auto grpc_status = config_stream->Finish();
+ if (!grpc_status.ok()) {
+ LOG(ERROR) << __func__
+ << ": GRPC GetAllPropertyConfig Failed: " << grpc_status.error_message();
+ }
+ return configs;
+}
+
+aidlvhal::StatusCode GRPCVehicleHardware::setValues(
+ std::shared_ptr<const SetValuesCallback> callback,
+ const std::vector<aidlvhal::SetValueRequest>& requests) {
+ ::grpc::ClientContext context;
+ proto::VehiclePropValueRequests protoRequests;
+ proto::SetValueResults protoResults;
+ for (const auto& request : requests) {
+ auto& protoRequest = *protoRequests.add_requests();
+ protoRequest.set_request_id(request.requestId);
+ proto_msg_converter::aidlToProto(request.value, protoRequest.mutable_value());
+ }
+ // TODO(chenhaosjtuacm): Make it Async.
+ auto grpc_status = mGrpcStub->SetValues(&context, protoRequests, &protoResults);
+ if (!grpc_status.ok()) {
+ LOG(ERROR) << __func__ << ": GRPC SetValues Failed: " << grpc_status.error_message();
+ {
+ std::shared_lock lck(mCallbackMutex);
+ // TODO(chenhaosjtuacm): call on-set-error callback.
+ }
+ return aidlvhal::StatusCode::INTERNAL_ERROR;
+ }
+ std::vector<aidlvhal::SetValueResult> results;
+ for (const auto& protoResult : protoResults.results()) {
+ auto& result = results.emplace_back();
+ result.requestId = protoResult.request_id();
+ result.status = static_cast<aidlvhal::StatusCode>(protoResult.status());
+ // TODO(chenhaosjtuacm): call on-set-error callback.
+ }
+ (*callback)(std::move(results));
+
+ return aidlvhal::StatusCode::OK;
+}
+
+aidlvhal::StatusCode GRPCVehicleHardware::getValues(
+ std::shared_ptr<const GetValuesCallback> callback,
+ const std::vector<aidlvhal::GetValueRequest>& requests) const {
+ ::grpc::ClientContext context;
+ proto::VehiclePropValueRequests protoRequests;
+ proto::GetValueResults protoResults;
+ for (const auto& request : requests) {
+ auto& protoRequest = *protoRequests.add_requests();
+ protoRequest.set_request_id(request.requestId);
+ proto_msg_converter::aidlToProto(request.prop, protoRequest.mutable_value());
+ }
+ // TODO(chenhaosjtuacm): Make it Async.
+ auto grpc_status = mGrpcStub->GetValues(&context, protoRequests, &protoResults);
+ if (!grpc_status.ok()) {
+ LOG(ERROR) << __func__ << ": GRPC GetValues Failed: " << grpc_status.error_message();
+ return aidlvhal::StatusCode::INTERNAL_ERROR;
+ }
+ std::vector<aidlvhal::GetValueResult> results;
+ for (const auto& protoResult : protoResults.results()) {
+ auto& result = results.emplace_back();
+ result.requestId = protoResult.request_id();
+ result.status = static_cast<aidlvhal::StatusCode>(protoResult.status());
+ if (protoResult.has_value()) {
+ aidlvhal::VehiclePropValue value;
+ proto_msg_converter::protoToAidl(protoResult.value(), &value);
+ result.prop = std::move(value);
+ }
+ }
+ (*callback)(std::move(results));
+
+ return aidlvhal::StatusCode::OK;
+}
+
+void GRPCVehicleHardware::registerOnPropertyChangeEvent(
+ std::unique_ptr<const PropertyChangeCallback> callback) {
+ std::lock_guard lck(mCallbackMutex);
+ if (mOnPropChange) {
+ LOG(ERROR) << __func__ << " must only be called once.";
+ return;
+ }
+ mOnPropChange = std::move(callback);
+}
+
+void GRPCVehicleHardware::registerOnPropertySetErrorEvent(
+ std::unique_ptr<const PropertySetErrorCallback> callback) {
+ std::lock_guard lck(mCallbackMutex);
+ if (mOnSetErr) {
+ LOG(ERROR) << __func__ << " must only be called once.";
+ return;
+ }
+ mOnSetErr = std::move(callback);
+}
+
+DumpResult GRPCVehicleHardware::dump(const std::vector<std::string>& options) {
+ ::grpc::ClientContext context;
+ proto::DumpOptions protoDumpOptions;
+ proto::DumpResult protoDumpResult;
+ for (const auto& option : options) {
+ protoDumpOptions.add_options(option);
+ }
+ auto grpc_status = mGrpcStub->Dump(&context, protoDumpOptions, &protoDumpResult);
+ if (!grpc_status.ok()) {
+ LOG(ERROR) << __func__ << ": GRPC Dump Failed: " << grpc_status.error_message();
+ return {};
+ }
+ return {
+ .callerShouldDumpState = protoDumpResult.caller_should_dump_state(),
+ .buffer = protoDumpResult.buffer(),
+ };
+}
+
+aidlvhal::StatusCode GRPCVehicleHardware::checkHealth() {
+ ::grpc::ClientContext context;
+ proto::VehicleHalCallStatus protoStatus;
+ auto grpc_status = mGrpcStub->CheckHealth(&context, ::google::protobuf::Empty(), &protoStatus);
+ if (!grpc_status.ok()) {
+ LOG(ERROR) << __func__ << ": GRPC CheckHealth Failed: " << grpc_status.error_message();
+ return aidlvhal::StatusCode::INTERNAL_ERROR;
+ }
+ return static_cast<aidlvhal::StatusCode>(protoStatus.status_code());
+}
+
+aidlvhal::StatusCode GRPCVehicleHardware::updateSampleRate(int32_t propId, int32_t areaId,
+ float sampleRate) {
+ ::grpc::ClientContext context;
+ proto::UpdateSampleRateRequest request;
+ proto::VehicleHalCallStatus protoStatus;
+ request.set_prop(propId);
+ request.set_area_id(areaId);
+ request.set_sample_rate(sampleRate);
+ auto grpc_status = mGrpcStub->UpdateSampleRate(&context, request, &protoStatus);
+ if (!grpc_status.ok()) {
+ LOG(ERROR) << __func__ << ": GRPC UpdateSampleRate Failed: " << grpc_status.error_message();
+ return aidlvhal::StatusCode::INTERNAL_ERROR;
+ }
+ return static_cast<aidlvhal::StatusCode>(protoStatus.status_code());
+}
+
+bool GRPCVehicleHardware::waitForConnected(std::chrono::milliseconds waitTime) {
+ return mGrpcChannel->WaitForConnected(gpr_time_add(
+ gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_millis(waitTime.count(), GPR_TIMESPAN)));
+}
+
+void GRPCVehicleHardware::ValuePollingLoop() {
+ while (!mShuttingDownFlag.load()) {
+ ::grpc::ClientContext context;
+
+ bool rpc_stopped{false};
+ std::thread shuttingdown_watcher([this, &rpc_stopped, &context]() {
+ std::unique_lock<std::mutex> lck(mShutdownMutex);
+ mShutdownCV.wait(lck, [this, &rpc_stopped]() {
+ return rpc_stopped || mShuttingDownFlag.load();
+ });
+ context.TryCancel();
+ });
+
+ auto value_stream =
+ mGrpcStub->StartPropertyValuesStream(&context, ::google::protobuf::Empty());
+ LOG(INFO) << __func__ << ": GRPC Value Streaming Started";
+ proto::VehiclePropValues protoValues;
+ while (!mShuttingDownFlag.load() && value_stream->Read(&protoValues)) {
+ std::vector<aidlvhal::VehiclePropValue> values;
+ for (const auto protoValue : protoValues.values()) {
+ values.push_back(aidlvhal::VehiclePropValue());
+ proto_msg_converter::protoToAidl(protoValue, &values.back());
+ }
+ std::shared_lock lck(mCallbackMutex);
+ if (mOnPropChange) {
+ (*mOnPropChange)(values);
+ }
+ }
+
+ {
+ std::lock_guard lck(mShutdownMutex);
+ rpc_stopped = true;
+ }
+ mShutdownCV.notify_all();
+ shuttingdown_watcher.join();
+
+ auto grpc_status = value_stream->Finish();
+ // never reach here until connection lost
+ LOG(ERROR) << __func__ << ": GRPC Value Streaming Failed: " << grpc_status.error_message();
+
+ // try to reconnect
+ }
+}
+
+} // namespace android::hardware::automotive::vehicle::virtualization
diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
new file mode 100644
index 0000000..e740da7
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <IVehicleHardware.h>
+#include <VehicleHalTypes.h>
+#include <VehicleUtils.h>
+#include <android-base/result.h>
+
+#include "VehicleServer.grpc.pb.h"
+#include "VehicleServer.pb.h"
+
+#include <grpc++/grpc++.h>
+
+#include <atomic>
+#include <chrono>
+#include <condition_variable>
+#include <memory>
+#include <shared_mutex>
+#include <string>
+#include <thread>
+#include <vector>
+
+namespace android::hardware::automotive::vehicle::virtualization {
+
+namespace aidlvhal = ::aidl::android::hardware::automotive::vehicle;
+
+class GRPCVehicleHardware : public IVehicleHardware {
+ public:
+ explicit GRPCVehicleHardware(std::string service_addr);
+
+ ~GRPCVehicleHardware();
+
+ // Get all the property configs.
+ std::vector<aidlvhal::VehiclePropConfig> getAllPropertyConfigs() const override;
+
+ // Set property values asynchronously. Server could return before the property set requests
+ // are sent to vehicle bus or before property set confirmation is received. The callback is
+ // safe to be called after the function returns and is safe to be called in a different thread.
+ aidlvhal::StatusCode setValues(std::shared_ptr<const SetValuesCallback> callback,
+ const std::vector<aidlvhal::SetValueRequest>& requests) override;
+
+ // Get property values asynchronously. Server could return before the property values are ready.
+ // The callback is safe to be called after the function returns and is safe to be called in a
+ // different thread.
+ aidlvhal::StatusCode getValues(
+ std::shared_ptr<const GetValuesCallback> callback,
+ const std::vector<aidlvhal::GetValueRequest>& requests) const override;
+
+ // Dump debug information in the server.
+ DumpResult dump(const std::vector<std::string>& options) override;
+
+ // Check whether the system is healthy, return {@code StatusCode::OK} for healthy.
+ aidlvhal::StatusCode checkHealth() override;
+
+ // Register a callback that would be called when there is a property change event from vehicle.
+ void registerOnPropertyChangeEvent(
+ std::unique_ptr<const PropertyChangeCallback> callback) override;
+
+ // Register a callback that would be called when there is a property set error event from
+ // vehicle.
+ void registerOnPropertySetErrorEvent(
+ std::unique_ptr<const PropertySetErrorCallback> callback) override;
+
+ // Update the sample rate for the [propId, areaId] pair.
+ aidlvhal::StatusCode updateSampleRate(int32_t propId, int32_t areaId,
+ float sampleRate) override;
+
+ bool waitForConnected(std::chrono::milliseconds waitTime);
+
+ private:
+ void ValuePollingLoop();
+
+ std::string mServiceAddr;
+ std::shared_ptr<::grpc::Channel> mGrpcChannel;
+ std::unique_ptr<proto::VehicleServer::Stub> mGrpcStub;
+ std::thread mValuePollingThread;
+
+ std::shared_mutex mCallbackMutex;
+ std::unique_ptr<const PropertyChangeCallback> mOnPropChange;
+ std::unique_ptr<const PropertySetErrorCallback> mOnSetErr;
+
+ std::mutex mShutdownMutex;
+ std::condition_variable mShutdownCV;
+ std::atomic<bool> mShuttingDownFlag{false};
+};
+
+} // namespace android::hardware::automotive::vehicle::virtualization
diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.cpp b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.cpp
new file mode 100644
index 0000000..af3dd59
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.cpp
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2023 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 "GRPCVehicleProxyServer.h"
+
+#include "ProtoMessageConverter.h"
+
+#include <grpc++/grpc++.h>
+
+#include <android-base/logging.h>
+
+#include <algorithm>
+#include <condition_variable>
+#include <mutex>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::automotive::vehicle::virtualization {
+
+std::atomic<uint64_t> GrpcVehicleProxyServer::ConnectionDescriptor::connection_id_counter_{0};
+
+static std::shared_ptr<::grpc::ServerCredentials> getServerCredentials() {
+ // TODO(chenhaosjtuacm): get secured credentials here
+ return ::grpc::InsecureServerCredentials();
+}
+
+GrpcVehicleProxyServer::GrpcVehicleProxyServer(std::string serverAddr,
+ std::unique_ptr<IVehicleHardware>&& hardware)
+ : mServiceAddr(std::move(serverAddr)), mHardware(std::move(hardware)) {
+ mHardware->registerOnPropertyChangeEvent(
+ std::make_unique<const IVehicleHardware::PropertyChangeCallback>(
+ [this](std::vector<aidlvhal::VehiclePropValue> values) {
+ OnVehiclePropChange(values);
+ }));
+}
+
+::grpc::Status GrpcVehicleProxyServer::GetAllPropertyConfig(
+ ::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
+ ::grpc::ServerWriter<proto::VehiclePropConfig>* stream) {
+ for (const auto& config : mHardware->getAllPropertyConfigs()) {
+ proto::VehiclePropConfig protoConfig;
+ proto_msg_converter::aidlToProto(config, &protoConfig);
+ if (!stream->Write(protoConfig)) {
+ return ::grpc::Status(::grpc::StatusCode::ABORTED, "Connection lost.");
+ }
+ }
+ return ::grpc::Status::OK;
+}
+
+::grpc::Status GrpcVehicleProxyServer::SetValues(::grpc::ServerContext* context,
+ const proto::VehiclePropValueRequests* requests,
+ proto::SetValueResults* results) {
+ std::vector<aidlvhal::SetValueRequest> aidlRequests;
+ for (const auto& protoRequest : requests->requests()) {
+ auto& aidlRequest = aidlRequests.emplace_back();
+ aidlRequest.requestId = protoRequest.request_id();
+ proto_msg_converter::protoToAidl(protoRequest.value(), &aidlRequest.value);
+ }
+ auto waitMtx = std::make_shared<std::mutex>();
+ auto waitCV = std::make_shared<std::condition_variable>();
+ auto complete = std::make_shared<bool>(false);
+ auto tmpResults = std::make_shared<proto::SetValueResults>();
+ auto aidlStatus = mHardware->setValues(
+ std::make_shared<const IVehicleHardware::SetValuesCallback>(
+ [waitMtx, waitCV, complete,
+ tmpResults](std::vector<aidlvhal::SetValueResult> setValueResults) {
+ for (const auto& aidlResult : setValueResults) {
+ auto& protoResult = *tmpResults->add_results();
+ protoResult.set_request_id(aidlResult.requestId);
+ protoResult.set_status(
+ static_cast<proto::StatusCode>(aidlResult.status));
+ }
+ {
+ std::lock_guard lck(*waitMtx);
+ *complete = true;
+ }
+ waitCV->notify_all();
+ }),
+ aidlRequests);
+ if (aidlStatus != aidlvhal::StatusCode::OK) {
+ return ::grpc::Status(::grpc::StatusCode::INTERNAL,
+ "The underlying hardware fails to set values, VHAL status: " +
+ toString(aidlStatus));
+ }
+ std::unique_lock lck(*waitMtx);
+ bool success = waitCV->wait_for(lck, kHardwareOpTimeout, [complete] { return *complete; });
+ if (!success) {
+ return ::grpc::Status(::grpc::StatusCode::INTERNAL,
+ "The underlying hardware set values timeout.");
+ }
+ *results = std::move(*tmpResults);
+ return ::grpc::Status::OK;
+}
+
+::grpc::Status GrpcVehicleProxyServer::GetValues(::grpc::ServerContext* context,
+ const proto::VehiclePropValueRequests* requests,
+ proto::GetValueResults* results) {
+ std::vector<aidlvhal::GetValueRequest> aidlRequests;
+ for (const auto& protoRequest : requests->requests()) {
+ auto& aidlRequest = aidlRequests.emplace_back();
+ aidlRequest.requestId = protoRequest.request_id();
+ proto_msg_converter::protoToAidl(protoRequest.value(), &aidlRequest.prop);
+ }
+ auto waitMtx = std::make_shared<std::mutex>();
+ auto waitCV = std::make_shared<std::condition_variable>();
+ auto complete = std::make_shared<bool>(false);
+ auto tmpResults = std::make_shared<proto::GetValueResults>();
+ auto aidlStatus = mHardware->getValues(
+ std::make_shared<const IVehicleHardware::GetValuesCallback>(
+ [waitMtx, waitCV, complete,
+ tmpResults](std::vector<aidlvhal::GetValueResult> getValueResults) {
+ for (const auto& aidlResult : getValueResults) {
+ auto& protoResult = *tmpResults->add_results();
+ protoResult.set_request_id(aidlResult.requestId);
+ protoResult.set_status(
+ static_cast<proto::StatusCode>(aidlResult.status));
+ if (aidlResult.prop) {
+ auto* valuePtr = protoResult.mutable_value();
+ proto_msg_converter::aidlToProto(*aidlResult.prop, valuePtr);
+ }
+ }
+ {
+ std::lock_guard lck(*waitMtx);
+ *complete = true;
+ }
+ waitCV->notify_all();
+ }),
+ aidlRequests);
+ if (aidlStatus != aidlvhal::StatusCode::OK) {
+ return ::grpc::Status(::grpc::StatusCode::INTERNAL,
+ "The underlying hardware fails to get values, VHAL status: " +
+ toString(aidlStatus));
+ }
+ std::unique_lock lck(*waitMtx);
+ bool success = waitCV->wait_for(lck, kHardwareOpTimeout, [complete] { return *complete; });
+ if (!success) {
+ return ::grpc::Status(::grpc::StatusCode::INTERNAL,
+ "The underlying hardware get values timeout.");
+ }
+ *results = std::move(*tmpResults);
+ return ::grpc::Status::OK;
+}
+
+::grpc::Status GrpcVehicleProxyServer::UpdateSampleRate(
+ ::grpc::ServerContext* context, const proto::UpdateSampleRateRequest* request,
+ proto::VehicleHalCallStatus* status) {
+ const auto status_code = mHardware->updateSampleRate(request->prop(), request->area_id(),
+ request->sample_rate());
+ status->set_status_code(static_cast<proto::StatusCode>(status_code));
+ return ::grpc::Status::OK;
+}
+
+::grpc::Status GrpcVehicleProxyServer::CheckHealth(::grpc::ServerContext* context,
+ const ::google::protobuf::Empty*,
+ proto::VehicleHalCallStatus* status) {
+ status->set_status_code(static_cast<proto::StatusCode>(mHardware->checkHealth()));
+ return ::grpc::Status::OK;
+}
+
+::grpc::Status GrpcVehicleProxyServer::Dump(::grpc::ServerContext* context,
+ const proto::DumpOptions* options,
+ proto::DumpResult* result) {
+ std::vector<std::string> dumpOptionStrings(options->options().begin(),
+ options->options().end());
+ auto dumpResult = mHardware->dump(dumpOptionStrings);
+ result->set_caller_should_dump_state(dumpResult.callerShouldDumpState);
+ result->set_buffer(dumpResult.buffer);
+ return ::grpc::Status::OK;
+}
+
+::grpc::Status GrpcVehicleProxyServer::StartPropertyValuesStream(
+ ::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
+ ::grpc::ServerWriter<proto::VehiclePropValues>* stream) {
+ auto conn = std::make_shared<ConnectionDescriptor>(stream);
+ {
+ std::lock_guard lck(mConnectionMutex);
+ mValueStreamingConnections.push_back(conn);
+ }
+ conn->Wait();
+ LOG(ERROR) << __func__ << ": Stream lost, ID : " << conn->ID();
+ return ::grpc::Status(::grpc::StatusCode::ABORTED, "Connection lost.");
+}
+
+void GrpcVehicleProxyServer::OnVehiclePropChange(
+ const std::vector<aidlvhal::VehiclePropValue>& values) {
+ std::unordered_set<uint64_t> brokenConn;
+ proto::VehiclePropValues protoValues;
+ for (const auto& value : values) {
+ auto* protoValuePtr = protoValues.add_values();
+ proto_msg_converter::aidlToProto(value, protoValuePtr);
+ }
+ {
+ std::shared_lock read_lock(mConnectionMutex);
+ for (auto& connection : mValueStreamingConnections) {
+ auto writeOK = connection->Write(protoValues);
+ if (!writeOK) {
+ LOG(ERROR) << __func__
+ << ": Server Write failed, connection lost. ID: " << connection->ID();
+ brokenConn.insert(connection->ID());
+ }
+ }
+ }
+ if (brokenConn.empty()) {
+ return;
+ }
+ std::unique_lock write_lock(mConnectionMutex);
+ mValueStreamingConnections.erase(
+ std::remove_if(mValueStreamingConnections.begin(), mValueStreamingConnections.end(),
+ [&brokenConn](const auto& conn) {
+ return brokenConn.find(conn->ID()) != brokenConn.end();
+ }),
+ mValueStreamingConnections.end());
+}
+
+GrpcVehicleProxyServer& GrpcVehicleProxyServer::Start() {
+ if (mServer) {
+ LOG(WARNING) << __func__ << ": GrpcVehicleProxyServer has already started.";
+ return *this;
+ }
+ ::grpc::ServerBuilder builder;
+ builder.RegisterService(this);
+ builder.AddListeningPort(mServiceAddr, getServerCredentials());
+ mServer = builder.BuildAndStart();
+ CHECK(mServer) << __func__ << ": failed to create the GRPC server, "
+ << "please make sure the configuration and permissions are correct";
+ return *this;
+}
+
+GrpcVehicleProxyServer& GrpcVehicleProxyServer::Shutdown() {
+ std::shared_lock read_lock(mConnectionMutex);
+ for (auto& conn : mValueStreamingConnections) {
+ conn->Shutdown();
+ }
+ if (mServer) {
+ mServer->Shutdown();
+ }
+ return *this;
+}
+
+void GrpcVehicleProxyServer::Wait() {
+ if (mServer) {
+ mServer->Wait();
+ }
+ mServer.reset();
+}
+
+GrpcVehicleProxyServer::ConnectionDescriptor::~ConnectionDescriptor() {
+ Shutdown();
+}
+
+bool GrpcVehicleProxyServer::ConnectionDescriptor::Write(const proto::VehiclePropValues& values) {
+ if (!mStream) {
+ LOG(ERROR) << __func__ << ": Empty stream. ID: " << ID();
+ Shutdown();
+ return false;
+ }
+ {
+ std::lock_guard lck(*mMtx);
+ if (!mShutdownFlag && mStream->Write(values)) {
+ return true;
+ } else {
+ LOG(ERROR) << __func__ << ": Server Write failed, connection lost. ID: " << ID();
+ }
+ }
+ Shutdown();
+ return false;
+}
+
+void GrpcVehicleProxyServer::ConnectionDescriptor::Wait() {
+ std::unique_lock lck(*mMtx);
+ mCV->wait(lck, [this] { return mShutdownFlag; });
+}
+
+void GrpcVehicleProxyServer::ConnectionDescriptor::Shutdown() {
+ {
+ std::lock_guard lck(*mMtx);
+ mShutdownFlag = true;
+ }
+ mCV->notify_all();
+}
+
+} // namespace android::hardware::automotive::vehicle::virtualization
diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.h b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.h
new file mode 100644
index 0000000..3596354
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include "IVehicleHardware.h"
+
+#include "VehicleServer.grpc.pb.h"
+#include "VehicleServer.pb.h"
+
+#include <grpc++/grpc++.h>
+
+#include <atomic>
+#include <chrono>
+#include <cstdint>
+#include <functional>
+#include <memory>
+#include <shared_mutex>
+#include <string>
+#include <utility>
+
+namespace android::hardware::automotive::vehicle::virtualization {
+
+namespace aidlvhal = ::aidl::android::hardware::automotive::vehicle;
+
+// Connect other GRPC vehicle hardware(s) to the underlying vehicle hardware.
+class GrpcVehicleProxyServer : public proto::VehicleServer::Service {
+ public:
+ GrpcVehicleProxyServer(std::string serverAddr, std::unique_ptr<IVehicleHardware>&& hardware);
+
+ ::grpc::Status GetAllPropertyConfig(
+ ::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
+ ::grpc::ServerWriter<proto::VehiclePropConfig>* stream) override;
+
+ ::grpc::Status SetValues(::grpc::ServerContext* context,
+ const proto::VehiclePropValueRequests* requests,
+ proto::SetValueResults* results) override;
+
+ ::grpc::Status GetValues(::grpc::ServerContext* context,
+ const proto::VehiclePropValueRequests* requests,
+ proto::GetValueResults* results) override;
+
+ ::grpc::Status UpdateSampleRate(::grpc::ServerContext* context,
+ const proto::UpdateSampleRateRequest* request,
+ proto::VehicleHalCallStatus* status) override;
+
+ ::grpc::Status CheckHealth(::grpc::ServerContext* context, const ::google::protobuf::Empty*,
+ proto::VehicleHalCallStatus* status) override;
+
+ ::grpc::Status Dump(::grpc::ServerContext* context, const proto::DumpOptions* options,
+ proto::DumpResult* result) override;
+
+ ::grpc::Status StartPropertyValuesStream(
+ ::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
+ ::grpc::ServerWriter<proto::VehiclePropValues>* stream) override;
+
+ GrpcVehicleProxyServer& Start();
+
+ GrpcVehicleProxyServer& Shutdown();
+
+ void Wait();
+
+ private:
+ void OnVehiclePropChange(const std::vector<aidlvhal::VehiclePropValue>& values);
+
+ // We keep long-lasting connection for streaming the prop values.
+ struct ConnectionDescriptor {
+ explicit ConnectionDescriptor(::grpc::ServerWriter<proto::VehiclePropValues>* stream)
+ : mStream(stream),
+ mConnectionID(connection_id_counter_.fetch_add(1) + 1),
+ mMtx(std::make_unique<std::mutex>()),
+ mCV(std::make_unique<std::condition_variable>()) {}
+
+ ConnectionDescriptor(const ConnectionDescriptor&) = delete;
+ ConnectionDescriptor(ConnectionDescriptor&& cd) = default;
+ ConnectionDescriptor& operator=(const ConnectionDescriptor&) = delete;
+ ConnectionDescriptor& operator=(ConnectionDescriptor&& cd) = default;
+
+ ~ConnectionDescriptor();
+
+ uint64_t ID() const { return mConnectionID; }
+
+ bool Write(const proto::VehiclePropValues& values);
+
+ void Wait();
+
+ void Shutdown();
+
+ private:
+ ::grpc::ServerWriter<proto::VehiclePropValues>* mStream;
+ uint64_t mConnectionID{0};
+ std::unique_ptr<std::mutex> mMtx;
+ std::unique_ptr<std::condition_variable> mCV;
+ bool mShutdownFlag{false};
+
+ static std::atomic<uint64_t> connection_id_counter_;
+ };
+
+ std::string mServiceAddr;
+ std::unique_ptr<::grpc::Server> mServer{nullptr};
+ std::unique_ptr<IVehicleHardware> mHardware;
+
+ std::shared_mutex mConnectionMutex;
+ std::vector<std::shared_ptr<ConnectionDescriptor>> mValueStreamingConnections;
+
+ static constexpr auto kHardwareOpTimeout = std::chrono::seconds(1);
+};
+
+} // namespace android::hardware::automotive::vehicle::virtualization
diff --git a/automotive/vehicle/aidl/impl/grpc/OWNERS b/automotive/vehicle/aidl/impl/grpc/OWNERS
new file mode 100644
index 0000000..7a96f23
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/grpc/OWNERS
@@ -0,0 +1,3 @@
+shanyu@google.com
+chenhaosjtuacm@google.com
+egranata@google.com
diff --git a/automotive/vehicle/aidl/impl/grpc/proto/VehicleServer.proto b/automotive/vehicle/aidl/impl/grpc/proto/VehicleServer.proto
new file mode 100644
index 0000000..22b11d8
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/grpc/proto/VehicleServer.proto
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+syntax = "proto3";
+
+package android.hardware.automotive.vehicle.proto;
+
+import "android/hardware/automotive/vehicle/DumpOptions.proto";
+import "android/hardware/automotive/vehicle/DumpResult.proto";
+import "android/hardware/automotive/vehicle/StatusCode.proto";
+import "android/hardware/automotive/vehicle/VehiclePropConfig.proto";
+import "android/hardware/automotive/vehicle/VehiclePropValue.proto";
+import "android/hardware/automotive/vehicle/VehiclePropValueRequest.proto";
+import "google/protobuf/empty.proto";
+
+service VehicleServer {
+ rpc GetAllPropertyConfig(google.protobuf.Empty) returns (stream VehiclePropConfig) {}
+
+ rpc SetValues(VehiclePropValueRequests) returns (SetValueResults) {}
+
+ rpc GetValues(VehiclePropValueRequests) returns (GetValueResults) {}
+
+ rpc UpdateSampleRate(UpdateSampleRateRequest) returns (VehicleHalCallStatus) {}
+
+ rpc CheckHealth(google.protobuf.Empty) returns (VehicleHalCallStatus) {}
+
+ rpc Dump(DumpOptions) returns (DumpResult) {}
+
+ rpc StartPropertyValuesStream(google.protobuf.Empty) returns (stream VehiclePropValues) {}
+}
diff --git a/automotive/vehicle/aidl/impl/grpc/test/Android.bp b/automotive/vehicle/aidl/impl/grpc/test/Android.bp
new file mode 100644
index 0000000..e53826f
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/grpc/test/Android.bp
@@ -0,0 +1,74 @@
+// Copyright (C) 2023 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.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+ name: "GRPCVehicleHardwareUnitTest",
+ vendor: true,
+ srcs: ["GRPCVehicleHardwareUnitTest.cpp"],
+ whole_static_libs: [
+ "android.hardware.automotive.vehicle@default-grpc-hardware-lib",
+ ],
+ header_libs: [
+ "IVehicleHardware",
+ ],
+ static_libs: [
+ "libgtest",
+ "libgmock",
+ ],
+ shared_libs: [
+ "libgrpc++",
+ "libprotobuf-cpp-full",
+ ],
+ // libgrpc++.so is installed as root, require root to access it.
+ require_root: true,
+ defaults: [
+ "VehicleHalDefaults",
+ ],
+ cflags: [
+ "-Wno-unused-parameter",
+ ],
+ test_suites: ["device-tests"],
+}
+
+cc_test {
+ name: "GRPCVehicleProxyServerUnitTest",
+ vendor: true,
+ srcs: ["GRPCVehicleProxyServerUnitTest.cpp"],
+ header_libs: [
+ "IVehicleHardware",
+ ],
+ static_libs: [
+ "android.hardware.automotive.vehicle@default-grpc-hardware-lib",
+ "android.hardware.automotive.vehicle@default-grpc-server-lib",
+ "libgtest",
+ "libgmock",
+ ],
+ shared_libs: [
+ "libgrpc++",
+ "libprotobuf-cpp-full",
+ ],
+ // libgrpc++.so is installed as root, require root to access it.
+ require_root: true,
+ defaults: [
+ "VehicleHalDefaults",
+ ],
+ cflags: [
+ "-Wno-unused-parameter",
+ ],
+ test_suites: ["device-tests"],
+}
diff --git a/automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleHardwareUnitTest.cpp b/automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleHardwareUnitTest.cpp
new file mode 100644
index 0000000..f578021
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleHardwareUnitTest.cpp
@@ -0,0 +1,94 @@
+// Copyright (C) 2023 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 "GRPCVehicleHardware.h"
+#include "VehicleServer.grpc.pb.h"
+#include "VehicleServer.pb.h"
+
+#include <gmock/gmock.h>
+#include <grpc++/grpc++.h>
+#include <gtest/gtest.h>
+
+#include <chrono>
+#include <memory>
+#include <string>
+
+namespace android::hardware::automotive::vehicle::virtualization {
+
+const std::string kFakeServerAddr = "0.0.0.0:54321";
+
+class FakeVehicleServer : public proto::VehicleServer::Service {
+ public:
+ ::grpc::Status StartPropertyValuesStream(
+ ::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
+ ::grpc::ServerWriter<proto::VehiclePropValues>* stream) override {
+ stream->Write(proto::VehiclePropValues());
+ // A fake disconnection.
+ return ::grpc::Status(::grpc::StatusCode::ABORTED, "Connection lost.");
+ }
+
+ // Functions that we do not care.
+ ::grpc::Status GetAllPropertyConfig(
+ ::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
+ ::grpc::ServerWriter<proto::VehiclePropConfig>* stream) override {
+ return ::grpc::Status::OK;
+ }
+
+ ::grpc::Status SetValues(::grpc::ServerContext* context,
+ const proto::VehiclePropValueRequests* requests,
+ proto::SetValueResults* results) override {
+ return ::grpc::Status::OK;
+ }
+
+ ::grpc::Status GetValues(::grpc::ServerContext* context,
+ const proto::VehiclePropValueRequests* requests,
+ proto::GetValueResults* results) override {
+ return ::grpc::Status::OK;
+ }
+};
+
+TEST(GRPCVehicleHardwareUnitTest, Reconnect) {
+ auto receivedUpdate = std::make_shared<std::atomic<int>>(0);
+ auto vehicleHardware = std::make_unique<GRPCVehicleHardware>(kFakeServerAddr);
+ vehicleHardware->registerOnPropertyChangeEvent(
+ std::make_unique<const IVehicleHardware::PropertyChangeCallback>(
+ [receivedUpdate](const auto&) { receivedUpdate->fetch_add(1); }));
+
+ constexpr size_t kServerRestartTimes = 5;
+ for (size_t serverStart = 0; serverStart < kServerRestartTimes; ++serverStart) {
+ EXPECT_EQ(receivedUpdate->load(), 0);
+ auto fakeServer = std::make_unique<FakeVehicleServer>();
+ ::grpc::ServerBuilder builder;
+ builder.RegisterService(fakeServer.get());
+ builder.AddListeningPort(kFakeServerAddr, ::grpc::InsecureServerCredentials());
+ auto grpcServer = builder.BuildAndStart();
+
+ // Wait until the vehicle hardware received the second update (after one fake
+ // disconnection).
+ constexpr auto kMaxWaitTime = std::chrono::seconds(5);
+ auto startTime = std::chrono::steady_clock::now();
+ while (receivedUpdate->load() <= 1 &&
+ std::chrono::steady_clock::now() - startTime < kMaxWaitTime)
+ ;
+
+ grpcServer->Shutdown();
+ grpcServer->Wait();
+ EXPECT_GT(receivedUpdate->load(), 1);
+
+ // Reset for the next round.
+ receivedUpdate->store(0);
+ }
+}
+
+} // namespace android::hardware::automotive::vehicle::virtualization
diff --git a/automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleProxyServerUnitTest.cpp b/automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleProxyServerUnitTest.cpp
new file mode 100644
index 0000000..49e6fc9
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleProxyServerUnitTest.cpp
@@ -0,0 +1,147 @@
+// Copyright (C) 2023 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 "GRPCVehicleHardware.h"
+#include "GRPCVehicleProxyServer.h"
+#include "IVehicleHardware.h"
+#include "VehicleServer.grpc.pb.h"
+#include "VehicleServer.pb.h"
+
+#include <gmock/gmock.h>
+#include <grpc++/grpc++.h>
+#include <gtest/gtest.h>
+
+#include <chrono>
+#include <memory>
+#include <string>
+#include <thread>
+#include <utility>
+
+namespace android::hardware::automotive::vehicle::virtualization {
+
+const std::string kFakeServerAddr = "0.0.0.0:54321";
+
+class VehicleHardwareForTest : public IVehicleHardware {
+ public:
+ void registerOnPropertyChangeEvent(
+ std::unique_ptr<const PropertyChangeCallback> callback) override {
+ mOnProp = std::move(callback);
+ }
+
+ void onPropertyEvent(
+ std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue> values) {
+ if (mOnProp) {
+ (*mOnProp)(std::move(values));
+ }
+ }
+
+ // Functions that we do not care.
+ std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
+ getAllPropertyConfigs() const override {
+ return {};
+ }
+
+ aidl::android::hardware::automotive::vehicle::StatusCode setValues(
+ std::shared_ptr<const SetValuesCallback> callback,
+ const std::vector<aidl::android::hardware::automotive::vehicle::SetValueRequest>&
+ requests) override {
+ return aidl::android::hardware::automotive::vehicle::StatusCode::OK;
+ }
+
+ aidl::android::hardware::automotive::vehicle::StatusCode getValues(
+ std::shared_ptr<const GetValuesCallback> callback,
+ const std::vector<aidl::android::hardware::automotive::vehicle::GetValueRequest>&
+ requests) const override {
+ return aidl::android::hardware::automotive::vehicle::StatusCode::OK;
+ }
+
+ DumpResult dump(const std::vector<std::string>& options) override { return {}; }
+
+ aidl::android::hardware::automotive::vehicle::StatusCode checkHealth() override {
+ return aidl::android::hardware::automotive::vehicle::StatusCode::OK;
+ }
+
+ void registerOnPropertySetErrorEvent(
+ std::unique_ptr<const PropertySetErrorCallback> callback) override {}
+
+ private:
+ std::unique_ptr<const PropertyChangeCallback> mOnProp;
+};
+
+TEST(GRPCVehicleProxyServerUnitTest, ClientConnectDisconnect) {
+ auto testHardware = std::make_unique<VehicleHardwareForTest>();
+ // HACK: manipulate the underlying hardware via raw pointer for testing.
+ auto* testHardwareRaw = testHardware.get();
+ auto vehicleServer =
+ std::make_unique<GrpcVehicleProxyServer>(kFakeServerAddr, std::move(testHardware));
+ vehicleServer->Start();
+
+ constexpr auto kWaitForConnectionMaxTime = std::chrono::seconds(5);
+ constexpr auto kWaitForStreamStartTime = std::chrono::seconds(1);
+ constexpr auto kWaitForUpdateDeliveryTime = std::chrono::milliseconds(100);
+
+ auto updateReceived1 = std::make_shared<bool>(false);
+ auto vehicleHardware1 = std::make_unique<GRPCVehicleHardware>(kFakeServerAddr);
+ vehicleHardware1->registerOnPropertyChangeEvent(
+ std::make_unique<const IVehicleHardware::PropertyChangeCallback>(
+ [updateReceived1](const auto&) { *updateReceived1 = true; }));
+ EXPECT_TRUE(vehicleHardware1->waitForConnected(kWaitForConnectionMaxTime));
+ std::this_thread::sleep_for(kWaitForStreamStartTime);
+
+ // Client hardware 1 received update from the server.
+ EXPECT_FALSE(*updateReceived1);
+ testHardwareRaw->onPropertyEvent({});
+ // Wait for the update delivery.
+ std::this_thread::sleep_for(kWaitForUpdateDeliveryTime);
+ EXPECT_TRUE(*updateReceived1);
+
+ // Reset.
+ *updateReceived1 = false;
+
+ auto updateReceived2 = std::make_shared<bool>(false);
+ auto vehicleHardware2 = std::make_unique<GRPCVehicleHardware>(kFakeServerAddr);
+ vehicleHardware2->registerOnPropertyChangeEvent(
+ std::make_unique<const IVehicleHardware::PropertyChangeCallback>(
+ [updateReceived2](const auto&) { *updateReceived2 = true; }));
+ EXPECT_TRUE(vehicleHardware2->waitForConnected(kWaitForConnectionMaxTime));
+ std::this_thread::sleep_for(kWaitForStreamStartTime);
+
+ // Both client hardware 1 and 2 received update from the server.
+ EXPECT_FALSE(*updateReceived1);
+ EXPECT_FALSE(*updateReceived2);
+ testHardwareRaw->onPropertyEvent({});
+ // Wait for the update delivery.
+ std::this_thread::sleep_for(kWaitForUpdateDeliveryTime);
+ EXPECT_TRUE(*updateReceived1);
+ EXPECT_TRUE(*updateReceived2);
+
+ // Reset.
+ *updateReceived1 = false;
+ *updateReceived2 = false;
+
+ vehicleHardware1.reset();
+
+ // Client 1 exited, only client hardware 2 received update from the server.
+ EXPECT_FALSE(*updateReceived1);
+ EXPECT_FALSE(*updateReceived2);
+ testHardwareRaw->onPropertyEvent({});
+ // Wait for the update delivery.
+ std::this_thread::sleep_for(kWaitForUpdateDeliveryTime);
+ EXPECT_FALSE(*updateReceived1);
+ EXPECT_TRUE(*updateReceived2);
+
+ vehicleServer->Shutdown().Wait();
+}
+
+} // namespace android::hardware::automotive::vehicle::virtualization
diff --git a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/Android.bp b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/Android.bp
index 7670c25..2b4059c 100644
--- a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/Android.bp
+++ b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/Android.bp
@@ -47,13 +47,19 @@
],
vendor: true,
defaults: ["VehicleHalDefaults"],
- shared_libs: ["libprotobuf-cpp-full"],
+ shared_libs: [
+ "libprotobuf-cpp-full",
+ "libjsoncpp",
+ ],
static_libs: [
+ "VehicleHalJsonConfigLoaderEnableTestProperties",
"VehicleHalProtoMessageConverter",
"VehicleHalProtos",
"VehicleHalUtils",
"libgtest",
],
- header_libs: ["VehicleHalDefaultConfig"],
+ data: [
+ ":VehicleHalDefaultProperties_JSON",
+ ],
test_suites: ["device-tests"],
}
diff --git a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp
index c742db5..308be46 100644
--- a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp
+++ b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp
@@ -16,9 +16,11 @@
#include <vector>
-#include <DefaultConfig.h>
+#include <JsonConfigLoader.h>
#include <ProtoMessageConverter.h>
#include <VehicleHalTypes.h>
+
+#include <android-base/file.h>
#include <android-base/format.h>
#include <android/hardware/automotive/vehicle/VehiclePropConfig.pb.h>
#include <android/hardware/automotive/vehicle/VehiclePropValue.pb.h>
@@ -35,23 +37,39 @@
namespace proto = ::android::hardware::automotive::vehicle::proto;
namespace aidl_vehicle = ::aidl::android::hardware::automotive::vehicle;
+constexpr char DEFAULT_PROPERTIES_CONFIG[] = "DefaultProperties.json";
+
+inline std::string getConfigPath(const std::string& name) {
+ return android::base::GetExecutableDirectory() + "/" + name;
+}
+
std::vector<aidl_vehicle::VehiclePropConfig> prepareTestConfigs() {
+ JsonConfigLoader loader;
+ auto result = loader.loadPropConfig(getConfigPath(DEFAULT_PROPERTIES_CONFIG));
+ if (!result.ok()) {
+ return {};
+ }
std::vector<aidl_vehicle::VehiclePropConfig> configs;
- for (auto& property : defaultconfig::getDefaultConfigs()) {
- configs.push_back(property.config);
+ for (auto& [_, configDeclaration] : result.value()) {
+ configs.push_back(configDeclaration.config);
}
return configs;
}
std::vector<aidl_vehicle::VehiclePropValue> prepareTestValues() {
+ JsonConfigLoader loader;
+ auto result = loader.loadPropConfig(getConfigPath(DEFAULT_PROPERTIES_CONFIG));
+ if (!result.ok()) {
+ return {};
+ }
std::vector<aidl_vehicle::VehiclePropValue> values;
int64_t timestamp = 1;
- for (auto& property : defaultconfig::getDefaultConfigs()) {
+ for (auto& [_, configDeclaration] : result.value()) {
values.push_back({
.timestamp = timestamp,
.areaId = 123,
- .prop = property.config.prop,
- .value = property.initialValue,
+ .prop = configDeclaration.config.prop,
+ .value = configDeclaration.initialValue,
.status = aidl_vehicle::VehiclePropertyStatus::ERROR,
});
}
diff --git a/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h b/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h
index 759db41..e53947e 100644
--- a/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h
@@ -35,6 +35,8 @@
bool callerShouldDumpState;
// The dumped information for the caller to print.
std::string buffer;
+ // To pass if DefaultVehicleHal should refresh the property configs
+ bool refreshPropertyConfigs = false;
};
// A structure to represent a set value error event reported from vehicle.
@@ -116,11 +118,12 @@
virtual aidl::android::hardware::automotive::vehicle::StatusCode checkHealth() = 0;
// Register a callback that would be called when there is a property change event from vehicle.
+ // Must only be called once during initialization.
virtual void registerOnPropertyChangeEvent(
std::unique_ptr<const PropertyChangeCallback> callback) = 0;
// Register a callback that would be called when there is a property set error event from
- // vehicle.
+ // vehicle. Must only be called once during initialization.
virtual void registerOnPropertySetErrorEvent(
std::unique_ptr<const PropertySetErrorCallback> callback) = 0;
};
diff --git a/automotive/vehicle/aidl/impl/proto/Android.bp b/automotive/vehicle/aidl/impl/proto/Android.bp
index 709307d..56fad7e 100644
--- a/automotive/vehicle/aidl/impl/proto/Android.bp
+++ b/automotive/vehicle/aidl/impl/proto/Android.bp
@@ -40,6 +40,7 @@
":VehicleHalProtoFiles",
],
out: [
+ "android/hardware/automotive/vehicle/DumpOptions.pb.h",
"android/hardware/automotive/vehicle/DumpResult.pb.h",
"android/hardware/automotive/vehicle/StatusCode.pb.h",
"android/hardware/automotive/vehicle/VehicleAreaConfig.pb.h",
@@ -63,6 +64,7 @@
":VehicleHalProtoFiles",
],
out: [
+ "android/hardware/automotive/vehicle/DumpOptions.pb.cc",
"android/hardware/automotive/vehicle/DumpResult.pb.cc",
"android/hardware/automotive/vehicle/StatusCode.pb.cc",
"android/hardware/automotive/vehicle/VehicleAreaConfig.pb.cc",
diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/DumpOptions.proto b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/DumpOptions.proto
new file mode 100644
index 0000000..4bed927
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/DumpOptions.proto
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+syntax = "proto3";
+
+package android.hardware.automotive.vehicle.proto;
+
+message DumpOptions {
+ repeated string options = 1;
+}
diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/StatusCode.proto b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/StatusCode.proto
index 97cb0f8..63d7933 100644
--- a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/StatusCode.proto
+++ b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/StatusCode.proto
@@ -39,3 +39,7 @@
/* Something unexpected has happened in Vehicle HAL */
INTERNAL_ERROR = 5;
};
+
+message VehicleHalCallStatus {
+ StatusCode status_code = 1;
+}
diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropValue.proto b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropValue.proto
index 80c73cb..dda9ff5 100644
--- a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropValue.proto
+++ b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropValue.proto
@@ -52,3 +52,7 @@
/* This is used for properties of type VehiclePropertyType#STRING */
string string_value = 9;
};
+
+message VehiclePropValues {
+ repeated VehiclePropValue values = 1;
+}
diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropValueRequest.proto b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropValueRequest.proto
index b16daa8..c347a80 100644
--- a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropValueRequest.proto
+++ b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/VehiclePropValueRequest.proto
@@ -18,9 +18,44 @@
package android.hardware.automotive.vehicle.proto;
+import "android/hardware/automotive/vehicle/StatusCode.proto";
import "android/hardware/automotive/vehicle/VehiclePropValue.proto";
message VehiclePropValueRequest {
- int32 request_id = 1;
+ int64 request_id = 1;
VehiclePropValue value = 2;
};
+
+message UpdateSampleRateRequest {
+ /* Property identifier */
+ int32 prop = 1;
+
+ /* Area type(s) for non-global property it must be one of the value from
+ * VehicleArea* enums or 0 for global properties. */
+ int32 area_id = 2;
+
+ float sample_rate = 3;
+};
+
+message SetValueResult {
+ int64 request_id = 1;
+ StatusCode status = 2;
+};
+
+message GetValueResult {
+ int64 request_id = 1;
+ StatusCode status = 2;
+ VehiclePropValue value = 3;
+};
+
+message VehiclePropValueRequests {
+ repeated VehiclePropValueRequest requests = 1;
+};
+
+message SetValueResults {
+ repeated SetValueResult results = 1;
+};
+
+message GetValueResults {
+ repeated GetValueResult results = 1;
+};
diff --git a/automotive/vehicle/aidl/impl/utils/README.md b/automotive/vehicle/aidl/impl/utils/README.md
new file mode 100644
index 0000000..87bb7e3
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/README.md
@@ -0,0 +1,62 @@
+# Utility classes for VHAL implementation
+---
+
+This directory stores utility classes for VHAL implementation. Vendor
+implementation could use utility classes from `common` folder in their
+VHAL implementation.
+
+## common
+
+Defines common utility libraries.
+
+### ConcurrentQueue
+
+Provides a thread-safe concurrent queue object. Useful for adding object to
+a queue in one thread (usually binder thread) and handle the objects in a
+separate handler thread.
+
+### ParcelableUtils
+
+Provides functions to convert between a regular parcelable and a
+`LargeParcelabe`.
+
+A `LargeParcelable` is a parcelable that marshals the payload
+into a shared memory file if the payload is too large to pass across binder.
+It is used to pass large data across binder. Before sending the data, VHAL
+impl should convert a regular parcelabe to a `LargeParcelable`. After receving
+data, VHAL impl should convert a `LargeParcelable` back to regular parcelabe.
+
+### PendingRequestPool
+
+Defines A class for managing pending requests and automatically call timeout
+callback if the request timed-out.
+
+### PropertyUtils
+
+Defines some useful constants.
+
+### RecurrentTimer
+
+Defines a thread-safe recurrent timer that can call a function periodically.
+
+### VehicleHalTypes
+
+Provides a header file that includes many commonly used header files. Useful
+when you are using multiple types defined in VHAL interface.
+
+### VehicleObjectPool
+
+Defines a reusable in-memory pool for `VehiclePropValue`.
+
+### VehiclePropertyStore
+
+Defines an in-memory map for storing vehicle properties. Allows easier insert,
+delete and lookup.
+
+### VehicleUtils
+
+Defines many useful utility functions.
+
+## test
+
+Defines utility libraries for test only.
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/PendingRequestPool.h b/automotive/vehicle/aidl/impl/utils/common/include/PendingRequestPool.h
index 3f8db93..28cf08e 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/PendingRequestPool.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/PendingRequestPool.h
@@ -21,7 +21,6 @@
#include <android-base/result.h>
#include <android-base/thread_annotations.h>
-#include <atomic>
#include <list>
#include <mutex>
#include <thread>
@@ -85,7 +84,7 @@
std::unordered_map<const void*, std::list<PendingRequest>> mPendingRequestsByClient
GUARDED_BY(mLock);
std::thread mThread;
- std::atomic<bool> mThreadStop = false;
+ bool mThreadStop = false;
std::condition_variable mCv;
std::mutex mCvLock;
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h b/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h
index 2743578..7275ba3 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h
@@ -28,6 +28,7 @@
namespace propertyutils_impl {
// These names are not part of the API since we only expose ints.
+using ::aidl::android::hardware::automotive::vehicle::EvStoppingMode;
using ::aidl::android::hardware::automotive::vehicle::PortLocationType;
using ::aidl::android::hardware::automotive::vehicle::VehicleArea;
using ::aidl::android::hardware::automotive::vehicle::VehicleAreaDoor;
@@ -96,7 +97,13 @@
constexpr int CHARGE_PORT_FRONT_LEFT = toInt(propertyutils_impl::PortLocationType::FRONT_LEFT);
constexpr int CHARGE_PORT_REAR_LEFT = toInt(propertyutils_impl::PortLocationType::REAR_LEFT);
constexpr int LIGHT_STATE_ON = toInt(propertyutils_impl::VehicleLightState::ON);
+constexpr int LIGHT_STATE_OFF = toInt(propertyutils_impl::VehicleLightState::OFF);
+constexpr int LIGHT_SWITCH_OFF = toInt(propertyutils_impl::VehicleLightSwitch::OFF);
+constexpr int LIGHT_SWITCH_ON = toInt(propertyutils_impl::VehicleLightSwitch::ON);
constexpr int LIGHT_SWITCH_AUTO = toInt(propertyutils_impl::VehicleLightSwitch::AUTOMATIC);
+constexpr int EV_STOPPING_MODE_CREEP = toInt(propertyutils_impl::EvStoppingMode::CREEP);
+constexpr int EV_STOPPING_MODE_ROLL = toInt(propertyutils_impl::EvStoppingMode::ROLL);
+constexpr int EV_STOPPING_MODE_HOLD = toInt(propertyutils_impl::EvStoppingMode::HOLD);
constexpr int WHEEL_FRONT_LEFT = toInt(propertyutils_impl::VehicleAreaWheel::LEFT_FRONT);
constexpr int WHEEL_FRONT_RIGHT = toInt(propertyutils_impl::VehicleAreaWheel::RIGHT_FRONT);
constexpr int WHEEL_REAR_LEFT = toInt(propertyutils_impl::VehicleAreaWheel::LEFT_REAR);
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h
index 8bc3c20..e6d657d 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h
@@ -17,15 +17,32 @@
#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/AutomaticEmergencyBrakingState.h>
+#include <aidl/android/hardware/automotive/vehicle/BlindSpotWarningState.h>
+#include <aidl/android/hardware/automotive/vehicle/CruiseControlCommand.h>
+#include <aidl/android/hardware/automotive/vehicle/CruiseControlState.h>
+#include <aidl/android/hardware/automotive/vehicle/CruiseControlType.h>
#include <aidl/android/hardware/automotive/vehicle/DiagnosticFloatSensorIndex.h>
#include <aidl/android/hardware/automotive/vehicle/DiagnosticIntegerSensorIndex.h>
+#include <aidl/android/hardware/automotive/vehicle/EmergencyLaneKeepAssistState.h>
+#include <aidl/android/hardware/automotive/vehicle/ErrorState.h>
#include <aidl/android/hardware/automotive/vehicle/EvConnectorType.h>
+#include <aidl/android/hardware/automotive/vehicle/EvStoppingMode.h>
#include <aidl/android/hardware/automotive/vehicle/EvsServiceState.h>
#include <aidl/android/hardware/automotive/vehicle/EvsServiceType.h>
+#include <aidl/android/hardware/automotive/vehicle/ForwardCollisionWarningState.h>
#include <aidl/android/hardware/automotive/vehicle/FuelType.h>
#include <aidl/android/hardware/automotive/vehicle/GetValueRequest.h>
#include <aidl/android/hardware/automotive/vehicle/GetValueResult.h>
#include <aidl/android/hardware/automotive/vehicle/GetValueResults.h>
+#include <aidl/android/hardware/automotive/vehicle/GsrComplianceRequirementType.h>
+#include <aidl/android/hardware/automotive/vehicle/HandsOnDetectionDriverState.h>
+#include <aidl/android/hardware/automotive/vehicle/HandsOnDetectionWarning.h>
+#include <aidl/android/hardware/automotive/vehicle/LaneCenteringAssistCommand.h>
+#include <aidl/android/hardware/automotive/vehicle/LaneCenteringAssistState.h>
+#include <aidl/android/hardware/automotive/vehicle/LaneDepartureWarningState.h>
+#include <aidl/android/hardware/automotive/vehicle/LaneKeepAssistState.h>
+#include <aidl/android/hardware/automotive/vehicle/LocationCharacterization.h>
#include <aidl/android/hardware/automotive/vehicle/Obd2CommonIgnitionMonitors.h>
#include <aidl/android/hardware/automotive/vehicle/Obd2FuelSystemStatus.h>
#include <aidl/android/hardware/automotive/vehicle/Obd2FuelType.h>
@@ -66,5 +83,7 @@
#include <aidl/android/hardware/automotive/vehicle/VehicleTurnSignal.h>
#include <aidl/android/hardware/automotive/vehicle/VehicleUnit.h>
#include <aidl/android/hardware/automotive/vehicle/VehicleVendorPermission.h>
+#include <aidl/android/hardware/automotive/vehicle/WindshieldWipersState.h>
+#include <aidl/android/hardware/automotive/vehicle/WindshieldWipersSwitch.h>
#endif // android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleHalTypes_H_
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/PendingRequestPool.cpp b/automotive/vehicle/aidl/impl/utils/common/src/PendingRequestPool.cpp
index 0196edd..ab50499 100644
--- a/automotive/vehicle/aidl/impl/utils/common/src/PendingRequestPool.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/src/PendingRequestPool.cpp
@@ -39,20 +39,27 @@
} // namespace
-PendingRequestPool::PendingRequestPool(int64_t timeoutInNano)
- : mTimeoutInNano(timeoutInNano), mThread([this] {
- // [this] must be alive within this thread because destructor would wait for this thread
- // to exit.
- int64_t sleepTime = std::min(mTimeoutInNano, static_cast<int64_t>(CHECK_TIME_IN_NANO));
- std::unique_lock<std::mutex> lk(mCvLock);
- while (!mCv.wait_for(lk, std::chrono::nanoseconds(sleepTime),
- [this] { return mThreadStop.load(); })) {
- checkTimeout();
- }
- }) {}
+PendingRequestPool::PendingRequestPool(int64_t timeoutInNano) : mTimeoutInNano(timeoutInNano) {
+ mThread = std::thread([this] {
+ // [this] must be alive within this thread because destructor would wait for this thread
+ // to exit.
+ int64_t sleepTime = std::min(mTimeoutInNano, static_cast<int64_t>(CHECK_TIME_IN_NANO));
+ std::unique_lock<std::mutex> lk(mCvLock);
+ while (!mCv.wait_for(lk, std::chrono::nanoseconds(sleepTime),
+ [this] { return mThreadStop; })) {
+ checkTimeout();
+ }
+ });
+}
PendingRequestPool::~PendingRequestPool() {
- mThreadStop = true;
+ {
+ // Even if the shared variable is atomic, it must be modified under the
+ // mutex in order to correctly publish the modification to the waiting
+ // thread.
+ std::unique_lock<std::mutex> lk(mCvLock);
+ mThreadStop = true;
+ }
mCv.notify_all();
if (mThread.joinable()) {
mThread.join();
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp b/automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp
index 908564c..c6d3687 100644
--- a/automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp
@@ -29,7 +29,9 @@
using ::android::base::ScopedLockAssertion;
-RecurrentTimer::RecurrentTimer() : mThread(&RecurrentTimer::loop, this) {}
+RecurrentTimer::RecurrentTimer() {
+ mThread = std::thread(&RecurrentTimer::loop, this);
+}
RecurrentTimer::~RecurrentTimer() {
{
diff --git a/automotive/vehicle/aidl/impl/utils/test/include/TestPropertyUtils.h b/automotive/vehicle/aidl/impl/utils/test/include/TestPropertyUtils.h
index d512713..1400288 100644
--- a/automotive/vehicle/aidl/impl/utils/test/include/TestPropertyUtils.h
+++ b/automotive/vehicle/aidl/impl/utils/test/include/TestPropertyUtils.h
@@ -35,7 +35,6 @@
} // namespace testpropertyutils_impl
-#ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
// Converts the system property to the vendor property.
// WARNING: This is only for the end-to-end testing, Should NOT include in the user build.
inline constexpr int32_t toVendor(
@@ -55,7 +54,6 @@
toVendor(testpropertyutils_impl::VehicleProperty::CLUSTER_REQUEST_DISPLAY);
constexpr int32_t VENDOR_CLUSTER_NAVIGATION_STATE =
toVendor(testpropertyutils_impl::VehicleProperty::CLUSTER_NAVIGATION_STATE);
-#endif // ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
// These properties are placeholder properties for developers to test new features without
// implementing a real property.
@@ -86,6 +84,13 @@
toInt(testpropertyutils_impl::VehicleArea::GLOBAL) |
toInt(testpropertyutils_impl::VehiclePropertyType::BYTES);
+// This property is used for testing vendor error codes end to end.
+// 0x21402a13
+constexpr int32_t VENDOR_PROPERTY_ID = 0x2a13 |
+ toInt(testpropertyutils_impl::VehiclePropertyGroup::VENDOR) |
+ toInt(testpropertyutils_impl::VehicleArea::GLOBAL) |
+ toInt(testpropertyutils_impl::VehiclePropertyType::INT32);
+
// This property is used for test purpose. End to end tests use this property to test set and get
// method for MIXED type properties.
constexpr int32_t kMixedTypePropertyForTest =
diff --git a/automotive/vehicle/aidl/impl/vhal/Android.bp b/automotive/vehicle/aidl/impl/vhal/Android.bp
index 5abcaf6..4feea79 100644
--- a/automotive/vehicle/aidl/impl/vhal/Android.bp
+++ b/automotive/vehicle/aidl/impl/vhal/Android.bp
@@ -66,3 +66,25 @@
"libbinder_ndk",
],
}
+
+cc_fuzz {
+ name: "android.hardware.automotive.vehicle@V1-default-service_fuzzer",
+ vendor: true,
+ defaults: [
+ "FakeVehicleHardwareDefaults",
+ "VehicleHalDefaults",
+ "android-automotive-large-parcelable-defaults",
+ "service_fuzzer_defaults",
+ ],
+ static_libs: [
+ "DefaultVehicleHal",
+ "FakeVehicleHardware",
+ "VehicleHalUtils",
+ ],
+ srcs: ["src/fuzzer.cpp"],
+ fuzz_config: {
+ cc: [
+ "keithmok@google.com",
+ ],
+ },
+}
diff --git a/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h b/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
index b3f4a0f..2e7298f 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
@@ -107,18 +107,12 @@
// Gets the callback to be called when the request for this client has finished.
std::shared_ptr<const IVehicleHardware::GetValuesCallback> getResultCallback();
- // Marshals the updated values into largeParcelable and sends it through {@code onPropertyEvent}
+ // Marshals the updated values into largeParcelable and sents it through {@code onPropertyEvent}
// callback.
static void sendUpdatedValues(
CallbackType callback,
std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>&&
updatedValues);
- // Marshals the set property error events into largeParcelable and sends it through
- // {@code onPropertySetError} callback.
- static void sendPropertySetErrors(
- CallbackType callback,
- std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropError>&&
- vehiclePropErrors);
protected:
// Gets the callback to be called when the request for this client has timeout.
diff --git a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
index b6dbbc1..2c2cf1a 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
@@ -123,10 +123,10 @@
std::shared_ptr<PendingRequestPool> mPendingRequestPool;
};
- // A wrapper for binder operations to enable stubbing for test.
- class IBinder {
+ // A wrapper for binder lifecycle operations to enable stubbing for test.
+ class BinderLifecycleInterface {
public:
- virtual ~IBinder() = default;
+ virtual ~BinderLifecycleInterface() = default;
virtual binder_status_t linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
void* cookie) = 0;
@@ -134,8 +134,8 @@
virtual bool isAlive(const AIBinder* binder) = 0;
};
- // A real implementation for IBinder.
- class AIBinderImpl final : public IBinder {
+ // A real implementation for BinderLifecycleInterface.
+ class BinderLifecycleHandler final : public BinderLifecycleInterface {
public:
binder_status_t linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
void* cookie) override;
@@ -154,7 +154,7 @@
// BinderDiedUnlinkedEvent represents either an onBinderDied or an onBinderUnlinked event.
struct BinderDiedUnlinkedEvent {
// true for onBinderDied, false for onBinderUnlinked.
- bool onBinderDied;
+ bool forOnBinderDied;
const AIBinder* clientId;
};
@@ -164,6 +164,7 @@
static constexpr int64_t TIMEOUT_IN_NANO = 30'000'000'000;
// heart beat event interval: 3s
static constexpr int64_t HEART_BEAT_INTERVAL_IN_NANO = 3'000'000'000;
+ bool mShouldRefreshPropertyConfigs;
std::unique_ptr<IVehicleHardware> mVehicleHardware;
// mConfigsByPropId and mConfigFile are only modified during initialization, so no need to
@@ -186,8 +187,8 @@
GUARDED_BY(mLock);
// SubscriptionClients is thread-safe.
std::shared_ptr<SubscriptionClients> mSubscriptionClients;
- // mBinderImpl is only going to be changed in test.
- std::unique_ptr<IBinder> mBinderImpl;
+ // mBinderLifecycleHandler is only going to be changed in test.
+ std::unique_ptr<BinderLifecycleInterface> mBinderLifecycleHandler;
// Only initialized once.
std::shared_ptr<std::function<void()>> mRecurrentAction;
@@ -212,7 +213,6 @@
android::base::Result<std::vector<int64_t>> checkDuplicateRequests(
const std::vector<aidl::android::hardware::automotive::vehicle::SetValueRequest>&
requests);
-
VhalResult<void> checkSubscribeOptions(
const std::vector<aidl::android::hardware::automotive::vehicle::SubscribeOptions>&
options);
@@ -236,6 +236,8 @@
bool checkDumpPermission();
+ bool getAllPropConfigsFromHardware();
+
// The looping handler function to process all onBinderDied or onBinderUnlinked events in
// mBinderEvents.
void onBinderDiedUnlinkedHandler();
@@ -247,14 +249,10 @@
const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool);
static void onPropertyChangeEvent(
- const std::weak_ptr<SubscriptionManager>& subscriptionManager,
+ std::weak_ptr<SubscriptionManager> subscriptionManager,
const std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>&
updatedValues);
- static void onPropertySetErrorEvent(
- const std::weak_ptr<SubscriptionManager>& subscriptionManager,
- const std::vector<SetValueErrorEvent>& errorEvents);
-
static void checkHealth(IVehicleHardware* hardware,
std::weak_ptr<SubscriptionManager> subscriptionManager);
@@ -267,7 +265,7 @@
void setTimeout(int64_t timeoutInNano);
// Test-only
- void setBinderImpl(std::unique_ptr<IBinder> impl);
+ void setBinderLifecycleHandler(std::unique_ptr<BinderLifecycleInterface> impl);
};
} // namespace vehicle
diff --git a/automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h b/automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h
index 4912093..14799d9 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h
@@ -41,15 +41,15 @@
public:
using ClientIdType = const AIBinder*;
- void addClient(const ClientIdType& clientId, float sampleRate);
+ void addClient(const ClientIdType& clientId, float sampleRateHz);
void removeClient(const ClientIdType& clientId);
- float getMaxSampleRate();
+ float getMaxSampleRateHz() const;
private:
- float mMaxSampleRate = 0.;
- std::unordered_map<ClientIdType, float> mSampleRates;
+ float mMaxSampleRateHz = 0.;
+ std::unordered_map<ClientIdType, float> mSampleRateHzByClient;
- void refreshMaxSampleRate();
+ void refreshMaxSampleRateHz();
};
// A thread-safe subscription manager that manages all VHAL subscriptions.
@@ -59,7 +59,7 @@
using CallbackType =
std::shared_ptr<aidl::android::hardware::automotive::vehicle::IVehicleCallback>;
- explicit SubscriptionManager(IVehicleHardware* hardware);
+ explicit SubscriptionManager(IVehicleHardware* vehicleHardware);
~SubscriptionManager();
// Subscribes to properties according to {@code SubscribeOptions}. Note that all option must
@@ -99,18 +99,8 @@
const std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>&
updatedValues);
- // Gets the sample rate for the continuous property. Returns {@code std::nullopt} if the
- // property has not been subscribed before or is not a continuous property.
- std::optional<float> getSampleRate(const ClientIdType& clientId, int32_t propId,
- int32_t areaId);
- // For a list of set property error events, returns a map that maps clients subscribing to the
- // properties to a list of errors for each client.
- std::unordered_map<CallbackType,
- std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropError>>
- getSubscribedClientsForErrorEvents(const std::vector<SetValueErrorEvent>& errorEvents);
-
// Checks whether the sample rate is valid.
- static bool checkSampleRate(float sampleRate);
+ static bool checkSampleRateHz(float sampleRateHz);
private:
// Friend class for testing.
@@ -127,17 +117,21 @@
std::unordered_map<PropIdAreaId, ContSubConfigs, PropIdAreaIdHash> mContSubConfigsByPropIdArea
GUARDED_BY(mLock);
- VhalResult<void> updateSampleRateLocked(const ClientIdType& clientId,
- const PropIdAreaId& propIdAreaId, float sampleRate)
+ VhalResult<void> addContinuousSubscriberLocked(const ClientIdType& clientId,
+ const PropIdAreaId& propIdAreaId,
+ float sampleRateHz) REQUIRES(mLock);
+ VhalResult<void> removeContinuousSubscriberLocked(const ClientIdType& clientId,
+ const PropIdAreaId& propIdAreaId)
REQUIRES(mLock);
- VhalResult<void> removeSampleRateLocked(const ClientIdType& clientId,
- const PropIdAreaId& propIdAreaId) REQUIRES(mLock);
+
+ VhalResult<void> updateContSubConfigs(const PropIdAreaId& PropIdAreaId,
+ const ContSubConfigs& newConfig) REQUIRES(mLock);
// Checks whether the manager is empty. For testing purpose.
bool isEmpty();
// Get the interval in nanoseconds accroding to sample rate.
- static android::base::Result<int64_t> getInterval(float sampleRate);
+ static android::base::Result<int64_t> getIntervalNanos(float sampleRateHz);
};
} // namespace vehicle
diff --git a/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp b/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
index fb23a25..81d231c 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
@@ -38,8 +38,6 @@
using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
using ::aidl::android::hardware::automotive::vehicle::SetValueResults;
using ::aidl::android::hardware::automotive::vehicle::StatusCode;
-using ::aidl::android::hardware::automotive::vehicle::VehiclePropError;
-using ::aidl::android::hardware::automotive::vehicle::VehiclePropErrors;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValues;
using ::android::base::Result;
@@ -302,34 +300,7 @@
if (ScopedAStatus callbackStatus =
callback->onPropertyEvent(vehiclePropValues, sharedMemoryFileCount);
!callbackStatus.isOk()) {
- ALOGE("subscribe: failed to call onPropertyEvent callback, client ID: %p, error: %s, "
- "exception: %d, service specific error: %d",
- callback->asBinder().get(), callbackStatus.getMessage(),
- callbackStatus.getExceptionCode(), callbackStatus.getServiceSpecificError());
- }
-}
-
-void SubscriptionClient::sendPropertySetErrors(std::shared_ptr<IVehicleCallback> callback,
- std::vector<VehiclePropError>&& vehiclePropErrors) {
- if (vehiclePropErrors.empty()) {
- return;
- }
-
- VehiclePropErrors vehiclePropErrorsLargeParcelable;
- ScopedAStatus status = vectorToStableLargeParcelable(std::move(vehiclePropErrors),
- &vehiclePropErrorsLargeParcelable);
- if (!status.isOk()) {
- int statusCode = status.getServiceSpecificError();
- ALOGE("subscribe: failed to marshal result into large parcelable, error: "
- "%s, code: %d",
- status.getMessage(), statusCode);
- return;
- }
-
- if (ScopedAStatus callbackStatus =
- callback->onPropertySetError(vehiclePropErrorsLargeParcelable);
- !callbackStatus.isOk()) {
- ALOGE("subscribe: failed to call onPropertySetError callback, client ID: %p, error: %s, "
+ ALOGE("subscribe: failed to call UpdateValues callback, client ID: %p, error: %s, "
"exception: %d, service specific error: %d",
callback->asBinder().get(), callbackStatus.getMessage(),
callbackStatus.getExceptionCode(), callbackStatus.getServiceSpecificError());
diff --git a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
index 2e9a4b6..98cfc39 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
@@ -15,6 +15,7 @@
*/
#define LOG_TAG "DefaultVehicleHal"
+#define ATRACE_TAG ATRACE_TAG_HAL
#include <DefaultVehicleHal.h>
@@ -28,6 +29,7 @@
#include <private/android_filesystem_config.h>
#include <utils/Log.h>
#include <utils/SystemClock.h>
+#include <utils/Trace.h>
#include <inttypes.h>
#include <set>
@@ -78,14 +80,14 @@
return str;
}
-float getDefaultSampleRate(float sampleRate, float minSampleRate, float maxSampleRate) {
- if (sampleRate < minSampleRate) {
- return minSampleRate;
+float getDefaultSampleRateHz(float sampleRateHz, float minSampleRateHz, float maxSampleRateHz) {
+ if (sampleRateHz < minSampleRateHz) {
+ return minSampleRateHz;
}
- if (sampleRate > maxSampleRate) {
- return maxSampleRate;
+ if (sampleRateHz > maxSampleRateHz) {
+ return maxSampleRateHz;
}
- return sampleRate;
+ return sampleRateHz;
}
} // namespace
@@ -123,32 +125,18 @@
return mClients.size();
}
-DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> hardware)
- : mVehicleHardware(std::move(hardware)),
+DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware)
+ : mVehicleHardware(std::move(vehicleHardware)),
mPendingRequestPool(std::make_shared<PendingRequestPool>(TIMEOUT_IN_NANO)) {
- auto configs = mVehicleHardware->getAllPropertyConfigs();
- for (auto& config : configs) {
- mConfigsByPropId[config.prop] = config;
- }
- VehiclePropConfigs vehiclePropConfigs;
- vehiclePropConfigs.payloads = std::move(configs);
- auto result = LargeParcelableBase::parcelableToStableLargeParcelable(vehiclePropConfigs);
- if (!result.ok()) {
- ALOGE("failed to convert configs to shared memory file, error: %s, code: %d",
- result.error().message().c_str(), static_cast<int>(result.error().code()));
+ if (!getAllPropConfigsFromHardware()) {
return;
}
- if (result.value() != nullptr) {
- mConfigFile = std::move(result.value());
- }
-
- mSubscriptionClients = std::make_shared<SubscriptionClients>(mPendingRequestPool);
mSubscriptionClients = std::make_shared<SubscriptionClients>(mPendingRequestPool);
auto subscribeIdByClient = std::make_shared<SubscribeIdByClient>();
- IVehicleHardware* hardwarePtr = mVehicleHardware.get();
- mSubscriptionManager = std::make_shared<SubscriptionManager>(hardwarePtr);
+ IVehicleHardware* vehicleHardwarePtr = mVehicleHardware.get();
+ mSubscriptionManager = std::make_shared<SubscriptionManager>(vehicleHardwarePtr);
std::weak_ptr<SubscriptionManager> subscriptionManagerCopy = mSubscriptionManager;
mVehicleHardware->registerOnPropertyChangeEvent(
@@ -156,20 +144,15 @@
[subscriptionManagerCopy](std::vector<VehiclePropValue> updatedValues) {
onPropertyChangeEvent(subscriptionManagerCopy, updatedValues);
}));
- mVehicleHardware->registerOnPropertySetErrorEvent(
- std::make_unique<IVehicleHardware::PropertySetErrorCallback>(
- [subscriptionManagerCopy](std::vector<SetValueErrorEvent> errorEvents) {
- onPropertySetErrorEvent(subscriptionManagerCopy, errorEvents);
- }));
// Register heartbeat event.
- mRecurrentAction =
- std::make_shared<std::function<void()>>([hardwarePtr, subscriptionManagerCopy]() {
- checkHealth(hardwarePtr, subscriptionManagerCopy);
+ mRecurrentAction = std::make_shared<std::function<void()>>(
+ [vehicleHardwarePtr, subscriptionManagerCopy]() {
+ checkHealth(vehicleHardwarePtr, subscriptionManagerCopy);
});
mRecurrentTimer.registerTimerCallback(HEART_BEAT_INTERVAL_IN_NANO, mRecurrentAction);
- mBinderImpl = std::make_unique<AIBinderImpl>();
+ mBinderLifecycleHandler = std::make_unique<BinderLifecycleHandler>();
mOnBinderDiedUnlinkedHandlerThread = std::thread([this] { onBinderDiedUnlinkedHandler(); });
mDeathRecipient = ScopedAIBinder_DeathRecipient(
AIBinder_DeathRecipient_new(&DefaultVehicleHal::onBinderDied));
@@ -194,7 +177,7 @@
}
void DefaultVehicleHal::onPropertyChangeEvent(
- const std::weak_ptr<SubscriptionManager>& subscriptionManager,
+ std::weak_ptr<SubscriptionManager> subscriptionManager,
const std::vector<VehiclePropValue>& updatedValues) {
auto manager = subscriptionManager.lock();
if (manager == nullptr) {
@@ -211,20 +194,6 @@
}
}
-void DefaultVehicleHal::onPropertySetErrorEvent(
- const std::weak_ptr<SubscriptionManager>& subscriptionManager,
- const std::vector<SetValueErrorEvent>& errorEvents) {
- auto manager = subscriptionManager.lock();
- if (manager == nullptr) {
- ALOGW("the SubscriptionManager is destroyed, DefaultVehicleHal is ending");
- return;
- }
- auto vehiclePropErrorsByClient = manager->getSubscribedClientsForErrorEvents(errorEvents);
- for (auto& [callback, vehiclePropErrors] : vehiclePropErrorsByClient) {
- SubscriptionClient::sendPropertySetErrors(callback, std::move(vehiclePropErrors));
- }
-}
-
template <class T>
std::shared_ptr<T> DefaultVehicleHal::getOrCreateClient(
std::unordered_map<const AIBinder*, std::shared_ptr<T>>* clients,
@@ -239,7 +208,7 @@
bool DefaultVehicleHal::monitorBinderLifeCycleLocked(const AIBinder* clientId) {
OnBinderDiedContext* contextPtr = nullptr;
if (mOnBinderDiedContexts.find(clientId) != mOnBinderDiedContexts.end()) {
- return mBinderImpl->isAlive(clientId);
+ return mBinderLifecycleHandler->isAlive(clientId);
} else {
std::unique_ptr<OnBinderDiedContext> context = std::make_unique<OnBinderDiedContext>(
OnBinderDiedContext{.vhal = this, .clientId = clientId});
@@ -251,7 +220,7 @@
}
// If this function fails, onBinderUnlinked would be called to remove the added context.
- binder_status_t status = mBinderImpl->linkToDeath(
+ binder_status_t status = mBinderLifecycleHandler->linkToDeath(
const_cast<AIBinder*>(clientId), mDeathRecipient.get(), static_cast<void*>(contextPtr));
if (status == STATUS_OK) {
return true;
@@ -265,7 +234,8 @@
OnBinderDiedContext* context = reinterpret_cast<OnBinderDiedContext*>(cookie);
// To be handled in mOnBinderDiedUnlinkedHandlerThread. We cannot handle the event in the same
// thread because we might be holding the mLock the handler requires.
- context->vhal->mBinderEvents.push(BinderDiedUnlinkedEvent{true, context->clientId});
+ context->vhal->mBinderEvents.push(
+ BinderDiedUnlinkedEvent{/*forOnBinderDied=*/true, context->clientId});
}
void DefaultVehicleHal::onBinderDiedWithContext(const AIBinder* clientId) {
@@ -281,7 +251,8 @@
OnBinderDiedContext* context = reinterpret_cast<OnBinderDiedContext*>(cookie);
// To be handled in mOnBinderDiedUnlinkedHandlerThread. We cannot handle the event in the same
// thread because we might be holding the mLock the handler requires.
- context->vhal->mBinderEvents.push(BinderDiedUnlinkedEvent{false, context->clientId});
+ context->vhal->mBinderEvents.push(
+ BinderDiedUnlinkedEvent{/*forOnBinderDied=*/false, context->clientId});
}
void DefaultVehicleHal::onBinderUnlinkedWithContext(const AIBinder* clientId) {
@@ -294,7 +265,7 @@
void DefaultVehicleHal::onBinderDiedUnlinkedHandler() {
while (mBinderEvents.waitForItems()) {
for (BinderDiedUnlinkedEvent& event : mBinderEvents.flush()) {
- if (event.onBinderDied) {
+ if (event.forOnBinderDied) {
onBinderDiedWithContext(event.clientId);
} else {
onBinderUnlinkedWithContext(event.clientId);
@@ -320,6 +291,27 @@
mPendingRequestPool = std::make_unique<PendingRequestPool>(timeoutInNano);
}
+bool DefaultVehicleHal::getAllPropConfigsFromHardware() {
+ auto configs = mVehicleHardware->getAllPropertyConfigs();
+ for (auto& config : configs) {
+ mConfigsByPropId[config.prop] = config;
+ }
+ VehiclePropConfigs vehiclePropConfigs;
+ vehiclePropConfigs.payloads = std::move(configs);
+ auto result = LargeParcelableBase::parcelableToStableLargeParcelable(vehiclePropConfigs);
+ if (!result.ok()) {
+ ALOGE("failed to convert configs to shared memory file, error: %s, code: %d",
+ result.error().message().c_str(), static_cast<int>(result.error().code()));
+ mConfigFile = nullptr;
+ return false;
+ }
+
+ if (result.value() != nullptr) {
+ mConfigFile = std::move(result.value());
+ }
+ return true;
+}
+
ScopedAStatus DefaultVehicleHal::getAllPropConfigs(VehiclePropConfigs* output) {
if (mConfigFile != nullptr) {
output->payloads.clear();
@@ -368,6 +360,10 @@
ScopedAStatus DefaultVehicleHal::getValues(const CallbackType& callback,
const GetValueRequests& requests) {
+ ATRACE_CALL();
+ if (callback == nullptr) {
+ return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
+ }
expected<LargeParcelableBase::BorrowedOwnedObject<GetValueRequests>, ScopedAStatus>
deserializedResults = fromStableLargeParcelable(requests);
if (!deserializedResults.ok()) {
@@ -451,6 +447,10 @@
ScopedAStatus DefaultVehicleHal::setValues(const CallbackType& callback,
const SetValueRequests& requests) {
+ ATRACE_CALL();
+ if (callback == nullptr) {
+ return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
+ }
expected<LargeParcelableBase::BorrowedOwnedObject<SetValueRequests>, ScopedAStatus>
deserializedResults = fromStableLargeParcelable(requests);
if (!deserializedResults.ok()) {
@@ -608,18 +608,20 @@
}
if (config.changeMode == VehiclePropertyChangeMode::CONTINUOUS) {
- float sampleRate = option.sampleRate;
- float minSampleRate = config.minSampleRate;
- float maxSampleRate = config.maxSampleRate;
- if (sampleRate < minSampleRate || sampleRate > maxSampleRate) {
- float defaultRate = getDefaultSampleRate(sampleRate, minSampleRate, maxSampleRate);
- ALOGW("sample rate: %f out of range, must be within %f and %f, set to %f",
- sampleRate, minSampleRate, maxSampleRate, defaultRate);
- sampleRate = defaultRate;
+ float sampleRateHz = option.sampleRate;
+ float minSampleRateHz = config.minSampleRate;
+ float maxSampleRateHz = config.maxSampleRate;
+ float defaultRateHz =
+ getDefaultSampleRateHz(sampleRateHz, minSampleRateHz, maxSampleRateHz);
+ if (sampleRateHz != defaultRateHz) {
+ ALOGW("sample rate: %f HZ out of range, must be within %f HZ and %f HZ , set to %f "
+ "HZ",
+ sampleRateHz, minSampleRateHz, maxSampleRateHz, defaultRateHz);
+ sampleRateHz = defaultRateHz;
}
- if (!SubscriptionManager::checkSampleRate(sampleRate)) {
+ if (!SubscriptionManager::checkSampleRateHz(sampleRateHz)) {
return StatusError(StatusCode::INVALID_ARG)
- << "invalid sample rate: " << sampleRate;
+ << "invalid sample rate: " << sampleRateHz << " HZ";
}
}
@@ -644,11 +646,13 @@
const std::vector<SubscribeOptions>& options,
[[maybe_unused]] int32_t maxSharedMemoryFileCount) {
// TODO(b/205189110): Use shared memory file count.
+ if (callback == nullptr) {
+ return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
+ }
if (auto result = checkSubscribeOptions(options); !result.ok()) {
ALOGE("subscribe: invalid subscribe options: %s", getErrorMsg(result).c_str());
return toScopedAStatus(result);
}
-
std::vector<SubscribeOptions> onChangeSubscriptions;
std::vector<SubscribeOptions> continuousSubscriptions;
for (const auto& option : options) {
@@ -669,7 +673,7 @@
}
if (config.changeMode == VehiclePropertyChangeMode::CONTINUOUS) {
- optionCopy.sampleRate = getDefaultSampleRate(
+ optionCopy.sampleRate = getDefaultSampleRateHz(
optionCopy.sampleRate, config.minSampleRate, config.maxSampleRate);
continuousSubscriptions.push_back(std::move(optionCopy));
} else {
@@ -688,19 +692,15 @@
// Create a new SubscriptionClient if there isn't an existing one.
mSubscriptionClients->maybeAddClient(callback);
+ // Since we have already check the sample rates, the following functions must succeed.
if (!onChangeSubscriptions.empty()) {
- auto result = mSubscriptionManager->subscribe(callback, onChangeSubscriptions,
- /*isContinuousProperty=*/false);
- if (!result.ok()) {
- return toScopedAStatus(result);
- }
+ return toScopedAStatus(mSubscriptionManager->subscribe(callback, onChangeSubscriptions,
+ /*isContinuousProperty=*/false));
}
if (!continuousSubscriptions.empty()) {
- auto result = mSubscriptionManager->subscribe(callback, continuousSubscriptions,
- /*isContinuousProperty=*/true);
- if (!result.ok()) {
- return toScopedAStatus(result);
- }
+ return toScopedAStatus(mSubscriptionManager->subscribe(callback,
+ continuousSubscriptions,
+ /*isContinuousProperty=*/true));
}
}
return ScopedAStatus::ok();
@@ -708,6 +708,9 @@
ScopedAStatus DefaultVehicleHal::unsubscribe(const CallbackType& callback,
const std::vector<int32_t>& propIds) {
+ if (callback == nullptr) {
+ return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
+ }
return toScopedAStatus(mSubscriptionManager->unsubscribe(callback->asBinder().get(), propIds));
}
@@ -752,9 +755,9 @@
return {};
}
-void DefaultVehicleHal::checkHealth(IVehicleHardware* hardware,
+void DefaultVehicleHal::checkHealth(IVehicleHardware* vehicleHardware,
std::weak_ptr<SubscriptionManager> subscriptionManager) {
- StatusCode status = hardware->checkHealth();
+ StatusCode status = vehicleHardware->checkHealth();
if (status != StatusCode::OK) {
ALOGE("VHAL check health returns non-okay status");
return;
@@ -769,18 +772,18 @@
return;
}
-binder_status_t DefaultVehicleHal::AIBinderImpl::linkToDeath(AIBinder* binder,
- AIBinder_DeathRecipient* recipient,
- void* cookie) {
+binder_status_t DefaultVehicleHal::BinderLifecycleHandler::linkToDeath(
+ AIBinder* binder, AIBinder_DeathRecipient* recipient, void* cookie) {
return AIBinder_linkToDeath(binder, recipient, cookie);
}
-bool DefaultVehicleHal::AIBinderImpl::isAlive(const AIBinder* binder) {
+bool DefaultVehicleHal::BinderLifecycleHandler::isAlive(const AIBinder* binder) {
return AIBinder_isAlive(binder);
}
-void DefaultVehicleHal::setBinderImpl(std::unique_ptr<IBinder> impl) {
- mBinderImpl = std::move(impl);
+void DefaultVehicleHal::setBinderLifecycleHandler(
+ std::unique_ptr<BinderLifecycleInterface> handler) {
+ mBinderLifecycleHandler = std::move(handler);
}
bool DefaultVehicleHal::checkDumpPermission() {
@@ -798,10 +801,16 @@
for (uint32_t i = 0; i < numArgs; i++) {
options.push_back(args[i]);
}
+ if (options.size() == 1 && options[0] == "-a") {
+ // Ignore "-a" option. Bugreport will call with this option.
+ options.clear();
+ }
DumpResult result = mVehicleHardware->dump(options);
+ if (result.refreshPropertyConfigs) {
+ getAllPropConfigsFromHardware();
+ }
dprintf(fd, "%s", (result.buffer + "\n").c_str());
if (!result.callerShouldDumpState) {
- dprintf(fd, "Skip dumping Vehicle HAL State.\n");
return STATUS_OK;
}
dprintf(fd, "Vehicle HAL State: \n");
diff --git a/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp b/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp
index 566c303..bba730f 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp
@@ -36,14 +36,14 @@
using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback;
using ::aidl::android::hardware::automotive::vehicle::StatusCode;
using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
-using ::aidl::android::hardware::automotive::vehicle::VehiclePropError;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
using ::android::base::Error;
using ::android::base::Result;
using ::android::base::StringPrintf;
using ::ndk::ScopedAStatus;
-SubscriptionManager::SubscriptionManager(IVehicleHardware* hardware) : mVehicleHardware(hardware) {}
+SubscriptionManager::SubscriptionManager(IVehicleHardware* vehicleHardware)
+ : mVehicleHardware(vehicleHardware) {}
SubscriptionManager::~SubscriptionManager() {
std::scoped_lock<std::mutex> lockGuard(mLock);
@@ -52,94 +52,82 @@
mSubscribedPropsByClient.clear();
}
-bool SubscriptionManager::checkSampleRate(float sampleRate) {
- return getInterval(sampleRate).ok();
+bool SubscriptionManager::checkSampleRateHz(float sampleRateHz) {
+ return getIntervalNanos(sampleRateHz).ok();
}
-Result<int64_t> SubscriptionManager::getInterval(float sampleRate) {
- int64_t interval = 0;
- if (sampleRate <= 0) {
+Result<int64_t> SubscriptionManager::getIntervalNanos(float sampleRateHz) {
+ int64_t intervalNanos = 0;
+ if (sampleRateHz <= 0) {
return Error() << "invalid sample rate, must be a positive number";
}
- if (sampleRate <= (ONE_SECOND_IN_NANO / static_cast<float>(INT64_MAX))) {
- return Error() << "invalid sample rate: " << sampleRate << ", too small";
+ if (sampleRateHz <= (ONE_SECOND_IN_NANO / static_cast<float>(INT64_MAX))) {
+ return Error() << "invalid sample rate: " << sampleRateHz << ", too small";
}
- interval = static_cast<int64_t>(ONE_SECOND_IN_NANO / sampleRate);
- return interval;
+ intervalNanos = static_cast<int64_t>(ONE_SECOND_IN_NANO / sampleRateHz);
+ return intervalNanos;
}
-void ContSubConfigs::refreshMaxSampleRate() {
- float maxSampleRate = 0.;
+void ContSubConfigs::refreshMaxSampleRateHz() {
+ float maxSampleRateHz = 0.;
// This is not called frequently so a brute-focre is okay. More efficient way exists but this
// is simpler.
- for (const auto& [_, sampleRate] : mSampleRates) {
- if (sampleRate > maxSampleRate) {
- maxSampleRate = sampleRate;
+ for (const auto& [_, sampleRateHz] : mSampleRateHzByClient) {
+ if (sampleRateHz > maxSampleRateHz) {
+ maxSampleRateHz = sampleRateHz;
}
}
- mMaxSampleRate = maxSampleRate;
+ mMaxSampleRateHz = maxSampleRateHz;
}
-void ContSubConfigs::addClient(const ClientIdType& clientId, float sampleRate) {
- mSampleRates[clientId] = sampleRate;
- refreshMaxSampleRate();
+void ContSubConfigs::addClient(const ClientIdType& clientId, float sampleRateHz) {
+ mSampleRateHzByClient[clientId] = sampleRateHz;
+ refreshMaxSampleRateHz();
}
void ContSubConfigs::removeClient(const ClientIdType& clientId) {
- mSampleRates.erase(clientId);
- refreshMaxSampleRate();
+ mSampleRateHzByClient.erase(clientId);
+ refreshMaxSampleRateHz();
}
-float ContSubConfigs::getMaxSampleRate() {
- return mMaxSampleRate;
+float ContSubConfigs::getMaxSampleRateHz() const {
+ return mMaxSampleRateHz;
}
-VhalResult<void> SubscriptionManager::updateSampleRateLocked(const ClientIdType& clientId,
- const PropIdAreaId& propIdAreaId,
- float sampleRate) {
+VhalResult<void> SubscriptionManager::addContinuousSubscriberLocked(
+ const ClientIdType& clientId, const PropIdAreaId& propIdAreaId, float sampleRateHz) {
// Make a copy so that we don't modify 'mContSubConfigsByPropIdArea' on failure cases.
- ContSubConfigs infoCopy = mContSubConfigsByPropIdArea[propIdAreaId];
- infoCopy.addClient(clientId, sampleRate);
- if (infoCopy.getMaxSampleRate() ==
- mContSubConfigsByPropIdArea[propIdAreaId].getMaxSampleRate()) {
- mContSubConfigsByPropIdArea[propIdAreaId] = infoCopy;
+ ContSubConfigs newConfig = mContSubConfigsByPropIdArea[propIdAreaId];
+ newConfig.addClient(clientId, sampleRateHz);
+ return updateContSubConfigs(propIdAreaId, newConfig);
+}
+
+VhalResult<void> SubscriptionManager::removeContinuousSubscriberLocked(
+ const ClientIdType& clientId, const PropIdAreaId& propIdAreaId) {
+ // Make a copy so that we don't modify 'mContSubConfigsByPropIdArea' on failure cases.
+ ContSubConfigs newConfig = mContSubConfigsByPropIdArea[propIdAreaId];
+ newConfig.removeClient(clientId);
+ return updateContSubConfigs(propIdAreaId, newConfig);
+}
+
+VhalResult<void> SubscriptionManager::updateContSubConfigs(const PropIdAreaId& propIdAreaId,
+ const ContSubConfigs& newConfig) {
+ if (newConfig.getMaxSampleRateHz() ==
+ mContSubConfigsByPropIdArea[propIdAreaId].getMaxSampleRateHz()) {
+ mContSubConfigsByPropIdArea[propIdAreaId] = newConfig;
return {};
}
- float newRate = infoCopy.getMaxSampleRate();
+ float newRateHz = newConfig.getMaxSampleRateHz();
int32_t propId = propIdAreaId.propId;
int32_t areaId = propIdAreaId.areaId;
- if (auto status = mVehicleHardware->updateSampleRate(propId, areaId, newRate);
+ if (auto status = mVehicleHardware->updateSampleRate(propId, areaId, newRateHz);
status != StatusCode::OK) {
return StatusError(status) << StringPrintf("failed to update sample rate for prop: %" PRId32
", area"
- ": %" PRId32 ", sample rate: %f",
- propId, areaId, newRate);
+ ": %" PRId32 ", sample rate: %f HZ",
+ propId, areaId, newRateHz);
}
- mContSubConfigsByPropIdArea[propIdAreaId] = infoCopy;
- return {};
-}
-
-VhalResult<void> SubscriptionManager::removeSampleRateLocked(const ClientIdType& clientId,
- const PropIdAreaId& propIdAreaId) {
- // Make a copy so that we don't modify 'mContSubConfigsByPropIdArea' on failure cases.
- ContSubConfigs infoCopy = mContSubConfigsByPropIdArea[propIdAreaId];
- infoCopy.removeClient(clientId);
- if (infoCopy.getMaxSampleRate() ==
- mContSubConfigsByPropIdArea[propIdAreaId].getMaxSampleRate()) {
- mContSubConfigsByPropIdArea[propIdAreaId] = infoCopy;
- return {};
- }
- float newRate = infoCopy.getMaxSampleRate();
- int32_t propId = propIdAreaId.propId;
- int32_t areaId = propIdAreaId.areaId;
- if (auto status = mVehicleHardware->updateSampleRate(propId, areaId, newRate);
- status != StatusCode::OK) {
- return StatusError(status) << StringPrintf("failed to update sample rate for prop: %" PRId32
- ", area"
- ": %" PRId32 ", sample rate: %f",
- propId, areaId, newRate);
- }
- mContSubConfigsByPropIdArea[propIdAreaId] = infoCopy;
+ mContSubConfigsByPropIdArea[propIdAreaId] = newConfig;
return {};
}
@@ -148,14 +136,12 @@
bool isContinuousProperty) {
std::scoped_lock<std::mutex> lockGuard(mLock);
- std::vector<int64_t> intervals;
for (const auto& option : options) {
- float sampleRate = option.sampleRate;
+ float sampleRateHz = option.sampleRate;
if (isContinuousProperty) {
- auto intervalResult = getInterval(sampleRate);
- if (!intervalResult.ok()) {
- return StatusError(StatusCode::INVALID_ARG) << intervalResult.error().message();
+ if (auto result = getIntervalNanos(sampleRateHz); !result.ok()) {
+ return StatusError(StatusCode::INVALID_ARG) << result.error().message();
}
}
@@ -177,7 +163,8 @@
.areaId = areaId,
};
if (isContinuousProperty) {
- if (auto result = updateSampleRateLocked(clientId, propIdAreaId, option.sampleRate);
+ if (auto result = addContinuousSubscriberLocked(clientId, propIdAreaId,
+ option.sampleRate);
!result.ok()) {
return result;
}
@@ -215,7 +202,7 @@
while (it != propIdAreaIds.end()) {
int32_t propId = it->propId;
if (std::find(propIds.begin(), propIds.end(), propId) != propIds.end()) {
- if (auto result = removeSampleRateLocked(clientId, *it); !result.ok()) {
+ if (auto result = removeContinuousSubscriberLocked(clientId, *it); !result.ok()) {
return result;
}
@@ -245,7 +232,7 @@
auto& subscriptions = mSubscribedPropsByClient[clientId];
for (auto const& propIdAreaId : subscriptions) {
- if (auto result = removeSampleRateLocked(clientId, propIdAreaId); !result.ok()) {
+ if (auto result = removeContinuousSubscriberLocked(clientId, propIdAreaId); !result.ok()) {
return result;
}
@@ -282,32 +269,6 @@
return clients;
}
-std::unordered_map<std::shared_ptr<IVehicleCallback>, std::vector<VehiclePropError>>
-SubscriptionManager::getSubscribedClientsForErrorEvents(
- const std::vector<SetValueErrorEvent>& errorEvents) {
- std::scoped_lock<std::mutex> lockGuard(mLock);
- std::unordered_map<std::shared_ptr<IVehicleCallback>, std::vector<VehiclePropError>> clients;
-
- for (const auto& errorEvent : errorEvents) {
- PropIdAreaId propIdAreaId{
- .propId = errorEvent.propId,
- .areaId = errorEvent.areaId,
- };
- if (mClientsByPropIdArea.find(propIdAreaId) == mClientsByPropIdArea.end()) {
- continue;
- }
-
- for (const auto& [_, client] : mClientsByPropIdArea[propIdAreaId]) {
- clients[client].push_back({
- .propId = errorEvent.propId,
- .areaId = errorEvent.areaId,
- .errorCode = errorEvent.errorCode,
- });
- }
- }
- return clients;
-}
-
bool SubscriptionManager::isEmpty() {
std::scoped_lock<std::mutex> lockGuard(mLock);
return mSubscribedPropsByClient.empty() && mClientsByPropIdArea.empty();
diff --git a/automotive/vehicle/aidl/impl/vhal/src/VehicleService.cpp b/automotive/vehicle/aidl/impl/vhal/src/VehicleService.cpp
index c8b5c65..f8a4e7d 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/VehicleService.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/VehicleService.cpp
@@ -27,6 +27,13 @@
using ::android::hardware::automotive::vehicle::fake::FakeVehicleHardware;
int main(int /* argc */, char* /* argv */[]) {
+ ALOGI("Starting thread pool...");
+ if (!ABinderProcess_setThreadPoolMaxThreadCount(4)) {
+ ALOGE("%s", "failed to set thread pool max thread count");
+ return 1;
+ }
+ ABinderProcess_startThreadPool();
+
std::unique_ptr<FakeVehicleHardware> hardware = std::make_unique<FakeVehicleHardware>();
std::shared_ptr<DefaultVehicleHal> vhal =
::ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
@@ -39,12 +46,6 @@
return 1;
}
- if (!ABinderProcess_setThreadPoolMaxThreadCount(4)) {
- ALOGE("%s", "failed to set thread pool max thread count");
- return 1;
- }
- ABinderProcess_startThreadPool();
-
ALOGI("Vehicle Service Ready");
ABinderProcess_joinThreadPool();
diff --git a/automotive/vehicle/aidl/impl/vhal/src/fuzzer.cpp b/automotive/vehicle/aidl/impl/vhal/src/fuzzer.cpp
new file mode 100644
index 0000000..ac1e3b1
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/src/fuzzer.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2022 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 <DefaultVehicleHal.h>
+#include <FakeVehicleHardware.h>
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+using ::android::fuzzService;
+using ::android::hardware::automotive::vehicle::DefaultVehicleHal;
+using ::android::hardware::automotive::vehicle::fake::FakeVehicleHardware;
+using ::ndk::SharedRefBase;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ std::unique_ptr<FakeVehicleHardware> hardware = std::make_unique<FakeVehicleHardware>();
+ std::shared_ptr<DefaultVehicleHal> vhal =
+ ::ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
+
+ fuzzService(vhal->asBinder().get(), FuzzedDataProvider(data, size));
+
+ return 0;
+}
diff --git a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
index 76b57c7..05e569a 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
@@ -62,7 +62,6 @@
using ::aidl::android::hardware::automotive::vehicle::VehicleAreaWindow;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs;
-using ::aidl::android::hardware::automotive::vehicle::VehiclePropError;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropErrors;
using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
@@ -325,9 +324,9 @@
mCallbackClient = IVehicleCallback::fromBinder(mBinder);
// Set the linkToDeath to a fake implementation that always returns OK.
- auto binderImpl = std::make_unique<TestBinderImpl>();
- mBinderImpl = binderImpl.get();
- mVhal->setBinderImpl(std::move(binderImpl));
+ auto handler = std::make_unique<TestBinderLifecycleHandler>();
+ mBinderLifecycleHandler = handler.get();
+ mVhal->setBinderLifecycleHandler(std::move(handler));
}
void TearDown() override {
@@ -371,7 +370,7 @@
bool hasNoSubscriptions() { return mVhal->mSubscriptionManager->isEmpty(); }
- void setBinderAlive(bool isAlive) { mBinderImpl->setAlive(isAlive); };
+ void setBinderAlive(bool isAlive) { mBinderLifecycleHandler->setAlive(isAlive); };
static Result<void> getValuesTestCases(size_t size, GetValueRequests& requests,
std::vector<GetValueResult>& expectedResults,
@@ -445,7 +444,7 @@
}
private:
- class TestBinderImpl final : public DefaultVehicleHal::IBinder {
+ class TestBinderLifecycleHandler final : public DefaultVehicleHal::BinderLifecycleInterface {
public:
binder_status_t linkToDeath(AIBinder*, AIBinder_DeathRecipient*, void*) override {
if (mIsAlive) {
@@ -469,7 +468,7 @@
std::shared_ptr<MockVehicleCallback> mCallback;
std::shared_ptr<IVehicleCallback> mCallbackClient;
SpAIBinder mBinder;
- TestBinderImpl* mBinderImpl;
+ TestBinderLifecycleHandler* mBinderLifecycleHandler;
};
TEST_F(DefaultVehicleHalTest, testGetAllPropConfigsSmall) {
@@ -672,8 +671,8 @@
}
TEST_F(DefaultVehicleHalTest, testGetValuesFinishBeforeTimeout) {
- // timeout: 0.1s
- int64_t timeout = 100000000;
+ // timeout: 1s
+ int64_t timeout = 1000000000;
setTimeout(timeout);
GetValueRequests requests;
@@ -682,17 +681,15 @@
ASSERT_TRUE(getValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
- // The response would be returned after 0.05s.
- getHardware()->setSleepTime(timeout / 2);
+ // The response would be returned after 0.01s.
+ getHardware()->setSleepTime(timeout / 100);
getHardware()->addGetValueResponses(expectedResults);
auto status = getClient()->getValues(getCallbackClient(), requests);
ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage();
- // Wait for the response.
- std::this_thread::sleep_for(std::chrono::nanoseconds(timeout));
-
+ ASSERT_TRUE(getCallback()->waitForGetValueResults(1, timeout)) << "no results in callback";
auto maybeGetValueResults = getCallback()->nextGetValueResults();
ASSERT_TRUE(maybeGetValueResults.has_value()) << "no results in callback";
EXPECT_EQ(maybeGetValueResults.value().payloads, expectedResults) << "results mismatch";
@@ -700,8 +697,8 @@
}
TEST_F(DefaultVehicleHalTest, testGetValuesFinishAfterTimeout) {
- // timeout: 0.1s
- int64_t timeout = 100000000;
+ // timeout: 0.01s
+ int64_t timeout = 10000000;
setTimeout(timeout);
GetValueRequests requests;
@@ -710,17 +707,14 @@
ASSERT_TRUE(getValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
- // The response would be returned after 0.2s.
- getHardware()->setSleepTime(timeout * 2);
+ // The response would be returned after 0.1s.
+ getHardware()->setSleepTime(timeout * 10);
getHardware()->addGetValueResponses(expectedResults);
auto status = getClient()->getValues(getCallbackClient(), requests);
ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage();
- // Wait for the response.
- std::this_thread::sleep_for(std::chrono::nanoseconds(timeout * 5));
-
for (size_t i = 0; i < expectedResults.size(); i++) {
expectedResults[i] = {
.requestId = expectedResults[i].requestId,
@@ -729,6 +723,8 @@
};
}
+ ASSERT_TRUE(getCallback()->waitForGetValueResults(1, timeout * 100))
+ << "no results in callback";
auto maybeGetValueResults = getCallback()->nextGetValueResults();
ASSERT_TRUE(maybeGetValueResults.has_value()) << "no results in callback";
ASSERT_THAT(maybeGetValueResults.value().payloads, UnorderedElementsAreArray(expectedResults))
@@ -961,8 +957,8 @@
}
TEST_F(DefaultVehicleHalTest, testSetValuesFinishBeforeTimeout) {
- // timeout: 0.1s
- int64_t timeout = 100000000;
+ // timeout: 1s
+ int64_t timeout = 1000000000;
setTimeout(timeout);
SetValueRequests requests;
@@ -971,17 +967,15 @@
ASSERT_TRUE(setValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
- // The response would be returned after 0.05s.
- getHardware()->setSleepTime(timeout / 2);
+ // The response would be returned after 0.01s.
+ getHardware()->setSleepTime(timeout / 100);
getHardware()->addSetValueResponses(expectedResults);
auto status = getClient()->setValues(getCallbackClient(), requests);
ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage();
- // Wait for the response.
- std::this_thread::sleep_for(std::chrono::nanoseconds(timeout));
-
+ ASSERT_TRUE(getCallback()->waitForSetValueResults(1, timeout)) << "no set value results";
auto maybeSetValueResults = getCallback()->nextSetValueResults();
ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results in callback";
EXPECT_EQ(maybeSetValueResults.value().payloads, expectedResults) << "results mismatch";
@@ -989,8 +983,8 @@
}
TEST_F(DefaultVehicleHalTest, testSetValuesFinishAfterTimeout) {
- // timeout: 0.1s
- int64_t timeout = 100000000;
+ // timeout: 0.01s
+ int64_t timeout = 10000000;
setTimeout(timeout);
SetValueRequests requests;
@@ -999,17 +993,14 @@
ASSERT_TRUE(setValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
- // The response would be returned after 0.2s.
- getHardware()->setSleepTime(timeout * 2);
+ // The response would be returned after 0.1s.
+ getHardware()->setSleepTime(timeout * 10);
getHardware()->addSetValueResponses(expectedResults);
auto status = getClient()->setValues(getCallbackClient(), requests);
ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage();
- // Wait for the response.
- std::this_thread::sleep_for(std::chrono::nanoseconds(timeout * 5));
-
for (size_t i = 0; i < expectedResults.size(); i++) {
expectedResults[i] = {
.requestId = expectedResults[i].requestId,
@@ -1017,6 +1008,7 @@
};
}
+ ASSERT_TRUE(getCallback()->waitForSetValueResults(1, timeout * 100)) << "no set value results";
auto maybeSetValueResults = getCallback()->nextSetValueResults();
ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results in callback";
ASSERT_THAT(maybeSetValueResults.value().payloads, UnorderedElementsAreArray(expectedResults))
@@ -1457,7 +1449,7 @@
std::vector<SubscribeOptions> options = {
{
.propId = GLOBAL_CONTINUOUS_PROP,
- .sampleRate = 20.0,
+ .sampleRate = 100.0,
},
};
@@ -1470,16 +1462,20 @@
ASSERT_TRUE(status.isOk()) << "unsubscribe failed: " << status.getMessage();
+ // Wait for the last events to come.
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
// Clear existing events.
while (getCallback()->nextOnPropertyEventResults().has_value()) {
// Do nothing.
}
- // Wait for a while, make sure no new events are generated.
+ // Wait for a while, make sure no new events are generated. If still subscribed, this should
+ // generate around 10 events.
std::this_thread::sleep_for(std::chrono::milliseconds(100));
- ASSERT_FALSE(getCallback()->nextOnPropertyEventResults().has_value())
- << "No property event should be generated after unsubscription";
+ ASSERT_EQ(getCallback()->countOnPropertyEventResults(), 0u)
+ << "Property event generation must stop after unsubscription";
}
class SubscribeInvalidOptionsTest
@@ -1657,63 +1653,6 @@
ASSERT_EQ(msg.find("Vehicle HAL State: "), std::string::npos);
}
-TEST_F(DefaultVehicleHalTest, testOnPropertySetErrorEvent) {
- std::vector<SubscribeOptions> options = {
- {
- .propId = GLOBAL_ON_CHANGE_PROP,
- .areaIds = {0},
- },
- {
- .propId = GLOBAL_CONTINUOUS_PROP,
- .areaIds = {0},
- .sampleRate = 1,
- },
- };
- auto status = getClient()->subscribe(getCallbackClient(), options, 0);
- ASSERT_TRUE(status.isOk()) << "subscribe failed: " << status.getMessage();
- std::vector<SetValueErrorEvent> errorEvents = {
- {
- .propId = GLOBAL_ON_CHANGE_PROP,
- .areaId = 0,
- .errorCode = StatusCode::INTERNAL_ERROR,
- },
- {
- .propId = GLOBAL_ON_CHANGE_PROP,
- .areaId = 0,
- .errorCode = StatusCode::ACCESS_DENIED,
- },
- {
- .propId = GLOBAL_CONTINUOUS_PROP,
- .areaId = 0,
- .errorCode = StatusCode::INVALID_ARG,
- },
- };
- std::vector<VehiclePropError> expectedResults = {
- {
- .propId = GLOBAL_ON_CHANGE_PROP,
- .areaId = 0,
- .errorCode = StatusCode::INTERNAL_ERROR,
- },
- {
- .propId = GLOBAL_ON_CHANGE_PROP,
- .areaId = 0,
- .errorCode = StatusCode::ACCESS_DENIED,
- },
- {
- .propId = GLOBAL_CONTINUOUS_PROP,
- .areaId = 0,
- .errorCode = StatusCode::INVALID_ARG,
- },
- };
- getHardware()->sendOnPropertySetErrorEvent(errorEvents);
-
- ASSERT_EQ(getCallback()->countOnPropertySetErrorResults(), 1u);
- auto maybeVehiclePropErrors = getCallback()->nextOnPropertySetErrorResults();
- ASSERT_TRUE(maybeVehiclePropErrors.has_value());
- const auto& vehiclePropErrors = maybeVehiclePropErrors.value();
- ASSERT_THAT(vehiclePropErrors.payloads, UnorderedElementsAreArray(expectedResults));
-}
-
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.cpp b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.cpp
index 75b8257..f51ce5c 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.cpp
@@ -16,6 +16,9 @@
#include "MockVehicleCallback.h"
+#include <android-base/thread_annotations.h>
+#include <chrono>
+
namespace android {
namespace hardware {
namespace automotive {
@@ -27,6 +30,7 @@
using ::aidl::android::hardware::automotive::vehicle::SetValueResults;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropErrors;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValues;
+using ::android::base::ScopedLockAssertion;
using ::ndk::ScopedAStatus;
using ::ndk::ScopedFileDescriptor;
@@ -46,26 +50,39 @@
} // namespace
ScopedAStatus MockVehicleCallback::onGetValues(const GetValueResults& results) {
- std::scoped_lock<std::mutex> lockGuard(mLock);
- return storeResults(results, &mGetValueResults);
+ ScopedAStatus result;
+ {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ result = storeResults(results, &mGetValueResults);
+ }
+ mCond.notify_all();
+ return result;
}
ScopedAStatus MockVehicleCallback::onSetValues(const SetValueResults& results) {
- std::scoped_lock<std::mutex> lockGuard(mLock);
- return storeResults(results, &mSetValueResults);
+ ScopedAStatus result;
+ {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ result = storeResults(results, &mSetValueResults);
+ }
+ mCond.notify_all();
+ return result;
}
ScopedAStatus MockVehicleCallback::onPropertyEvent(const VehiclePropValues& results,
int32_t sharedMemoryFileCount) {
- std::scoped_lock<std::mutex> lockGuard(mLock);
-
- mSharedMemoryFileCount = sharedMemoryFileCount;
- return storeResults(results, &mOnPropertyEventResults);
+ ScopedAStatus result;
+ {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mSharedMemoryFileCount = sharedMemoryFileCount;
+ result = storeResults(results, &mOnPropertyEventResults);
+ }
+ mCond.notify_all();
+ return result;
}
-ScopedAStatus MockVehicleCallback::onPropertySetError(const VehiclePropErrors& results) {
- std::scoped_lock<std::mutex> lockGuard(mLock);
- return storeResults(results, &mOnPropertySetErrorResults);
+ScopedAStatus MockVehicleCallback::onPropertySetError(const VehiclePropErrors&) {
+ return ScopedAStatus::ok();
}
std::optional<GetValueResults> MockVehicleCallback::nextGetValueResults() {
@@ -88,14 +105,20 @@
return mOnPropertyEventResults.size();
}
-std::optional<VehiclePropErrors> MockVehicleCallback::nextOnPropertySetErrorResults() {
- std::scoped_lock<std::mutex> lockGuard(mLock);
- return pop(mOnPropertySetErrorResults);
+bool MockVehicleCallback::waitForSetValueResults(size_t size, size_t timeoutInNano) {
+ std::unique_lock lk(mLock);
+ return mCond.wait_for(lk, std::chrono::nanoseconds(timeoutInNano), [this, size] {
+ ScopedLockAssertion lockAssertion(mLock);
+ return mSetValueResults.size() >= size;
+ });
}
-size_t MockVehicleCallback::countOnPropertySetErrorResults() {
- std::scoped_lock<std::mutex> lockGuard(mLock);
- return mOnPropertySetErrorResults.size();
+bool MockVehicleCallback::waitForGetValueResults(size_t size, size_t timeoutInNano) {
+ std::unique_lock lk(mLock);
+ return mCond.wait_for(lk, std::chrono::nanoseconds(timeoutInNano), [this, size] {
+ ScopedLockAssertion lockAssertion(mLock);
+ return mGetValueResults.size() >= size;
+ });
}
} // namespace vehicle
diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h
index 91dbb7e..f17b273 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h
+++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h
@@ -22,6 +22,7 @@
#include <aidl/android/hardware/automotive/vehicle/BnVehicleCallback.h>
#include <android-base/thread_annotations.h>
+#include <condition_variable>
#include <list>
#include <mutex>
#include <optional>
@@ -62,13 +63,13 @@
nextSetValueResults();
std::optional<aidl::android::hardware::automotive::vehicle::VehiclePropValues>
nextOnPropertyEventResults();
- size_t countOnPropertySetErrorResults();
- std::optional<aidl::android::hardware::automotive::vehicle::VehiclePropErrors>
- nextOnPropertySetErrorResults();
size_t countOnPropertyEventResults();
+ bool waitForSetValueResults(size_t size, size_t timeoutInNano);
+ bool waitForGetValueResults(size_t size, size_t timeoutInNano);
private:
std::mutex mLock;
+ std::condition_variable mCond;
std::list<aidl::android::hardware::automotive::vehicle::GetValueResults> mGetValueResults
GUARDED_BY(mLock);
std::list<aidl::android::hardware::automotive::vehicle::SetValueResults> mSetValueResults
@@ -76,8 +77,6 @@
std::list<aidl::android::hardware::automotive::vehicle::VehiclePropValues>
mOnPropertyEventResults GUARDED_BY(mLock);
int32_t mSharedMemoryFileCount GUARDED_BY(mLock);
- std::list<aidl::android::hardware::automotive::vehicle::VehiclePropErrors>
- mOnPropertySetErrorResults GUARDED_BY(mLock);
};
} // namespace vehicle
diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp
index ba0d33d..4df4e1a 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp
@@ -131,9 +131,8 @@
}
void MockVehicleHardware::registerOnPropertySetErrorEvent(
- std::unique_ptr<const PropertySetErrorCallback> callback) {
- std::scoped_lock<std::mutex> lockGuard(mLock);
- mPropertySetErrorCallback = std::move(callback);
+ std::unique_ptr<const PropertySetErrorCallback>) {
+ // TODO(b/200737967): mock this.
}
void MockVehicleHardware::setPropertyConfigs(const std::vector<VehiclePropConfig>& configs) {
@@ -255,12 +254,6 @@
std::list<std::vector<SetValueRequest>>* storedRequests,
std::list<std::vector<SetValueResult>>* storedResponses) const;
-void MockVehicleHardware::sendOnPropertySetErrorEvent(
- const std::vector<SetValueErrorEvent>& errorEvents) {
- std::scoped_lock<std::mutex> lockGuard(mLock);
- (*mPropertySetErrorCallback)(errorEvents);
-}
-
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h
index 46b30b9..743841c 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h
@@ -85,7 +85,6 @@
aidl::android::hardware::automotive::vehicle::StatusCode status);
void setSleepTime(int64_t timeInNano);
void setDumpResult(DumpResult result);
- void sendOnPropertySetErrorEvent(const std::vector<SetValueErrorEvent>& errorEvents);
private:
mutable std::mutex mLock;
@@ -105,7 +104,6 @@
mStatusByFunctions GUARDED_BY(mLock);
int64_t mSleepTime GUARDED_BY(mLock) = 0;
std::unique_ptr<const PropertyChangeCallback> mPropertyChangeCallback GUARDED_BY(mLock);
- std::unique_ptr<const PropertySetErrorCallback> mPropertySetErrorCallback GUARDED_BY(mLock);
std::function<aidl::android::hardware::automotive::vehicle::StatusCode(
std::shared_ptr<const GetValuesCallback>,
const std::vector<aidl::android::hardware::automotive::vehicle::GetValueRequest>&)>
diff --git a/automotive/vehicle/aidl/impl/vhal/test/SubscriptionManagerTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/SubscriptionManagerTest.cpp
index 3f59363..cb8c8d1 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/SubscriptionManagerTest.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/SubscriptionManagerTest.cpp
@@ -231,7 +231,7 @@
std::vector<SubscribeOptions> options = {{
.propId = 0,
.areaIds = {0},
- .sampleRate = 10.0,
+ .sampleRate = 100.0,
}};
auto result = getManager()->subscribe(getCallbackClient(), options, true);
@@ -240,11 +240,13 @@
result = getManager()->unsubscribe(getCallbackClient()->asBinder().get());
ASSERT_TRUE(result.ok()) << "failed to unsubscribe: " << result.error().message();
+ // Wait for the last events to come.
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
clearEvents();
- std::this_thread::sleep_for(std::chrono::milliseconds(200));
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
- // Theoretically trigger 10 times, but check for at least 9 times to be stable.
ASSERT_TRUE(getEvents().empty());
}
@@ -269,6 +271,9 @@
std::vector<int32_t>({0}));
ASSERT_TRUE(result.ok()) << "failed to unsubscribe: " << result.error().message();
+ // Wait for the last events to come.
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
clearEvents();
std::this_thread::sleep_for(std::chrono::seconds(1));
@@ -301,6 +306,9 @@
result = getManager()->unsubscribe(getCallbackClient()->asBinder().get());
ASSERT_TRUE(result.ok()) << "failed to unsubscribe: " << result.error().message();
+ // Wait for the last events to come.
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
clearEvents();
std::this_thread::sleep_for(std::chrono::seconds(1));
@@ -477,16 +485,16 @@
ASSERT_THAT(clients[getCallbackClient()], ElementsAre(&updatedValues[1]));
}
-TEST_F(SubscriptionManagerTest, testCheckSampleRateValid) {
- ASSERT_TRUE(SubscriptionManager::checkSampleRate(1.0));
+TEST_F(SubscriptionManagerTest, testCheckSampleRateHzValid) {
+ ASSERT_TRUE(SubscriptionManager::checkSampleRateHz(1.0));
}
-TEST_F(SubscriptionManagerTest, testCheckSampleRateInvalidTooSmall) {
- ASSERT_FALSE(SubscriptionManager::checkSampleRate(FLT_MIN));
+TEST_F(SubscriptionManagerTest, testCheckSampleRateHzInvalidTooSmall) {
+ ASSERT_FALSE(SubscriptionManager::checkSampleRateHz(FLT_MIN));
}
-TEST_F(SubscriptionManagerTest, testCheckSampleRateInvalidZero) {
- ASSERT_FALSE(SubscriptionManager::checkSampleRate(0));
+TEST_F(SubscriptionManagerTest, testCheckSampleRateHzInvalidZero) {
+ ASSERT_FALSE(SubscriptionManager::checkSampleRateHz(0));
}
} // namespace vehicle
diff --git a/automotive/vehicle/aidl/impl/vhal/vhal-default-service.xml b/automotive/vehicle/aidl/impl/vhal/vhal-default-service.xml
index 4d587ee..9834cdb 100644
--- a/automotive/vehicle/aidl/impl/vhal/vhal-default-service.xml
+++ b/automotive/vehicle/aidl/impl/vhal/vhal-default-service.xml
@@ -1,7 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.automotive.vehicle</name>
- <version>1</version>
+ <version>2</version>
<fqname>IVehicle/default</fqname>
</hal>
</manifest>