summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXin Li <delphij@google.com>2022-06-28 21:23:15 +0000
committerXin Li <delphij@google.com>2022-06-28 21:23:15 +0000
commit8d7f62061eaf2993eece5614a8de37aa286feb29 (patch)
tree8d903d2222c6c1733589b7b2e3458465d9635fb8
parentc44d9f40639efdb885a261f071cf33be389925b4 (diff)
parent1dafa1ea1d1f73ee8a7654fca929f87bf8fd037c (diff)
downloadcar-temp_sam_242648940.tar.gz
Merge tm-dev-plus-aosp-without-vendor@8763363temp_sam_242648940
Bug: 236760014 Merged-In: Id5ea4670f6e87629666aae6b5c1cfe64b0e4e7b2 Change-Id: Ib0cab0e6ca0e559dfd98480677729b88fb9ba6bb
-rw-r--r--car_ui_portrait.mk1
-rw-r--r--common/car.mk6
-rw-r--r--common/car_core_hardware.xml5
-rw-r--r--common/overlay/frameworks/base/core/res/res/values/config.xml4
-rw-r--r--common/overlay/frameworks/base/core/res/res/values/vendor_required_apps_managed_user.xml1
-rw-r--r--common/overlay/packages/services/Car/service/res/values/config.xml28
-rw-r--r--common/preinstalled-packages-product-car-emulator.xml7
-rw-r--r--emulator/Conn/CommConn/Android.bp33
-rw-r--r--emulator/Conn/CommConn/CommConn.cpp79
-rw-r--r--emulator/Conn/CommConn/include/CommConn.h140
-rw-r--r--emulator/Conn/PipeComm/Android.bp35
-rw-r--r--emulator/Conn/PipeComm/PipeComm.cpp105
-rw-r--r--emulator/Conn/PipeComm/include/PipeComm.h64
-rw-r--r--emulator/Conn/PipeComm/include/qemu_pipe.h65
-rw-r--r--emulator/Conn/PipeComm/qemu_pipe.cpp104
-rw-r--r--emulator/Conn/SocketComm/Android.bp34
-rw-r--r--emulator/Conn/SocketComm/SocketComm.cpp225
-rw-r--r--emulator/Conn/SocketComm/include/SocketComm.h124
-rw-r--r--emulator/aosp_car_emulator.mk5
-rw-r--r--emulator/audio/overlay/packages/services/Car/service/res/values/config.xml31
-rw-r--r--emulator/cluster/rro_overlays/CarServiceOverlay/Android.bp27
-rw-r--r--emulator/cluster/rro_overlays/CarServiceOverlay/AndroidManifest.xml25
-rw-r--r--emulator/cluster/rro_overlays/CarServiceOverlay/res/values/config.xml (renamed from emulator/cluster/overlay/packages/services/Car/service/res/values/config.xml)7
-rw-r--r--emulator/cluster/rro_overlays/CarServiceOverlay/res/xml/overlays.xml22
-rw-r--r--emulator/cluster/rro_overlays/CarServiceOverlay_OsDouble/Android.bp34
-rw-r--r--emulator/cluster/rro_overlays/CarServiceOverlay_OsDouble/AndroidManifest.xml25
-rw-r--r--emulator/cluster/rro_overlays/CarServiceOverlay_OsDouble/res/values/config.xml (renamed from emulator/cluster/osdouble_overlay/packages/services/Car/service/res/values/config.xml)7
-rw-r--r--emulator/cluster/rro_overlays/CarServiceOverlay_OsDouble/res/xml/overlays.xml22
-rw-r--r--emulator/usbpt/bluetooth/btusb/btusb.mk4
-rw-r--r--emulator/usbpt/bluetooth/btusb/rtl_bt/Android.bp24
-rwxr-xr-xemulator/usbpt/bluetooth/btusb/rtl_bt/rtl8821c_config.binbin10 -> 0 bytes
-rw-r--r--emulator/usbpt/bluetooth/btusb/rtl_bt/rtl8821c_fw.binbin48816 -> 0 bytes
-rw-r--r--emulator/usbpt/car_usbpt.mk1
-rw-r--r--emulator/usbpt/protocan/canbus_config.pb30
-rw-r--r--emulator/usbpt/protocan/manifest.protocan.xml19
-rw-r--r--emulator/usbpt/protocan/protocan.mk27
-rw-r--r--emulator/usbpt/protocan/protocanbus/Android.bp61
-rw-r--r--emulator/usbpt/protocan/protocanbus/CanClient.cpp138
-rw-r--r--emulator/usbpt/protocan/protocanbus/CanClient.h70
-rw-r--r--emulator/usbpt/protocan/protocanbus/CloseHandleWrapper.cpp64
-rw-r--r--emulator/usbpt/protocan/protocanbus/CloseHandleWrapper.h50
-rw-r--r--emulator/usbpt/protocan/protocanbus/ExtraCanClient.cpp139
-rw-r--r--emulator/usbpt/protocan/protocanbus/ExtraCanClient.h29
-rw-r--r--emulator/usbpt/protocan/protocanbus/VehicleBus.cpp96
-rw-r--r--emulator/usbpt/protocan/protocanbus/VehicleBus.h58
-rw-r--r--emulator/usbpt/protocan/protocanbus/android.device.generic.car.emulator@1.0-protocanbus-service.rc4
-rw-r--r--emulator/usbpt/protocan/protocanbus/manifest_android.device.generic.car.emulator@1.0-protocanbus.xml18
-rw-r--r--emulator/usbpt/protocan/protocanbus/sepolicy/file_contexts1
-rw-r--r--emulator/usbpt/protocan/protocanbus/sepolicy/hal_vehiclebus.te4
-rw-r--r--emulator/usbpt/protocan/protocanbus/sepolicy/hal_vehiclebus_default.te13
-rw-r--r--emulator/usbpt/protocan/protocanbus/sepolicy/service.te1
-rw-r--r--emulator/usbpt/protocan/protocanbus/sepolicy/service_contexts1
-rw-r--r--emulator/usbpt/protocan/protocanbus/service.cpp41
-rw-r--r--emulator/usbpt/protocan/protocanbus/service.h0
-rw-r--r--emulator/vhal_aidl/Android.bp57
-rw-r--r--emulator/vhal_aidl/EmulatedVehicleService.cpp55
-rw-r--r--emulator/vhal_aidl/VehicleEmulator/Android.bp49
-rw-r--r--emulator/vhal_aidl/VehicleEmulator/EmulatedVehicleHardware.cpp178
-rw-r--r--emulator/vhal_aidl/VehicleEmulator/VehicleEmulator.cpp354
-rw-r--r--emulator/vhal_aidl/VehicleEmulator/include/EmulatedVehicleHardware.h99
-rw-r--r--emulator/vhal_aidl/VehicleEmulator/include/VehicleEmulator.h81
-rw-r--r--emulator/vhal_aidl/VehicleEmulator/test/Android.bp48
-rw-r--r--emulator/vhal_aidl/VehicleEmulator/test/VehicleEmulatorTest.cpp457
-rw-r--r--emulator/vhal_aidl/vhal-emulator-service.rc4
-rw-r--r--emulator/vhal_aidl/vhal-emulator-service.xml10
-rw-r--r--emulator/vhal_v2_0/Android.bp80
-rw-r--r--emulator/vhal_v2_0/EmulatedVehicleConnector.cpp39
-rw-r--r--emulator/vhal_v2_0/EmulatedVehicleConnector.h52
-rw-r--r--emulator/vhal_v2_0/EmulatedVehicleHal.cpp40
-rw-r--r--emulator/vhal_v2_0/EmulatedVehicleHal.h47
-rw-r--r--emulator/vhal_v2_0/EmulatedVehicleHalServer.cpp161
-rw-r--r--emulator/vhal_v2_0/EmulatedVehicleHalServer.h86
-rw-r--r--emulator/vhal_v2_0/VehicleEmulator.cpp254
-rw-r--r--emulator/vhal_v2_0/VehicleEmulator.h117
-rw-r--r--emulator/vhal_v2_0/VehicleService.cpp56
-rw-r--r--emulator/vhal_v2_0/android.hardware.automotive.vehicle@2.0-emulator-service.rc4
-rw-r--r--emulator/vhal_v2_0/android.hardware.automotive.vehicle@2.0-emulator-service.xml11
-rw-r--r--emulator/vhal_v2_0/interfaces/aidl/Android.bp38
-rw-r--r--emulator/vhal_v2_0/interfaces/aidl/aidl_api/device.generic.car.emulator-aidl/1/.hash1
-rw-r--r--emulator/vhal_v2_0/interfaces/aidl/aidl_api/device.generic.car.emulator-aidl/1/device/generic/car/emulator/IVehicleBus.aidl24
-rw-r--r--emulator/vhal_v2_0/interfaces/aidl/aidl_api/device.generic.car.emulator-aidl/1/device/generic/car/emulator/IVehicleBusCallback.aidl23
-rw-r--r--emulator/vhal_v2_0/interfaces/aidl/aidl_api/device.generic.car.emulator-aidl/current/device/generic/car/emulator/IVehicleBus.aidl24
-rw-r--r--emulator/vhal_v2_0/interfaces/aidl/aidl_api/device.generic.car.emulator-aidl/current/device/generic/car/emulator/IVehicleBusCallback.aidl23
-rw-r--r--emulator/vhal_v2_0/interfaces/aidl/device/generic/car/emulator/IVehicleBus.aidl32
-rw-r--r--emulator/vhal_v2_0/interfaces/aidl/device/generic/car/emulator/IVehicleBusCallback.aidl14
-rw-r--r--emulator_car64_x86_64/BoardConfig.mk24
-rw-r--r--gsi_car_base.mk72
-rw-r--r--setup/overlay/packages/services/Car/service/res/values/config.xml30
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
deleted file mode 100755
index 76f62b8..0000000
--- a/emulator/usbpt/bluetooth/btusb/rtl_bt/rtl8821c_config.bin
+++ /dev/null
Binary files differ
diff --git a/emulator/usbpt/bluetooth/btusb/rtl_bt/rtl8821c_fw.bin b/emulator/usbpt/bluetooth/btusb/rtl_bt/rtl8821c_fw.bin
deleted file mode 100644
index ad31c94..0000000
--- a/emulator/usbpt/bluetooth/btusb/rtl_bt/rtl8821c_fw.bin
+++ /dev/null
Binary files differ
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>