diff options
author | Xin Li <delphij@google.com> | 2022-06-28 21:23:15 +0000 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2022-06-28 21:23:15 +0000 |
commit | 8d7f62061eaf2993eece5614a8de37aa286feb29 (patch) | |
tree | 8d903d2222c6c1733589b7b2e3458465d9635fb8 | |
parent | c44d9f40639efdb885a261f071cf33be389925b4 (diff) | |
parent | 1dafa1ea1d1f73ee8a7654fca929f87bf8fd037c (diff) | |
download | car-temp_sam_242648940.tar.gz |
Merge tm-dev-plus-aosp-without-vendor@8763363temp_sam_242648940
Bug: 236760014
Merged-In: Id5ea4670f6e87629666aae6b5c1cfe64b0e4e7b2
Change-Id: Ib0cab0e6ca0e559dfd98480677729b88fb9ba6bb
88 files changed, 4643 insertions, 159 deletions
diff --git a/car_ui_portrait.mk b/car_ui_portrait.mk index 88675a5..c65fbdb 100644 --- a/car_ui_portrait.mk +++ b/car_ui_portrait.mk @@ -34,6 +34,7 @@ $(call inherit-product, device/generic/car/emulator/aosp_car_emulator.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_x86_64.mk) $(call inherit-product, packages/services/Car/car_product/car_ui_portrait/apps/car_ui_portrait_apps.mk) $(call inherit-product, packages/services/Car/car_product/car_ui_portrait/rro/car_ui_portrait_rro.mk) +$(call inherit-product, packages/services/Car/car_product/car_ui_portrait/emu/car_ui_portrait_emu.mk) PRODUCT_SDK_ADDON_NAME := car_emu_x86_64 diff --git a/common/car.mk b/common/car.mk index 583c1a3..cbcf55a 100644 --- a/common/car.mk +++ b/common/car.mk @@ -16,7 +16,7 @@ # Auto modules PRODUCT_PACKAGES += \ - android.hardware.automotive.vehicle@2.0-service \ + android.hardware.automotive.vehicle@V1-emulator-service \ android.hardware.broadcastradio@2.0-service \ android.hardware.audio.service-caremu @@ -72,6 +72,10 @@ PRODUCT_COPY_FILES += \ PRODUCT_COPY_FILES += \ frameworks/native/data/etc/android.hardware.sensor.accelerometer.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.accelerometer.xml \ frameworks/native/data/etc/android.hardware.sensor.gyroscope.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.gyroscope.xml \ + frameworks/native/data/etc/android.hardware.sensor.accelerometer_limited_axes.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.accelerometer_limited_axes.xml \ + frameworks/native/data/etc/android.hardware.sensor.gyroscope_limited_axes.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.gyroscope_limited_axes.xml \ + frameworks/native/data/etc/android.hardware.sensor.accelerometer_limited_axes_uncalibrated.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.accelerometer_limited_axes_uncalibrated.xml \ + frameworks/native/data/etc/android.hardware.sensor.gyroscope_limited_axes_uncalibrated.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.gyroscope_limited_axes_uncalibrated.xml \ # Copy APN configs PRODUCT_COPY_FILES += \ diff --git a/common/car_core_hardware.xml b/common/car_core_hardware.xml index 2acfdde..99ff362 100644 --- a/common/car_core_hardware.xml +++ b/common/car_core_hardware.xml @@ -40,8 +40,11 @@ <!-- Notably bluetooth is added to avoid crashing. It does not work in the emulator. --> <feature name="android.hardware.bluetooth" /> + <!-- Indicate support for the Android security model per the CDD. --> + <feature name="android.hardware.security.model.compatible" /> + <!-- basic system services --> - <feature name="android.software.connectionservice" /> + <feature name="android.software.telecom" /> <feature name="android.software.voice_recognizers" notLowRam="true" /> <feature name="android.software.home_screen" /> <feature name="android.software.companion_device_setup" /> diff --git a/common/overlay/frameworks/base/core/res/res/values/config.xml b/common/overlay/frameworks/base/core/res/res/values/config.xml index 6933a49..fa815d2 100644 --- a/common/overlay/frameworks/base/core/res/res/values/config.xml +++ b/common/overlay/frameworks/base/core/res/res/values/config.xml @@ -25,4 +25,8 @@ <!-- AAOS doesn't support fingerprint and face --> <string-array name="config_biometric_sensors" translatable="false" > </string-array> + + <integer-array name="config_availableColorModes"> + <item>0</item> <!-- COLOR_MODE_NATURAL --> + </integer-array> </resources> diff --git a/common/overlay/frameworks/base/core/res/res/values/vendor_required_apps_managed_user.xml b/common/overlay/frameworks/base/core/res/res/values/vendor_required_apps_managed_user.xml index dceae9a..5784afa 100644 --- a/common/overlay/frameworks/base/core/res/res/values/vendor_required_apps_managed_user.xml +++ b/common/overlay/frameworks/base/core/res/res/values/vendor_required_apps_managed_user.xml @@ -30,6 +30,7 @@ <item>com.google.android.car.kitchensink</item> <item>com.google.android.car.netdbug</item> <item>com.google.android.car.networking.preferenceupdater</item> + <item>com.google.android.car.networking.railway</item> <item>com.google.android.car.setupwizard</item> <item>com.google.android.car.uxr.oas</item> <item>com.google.android.car.uxr.sample</item> diff --git a/common/overlay/packages/services/Car/service/res/values/config.xml b/common/overlay/packages/services/Car/service/res/values/config.xml deleted file mode 100644 index f29d9da..0000000 --- a/common/overlay/packages/services/Car/service/res/values/config.xml +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2021, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<!-- Resources to configure car service based on each OEM's preference. --> - -<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- The camera Activity name for EVS, if defined, the Activity will be launched by - CarEvsService. --> - <string name="config_evsCameraActivity" translatable="false"> - com.google.android.car.evs/com.google.android.car.evs.CarEvsCameraPreviewActivity - </string> -</resources> diff --git a/common/preinstalled-packages-product-car-emulator.xml b/common/preinstalled-packages-product-car-emulator.xml index 9dd99f9..68137ef 100644 --- a/common/preinstalled-packages-product-car-emulator.xml +++ b/common/preinstalled-packages-product-car-emulator.xml @@ -42,6 +42,10 @@ <install-in user-type="FULL" /> <install-in user-type="SYSTEM" /> </install-in-user-type> + <install-in-user-type package="com.android.localtransport"> + <install-in user-type="FULL" /> + <install-in user-type="SYSTEM" /> + </install-in-user-type> <!-- Android remote display which need to work for all users--> <install-in-user-type package="com.android.car.acast.source"> @@ -112,9 +116,6 @@ <install-in-user-type package="com.android.dynsystem"> <install-in user-type="FULL" /> </install-in-user-type> - <install-in-user-type package="com.android.localtransport"> - <install-in user-type="FULL" /> - </install-in-user-type> <install-in-user-type package="com.android.mms.service"> <install-in user-type="FULL" /> </install-in-user-type> diff --git a/emulator/Conn/CommConn/Android.bp b/emulator/Conn/CommConn/Android.bp new file mode 100644 index 0000000..9de4e08 --- /dev/null +++ b/emulator/Conn/CommConn/Android.bp @@ -0,0 +1,33 @@ +// Copyright (C) 2022 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_applicable_licenses: ["device_generic_car_license"], +} + +cc_library { + name: "EmulatorCommConn", + vendor: true, + srcs: [ + "*.cpp", + ], + shared_libs: [ + "liblog", + "libprotobuf-cpp-lite", + ], + export_include_dirs: ["include"], + static_libs: [ + "android.hardware.automotive.vehicle@2.0-libproto-native", + ], +} diff --git a/emulator/Conn/CommConn/CommConn.cpp b/emulator/Conn/CommConn/CommConn.cpp new file mode 100644 index 0000000..c800edc --- /dev/null +++ b/emulator/Conn/CommConn/CommConn.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2018 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 "CommConn" + +#include <thread> + +#include <log/log.h> + +#include "CommConn.h" + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace V2_0 { + +namespace impl { + +void CommConn::start() { + mReadThread = std::make_unique<std::thread>(std::bind(&CommConn::readThread, this)); +} + +void CommConn::stop() { + if (mReadThread->joinable()) { + mReadThread->join(); + } +} + +void CommConn::sendMessage(vhal_proto::EmulatorMessage const& msg) { + int numBytes = msg.ByteSize(); + std::vector<uint8_t> buffer(static_cast<size_t>(numBytes)); + if (!msg.SerializeToArray(buffer.data(), numBytes)) { + ALOGE("%s: SerializeToString failed!", __func__); + return; + } + + write(buffer); +} + +void CommConn::readThread() { + std::vector<uint8_t> buffer; + while (isOpen()) { + buffer = read(); + if (buffer.size() == 0) { + ALOGI("%s: Read returned empty message, exiting read loop.", __func__); + break; + } + + vhal_proto::EmulatorMessage rxMsg; + if (rxMsg.ParseFromArray(buffer.data(), static_cast<int32_t>(buffer.size()))) { + vhal_proto::EmulatorMessage respMsg; + mMessageProcessor->processMessage(rxMsg, &respMsg); + + sendMessage(respMsg); + } + } +} + +} // namespace impl + +} // namespace V2_0 +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/emulator/Conn/CommConn/include/CommConn.h b/emulator/Conn/CommConn/include/CommConn.h new file mode 100644 index 0000000..ba5fd9f --- /dev/null +++ b/emulator/Conn/CommConn/include/CommConn.h @@ -0,0 +1,140 @@ +/* + * 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. + */ + +#ifndef ANDROID_EMULATORCOMMCONN_COMMCONN_H +#define ANDROID_EMULATORCOMMCONN_COMMCONN_H + +#include <string> +#include <thread> +#include <vector> + +#include "VehicleHalProto.pb.h" + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace V2_0 { + +namespace impl { + +/** + * MessageProcess is an interface implemented by VehicleEmulator to process messages received + * over a CommConn. + */ +class MessageProcessor { + public: + virtual ~MessageProcessor() = default; + + /** + * Process a single message received over a CommConn. Populate the given respMsg with the reply + * message we should send. + */ + virtual void processMessage(const vhal_proto::EmulatorMessage& rxMsg, + vhal_proto::EmulatorMessage* respMsg) = 0; +}; + +/** + * This is a pure virtual interface that could start/stop and send message. + * This is implemented by CommConn and SocketComm. + */ +class MessageSender { + public: + virtual ~MessageSender() {} + + /** + * Starts the read thread reading messages from this connection. + */ + virtual void start() = 0; + + /** + * Closes a connection if it is open. + */ + virtual void stop() = 0; + + /** + * Serializes and sends the given message to the other side. + */ + virtual void sendMessage(const vhal_proto::EmulatorMessage& msg) = 0; +}; + +/** + * This is the interface that both PipeComm and SocketComm use to represent a connection. The + * connection will listen for commands on a separate 'read' thread. + */ +class CommConn : public MessageSender { + public: + CommConn(MessageProcessor* messageProcessor) : mMessageProcessor(messageProcessor) {} + + virtual ~CommConn() {} + + /** + * Start the read thread reading messages from this connection. + */ + void start() override; + + /** + * Closes a connection if it is open. + */ + void stop() override; + + /** + * Returns true if the connection is open and available to send/receive. + */ + virtual bool isOpen() = 0; + + /** + * Blocking call to read data from the connection. + * + * @return std::vector<uint8_t> Serialized protobuf data received from emulator. This will be + * an empty vector if the connection was closed or some other error occurred. + */ + virtual std::vector<uint8_t> read() = 0; + + /** + * Transmits a string of data to the emulator. + * + * @param data Serialized protobuf data to transmit. + * + * @return int Number of bytes transmitted, or -1 if failed. + */ + virtual int write(const std::vector<uint8_t>& data) = 0; + + /** + * Serialized and send the given message to the other side. + */ + void sendMessage(const vhal_proto::EmulatorMessage& msg); + + protected: + std::unique_ptr<std::thread> mReadThread; + MessageProcessor* mMessageProcessor; + + /** + * A thread that reads messages in a loop, and responds. You can stop this thread by calling + * stop(). + */ + void readThread(); +}; + +} // namespace impl + +} // namespace V2_0 +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // ANDROID_EMULATORCOMMCONN_COMMCONN_H diff --git a/emulator/Conn/PipeComm/Android.bp b/emulator/Conn/PipeComm/Android.bp new file mode 100644 index 0000000..6f8e3b4 --- /dev/null +++ b/emulator/Conn/PipeComm/Android.bp @@ -0,0 +1,35 @@ +// Copyright (C) 2022 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_applicable_licenses: ["device_generic_car_license"], +} + +cc_library { + name: "EmulatorPipeComm", + vendor: true, + srcs: [ + "*.cpp", + ], + shared_libs: [ + "libbase", + "liblog", + "libprotobuf-cpp-lite", + ], + export_include_dirs: ["include"], + static_libs: [ + "android.hardware.automotive.vehicle@2.0-libproto-native", + "EmulatorCommConn", + ], +} diff --git a/emulator/Conn/PipeComm/PipeComm.cpp b/emulator/Conn/PipeComm/PipeComm.cpp new file mode 100644 index 0000000..c54bf9f --- /dev/null +++ b/emulator/Conn/PipeComm/PipeComm.cpp @@ -0,0 +1,105 @@ +/* + * 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 "PipeComm" + +#include <log/log.h> + +#include "qemu_pipe.h" + +#include "PipeComm.h" + +#define CAR_SERVICE_NAME "pipe:qemud:car" + + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace V2_0 { + +namespace impl { + +PipeComm::PipeComm(MessageProcessor* messageProcessor) : CommConn(messageProcessor), mPipeFd(-1) {} + +void PipeComm::start() { + int fd = qemu_pipe_open(CAR_SERVICE_NAME); + + if (fd < 0) { + ALOGE("%s: Could not open connection to service: %s %d", __FUNCTION__, strerror(errno), fd); + return; + } + + ALOGI("%s: Starting pipe connection, fd=%d", __FUNCTION__, fd); + mPipeFd = fd; + + CommConn::start(); +} + +void PipeComm::stop() { + if (mPipeFd > 0) { + ::close(mPipeFd); + mPipeFd = -1; + } + CommConn::stop(); +} + +std::vector<uint8_t> PipeComm::read() { + static constexpr int MAX_RX_MSG_SZ = 2048; + std::vector<uint8_t> msg = std::vector<uint8_t>(MAX_RX_MSG_SZ); + int numBytes; + + numBytes = qemu_pipe_frame_recv(mPipeFd, msg.data(), msg.size()); + + if (numBytes == MAX_RX_MSG_SZ) { + ALOGE("%s: Received max size = %d", __FUNCTION__, MAX_RX_MSG_SZ); + } else if (numBytes > 0) { + msg.resize(numBytes); + return msg; + } else { + ALOGD("%s: Connection terminated on pipe %d, numBytes=%d", __FUNCTION__, mPipeFd, numBytes); + mPipeFd = -1; + } + + return std::vector<uint8_t>(); +} + +int PipeComm::write(const std::vector<uint8_t>& data) { + int retVal = 0; + + if (mPipeFd != -1) { + retVal = qemu_pipe_frame_send(mPipeFd, data.data(), data.size()); + } + + if (retVal < 0) { + retVal = -errno; + ALOGE("%s: send_cmd: (fd=%d): ERROR: %s", __FUNCTION__, mPipeFd, strerror(errno)); + } + + return retVal; +} + + +} // impl + +} // namespace V2_0 +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + + + diff --git a/emulator/Conn/PipeComm/include/PipeComm.h b/emulator/Conn/PipeComm/include/PipeComm.h new file mode 100644 index 0000000..24dd686 --- /dev/null +++ b/emulator/Conn/PipeComm/include/PipeComm.h @@ -0,0 +1,64 @@ +/* + * 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. + */ + +#ifndef ANDROID_EMULATORPIPECOMM_PIPECOMM_H +#define ANDROID_EMULATORPIPECOMM_PIPECOMM_H + +#include <mutex> +#include <vector> + +#include "CommConn.h" + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace V2_0 { + +namespace impl { + +/** + * PipeComm opens a qemu pipe to connect to the emulator, allowing the emulator UI to access the + * Vehicle HAL and simulate changing properties. + * + * Since the pipe is a client, it directly implements CommConn, and only one PipeComm can be open + * at a time. + */ +class PipeComm : public CommConn { + public: + PipeComm(MessageProcessor* messageProcessor); + + void start() override; + void stop() override; + + std::vector<uint8_t> read() override; + int write(const std::vector<uint8_t>& data) override; + + inline bool isOpen() override { return mPipeFd > 0; } + + private: + int mPipeFd; +}; + +} // impl + +} // namespace V2_0 +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // ANDROID_EMULATORPIPECOMM_PIPECOMM_H diff --git a/emulator/Conn/PipeComm/include/qemu_pipe.h b/emulator/Conn/PipeComm/include/qemu_pipe.h new file mode 100644 index 0000000..bd3e71d --- /dev/null +++ b/emulator/Conn/PipeComm/include/qemu_pipe.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_EMULATORPIPECOMM_QEMU_PIPE_H +#define ANDROID_EMULATORPIPECOMM_QEMU_PIPE_H + +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif +// Try to open a new Qemu fast-pipe. This function returns a file descriptor +// that can be used to communicate with a named service managed by the +// emulator. +// +// This file descriptor can be used as a standard pipe/socket descriptor. +// +// 'pipeName' is the name of the emulator service you want to connect to, +// and should begin with 'pipe:' (e.g. 'pipe:camera' or 'pipe:opengles'). +// For backward compatibility, the 'pipe:' prefix can be omitted, and in +// that case, qemu_pipe_open will add it for you. + +// On success, return a valid file descriptor, or -1/errno on failure. E.g.: +// +// EINVAL -> unknown/unsupported pipeName +// ENOSYS -> fast pipes not available in this system. +// +// ENOSYS should never happen, except if you're trying to run within a +// misconfigured emulator. +// +// You should be able to open several pipes to the same pipe service, +// except for a few special cases (e.g. GSM modem), where EBUSY will be +// returned if more than one client tries to connect to it. +int qemu_pipe_open(const char* pipeName); + +// Send a framed message |buff| of |len| bytes through the |fd| descriptor. +// This really adds a 4-hexchar prefix describing the payload size. +// Returns 0 on success, and -1 on error. +int qemu_pipe_frame_send(int fd, const void* buff, size_t len); + +// Read a frame message from |fd|, and store it into |buff| of |len| bytes. +// If the framed message is larger than |len|, then this returns -1 and the +// content is lost. Otherwise, this returns the size of the message. NOTE: +// empty messages are possible in a framed wire protocol and do not mean +// end-of-stream. +int qemu_pipe_frame_recv(int fd, void* buff, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif // ANDROID_EMULATORPIPECOMM_QEMU_PIPE_H diff --git a/emulator/Conn/PipeComm/qemu_pipe.cpp b/emulator/Conn/PipeComm/qemu_pipe.cpp new file mode 100644 index 0000000..1f541b5 --- /dev/null +++ b/emulator/Conn/PipeComm/qemu_pipe.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include <android-base/file.h> + +#include "qemu_pipe.h" + +using android::base::ReadFully; +using android::base::WriteFully; + +// Define QEMU_PIPE_DEBUG if you want to print error messages when an error +// occurs during pipe operations. The macro should simply take a printf-style +// formatting string followed by optional arguments. +#ifndef QEMU_PIPE_DEBUG +#define QEMU_PIPE_DEBUG(...) (void)0 +#endif + +int qemu_pipe_open(const char* pipeName) { + if (!pipeName) { + errno = EINVAL; + return -1; + } + + int fd = TEMP_FAILURE_RETRY(open("/dev/qemu_pipe", O_RDWR)); + if (fd < 0) { + QEMU_PIPE_DEBUG("%s: Could not open /dev/qemu_pipe: %s", __FUNCTION__, strerror(errno)); + return -1; + } + + // Write the pipe name, *including* the trailing zero which is necessary. + size_t pipeNameLen = strlen(pipeName); + if (WriteFully(fd, pipeName, pipeNameLen + 1U)) { + return fd; + } + + // now, add 'pipe:' prefix and try again + // Note: host side will wait for the trailing '\0' to start + // service lookup. + const char pipe_prefix[] = "pipe:"; + if (WriteFully(fd, pipe_prefix, strlen(pipe_prefix)) && + WriteFully(fd, pipeName, pipeNameLen + 1U)) { + return fd; + } + QEMU_PIPE_DEBUG("%s: Could not write to %s pipe service: %s", __FUNCTION__, pipeName, + strerror(errno)); + close(fd); + return -1; +} + +int qemu_pipe_frame_send(int fd, const void* buff, size_t len) { + char header[5]; + snprintf(header, sizeof(header), "%04zx", len); + if (!WriteFully(fd, header, 4)) { + QEMU_PIPE_DEBUG("Can't write qemud frame header: %s", strerror(errno)); + return -1; + } + if (!WriteFully(fd, buff, len)) { + QEMU_PIPE_DEBUG("Can't write qemud frame payload: %s", strerror(errno)); + return -1; + } + return 0; +} + +int qemu_pipe_frame_recv(int fd, void* buff, size_t len) { + char header[5]; + if (!ReadFully(fd, header, 4)) { + QEMU_PIPE_DEBUG("Can't read qemud frame header: %s", strerror(errno)); + return -1; + } + header[4] = '\0'; + size_t size; + if (sscanf(header, "%04zx", &size) != 1) { + QEMU_PIPE_DEBUG("Malformed qemud frame header: [%.*s]", 4, header); + return -1; + } + if (size > len) { + QEMU_PIPE_DEBUG("Oversized qemud frame (% bytes, expected <= %)", size, len); + return -1; + } + if (!ReadFully(fd, buff, size)) { + QEMU_PIPE_DEBUG("Could not read qemud frame payload: %s", strerror(errno)); + return -1; + } + return size; +} diff --git a/emulator/Conn/SocketComm/Android.bp b/emulator/Conn/SocketComm/Android.bp new file mode 100644 index 0000000..0a186d1 --- /dev/null +++ b/emulator/Conn/SocketComm/Android.bp @@ -0,0 +1,34 @@ +// Copyright (C) 2022 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_applicable_licenses: ["device_generic_car_license"], +} + +cc_library { + name: "EmulatorSocketComm", + vendor: true, + srcs: [ + "*.cpp", + ], + shared_libs: [ + "liblog", + "libprotobuf-cpp-lite", + ], + export_include_dirs: ["include"], + static_libs: [ + "android.hardware.automotive.vehicle@2.0-libproto-native", + "EmulatorCommConn", + ], +} diff --git a/emulator/Conn/SocketComm/SocketComm.cpp b/emulator/Conn/SocketComm/SocketComm.cpp new file mode 100644 index 0000000..1e9a9bd --- /dev/null +++ b/emulator/Conn/SocketComm/SocketComm.cpp @@ -0,0 +1,225 @@ +/* + * 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 "SocketComm" + +#include <android/log.h> +#include <arpa/inet.h> +#include <log/log.h> +#include <netinet/in.h> +#include <sys/socket.h> + +#include "SocketComm.h" + +// Socket to use when communicating with Host PC +static constexpr int DEBUG_SOCKET = 33452; + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace V2_0 { + +namespace impl { + +SocketComm::SocketComm(MessageProcessor* messageProcessor) + : mListenFd(-1), mMessageProcessor(messageProcessor) {} + +SocketComm::~SocketComm() { +} + +void SocketComm::start() { + if (!listen()) { + return; + } + + mListenThread = std::make_unique<std::thread>(std::bind(&SocketComm::listenThread, this)); +} + +void SocketComm::stop() { + if (mListenFd > 0) { + ::close(mListenFd); + if (mListenThread->joinable()) { + mListenThread->join(); + } + mListenFd = -1; + } +} + +void SocketComm::sendMessage(vhal_proto::EmulatorMessage const& msg) { + std::lock_guard<std::mutex> lock(mMutex); + for (std::unique_ptr<SocketConn> const& conn : mOpenConnections) { + conn->sendMessage(msg); + } +} + +bool SocketComm::listen() { + int retVal; + struct sockaddr_in servAddr; + + mListenFd = socket(AF_INET, SOCK_STREAM, 0); + if (mListenFd < 0) { + ALOGE("%s: socket() failed, mSockFd=%d, errno=%d", __FUNCTION__, mListenFd, errno); + mListenFd = -1; + return false; + } + + memset(&servAddr, 0, sizeof(servAddr)); + servAddr.sin_family = AF_INET; + servAddr.sin_addr.s_addr = INADDR_ANY; + servAddr.sin_port = htons(DEBUG_SOCKET); + + retVal = bind(mListenFd, reinterpret_cast<struct sockaddr*>(&servAddr), sizeof(servAddr)); + if(retVal < 0) { + ALOGE("%s: Error on binding: retVal=%d, errno=%d", __FUNCTION__, retVal, errno); + close(mListenFd); + mListenFd = -1; + return false; + } + + ALOGI("%s: Listening for connections on port %d", __FUNCTION__, DEBUG_SOCKET); + if (::listen(mListenFd, 1) == -1) { + ALOGE("%s: Error on listening: errno: %d: %s", __FUNCTION__, errno, strerror(errno)); + return false; + } + return true; +} + +SocketConn* SocketComm::accept() { + sockaddr_in cliAddr; + socklen_t cliLen = sizeof(cliAddr); + int sfd = ::accept(mListenFd, reinterpret_cast<struct sockaddr*>(&cliAddr), &cliLen); + + if (sfd > 0) { + char addr[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &cliAddr.sin_addr, addr, INET_ADDRSTRLEN); + + ALOGD("%s: Incoming connection received from %s:%d", __FUNCTION__, addr, cliAddr.sin_port); + return new SocketConn(mMessageProcessor, sfd); + } + + return nullptr; +} + +void SocketComm::listenThread() { + while (true) { + SocketConn* conn = accept(); + if (conn == nullptr) { + return; + } + + conn->start(); + { + std::lock_guard<std::mutex> lock(mMutex); + mOpenConnections.push_back(std::unique_ptr<SocketConn>(conn)); + } + } +} + +/** + * Called occasionally to clean up connections that have been closed. + */ +void SocketComm::removeClosedConnections() { + std::lock_guard<std::mutex> lock(mMutex); + std::remove_if(mOpenConnections.begin(), mOpenConnections.end(), + [](std::unique_ptr<SocketConn> const& c) { return !c->isOpen(); }); +} + +SocketConn::SocketConn(MessageProcessor* messageProcessor, int sfd) + : CommConn(messageProcessor), mSockFd(sfd) {} + +/** + * Reads, in a loop, exactly numBytes from the given fd. If the connection is closed, returns + * an empty buffer, otherwise will return exactly the given number of bytes. + */ +std::vector<uint8_t> readExactly(int fd, int numBytes) { + std::vector<uint8_t> buffer(numBytes); + int totalRead = 0; + int offset = 0; + while (totalRead < numBytes) { + int numRead = ::read(fd, &buffer.data()[offset], numBytes - offset); + if (numRead == 0) { + buffer.resize(0); + return buffer; + } + + totalRead += numRead; + } + return buffer; +} + +/** + * Reads an int, guaranteed to be non-zero, from the given fd. If the connection is closed, returns + * -1. + */ +int32_t readInt(int fd) { + std::vector<uint8_t> buffer = readExactly(fd, sizeof(int32_t)); + if (buffer.size() == 0) { + return -1; + } + + int32_t value = *reinterpret_cast<int32_t*>(buffer.data()); + return ntohl(value); +} + +std::vector<uint8_t> SocketConn::read() { + int32_t msgSize = readInt(mSockFd); + if (msgSize <= 0) { + ALOGD("%s: Connection terminated on socket %d", __FUNCTION__, mSockFd); + return std::vector<uint8_t>(); + } + + return readExactly(mSockFd, msgSize); +} + +void SocketConn::stop() { + if (mSockFd > 0) { + close(mSockFd); + mSockFd = -1; + } +} + +int SocketConn::write(const std::vector<uint8_t>& data) { + static constexpr int MSG_HEADER_LEN = 4; + int retVal = 0; + union { + uint32_t msgLen; + uint8_t msgLenBytes[MSG_HEADER_LEN]; + }; + + // Prepare header for the message + msgLen = static_cast<uint32_t>(data.size()); + msgLen = htonl(msgLen); + + if (mSockFd > 0) { + retVal = ::write(mSockFd, msgLenBytes, MSG_HEADER_LEN); + + if (retVal == MSG_HEADER_LEN) { + retVal = ::write(mSockFd, data.data(), data.size()); + } + } + + return retVal; +} + +} // impl + +} // namespace V2_0 +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + diff --git a/emulator/Conn/SocketComm/include/SocketComm.h b/emulator/Conn/SocketComm/include/SocketComm.h new file mode 100644 index 0000000..4e385c3 --- /dev/null +++ b/emulator/Conn/SocketComm/include/SocketComm.h @@ -0,0 +1,124 @@ +/* + * 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. + */ + +#ifndef ANDROID_EMULATORSOCKETCOMM_SOCKETCOMM_H +#define ANDROID_EMULATORSOCKETCOMM_SOCKETCOMM_H + +#include <mutex> +#include <thread> +#include <vector> +#include "CommConn.h" + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace V2_0 { + +namespace impl { + +class SocketConn; + +/** + * SocketComm opens a socket, and listens for connections from clients. Typically the client will be + * adb's TCP port-forwarding to enable a host PC to connect to the VehicleHAL. + */ +class SocketComm : public MessageSender { + public: + SocketComm(MessageProcessor* messageProcessor); + virtual ~SocketComm(); + + void start() override; + void stop() override ; + + /** + * Serialized and send the given message to all connected clients. + */ + void sendMessage(vhal_proto::EmulatorMessage const& msg) override; + + private: + int mListenFd; + std::unique_ptr<std::thread> mListenThread; + std::vector<std::unique_ptr<SocketConn>> mOpenConnections; + MessageProcessor* mMessageProcessor; + std::mutex mMutex; + + /** + * Opens the socket and begins listening. + * + * @return bool Returns true on success. + */ + bool listen(); + + /** + * Blocks and waits for a connection from a client, returns a new SocketConn with the connection + * or null, if the connection has been closed. + * + * @return int Returns fd or socket number if connection is successful. + * Otherwise, returns -1 if no connection is available. + */ + SocketConn* accept(); + + void listenThread(); + + void removeClosedConnections(); +}; + +/** + * SocketConn represents a single connection to a client. + */ +class SocketConn : public CommConn { + public: + SocketConn(MessageProcessor* messageProcessor, int sfd); + virtual ~SocketConn() = default; + + /** + * Blocking call to read data from the connection. + * + * @return std::vector<uint8_t> Serialized protobuf data received from emulator. This will be + * an empty vector if the connection was closed or some other error occurred. + */ + std::vector<uint8_t> read() override; + + /** + * Closes a connection if it is open. + */ + void stop() override; + + /** + * Transmits a string of data to the emulator. + * + * @param data Serialized protobuf data to transmit. + * + * @return int Number of bytes transmitted, or -1 if failed. + */ + int write(const std::vector<uint8_t>& data) override; + + inline bool isOpen() override { return mSockFd > 0; } + + private: + int mSockFd; +}; + +} // impl + +} // namespace V2_0 +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // ANDROID_EMULATORSOCKETCOMM_SOCKETCOMM_H diff --git a/emulator/aosp_car_emulator.mk b/emulator/aosp_car_emulator.mk index 711b590..f0810a9 100644 --- a/emulator/aosp_car_emulator.mk +++ b/emulator/aosp_car_emulator.mk @@ -37,11 +37,12 @@ PRODUCT_PRODUCT_PROPERTIES += \ persist.service.bootanim.displays=8140900251843329 \ ifeq (true,$(ENABLE_CLUSTER_OS_DOUBLE)) -DEVICE_PACKAGE_OVERLAYS += device/generic/car/emulator/cluster/osdouble_overlay +PRODUCT_PACKAGES += CarServiceOverlayEmulatorOsDouble else -DEVICE_PACKAGE_OVERLAYS += device/generic/car/emulator/cluster/overlay +PRODUCT_PACKAGES += CarServiceOverlayEmulator endif # ENABLE_CLUSTER_OS_DOUBLE endif # BUILD_EMULATOR_CLUSTER_DISPLAY PRODUCT_PRODUCT_PROPERTIES += \ ro.carwatchdog.vhal_healthcheck.interval=10 \ + ro.carwatchdog.client_healthcheck.interval=20 \ diff --git a/emulator/audio/overlay/packages/services/Car/service/res/values/config.xml b/emulator/audio/overlay/packages/services/Car/service/res/values/config.xml deleted file mode 100644 index 38ad500..0000000 --- a/emulator/audio/overlay/packages/services/Car/service/res/values/config.xml +++ /dev/null @@ -1,31 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2018, 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. -*/ ---> - -<!-- - Overlay resources to configure car service based on each OEM's preference. - See also packages/services/Car/service/res/values/config.xml ---> -<resources> - <bool name="audioUseDynamicRouting">true</bool> - <!-- Configuration to enable muting of individual volume groups. If this is set to - false, muting of individual volume groups is disabled, instead muting will toggle master - mute. If this is set to true, car volume group muting is enabled and each individual - volume group can be muted separately. --> - <bool name="audioUseCarVolumeGroupMuting">true</bool> -</resources> diff --git a/emulator/cluster/rro_overlays/CarServiceOverlay/Android.bp b/emulator/cluster/rro_overlays/CarServiceOverlay/Android.bp new file mode 100644 index 0000000..22fc331 --- /dev/null +++ b/emulator/cluster/rro_overlays/CarServiceOverlay/Android.bp @@ -0,0 +1,27 @@ +// Copyright (C) 2022 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// + +package { + default_applicable_licenses: ["device_generic_car_license"], +} + +runtime_resource_overlay { + name: "CarServiceOverlayEmulator", + resource_dirs: ["res"], + manifest: "AndroidManifest.xml", + sdk_version: "current", + product_specific: true +} diff --git a/emulator/cluster/rro_overlays/CarServiceOverlay/AndroidManifest.xml b/emulator/cluster/rro_overlays/CarServiceOverlay/AndroidManifest.xml new file mode 100644 index 0000000..332c34d --- /dev/null +++ b/emulator/cluster/rro_overlays/CarServiceOverlay/AndroidManifest.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2022 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.car.resources.emulator"> + <application android:hasCode="false"/> + <overlay android:priority="5001" + android:targetPackage="com.android.car.updatable" + android:targetName="CarServiceCustomization" + android:resourcesMap="@xml/overlays" + android:isStatic="true" /> +</manifest> diff --git a/emulator/cluster/overlay/packages/services/Car/service/res/values/config.xml b/emulator/cluster/rro_overlays/CarServiceOverlay/res/values/config.xml index 21eb7d9..40f47eb 100644 --- a/emulator/cluster/overlay/packages/services/Car/service/res/values/config.xml +++ b/emulator/cluster/rro_overlays/CarServiceOverlay/res/values/config.xml @@ -66,4 +66,11 @@ <item>vehicle_map_service</item> <item>car_telemetry_service</item> </string-array> + + <bool name="audioUseDynamicRouting">true</bool> + <!-- Configuration to enable muting of individual volume groups. If this is set to + false, muting of individual volume groups is disabled, instead muting will toggle master + mute. If this is set to true, car volume group muting is enabled and each individual + volume group can be muted separately. --> + <bool name="audioUseCarVolumeGroupMuting">true</bool> </resources> diff --git a/emulator/cluster/rro_overlays/CarServiceOverlay/res/xml/overlays.xml b/emulator/cluster/rro_overlays/CarServiceOverlay/res/xml/overlays.xml new file mode 100644 index 0000000..bfb9c4c --- /dev/null +++ b/emulator/cluster/rro_overlays/CarServiceOverlay/res/xml/overlays.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2022 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<overlay> + <item target="array/config_occupant_display_mapping" value="@array/config_occupant_display_mapping" /> + <item target="array/config_allowed_optional_car_features" value="@array/config_allowed_optional_car_features" /> + <item target="bool/audioUseDynamicRouting" value="@bool/audioUseDynamicRouting" /> + <item target="bool/audioUseCarVolumeGroupMuting" value="@bool/audioUseCarVolumeGroupMuting" /> +</overlay> diff --git a/emulator/cluster/rro_overlays/CarServiceOverlay_OsDouble/Android.bp b/emulator/cluster/rro_overlays/CarServiceOverlay_OsDouble/Android.bp new file mode 100644 index 0000000..2b7600e --- /dev/null +++ b/emulator/cluster/rro_overlays/CarServiceOverlay_OsDouble/Android.bp @@ -0,0 +1,34 @@ +// Copyright (C) 2022 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// + +package { + default_applicable_licenses: ["device_generic_car_license"], +} + +runtime_resource_overlay { + name: "CarServiceOverlayEmulatorOsDouble", + resource_dirs: ["res"], + manifest: "AndroidManifest.xml", + sdk_version: "current", + product_specific: true +} + +override_runtime_resource_overlay { + name: "CarServiceOverlayEmulatorOsDoubleGoogle", + base: "CarServiceOverlayEmulatorOsDouble", + package_name: "com.google.android.car.resources.emulator.osdouble", + target_package_name: "com.google.android.car.updatable", +} diff --git a/emulator/cluster/rro_overlays/CarServiceOverlay_OsDouble/AndroidManifest.xml b/emulator/cluster/rro_overlays/CarServiceOverlay_OsDouble/AndroidManifest.xml new file mode 100644 index 0000000..dda9cff --- /dev/null +++ b/emulator/cluster/rro_overlays/CarServiceOverlay_OsDouble/AndroidManifest.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2022 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.car.resources.emulator.osdouble"> + <application android:hasCode="false"/> + <overlay android:priority="5001" + android:targetPackage="com.android.car.updatable" + android:targetName="CarServiceCustomization" + android:resourcesMap="@xml/overlays" + android:isStatic="true" /> +</manifest> diff --git a/emulator/cluster/osdouble_overlay/packages/services/Car/service/res/values/config.xml b/emulator/cluster/rro_overlays/CarServiceOverlay_OsDouble/res/values/config.xml index 245069c..08ecf4b 100644 --- a/emulator/cluster/osdouble_overlay/packages/services/Car/service/res/values/config.xml +++ b/emulator/cluster/rro_overlays/CarServiceOverlay_OsDouble/res/values/config.xml @@ -67,4 +67,11 @@ <item>vehicle_map_service</item> <item>car_telemetry_service</item> </string-array> + + <bool name="audioUseDynamicRouting">true</bool> + <!-- Configuration to enable muting of individual volume groups. If this is set to + false, muting of individual volume groups is disabled, instead muting will toggle master + mute. If this is set to true, car volume group muting is enabled and each individual + volume group can be muted separately. --> + <bool name="audioUseCarVolumeGroupMuting">true</bool> </resources> diff --git a/emulator/cluster/rro_overlays/CarServiceOverlay_OsDouble/res/xml/overlays.xml b/emulator/cluster/rro_overlays/CarServiceOverlay_OsDouble/res/xml/overlays.xml new file mode 100644 index 0000000..bfb9c4c --- /dev/null +++ b/emulator/cluster/rro_overlays/CarServiceOverlay_OsDouble/res/xml/overlays.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2022 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<overlay> + <item target="array/config_occupant_display_mapping" value="@array/config_occupant_display_mapping" /> + <item target="array/config_allowed_optional_car_features" value="@array/config_allowed_optional_car_features" /> + <item target="bool/audioUseDynamicRouting" value="@bool/audioUseDynamicRouting" /> + <item target="bool/audioUseCarVolumeGroupMuting" value="@bool/audioUseCarVolumeGroupMuting" /> +</overlay> diff --git a/emulator/usbpt/bluetooth/btusb/btusb.mk b/emulator/usbpt/bluetooth/btusb/btusb.mk index 6e21465..d2c52c2 100644 --- a/emulator/usbpt/bluetooth/btusb/btusb.mk +++ b/emulator/usbpt/bluetooth/btusb/btusb.mk @@ -19,9 +19,5 @@ BOARD_SEPOLICY_DIRS += \ device/generic/car/emulator/usbpt/bluetooth/btusb/sepolicy endif -# USB Passthru -PRODUCT_PACKAGES += rtl8821c_fw.bin.car \ - rtl8821c_config.bin.car - PRODUCT_COPY_FILES += \ device/generic/car/emulator/usbpt/bluetooth/btusb/init.btusb.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/init.btusb.rc \ diff --git a/emulator/usbpt/bluetooth/btusb/rtl_bt/Android.bp b/emulator/usbpt/bluetooth/btusb/rtl_bt/Android.bp deleted file mode 100644 index ade064e..0000000 --- a/emulator/usbpt/bluetooth/btusb/rtl_bt/Android.bp +++ /dev/null @@ -1,24 +0,0 @@ -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "device_generic_car_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["device_generic_car_license"], -} - -prebuilt_firmware { - name: "rtl8821c_fw.bin.car", - src: "rtl8821c_fw.bin", - sub_dir: "rtl_bt", - filename_from_src: true, - proprietary: true, -} - -prebuilt_firmware { - name: "rtl8821c_config.bin.car", - src: "rtl8821c_config.bin", - sub_dir: "rtl_bt", - filename_from_src: true, - proprietary: true, -} diff --git a/emulator/usbpt/bluetooth/btusb/rtl_bt/rtl8821c_config.bin b/emulator/usbpt/bluetooth/btusb/rtl_bt/rtl8821c_config.bin Binary files differdeleted file mode 100755 index 76f62b8..0000000 --- a/emulator/usbpt/bluetooth/btusb/rtl_bt/rtl8821c_config.bin +++ /dev/null diff --git a/emulator/usbpt/bluetooth/btusb/rtl_bt/rtl8821c_fw.bin b/emulator/usbpt/bluetooth/btusb/rtl_bt/rtl8821c_fw.bin Binary files differdeleted file mode 100644 index ad31c94..0000000 --- a/emulator/usbpt/bluetooth/btusb/rtl_bt/rtl8821c_fw.bin +++ /dev/null diff --git a/emulator/usbpt/car_usbpt.mk b/emulator/usbpt/car_usbpt.mk index d6dc800..922c5b3 100644 --- a/emulator/usbpt/car_usbpt.mk +++ b/emulator/usbpt/car_usbpt.mk @@ -14,6 +14,7 @@ # limitations under the License. $(call inherit-product, device/generic/car/emulator/usbpt/bluetooth/bluetooth.mk) +$(call inherit-product, device/generic/car/emulator/usbpt/protocan/protocan.mk) $(call inherit-product, device/generic/car/emulator/usbpt/usbip-service/usbip-service.mk) # Required for USB passthrough diff --git a/emulator/usbpt/protocan/canbus_config.pb b/emulator/usbpt/protocan/canbus_config.pb new file mode 100644 index 0000000..2e3599d --- /dev/null +++ b/emulator/usbpt/protocan/canbus_config.pb @@ -0,0 +1,30 @@ +# Copyright (C) 2021 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +buses: [ + { + name: "BCAN" + virtual { ifname: "vcan0" } + bitrate: 125000 + }, + { + name: "CCAN" + virtual { ifname: "vcan0" } + bitrate: 250000 + }, + { + name: "aae" + native { ifname: "can0" } + bitrate: 250000 + } +] diff --git a/emulator/usbpt/protocan/manifest.protocan.xml b/emulator/usbpt/protocan/manifest.protocan.xml new file mode 100644 index 0000000..f23cbf9 --- /dev/null +++ b/emulator/usbpt/protocan/manifest.protocan.xml @@ -0,0 +1,19 @@ +<manifest version="1.0" type="device"> + <hal format="hidl"> + <name>android.hardware.automotive.can</name> + <transport>hwbinder</transport> + <impl level="generic"></impl> + <version>1.0</version> + <interface> + <name>ICanController</name> + <instance>socketcan</instance> + </interface> + <interface> + <name>ICanBus</name> + <instance>BCAN</instance> + <instance>CCAN</instance> + <instance>aae</instance> + <instance>test</instance> + </interface> + </hal> +</manifest> diff --git a/emulator/usbpt/protocan/protocan.mk b/emulator/usbpt/protocan/protocan.mk new file mode 100644 index 0000000..4f02d52 --- /dev/null +++ b/emulator/usbpt/protocan/protocan.mk @@ -0,0 +1,27 @@ +# +# Copyright (C) 2021 Google Inc. +# +# 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. +# + +# CAN bus HAL +PRODUCT_PACKAGES += android.hardware.automotive.can@1.0-service +PRODUCT_PACKAGES += canhalconfigurator +PRODUCT_COPY_FILES += device/generic/car/emulator/usbpt/protocan/canbus_config.pb:system/etc/canbus_config.pb +PRODUCT_PACKAGES_DEBUG += canhalctrl \ + canhaldump \ + canhalsend + +PRODUCT_PACKAGES += android.device.generic.car.emulator@1.0-protocanbus-service +BOARD_SEPOLICY_DIRS += device/generic/car/emulator/usbpt/protocan/protocanbus/sepolicy +DEVICE_MANIFEST_FILE += device/generic/car/emulator/usbpt/protocan/manifest.protocan.xml diff --git a/emulator/usbpt/protocan/protocanbus/Android.bp b/emulator/usbpt/protocan/protocanbus/Android.bp new file mode 100644 index 0000000..f35dfa7 --- /dev/null +++ b/emulator/usbpt/protocan/protocanbus/Android.bp @@ -0,0 +1,61 @@ +// +// Copyright (C) 2021 Google Inc. All Rights Reserved. +// + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "device_generic_car_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["device_generic_car_license"], +} + +cc_defaults { + name: "android.device.generic.car.emulator@1.0-protocanbus-defaults", + cpp_std: "experimental", + cflags: [ + "-Wall", + "-Wextra", + "-Werror", + ], + shared_libs: [ + "libbase", + "libutils", + ], +} + +cc_binary { + name: "android.device.generic.car.emulator@1.0-protocanbus-service", + init_rc: ["android.device.generic.car.emulator@1.0-protocanbus-service.rc"], + defaults: ["android.device.generic.car.emulator@1.0-protocanbus-defaults"], + vendor: true, + relative_install_path: "hw", + srcs: [ + "service.cpp", + "CanClient.cpp", + "CloseHandleWrapper.cpp", + "ExtraCanClient.cpp", + "VehicleBus.cpp", + ], + header_libs: [ + "android.hardware.automotive.can@hidl-utils-lib", + "VehicleHalUtilHeaders" + ], + include_dirs: ["frameworks/native/include"], + shared_libs: [ + "android.hardware.automotive.can@1.0", + "device.generic.car.emulator-aidl-V1-ndk", + "libbinder_ndk", + "libhidlbase", + "libcutils", + ], + whole_static_libs: [ + "libprotocan", + ], + static_libs: [ + "libmath", + ], + + vintf_fragments: ["manifest_android.device.generic.car.emulator@1.0-protocanbus.xml"] +} diff --git a/emulator/usbpt/protocan/protocanbus/CanClient.cpp b/emulator/usbpt/protocan/protocanbus/CanClient.cpp new file mode 100644 index 0000000..5dc0e07 --- /dev/null +++ b/emulator/usbpt/protocan/protocanbus/CanClient.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CanClient.h" + +#include <android-base/logging.h> +#include <android/hardware/automotive/can/1.0/ICanMessageListener.h> +#include <android/hidl/manager/1.1/IServiceManager.h> +#include <hidl-utils/hidl-utils.h> + +namespace android { +namespace hardware { +namespace automotive { +namespace can { +namespace V1_0 { +namespace utils { + +using hidl::manager::V1_1::IServiceManager; +using hidl::manager::V1_0::IServiceNotification; + +CanClient::CanClient(const std::string& busName) : mBusName(busName) {} + +::ndk::ScopedAStatus CanClient::start() { + VehicleBus::start(); + LOG(VERBOSE) << "Waiting for ICanBus/" << mBusName; + ICanBus::registerForNotifications(mBusName, static_cast<IServiceNotification*>(this)); + return ::ndk::ScopedAStatus::ok(); +} + +CanClient::~CanClient() { + auto manager = IServiceManager::getService(); + CHECK(manager != nullptr) << "Can't fetch IServiceManager"; + manager->unregisterForNotifications("", "", static_cast<IServiceNotification*>(this)); + + close(); +} + +void CanClient::onReady(const sp<ICanBus>&) {} + +Return<void> CanClient::onRegistration(const hidl_string&, const hidl_string& name, bool) { + LOG(VERBOSE) << "ICanBus/" << name << " is registered"; + auto bus = ICanBus::tryGetService(name); + if (bus == nullptr) { + LOG(WARNING) << "Can't fetch ICanBus/" << name; + return {}; + } + + std::lock_guard<std::mutex> lck(mCanBusGuard); + if (mCanBus) { + LOG(DEBUG) << "Bus " << mBusName << " service is already registered"; + return {}; + } + mCanBus = bus; + + // TODO(b/146214370): configure CAN message filtering (see first argument to listen()) + Result halResult; + sp<ICloseHandle> listenerCloseHandle; + // TODO(b/146214370): check why the cast requires transfer SEPolicy permission + auto res = bus->listen({}, static_cast<ICanMessageListener*>(this), + hidl_utils::fill(&halResult, &listenerCloseHandle)); + mListenerCloseHandle = CloseHandleWrapper(listenerCloseHandle); + if (!res.isOk() || halResult != Result::OK) { + LOG(WARNING) << "Listen call failed"; + close(); + return {}; + } + + auto errRes = bus->listenForErrors(static_cast<ICanErrorListener*>(this)); + if (!errRes.isOk()) { + LOG(WARNING) << "listenForErrors call failed"; + close(); + return {}; + } + mErrorCloseHandle = CloseHandleWrapper(errRes); + + if (!bus->linkToDeath(static_cast<hidl_death_recipient*>(this), 0).withDefault(false)) { + LOG(WARNING) << "linkToDeath failed"; + close(); + return {}; + } + + LOG(INFO) << "Bus " << mBusName << " successfully configured"; + onReady(mCanBus); + return {}; +} + +void CanClient::serviceDied(uint64_t, const wp<hidl::base::V1_0::IBase>&) { + onError(ErrorEvent::INTERFACE_DOWN, true); +} + +Return<void> CanClient::onError(ErrorEvent error, bool isFatal) { + if (!isFatal) { + LOG(VERBOSE) << "Got non-fatal error from CAN bus HAL: " << toString(error); + return {}; + } + + LOG(DEBUG) << "Got fatal error from CAN bus HAL: " << toString(error); + + if (!close()) { + LOG(WARNING) << "Service is dead already"; + return {}; + } + LOG(INFO) << "Bus " << mBusName << " became unavailable, waiting for it to come back..."; + + return {}; +} + +bool CanClient::close() { + std::lock_guard<std::mutex> lck(mCanBusGuard); + mListenerCloseHandle.close(); + mErrorCloseHandle.close(); + if (mCanBus == nullptr) return false; + if (!mCanBus->unlinkToDeath(static_cast<hidl_death_recipient*>(this)).isOk()) { + LOG(WARNING) << "unlinkToDeath failed"; + } + mCanBus = nullptr; + return true; +} + +} // namespace utils +} // namespace V1_0 +} // namespace can +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/emulator/usbpt/protocan/protocanbus/CanClient.h b/emulator/usbpt/protocan/protocanbus/CanClient.h new file mode 100644 index 0000000..6774176 --- /dev/null +++ b/emulator/usbpt/protocan/protocanbus/CanClient.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "CloseHandleWrapper.h" + +#include <android/hardware/automotive/can/1.0/ICanBus.h> +#include <android/hidl/manager/1.0/IServiceNotification.h> +#include <utils/Mutex.h> +#include <VehicleBus.h> + +namespace android { +namespace hardware { +namespace automotive { +namespace can { +namespace V1_0 { +namespace utils { + +class CanClient : public ::aidl::android::hardware::automotive::vehicle::VehicleBus, + public hidl::manager::V1_0::IServiceNotification, + private ICanErrorListener, + private ICanMessageListener, + private hidl_death_recipient { +public: + virtual ~CanClient(); + + virtual ::ndk::ScopedAStatus start(); + +protected: + CanClient(const std::string& busName); + + virtual void onReady(const sp<ICanBus>& canBus); + +private: + const std::string mBusName; + + CloseHandleWrapper mListenerCloseHandle; + CloseHandleWrapper mErrorCloseHandle; + + mutable std::mutex mCanBusGuard; + sp<ICanBus> mCanBus GUARDED_BY(mCanBusGuard); + + Return<void> onRegistration(const hidl_string&, const hidl_string& name, bool) override; + void serviceDied(uint64_t cookie, const wp<hidl::base::V1_0::IBase>& who) override; + Return<void> onError(ErrorEvent error, bool isFatal) override; + bool close(); + + DISALLOW_COPY_AND_ASSIGN(CanClient); +}; + +} // namespace utils +} // namespace V1_0 +} // namespace can +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/emulator/usbpt/protocan/protocanbus/CloseHandleWrapper.cpp b/emulator/usbpt/protocan/protocanbus/CloseHandleWrapper.cpp new file mode 100644 index 0000000..9da3efe --- /dev/null +++ b/emulator/usbpt/protocan/protocanbus/CloseHandleWrapper.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CloseHandleWrapper.h" + +#include <android-base/logging.h> + +namespace android { +namespace hardware { +namespace automotive { +namespace can { +namespace V1_0 { +namespace utils { + +CloseHandleWrapper::CloseHandleWrapper() : mIsClosed(true) {} + +CloseHandleWrapper::CloseHandleWrapper(sp<ICloseHandle> handle) : mHandle(handle) { + if (handle == nullptr) mIsClosed = true; +} + +CloseHandleWrapper::~CloseHandleWrapper() { + close(); +} + +CloseHandleWrapper& CloseHandleWrapper::operator=(CloseHandleWrapper&& other) { + if (this != &other) { + close(); + + mHandle = other.mHandle; + other.mHandle = nullptr; + mIsClosed = other.mIsClosed.load(); + other.mIsClosed = true; + } + + return *this; +} + +void CloseHandleWrapper::close() { + const auto wasClosed = mIsClosed.exchange(true); + if (wasClosed) return; + + mHandle->close(); + mHandle = nullptr; +} + +} // namespace utils +} // namespace V1_0 +} // namespace can +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/emulator/usbpt/protocan/protocanbus/CloseHandleWrapper.h b/emulator/usbpt/protocan/protocanbus/CloseHandleWrapper.h new file mode 100644 index 0000000..2b68927 --- /dev/null +++ b/emulator/usbpt/protocan/protocanbus/CloseHandleWrapper.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <android-base/macros.h> +#include <android/hardware/automotive/can/1.0/ICloseHandle.h> + +namespace android { +namespace hardware { +namespace automotive { +namespace can { +namespace V1_0 { +namespace utils { + +struct CloseHandleWrapper { + CloseHandleWrapper(); + CloseHandleWrapper(sp<ICloseHandle> handle); + virtual ~CloseHandleWrapper(); + + CloseHandleWrapper& operator=(CloseHandleWrapper&& other); + + void close(); + + private: + sp<ICloseHandle> mHandle; + std::atomic<bool> mIsClosed = false; + + DISALLOW_COPY_AND_ASSIGN(CloseHandleWrapper); +}; + +} // namespace utils +} // namespace V1_0 +} // namespace can +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/emulator/usbpt/protocan/protocanbus/ExtraCanClient.cpp b/emulator/usbpt/protocan/protocanbus/ExtraCanClient.cpp new file mode 100644 index 0000000..7da7057 --- /dev/null +++ b/emulator/usbpt/protocan/protocanbus/ExtraCanClient.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2020 Google Inc. All Rights Reserved. + */ + +#include "ExtraCanClient.h" + +#include <VehicleUtils.h> +#include <VehicleHalTypes.h> + +#include <aidl/android/hardware/automotive/vehicle/VehicleDisplay.h> +#include <aidl/android/hardware/automotive/vehicle/VehicleHwKeyInputAction.h> +#include <android-base/logging.h> +#include <android/keycodes.h> +#include <libprotocan/MessageDef.h> + +#include <cmath> +#include <set> + +namespace android::hardware::automotive::vehicle::V2_0::impl { + +using can::V1_0::CanMessage; +using can::V1_0::CanMessageId; +using can::V1_0::ICanBus; +using protocan::MessageDef; +using protocan::Signal; +using ::aidl::android::hardware::automotive::vehicle::VehicleArea; +using ::aidl::android::hardware::automotive::vehicle::VehicleDisplay; +using ::aidl::android::hardware::automotive::vehicle::VehicleHwKeyInputAction; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus; +using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; + +namespace can { +// clang-format off + +static const MessageDef EncEvent(0x18A, 5, { + {"EncPos", Signal(0, 16)}, + {"EncDir", Signal(16, 2)}, + {"Buttons", Signal(24, 16)}, +}); + +static const MessageDef ModuleControl(0x000, 2, { + {"ReqState", Signal(0, 8)}, + {"Address", Signal(8, 8)}, +}); + +// clang-format on +} // namespace can + +ExtraCanClient::ExtraCanClient() : CanClient("aae") {} + +void ExtraCanClient::onReady(const sp<ICanBus>& canBus) { + auto msg = can::ModuleControl.makeDefault(); + can::ModuleControl["ReqState"].set(msg, 1); + canBus->send(msg); +} + +void ExtraCanClient::appendKeyInput(std::vector<VehiclePropValue>& props, int32_t keyCode, bool keyDown) { + VehiclePropValue prop = {}; + + prop.areaId = toInt(VehicleArea::GLOBAL); + prop.prop = toInt(VehicleProperty::HW_KEY_INPUT); + prop.status = VehiclePropertyStatus::AVAILABLE; + prop.value.int32Values = { + toInt(keyDown ? VehicleHwKeyInputAction::ACTION_DOWN + : VehicleHwKeyInputAction::ACTION_UP), + keyCode, + toInt(VehicleDisplay::MAIN), + }; + + props.push_back(prop); +} + +void ExtraCanClient::appendRepeatedKeyInput(std::vector<VehiclePropValue>& props, int32_t keyCode, + unsigned repeat) { + for (unsigned i = 0; i < repeat; i++) { + appendKeyInput(props, keyCode, true); + appendKeyInput(props, keyCode, false); + } +} + +std::set<int> decodeButtons(uint16_t val) { + std::set<int> buttons; + + if (val & (1 << 0)) buttons.insert(AKEYCODE_BUTTON_A); // NAV + if (val & (1 << 1)) buttons.insert(AKEYCODE_BUTTON_B); // TEL + if (val & (1 << 2)) buttons.insert(AKEYCODE_MUSIC); // MEDIA + if (val & (1 << 3)) buttons.insert(AKEYCODE_MENU); // MENU + if (val & (1 << 4)) buttons.insert(AKEYCODE_BACK); // BACK + if (val & (1 << 5)) buttons.insert(AKEYCODE_ENTER); // ENC-PUSH + if (val & (1 << 8)) buttons.insert(AKEYCODE_DPAD_UP); // DPAD-UP + if (val & (1 << 9)) buttons.insert(AKEYCODE_DPAD_DOWN); // DPAD-DOWN + if (val & (1 << 10)) buttons.insert(AKEYCODE_DPAD_LEFT); // DPAD-LEFT + if (val & (1 << 11)) buttons.insert(AKEYCODE_DPAD_RIGHT); // DPAD-RIGHT + + return buttons; +} + +::android::hardware::Return<void> ExtraCanClient::onReceive(const CanMessage& message) { + std::vector<VehiclePropValue> props; + + if (message.id == can::EncEvent.id) { + if (!can::EncEvent.validate(message)) return {}; + LOG(INFO) << "EncPos: " << can::EncEvent["EncPos"].get(message); + LOG(INFO) << "EncDir: " << can::EncEvent["EncDir"].get(message); + LOG(INFO) << "Buttons: " << can::EncEvent["Buttons"].get(message); + + uint16_t encPos = can::EncEvent["EncPos"].get(message); + static std::optional<uint16_t> prevEncPos; + if (prevEncPos.has_value()) { + int16_t diff = encPos - *prevEncPos; + if (diff > 0) { + appendRepeatedKeyInput(props, AKEYCODE_DPAD_DOWN, diff); + } else if (diff < 0) { + appendRepeatedKeyInput(props, AKEYCODE_DPAD_UP, -diff); + } + } + prevEncPos = encPos; + + static std::set<int> oldButtons; + auto newButtons = decodeButtons(can::EncEvent["Buttons"].get(message)); + for (int key : newButtons) { + if (oldButtons.count(key) == 0) { + appendKeyInput(props, key, true); + } + } + for (int key : oldButtons) { + if (newButtons.count(key) == 0) { + appendKeyInput(props, key, false); + } + } + oldButtons = newButtons; + } + + updateTimestamps(props, message.timestamp); + sendPropertyEvent(props); + return {}; +} + +} // namespace aidl::android::hardware::automotive::vehicle diff --git a/emulator/usbpt/protocan/protocanbus/ExtraCanClient.h b/emulator/usbpt/protocan/protocanbus/ExtraCanClient.h new file mode 100644 index 0000000..3c1afc4 --- /dev/null +++ b/emulator/usbpt/protocan/protocanbus/ExtraCanClient.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2020 Google Inc. All Rights Reserved. + */ + +#pragma once + +#include "CanClient.h" + +#include <optional> + +namespace android::hardware::automotive::vehicle::V2_0::impl { + +class ExtraCanClient : public can::V1_0::utils::CanClient { + public: + ExtraCanClient(); + + void onReady(const sp<can::V1_0::ICanBus>& canBus) override; + Return<void> onReceive(const can::V1_0::CanMessage& message) override; + + private: + using VehiclePropValue = + aidl::android::hardware::automotive::vehicle::VehiclePropValue; + void appendKeyInput(std::vector<VehiclePropValue>& props, int32_t keyCode, + bool keyDown); + void appendRepeatedKeyInput(std::vector<VehiclePropValue>& props, + int32_t keyCode, unsigned repeat); +}; + +} // namespace android::hardware::automotive::vehicle::V2_0::impl diff --git a/emulator/usbpt/protocan/protocanbus/VehicleBus.cpp b/emulator/usbpt/protocan/protocanbus/VehicleBus.cpp new file mode 100644 index 0000000..8022367 --- /dev/null +++ b/emulator/usbpt/protocan/protocanbus/VehicleBus.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <VehicleBus.h> + +#include <android/binder_auto_utils.h> + +#include <android-base/logging.h> + +namespace aidl::android::hardware::automotive::vehicle { + +VehicleBus::VehicleBus() { + mDeathRecipient = ::ndk::ScopedAIBinder_DeathRecipient( + AIBinder_DeathRecipient_new(&VehicleBus::onBinderDied)); +} + +VehicleBus::~VehicleBus() {} + +::ndk::ScopedAStatus VehicleBus::start() { + return ::ndk::ScopedAStatus::ok(); +} + +::ndk::ScopedAStatus VehicleBus::setOnNewPropValuesCallback( + const std::shared_ptr<IVehicleBusCallback>& callback) { + std::lock_guard<std::mutex> g(mLock); + + if (mVehicleBusCallback) { + return ::ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage( + ERROR_INVALID_OPERATION, "Can't set callback twice!"); + + } + + AIBinder_linkToDeath(callback->asBinder().get(), mDeathRecipient.get(), + static_cast<void*>(this)); + mVehicleBusCallback = callback; + return ::ndk::ScopedAStatus::ok(); +} + +::ndk::ScopedAStatus VehicleBus::unsetOnNewPropValuesCallback( + const std::shared_ptr<IVehicleBusCallback>& callback) { + std::lock_guard<std::mutex> g(mLock); + + if (mVehicleBusCallback != callback) { + return ::ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage( + ERROR_INVALID_OPERATION, "Invalid callback argument"); + } + + AIBinder_unlinkToDeath(callback->asBinder().get(), mDeathRecipient.get(), + static_cast<void*>(this)); + mVehicleBusCallback = nullptr; + return ::ndk::ScopedAStatus::ok(); +} + +void VehicleBus::sendPropertyEvent( + const std::vector<VehiclePropValue>& propValues) { + std::lock_guard<std::mutex> g(mLock); + + if (mVehicleBusCallback == nullptr) { + LOG(ERROR) << "Callback isn't set"; + return; + } + mVehicleBusCallback->onNewPropValues(propValues); +} + +void VehicleBus::updateTimestamps(std::vector<VehiclePropValue>& propValues, + uint64_t timestamp) { + for (auto&& pv : propValues) { + pv.timestamp = timestamp; + } +} + +void VehicleBus::onBinderDied(void* cookie) { + VehicleBus* server = reinterpret_cast<VehicleBus*>(cookie); + server->handleBinderDied(); +} + +void VehicleBus::handleBinderDied() { + std::lock_guard<std::mutex> g(mLock); + mVehicleBusCallback = nullptr; + LOG(ERROR) << "Received onBinderDied on registered VehicleBusCallback"; +} + +}; // namespace aidl::android::hardware::automotive::vehicle diff --git a/emulator/usbpt/protocan/protocanbus/VehicleBus.h b/emulator/usbpt/protocan/protocanbus/VehicleBus.h new file mode 100644 index 0000000..2e08697 --- /dev/null +++ b/emulator/usbpt/protocan/protocanbus/VehicleBus.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <aidl/device/generic/car/emulator/BnVehicleBus.h> +#include <aidl/device/generic/car/emulator/IVehicleBusCallback.h> + +#include <android-base/thread_annotations.h> + +namespace aidl::android::hardware::automotive::vehicle { + +class VehicleBus : public device::generic::car::emulator::BnVehicleBus { +public: + using IVehicleBusCallback = aidl::device::generic::car::emulator::IVehicleBusCallback; + + enum { + ERROR_INVALID_OPERATION = 1, + }; + + VehicleBus(); + virtual ~VehicleBus(); + + virtual ::ndk::ScopedAStatus setOnNewPropValuesCallback( + const std::shared_ptr<IVehicleBusCallback>& callback); + virtual ::ndk::ScopedAStatus unsetOnNewPropValuesCallback( + const std::shared_ptr<IVehicleBusCallback>& callback); + virtual ::ndk::ScopedAStatus start(); + +protected: + void sendPropertyEvent(const std::vector<VehiclePropValue>& propValues); + static void updateTimestamps(std::vector<VehiclePropValue>& propValues, + uint64_t timestamp); + + private: + std::mutex mLock; + std::shared_ptr<IVehicleBusCallback> mVehicleBusCallback GUARDED_BY(mLock); + ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient; + + void handleBinderDied(); + static void onBinderDied(void* cookie); + +}; + +}; // namespace aidl::android::hardware::automotive::vehicle diff --git a/emulator/usbpt/protocan/protocanbus/android.device.generic.car.emulator@1.0-protocanbus-service.rc b/emulator/usbpt/protocan/protocanbus/android.device.generic.car.emulator@1.0-protocanbus-service.rc new file mode 100644 index 0000000..6eff93d --- /dev/null +++ b/emulator/usbpt/protocan/protocanbus/android.device.generic.car.emulator@1.0-protocanbus-service.rc @@ -0,0 +1,4 @@ +service vendor.vehiclebus-hal-1.0-protocanbus /vendor/bin/hw/android.device.generic.car.emulator@1.0-protocanbus-service + class hal + user vehicle_network + group system inet diff --git a/emulator/usbpt/protocan/protocanbus/manifest_android.device.generic.car.emulator@1.0-protocanbus.xml b/emulator/usbpt/protocan/protocanbus/manifest_android.device.generic.car.emulator@1.0-protocanbus.xml new file mode 100644 index 0000000..7308109 --- /dev/null +++ b/emulator/usbpt/protocan/protocanbus/manifest_android.device.generic.car.emulator@1.0-protocanbus.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2021 The Android Open Source Project + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<manifest version="1.0" type="device"> + <hal format="aidl"> + <name>device.generic.car.emulator</name> + <fqname>IVehicleBus/protocanbus</fqname> + </hal> +</manifest> diff --git a/emulator/usbpt/protocan/protocanbus/sepolicy/file_contexts b/emulator/usbpt/protocan/protocanbus/sepolicy/file_contexts new file mode 100644 index 0000000..7d47da3 --- /dev/null +++ b/emulator/usbpt/protocan/protocanbus/sepolicy/file_contexts @@ -0,0 +1 @@ +/vendor/bin/hw/android\.device\.generic\.car\.emulator@1\.0-protocanbus-service u:object_r:hal_vehiclebus_default_exec:s0 diff --git a/emulator/usbpt/protocan/protocanbus/sepolicy/hal_vehiclebus.te b/emulator/usbpt/protocan/protocanbus/sepolicy/hal_vehiclebus.te new file mode 100644 index 0000000..d24af12 --- /dev/null +++ b/emulator/usbpt/protocan/protocanbus/sepolicy/hal_vehiclebus.te @@ -0,0 +1,4 @@ +binder_call(hal_vehiclebus_client, hal_vehiclebus_server) +binder_call(hal_vehiclebus_server, hal_vehiclebus_client) + +hal_attribute_service(hal_vehiclebus, hal_vehiclebus_service) diff --git a/emulator/usbpt/protocan/protocanbus/sepolicy/hal_vehiclebus_default.te b/emulator/usbpt/protocan/protocanbus/sepolicy/hal_vehiclebus_default.te new file mode 100644 index 0000000..2aa8f05 --- /dev/null +++ b/emulator/usbpt/protocan/protocanbus/sepolicy/hal_vehiclebus_default.te @@ -0,0 +1,13 @@ +# vehiclebus subsystem +hal_attribute(vehiclebus); + +type hal_vehiclebus_default, domain; +type hal_vehiclebus_default_exec, exec_type, vendor_file_type, file_type; +init_daemon_domain(hal_vehiclebus_default); + +hal_server_domain(hal_vehiclebus_default, hal_vehiclebus); +hal_client_domain(hal_vehiclebus_default, hal_can_bus); +hal_client_domain(hal_vehicle_default, hal_vehiclebus); + +binder_use(hal_vehicle_default) +binder_use(hal_vehiclebus_default) diff --git a/emulator/usbpt/protocan/protocanbus/sepolicy/service.te b/emulator/usbpt/protocan/protocanbus/sepolicy/service.te new file mode 100644 index 0000000..1016fe4 --- /dev/null +++ b/emulator/usbpt/protocan/protocanbus/sepolicy/service.te @@ -0,0 +1 @@ +type hal_vehiclebus_service, vendor_service, protected_service, service_manager_type; diff --git a/emulator/usbpt/protocan/protocanbus/sepolicy/service_contexts b/emulator/usbpt/protocan/protocanbus/sepolicy/service_contexts new file mode 100644 index 0000000..d63c7cf --- /dev/null +++ b/emulator/usbpt/protocan/protocanbus/sepolicy/service_contexts @@ -0,0 +1 @@ +device.generic.car.emulator.IVehicleBus/protocanbus u:object_r:hal_vehiclebus_service:s0 diff --git a/emulator/usbpt/protocan/protocanbus/service.cpp b/emulator/usbpt/protocan/protocanbus/service.cpp new file mode 100644 index 0000000..6ae7687 --- /dev/null +++ b/emulator/usbpt/protocan/protocanbus/service.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2019 Google Inc. All Rights Reserved. + */ + +#include "ExtraCanClient.h" + +#include <android/binder_manager.h> +#include <android-base/logging.h> +#include <android/binder_process.h> +#include <hidl/HidlTransportSupport.h> + + +namespace android::hardware::automotive::vehicle::V2_0::impl { + +using ::aidl::device::generic::car::emulator::IVehicleBus; +using ::aidl::android::hardware::automotive::vehicle::VehicleBus; + +static void protocanbusService() { + base::SetDefaultTag("ProtoCanBusSrv"); + base::SetMinimumLogSeverity(base::VERBOSE); + ABinderProcess_setThreadPoolMaxThreadCount(4); + LOG(DEBUG) << "ProtoCAN service starting..."; + + std::shared_ptr<VehicleBus> vehicleBus = ::ndk::SharedRefBase::make<ExtraCanClient>(); + + auto serviceName = std::string(IVehicleBus::descriptor) + "/protocanbus"; + auto status = AServiceManager_addService(vehicleBus->asBinder().get(), + serviceName.c_str()); + CHECK_EQ(status, OK) << "Failed to register ProtoCAN VehicleBus HAL implementation"; + + vehicleBus->start(); + ABinderProcess_startThreadPool(); + ABinderProcess_joinThreadPool(); +}; + +} // namespace android::hardware::automotive::vehicle::V2_0::impl + +int main() { + ::android::hardware::automotive::vehicle::V2_0::impl::protocanbusService(); + return 1; // protocanbusService (joinRpcThreadpool) shouldn't exit +} diff --git a/emulator/usbpt/protocan/protocanbus/service.h b/emulator/usbpt/protocan/protocanbus/service.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/emulator/usbpt/protocan/protocanbus/service.h diff --git a/emulator/vhal_aidl/Android.bp b/emulator/vhal_aidl/Android.bp new file mode 100644 index 0000000..4f843fa --- /dev/null +++ b/emulator/vhal_aidl/Android.bp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_binary { + name: "android.hardware.automotive.vehicle@V1-emulator-service", + vendor: true, + defaults: [ + "FakeVehicleHardwareDefaults", + "VehicleHalDefaults", + "android-automotive-large-parcelable-defaults", + ], + vintf_fragments: ["vhal-emulator-service.xml"], + init_rc: ["vhal-emulator-service.rc"], + relative_install_path: "hw", + cflags: ["-DENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING"], + srcs: ["EmulatedVehicleService.cpp"], + static_libs: [ + "DefaultVehicleHal", + "VehicleEmulator", + "VehicleHalUtils", + "EmulatorCommConn", + "EmulatorPipeComm", + "EmulatorSocketComm", + "FakeVehicleHardware", + "VehicleHalProtos", + "android.hardware.automotive.vehicle@2.0-libproto-native", + "android-automotive-large-parcelable-lib", + ], + header_libs: [ + "IVehicleHardware", + ], + shared_libs: [ + "libbase", + "liblog", + "libutils", + "libprotobuf-cpp-lite", + "libbinder_ndk", + "device.generic.car.emulator-aidl-V1-ndk", + ], +} diff --git a/emulator/vhal_aidl/EmulatedVehicleService.cpp b/emulator/vhal_aidl/EmulatedVehicleService.cpp new file mode 100644 index 0000000..aeada2f --- /dev/null +++ b/emulator/vhal_aidl/EmulatedVehicleService.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "EmulatedVehicleService" + +#include <DefaultVehicleHal.h> +#include <EmulatedVehicleHardware.h> + +#include <android/binder_manager.h> +#include <android/binder_process.h> +#include <utils/Log.h> + +using ::android::hardware::automotive::vehicle::DefaultVehicleHal; +using ::android::hardware::automotive::vehicle::fake::EmulatedVehicleHardware; + +int main(int /* argc */, char* /* argv */[]) { + std::unique_ptr<EmulatedVehicleHardware> hardware = std::make_unique<EmulatedVehicleHardware>(); + std::shared_ptr<DefaultVehicleHal> vhal = + ::ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware)); + + ALOGI("Emulator Vehicle Service: Registering as service..."); + binder_exception_t err = AServiceManager_addService( + vhal->asBinder().get(), "android.hardware.automotive.vehicle.IVehicle/default"); + if (err != EX_NONE) { + ALOGE("failed to register android.hardware.automotive.vehicle service, exception: %d", err); + return 1; + } + + if (!ABinderProcess_setThreadPoolMaxThreadCount(4)) { + ALOGE("%s", "failed to set thread pool max thread count"); + return 1; + } + ABinderProcess_startThreadPool(); + + ALOGI("Emulator Vehicle Service Ready"); + + ABinderProcess_joinThreadPool(); + + ALOGI("Emulator Vehicle Service Exiting"); + + return 0; +} diff --git a/emulator/vhal_aidl/VehicleEmulator/Android.bp b/emulator/vhal_aidl/VehicleEmulator/Android.bp new file mode 100644 index 0000000..e301233 --- /dev/null +++ b/emulator/vhal_aidl/VehicleEmulator/Android.bp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + default_applicable_licenses: ["device_generic_car_license"], +} + +cc_library { + name: "VehicleEmulator", + vendor: true, + cflags: ["-DENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING"], + srcs: ["*.cpp"], + static_libs: [ + "VehicleHalUtils", + "EmulatorCommConn", + "EmulatorPipeComm", + "EmulatorSocketComm", + "FakeVehicleHardware", + "VehicleHalProtos", + "android.hardware.automotive.vehicle@2.0-libproto-native", + ], + shared_libs: [ + "libbase", + "liblog", + "libutils", + "libprotobuf-cpp-lite", + "libbinder_ndk", + "device.generic.car.emulator-aidl-V1-ndk", + ], + local_include_dirs: ["include"], + export_include_dirs: ["include"], + defaults: [ + "VehicleHalDefaults", + "FakeVehicleHardwareDefaults", + ], +} diff --git a/emulator/vhal_aidl/VehicleEmulator/EmulatedVehicleHardware.cpp b/emulator/vhal_aidl/VehicleEmulator/EmulatedVehicleHardware.cpp new file mode 100644 index 0000000..54eb716 --- /dev/null +++ b/emulator/vhal_aidl/VehicleEmulator/EmulatedVehicleHardware.cpp @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "EmulatedVehicleHardware" + +#include "EmulatedVehicleHardware.h" +#include "VehicleEmulator.h" + +#include <VehicleHalTypes.h> +#include <VehicleUtils.h> +#include <android-base/properties.h> +#include <android/binder_manager.h> +#include <utils/Log.h> + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { + +using ::aidl::android::hardware::automotive::vehicle::StatusCode; +using ::aidl::android::hardware::automotive::vehicle::SetValueRequest; +using ::aidl::android::hardware::automotive::vehicle::SetValueResult; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; +using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; + +using ::android::base::Result; +using ::android::hardware::automotive::vehicle::V2_0::impl::MessageSender; + +EmulatedVehicleHardware::EmulatedVehicleHardware() { + mInQemu = isInQemu(); + ALOGD("mInQemu=%s", mInQemu ? "true" : "false"); + + mVehicleBusCallback = ::ndk::SharedRefBase::make<VehicleBusCallback>(this); + mEmulator = std::make_unique<VehicleEmulator>(this); + startVehicleBuses(); +} + +EmulatedVehicleHardware::EmulatedVehicleHardware( + bool inQemu, + std::unique_ptr<MessageSender> socketComm, + std::unique_ptr<MessageSender> pipeComm) { + mInQemu = inQemu; + mEmulator = std::make_unique<VehicleEmulator>(std::move(socketComm), std::move(pipeComm), this); +} + +VehicleEmulator* EmulatedVehicleHardware::getEmulator() { + return mEmulator.get(); +} + +EmulatedVehicleHardware::~EmulatedVehicleHardware() { + mEmulator.reset(); + stopVehicleBuses(); +} + +StatusCode EmulatedVehicleHardware::setValues( + std::shared_ptr<const SetValuesCallback> callback, + const std::vector<SetValueRequest>& requests) { + std::vector<SetValueResult> results; + + for (const auto& request: requests) { + const VehiclePropValue& value = request.value; + int propId = value.prop; + + ALOGD("Set value for property ID: %d", propId); + + if (mInQemu && propId == toInt(VehicleProperty::DISPLAY_BRIGHTNESS)) { + ALOGD("Return OKAY for DISPLAY_BRIGHTNESS in QEMU"); + + // Emulator does not support remote brightness control, b/139959479 + // do not send it down so that it does not bring unnecessary property change event + // return other error code, such NOT_AVAILABLE, causes Emulator to be freezing + // TODO: return StatusCode::NOT_AVAILABLE once the above issue is fixed + results.push_back({ + .requestId = request.requestId, + .status = StatusCode::OK, + }); + continue; + } + + SetValueResult setValueResult; + setValueResult.requestId = request.requestId; + + if (auto result = setValue(value); !result.ok()) { + ALOGE("failed to set value, error: %s, code: %d", getErrorMsg(result).c_str(), + getIntErrorCode(result)); + setValueResult.status = getErrorCode(result); + } else { + setValueResult.status = StatusCode::OK; + // Inform the emulator about a new value change. + mEmulator->doSetValueFromClient(value); + } + + results.push_back(std::move(setValueResult)); + } + // In real Vehicle HAL, the values would be sent to vehicle bus. But here, we just assume + // it is done and notify the client. + (*callback)(std::move(results)); + + return StatusCode::OK; +} + +void EmulatedVehicleHardware::startVehicleBuses() { + std::vector<std::string> names; + AServiceManager_forEachDeclaredInstance(IVehicleBus::descriptor, static_cast<void*>(&names), + [](const char* instance, void* context) { + auto fullName = std::string(IVehicleBus::descriptor) + "/" + instance; + static_cast<std::vector<std::string>*>(context)->push_back(fullName); + }); + + for (const auto& fullName : names) { + ::ndk::SpAIBinder binder(AServiceManager_waitForService(fullName.c_str())); + if (binder.get() == nullptr) { + ALOGE("%s binder returned null", fullName.c_str()); + continue; + } + std::shared_ptr<IVehicleBus> vehicleBus = IVehicleBus::fromBinder(binder); + if (vehicleBus == nullptr) { + ALOGE("Couldn't open %s", fullName.c_str()); + continue; + } + + vehicleBus->setOnNewPropValuesCallback(mVehicleBusCallback); + mVehicleBuses.push_back(vehicleBus); + } +} + +::ndk::ScopedAStatus EmulatedVehicleHardware::VehicleBusCallback::onNewPropValues( + const std::vector<AidlVehiclePropValue>& aidlPropValues) { + for (const auto& aidlPropValue : aidlPropValues) { + if (auto result = mVehicleHardware->setValue(aidlPropValue); !result.ok()) { + ALOGE("Failed to set value, error: %s", getErrorMsg(result).c_str()); + continue; + } + } + return ::ndk::ScopedAStatus::ok(); +} + +void EmulatedVehicleHardware::stopVehicleBuses() { + for (const auto& vehicleBus : mVehicleBuses) { + vehicleBus->unsetOnNewPropValuesCallback(mVehicleBusCallback); + } +} + +std::vector<VehiclePropValuePool::RecyclableType> EmulatedVehicleHardware::getAllProperties() + const { + return mServerSidePropStore->readAllValues(); +} + +EmulatedVehicleHardware::ConfigResultType EmulatedVehicleHardware::getPropConfig(int32_t propId) + const { + return mServerSidePropStore->getConfig(propId); +} + +bool EmulatedVehicleHardware::isInQemu() { + return android::base::GetBoolProperty("ro.boot.qemu", false); +} + +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + diff --git a/emulator/vhal_aidl/VehicleEmulator/VehicleEmulator.cpp b/emulator/vhal_aidl/VehicleEmulator/VehicleEmulator.cpp new file mode 100644 index 0000000..b09b8b9 --- /dev/null +++ b/emulator/vhal_aidl/VehicleEmulator/VehicleEmulator.cpp @@ -0,0 +1,354 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "VehicleEmulator" + +#include "VehicleEmulator.h" + +#include <utils/Log.h> +#include <utils/SystemClock.h> +#include <algorithm> +#include <vector> + +#include <VehicleUtils.h> +#include <IVehicleHardware.h> +#include <PipeComm.h> +#include <SocketComm.h> + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { + +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType; + +using ::android::hardware::automotive::vehicle::V2_0::impl::SocketComm; +using ::android::hardware::automotive::vehicle::V2_0::impl::PipeComm; +using ::android::hardware::automotive::vehicle::V2_0::impl::MessageSender; + +VehicleEmulator::VehicleEmulator(EmulatedVehicleHardware* hal) : mHal(hal) { + ALOGI("Starting SocketComm"); + mSocketComm = std::make_unique<SocketComm>(this); + mSocketComm->start(); + + if (hal->isInQemu()) { + ALOGI("Starting PipeComm"); + mPipeComm = std::make_unique<PipeComm>(this); + mPipeComm->start(); + } +} + +VehicleEmulator::VehicleEmulator( + std::unique_ptr<MessageSender> socketComm, + std::unique_ptr<MessageSender> pipeComm, + EmulatedVehicleHardware* hal) : mHal(hal), mSocketComm(std::move(socketComm)), + mPipeComm(std::move(pipeComm)) {}; + +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(propValue, val); + 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) { + respMsg->set_msg_type(vhal_proto::GET_CONFIG_RESP); + + if (rxMsg.prop_size() < 1) { + ALOGE("Invalid GET_CONFIG_CMD msg, missing prop"); + respMsg->set_status(vhal_proto::ERROR_INVALID_OPERATION); + return; + } + + vhal_proto::VehiclePropGet getProp = rxMsg.prop(0); + + int32_t propId = getProp.prop(); + auto result = mHal->getPropConfig(propId); + if (!result.ok()) { + ALOGE("No config for property: %d\n", propId); + respMsg->set_status(vhal_proto::ERROR_INVALID_PROPERTY); + return; + } + + vhal_proto::VehiclePropConfig* protoCfg = respMsg->add_config(); + populateProtoVehicleConfig(*result.value(), protoCfg); + respMsg->set_status(vhal_proto::RESULT_OK); +} + +void VehicleEmulator::doGetConfigAll(const VehicleEmulator::EmulatorMessage& /* rxMsg */, + VehicleEmulator::EmulatorMessage* respMsg) { + respMsg->set_msg_type(vhal_proto::GET_CONFIG_ALL_RESP); + + std::vector<VehiclePropConfig> configs = mHal->getAllPropertyConfigs(); + respMsg->set_status(vhal_proto::RESULT_OK); + + for (auto& config : configs) { + vhal_proto::VehiclePropConfig* protoCfg = respMsg->add_config(); + populateProtoVehicleConfig(config, protoCfg); + } +} + +void VehicleEmulator::doGetProperty(const VehicleEmulator::EmulatorMessage& rxMsg, + VehicleEmulator::EmulatorMessage* respMsg) { + respMsg->set_msg_type(vhal_proto::GET_PROPERTY_RESP); + + if (rxMsg.prop_size() < 1) { + ALOGE("Invalid GET_PROPERTY_CMD msg, missing prop"); + respMsg->set_status(vhal_proto::ERROR_INVALID_OPERATION); + return; + } + + vhal_proto::VehiclePropGet getProp = rxMsg.prop(0); + int32_t propId = getProp.prop(); + vhal_proto::Status status; + + ALOGD("get property: %d", propId); + + int32_t areaId = 0; + if (getProp.has_area_id()) { + areaId = getProp.area_id(); + } + + VehiclePropValue request = { + .areaId = areaId, + .prop = propId, + }; + auto result = mHal->getValue(request); + if (result.ok()) { + vhal_proto::VehiclePropValue* protoVal = respMsg->add_value(); + populateProtoVehiclePropValue(*result.value(), protoVal); + status = vhal_proto::RESULT_OK; + } else { + ALOGW("Failed to get value, error: %s", getErrorMsg(result).c_str()); + status = vhal_proto::ERROR_INVALID_PROPERTY; + } + + 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(*prop, protoVal); + } + } +} + +void VehicleEmulator::doSetProperty(const VehicleEmulator::EmulatorMessage& rxMsg, + VehicleEmulator::EmulatorMessage* respMsg) { + respMsg->set_msg_type(vhal_proto::SET_PROPERTY_RESP); + + if (rxMsg.value_size() < 1) { + ALOGE("Invalid SET_PROPERTY_CMD msg, missing value"); + respMsg->set_status(vhal_proto::ERROR_INVALID_OPERATION); + return; + } + + vhal_proto::VehiclePropValue protoVal = rxMsg.value(0); + VehiclePropValue val = { + .timestamp = elapsedRealtimeNano(), + .areaId = protoVal.area_id(), + .prop = protoVal.prop(), + .status = static_cast<VehiclePropertyStatus>(protoVal.status()), + }; + + ALOGD("set property: %d", protoVal.prop()); + + // 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.byteValues = 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() }; + } + + auto result = mHal->setValue(val); + respMsg->set_status(result.ok() ? vhal_proto::RESULT_OK : vhal_proto::ERROR_INVALID_PROPERTY); +} + +void VehicleEmulator::doDebug(const vhal_proto::EmulatorMessage& rxMsg, + vhal_proto::EmulatorMessage* respMsg) { + respMsg->set_msg_type(vhal_proto::DEBUG_RESP); + + auto protoCommands = rxMsg.debug_commands(); + std::vector<std::string> commands = std::vector<std::string>( + protoCommands.begin(), protoCommands.end()); + DumpResult msg = mHal->dump(commands); + respMsg->set_status(vhal_proto::RESULT_OK); + respMsg->set_debug_result(msg.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(const VehiclePropConfig& cfg, + vhal_proto::VehiclePropConfig* protoCfg) { + 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))); + + 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()); + } + + protoCfg->clear_area_configs(); + for (auto& areaConfig : cfg.areaConfigs) { + auto* protoACfg = protoCfg->add_area_configs(); + protoACfg->set_area_id(areaConfig.areaId); + + switch (getPropType(cfg.prop)) { + case VehiclePropertyType::STRING: + case VehiclePropertyType::BOOLEAN: + case VehiclePropertyType::INT32_VEC: + case VehiclePropertyType::INT64_VEC: + case VehiclePropertyType::FLOAT_VEC: + case VehiclePropertyType::BYTES: + case VehiclePropertyType::MIXED: + // Do nothing. These types don't have min/max values + break; + case VehiclePropertyType::INT64: + protoACfg->set_min_int64_value(areaConfig.minInt64Value); + protoACfg->set_max_int64_value(areaConfig.maxInt64Value); + break; + case VehiclePropertyType::FLOAT: + protoACfg->set_min_float_value(areaConfig.minFloatValue); + protoACfg->set_max_float_value(areaConfig.maxFloatValue); + break; + case VehiclePropertyType::INT32: + protoACfg->set_min_int32_value(areaConfig.minInt32Value); + protoACfg->set_max_int32_value(areaConfig.maxInt32Value); + break; + default: + ALOGW("%s: Unknown property type: 0x%x", __func__, toInt(getPropType(cfg.prop))); + break; + } + } + + protoCfg->set_min_sample_rate(cfg.minSampleRate); + protoCfg->set_max_sample_rate(cfg.maxSampleRate); +} + +void VehicleEmulator::populateProtoVehiclePropValue(const VehiclePropValue& val, + vhal_proto::VehiclePropValue* protoVal) { + protoVal->set_prop(val.prop); + protoVal->set_value_type(toInt(getPropType(val.prop))); + protoVal->set_timestamp(val.timestamp); + protoVal->set_status(static_cast<vhal_proto::VehiclePropStatus>(val.status)); + protoVal->set_area_id(val.areaId); + + // 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()); + } + + if (val.value.byteValues.size() > 0) { + protoVal->set_bytes_value(val.value.byteValues.data(), val.value.byteValues.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); + } +} + +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/emulator/vhal_aidl/VehicleEmulator/include/EmulatedVehicleHardware.h b/emulator/vhal_aidl/VehicleEmulator/include/EmulatedVehicleHardware.h new file mode 100644 index 0000000..3bd4f15 --- /dev/null +++ b/emulator/vhal_aidl/VehicleEmulator/include/EmulatedVehicleHardware.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_VEHICLEEMULATOR_EMULATEDVEHICLEHARDWARE_H +#define ANDROID_VEHICLEEMULATOR_EMULATEDVEHICLEHARDWARE_H + +#include <aidl/device/generic/car/emulator/IVehicleBus.h> +#include <aidl/device/generic/car/emulator/BnVehicleBusCallback.h> + +#include <CommConn.h> +#include <FakeVehicleHardware.h> +#include <VehicleUtils.h> + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { + +class VehicleEmulator; +class VehicleEmulatorTest; + +class EmulatedVehicleHardware final : public FakeVehicleHardware { + public: + using AidlVehiclePropValue = aidl::android::hardware::automotive::vehicle::VehiclePropValue; + using IVehicleBus = aidl::device::generic::car::emulator::IVehicleBus; + using BnVehicleBusCallback = aidl::device::generic::car::emulator::BnVehicleBusCallback; + using ConfigResultType = android::base::Result<const aidl::android::hardware::automotive::vehicle::VehiclePropConfig*, VhalError>; + + EmulatedVehicleHardware(); + + ~EmulatedVehicleHardware(); + + aidl::android::hardware::automotive::vehicle::StatusCode setValues( + std::shared_ptr<const SetValuesCallback> callback, + const std::vector<aidl::android::hardware::automotive::vehicle::SetValueRequest>& + requests) override; + + std::vector<VehiclePropValuePool::RecyclableType> getAllProperties() const; + + ConfigResultType getPropConfig(int32_t propId) const; + + private: + friend class VehicleEmulator; + friend class VehicleEmulatorTest; + + bool mInQemu; + + class VehicleBusCallback : public BnVehicleBusCallback { + public: + VehicleBusCallback( + EmulatedVehicleHardware* vehicleHardware) : + mVehicleHardware(vehicleHardware) {} + + ndk::ScopedAStatus onNewPropValues( + const std::vector<AidlVehiclePropValue>& propValues) override; + + private: + EmulatedVehicleHardware* mVehicleHardware; + }; + std::shared_ptr<BnVehicleBusCallback> mVehicleBusCallback; + std::vector<std::shared_ptr<IVehicleBus>> mVehicleBuses; + std::unique_ptr<VehicleEmulator> mEmulator; + + // determine if it's running inside Android Emulator + static bool isInQemu(); + void startVehicleBuses(); + void stopVehicleBuses(); + + // For testing only. + EmulatedVehicleHardware( + bool inQEMU, + std::unique_ptr<V2_0::impl::MessageSender> socketComm, + std::unique_ptr<V2_0::impl::MessageSender> pipeComm); + + // For testing only. + VehicleEmulator* getEmulator(); +}; + +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // ANDROID_VEHICLEEMULATOR_EMULATEDVEHICLEHARDWARE_H diff --git a/emulator/vhal_aidl/VehicleEmulator/include/VehicleEmulator.h b/emulator/vhal_aidl/VehicleEmulator/include/VehicleEmulator.h new file mode 100644 index 0000000..4b66003 --- /dev/null +++ b/emulator/vhal_aidl/VehicleEmulator/include/VehicleEmulator.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_VEHICLEEMULATOR_VEHICLEEMULATOR_H +#define ANDROID_VEHICLEEMULATOR_VEHICLEEMULATOR_H + +#include "EmulatedVehicleHardware.h" + +#include <CommConn.h> +#include <VehicleHalTypes.h> +#include <VehicleHalProto.pb.h> + +#include <log/log.h> + +#include <memory> + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { +/** + * Emulates vehicle by providing controlling interface from host side either through ADB or Pipe. + */ +class VehicleEmulator final : public V2_0::impl::MessageProcessor { + public: + explicit VehicleEmulator(EmulatedVehicleHardware* hal); + // For testing only. + VehicleEmulator( + std::unique_ptr<V2_0::impl::MessageSender> socketComm, + std::unique_ptr<V2_0::impl::MessageSender> pipeComm, + EmulatedVehicleHardware* mHal); + virtual ~VehicleEmulator(); + + void doSetValueFromClient(const aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue); + void processMessage(const vhal_proto::EmulatorMessage& rxMsg, + vhal_proto::EmulatorMessage* respMsg) override; + + private: + friend class ConnectionThread; + using EmulatorMessage = vhal_proto::EmulatorMessage; + + void doGetConfig(const EmulatorMessage& rxMsg, EmulatorMessage* respMsg); + void doGetConfigAll(const EmulatorMessage& rxMsg, EmulatorMessage* respMsg); + void doGetProperty(const EmulatorMessage& rxMsg, EmulatorMessage* respMsg); + void doGetPropertyAll(const EmulatorMessage& rxMsg, EmulatorMessage* respMsg); + void doSetProperty(const EmulatorMessage& rxMsg, EmulatorMessage* respMsg); + void doDebug(const EmulatorMessage& rxMsg, EmulatorMessage* respMsg); + void populateProtoVehicleConfig( + const aidl::android::hardware::automotive::vehicle::VehiclePropConfig& cfg, + vhal_proto::VehiclePropConfig* protoCfg); + void populateProtoVehiclePropValue( + const aidl::android::hardware::automotive::vehicle::VehiclePropValue& val, + vhal_proto::VehiclePropValue* protoVal); + + private: + EmulatedVehicleHardware* mHal; + std::unique_ptr<V2_0::impl::MessageSender> mSocketComm; + std::unique_ptr<V2_0::impl::MessageSender> mPipeComm; +}; + +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // ANDROID_VEHICLEEMULATOR_VEHICLEEMULATOR_H diff --git a/emulator/vhal_aidl/VehicleEmulator/test/Android.bp b/emulator/vhal_aidl/VehicleEmulator/test/Android.bp new file mode 100644 index 0000000..700ee42 --- /dev/null +++ b/emulator/vhal_aidl/VehicleEmulator/test/Android.bp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + default_applicable_licenses: ["device_generic_car_license"], +} + +cc_test { + name: "VehicleEmulatorTest", + vendor: true, + cflags: ["-DENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING"], + srcs: ["*.cpp"], + static_libs: [ + "libgtest", + "libgmock", + "VehicleEmulator", + "VehicleHalUtils", + "EmulatorCommConn", + "FakeVehicleHardware", + "VehicleHalProtos", + "android.hardware.automotive.vehicle@2.0-libproto-native", + ], + shared_libs: [ + "libbase", + "liblog", + "libutils", + "libprotobuf-cpp-lite", + "libbinder_ndk", + "device.generic.car.emulator-aidl-V1-ndk", + ], + defaults: [ + "VehicleHalDefaults", + "FakeVehicleHardwareDefaults", + ], +} diff --git a/emulator/vhal_aidl/VehicleEmulator/test/VehicleEmulatorTest.cpp b/emulator/vhal_aidl/VehicleEmulator/test/VehicleEmulatorTest.cpp new file mode 100644 index 0000000..c7d945a --- /dev/null +++ b/emulator/vhal_aidl/VehicleEmulator/test/VehicleEmulatorTest.cpp @@ -0,0 +1,457 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include "EmulatedVehicleHardware.h" +#include "VehicleEmulator.h" + +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include <PropertyUtils.h> +#include <VehicleUtils.h> + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace fake { + +namespace { + +using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus; +using ::aidl::android::hardware::automotive::vehicle::SetValueRequest; +using ::aidl::android::hardware::automotive::vehicle::SetValueResult; +using ::aidl::android::hardware::automotive::vehicle::StatusCode; + +using ::android::hardware::automotive::vehicle::V2_0::impl::MessageSender; + +using ::vhal_proto::EmulatorMessage; +using ::vhal_proto::GET_CONFIG_ALL_CMD; +using ::vhal_proto::GET_CONFIG_ALL_RESP; +using ::vhal_proto::GET_CONFIG_CMD; +using ::vhal_proto::GET_CONFIG_RESP; +using ::vhal_proto::GET_PROPERTY_CMD; +using ::vhal_proto::GET_PROPERTY_RESP; +using ::vhal_proto::GET_PROPERTY_ALL_CMD; +using ::vhal_proto::GET_PROPERTY_ALL_RESP; +using ::vhal_proto::SET_PROPERTY_CMD; +using ::vhal_proto::SET_PROPERTY_RESP; +using ::vhal_proto::SET_PROPERTY_ASYNC; +using ::vhal_proto::DEBUG_CMD; +using ::vhal_proto::DEBUG_RESP; +using ::vhal_proto::VehiclePropGet; +using ::vhal_proto::VehiclePropConfig; +using ::vhal_proto::VehiclePropValue; +using ::vhal_proto::VehicleAreaConfig; +using ::vhal_proto::RESULT_OK; +using ::vhal_proto::ERROR_INVALID_PROPERTY; +using ::vhal_proto::ERROR_INVALID_OPERATION; +using ::vhal_proto::VehiclePropStatus; + +constexpr int INVALID_PROP_ID = 0; + +} // namespace + + +class TestConn : public MessageSender { + public: + void start() override { + // Do nothing. + } + + void stop() override { + // Do nothing. + } + + void sendMessage(const EmulatorMessage& msg) override { + mMsg = msg; + } + + EmulatorMessage getMessage() { + return mMsg; + } + + private: + EmulatorMessage mMsg; +}; + + +class VehicleEmulatorTest : public ::testing::Test { + protected: + void SetUp() override { + std::unique_ptr<TestConn> socketComm = std::make_unique<TestConn>(); + mSocketComm = socketComm.get(); + std::unique_ptr<TestConn> pipeComm = std::make_unique<TestConn>(); + mPipeComm = pipeComm.get(); + // Cannot use make_unique here because the constructor is private. + mHardware = std::unique_ptr<EmulatedVehicleHardware>( + new EmulatedVehicleHardware(/*inQemu=*/true, std::move(socketComm), + std::move(pipeComm))); + mEmulator = mHardware->getEmulator(); + mSetValuesCallback = std::make_shared<IVehicleHardware::SetValuesCallback>( + [this](std::vector<SetValueResult> results) { onSetValues(results); }); + } + + VehicleEmulator* getEmulator() { + return mEmulator; + } + + StatusCode setValues(const std::vector<SetValueRequest>& requests) { + return mHardware->setValues(mSetValuesCallback, requests); + } + + std::vector<SetValueResult> getSetValueResults() { + return mSetValueResults; + } + + EmulatorMessage getPipeCommMessage() { + return mPipeComm->getMessage(); + } + + EmulatorMessage getSocketCommMessage() { + return mSocketComm->getMessage(); + } + + private: + TestConn* mPipeComm; + TestConn* mSocketComm; + std::unique_ptr<EmulatedVehicleHardware> mHardware; + VehicleEmulator* mEmulator; + std::vector<SetValueResult> mSetValueResults; + std::shared_ptr<IVehicleHardware::SetValuesCallback> mSetValuesCallback; + + void onSetValues(std::vector<SetValueResult> results) { + for (auto& result : results) { + mSetValueResults.push_back(result); + } + } +}; + +TEST_F(VehicleEmulatorTest, testProcessGetConfig) { + EmulatorMessage rxMsg; + EmulatorMessage respMsg; + + rxMsg.set_msg_type(GET_CONFIG_CMD); + VehiclePropGet* propGet = rxMsg.add_prop(); + int32_t propId = toInt(VehicleProperty::HVAC_FAN_SPEED); + propGet->set_prop(propId); + + getEmulator()->processMessage(rxMsg, &respMsg); + + ASSERT_EQ(respMsg.status(), RESULT_OK); + ASSERT_EQ(respMsg.msg_type(), GET_CONFIG_RESP); + ASSERT_EQ(respMsg.config_size(), 1); + + VehiclePropConfig config = respMsg.config(0); + + // The definition for default config: + // {.config = {.prop = toInt(VehicleProperty::HVAC_FAN_SPEED), + // .access = VehiclePropertyAccess::READ_WRITE, + // .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + // .areaConfigs = {VehicleAreaConfig{ + // .areaId = HVAC_ALL, .minInt32Value = 1, .maxInt32Value = 7}}}, + // .initialValue = {.int32Values = {3}}}, + ASSERT_EQ(config.prop(), propId); + ASSERT_EQ(config.access(), toInt(VehiclePropertyAccess::READ_WRITE)); + ASSERT_EQ(config.change_mode(), toInt(VehiclePropertyChangeMode::ON_CHANGE)); + ASSERT_EQ(config.value_type(), toInt(VehiclePropertyType::INT32)); + ASSERT_FALSE(config.has_config_flags()); + ASSERT_EQ(config.config_array_size(), 0); + ASSERT_FALSE(config.has_config_string()); + + ASSERT_EQ(config.area_configs_size(), 1); + + VehicleAreaConfig areaConfig = config.area_configs(0); + + ASSERT_EQ(areaConfig.area_id(), HVAC_ALL); + ASSERT_TRUE(areaConfig.has_min_int32_value()); + ASSERT_EQ(areaConfig.min_int32_value(), 1); + ASSERT_EQ(areaConfig.max_int32_value(), 7); +} + +TEST_F(VehicleEmulatorTest, testProcessGetConfigErrorNoProp) { + EmulatorMessage rxMsg; + EmulatorMessage respMsg; + + rxMsg.set_msg_type(GET_CONFIG_CMD); + + getEmulator()->processMessage(rxMsg, &respMsg); + + ASSERT_EQ(respMsg.status(), ERROR_INVALID_OPERATION); + ASSERT_EQ(respMsg.msg_type(), GET_CONFIG_RESP); +} + +TEST_F(VehicleEmulatorTest, testProcessGetConfigErrorInvalidProp) { + EmulatorMessage rxMsg; + EmulatorMessage respMsg; + + rxMsg.set_msg_type(GET_CONFIG_CMD); + VehiclePropGet* propGet = rxMsg.add_prop(); + propGet->set_prop(INVALID_PROP_ID); + + getEmulator()->processMessage(rxMsg, &respMsg); + + ASSERT_EQ(respMsg.status(), ERROR_INVALID_PROPERTY); + ASSERT_EQ(respMsg.msg_type(), GET_CONFIG_RESP); +} + +TEST_F(VehicleEmulatorTest, testProcessGetConfigAll) { + EmulatorMessage rxMsg; + EmulatorMessage respMsg; + + rxMsg.set_msg_type(GET_CONFIG_ALL_CMD); + + getEmulator()->processMessage(rxMsg, &respMsg); + + ASSERT_EQ(respMsg.status(), RESULT_OK); + ASSERT_EQ(respMsg.msg_type(), GET_CONFIG_ALL_RESP); + // We have at least 10 properties. + ASSERT_GT(respMsg.config_size(), 10); +} + +TEST_F(VehicleEmulatorTest, testProcessGetProperty) { + EmulatorMessage rxMsg; + EmulatorMessage respMsg; + + rxMsg.set_msg_type(GET_PROPERTY_CMD); + VehiclePropGet* propGet = rxMsg.add_prop(); + int32_t propId = toInt(VehicleProperty::HVAC_FAN_SPEED); + propGet->set_prop(propId); + propGet->set_area_id(HVAC_ALL); + + getEmulator()->processMessage(rxMsg, &respMsg); + + ASSERT_EQ(respMsg.status(), RESULT_OK); + ASSERT_EQ(respMsg.msg_type(), GET_PROPERTY_RESP); + ASSERT_EQ(respMsg.value_size(), 1); + + VehiclePropValue gotValue = respMsg.value(0); + + ASSERT_EQ(gotValue.prop(), propId); + ASSERT_EQ(gotValue.value_type(), toInt(VehiclePropertyType::INT32)); + ASSERT_EQ(gotValue.status(), VehiclePropStatus::AVAILABLE); + ASSERT_EQ(gotValue.area_id(), HVAC_ALL); + ASSERT_EQ(gotValue.int32_values_size(), 1); + ASSERT_EQ(gotValue.int32_values(0), 3); +} + +TEST_F(VehicleEmulatorTest, testProcessGetPropertyErrorNoProp) { + EmulatorMessage rxMsg; + EmulatorMessage respMsg; + + rxMsg.set_msg_type(GET_PROPERTY_CMD); + + getEmulator()->processMessage(rxMsg, &respMsg); + + ASSERT_EQ(respMsg.status(), ERROR_INVALID_OPERATION); + ASSERT_EQ(respMsg.msg_type(), GET_PROPERTY_RESP); +} + +TEST_F(VehicleEmulatorTest, testProcessGetPropertyErrorInvalidProp) { + EmulatorMessage rxMsg; + EmulatorMessage respMsg; + + rxMsg.set_msg_type(GET_PROPERTY_CMD); + VehiclePropGet* propGet = rxMsg.add_prop(); + propGet->set_prop(INVALID_PROP_ID); + + getEmulator()->processMessage(rxMsg, &respMsg); + + ASSERT_EQ(respMsg.status(), ERROR_INVALID_PROPERTY); + ASSERT_EQ(respMsg.msg_type(), GET_PROPERTY_RESP); +} + +TEST_F(VehicleEmulatorTest, testProcessGetPropertyAll) { + EmulatorMessage rxMsg; + EmulatorMessage respMsg; + + rxMsg.set_msg_type(GET_PROPERTY_ALL_CMD); + + getEmulator()->processMessage(rxMsg, &respMsg); + + ASSERT_EQ(respMsg.status(), RESULT_OK); + ASSERT_EQ(respMsg.msg_type(), GET_PROPERTY_ALL_RESP); + // We have at least 10 properties. + ASSERT_GT(respMsg.value_size(), 10); +} + +TEST_F(VehicleEmulatorTest, testProcessSetProperty) { + EmulatorMessage rxMsg; + EmulatorMessage respMsg; + int32_t testValue = 2; + + rxMsg.set_msg_type(SET_PROPERTY_CMD); + VehiclePropValue* propValue = rxMsg.add_value(); + int32_t propId = toInt(VehicleProperty::HVAC_FAN_SPEED); + propValue->set_prop(propId); + propValue->set_area_id(HVAC_ALL); + propValue->set_status(VehiclePropStatus::AVAILABLE); + propValue->add_int32_values(testValue); + + getEmulator()->processMessage(rxMsg, &respMsg); + + ASSERT_EQ(respMsg.status(), RESULT_OK); + ASSERT_EQ(respMsg.msg_type(), SET_PROPERTY_RESP); + + + rxMsg.set_msg_type(GET_PROPERTY_CMD); + VehiclePropGet* propGet = rxMsg.add_prop(); + propGet->set_prop(propId); + propGet->set_area_id(HVAC_ALL); + + getEmulator()->processMessage(rxMsg, &respMsg); + + ASSERT_EQ(respMsg.status(), RESULT_OK); + ASSERT_EQ(respMsg.msg_type(), GET_PROPERTY_RESP); + ASSERT_EQ(respMsg.value_size(), 1); + + VehiclePropValue gotValue = respMsg.value(0); + + ASSERT_EQ(gotValue.prop(), propId); + ASSERT_EQ(gotValue.int32_values_size(), 1); + ASSERT_EQ(gotValue.int32_values(0), testValue); +} + +TEST_F(VehicleEmulatorTest, testProcessSetPropertyErrorNoValue) { + EmulatorMessage rxMsg; + EmulatorMessage respMsg; + + rxMsg.set_msg_type(SET_PROPERTY_CMD); + + getEmulator()->processMessage(rxMsg, &respMsg); + + ASSERT_EQ(respMsg.status(), ERROR_INVALID_OPERATION); + ASSERT_EQ(respMsg.msg_type(), SET_PROPERTY_RESP); +} + +TEST_F(VehicleEmulatorTest, testProcessSetPropertyErrorInvalidProp) { + EmulatorMessage rxMsg; + EmulatorMessage respMsg; + + rxMsg.set_msg_type(SET_PROPERTY_CMD); + VehiclePropValue* propValue = rxMsg.add_value(); + propValue->set_prop(INVALID_PROP_ID); + + getEmulator()->processMessage(rxMsg, &respMsg); + + ASSERT_EQ(respMsg.status(), ERROR_INVALID_PROPERTY); + ASSERT_EQ(respMsg.msg_type(), SET_PROPERTY_RESP); +} + +TEST_F(VehicleEmulatorTest, testProcessDebug) { + EmulatorMessage rxMsg; + EmulatorMessage respMsg; + + rxMsg.set_msg_type(DEBUG_CMD); + rxMsg.add_debug_commands("blabla"); + + getEmulator()->processMessage(rxMsg, &respMsg); + + ASSERT_EQ(respMsg.status(), RESULT_OK); + ASSERT_EQ(respMsg.msg_type(), DEBUG_RESP); + ASSERT_TRUE(respMsg.has_debug_result()); +} + +TEST_F(VehicleEmulatorTest, testSetValuesDisplayBrightness) { + std::vector<SetValueRequest> requests = { + { + .requestId = 0, + .value = { + .prop = toInt(VehicleProperty::DISPLAY_BRIGHTNESS), + } + }, + }; + + auto status = setValues(requests); + + ASSERT_EQ(status, StatusCode::OK); + + std::vector<SetValueResult> results = getSetValueResults(); + + ASSERT_EQ(results, std::vector<SetValueResult>({ + { + .requestId = 0, + .status = StatusCode::OK, + }, + })); +} + +TEST_F(VehicleEmulatorTest, testSetValuesNormal) { + int32_t testValue = 2; + int32_t propId = toInt(VehicleProperty::HVAC_FAN_SPEED); + std::vector<SetValueRequest> requests = { + { + .requestId = 0, + .value = { + .prop = propId, + .areaId = HVAC_ALL, + .value.int32Values = {testValue}, + } + }, + }; + + auto status = setValues(requests); + + ASSERT_EQ(status, StatusCode::OK); + + std::vector<SetValueResult> results = getSetValueResults(); + + ASSERT_EQ(results, std::vector<SetValueResult>({ + { + .requestId = 0, + .status = StatusCode::OK, + }, + })); + + // Messages that a property has been set are sent to emulator. + EmulatorMessage pipeCommMsg = getPipeCommMessage(); + EmulatorMessage socketCommMsg = getSocketCommMessage(); + + ASSERT_EQ(pipeCommMsg.status(), RESULT_OK); + ASSERT_EQ(pipeCommMsg.msg_type(), SET_PROPERTY_ASYNC); + ASSERT_EQ(pipeCommMsg.value_size(), 1); + ASSERT_EQ(socketCommMsg.status(), RESULT_OK); + ASSERT_EQ(socketCommMsg.msg_type(), SET_PROPERTY_ASYNC); + ASSERT_EQ(socketCommMsg.value_size(), 1); + + VehiclePropValue gotValue = pipeCommMsg.value(0); + + ASSERT_EQ(gotValue.prop(), propId); + ASSERT_EQ(gotValue.value_type(), toInt(VehiclePropertyType::INT32)); + ASSERT_EQ(gotValue.status(), VehiclePropStatus::AVAILABLE); + ASSERT_EQ(gotValue.area_id(), HVAC_ALL); + ASSERT_EQ(gotValue.int32_values_size(), 1); + ASSERT_EQ(gotValue.int32_values(0), testValue); + + gotValue = socketCommMsg.value(0); + + ASSERT_EQ(gotValue.prop(), propId); + ASSERT_EQ(gotValue.value_type(), toInt(VehiclePropertyType::INT32)); + ASSERT_EQ(gotValue.status(), VehiclePropStatus::AVAILABLE); + ASSERT_EQ(gotValue.area_id(), HVAC_ALL); + ASSERT_EQ(gotValue.int32_values_size(), 1); + ASSERT_EQ(gotValue.int32_values(0), testValue); +} + +} // namespace fake +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/emulator/vhal_aidl/vhal-emulator-service.rc b/emulator/vhal_aidl/vhal-emulator-service.rc new file mode 100644 index 0000000..d311ece --- /dev/null +++ b/emulator/vhal_aidl/vhal-emulator-service.rc @@ -0,0 +1,4 @@ +service vendor.vehicle-hal-emulator /vendor/bin/hw/android.hardware.automotive.vehicle@V1-emulator-service + class early_hal + user vehicle_network + group system inet diff --git a/emulator/vhal_aidl/vhal-emulator-service.xml b/emulator/vhal_aidl/vhal-emulator-service.xml new file mode 100644 index 0000000..adf40da --- /dev/null +++ b/emulator/vhal_aidl/vhal-emulator-service.xml @@ -0,0 +1,10 @@ +<manifest version="1.0" type="device"> + <hal format="aidl"> + <name>android.hardware.automotive.vehicle</name> + <version>1</version> + <interface> + <name>IVehicle</name> + <instance>default</instance> + </interface> + </hal> +</manifest> diff --git a/emulator/vhal_v2_0/Android.bp b/emulator/vhal_v2_0/Android.bp new file mode 100644 index 0000000..50e8169 --- /dev/null +++ b/emulator/vhal_v2_0/Android.bp @@ -0,0 +1,80 @@ +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "device_generic_car_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["device_generic_car_license"], +} + +// Emulator VehicleHAL implementation +cc_library_static { + name: "android.hardware.automotive.vehicle@2.0-emulator-impl-lib", + visibility: ["//hardware/interfaces/automotive/vehicle/2.0:__subpackages__"], + vendor: true, + defaults: ["vhal_v2_0_target_defaults"], + cflags: ["-DENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING"], + srcs: [ + "EmulatedVehicleConnector.cpp", + "EmulatedVehicleHal.cpp", + "EmulatedVehicleHalServer.cpp", + "VehicleEmulator.cpp", + ], + header_libs: ["vhal_v2_0_common_headers"], + whole_static_libs: [ + "android.hardware.automotive.vehicle@2.0-default-impl-lib", + ], + shared_libs: [ + "libbase", + "libjsoncpp", + "libprotobuf-cpp-lite", + "device.generic.car.emulator-aidl-V1-ndk", + ], + export_include_dirs: ["."], + static_libs: [ + "android.hardware.automotive.vehicle@2.0-libproto-native", + "EmulatorCommConn", + "EmulatorPipeComm", + "EmulatorSocketComm", + ], +} + +cc_binary { + name: "android.hardware.automotive.vehicle@2.0-emulator-service", + defaults: ["vhal_v2_0_target_defaults"], + vintf_fragments: [ + "android.hardware.automotive.vehicle@2.0-emulator-service.xml", + ], + init_rc: ["android.hardware.automotive.vehicle@2.0-emulator-service.rc"], + vendor: true, + relative_install_path: "hw", + srcs: ["VehicleService.cpp"], + shared_libs: [ + "libbase", + "libjsoncpp", + "libprotobuf-cpp-lite", + "device.generic.car.emulator-aidl-V1-ndk", + ], + static_libs: [ + "android.hardware.automotive.vehicle@2.0-manager-lib", + "android.hardware.automotive.vehicle@2.0-libproto-native", + "android.hardware.automotive.vehicle@2.0-emulator-impl-lib", + "EmulatorCommConn", + "EmulatorPipeComm", + "EmulatorSocketComm", + ], +} diff --git a/emulator/vhal_v2_0/EmulatedVehicleConnector.cpp b/emulator/vhal_v2_0/EmulatedVehicleConnector.cpp new file mode 100644 index 0000000..f9b3e44 --- /dev/null +++ b/emulator/vhal_v2_0/EmulatedVehicleConnector.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2019 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 "automotive.vehicle@2.0-connector" + +#include "EmulatedVehicleConnector.h" + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace V2_0 { + +namespace impl { + +std::unique_ptr<VehicleEmulator> EmulatedVehicleConnector::getEmulator() { + return std::make_unique<VehicleEmulator>(this); +} + +} // namespace impl + +} // namespace V2_0 +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/emulator/vhal_v2_0/EmulatedVehicleConnector.h b/emulator/vhal_v2_0/EmulatedVehicleConnector.h new file mode 100644 index 0000000..cb876ad --- /dev/null +++ b/emulator/vhal_v2_0/EmulatedVehicleConnector.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleConnector_H_ +#define android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleConnector_H_ + +#include <vhal_v2_0/VehicleConnector.h> +#include <vhal_v2_0/VehicleHalClient.h> + +#include "EmulatedVehicleHalServer.h" +#include "VehicleEmulator.h" + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace V2_0 { + +namespace impl { + +class EmulatedVehicleConnector + : public IPassThroughConnector<VehicleHalClient, EmulatedVehicleHalServer> { + public: + EmulatedVehicleConnector() = default; + + std::unique_ptr<VehicleEmulator> getEmulator(); + + void triggerSendAllValues() { this->sendAllValuesToClient(); } +}; + +} // namespace impl + +} // namespace V2_0 +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleConnector_H_ diff --git a/emulator/vhal_v2_0/EmulatedVehicleHal.cpp b/emulator/vhal_v2_0/EmulatedVehicleHal.cpp new file mode 100644 index 0000000..1bd44c4 --- /dev/null +++ b/emulator/vhal_v2_0/EmulatedVehicleHal.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2016 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 "EmulatedVehicleHal_v2_0" + +#include <vhal_v2_0/VehicleHalClient.h> +#include <vhal_v2_0/VehiclePropertyStore.h> + +#include "EmulatedVehicleHal.h" + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace V2_0 { + +namespace impl { + +EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client) + : DefaultVehicleHal(propStore, client) {} + +} // namespace impl + +} // namespace V2_0 +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/emulator/vhal_v2_0/EmulatedVehicleHal.h b/emulator/vhal_v2_0/EmulatedVehicleHal.h new file mode 100644 index 0000000..6adab70 --- /dev/null +++ b/emulator/vhal_v2_0/EmulatedVehicleHal.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_ +#define android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_ + +#include <vhal_v2_0/DefaultVehicleHal.h> +#include <vhal_v2_0/VehicleHalClient.h> +#include <vhal_v2_0/VehiclePropertyStore.h> + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace V2_0 { + +namespace impl { + +/** Implementation of VehicleHal that connected to emulator instead of real vehicle network. */ +class EmulatedVehicleHal : public DefaultVehicleHal { + public: + EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client); + ~EmulatedVehicleHal() = default; +}; + +} // namespace impl + +} // namespace V2_0 +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_ diff --git a/emulator/vhal_v2_0/EmulatedVehicleHalServer.cpp b/emulator/vhal_v2_0/EmulatedVehicleHalServer.cpp new file mode 100644 index 0000000..be4eefe --- /dev/null +++ b/emulator/vhal_v2_0/EmulatedVehicleHalServer.cpp @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "EmulatedVehicleHalServer" + +#include <android/binder_manager.h> +#include <utils/SystemClock.h> +#include <vhal_v2_0/VehicleUtils.h> + +#include "EmulatedVehicleHalServer.h" + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace V2_0 { + +namespace impl { + +EmulatedVehicleHalServer::EmulatedVehicleHalServer(): DefaultVehicleHalServer() { + mInQEMU = isInQEMU(); + ALOGD("mInQEMU=%s", mInQEMU ? "true" : "false"); + + mVehicleBusCallback = ::ndk::SharedRefBase::make<VehicleBusCallback>(this); + startVehicleBuses(); +} + +EmulatedVehicleHalServer::~EmulatedVehicleHalServer() { + stopVehicleBuses(); +} + +StatusCode EmulatedVehicleHalServer::onSetProperty(const VehiclePropValue& value, + bool updateStatus) { + if (mInQEMU && value.prop == toInt(VehicleProperty::DISPLAY_BRIGHTNESS)) { + // Emulator does not support remote brightness control, b/139959479 + // do not send it down so that it does not bring unnecessary property change event + // return other error code, such NOT_AVAILABLE, causes Emulator to be freezing + // TODO: return StatusCode::NOT_AVAILABLE once the above issue is fixed + return StatusCode::OK; + } + + return DefaultVehicleHalServer::onSetProperty(value, updateStatus); +} + +bool EmulatedVehicleHalServer::setPropertyFromVehicle(const VehiclePropValue& propValue) { + auto updatedPropValue = getValuePool()->obtain(propValue); + updatedPropValue->timestamp = elapsedRealtimeNano(); + mServerSidePropStore.writeValue(*updatedPropValue, true); + onPropertyValueFromCar(*updatedPropValue, true); + return true; +} + +std::vector<VehiclePropValue> EmulatedVehicleHalServer::getAllProperties() const { + return mServerSidePropStore.readAllValues(); +} + +std::vector<VehiclePropConfig> EmulatedVehicleHalServer::listProperties() { + return mServerSidePropStore.getAllConfigs(); +} + +EmulatedVehicleHalServer::VehiclePropValuePtr EmulatedVehicleHalServer::get( + const VehiclePropValue& requestedPropValue, StatusCode* outStatus) { + EmulatedVehicleHalServer::VehiclePropValuePtr v = nullptr; + auto prop = mServerSidePropStore.readValueOrNull(requestedPropValue); + if (prop != nullptr) { + v = getValuePool()->obtain(*prop); + } + + if (!v) { + *outStatus = StatusCode::INVALID_ARG; + } else if (v->status == VehiclePropertyStatus::AVAILABLE) { + *outStatus = StatusCode::OK; + } else { + *outStatus = StatusCode::TRY_AGAIN; + } + + if (v.get()) { + v->timestamp = elapsedRealtimeNano(); + } + return v; +} + +void EmulatedVehicleHalServer::startVehicleBuses() { + std::vector<std::string> names; + AServiceManager_forEachDeclaredInstance(IVehicleBus::descriptor, static_cast<void*>(&names), + [](const char* instance, void* context) { + auto fullName = std::string(IVehicleBus::descriptor) + "/" + instance; + static_cast<std::vector<std::string>*>(context)->emplace_back(fullName); + }); + + for (const auto& fullName : names) { + ::ndk::SpAIBinder binder(AServiceManager_waitForService(fullName.c_str())); + if (binder.get() == nullptr) { + ALOGE("%s binder returned null", fullName.c_str()); + continue; + } + std::shared_ptr<IVehicleBus> vehicleBus = IVehicleBus::fromBinder(binder); + if (vehicleBus == nullptr) { + ALOGE("Couldn't open %s", fullName.c_str()); + continue; + } + + vehicleBus->setOnNewPropValuesCallback(mVehicleBusCallback); + mVehicleBuses.push_back(vehicleBus); + } +} + +void EmulatedVehicleHalServer::stopVehicleBuses() { + for (const auto& vehicleBus : mVehicleBuses) { + vehicleBus->unsetOnNewPropValuesCallback(mVehicleBusCallback); + } +} + +VehiclePropValue EmulatedVehicleHalServer::VehicleBusCallback::makeHidlVehiclePropValue( + const AidlVehiclePropValue& aidlPropValue) { + VehiclePropValue hidlPropValue; + hidlPropValue.timestamp = aidlPropValue.timestamp; + hidlPropValue.areaId = aidlPropValue.areaId; + hidlPropValue.prop = aidlPropValue.prop; + hidlPropValue.status = static_cast<VehiclePropertyStatus>(aidlPropValue.status); + hidlPropValue.value.int32Values = aidlPropValue.value.int32Values; + hidlPropValue.value.floatValues = aidlPropValue.value.floatValues; + hidlPropValue.value.int64Values = aidlPropValue.value.int64Values; + hidlPropValue.value.bytes = aidlPropValue.value.byteValues; + hidlPropValue.value.stringValue = aidlPropValue.value.stringValue; + return hidlPropValue; +} + +::ndk::ScopedAStatus EmulatedVehicleHalServer::VehicleBusCallback::onNewPropValues( + const std::vector<AidlVehiclePropValue>& aidlPropValues) { + for (const auto& aidlPropValue : aidlPropValues) { + mVehicleHalServer->onPropertyValueFromCar( + makeHidlVehiclePropValue(aidlPropValue), true); + } + return ::ndk::ScopedAStatus::ok(); +} + +IVehicleServer::DumpResult EmulatedVehicleHalServer::debug(const std::vector<std::string>& options){ + return DefaultVehicleHalServer::onDump(options); +} + +} // namespace impl + +} // namespace V2_0 +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/emulator/vhal_v2_0/EmulatedVehicleHalServer.h b/emulator/vhal_v2_0/EmulatedVehicleHalServer.h new file mode 100644 index 0000000..5e69eed --- /dev/null +++ b/emulator/vhal_v2_0/EmulatedVehicleHalServer.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <aidl/device/generic/car/emulator/IVehicleBus.h> +#include <aidl/device/generic/car/emulator/BnVehicleBusCallback.h> + +#include <vhal_v2_0/DefaultVehicleHalServer.h> + +#include "VehicleEmulator.h" + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace V2_0 { + +namespace impl { + +// This contains the server operation for VHAL running in emulator. +class EmulatedVehicleHalServer : public DefaultVehicleHalServer, public EmulatedServerIface { + public: + using AidlVehiclePropValue = ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; + using IVehicleBus = ::aidl::device::generic::car::emulator::IVehicleBus; + using BnVehicleBusCallback = ::aidl::device::generic::car::emulator::BnVehicleBusCallback; + + EmulatedVehicleHalServer(); + ~EmulatedVehicleHalServer(); + + StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) override; + + // Methods from EmulatedServerIface + bool setPropertyFromVehicle(const VehiclePropValue& propValue); + + std::vector<VehiclePropValue> getAllProperties() const; + + std::vector<VehiclePropConfig> listProperties(); + + VehiclePropValuePtr get(const VehiclePropValue& requestedPropValue, StatusCode* outStatus); + + IVehicleServer::DumpResult debug(const std::vector<std::string>& options); + + private: + bool mInQEMU; + + class VehicleBusCallback : public BnVehicleBusCallback { + public: + VehicleBusCallback(EmulatedVehicleHalServer* vehicleHalServer) : + mVehicleHalServer(vehicleHalServer) {} + + ::ndk::ScopedAStatus onNewPropValues( + const std::vector<AidlVehiclePropValue>& propValues) override; + + private: + EmulatedVehicleHalServer* mVehicleHalServer; + + VehiclePropValue makeHidlVehiclePropValue(const AidlVehiclePropValue& aidlPropValue); + }; + std::shared_ptr<BnVehicleBusCallback> mVehicleBusCallback; + std::vector<std::shared_ptr<IVehicleBus>> mVehicleBuses; + + void startVehicleBuses(); + void stopVehicleBuses(); +}; + +} // namespace impl + +} // namespace V2_0 +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/emulator/vhal_v2_0/VehicleEmulator.cpp b/emulator/vhal_v2_0/VehicleEmulator.cpp new file mode 100644 index 0000000..f392ddb --- /dev/null +++ b/emulator/vhal_v2_0/VehicleEmulator.cpp @@ -0,0 +1,254 @@ +/* + * 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 diff --git a/emulator/vhal_v2_0/VehicleEmulator.h b/emulator/vhal_v2_0/VehicleEmulator.h new file mode 100644 index 0000000..fa39a57 --- /dev/null +++ b/emulator/vhal_v2_0/VehicleEmulator.h @@ -0,0 +1,117 @@ +/* + * 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. + */ + +#ifndef android_hardware_automotive_vehicle_V2_0_impl_VehicleHalEmulator_H_ +#define android_hardware_automotive_vehicle_V2_0_impl_VehicleHalEmulator_H_ + +#include <log/log.h> +#include <memory> +#include <thread> +#include <vector> + +#include <vhal_v2_0/VehicleHal.h> +#include <vhal_v2_0/VehicleServer.h> + +#include "CommConn.h" +#include "PipeComm.h" +#include "SocketComm.h" +#include "VehicleHalProto.pb.h" + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace V2_0 { + +namespace impl { + +class VehicleEmulator; // Forward declaration. + +/** An interface used by VehicleEmulator. */ +class EmulatedServerIface { + public: + using VehiclePropValuePtr = VehicleHal::VehiclePropValuePtr; + virtual ~EmulatedServerIface() = default; + virtual bool setPropertyFromVehicle(const VehiclePropValue& propValue) = 0; + virtual std::vector<VehiclePropValue> getAllProperties() const = 0; + virtual std::vector<VehiclePropConfig> listProperties() = 0; + virtual VehiclePropValuePtr get(const VehiclePropValue& requestedPropValue, + StatusCode* outStatus) = 0; + virtual IVehicleServer::DumpResult debug(const std::vector<std::string>& options) = 0; + + void registerEmulator(VehicleEmulator* emulator) { + ALOGI("%s, emulator: %p", __func__, emulator); + std::lock_guard<std::mutex> g(mEmulatorLock); + mEmulator = emulator; + } + +protected: + VehicleEmulator* getEmulatorOrDie() { + std::lock_guard<std::mutex> g(mEmulatorLock); + if (mEmulator == nullptr) abort(); + return mEmulator; + } + +private: + mutable std::mutex mEmulatorLock; + VehicleEmulator* mEmulator; +}; + +/** + * Emulates vehicle by providing controlling interface from host side either through ADB or Pipe. + */ +class VehicleEmulator : public MessageProcessor { + public: + VehicleEmulator(EmulatedServerIface* hal); + virtual ~VehicleEmulator(); + + void doSetValueFromClient(const VehiclePropValue& propValue); + void processMessage(const vhal_proto::EmulatorMessage& rxMsg, + vhal_proto::EmulatorMessage* respMsg) override; + + private: + friend class ConnectionThread; + using EmulatorMessage = vhal_proto::EmulatorMessage; + + void doGetConfig(const EmulatorMessage& rxMsg, EmulatorMessage* respMsg); + void doGetConfigAll(const EmulatorMessage& rxMsg, EmulatorMessage* respMsg); + void doGetProperty(const EmulatorMessage& rxMsg, EmulatorMessage* respMsg); + void doGetPropertyAll(const EmulatorMessage& rxMsg, EmulatorMessage* respMsg); + void doSetProperty(const EmulatorMessage& rxMsg, EmulatorMessage* respMsg); + void doDebug(const EmulatorMessage& rxMsg, EmulatorMessage* respMsg); + void populateProtoVehicleConfig(vhal_proto::VehiclePropConfig* protoCfg, + const VehiclePropConfig& cfg); + void populateProtoVehiclePropValue(vhal_proto::VehiclePropValue* protoVal, + const VehiclePropValue* val); + +private: + EmulatedServerIface* mHal; + std::unique_ptr<SocketComm> mSocketComm; + std::unique_ptr<PipeComm> mPipeComm; +}; + +// determine if it's running inside Android Emulator +bool isInQEMU(); + +} // impl + +} // namespace V2_0 +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_V2_0_impl_VehicleHalEmulator_H_ diff --git a/emulator/vhal_v2_0/VehicleService.cpp b/emulator/vhal_v2_0/VehicleService.cpp new file mode 100644 index 0000000..b174433 --- /dev/null +++ b/emulator/vhal_v2_0/VehicleService.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2016 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 "automotive.vehicle@2.0-emulator-service" +#include <android/binder_process.h> +#include <android/log.h> +#include <hidl/HidlTransportSupport.h> + +#include <iostream> + +#include <EmulatedVehicleConnector.h> +#include <EmulatedVehicleHal.h> +#include <vhal_v2_0/VehicleHalManager.h> + +using ::android::hardware::automotive::vehicle::V2_0::VehicleHalManager; +using ::android::hardware::automotive::vehicle::V2_0::VehiclePropertyStore; +using ::android::hardware::automotive::vehicle::V2_0::impl::EmulatedVehicleConnector; +using ::android::hardware::automotive::vehicle::V2_0::impl::EmulatedVehicleHal; + +int main(int /* argc */, char* /* argv */ []) { + auto store = std::make_unique<VehiclePropertyStore>(); + auto connector = std::make_unique<EmulatedVehicleConnector>(); + auto hal = std::make_unique<EmulatedVehicleHal>(store.get(), connector.get()); + auto emulator = connector->getEmulator(); + auto service = std::make_unique<VehicleHalManager>(hal.get()); + connector->setValuePool(hal->getValuePool()); + + ABinderProcess_startThreadPool(); + android::hardware::configureRpcThreadpool(4, true /* callerWillJoin */); + + ALOGI("Registering as service..."); + android::status_t status = service->registerAsService(); + + if (status != android::OK) { + ALOGE("Unable to register vehicle service (%d)", status); + return 1; + } + + ALOGI("Ready"); + android::hardware::joinRpcThreadpool(); + + return 0; +} diff --git a/emulator/vhal_v2_0/android.hardware.automotive.vehicle@2.0-emulator-service.rc b/emulator/vhal_v2_0/android.hardware.automotive.vehicle@2.0-emulator-service.rc new file mode 100644 index 0000000..1fa2e79 --- /dev/null +++ b/emulator/vhal_v2_0/android.hardware.automotive.vehicle@2.0-emulator-service.rc @@ -0,0 +1,4 @@ +service vendor.vehicle-hal-2.0 /vendor/bin/hw/android.hardware.automotive.vehicle@2.0-emulator-service + class early_hal + user vehicle_network + group system inet diff --git a/emulator/vhal_v2_0/android.hardware.automotive.vehicle@2.0-emulator-service.xml b/emulator/vhal_v2_0/android.hardware.automotive.vehicle@2.0-emulator-service.xml new file mode 100644 index 0000000..660b03d --- /dev/null +++ b/emulator/vhal_v2_0/android.hardware.automotive.vehicle@2.0-emulator-service.xml @@ -0,0 +1,11 @@ +<manifest version="1.0" type="device"> + <hal format="hidl"> + <name>android.hardware.automotive.vehicle</name> + <transport>hwbinder</transport> + <version>2.0</version> + <interface> + <name>IVehicle</name> + <instance>default</instance> + </interface> + </hal> +</manifest> diff --git a/emulator/vhal_v2_0/interfaces/aidl/Android.bp b/emulator/vhal_v2_0/interfaces/aidl/Android.bp new file mode 100644 index 0000000..b22d821 --- /dev/null +++ b/emulator/vhal_v2_0/interfaces/aidl/Android.bp @@ -0,0 +1,38 @@ +// This is the expected build file, but it may not be right in all cases + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "device_generic_car_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["device_generic_car_license"], +} + +aidl_interface { + name: "device.generic.car.emulator-aidl", + vendor_available: true, + srcs: ["device/generic/car/emulator/*.aidl"], + imports: [ + "android.hardware.automotive.vehicle", + ], + stability: "vintf", + backend: { + cpp: { + enabled: false, + }, + java: { + enabled: false, + }, + ndk: { + enabled: true, + }, + }, + versions_with_info: [ + { + version: "1", + imports: ["android.hardware.automotive.vehicle-V1"], + }, + ], + +} diff --git a/emulator/vhal_v2_0/interfaces/aidl/aidl_api/device.generic.car.emulator-aidl/1/.hash b/emulator/vhal_v2_0/interfaces/aidl/aidl_api/device.generic.car.emulator-aidl/1/.hash new file mode 100644 index 0000000..34b9cf1 --- /dev/null +++ b/emulator/vhal_v2_0/interfaces/aidl/aidl_api/device.generic.car.emulator-aidl/1/.hash @@ -0,0 +1 @@ +8f02e63cbb8524d7c81a20ca5524d4a27da138a8 diff --git a/emulator/vhal_v2_0/interfaces/aidl/aidl_api/device.generic.car.emulator-aidl/1/device/generic/car/emulator/IVehicleBus.aidl b/emulator/vhal_v2_0/interfaces/aidl/aidl_api/device.generic.car.emulator-aidl/1/device/generic/car/emulator/IVehicleBus.aidl new file mode 100644 index 0000000..a2ff948 --- /dev/null +++ b/emulator/vhal_v2_0/interfaces/aidl/aidl_api/device.generic.car.emulator-aidl/1/device/generic/car/emulator/IVehicleBus.aidl @@ -0,0 +1,24 @@ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package device.generic.car.emulator; +@VintfStability +interface IVehicleBus { + void setOnNewPropValuesCallback(device.generic.car.emulator.IVehicleBusCallback callback); + void unsetOnNewPropValuesCallback(device.generic.car.emulator.IVehicleBusCallback callback); +} diff --git a/emulator/vhal_v2_0/interfaces/aidl/aidl_api/device.generic.car.emulator-aidl/1/device/generic/car/emulator/IVehicleBusCallback.aidl b/emulator/vhal_v2_0/interfaces/aidl/aidl_api/device.generic.car.emulator-aidl/1/device/generic/car/emulator/IVehicleBusCallback.aidl new file mode 100644 index 0000000..b5cc3a4 --- /dev/null +++ b/emulator/vhal_v2_0/interfaces/aidl/aidl_api/device.generic.car.emulator-aidl/1/device/generic/car/emulator/IVehicleBusCallback.aidl @@ -0,0 +1,23 @@ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package device.generic.car.emulator; +@VintfStability +interface IVehicleBusCallback { + oneway void onNewPropValues(in android.hardware.automotive.vehicle.VehiclePropValue[] values); +} diff --git a/emulator/vhal_v2_0/interfaces/aidl/aidl_api/device.generic.car.emulator-aidl/current/device/generic/car/emulator/IVehicleBus.aidl b/emulator/vhal_v2_0/interfaces/aidl/aidl_api/device.generic.car.emulator-aidl/current/device/generic/car/emulator/IVehicleBus.aidl new file mode 100644 index 0000000..a2ff948 --- /dev/null +++ b/emulator/vhal_v2_0/interfaces/aidl/aidl_api/device.generic.car.emulator-aidl/current/device/generic/car/emulator/IVehicleBus.aidl @@ -0,0 +1,24 @@ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package device.generic.car.emulator; +@VintfStability +interface IVehicleBus { + void setOnNewPropValuesCallback(device.generic.car.emulator.IVehicleBusCallback callback); + void unsetOnNewPropValuesCallback(device.generic.car.emulator.IVehicleBusCallback callback); +} diff --git a/emulator/vhal_v2_0/interfaces/aidl/aidl_api/device.generic.car.emulator-aidl/current/device/generic/car/emulator/IVehicleBusCallback.aidl b/emulator/vhal_v2_0/interfaces/aidl/aidl_api/device.generic.car.emulator-aidl/current/device/generic/car/emulator/IVehicleBusCallback.aidl new file mode 100644 index 0000000..b5cc3a4 --- /dev/null +++ b/emulator/vhal_v2_0/interfaces/aidl/aidl_api/device.generic.car.emulator-aidl/current/device/generic/car/emulator/IVehicleBusCallback.aidl @@ -0,0 +1,23 @@ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package device.generic.car.emulator; +@VintfStability +interface IVehicleBusCallback { + oneway void onNewPropValues(in android.hardware.automotive.vehicle.VehiclePropValue[] values); +} diff --git a/emulator/vhal_v2_0/interfaces/aidl/device/generic/car/emulator/IVehicleBus.aidl b/emulator/vhal_v2_0/interfaces/aidl/device/generic/car/emulator/IVehicleBus.aidl new file mode 100644 index 0000000..ed06d96 --- /dev/null +++ b/emulator/vhal_v2_0/interfaces/aidl/device/generic/car/emulator/IVehicleBus.aidl @@ -0,0 +1,32 @@ +package device.generic.car.emulator; + +import device.generic.car.emulator.IVehicleBusCallback; + +/** + * IVehicleBus provides generic interface for various bus interpreters + * (emulated/virtual/physical/etc) to connect to Emulator VHAL and provides + * VehiclePropValue update as if it were generated from real car. + * + * This separates bus implementation details from emulator. For example, + * hard-coded rotary controller vendor specific key mapping can separately + * run as a service, allowing emulator to be spinned separately from the + * particular hardware of interest to be tested at the time. + */ + +import android.hardware.automotive.vehicle.VehiclePropValue; + +@VintfStability +interface IVehicleBus { + /** + * Sets a callback function for whenever new property value is generated + * from the bus. Calling this function twice will result in error. To + * change callback function, call unset function first. + */ + void setOnNewPropValuesCallback(IVehicleBusCallback callback); + + /** + * Unregisters a callback function that is currently active. Expected to + * receive the same Callback that was used to set for successful unset. + */ + void unsetOnNewPropValuesCallback(IVehicleBusCallback callback); +} diff --git a/emulator/vhal_v2_0/interfaces/aidl/device/generic/car/emulator/IVehicleBusCallback.aidl b/emulator/vhal_v2_0/interfaces/aidl/device/generic/car/emulator/IVehicleBusCallback.aidl new file mode 100644 index 0000000..0cbb905 --- /dev/null +++ b/emulator/vhal_v2_0/interfaces/aidl/device/generic/car/emulator/IVehicleBusCallback.aidl @@ -0,0 +1,14 @@ +package device.generic.car.emulator; + +import device.generic.car.emulator.IVehicleBusCallback; +import android.hardware.automotive.vehicle.VehiclePropValue; + +@VintfStability +interface IVehicleBusCallback { + + /** + * This callback is called whenever there is a new propValue detected + * from the bus. + */ + oneway void onNewPropValues(in VehiclePropValue[] values); +} diff --git a/emulator_car64_x86_64/BoardConfig.mk b/emulator_car64_x86_64/BoardConfig.mk new file mode 100644 index 0000000..bfd00ce --- /dev/null +++ b/emulator_car64_x86_64/BoardConfig.mk @@ -0,0 +1,24 @@ +# Copyright (C) 2022 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Use emulator64_x86_64_arm64 BoardConfig as base +include device/generic/goldfish/emulator64_x86_64/BoardConfig.mk +include device/generic/car/emulator/usbpt/BoardConfig.mk + +# Override BOARD_SUPER_PARTITION_SIZE to inclease the mounted system partition. +BOARD_SUPER_PARTITION_SIZE := 5856296960 + +BOARD_EMULATOR_DYNAMIC_PARTITIONS_SIZE = 3489660928 + diff --git a/gsi_car_base.mk b/gsi_car_base.mk index b1fa936..3fdfa77 100644 --- a/gsi_car_base.mk +++ b/gsi_car_base.mk @@ -16,42 +16,49 @@ PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed PRODUCT_PACKAGES += android.frameworks.automotive.display@1.0-service +# TODO(b/193056430): Improve this temp fix for "artifact path requirement" +# errors. +# TODO(b/194941497): SHIPSTOP - remove CarServiceModule PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST += \ root/init.bootstat.rc \ root/init.car.rc \ + system/apex/com.android.car.framework.apex \ + system/app/Bluetooth/Bluetooth.apk \ + system/app/Bluetooth/lib/arm64/libbluetooth_jni.so \ + system/app/Bluetooth/lib/x86_64/libbluetooth_jni.so \ system/app/CarFrameworkPackageStubs/CarFrameworkPackageStubs.apk \ - system/app/CarFrameworkPackageStubs/oat/arm64/CarFrameworkPackageStubs.odex \ - system/app/CarFrameworkPackageStubs/oat/arm64/CarFrameworkPackageStubs.vdex \ system/app/CarHTMLViewer/CarHTMLViewer.apk \ system/app/CarLatinIME/CarLatinIME.apk \ system/app/CarMapsPlaceholder/CarMapsPlaceholder.apk \ system/app/CarPermissionControllerRRO/CarPermissionControllerRRO.apk \ - system/app/RotaryIME/RotaryIME.apk \ - system/app/RotaryIME/oat/arm64/RotaryIME.odex \ - system/app/RotaryIME/oat/arm64/RotaryIME.vdex \ system/app/CarRotaryImeRRO/CarRotaryImeRRO.apk \ + system/app/HideCameraApps/HideCameraApps.apk \ + system/app/RotaryIME/RotaryIME.apk \ system/app/RotaryPlayground/RotaryPlayground.apk \ system/app/SampleCustomInputService/SampleCustomInputService.apk \ system/app/SampleRearViewCamera/SampleRearViewCamera.apk \ - system/app/SampleRearViewCamera/oat/arm64/SampleRearViewCamera.odex \ - system/app/SampleRearViewCamera/oat/arm64/SampleRearViewCamera.vdex \ - system/app/ScriptExecutor/ScriptExecutor.apk \ - system/app/ScriptExecutor/lib/arm64/libscriptexecutorjni.so \ - system/app/ScriptExecutor/lib/x86_64/libscriptexecutorjni.so \ system/app/SystemUpdater/SystemUpdater.apk \ system/bin/android.automotive.evs.manager@1.1 \ + system/bin/canhalconfigurator \ + system/bin/canhalctrl \ + system/bin/canhaldump \ + system/bin/canhalsend \ system/bin/carbugreportd \ system/bin/carpowerpolicyd \ system/bin/carwatchdogd \ system/bin/com.android.car.procfsinspector \ system/bin/curl \ + system/bin/evsmanagerd \ system/bin/vehicle_binding_util \ system/etc/apns-conf.xml \ + system/etc/canbus_config.pb \ system/etc/init/android.automotive.evs.manager@1.1.rc \ + system/etc/init/canhalconfigurator.rc \ system/etc/init/carbugreportd.rc \ system/etc/init/carpowerpolicyd.rc \ system/etc/init/carwatchdogd.rc \ system/etc/init/com.android.car.procfsinspector.rc \ + system/etc/init/evsmanagerd.rc \ system/etc/init/init.bootstat.car.rc \ system/etc/init/init.car.rc \ system/etc/init/vehicle_binding_util.rc \ @@ -60,8 +67,10 @@ PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST += \ system/etc/permissions/android.car.usb.handler.xml \ system/etc/permissions/android.hardware.broadcastradio.xml \ system/etc/permissions/android.hardware.type.automotive.xml \ + system/etc/permissions/car-frameworks-service.xml \ system/etc/permissions/com.android.car.activityresolver.xml \ system/etc/permissions/com.android.car.bugreport.xml \ + system/etc/permissions/com.android.car.cartelemetryapp.xml \ system/etc/permissions/com.android.car.carlauncher.xml \ system/etc/permissions/com.android.car.cluster.home.xml \ system/etc/permissions/com.android.car.dialer.xml \ @@ -78,27 +87,34 @@ PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST += \ system/etc/permissions/com.google.android.car.garagemode.testapp.xml \ system/etc/permissions/com.google.android.car.kitchensink.xml \ system/etc/permissions/com.google.android.car.networking.preferenceupdater.xml \ + system/etc/permissions/com.google.android.car.networking.railway.xml \ system/etc/sysconfig/preinstalled-packages-product-car-base.xml \ system/etc/vintf/manifest/carpowerpolicyd.xml \ system/etc/vintf/manifest/carwatchdogd.xml \ system/etc/vintf/manifest/manifest_android.automotive.evs.manager@1.1.xml \ + system/etc/vintf/manifest/manifest_evsmanagerd.xml \ system/framework/android.car.jar \ + system/framework/android.car.builtin.jar \ system/framework/car-frameworks-service.jar \ - system/framework/oat/arm64/car-frameworks-service.odex \ - system/framework/oat/arm64/car-frameworks-service.vdex \ - system/lib/libcar-framework-service-jni.so \ + system/framework/car-frameworks-service-module.jar \ system/lib/libsuspend.so \ system/lib64/android.automotive.watchdog-V3-cpp.so \ system/lib64/android.automotive.watchdog.internal-cpp.so \ system/lib64/android.frameworks.automotive.display@1.0.so \ system/lib64/android.frameworks.automotive.powerpolicy-V1-cpp.so \ - system/lib64/android.frameworks.automotive.powerpolicy.internal-cpp.so \ + system/lib64/android.frameworks.automotive.powerpolicy-V1-ndk.so \ + system/lib64/android.frameworks.automotive.powerpolicy.internal-V1-cpp.so \ + system/lib64/android.frameworks.automotive.powerpolicy.internal-V1-ndk.so \ + system/lib64/android.hardware.automotive.can@1.0.so \ system/lib64/android.hardware.automotive.evs@1.0.so \ system/lib64/android.hardware.automotive.evs@1.1.so \ + system/lib64/android.hardware.automotive.evs-V1-ndk.so \ system/lib64/android.hardware.automotive.vehicle@2.0.so \ - system/lib64/libcar-framework-service-jni.so \ - system/lib64/libscriptexecutor.so \ - system/lib64/libscriptexecutorjni.so \ + system/lib64/android.os.statsbootstrap_aidl-cpp.so \ + system/lib64/libbluetooth_jni.so \ + system/lib64/libstatsbootstrap.so \ + system/lib64/libstatslog_evs.so \ + system/lib64/libstatslog_evsmanagerd.so \ system/lib64/libsuspend.so \ system/lib64/libwatchdog_binder_mediator.so \ system/lib64/libwatchdog_package_info_resolver.so \ @@ -107,8 +123,6 @@ PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST += \ system/media/bootanimation.zip \ system/priv-app/BugReportApp/BugReportApp.apk \ system/priv-app/CarActivityResolver/CarActivityResolver.apk \ - system/priv-app/CarActivityResolver/oat/arm64/CarActivityResolver.odex \ - system/priv-app/CarActivityResolver/oat/arm64/CarActivityResolver.vdex \ system/priv-app/CarDialerApp/CarDialerApp.apk \ system/priv-app/CarHvacApp/CarHvacApp.apk \ system/priv-app/CarLauncher/CarLauncher.apk \ @@ -118,35 +132,23 @@ PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST += \ system/priv-app/CarRadioApp/CarRadioApp.apk \ system/priv-app/CarRotaryController/CarRotaryController.apk \ system/priv-app/CarService/CarService.apk \ - system/priv-app/CarService/lib/arm64/libscriptexecutorjni.so \ - system/priv-app/CarService/lib/x86_64/libscriptexecutorjni.so \ - system/priv-app/CarService/oat/arm64/CarService.odex \ - system/priv-app/CarService/oat/arm64/CarService.vdex \ + system/priv-app/CarService/lib/arm64/libcarservicejni.so \ + system/priv-app/CarService/lib/x86_64/libcarservicejni.so \ system/priv-app/CarSettings/CarSettings.apk \ system/priv-app/CarShell/CarShell.apk \ - system/priv-app/CarShell/oat/arm64/CarShell.odex \ - system/priv-app/CarShell/oat/arm64/CarShell.vdex \ + system/priv-app/CarTelemetryApp/CarTelemetryApp.apk \ system/priv-app/CarUsbHandler/CarUsbHandler.apk \ - system/priv-app/CarUsbHandler/oat/arm64/CarUsbHandler.odex \ - system/priv-app/CarUsbHandler/oat/arm64/CarUsbHandler.vdex \ system/priv-app/ClusterHomeSample/ClusterHomeSample.apk \ - system/priv-app/ClusterHomeSample/oat/arm64/ClusterHomeSample.odex \ - system/priv-app/ClusterHomeSample/oat/arm64/ClusterHomeSample.vdex \ system/priv-app/DefaultStorageMonitoringCompanionApp/DefaultStorageMonitoringCompanionApp.apk \ system/priv-app/DirectRenderingCluster/DirectRenderingCluster.apk \ - system/priv-app/DirectRenderingCluster/oat/arm64/DirectRenderingCluster.odex \ - system/priv-app/DirectRenderingCluster/oat/arm64/DirectRenderingCluster.vdex \ system/priv-app/EmbeddedKitchenSinkApp/EmbeddedKitchenSinkApp.apk \ system/priv-app/ExperimentalCarService/ExperimentalCarService.apk \ - system/priv-app/ExperimentalCarService/oat/arm64/ExperimentalCarService.odex \ - system/priv-app/ExperimentalCarService/oat/arm64/ExperimentalCarService.vdex \ system/priv-app/AdasLocationTestApp/AdasLocationTestApp.apk \ system/priv-app/GarageModeTestApp/GarageModeTestApp.apk \ system/priv-app/LocalMediaPlayer/LocalMediaPlayer.apk \ system/priv-app/NetworkPreferenceApp/NetworkPreferenceApp.apk \ + system/priv-app/RailwayReferenceApp/RailwayReferenceApp.apk \ system/lib64/libcarservicejni.so \ - system/priv-app/CarService/lib/arm64/libcarservicejni.so \ - system/priv-app/CarService/lib/x86_64/libcarservicejni.so \ system/bin/android.automotive.telemetryd@1.0 \ system/etc/init/android.automotive.telemetryd@1.0.rc \ system/etc/vintf/manifest/android.automotive.telemetryd@1.0.xml \ diff --git a/setup/overlay/packages/services/Car/service/res/values/config.xml b/setup/overlay/packages/services/Car/service/res/values/config.xml deleted file mode 100644 index 5add0cd..0000000 --- a/setup/overlay/packages/services/Car/service/res/values/config.xml +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2020, 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. -*/ ---> - -<!-- Resources to configure car service based on each OEM's preference. --> -<resources> - - <!-- Specifies notice UI that will be launched when user starts a car or do user - switching. It is recommended to use dialog with at least TYPE_APPLICATION_OVERLAY window - type to show the UI regardless of activity launches. Target package will be auto-granted - necessary permission for TYPE_APPLICATION_OVERLAY window type. The UI package should - resolve permission by itself to use any higher priority window type. - Setting this string to empty will disable the feature. --> - <string name="config_userNoticeUiService" translatable="false">com.google.android.car.setupwizard/.account.ShortNoticeService</string> -</resources> |