Merge changes from topic "move_conn_lib"
* changes:
Move VehicleHalProto out from vhal_v2_0.
Support set property in dump.
Support debug dump
Prevent log spam.
Optimize some code path to move instead of copy data.
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleHalProto.proto b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleHalProto.proto
deleted file mode 100644
index 58daca6..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleHalProto.proto
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2015 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 = "proto2";
-
-package vhal_proto;
-
-// CMD messages are from workstation --> VHAL
-// RESP messages are from VHAL --> workstation
-enum MsgType {
- GET_CONFIG_CMD = 0;
- GET_CONFIG_RESP = 1;
- GET_CONFIG_ALL_CMD = 2;
- GET_CONFIG_ALL_RESP = 3;
- GET_PROPERTY_CMD = 4;
- GET_PROPERTY_RESP = 5;
- GET_PROPERTY_ALL_CMD = 6;
- GET_PROPERTY_ALL_RESP = 7;
- SET_PROPERTY_CMD = 8;
- SET_PROPERTY_RESP = 9;
- SET_PROPERTY_ASYNC = 10;
- DEBUG_CMD = 11;
- DEBUG_RESP = 12;
-}
-enum Status {
- RESULT_OK = 0;
- ERROR_UNKNOWN = 1;
- ERROR_UNIMPLEMENTED_CMD = 2;
- ERROR_INVALID_PROPERTY = 3;
- ERROR_INVALID_AREA_ID = 4;
- ERROR_PROPERTY_UNINITIALIZED = 5;
- ERROR_WRITE_ONLY_PROPERTY = 6;
- ERROR_MEMORY_ALLOC_FAILED = 7;
- ERROR_INVALID_OPERATION = 8;
-}
-
-enum VehiclePropStatus {
- AVAILABLE = 0;
- UNAVAILABLE = 1;
- ERROR = 2;
-}
-
-message VehicleAreaConfig {
- required int32 area_id = 1;
- optional sint32 min_int32_value = 2;
- optional sint32 max_int32_value = 3;
- optional sint64 min_int64_value = 4;
- optional sint64 max_int64_value = 5;
- optional float min_float_value = 6;
- optional float max_float_value = 7;
-}
-
-message VehiclePropConfig {
- required int32 prop = 1;
- optional int32 access = 2;
- optional int32 change_mode = 3;
- optional int32 value_type = 4;
- optional int32 supported_areas = 5; // Deprecated - DO NOT USE
- repeated VehicleAreaConfig area_configs = 6;
- optional int32 config_flags = 7;
- repeated int32 config_array = 8;
- optional string config_string = 9;
- optional float min_sample_rate = 10;
- optional float max_sample_rate = 11;
-};
-
-message VehiclePropValue {
- // common data
- required int32 prop = 1;
- optional int32 value_type = 2;
- optional int64 timestamp = 3; // required for valid data from HAL, skipped for set
- optional VehiclePropStatus status = 10; // required for valid data from HAL, skipped for set
-
- // values
- optional int32 area_id = 4;
- repeated sint32 int32_values = 5; // this also covers boolean value.
- repeated sint64 int64_values = 6;
- repeated float float_values = 7;
- optional string string_value = 8;
- optional bytes bytes_value = 9;
-};
-
-// This structure is used to notify what values to get from the Vehicle HAL
-message VehiclePropGet {
- required int32 prop = 1;
- optional int32 area_id = 2;
-};
-
-message EmulatorMessage {
- required MsgType msg_type = 1;
- optional Status status = 2; // Only for RESP messages
- repeated VehiclePropGet prop = 3; // Provided for getConfig, getProperty commands
- repeated VehiclePropConfig config = 4;
- repeated VehiclePropValue value = 5;
- repeated string debug_commands = 6; // Required for debug command
- optional string debug_result = 7; // Required for debug RESP messages
-};
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 cab184b..1c45271 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
@@ -23,7 +23,9 @@
#include <IVehicleHardware.h>
#include <VehicleHalTypes.h>
#include <VehiclePropertyStore.h>
+#include <android-base/parseint.h>
#include <android-base/result.h>
+#include <android-base/stringprintf.h>
#include <android-base/thread_annotations.h>
#include <map>
@@ -37,7 +39,7 @@
namespace vehicle {
namespace fake {
-class FakeVehicleHardware final : public IVehicleHardware {
+class FakeVehicleHardware : public IVehicleHardware {
public:
FakeVehicleHardware();
@@ -78,13 +80,15 @@
void registerOnPropertySetErrorEvent(
std::unique_ptr<const PropertySetErrorCallback> callback) override;
+ protected:
+ // mValuePool is also used in mServerSidePropStore.
+ const std::shared_ptr<VehiclePropValuePool> mValuePool;
+ const std::shared_ptr<VehiclePropertyStore> mServerSidePropStore;
+
private:
// Expose private methods to unit test.
friend class FakeVehicleHardwareTestHelper;
- // mValuePool is also used in mServerSidePropStore.
- const std::shared_ptr<VehiclePropValuePool> mValuePool;
- const std::shared_ptr<VehiclePropertyStore> mServerSidePropStore;
const std::unique_ptr<obd2frame::FakeObd2Frame> mFakeObd2Frame;
const std::unique_ptr<FakeUserHal> mFakeUserHal;
std::mutex mCallbackLock;
@@ -120,6 +124,35 @@
::android::base::Result<VehiclePropValuePool::RecyclableType> getUserHalProp(
const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const;
bool isHvacPropAndHvacNotAvailable(int32_t propId);
+
+ std::string dumpAllProperties();
+ std::string dumpOnePropertyByConfig(
+ int rowNumber,
+ const ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig& config);
+ std::string dumpOnePropertyById(int32_t propId, int32_t areaId);
+ std::string dumpHelp();
+ std::string dumpListProperties();
+ std::string dumpSpecificProperty(const std::vector<std::string>& options);
+ std::string dumpSetProperties(const std::vector<std::string>& options);
+
+ template <typename T>
+ ::android::base::Result<T> safelyParseInt(int index, const std::string& s) {
+ T out;
+ if (!::android::base::ParseInt(s, &out)) {
+ return ::android::base::Error() << ::android::base::StringPrintf(
+ "non-integer argument at index %d: %s\n", index, s.c_str());
+ }
+ return out;
+ }
+ ::android::base::Result<float> safelyParseFloat(int index, const std::string& s);
+ 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);
+ ::android::base::Result<std::vector<uint8_t>> parseHexString(const std::string& s);
+
+ ::android::base::Result<void> checkArgumentsSize(const std::vector<std::string>& options,
+ size_t minSize);
};
} // 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 e75f0e7..9660793 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+#define LOG_TAG "FakeVehicleHardware"
+#define FAKE_VEHICLEHARDWARE_DEBUG false // STOPSHIP if true.
+
#include "FakeVehicleHardware.h"
#include <DefaultConfig.h>
@@ -22,7 +25,9 @@
#include <PropertyUtils.h>
#include <VehicleHalTypes.h>
#include <VehicleUtils.h>
+#include <android-base/parsedouble.h>
#include <android-base/properties.h>
+#include <android-base/strings.h>
#include <utils/Log.h>
#include <utils/SystemClock.h>
@@ -56,12 +61,31 @@
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+using ::android::base::EqualsIgnoreCase;
using ::android::base::Error;
+using ::android::base::ParseFloat;
using ::android::base::Result;
+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";
+// A list of supported options for "--set" command.
+const std::unordered_set<std::string> SET_PROP_OPTIONS = {
+ // integer.
+ "-i",
+ // 64bit integer.
+ "-i64",
+ // float.
+ "-f",
+ // string.
+ "-s",
+ // bytes in hex format, e.g. 0xDEADBEEF.
+ "-b",
+ // Area id in integer.
+ "-a"};
+
} // namespace
void FakeVehicleHardware::storePropInitialValue(const defaultconfig::ConfigDeclaration& config) {
@@ -387,7 +411,9 @@
const VehiclePropValue& value = request.value;
int propId = value.prop;
- ALOGD("Set value for property ID: %d", propId);
+ if (FAKE_VEHICLEHARDWARE_DEBUG) {
+ ALOGD("Set value for property ID: %d", propId);
+ }
SetValueResult setValueResult;
setValueResult.requestId = request.requestId;
@@ -434,7 +460,10 @@
std::vector<GetValueResult> results;
for (auto& request : requests) {
const VehiclePropValue& value = request.prop;
- ALOGD("getValues(%d)", value.prop);
+
+ if (FAKE_VEHICLEHARDWARE_DEBUG) {
+ ALOGD("getValues(%d)", value.prop);
+ }
GetValueResult getValueResult;
getValueResult.requestId = request.requestId;
@@ -476,14 +505,290 @@
return StatusCode::OK;
}
-DumpResult FakeVehicleHardware::dump(const std::vector<std::string>&) {
+DumpResult FakeVehicleHardware::dump(const std::vector<std::string>& options) {
DumpResult result;
- // TODO(b/201830716): Implement this.
+ result.callerShouldDumpState = false;
+ if (options.size() == 0) {
+ // We only want caller to dump default state when there is no options.
+ result.callerShouldDumpState = true;
+ result.buffer = dumpAllProperties();
+ return result;
+ }
+ std::string option = options[0];
+ if (EqualsIgnoreCase(option, "--help")) {
+ result.buffer = dumpHelp();
+ return result;
+ } else if (EqualsIgnoreCase(option, "--list")) {
+ result.buffer = dumpListProperties();
+ } else if (EqualsIgnoreCase(option, "--get")) {
+ result.buffer = dumpSpecificProperty(options);
+ } else if (EqualsIgnoreCase(option, "--set")) {
+ result.buffer = dumpSetProperties(options);
+ } else {
+ result.buffer = StringPrintf("Invalid option: %s\n", option.c_str());
+ }
return result;
}
+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. "
+ "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";
+}
+
+std::string FakeVehicleHardware::dumpAllProperties() {
+ auto configs = mServerSidePropStore->getAllConfigs();
+ if (configs.size() == 0) {
+ return "no properties to dump\n";
+ }
+ std::string msg = StringPrintf("dumping %zu properties\n", configs.size());
+ int rowNumber = 1;
+ for (const VehiclePropConfig& config : configs) {
+ msg += dumpOnePropertyByConfig(rowNumber++, config);
+ }
+ return msg;
+}
+
+std::string FakeVehicleHardware::dumpOnePropertyByConfig(int rowNumber,
+ const VehiclePropConfig& config) {
+ size_t numberAreas = config.areaConfigs.size();
+ std::string msg = "";
+ if (numberAreas == 0) {
+ msg += StringPrintf("%d: ", rowNumber);
+ msg += dumpOnePropertyById(config.prop, /* areaId= */ 0);
+ return msg;
+ }
+ for (size_t j = 0; j < numberAreas; ++j) {
+ if (numberAreas > 1) {
+ msg += StringPrintf("%d-%zu: ", rowNumber, j);
+ } else {
+ msg += StringPrintf("%d: ", rowNumber);
+ }
+ msg += dumpOnePropertyById(config.prop, config.areaConfigs[j].areaId);
+ }
+ return msg;
+}
+
+std::string FakeVehicleHardware::dumpOnePropertyById(int32_t propId, int32_t areaId) {
+ VehiclePropValue value = {
+ .prop = propId,
+ .areaId = areaId,
+ };
+ bool isSpecialValue = false;
+ auto result = maybeGetSpecialValue(value, &isSpecialValue);
+ if (!isSpecialValue) {
+ result = mServerSidePropStore->readValue(value);
+ }
+ if (!result.ok()) {
+ return StringPrintf("failed to read property value: %d, error: %s, code: %d\n", propId,
+ getErrorMsg(result).c_str(), getIntErrorCode(result));
+
+ } else {
+ return result.value()->toString() + "\n";
+ }
+}
+
+std::string FakeVehicleHardware::dumpListProperties() {
+ auto configs = mServerSidePropStore->getAllConfigs();
+ if (configs.size() == 0) {
+ return "no properties to list\n";
+ }
+ int rowNumber = 1;
+ std::string msg = StringPrintf("listing %zu properties\n", configs.size());
+ for (const auto& config : configs) {
+ msg += StringPrintf("%d: %d\n", rowNumber++, config.prop);
+ }
+ return msg;
+}
+
+Result<void> FakeVehicleHardware::checkArgumentsSize(const std::vector<std::string>& options,
+ size_t minSize) {
+ size_t size = options.size();
+ if (size >= minSize) {
+ return {};
+ }
+ return Error() << StringPrintf("Invalid number of arguments: required at least %zu, got %zu\n",
+ minSize, size);
+}
+
+std::string FakeVehicleHardware::dumpSpecificProperty(const std::vector<std::string>& options) {
+ if (auto result = checkArgumentsSize(options, /*minSize=*/2); !result.ok()) {
+ return getErrorMsg(result);
+ }
+
+ // options[0] is the command itself...
+ int rowNumber = 1;
+ size_t size = options.size();
+ std::string msg = "";
+ for (size_t i = 1; i < size; ++i) {
+ auto propResult = safelyParseInt<int32_t>(i, options[i]);
+ if (!propResult.ok()) {
+ msg += getErrorMsg(propResult);
+ continue;
+ }
+ int32_t prop = propResult.value();
+ auto result = mServerSidePropStore->getConfig(prop);
+ if (!result.ok()) {
+ msg += StringPrintf("No property %d\n", prop);
+ continue;
+ }
+ msg += dumpOnePropertyByConfig(rowNumber++, *result.value());
+ }
+ return msg;
+}
+
+std::vector<std::string> FakeVehicleHardware::getOptionValues(
+ const std::vector<std::string>& options, size_t* index) {
+ std::vector<std::string> values;
+ while (*index < options.size()) {
+ std::string option = options[*index];
+ if (SET_PROP_OPTIONS.find(option) != SET_PROP_OPTIONS.end()) {
+ return std::move(values);
+ }
+ values.push_back(option);
+ (*index)++;
+ }
+ return std::move(values);
+}
+
+Result<VehiclePropValue> FakeVehicleHardware::parseSetPropOptions(
+ 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]
+ size_t optionIndex = 1;
+ auto result = safelyParseInt<int32_t>(optionIndex, options[optionIndex]);
+ if (!result.ok()) {
+ return Error() << StringPrintf("Property value: \"%s\" is not a valid int: %s\n",
+ options[optionIndex].c_str(), getErrorMsg(result).c_str());
+ }
+ VehiclePropValue prop = {};
+ prop.prop = result.value();
+ prop.status = VehiclePropertyStatus::AVAILABLE;
+ optionIndex++;
+ std::unordered_set<std::string> parsedOptions;
+
+ while (optionIndex < options.size()) {
+ std::string type = 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());
+ }
+ parsedOptions.insert(type);
+ if (EqualsIgnoreCase(type, "-i")) {
+ if (values.size() == 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]);
+ if (!int32Result.ok()) {
+ return Error()
+ << StringPrintf("Value: \"%s\" is not a valid int: %s\n",
+ values[i].c_str(), getErrorMsg(int32Result).c_str());
+ }
+ prop.value.int32Values[i] = int32Result.value();
+ }
+ } else if (EqualsIgnoreCase(type, "-i64")) {
+ if (values.size() == 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]);
+ if (!int64Result.ok()) {
+ return Error()
+ << StringPrintf("Value: \"%s\" is not a valid int64: %s\n",
+ values[i].c_str(), getErrorMsg(int64Result).c_str());
+ }
+ prop.value.int64Values[i] = int64Result.value();
+ }
+ } else if (EqualsIgnoreCase(type, "-f")) {
+ if (values.size() == 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]);
+ if (!floatResult.ok()) {
+ return Error()
+ << StringPrintf("Value: \"%s\" is not a valid float: %s\n",
+ values[i].c_str(), getErrorMsg(floatResult).c_str());
+ }
+ prop.value.floatValues[i] = floatResult.value();
+ }
+ } else if (EqualsIgnoreCase(type, "-s")) {
+ if (values.size() != 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) {
+ return Error() << "Expect exact one value when using \"-b\"\n";
+ }
+ auto bytesResult = parseHexString(values[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());
+ }
+ prop.value.byteValues = std::move(bytesResult.value());
+ } else if (EqualsIgnoreCase(type, "-a")) {
+ if (values.size() != 1) {
+ return Error() << "Expect exact one value when using \"-a\"\n";
+ }
+ auto int32Result = safelyParseInt<int32_t>(currentIndex, values[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());
+ }
+ prop.areaId = int32Result.value();
+ } else {
+ return Error() << StringPrintf("Unknown option: %s\n", type.c_str());
+ }
+ }
+
+ return prop;
+}
+
+std::string FakeVehicleHardware::dumpSetProperties(const std::vector<std::string>& options) {
+ if (auto result = checkArgumentsSize(options, 3); !result.ok()) {
+ return getErrorMsg(result);
+ }
+
+ auto parseResult = parseSetPropOptions(options);
+ if (!parseResult.ok()) {
+ return getErrorMsg(parseResult);
+ }
+ VehiclePropValue prop = std::move(parseResult.value());
+ ALOGD("Dump: Setting property: %s", prop.toString().c_str());
+
+ bool isSpecialValue = false;
+ auto setResult = maybeSetSpecialValue(prop, &isSpecialValue);
+
+ if (!isSpecialValue) {
+ auto updatedValue = mValuePool->obtain(prop);
+ updatedValue->timestamp = elapsedRealtimeNano();
+ setResult = mServerSidePropStore->writeValue(std::move(updatedValue));
+ }
+
+ if (setResult.ok()) {
+ return StringPrintf("Set property: %s\n", prop.toString().c_str());
+ }
+ return StringPrintf("failed to set property: %s, error: %s\n", prop.toString().c_str(),
+ getErrorMsg(setResult).c_str());
+}
+
StatusCode FakeVehicleHardware::checkHealth() {
- // TODO(b/201830716): Implement this.
+ // Always return OK for checkHealth.
return StatusCode::OK;
}
@@ -544,6 +849,49 @@
}
}
+Result<float> FakeVehicleHardware::safelyParseFloat(int index, const std::string& s) {
+ float out;
+ if (!ParseFloat(s, &out)) {
+ return Error() << StringPrintf("non-float argument at index %d: %s\n", index, s.c_str());
+ }
+ return out;
+}
+
+Result<std::vector<uint8_t>> FakeVehicleHardware::parseHexString(const std::string& s) {
+ std::vector<uint8_t> bytes;
+ if (s.size() % 2 != 0) {
+ return Error() << StringPrintf("invalid hex string: %s, should have even size\n",
+ s.c_str());
+ }
+ if (!StartsWith(s, "0x")) {
+ return Error() << StringPrintf("hex string should start with \"0x\", got %s\n", s.c_str());
+ }
+ std::string subs = s.substr(2);
+ std::transform(subs.begin(), subs.end(), subs.begin(),
+ [](unsigned char c) { return std::tolower(c); });
+
+ bool highDigit = true;
+ for (size_t i = 0; i < subs.size(); i++) {
+ char c = subs[i];
+ uint8_t v;
+ if (c >= '0' && c <= '9') {
+ v = c - '0';
+ } else if (c >= 'a' && c <= 'f') {
+ v = c - 'a' + 10;
+ } else {
+ return Error() << StringPrintf("invalid character %c in hex string %s\n", c,
+ subs.c_str());
+ }
+ if (highDigit) {
+ bytes.push_back(v * 16);
+ } else {
+ bytes[bytes.size() - 1] += v;
+ }
+ highDigit = !highDigit;
+ }
+ return bytes;
+}
+
} // namespace fake
} // namespace vehicle
} // namespace automotive
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 970d044..0812c2a 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
@@ -24,6 +24,7 @@
#include <android-base/expected.h>
#include <android-base/file.h>
+#include <android-base/stringprintf.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <utils/Log.h>
@@ -52,13 +53,16 @@
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
using ::android::base::expected;
+using ::android::base::StringPrintf;
using ::android::base::unexpected;
using ::testing::ContainerEq;
+using ::testing::ContainsRegex;
using ::testing::Eq;
using ::testing::IsSubsetOf;
using ::testing::WhenSortedBy;
constexpr int INVALID_PROP_ID = 0;
+constexpr char CAR_MAKE[] = "Default Car";
} // namespace
@@ -1203,6 +1207,261 @@
}));
}
+TEST_F(FakeVehicleHardwareTest, testDumpAllProperties) {
+ std::vector<std::string> options;
+ DumpResult result = getHardware()->dump(options);
+ ASSERT_TRUE(result.callerShouldDumpState);
+ ASSERT_NE(result.buffer, "");
+ ASSERT_THAT(result.buffer, ContainsRegex("dumping .+ properties"));
+}
+
+TEST_F(FakeVehicleHardwareTest, testDumpHelp) {
+ std::vector<std::string> options;
+ options.push_back("--help");
+ DumpResult result = getHardware()->dump(options);
+ ASSERT_FALSE(result.callerShouldDumpState);
+ ASSERT_NE(result.buffer, "");
+ ASSERT_THAT(result.buffer, ContainsRegex("Usage: "));
+}
+
+TEST_F(FakeVehicleHardwareTest, testDumpListProperties) {
+ std::vector<std::string> options;
+ options.push_back("--list");
+ DumpResult result = getHardware()->dump(options);
+ ASSERT_FALSE(result.callerShouldDumpState);
+ ASSERT_NE(result.buffer, "");
+ ASSERT_THAT(result.buffer, ContainsRegex("listing .+ properties"));
+}
+
+TEST_F(FakeVehicleHardwareTest, testDumpSpecificProperties) {
+ std::vector<std::string> options;
+ options.push_back("--get");
+ std::string prop1 = std::to_string(toInt(VehicleProperty::INFO_FUEL_CAPACITY));
+ std::string prop2 = std::to_string(toInt(VehicleProperty::TIRE_PRESSURE));
+ options.push_back(prop1);
+ options.push_back(prop2);
+ DumpResult result = getHardware()->dump(options);
+ ASSERT_FALSE(result.callerShouldDumpState);
+ ASSERT_NE(result.buffer, "");
+ ASSERT_THAT(result.buffer,
+ ContainsRegex(StringPrintf("1:.*prop: %s.*\n2-0:.*prop: %s.*\n2-1:.*prop: %s.*\n",
+ prop1.c_str(), prop2.c_str(), prop2.c_str())));
+}
+
+TEST_F(FakeVehicleHardwareTest, testDumpSpecificPropertiesInvalidProp) {
+ std::vector<std::string> options;
+ options.push_back("--get");
+ std::string prop1 = std::to_string(toInt(VehicleProperty::INFO_FUEL_CAPACITY));
+ std::string prop2 = std::to_string(INVALID_PROP_ID);
+ options.push_back(prop1);
+ options.push_back(prop2);
+ DumpResult result = getHardware()->dump(options);
+ ASSERT_FALSE(result.callerShouldDumpState);
+ ASSERT_NE(result.buffer, "");
+ ASSERT_THAT(result.buffer, ContainsRegex(StringPrintf("1:.*prop: %s.*\nNo property %d\n",
+ prop1.c_str(), INVALID_PROP_ID)));
+}
+
+TEST_F(FakeVehicleHardwareTest, testDumpSpecificPropertiesNoArg) {
+ std::vector<std::string> options;
+ options.push_back("--get");
+
+ // No arguments.
+ DumpResult result = getHardware()->dump(options);
+ ASSERT_FALSE(result.callerShouldDumpState);
+ ASSERT_NE(result.buffer, "");
+ ASSERT_THAT(result.buffer, ContainsRegex("Invalid number of arguments"));
+}
+
+TEST_F(FakeVehicleHardwareTest, testDumpInvalidOptions) {
+ std::vector<std::string> options;
+ options.push_back("--invalid");
+
+ DumpResult result = getHardware()->dump(options);
+ ASSERT_FALSE(result.callerShouldDumpState);
+ ASSERT_NE(result.buffer, "");
+ ASSERT_THAT(result.buffer, ContainsRegex("Invalid option: --invalid"));
+}
+
+struct SetPropTestCase {
+ std::string test_name;
+ std::vector<std::string> options;
+ bool success;
+ std::string errorMsg = "";
+};
+
+class FakeVehicleHardwareSetPropTest : public FakeVehicleHardwareTest,
+ public testing::WithParamInterface<SetPropTestCase> {};
+
+TEST_P(FakeVehicleHardwareSetPropTest, cmdSetOneProperty) {
+ const SetPropTestCase& tc = GetParam();
+
+ DumpResult result = getHardware()->dump(tc.options);
+ ASSERT_FALSE(result.callerShouldDumpState);
+ ASSERT_NE(result.buffer, "");
+ if (tc.success) {
+ ASSERT_THAT(result.buffer, ContainsRegex("Set property:"));
+ } else {
+ ASSERT_THAT(result.buffer, ContainsRegex(tc.errorMsg));
+ }
+}
+
+std::vector<SetPropTestCase> GenSetPropParams() {
+ std::string infoMakeProperty = std::to_string(toInt(VehicleProperty::INFO_MAKE));
+ return {
+ {"success_set_string", {"--set", infoMakeProperty, "-s", CAR_MAKE}, true},
+ {"success_set_bytes", {"--set", infoMakeProperty, "-b", "0xdeadbeef"}, true},
+ {"success_set_bytes_caps", {"--set", infoMakeProperty, "-b", "0xDEADBEEF"}, true},
+ {"success_set_int", {"--set", infoMakeProperty, "-i", "2147483647"}, true},
+ {"success_set_ints",
+ {"--set", infoMakeProperty, "-i", "2147483647", "0", "-2147483648"},
+ true},
+ {"success_set_int64",
+ {"--set", infoMakeProperty, "-i64", "-9223372036854775808"},
+ true},
+ {"success_set_int64s",
+ {"--set", infoMakeProperty, "-i64", "-9223372036854775808", "0",
+ "9223372036854775807"},
+ true},
+ {"success_set_float", {"--set", infoMakeProperty, "-f", "1.175494351E-38"}, true},
+ {"success_set_floats",
+ {"--set", infoMakeProperty, "-f", "-3.402823466E+38", "0", "3.402823466E+38"},
+ true},
+ {"success_set_area", {"--set", infoMakeProperty, "-a", "2147483647"}, true},
+ {"fail_no_options", {"--set", infoMakeProperty}, false, "Invalid number of arguments"},
+ {"fail_less_than_4_options",
+ {"--set", infoMakeProperty, "-i"},
+ false,
+ "No values specified"},
+ {"fail_unknown_options", {"--set", infoMakeProperty, "-abcd"}, false, "Unknown option"},
+ {"fail_invalid_property",
+ {"--set", "not valid", "-s", CAR_MAKE},
+ false,
+ "not a valid int"},
+ {"fail_duplicate_string",
+ {"--set", infoMakeProperty, "-s", CAR_MAKE, "-s", CAR_MAKE},
+ false,
+ "Duplicate \"-s\" options"},
+ {"fail_multiple_strings",
+ {"--set", infoMakeProperty, "-s", CAR_MAKE, CAR_MAKE},
+ false,
+ "Expect exact one value"},
+ {"fail_no_string_value",
+ {"--set", infoMakeProperty, "-s", "-a", "1234"},
+ false,
+ "Expect exact one value"},
+ {"fail_duplicate_bytes",
+ {"--set", infoMakeProperty, "-b", "0xdeadbeef", "-b", "0xdeadbeef"},
+ false,
+ "Duplicate \"-b\" options"},
+ {"fail_multiple_bytes",
+ {"--set", infoMakeProperty, "-b", "0xdeadbeef", "0xdeadbeef"},
+ false,
+ "Expect exact one value"},
+ {"fail_invalid_bytes",
+ {"--set", infoMakeProperty, "-b", "0xgood"},
+ false,
+ "not a valid hex string"},
+ {"fail_invalid_bytes_no_prefix",
+ {"--set", infoMakeProperty, "-b", "deadbeef"},
+ false,
+ "not a valid hex string"},
+ {"fail_invalid_int",
+ {"--set", infoMakeProperty, "-i", "abc"},
+ false,
+ "not a valid int"},
+ {"fail_int_out_of_range",
+ {"--set", infoMakeProperty, "-i", "2147483648"},
+ false,
+ "not a valid int"},
+ {"fail_no_int_value",
+ {"--set", infoMakeProperty, "-i", "-s", CAR_MAKE},
+ false,
+ "No values specified"},
+ {"fail_invalid_int64",
+ {"--set", infoMakeProperty, "-i64", "abc"},
+ false,
+ "not a valid int64"},
+ {"fail_int64_out_of_range",
+ {"--set", infoMakeProperty, "-i64", "-9223372036854775809"},
+ false,
+ "not a valid int64"},
+ {"fail_no_int64_value",
+ {"--set", infoMakeProperty, "-i64", "-s", CAR_MAKE},
+ false,
+ "No values specified"},
+ {"fail_invalid_float",
+ {"--set", infoMakeProperty, "-f", "abc"},
+ false,
+ "not a valid float"},
+ {"fail_float_out_of_range",
+ {"--set", infoMakeProperty, "-f", "-3.402823466E+39"},
+ false,
+ "not a valid float"},
+ {"fail_no_float_value",
+ {"--set", infoMakeProperty, "-f", "-s", CAR_MAKE},
+ false,
+ "No values specified"},
+ {"fail_multiple_areas",
+ {"--set", infoMakeProperty, "-a", "2147483648", "0"},
+ false,
+ "Expect exact one value"},
+ {"fail_invalid_area",
+ {"--set", infoMakeProperty, "-a", "abc"},
+ false,
+ "not a valid int"},
+ {"fail_area_out_of_range",
+ {"--set", infoMakeProperty, "-a", "2147483648"},
+ false,
+ "not a valid int"},
+ {"fail_no_area_value",
+ {"--set", infoMakeProperty, "-a", "-s", CAR_MAKE},
+ false,
+ "Expect exact one value"},
+ };
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ FakeVehicleHardwareSetPropTests, FakeVehicleHardwareSetPropTest,
+ testing::ValuesIn(GenSetPropParams()),
+ [](const testing::TestParamInfo<FakeVehicleHardwareSetPropTest::ParamType>& info) {
+ return info.param.test_name;
+ });
+
+TEST_F(FakeVehicleHardwareTest, SetComplexPropTest) {
+ std::string infoMakeProperty = std::to_string(toInt(VehicleProperty::INFO_MAKE));
+ getHardware()->dump({"--set", infoMakeProperty, "-s", CAR_MAKE,
+ "-b", "0xdeadbeef", "-i", "2147483647",
+ "0", "-2147483648", "-i64", "-9223372036854775808",
+ "0", "9223372036854775807", "-f", "-3.402823466E+38",
+ "0", "3.402823466E+38", "-a", "123"});
+ VehiclePropValue requestProp;
+ requestProp.prop = toInt(VehicleProperty::INFO_MAKE);
+ requestProp.areaId = 123;
+ auto result = getValue(requestProp);
+ ASSERT_TRUE(result.ok());
+ VehiclePropValue value = result.value();
+ ASSERT_EQ(value.prop, toInt(VehicleProperty::INFO_MAKE));
+ ASSERT_EQ(value.areaId, 123);
+ ASSERT_STREQ(CAR_MAKE, value.value.stringValue.c_str());
+ uint8_t bytes[] = {0xde, 0xad, 0xbe, 0xef};
+ ASSERT_FALSE(memcmp(bytes, value.value.byteValues.data(), sizeof(bytes)));
+ ASSERT_EQ(3u, value.value.int32Values.size());
+ ASSERT_EQ(2147483647, value.value.int32Values[0]);
+ ASSERT_EQ(0, value.value.int32Values[1]);
+ ASSERT_EQ(-2147483648, value.value.int32Values[2]);
+ ASSERT_EQ(3u, value.value.int64Values.size());
+ // -9223372036854775808 is not a valid literal since '-' and '9223372036854775808' would be two
+ // tokens and the later does not fit in unsigned long long.
+ ASSERT_EQ(-9223372036854775807 - 1, value.value.int64Values[0]);
+ ASSERT_EQ(0, value.value.int64Values[1]);
+ ASSERT_EQ(9223372036854775807, value.value.int64Values[2]);
+ ASSERT_EQ(3u, value.value.floatValues.size());
+ ASSERT_EQ(-3.402823466E+38f, value.value.floatValues[0]);
+ ASSERT_EQ(0.0f, value.value.floatValues[1]);
+ ASSERT_EQ(3.402823466E+38f, value.value.floatValues[2]);
+}
+
} // namespace fake
} // namespace vehicle
} // namespace automotive
diff --git a/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h b/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
index 833707a..15a6278 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
@@ -79,7 +79,7 @@
GetSetValuesClient(std::shared_ptr<PendingRequestPool> requestPool, CallbackType callback);
// Sends the results to this client.
- void sendResults(const std::vector<ResultType>& results);
+ void sendResults(std::vector<ResultType>&& results);
// Sends each result separately to this client. Each result would be sent through one callback
// invocation.
diff --git a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
index 62b2627..5e7adfc 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
@@ -39,13 +39,6 @@
namespace automotive {
namespace vehicle {
-// private namespace
-namespace defaultvehiclehal_impl {
-
-constexpr int INVALID_MEMORY_FD = -1;
-
-} // namespace defaultvehiclehal_impl
-
class DefaultVehicleHal final : public ::aidl::android::hardware::automotive::vehicle::BnVehicle {
public:
using CallbackType =
@@ -79,6 +72,7 @@
const std::vector<int32_t>& propIds) override;
::ndk::ScopedAStatus returnSharedMemory(const CallbackType& callback,
int64_t sharedMemoryId) override;
+ binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
IVehicleHardware* getHardware();
@@ -215,6 +209,8 @@
void monitorBinderLifeCycle(const CallbackType& callback);
+ bool checkDumpPermission();
+
template <class T>
static std::shared_ptr<T> getOrCreateClient(
std::unordered_map<const AIBinder*, std::shared_ptr<T>>* clients,
diff --git a/automotive/vehicle/aidl/impl/vhal/include/ParcelableUtils.h b/automotive/vehicle/aidl/impl/vhal/include/ParcelableUtils.h
index 4b7c2f3..7b2111b 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/ParcelableUtils.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/ParcelableUtils.h
@@ -29,6 +29,9 @@
namespace automotive {
namespace vehicle {
+// Turns the values into a stable large parcelable that could be sent via binder.
+// If values is small enough, it would be put into output.payloads, otherwise a shared memory file
+// would be created and output.sharedMemoryFd would be filled in.
template <class T1, class T2>
::ndk::ScopedAStatus vectorToStableLargeParcelable(std::vector<T1>&& values, T2* output) {
output->payloads = std::move(values);
@@ -44,6 +47,9 @@
// 'sharedMemoryFd' field.
output->payloads.clear();
output->sharedMemoryFd = std::move(*fd);
+ } else {
+ output->sharedMemoryFd = ::ndk::ScopedFileDescriptor();
+ // Do not modify payloads.
}
return ::ndk::ScopedAStatus::ok();
}
diff --git a/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp b/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
index 5ccef55..098bfee 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
@@ -84,9 +84,9 @@
// Send all the GetValue/SetValue results through callback in a single callback invocation.
template <class ResultType, class ResultsType>
void sendGetOrSetValueResults(std::shared_ptr<IVehicleCallback> callback,
- const std::vector<ResultType>& results) {
+ std::vector<ResultType>&& results) {
ResultsType parcelableResults;
- ScopedAStatus status = vectorToStableLargeParcelable(results, &parcelableResults);
+ ScopedAStatus status = vectorToStableLargeParcelable(std::move(results), &parcelableResults);
if (status.isOk()) {
if (ScopedAStatus callbackStatus = callCallback(callback, parcelableResults);
!callbackStatus.isOk()) {
@@ -99,7 +99,8 @@
ALOGE("failed to marshal result into large parcelable, error: "
"%s, code: %d",
status.getMessage(), statusCode);
- sendGetOrSetValueResultsSeparately<ResultType, ResultsType>(callback, results);
+ sendGetOrSetValueResultsSeparately<ResultType, ResultsType>(callback,
+ parcelableResults.payloads);
}
// The timeout callback for GetValues/SetValues.
@@ -115,7 +116,7 @@
.status = StatusCode::TRY_AGAIN,
});
}
- sendGetOrSetValueResults<ResultType, ResultsType>(callback, timeoutResults);
+ sendGetOrSetValueResults<ResultType, ResultsType>(callback, std::move(timeoutResults));
}
// The on-results callback for GetValues/SetValues.
@@ -123,7 +124,7 @@
void getOrSetValuesCallback(
const void* clientId,
std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback> callback,
- std::vector<ResultType> results, std::shared_ptr<PendingRequestPool> requestPool) {
+ std::vector<ResultType>&& results, std::shared_ptr<PendingRequestPool> requestPool) {
std::unordered_set<int64_t> requestIds;
for (const auto& result : results) {
requestIds.insert(result.requestId);
@@ -145,7 +146,7 @@
}
if (!results.empty()) {
- sendGetOrSetValueResults<ResultType, ResultsType>(callback, results);
+ sendGetOrSetValueResults<ResultType, ResultsType>(callback, std::move(results));
}
}
@@ -156,9 +157,9 @@
std::shared_ptr<IVehicleCallback> callback, const SetValueResult& result);
template void sendGetOrSetValueResults<GetValueResult, GetValueResults>(
- std::shared_ptr<IVehicleCallback> callback, const std::vector<GetValueResult>& results);
+ std::shared_ptr<IVehicleCallback> callback, std::vector<GetValueResult>&& results);
template void sendGetOrSetValueResults<SetValueResult, SetValueResults>(
- std::shared_ptr<IVehicleCallback> callback, const std::vector<SetValueResult>& results);
+ std::shared_ptr<IVehicleCallback> callback, std::vector<SetValueResult>&& results);
template void sendGetOrSetValueResultsSeparately<GetValueResult, GetValueResults>(
std::shared_ptr<IVehicleCallback> callback, const std::vector<GetValueResult>& results);
@@ -175,11 +176,11 @@
template void getOrSetValuesCallback<GetValueResult, GetValueResults>(
const void* clientId,
std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback> callback,
- std::vector<GetValueResult> results, std::shared_ptr<PendingRequestPool> requestPool);
+ std::vector<GetValueResult>&& results, std::shared_ptr<PendingRequestPool> requestPool);
template void getOrSetValuesCallback<SetValueResult, SetValueResults>(
const void* clientId,
std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback> callback,
- std::vector<SetValueResult> results, std::shared_ptr<PendingRequestPool> requestPool);
+ std::vector<SetValueResult>&& results, std::shared_ptr<PendingRequestPool> requestPool);
} // namespace
@@ -230,9 +231,8 @@
}
template <class ResultType, class ResultsType>
-void GetSetValuesClient<ResultType, ResultsType>::sendResults(
- const std::vector<ResultType>& results) {
- return sendGetOrSetValueResults<ResultType, ResultsType>(mCallback, results);
+void GetSetValuesClient<ResultType, ResultsType>::sendResults(std::vector<ResultType>&& results) {
+ return sendGetOrSetValueResults<ResultType, ResultsType>(mCallback, std::move(results));
}
template <class ResultType, class ResultsType>
@@ -283,7 +283,8 @@
// TODO(b/205189110): Use memory pool here and fill in sharedMemoryId.
VehiclePropValues vehiclePropValues;
int32_t sharedMemoryFileCount = 0;
- ScopedAStatus status = vectorToStableLargeParcelable(updatedValues, &vehiclePropValues);
+ ScopedAStatus status =
+ vectorToStableLargeParcelable(std::move(updatedValues), &vehiclePropValues);
if (!status.isOk()) {
int statusCode = status.getServiceSpecificError();
ALOGE("subscribe: failed to marshal result into large parcelable, error: "
diff --git a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
index 3e088c5..c0a66da 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
@@ -24,6 +24,8 @@
#include <android-base/result.h>
#include <android-base/stringprintf.h>
+#include <android/binder_ibinder.h>
+#include <private/android_filesystem_config.h>
#include <utils/Log.h>
#include <utils/SystemClock.h>
@@ -387,7 +389,7 @@
if (!failedResults.empty()) {
// First send the failed results we already know back to the client.
- client->sendResults(failedResults);
+ client->sendResults(std::move(failedResults));
}
if (hardwareRequests.empty()) {
@@ -476,7 +478,7 @@
if (!failedResults.empty()) {
// First send the failed results we already know back to the client.
- client->sendResults(failedResults);
+ client->sendResults(std::move(failedResults));
}
if (hardwareRequests.empty()) {
@@ -718,6 +720,39 @@
mLinkToDeathImpl = std::move(impl);
}
+bool DefaultVehicleHal::checkDumpPermission() {
+ uid_t uid = AIBinder_getCallingUid();
+ return uid == AID_ROOT || uid == AID_SHELL || uid == AID_SYSTEM;
+}
+
+binder_status_t DefaultVehicleHal::dump(int fd, const char** args, uint32_t numArgs) {
+ if (!checkDumpPermission()) {
+ dprintf(fd, "Caller must be root, system or shell");
+ return STATUS_PERMISSION_DENIED;
+ }
+
+ std::vector<std::string> options;
+ for (uint32_t i = 0; i < numArgs; i++) {
+ options.push_back(args[i]);
+ }
+ DumpResult result = mVehicleHardware->dump(options);
+ 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");
+ {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ dprintf(fd, "Containing %zu property configs\n", mConfigsByPropId.size());
+ dprintf(fd, "Currently have %zu getValues clients\n", mGetValuesClients.size());
+ dprintf(fd, "Currently have %zu setValues clients\n", mSetValuesClients.size());
+ dprintf(fd, "Currently have %zu subscription clients\n",
+ mSubscriptionClients->countClients());
+ }
+ return STATUS_OK;
+}
+
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/vhal/test/ConnectedClientTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/ConnectedClientTest.cpp
index bd4a565..bdb0d31 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/ConnectedClientTest.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/ConnectedClientTest.cpp
@@ -80,7 +80,8 @@
GetValuesClient client(getPool(), getCallbackClient());
- client.sendResults(results);
+ auto resultsCopy = results;
+ client.sendResults(std::move(resultsCopy));
auto maybeGetValueResults = getCallback()->nextGetValueResults();
ASSERT_TRUE(maybeGetValueResults.has_value());
@@ -160,7 +161,8 @@
SetValuesClient client(getPool(), getCallbackClient());
- client.sendResults(results);
+ auto resultsCopy = results;
+ client.sendResults(std::move(resultsCopy));
auto maybeSetValueResults = getCallback()->nextSetValueResults();
ASSERT_TRUE(maybeSetValueResults.has_value());
diff --git a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
index ff355c3..7443d5b 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
@@ -27,6 +27,7 @@
#include <android-base/thread_annotations.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <sys/mman.h>
#include <utils/Log.h>
#include <utils/SystemClock.h>
@@ -75,6 +76,7 @@
using ::ndk::ScopedFileDescriptor;
using ::ndk::SpAIBinder;
+using ::testing::ContainsRegex;
using ::testing::Eq;
using ::testing::UnorderedElementsAre;
using ::testing::UnorderedElementsAreArray;
@@ -371,7 +373,7 @@
return mVhal->mOnBinderDiedContexts[clientId].get();
}
- bool countOnBinderDiedContexts() {
+ size_t countOnBinderDiedContexts() {
std::scoped_lock<std::mutex> lockGuard(mVhal->mLock);
return mVhal->mOnBinderDiedContexts.size();
}
@@ -444,6 +446,7 @@
if (result.value() != nullptr) {
requests.payloads.clear();
requests.sharedMemoryFd = std::move(*result.value());
+ requests.payloads.clear();
}
return {};
}
@@ -1544,6 +1547,45 @@
<< "expect OnBinderDied context to be deleted when binder is unlinked";
}
+TEST_F(DefaultVehicleHalTest, testDumpCallerShouldDump) {
+ std::string buffer = "Dump from hardware";
+ getHardware()->setDumpResult({
+ .callerShouldDumpState = true,
+ .buffer = buffer,
+ });
+ int fd = memfd_create("memfile", 0);
+ getClient()->dump(fd, nullptr, 0);
+
+ lseek(fd, 0, SEEK_SET);
+ char buf[10240] = {};
+ read(fd, buf, sizeof(buf));
+ close(fd);
+
+ std::string msg(buf);
+
+ ASSERT_THAT(msg, ContainsRegex(buffer + "\nVehicle HAL State: \n"));
+}
+
+TEST_F(DefaultVehicleHalTest, testDumpCallerShouldNotDump) {
+ std::string buffer = "Dump from hardware";
+ getHardware()->setDumpResult({
+ .callerShouldDumpState = false,
+ .buffer = buffer,
+ });
+ int fd = memfd_create("memfile", 0);
+ getClient()->dump(fd, nullptr, 0);
+
+ lseek(fd, 0, SEEK_SET);
+ char buf[10240] = {};
+ read(fd, buf, sizeof(buf));
+ close(fd);
+
+ std::string msg(buf);
+
+ ASSERT_THAT(msg, ContainsRegex(buffer));
+ ASSERT_EQ(msg.find("Vehicle HAL State: "), std::string::npos);
+}
+
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp
index eec32dd..66aef7c 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp
@@ -71,13 +71,15 @@
&mGetValueResponses);
}
+void MockVehicleHardware::setDumpResult(DumpResult result) {
+ mDumpResult = result;
+}
+
DumpResult MockVehicleHardware::dump(const std::vector<std::string>&) {
- // TODO(b/200737967): mock this.
- return DumpResult{};
+ return mDumpResult;
}
StatusCode MockVehicleHardware::checkHealth() {
- // TODO(b/200737967): mock this.
return StatusCode::OK;
}
diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h
index 0844de1..74d4fae 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h
@@ -79,6 +79,7 @@
void setStatus(const char* functionName,
::aidl::android::hardware::automotive::vehicle::StatusCode status);
void setSleepTime(int64_t timeInNano);
+ void setDumpResult(DumpResult result);
private:
mutable std::mutex mLock;
@@ -114,6 +115,8 @@
const std::vector<RequestType>& requests,
std::list<std::vector<RequestType>>* storedRequests,
std::list<std::vector<ResultType>>* storedResponses) const REQUIRES(mLock);
+
+ DumpResult mDumpResult;
};
} // namespace vehicle
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp b/automotive/vehicle/proto/Android.bp
similarity index 94%
rename from automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp
rename to automotive/vehicle/proto/Android.bp
index 3307bd6..683f128 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp
+++ b/automotive/vehicle/proto/Android.bp
@@ -25,8 +25,8 @@
cc_library_static {
name: "android.hardware.automotive.vehicle@2.0-libproto-native",
visibility: [
- "//hardware/interfaces/automotive/vehicle/2.0/default:__subpackages__",
- "//device/generic/car/emulator/vhal_v2_0:__subpackages__",
+ "//hardware/interfaces/automotive/vehicle:__subpackages__",
+ "//device/generic/car/emulator:__subpackages__",
],
vendor: true,
host_supported: true,
diff --git a/automotive/vehicle/proto/VehicleHalProto.proto b/automotive/vehicle/proto/VehicleHalProto.proto
new file mode 100644
index 0000000..0dafe8c
--- /dev/null
+++ b/automotive/vehicle/proto/VehicleHalProto.proto
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2015 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 = "proto2";
+
+package vhal_proto;
+
+// CMD messages are from workstation --> VHAL
+// RESP messages are from VHAL --> workstation
+enum MsgType {
+ GET_CONFIG_CMD = 0;
+ GET_CONFIG_RESP = 1;
+ GET_CONFIG_ALL_CMD = 2;
+ GET_CONFIG_ALL_RESP = 3;
+ GET_PROPERTY_CMD = 4;
+ GET_PROPERTY_RESP = 5;
+ GET_PROPERTY_ALL_CMD = 6;
+ GET_PROPERTY_ALL_RESP = 7;
+ SET_PROPERTY_CMD = 8;
+ SET_PROPERTY_RESP = 9;
+ SET_PROPERTY_ASYNC = 10;
+ DEBUG_CMD = 11;
+ DEBUG_RESP = 12;
+}
+enum Status {
+ RESULT_OK = 0;
+ ERROR_UNKNOWN = 1;
+ ERROR_UNIMPLEMENTED_CMD = 2;
+ ERROR_INVALID_PROPERTY = 3;
+ ERROR_INVALID_AREA_ID = 4;
+ ERROR_PROPERTY_UNINITIALIZED = 5;
+ ERROR_WRITE_ONLY_PROPERTY = 6;
+ ERROR_MEMORY_ALLOC_FAILED = 7;
+ ERROR_INVALID_OPERATION = 8;
+}
+
+enum VehiclePropStatus {
+ AVAILABLE = 0;
+ UNAVAILABLE = 1;
+ ERROR = 2;
+}
+
+message VehicleAreaConfig {
+ required int32 area_id = 1;
+ optional sint32 min_int32_value = 2;
+ optional sint32 max_int32_value = 3;
+ optional sint64 min_int64_value = 4;
+ optional sint64 max_int64_value = 5;
+ optional float min_float_value = 6;
+ optional float max_float_value = 7;
+}
+
+message VehiclePropConfig {
+ required int32 prop = 1;
+ optional int32 access = 2;
+ optional int32 change_mode = 3;
+ optional int32 value_type = 4;
+ optional int32 supported_areas = 5; // Deprecated - DO NOT USE
+ repeated VehicleAreaConfig area_configs = 6;
+ optional int32 config_flags = 7;
+ repeated int32 config_array = 8;
+ optional string config_string = 9;
+ optional float min_sample_rate = 10;
+ optional float max_sample_rate = 11;
+};
+
+message VehiclePropValue {
+ // common data
+ required int32 prop = 1;
+ optional int32 value_type = 2;
+ optional int64 timestamp = 3; // required for valid data from HAL, skipped for set
+ optional VehiclePropStatus status = 10; // required for valid data from HAL, skipped for set
+
+ // values
+ optional int32 area_id = 4;
+ repeated sint32 int32_values = 5; // this also covers boolean value.
+ repeated sint64 int64_values = 6;
+ repeated float float_values = 7;
+ optional string string_value = 8;
+ optional bytes bytes_value = 9;
+};
+
+// This structure is used to notify what values to get from the Vehicle HAL
+message VehiclePropGet {
+ required int32 prop = 1;
+ optional int32 area_id = 2;
+};
+
+message EmulatorMessage {
+ required MsgType msg_type = 1;
+ optional Status status = 2; // Only for RESP messages
+ repeated VehiclePropGet prop = 3; // Provided for getConfig, getProperty commands
+ repeated VehiclePropConfig config = 4;
+ repeated VehiclePropValue value = 5;
+ repeated string debug_commands = 6; // Required for debug command
+ optional string debug_result = 7; // Required for debug RESP messages
+};