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.
This commit is contained in:
Yu Shan
2022-01-22 04:38:42 +00:00
committed by Android (Google) Code Review
15 changed files with 878 additions and 151 deletions

View File

@@ -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
};

View File

@@ -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 automotive {
namespace vehicle {
namespace fake {
class FakeVehicleHardware final : public IVehicleHardware {
class FakeVehicleHardware : public IVehicleHardware {
public:
FakeVehicleHardware();
@@ -78,13 +80,15 @@ class FakeVehicleHardware final : public IVehicleHardware {
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 @@ class FakeVehicleHardware final : public IVehicleHardware {
::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

View File

@@ -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::VehiclePropertyStatus;
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 @@ StatusCode FakeVehicleHardware::setValues(std::shared_ptr<const SetValuesCallbac
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 @@ StatusCode FakeVehicleHardware::getValues(std::shared_ptr<const GetValuesCallbac
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 @@ StatusCode FakeVehicleHardware::getValues(std::shared_ptr<const GetValuesCallbac
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 @@ void FakeVehicleHardware::overrideProperties(const char* overrideDir) {
}
}
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

View File

@@ -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::VehicleProperty;
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, testInitialUserInfo) {
}));
}
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

View File

@@ -79,7 +79,7 @@ class GetSetValuesClient final : public ConnectedClient {
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.

View File

@@ -39,13 +39,6 @@ namespace hardware {
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 @@ class DefaultVehicleHal final : public ::aidl::android::hardware::automotive::ve
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 @@ class DefaultVehicleHal final : public ::aidl::android::hardware::automotive::ve
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,

View File

@@ -29,6 +29,9 @@ namespace hardware {
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 @@ template <class T1, class T2>
// 'sharedMemoryFd' field.
output->payloads.clear();
output->sharedMemoryFd = std::move(*fd);
} else {
output->sharedMemoryFd = ::ndk::ScopedFileDescriptor();
// Do not modify payloads.
}
return ::ndk::ScopedAStatus::ok();
}

View File

@@ -84,9 +84,9 @@ void sendGetOrSetValueResultsSeparately(std::shared_ptr<IVehicleCallback> callba
// 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 @@ void sendGetOrSetValueResults(std::shared_ptr<IVehicleCallback> callback,
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 @@ void onTimeout(
.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 @@ template <class ResultType, class ResultsType>
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 @@ void getOrSetValuesCallback(
}
if (!results.empty()) {
sendGetOrSetValueResults<ResultType, ResultsType>(callback, results);
sendGetOrSetValueResults<ResultType, ResultsType>(callback, std::move(results));
}
}
@@ -156,9 +157,9 @@ template void sendGetOrSetValueResult<SetValueResult, SetValueResults>(
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 onTimeout<SetValueResult, SetValueResults>(
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 @@ GetSetValuesClient<ResultType, ResultsType>::getTimeoutCallback() {
}
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 @@ void SubscriptionClient::sendUpdatedValues(std::shared_ptr<IVehicleCallback> cal
// 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: "

View File

@@ -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 @@ ScopedAStatus DefaultVehicleHal::getValues(const CallbackType& callback,
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 @@ ScopedAStatus DefaultVehicleHal::setValues(const CallbackType& callback,
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 @@ void DefaultVehicleHal::setLinkToDeathImpl(std::unique_ptr<ILinkToDeath> impl) {
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

View File

@@ -80,7 +80,8 @@ TEST_F(ConnectedClientTest, testSendGetValueResults) {
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 @@ TEST_F(ConnectedClientTest, testSendSetValueResults) {
SetValuesClient client(getPool(), getCallbackClient());
client.sendResults(results);
auto resultsCopy = results;
client.sendResults(std::move(resultsCopy));
auto maybeSetValueResults = getCallback()->nextSetValueResults();
ASSERT_TRUE(maybeSetValueResults.has_value());

View File

@@ -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::ScopedAStatus;
using ::ndk::ScopedFileDescriptor;
using ::ndk::SpAIBinder;
using ::testing::ContainsRegex;
using ::testing::Eq;
using ::testing::UnorderedElementsAre;
using ::testing::UnorderedElementsAreArray;
@@ -371,7 +373,7 @@ class DefaultVehicleHalTest : public ::testing::Test {
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 @@ class DefaultVehicleHalTest : public ::testing::Test {
if (result.value() != nullptr) {
requests.payloads.clear();
requests.sharedMemoryFd = std::move(*result.value());
requests.payloads.clear();
}
return {};
}
@@ -1544,6 +1547,45 @@ TEST_F(DefaultVehicleHalTest, testOnBinderDiedUnlinked) {
<< "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

View File

@@ -71,13 +71,15 @@ StatusCode MockVehicleHardware::getValues(std::shared_ptr<const GetValuesCallbac
&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;
}

View File

@@ -79,6 +79,7 @@ class MockVehicleHardware final : public IVehicleHardware {
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 @@ class MockVehicleHardware final : public IVehicleHardware {
const std::vector<RequestType>& requests,
std::list<std::vector<RequestType>>* storedRequests,
std::list<std::vector<ResultType>>* storedResponses) const REQUIRES(mLock);
DumpResult mDumpResult;
};
} // namespace vehicle

View File

@@ -25,8 +25,8 @@ package {
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,

View File

@@ -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
};