mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 22:04:26 +00:00
Merge "Enable vehicle HAL to be controlled via ADB"
This commit is contained in:
@@ -40,6 +40,28 @@ LOCAL_SHARED_LIBRARIES := \
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
###############################################################################
|
||||
# Vehicle HAL Protobuf library
|
||||
###############################################################################
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES := $(call all-proto-files-under, impl/proto)
|
||||
|
||||
LOCAL_PROTOC_OPTIMIZE_TYPE := nano
|
||||
|
||||
LOCAL_MODULE := $(module_prefix)-libproto-native
|
||||
LOCAL_MODULE_CLASS := STATIC_LIBRARIES
|
||||
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
LOCAL_STRIP_MODULE := keep_symbols
|
||||
|
||||
generated_sources_dir := $(call local-generated-sources-dir)
|
||||
LOCAL_EXPORT_C_INCLUDE_DIRS := \
|
||||
$(generated_sources_dir)/proto/$(LOCAL_PATH)/impl/proto
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Vehicle default VehicleHAL implementation
|
||||
###############################################################################
|
||||
@@ -55,9 +77,13 @@ LOCAL_SHARED_LIBRARIES := \
|
||||
libhidltransport \
|
||||
libhwbinder \
|
||||
liblog \
|
||||
libprotobuf-cpp-lite \
|
||||
libutils \
|
||||
$(module_prefix) \
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
$(module_prefix)-libproto-native
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
|
||||
@@ -114,7 +140,11 @@ LOCAL_SHARED_LIBRARIES := \
|
||||
libhidltransport \
|
||||
libhwbinder \
|
||||
liblog \
|
||||
libprotobuf-cpp-lite \
|
||||
libutils \
|
||||
$(module_prefix) \
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
$(module_prefix)-libproto-native
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
service vehicle-hal-2.0 /system/bin/hw/android.hardware.automotive.vehicle@2.0-service
|
||||
class hal
|
||||
user vehicle_network
|
||||
group system
|
||||
group system inet
|
||||
|
||||
@@ -14,12 +14,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "DefaultVehicleHal.h"
|
||||
#define LOG_TAG "DefaultVehicleHal"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#define LOG_TAG "default_vehicle"
|
||||
#include <android/log.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "DefaultVehicleHal.h"
|
||||
#include "VehicleHalProto.pb.h"
|
||||
|
||||
#define DEBUG_SOCKET (33452)
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
@@ -29,144 +34,157 @@ namespace V2_0 {
|
||||
|
||||
namespace impl {
|
||||
|
||||
VehicleHal::VehiclePropValuePtr DefaultVehicleHal::get(
|
||||
const VehiclePropValue& requestedPropValue, StatusCode* outStatus) {
|
||||
*outStatus = StatusCode::OK;
|
||||
void DefaultVehicleHal::doGetConfig(emulator::EmulatorMessage& rxMsg,
|
||||
emulator::EmulatorMessage& respMsg) {
|
||||
std::vector<VehiclePropConfig> configs = listProperties();
|
||||
emulator::VehiclePropGet getProp = rxMsg.prop(0);
|
||||
|
||||
VehiclePropValuePtr v;
|
||||
auto property = static_cast<VehicleProperty>(requestedPropValue.prop);
|
||||
int32_t areaId = requestedPropValue.areaId;
|
||||
auto& pool = *getValuePool();
|
||||
respMsg.set_msg_type(emulator::GET_CONFIG_RESP);
|
||||
respMsg.set_status(emulator::ERROR_INVALID_PROPERTY);
|
||||
|
||||
switch (property) {
|
||||
case VehicleProperty::INFO_MAKE:
|
||||
v = pool.obtainString("Default Car");
|
||||
for (auto& config : configs) {
|
||||
// Find the config we are looking for
|
||||
if (config.prop == getProp.prop()) {
|
||||
emulator::VehiclePropConfig* protoCfg = respMsg.add_config();
|
||||
populateProtoVehicleConfig(protoCfg, config);
|
||||
respMsg.set_status(emulator::RESULT_OK);
|
||||
break;
|
||||
case VehicleProperty::HVAC_FAN_SPEED:
|
||||
v = pool.obtainInt32(mFanSpeed);
|
||||
break;
|
||||
case VehicleProperty::HVAC_POWER_ON:
|
||||
v = pool.obtainBoolean(mHvacPowerOn);
|
||||
break;
|
||||
case VehicleProperty::HVAC_RECIRC_ON:
|
||||
v = pool.obtainBoolean(mHvacRecircOn);
|
||||
break;
|
||||
case VehicleProperty::HVAC_AC_ON:
|
||||
v = pool.obtainBoolean(mHvacAcOn);
|
||||
break;
|
||||
case VehicleProperty::HVAC_AUTO_ON:
|
||||
v = pool.obtainBoolean(mHvacAutoOn);
|
||||
break;
|
||||
case VehicleProperty::HVAC_FAN_DIRECTION:
|
||||
v = pool.obtainInt32(toInt(mFanDirection));
|
||||
break;
|
||||
case VehicleProperty::HVAC_DEFROSTER:
|
||||
bool defroster;
|
||||
*outStatus = getHvacDefroster(areaId, &defroster);
|
||||
if (StatusCode::OK == *outStatus) {
|
||||
v = pool.obtainBoolean(defroster);
|
||||
}
|
||||
break;
|
||||
case VehicleProperty::HVAC_TEMPERATURE_SET:
|
||||
float value;
|
||||
*outStatus = getHvacTemperature(requestedPropValue.areaId,
|
||||
&value);
|
||||
if (StatusCode::OK == *outStatus) {
|
||||
v = pool.obtainFloat(value);
|
||||
}
|
||||
break;
|
||||
case VehicleProperty::INFO_FUEL_CAPACITY:
|
||||
v = pool.obtainFloat(0.75f);
|
||||
break;
|
||||
case VehicleProperty::DISPLAY_BRIGHTNESS:
|
||||
v = pool.obtainInt32(mBrightness);
|
||||
break;
|
||||
case VehicleProperty::NIGHT_MODE:
|
||||
v = pool.obtainBoolean(false);
|
||||
break;
|
||||
case VehicleProperty::GEAR_SELECTION:
|
||||
v = pool.obtainInt32(toInt(VehicleGear::GEAR_PARK));
|
||||
break;
|
||||
case VehicleProperty::DRIVING_STATUS:
|
||||
v = pool.obtainInt32(toInt(VehicleDrivingStatus::UNRESTRICTED));
|
||||
break;
|
||||
case VehicleProperty::IGNITION_STATE:
|
||||
v = pool.obtainInt32(toInt(VehicleIgnitionState::ACC));
|
||||
break;
|
||||
case VehicleProperty::OBD2_LIVE_FRAME:
|
||||
v = pool.obtainComplex();
|
||||
*outStatus = fillObd2LiveFrame(&v);
|
||||
break;
|
||||
case VehicleProperty::OBD2_FREEZE_FRAME:
|
||||
v = pool.obtainComplex();
|
||||
*outStatus = fillObd2FreezeFrame(&v);
|
||||
break;
|
||||
default:
|
||||
*outStatus = StatusCode::INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
if (StatusCode::OK == *outStatus && v.get() != nullptr) {
|
||||
v->prop = toInt(property);
|
||||
v->areaId = areaId;
|
||||
v->timestamp = elapsedRealtimeNano();
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
StatusCode DefaultVehicleHal::set(const VehiclePropValue& propValue) {
|
||||
auto property = static_cast<VehicleProperty>(propValue.prop);
|
||||
const auto& v = propValue.value;
|
||||
void DefaultVehicleHal::doGetConfigAll(emulator::EmulatorMessage& /* rxMsg */,
|
||||
emulator::EmulatorMessage& respMsg) {
|
||||
std::vector<VehiclePropConfig> configs = listProperties();
|
||||
|
||||
StatusCode status = StatusCode::OK;
|
||||
respMsg.set_msg_type(emulator::GET_CONFIG_ALL_RESP);
|
||||
respMsg.set_status(emulator::RESULT_OK);
|
||||
|
||||
switch (property) {
|
||||
case VehicleProperty::HVAC_POWER_ON:
|
||||
mHvacPowerOn = v.int32Values[0] == 1;
|
||||
break;
|
||||
case VehicleProperty::HVAC_RECIRC_ON:
|
||||
mHvacRecircOn = v.int32Values[0] == 1;
|
||||
break;
|
||||
case VehicleProperty::HVAC_AC_ON:
|
||||
mHvacAcOn = v.int32Values[0] == 1;
|
||||
break;
|
||||
case VehicleProperty::HVAC_AUTO_ON:
|
||||
mHvacAutoOn = v.int32Values[0] == 1;
|
||||
break;
|
||||
case VehicleProperty::HVAC_DEFROSTER:
|
||||
status = setHvacDefroster(propValue.areaId, v.int32Values[0] == 1);
|
||||
break;
|
||||
case VehicleProperty::HVAC_FAN_DIRECTION:
|
||||
mFanDirection =
|
||||
static_cast<VehicleHvacFanDirection>(v.int32Values[0]);
|
||||
break;
|
||||
case VehicleProperty::HVAC_FAN_SPEED:
|
||||
mFanSpeed = v.int32Values[0];
|
||||
break;
|
||||
case VehicleProperty::HVAC_TEMPERATURE_SET:
|
||||
status = setHvacTemperature(propValue.areaId, v.floatValues[0]);
|
||||
break;
|
||||
case VehicleProperty::DISPLAY_BRIGHTNESS:
|
||||
mBrightness = v.int32Values[0];
|
||||
break;
|
||||
default:
|
||||
status = StatusCode::INVALID_ARG;
|
||||
for (auto& config : configs) {
|
||||
emulator::VehiclePropConfig* protoCfg = respMsg.add_config();
|
||||
populateProtoVehicleConfig(protoCfg, config);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void DefaultVehicleHal::onCreate() {
|
||||
const auto& propConfigs(listProperties());
|
||||
auto obd2LiveFramePropConfig = std::find_if(
|
||||
propConfigs.begin(),
|
||||
propConfigs.end(),
|
||||
[] (VehiclePropConfig config) -> bool {
|
||||
return (config.prop == toInt(VehicleProperty::OBD2_LIVE_FRAME));
|
||||
});
|
||||
void DefaultVehicleHal::doGetProperty(emulator::EmulatorMessage& rxMsg,
|
||||
emulator::EmulatorMessage& respMsg) {
|
||||
int32_t areaId = 0;
|
||||
emulator::VehiclePropGet getProp = rxMsg.prop(0);
|
||||
int32_t propId = getProp.prop();
|
||||
emulator::Status status = emulator::ERROR_INVALID_PROPERTY;
|
||||
VehiclePropValue* val;
|
||||
|
||||
respMsg.set_msg_type(emulator::GET_PROPERTY_RESP);
|
||||
|
||||
if (getProp.has_area_id()) {
|
||||
areaId = getProp.area_id();
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mPropsMutex);
|
||||
|
||||
val = getVehiclePropValueLocked(propId, areaId);
|
||||
if (val != nullptr) {
|
||||
emulator::VehiclePropValue* protoVal = respMsg.add_value();
|
||||
populateProtoVehiclePropValue(protoVal, val);
|
||||
status = emulator::RESULT_OK;
|
||||
}
|
||||
}
|
||||
|
||||
respMsg.set_status(status);
|
||||
}
|
||||
|
||||
void DefaultVehicleHal::doGetPropertyAll(emulator::EmulatorMessage& /* rxMsg */,
|
||||
emulator::EmulatorMessage& respMsg) {
|
||||
respMsg.set_msg_type(emulator::GET_PROPERTY_ALL_RESP);
|
||||
respMsg.set_status(emulator::RESULT_OK);
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mPropsMutex);
|
||||
|
||||
for (auto& propVal : mProps) {
|
||||
emulator::VehiclePropValue* protoVal = respMsg.add_value();
|
||||
populateProtoVehiclePropValue(protoVal, propVal.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DefaultVehicleHal::doSetProperty(emulator::EmulatorMessage& rxMsg,
|
||||
emulator::EmulatorMessage& respMsg) {
|
||||
emulator::VehiclePropValue protoVal = rxMsg.value(0);
|
||||
VehiclePropValue val;
|
||||
|
||||
respMsg.set_msg_type(emulator::SET_PROPERTY_RESP);
|
||||
|
||||
val.prop = protoVal.prop();
|
||||
val.areaId = protoVal.area_id();
|
||||
|
||||
// Copy value data if it is set. This automatically handles complex data types if needed.
|
||||
if (protoVal.has_string_value()) {
|
||||
val.value.stringValue = protoVal.string_value().c_str();
|
||||
}
|
||||
|
||||
if (protoVal.has_bytes_value()) {
|
||||
std::vector<uint8_t> tmp(protoVal.bytes_value().begin(), protoVal.bytes_value().end());
|
||||
val.value.bytes = tmp;
|
||||
}
|
||||
|
||||
if (protoVal.int32_values_size() > 0) {
|
||||
std::vector<int32_t> int32Values = std::vector<int32_t>(protoVal.int32_values_size());
|
||||
for (int i=0; i<protoVal.int32_values_size(); i++) {
|
||||
int32Values[i] = protoVal.int32_values(i);
|
||||
}
|
||||
val.value.int32Values = int32Values;
|
||||
}
|
||||
|
||||
if (protoVal.int64_values_size() > 0) {
|
||||
std::vector<int64_t> int64Values = std::vector<int64_t>(protoVal.int64_values_size());
|
||||
for (int i=0; i<protoVal.int64_values_size(); i++) {
|
||||
int64Values[i] = protoVal.int64_values(i);
|
||||
}
|
||||
val.value.int64Values = int64Values;
|
||||
}
|
||||
|
||||
if (protoVal.float_values_size() > 0) {
|
||||
std::vector<float> floatValues = std::vector<float>(protoVal.float_values_size());
|
||||
for (int i=0; i<protoVal.float_values_size(); i++) {
|
||||
floatValues[i] = protoVal.float_values(i);
|
||||
}
|
||||
val.value.floatValues = floatValues;
|
||||
}
|
||||
|
||||
if (updateProperty(val) == StatusCode::OK) {
|
||||
// Send property up to VehicleHalManager via callback
|
||||
auto& pool = *getValuePool();
|
||||
VehiclePropValuePtr v = pool.obtain(val);
|
||||
|
||||
doHalEvent(std::move(v));
|
||||
respMsg.set_status(emulator::RESULT_OK);
|
||||
} else {
|
||||
respMsg.set_status(emulator::ERROR_INVALID_PROPERTY);
|
||||
}
|
||||
}
|
||||
|
||||
// This function should only be called while mPropsMutex is locked.
|
||||
VehiclePropValue* DefaultVehicleHal::getVehiclePropValueLocked(int32_t propId, int32_t areaId) {
|
||||
if (getPropArea(propId) == VehicleArea::GLOBAL) {
|
||||
// In VehicleHal, global properties have areaId = -1. We use 0.
|
||||
areaId = 0;
|
||||
}
|
||||
|
||||
for (auto& prop : mProps) {
|
||||
if ((prop->prop == propId) && (prop->areaId == areaId)) {
|
||||
return prop.get();
|
||||
}
|
||||
}
|
||||
ALOGW("%s: Property not found: propId = 0x%x, areaId = 0x%x", __FUNCTION__, propId, areaId);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void DefaultVehicleHal::initObd2LiveFrame(VehiclePropConfig& obd2LiveFramePropConfig) {
|
||||
mObd2SensorStore.reset(new Obd2SensorStore(
|
||||
obd2LiveFramePropConfig->configArray[0],
|
||||
obd2LiveFramePropConfig->configArray[1]));
|
||||
obd2LiveFramePropConfig.configArray[0],
|
||||
obd2LiveFramePropConfig.configArray[1]));
|
||||
// precalculate OBD2 sensor values
|
||||
mObd2SensorStore->setIntegerSensor(
|
||||
Obd2IntegerSensorIndex::FUEL_SYSTEM_STATUS,
|
||||
@@ -246,56 +264,461 @@ void DefaultVehicleHal::onCreate() {
|
||||
Obd2FloatSensorIndex::COMMANDED_THROTTLE_ACTUATOR, 0.024);
|
||||
}
|
||||
|
||||
StatusCode DefaultVehicleHal::getHvacTemperature(int32_t areaId,
|
||||
float* outValue) {
|
||||
if (areaId == toInt(VehicleAreaZone::ROW_1_LEFT)) {
|
||||
*outValue = mRow1LeftHvacTemperatureSet;
|
||||
} else if (areaId == toInt(VehicleAreaZone::ROW_1_RIGHT)) {
|
||||
*outValue = mRow1RightHvacTemperatureSet;
|
||||
} else {
|
||||
return StatusCode::INVALID_ARG;
|
||||
void DefaultVehicleHal::parseRxProtoBuf(std::vector<uint8_t>& msg) {
|
||||
emulator::EmulatorMessage rxMsg;
|
||||
emulator::EmulatorMessage respMsg;
|
||||
std::string str(reinterpret_cast<const char*>(msg.data()), msg.size());
|
||||
|
||||
rxMsg.ParseFromString(str);
|
||||
|
||||
switch (rxMsg.msg_type()) {
|
||||
case emulator::GET_CONFIG_CMD:
|
||||
doGetConfig(rxMsg, respMsg);
|
||||
break;
|
||||
case emulator::GET_CONFIG_ALL_CMD:
|
||||
doGetConfigAll(rxMsg, respMsg);
|
||||
break;
|
||||
case emulator::GET_PROPERTY_CMD:
|
||||
doGetProperty(rxMsg, respMsg);
|
||||
break;
|
||||
case emulator::GET_PROPERTY_ALL_CMD:
|
||||
doGetPropertyAll(rxMsg, respMsg);
|
||||
break;
|
||||
case emulator::SET_PROPERTY_CMD:
|
||||
doSetProperty(rxMsg, respMsg);
|
||||
break;
|
||||
default:
|
||||
ALOGW("%s: Unknown message received, type = %d", __FUNCTION__, rxMsg.msg_type());
|
||||
respMsg.set_status(emulator::ERROR_UNIMPLEMENTED_CMD);
|
||||
break;
|
||||
}
|
||||
return StatusCode::OK;
|
||||
|
||||
// Send the reply
|
||||
txMsg(respMsg);
|
||||
}
|
||||
|
||||
StatusCode DefaultVehicleHal::setHvacTemperature(
|
||||
int32_t areaId, float value) {
|
||||
if (areaId == toInt(VehicleAreaZone::ROW_1_LEFT)) {
|
||||
mRow1LeftHvacTemperatureSet = value;
|
||||
} else if (areaId == toInt(VehicleAreaZone::ROW_1_RIGHT)) {
|
||||
mRow1RightHvacTemperatureSet = value;
|
||||
} else {
|
||||
return StatusCode::INVALID_ARG;
|
||||
// Copies internal VehiclePropConfig data structure to protobuf VehiclePropConfig
|
||||
void DefaultVehicleHal::populateProtoVehicleConfig(emulator::VehiclePropConfig* protoCfg,
|
||||
const VehiclePropConfig& cfg) {
|
||||
protoCfg->set_prop(cfg.prop);
|
||||
protoCfg->set_access(toInt(cfg.access));
|
||||
protoCfg->set_change_mode(toInt(cfg.changeMode));
|
||||
protoCfg->set_value_type(toInt(getPropType(cfg.prop)));
|
||||
|
||||
if (!isGlobalProp(cfg.prop)) {
|
||||
protoCfg->set_supported_areas(cfg.supportedAreas);
|
||||
}
|
||||
return StatusCode::OK;
|
||||
|
||||
for (auto& configElement : cfg.configArray) {
|
||||
protoCfg->add_config_array(configElement);
|
||||
}
|
||||
|
||||
if (cfg.configString.size() > 0) {
|
||||
protoCfg->set_config_string(cfg.configString.c_str(), cfg.configString.size());
|
||||
}
|
||||
|
||||
// Populate the min/max values based on property type
|
||||
switch (getPropType(cfg.prop)) {
|
||||
case VehiclePropertyType::STRING:
|
||||
case VehiclePropertyType::BOOLEAN:
|
||||
case VehiclePropertyType::INT32_VEC:
|
||||
case VehiclePropertyType::FLOAT_VEC:
|
||||
case VehiclePropertyType::BYTES:
|
||||
case VehiclePropertyType::COMPLEX:
|
||||
// Do nothing. These types don't have min/max values
|
||||
break;
|
||||
case VehiclePropertyType::INT64:
|
||||
if (cfg.areaConfigs.size() > 0) {
|
||||
emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
|
||||
aCfg->set_min_int64_value(cfg.areaConfigs[0].minInt64Value);
|
||||
aCfg->set_max_int64_value(cfg.areaConfigs[0].maxInt64Value);
|
||||
}
|
||||
break;
|
||||
case VehiclePropertyType::FLOAT:
|
||||
if (cfg.areaConfigs.size() > 0) {
|
||||
emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
|
||||
aCfg->set_min_float_value(cfg.areaConfigs[0].minFloatValue);
|
||||
aCfg->set_max_float_value(cfg.areaConfigs[0].maxFloatValue);
|
||||
}
|
||||
break;
|
||||
case VehiclePropertyType::INT32:
|
||||
if (cfg.areaConfigs.size() > 0) {
|
||||
emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
|
||||
aCfg->set_min_int32_value(cfg.areaConfigs[0].minInt32Value);
|
||||
aCfg->set_max_int32_value(cfg.areaConfigs[0].maxInt32Value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ALOGW("%s: Unknown property type: 0x%x", __FUNCTION__, toInt(getPropType(cfg.prop)));
|
||||
break;
|
||||
}
|
||||
|
||||
protoCfg->set_min_sample_rate(cfg.minSampleRate);
|
||||
protoCfg->set_max_sample_rate(cfg.maxSampleRate);
|
||||
}
|
||||
|
||||
StatusCode DefaultVehicleHal::getHvacDefroster(int32_t areaId,
|
||||
bool* outValue) {
|
||||
ALOGI("Getting Hvac defroster for area: 0x%x", areaId);
|
||||
// Copies internal VehiclePropValue data structure to protobuf VehiclePropValue
|
||||
void DefaultVehicleHal::populateProtoVehiclePropValue(emulator::VehiclePropValue* protoVal,
|
||||
const VehiclePropValue* val) {
|
||||
protoVal->set_prop(val->prop);
|
||||
protoVal->set_value_type(toInt(getPropType(val->prop)));
|
||||
protoVal->set_timestamp(val->timestamp);
|
||||
protoVal->set_area_id(val->areaId);
|
||||
|
||||
if (areaId == toInt(VehicleAreaWindow::FRONT_WINDSHIELD)) {
|
||||
*outValue = mFrontDefroster;
|
||||
} else if (areaId == toInt(VehicleAreaWindow::REAR_WINDSHIELD)) {
|
||||
*outValue = mRearDefroster;
|
||||
} else {
|
||||
ALOGE("Unable to get hvac defroster for area: 0x%x", areaId);
|
||||
return StatusCode::INVALID_ARG;
|
||||
// Copy value data if it is set.
|
||||
// - for bytes and strings, this is indicated by size > 0
|
||||
// - for int32, int64, and float, copy the values if vectors have data
|
||||
if (val->value.stringValue.size() > 0) {
|
||||
protoVal->set_string_value(val->value.stringValue.c_str(), val->value.stringValue.size());
|
||||
}
|
||||
|
||||
ALOGI("Getting Hvac defroster for area: 0x%x, OK", areaId);
|
||||
return StatusCode::OK;
|
||||
if (val->value.bytes.size() > 0) {
|
||||
protoVal->set_bytes_value(val->value.bytes.data(), val->value.bytes.size());
|
||||
}
|
||||
|
||||
for (auto& int32Value : val->value.int32Values) {
|
||||
protoVal->add_int32_values(int32Value);
|
||||
}
|
||||
|
||||
for (auto& int64Value : val->value.int64Values) {
|
||||
protoVal->add_int64_values(int64Value);
|
||||
}
|
||||
|
||||
for (auto& floatValue : val->value.floatValues) {
|
||||
protoVal->add_float_values(floatValue);
|
||||
}
|
||||
}
|
||||
|
||||
StatusCode DefaultVehicleHal::setHvacDefroster(int32_t areaId, bool value) {
|
||||
if (areaId == toInt(VehicleAreaWindow::FRONT_WINDSHIELD)) {
|
||||
mFrontDefroster = value;
|
||||
} else if (areaId == toInt(VehicleAreaWindow::REAR_WINDSHIELD)) {
|
||||
mRearDefroster = value;
|
||||
} else {
|
||||
return StatusCode::INVALID_ARG;
|
||||
void DefaultVehicleHal::rxMsg(void) {
|
||||
int numBytes = 0;
|
||||
int32_t msgSize;
|
||||
do {
|
||||
// This is a variable length message.
|
||||
// Read the number of bytes to rx over the socket
|
||||
numBytes = read(mCurSocket, &msgSize, sizeof(msgSize));
|
||||
|
||||
if (numBytes != sizeof(msgSize)) {
|
||||
// This happens when connection is closed
|
||||
ALOGD("%s: numBytes=%d, expected=4", __FUNCTION__, numBytes);
|
||||
break;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> msg = std::vector<uint8_t>(msgSize);
|
||||
|
||||
numBytes = read(mCurSocket, msg.data(), msgSize);
|
||||
|
||||
if ((numBytes == msgSize) && (msgSize > 0)) {
|
||||
// Received a message.
|
||||
parseRxProtoBuf(msg);
|
||||
} else {
|
||||
// This happens when connection is closed
|
||||
ALOGD("%s: numBytes=%d, msgSize=%d", __FUNCTION__, numBytes, msgSize);
|
||||
break;
|
||||
}
|
||||
} while (mExit == 0);
|
||||
}
|
||||
|
||||
void DefaultVehicleHal::rxThread(void) {
|
||||
// Initialize the socket
|
||||
{
|
||||
int retVal;
|
||||
struct sockaddr_in servAddr;
|
||||
|
||||
mSocket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (mSocket < 0) {
|
||||
ALOGE("%s: socket() failed, mSocket=%d, errno=%d", __FUNCTION__, mSocket, errno);
|
||||
mSocket = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
bzero(&servAddr, sizeof(servAddr));
|
||||
servAddr.sin_family = AF_INET;
|
||||
servAddr.sin_addr.s_addr = INADDR_ANY;
|
||||
servAddr.sin_port = htons(DEBUG_SOCKET);
|
||||
|
||||
retVal = bind(mSocket, reinterpret_cast<struct sockaddr*>(&servAddr), sizeof(servAddr));
|
||||
if(retVal < 0) {
|
||||
ALOGE("%s: Error on binding: retVal=%d, errno=%d", __FUNCTION__, retVal, errno);
|
||||
close(mSocket);
|
||||
mSocket = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
listen(mSocket, 1);
|
||||
|
||||
// Set the socket to be non-blocking so we can poll it continouously
|
||||
fcntl(mSocket, F_SETFL, O_NONBLOCK);
|
||||
}
|
||||
return StatusCode::OK;
|
||||
|
||||
while (mExit == 0) {
|
||||
struct sockaddr_in cliAddr;
|
||||
socklen_t cliLen = sizeof(cliAddr);
|
||||
int cSocket = accept(mSocket, reinterpret_cast<struct sockaddr*>(&cliAddr), &cliLen);
|
||||
|
||||
if (cSocket >= 0) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mTxMutex);
|
||||
mCurSocket = cSocket;
|
||||
}
|
||||
ALOGD("%s: Incoming connection received on socket %d", __FUNCTION__, cSocket);
|
||||
rxMsg();
|
||||
ALOGD("%s: Connection terminated on socket %d", __FUNCTION__, cSocket);
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mTxMutex);
|
||||
mCurSocket = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Use a blocking socket?
|
||||
// Check every 100ms for a new socket connection
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
|
||||
// Shutdown the socket
|
||||
close(mSocket);
|
||||
mSocket = -1;
|
||||
}
|
||||
|
||||
// This function sets the default value of a property if we are interested in setting it.
|
||||
// TODO: Co-locate the default values with the configuration structure, to make it easier to
|
||||
// add new properties and their defaults.
|
||||
void DefaultVehicleHal::setDefaultValue(VehiclePropValue* prop) {
|
||||
switch (prop->prop) {
|
||||
case toInt(VehicleProperty::INFO_MAKE):
|
||||
prop->value.stringValue = "Default Car";
|
||||
break;
|
||||
case toInt(VehicleProperty::HVAC_POWER_ON):
|
||||
prop->value.int32Values[0] = 1;
|
||||
break;
|
||||
case toInt(VehicleProperty::HVAC_DEFROSTER):
|
||||
prop->value.int32Values[0] = 0;
|
||||
break;
|
||||
case toInt(VehicleProperty::HVAC_RECIRC_ON):
|
||||
prop->value.int32Values[0] = 1;
|
||||
break;
|
||||
case toInt(VehicleProperty::HVAC_AC_ON):
|
||||
prop->value.int32Values[0] = 1;
|
||||
break;
|
||||
case toInt(VehicleProperty::HVAC_AUTO_ON):
|
||||
prop->value.int32Values[0] = 1;
|
||||
break;
|
||||
case toInt(VehicleProperty::HVAC_FAN_SPEED):
|
||||
prop->value.int32Values[0] = 3;
|
||||
break;
|
||||
case toInt(VehicleProperty::HVAC_FAN_DIRECTION):
|
||||
prop->value.int32Values[0] = toInt(VehicleHvacFanDirection::FACE);
|
||||
break;
|
||||
case toInt(VehicleProperty::HVAC_TEMPERATURE_SET):
|
||||
prop->value.floatValues[0] = 16;
|
||||
break;
|
||||
case toInt(VehicleProperty::NIGHT_MODE):
|
||||
prop->value.int32Values[0] = 0;
|
||||
break;
|
||||
case toInt(VehicleProperty::DRIVING_STATUS):
|
||||
prop->value.int32Values[0] = toInt(VehicleDrivingStatus::UNRESTRICTED);
|
||||
break;
|
||||
case toInt(VehicleProperty::GEAR_SELECTION):
|
||||
prop->value.int32Values[0] = toInt(VehicleGear::GEAR_PARK);
|
||||
break;
|
||||
case toInt(VehicleProperty::INFO_FUEL_CAPACITY):
|
||||
prop->value.floatValues[0] = 0.75f;
|
||||
break;
|
||||
case toInt(VehicleProperty::DISPLAY_BRIGHTNESS):
|
||||
prop->value.int32Values[0] = 7;
|
||||
break;
|
||||
case toInt(VehicleProperty::IGNITION_STATE):
|
||||
prop->value.int32Values[0] = toInt(VehicleIgnitionState::ON);
|
||||
break;
|
||||
case toInt(VehicleProperty::OBD2_LIVE_FRAME):
|
||||
// OBD2 is handled separately
|
||||
break;
|
||||
case toInt(VehicleProperty::OBD2_FREEZE_FRAME):
|
||||
// OBD2 is handled separately
|
||||
break;
|
||||
default:
|
||||
ALOGW("%s: propId=0x%x not found", __FUNCTION__, prop->prop);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Transmit a reply back to the emulator
|
||||
void DefaultVehicleHal::txMsg(emulator::EmulatorMessage& txMsg) {
|
||||
std::string msgString;
|
||||
|
||||
if (txMsg.SerializeToString(&msgString)) {
|
||||
int32_t msgLen = msgString.length();
|
||||
int retVal = 0;
|
||||
|
||||
// TODO: Prepend the message length to the string without a copy
|
||||
msgString.insert(0, reinterpret_cast<char*>(&msgLen), 4);
|
||||
|
||||
// Send the message
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mTxMutex);
|
||||
if (mCurSocket != -1) {
|
||||
retVal = write(mCurSocket, msgString.data(), msgString.size());
|
||||
}
|
||||
}
|
||||
|
||||
if (retVal < 0) {
|
||||
ALOGE("%s: Failed to tx message: retval=%d, errno=%d", __FUNCTION__, retVal, errno);
|
||||
}
|
||||
} else {
|
||||
ALOGE("%s: SerializeToString failed!", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
|
||||
// Updates the property value held in the HAL
|
||||
StatusCode DefaultVehicleHal::updateProperty(const VehiclePropValue& propValue) {
|
||||
auto propId = propValue.prop;
|
||||
auto areaId = propValue.areaId;
|
||||
StatusCode status = StatusCode::INVALID_ARG;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mPropsMutex);
|
||||
|
||||
VehiclePropValue* internalPropValue = getVehiclePropValueLocked(propId, areaId);
|
||||
if (internalPropValue != nullptr) {
|
||||
internalPropValue->value = propValue.value;
|
||||
internalPropValue->timestamp = elapsedRealtimeNano();
|
||||
status = StatusCode::OK;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
VehicleHal::VehiclePropValuePtr DefaultVehicleHal::get(
|
||||
const VehiclePropValue& requestedPropValue, StatusCode* outStatus) {
|
||||
auto areaId = requestedPropValue.areaId;
|
||||
auto& pool = *getValuePool();
|
||||
auto propId = requestedPropValue.prop;
|
||||
StatusCode status;
|
||||
VehiclePropValuePtr v = nullptr;
|
||||
|
||||
switch (propId) {
|
||||
case toInt(VehicleProperty::OBD2_LIVE_FRAME):
|
||||
v = pool.obtainComplex();
|
||||
status = fillObd2LiveFrame(&v);
|
||||
break;
|
||||
case toInt(VehicleProperty::OBD2_FREEZE_FRAME):
|
||||
v = pool.obtainComplex();
|
||||
status = fillObd2FreezeFrame(&v);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mPropsMutex);
|
||||
|
||||
VehiclePropValue *internalPropValue = getVehiclePropValueLocked(propId, areaId);
|
||||
if (internalPropValue != nullptr) {
|
||||
v = pool.obtain(*internalPropValue);
|
||||
}
|
||||
}
|
||||
|
||||
if (v != nullptr) {
|
||||
status = StatusCode::OK;
|
||||
} else {
|
||||
status = StatusCode::INVALID_ARG;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
*outStatus = status;
|
||||
return v;
|
||||
}
|
||||
|
||||
StatusCode DefaultVehicleHal::set(const VehiclePropValue& propValue) {
|
||||
StatusCode status = updateProperty(propValue);
|
||||
|
||||
if (status == StatusCode::OK) {
|
||||
// Send property update to emulator
|
||||
emulator::EmulatorMessage msg;
|
||||
emulator::VehiclePropValue *val = msg.add_value();
|
||||
populateProtoVehiclePropValue(val, &propValue);
|
||||
msg.set_status(emulator::RESULT_OK);
|
||||
msg.set_msg_type(emulator::SET_PROPERTY_ASYNC);
|
||||
txMsg(msg);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Parse supported properties list and generate vector of property values to hold current values.
|
||||
void DefaultVehicleHal::onCreate() {
|
||||
// Initialize member variables
|
||||
mCurSocket = -1;
|
||||
mExit = 0;
|
||||
mSocket = -1;
|
||||
|
||||
// Get the list of configurations supported by this HAL
|
||||
std::vector<VehiclePropConfig> configs = listProperties();
|
||||
|
||||
for (auto& cfg : configs) {
|
||||
VehiclePropertyType propType = getPropType(cfg.prop);
|
||||
int32_t supportedAreas = cfg.supportedAreas;
|
||||
int32_t vecSize;
|
||||
|
||||
// Set the vector size based on property type
|
||||
switch (propType) {
|
||||
case VehiclePropertyType::BOOLEAN:
|
||||
case VehiclePropertyType::INT32:
|
||||
case VehiclePropertyType::INT64:
|
||||
case VehiclePropertyType::FLOAT:
|
||||
vecSize = 1;
|
||||
break;
|
||||
case VehiclePropertyType::INT32_VEC:
|
||||
case VehiclePropertyType::FLOAT_VEC:
|
||||
case VehiclePropertyType::BYTES:
|
||||
// TODO: Add proper support for these types
|
||||
vecSize = 1;
|
||||
break;
|
||||
case VehiclePropertyType::STRING:
|
||||
// Require individual handling
|
||||
vecSize = 0;
|
||||
break;
|
||||
case VehiclePropertyType::COMPLEX:
|
||||
switch (cfg.prop) {
|
||||
case toInt(VehicleProperty::OBD2_LIVE_FRAME):
|
||||
initObd2LiveFrame(cfg);
|
||||
break;
|
||||
default:
|
||||
// Need to handle each complex property separately
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
break;
|
||||
case VehiclePropertyType::MASK:
|
||||
default:
|
||||
ALOGW("%s: propType=0x%x not found", __FUNCTION__, propType);
|
||||
vecSize = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// A global property will have supportedAreas = 0
|
||||
if (getPropArea(cfg.prop) == VehicleArea::GLOBAL) {
|
||||
supportedAreas = 0;
|
||||
}
|
||||
|
||||
// This loop is a do-while so it executes at least once to handle global properties
|
||||
do {
|
||||
int32_t curArea = supportedAreas;
|
||||
|
||||
// Clear the right-most bit of supportedAreas
|
||||
supportedAreas &= supportedAreas - 1;
|
||||
|
||||
// Set curArea to the previously cleared bit
|
||||
curArea ^= supportedAreas;
|
||||
|
||||
// Create a separate instance for each individual zone
|
||||
std::unique_ptr<VehiclePropValue> prop = createVehiclePropValue(propType, vecSize);
|
||||
prop->areaId = curArea;
|
||||
prop->prop = cfg.prop;
|
||||
setDefaultValue(prop.get());
|
||||
mProps.push_back(std::move(prop));
|
||||
} while (supportedAreas != 0);
|
||||
}
|
||||
|
||||
// Start rx thread
|
||||
mThread = std::thread(&DefaultVehicleHal::rxThread, this);
|
||||
}
|
||||
|
||||
StatusCode DefaultVehicleHal::fillObd2LiveFrame(VehiclePropValuePtr* v) {
|
||||
|
||||
@@ -21,8 +21,12 @@
|
||||
|
||||
#include <VehicleHal.h>
|
||||
#include <impl/DefaultConfig.h>
|
||||
#include <vehicle_hal_manager/Obd2SensorStore.h>
|
||||
#include <sys/socket.h>
|
||||
#include <thread>
|
||||
#include <utils/SystemClock.h>
|
||||
#include <vehicle_hal_manager/Obd2SensorStore.h>
|
||||
#include "VehicleHalProto.pb.h"
|
||||
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
@@ -34,6 +38,23 @@ namespace impl {
|
||||
|
||||
class DefaultVehicleHal : public VehicleHal {
|
||||
public:
|
||||
DefaultVehicleHal() : mThread() {}
|
||||
~DefaultVehicleHal() override {
|
||||
// Notify thread to finish and wait for it to terminate
|
||||
mExit = 1;
|
||||
|
||||
// Close emulator socket if it is open
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mTxMutex);
|
||||
if (mCurSocket != -1) {
|
||||
close(mCurSocket);
|
||||
mCurSocket = -1;
|
||||
}
|
||||
}
|
||||
|
||||
mThread.join();
|
||||
}
|
||||
|
||||
std::vector<VehiclePropConfig> listProperties() override {
|
||||
return std::vector<VehiclePropConfig>(std::begin(kVehicleProperties),
|
||||
std::end(kVehicleProperties));
|
||||
@@ -46,38 +67,47 @@ public:
|
||||
|
||||
StatusCode set(const VehiclePropValue& propValue) override;
|
||||
|
||||
StatusCode subscribe(int32_t /*property*/,
|
||||
int32_t /*areas*/,
|
||||
float /*sampleRate*/) override {
|
||||
// TODO(pavelm): implement
|
||||
StatusCode subscribe(int32_t property, int32_t areas, float sampleRate) {
|
||||
ALOGD("%s: not implemented: prop=0x%x, areas=0x%x, rate=%f", __FUNCTION__, property,
|
||||
areas, sampleRate);
|
||||
return StatusCode::OK;
|
||||
}
|
||||
|
||||
StatusCode unsubscribe(int32_t /*property*/) override {
|
||||
// TODO(pavelm): implement
|
||||
StatusCode unsubscribe(int32_t property) {
|
||||
ALOGD("%s: not implemented: prop=0x%x", __FUNCTION__, property);
|
||||
return StatusCode::OK;
|
||||
}
|
||||
|
||||
private:
|
||||
StatusCode getHvacTemperature(int32_t areaId, float* outValue);
|
||||
StatusCode setHvacTemperature(int32_t areaId, float value);
|
||||
StatusCode getHvacDefroster(int32_t areaId, bool* outValue);
|
||||
StatusCode setHvacDefroster(int32_t areaId, bool value);
|
||||
void doGetConfig(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
|
||||
void doGetConfigAll(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
|
||||
void doGetProperty(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
|
||||
void doGetPropertyAll(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
|
||||
void doSetProperty(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
|
||||
VehiclePropValue* getVehiclePropValueLocked(int32_t propId, int32_t areaId);
|
||||
void initObd2LiveFrame(VehiclePropConfig& obd2LiveFramePropConfig);
|
||||
void parseRxProtoBuf(std::vector<uint8_t>& msg);
|
||||
void populateProtoVehicleConfig(emulator::VehiclePropConfig* protoCfg,
|
||||
const VehiclePropConfig& cfg);
|
||||
void populateProtoVehiclePropValue(emulator::VehiclePropValue* protoVal,
|
||||
const VehiclePropValue* val);
|
||||
void setDefaultValue(VehiclePropValue* prop);
|
||||
void rxMsg(void);
|
||||
void rxThread(void);
|
||||
void txMsg(emulator::EmulatorMessage& txMsg);
|
||||
StatusCode updateProperty(const VehiclePropValue& propValue);
|
||||
StatusCode fillObd2LiveFrame(VehiclePropValuePtr* v);
|
||||
StatusCode fillObd2FreezeFrame(VehiclePropValuePtr* v);
|
||||
private:
|
||||
int32_t mFanSpeed = 3;
|
||||
int32_t mBrightness = 7;
|
||||
float mRow1LeftHvacTemperatureSet = 16;
|
||||
float mRow1RightHvacTemperatureSet = 22;
|
||||
bool mFrontDefroster = false;
|
||||
bool mRearDefroster = false;
|
||||
bool mHvacPowerOn = true;
|
||||
bool mHvacRecircOn = true;
|
||||
bool mHvacAcOn = true;
|
||||
bool mHvacAutoOn = true;
|
||||
VehicleHvacFanDirection mFanDirection = VehicleHvacFanDirection::FACE;
|
||||
// TODO: Use a hashtable to support indexing props
|
||||
std::vector<std::unique_ptr<VehiclePropValue>> mProps;
|
||||
std::atomic<int> mCurSocket;
|
||||
std::atomic<int> mExit;
|
||||
std::unique_ptr<Obd2SensorStore> mObd2SensorStore{nullptr};
|
||||
std::mutex mPropsMutex;
|
||||
int mSocket;
|
||||
std::mutex mTxMutex;
|
||||
std::thread mThread;
|
||||
};
|
||||
|
||||
} // impl
|
||||
|
||||
100
automotive/vehicle/2.0/default/impl/proto/VehicleHalProto.proto
Normal file
100
automotive/vehicle/2.0/default/impl/proto/VehicleHalProto.proto
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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";
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
package emulator;
|
||||
|
||||
// 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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
|
||||
|
||||
// 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;
|
||||
};
|
||||
Reference in New Issue
Block a user