| /* |
| * Copyright (C) 2017 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. |
| */ |
| #define LOG_TAG "VehicleEmulator_v2_0" |
| |
| #include <android/log.h> |
| |
| #include <android-base/properties.h> |
| #include <log/log.h> |
| #include <utils/SystemClock.h> |
| #include <algorithm> |
| |
| #include <vhal_v2_0/ProtoMessageConverter.h> |
| #include <vhal_v2_0/VehicleUtils.h> |
| |
| #include "PipeComm.h" |
| #include "SocketComm.h" |
| |
| #include "VehicleEmulator.h" |
| |
| namespace android { |
| namespace hardware { |
| namespace automotive { |
| namespace vehicle { |
| namespace V2_0 { |
| |
| namespace impl { |
| |
| VehicleEmulator::VehicleEmulator(EmulatedServerIface* hal) : mHal{hal} { |
| mHal->registerEmulator(this); |
| |
| ALOGI("Starting SocketComm"); |
| mSocketComm = std::make_unique<SocketComm>(this); |
| mSocketComm->start(); |
| |
| if (isInQEMU()) { |
| ALOGI("Starting PipeComm"); |
| mPipeComm = std::make_unique<PipeComm>(this); |
| mPipeComm->start(); |
| } |
| } |
| |
| VehicleEmulator::~VehicleEmulator() { |
| mSocketComm->stop(); |
| if (mPipeComm) { |
| mPipeComm->stop(); |
| } |
| } |
| |
| /** |
| * This is called by the HAL when a property changes. We need to notify our clients that it has |
| * changed. |
| */ |
| void VehicleEmulator::doSetValueFromClient(const VehiclePropValue& propValue) { |
| vhal_proto::EmulatorMessage msg; |
| vhal_proto::VehiclePropValue* val = msg.add_value(); |
| populateProtoVehiclePropValue(val, &propValue); |
| msg.set_status(vhal_proto::RESULT_OK); |
| msg.set_msg_type(vhal_proto::SET_PROPERTY_ASYNC); |
| |
| mSocketComm->sendMessage(msg); |
| if (mPipeComm) { |
| mPipeComm->sendMessage(msg); |
| } |
| } |
| |
| void VehicleEmulator::doGetConfig(const VehicleEmulator::EmulatorMessage& rxMsg, |
| VehicleEmulator::EmulatorMessage* respMsg) { |
| std::vector<VehiclePropConfig> configs = mHal->listProperties(); |
| vhal_proto::VehiclePropGet getProp = rxMsg.prop(0); |
| |
| respMsg->set_msg_type(vhal_proto::GET_CONFIG_RESP); |
| respMsg->set_status(vhal_proto::ERROR_INVALID_PROPERTY); |
| |
| for (auto& config : configs) { |
| // Find the config we are looking for |
| if (config.prop == getProp.prop()) { |
| vhal_proto::VehiclePropConfig* protoCfg = respMsg->add_config(); |
| populateProtoVehicleConfig(protoCfg, config); |
| respMsg->set_status(vhal_proto::RESULT_OK); |
| break; |
| } |
| } |
| } |
| |
| void VehicleEmulator::doGetConfigAll(const VehicleEmulator::EmulatorMessage& /* rxMsg */, |
| VehicleEmulator::EmulatorMessage* respMsg) { |
| std::vector<VehiclePropConfig> configs = mHal->listProperties(); |
| |
| respMsg->set_msg_type(vhal_proto::GET_CONFIG_ALL_RESP); |
| respMsg->set_status(vhal_proto::RESULT_OK); |
| |
| for (auto& config : configs) { |
| vhal_proto::VehiclePropConfig* protoCfg = respMsg->add_config(); |
| populateProtoVehicleConfig(protoCfg, config); |
| } |
| } |
| |
| void VehicleEmulator::doGetProperty(const VehicleEmulator::EmulatorMessage& rxMsg, |
| VehicleEmulator::EmulatorMessage* respMsg) { |
| int32_t areaId = 0; |
| vhal_proto::VehiclePropGet getProp = rxMsg.prop(0); |
| int32_t propId = getProp.prop(); |
| vhal_proto::Status status = vhal_proto::ERROR_INVALID_PROPERTY; |
| |
| respMsg->set_msg_type(vhal_proto::GET_PROPERTY_RESP); |
| |
| if (getProp.has_area_id()) { |
| areaId = getProp.area_id(); |
| } |
| |
| { |
| VehiclePropValue request = { |
| .areaId = areaId, |
| .prop = propId, |
| }; |
| StatusCode halStatus; |
| auto val = mHal->get(request, &halStatus); |
| if (val != nullptr) { |
| vhal_proto::VehiclePropValue* protoVal = respMsg->add_value(); |
| populateProtoVehiclePropValue(protoVal, val.get()); |
| status = vhal_proto::RESULT_OK; |
| } |
| } |
| |
| respMsg->set_status(status); |
| } |
| |
| void VehicleEmulator::doGetPropertyAll(const VehicleEmulator::EmulatorMessage& /* rxMsg */, |
| VehicleEmulator::EmulatorMessage* respMsg) { |
| respMsg->set_msg_type(vhal_proto::GET_PROPERTY_ALL_RESP); |
| respMsg->set_status(vhal_proto::RESULT_OK); |
| |
| { |
| for (const auto& prop : mHal->getAllProperties()) { |
| vhal_proto::VehiclePropValue* protoVal = respMsg->add_value(); |
| populateProtoVehiclePropValue(protoVal, &prop); |
| } |
| } |
| } |
| |
| void VehicleEmulator::doSetProperty(const VehicleEmulator::EmulatorMessage& rxMsg, |
| VehicleEmulator::EmulatorMessage* respMsg) { |
| vhal_proto::VehiclePropValue protoVal = rxMsg.value(0); |
| VehiclePropValue val = { |
| .timestamp = elapsedRealtimeNano(), |
| .areaId = protoVal.area_id(), |
| .prop = protoVal.prop(), |
| .status = (VehiclePropertyStatus)protoVal.status(), |
| }; |
| |
| respMsg->set_msg_type(vhal_proto::SET_PROPERTY_RESP); |
| |
| // 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()) { |
| val.value.bytes = std::vector<uint8_t> { protoVal.bytes_value().begin(), |
| protoVal.bytes_value().end() }; |
| } |
| |
| if (protoVal.int32_values_size() > 0) { |
| val.value.int32Values = std::vector<int32_t> { protoVal.int32_values().begin(), |
| protoVal.int32_values().end() }; |
| } |
| |
| if (protoVal.int64_values_size() > 0) { |
| val.value.int64Values = std::vector<int64_t> { protoVal.int64_values().begin(), |
| protoVal.int64_values().end() }; |
| } |
| |
| if (protoVal.float_values_size() > 0) { |
| val.value.floatValues = std::vector<float> { protoVal.float_values().begin(), |
| protoVal.float_values().end() }; |
| } |
| |
| bool halRes = mHal->setPropertyFromVehicle(val); |
| respMsg->set_status(halRes ? vhal_proto::RESULT_OK : vhal_proto::ERROR_INVALID_PROPERTY); |
| } |
| |
| void VehicleEmulator::doDebug(const vhal_proto::EmulatorMessage& rxMsg, |
| vhal_proto::EmulatorMessage* respMsg) { |
| auto protoCommands = rxMsg.debug_commands(); |
| std::vector<std::string> commands = std::vector<std::string>( |
| protoCommands.begin(), protoCommands.end()); |
| IVehicleServer::DumpResult result = mHal->debug(commands); |
| respMsg->set_status(vhal_proto::RESULT_OK); |
| respMsg->set_msg_type(vhal_proto::DEBUG_RESP); |
| respMsg->set_debug_result(result.buffer); |
| } |
| |
| void VehicleEmulator::processMessage(const vhal_proto::EmulatorMessage& rxMsg, |
| vhal_proto::EmulatorMessage* respMsg) { |
| switch (rxMsg.msg_type()) { |
| case vhal_proto::GET_CONFIG_CMD: |
| doGetConfig(rxMsg, respMsg); |
| break; |
| case vhal_proto::GET_CONFIG_ALL_CMD: |
| doGetConfigAll(rxMsg, respMsg); |
| break; |
| case vhal_proto::GET_PROPERTY_CMD: |
| doGetProperty(rxMsg, respMsg); |
| break; |
| case vhal_proto::GET_PROPERTY_ALL_CMD: |
| doGetPropertyAll(rxMsg, respMsg); |
| break; |
| case vhal_proto::SET_PROPERTY_CMD: |
| doSetProperty(rxMsg, respMsg); |
| break; |
| case vhal_proto::DEBUG_CMD: |
| doDebug(rxMsg, respMsg); |
| break; |
| default: |
| ALOGW("%s: Unknown message received, type = %d", __func__, rxMsg.msg_type()); |
| respMsg->set_status(vhal_proto::ERROR_UNIMPLEMENTED_CMD); |
| break; |
| } |
| } |
| |
| void VehicleEmulator::populateProtoVehicleConfig(vhal_proto::VehiclePropConfig* protoCfg, |
| const VehiclePropConfig& cfg) { |
| return proto_msg_converter::toProto(protoCfg, cfg); |
| } |
| |
| void VehicleEmulator::populateProtoVehiclePropValue(vhal_proto::VehiclePropValue* protoVal, |
| const VehiclePropValue* val) { |
| return proto_msg_converter::toProto(protoVal, *val); |
| } |
| |
| bool isInQEMU() { |
| return android::base::GetBoolProperty("ro.boot.qemu", false); |
| } |
| |
| } // impl |
| |
| } // namespace V2_0 |
| } // namespace vehicle |
| } // namespace automotive |
| } // namespace hardware |
| } // namespace android |