AAOS - Create AIDL Interface
Tags: automotiveandroidaidl
Android Interface Definition Language (AIDL) defines the programming interface that both the client and service agree upon, in order to communicate with each other using Inter-Process Communication (IPC).
Create AIDL Interface
Compiling the AIDL interface auto-generates 2 classes - a Proxy class and a Stub class:
- The Proxy class acts as a client-side representation, managing communication with the remote service and marshalling the request to a kernel driver (Binder)
- The Stub class serves as the server-side implementation, un-marshalling incoming requests from the proxy (via the Binder) and executing the actual service operations defined in the AIDL
Create folder structure in vendor/trongvq/interfaces/virtio_rtc
as below:
Directoryvendor/trongvq/interfaces/virtio_rtc
- Android.bp
Directoryvendor/trongvq/virtio_rtc
- IVirtio_RTC.aidl
-
Create an
Android.bp
file to define the build modules and build configuration:vendor/trongvq/interfaces/virtio_rtc/Android.bp aidl_interface {name: "vendor.trongvq.virtio_rtc",vendor: true, // installed in /vendorsrcs: ["vendor/trongvq/virtio_rtc/*.aidl"],stability: "vintf", // Stable Vendor Interfaceowner: "TRONGVQ",backend: {cpp: {enabled: true,},java: {sdk_version: "module_current",},},} -
Create
IVirtio_RTC.aidl
file which define Interface’s methods:vendor/trongvq/interfaces/virtio_rtc/vendor/trongvq/virtio_rtc/IVirtio_RTC.aidl package vendor.trongvq.virtio_rtc;@VintfStabilityinterface IVirtio_RTC {String getTime();boolean setTime(in String seconds);} -
Tag AIDL
current
version:Run make to build AIDL, but the first time, it will fail. Fix it with provided command:
mm -j10API dump for the current version of AIDL interface vendor.trongvq.virtio_rtc does not exist.Run the command "m vendor.trongvq.virtio_rtc-update-api" or add "unstable: true" to the build rule for the interface if it does not need to be versionedExecute suggested command:
m vendor.trongvq.virtio_rtc-update-apiThe command will create a tag current aidl api for the AIDL interface:
Directoryvendor/trongvq/interfaces/virtio_rtc
- Android.bp
Directoryvendor/trongvq/virtio_rtc
- IVirtio_RTC.aidl
Directoryaidl_api
Directoryvendor.trongvq.virtio_rtc
Directorycurrent
Directoryvendor/trongvq/virtio_rtc
- IVirtio_RTC.aidl
The current folder will be renamed to 1 if there is a new api created. That new version will be new current folder then after.
-
Build AIDL Interface:
vendor/trongvq/interfaces/virtio_rtc mm -j10find out/target/product/vsoc_x86_64_only/vendor/ -name *virtio_rtc*out/target/product/vsoc_x86_64_only/vendor/bin/vendor.trongvq.virtio_rtc-cpp-analyzerout/target/product/vsoc_x86_64_only/vendor/framework/vendor.trongvq.virtio_rtc-V1-java.jarout/target/product/vsoc_x86_64_only/vendor/lib64/libvendor_trongvq_virtio_rtc_V1.dylib.soout/target/product/vsoc_x86_64_only/vendor/lib64/vendor.trongvq.virtio_rtc-V1-ndk.soout/target/product/vsoc_x86_64_only/vendor/lib64/vendor.trongvq.virtio_rtc-V1-cpp.soRefer:
- https://source.android.com/docs/core/architecture/aidl/aidl-hals#choosing-runtime
- https://source.android.com/docs/core/architecture/aidl/stable-aidl#module-naming-rules
AIDL has three different backends: Java, NDK, CPP:
-
Java
vendor.trongvq.virtio_rtc-V1-java.jar
: Stable Java Proxy and Java Stub classes, usefind ./out/ -name *Virtio_RTC.java
to locate the generated file. -
NDK
vendor.trongvq.virtio_rtc-V1-ndk.so
: Stable Native Binder Proxy (BpVirio_RTC.h) class for client code and Binder Native Stub (BnVitio_RTC.h), linked tolibbinder_ndk
, use for vendor service and client, usefind ./out/ -name *Virtio_RTC.h
to locate the generated file. -
CPP
vendor.trongvq.virtio_rtc-V1-cpp.so
: Unstable CPP Proxy (BpVirio_RTC.h) and Stube (BnVitio_RTC.h) classes, linked tolibbinder
, usefind ./out/ -name *Virtio_RTC.h
to locate the generated file.
-
Add AIDL to vendor packages:
Create a vendor make file:
device/google/cuttlefish/shared/trongvq.mk PRODUCT_PACKAGES += vendor.trongvq.virtio_rtcAdd vendor make file into Cuttlefish device make file:
device/google/cuttlefish/shared/device.mk # Include vendor trongvq modules$(call inherit-product, device/google/cuttlefish/shared/trongvq.mk) -
Rebuild Android to include built AIDL library to target device
Create Service
Refer: https://source.android.com/docs/core/architecture/aidl/aidl-backends
Create a vendor service in vendor/trongvq/services/virtio_rtc
:
Directoryvendor/trongvq/
- device_framework_matrix.xml # compatibility
Directoryinterfaces/virio_rtc
- Android.bp
Directoryvendor/trongvq/virtio_rtc
- IVirtio_RTC.aidl
Directoryservices/virtio_rtc
- Android.bp
- inc
Directorysrc
- Virtio_RTC_Service.cpp
- vendor.trongvq.virtio_rtc-service.rc # start service at startup
- vendor.trongvq.virtio_rtc-service.xml # declare and configure interface
-
Create
Android.bp
to declare a Service binary:vendor/trongvq/services/virtio_rtc/Android.bp cc_binary {name: "vendor.trongvq.virtio_rtc-service",vendor: true,relative_install_path: "hw", // relative to /vendor/bininit_rc: ["vendor.trongvq.virtio_rtc-service.rc"],vintf_fragments: ["vendor.trongvq.virtio_rtc-service.xml"],local_include_dirs: ["inc",],srcs: ["src/*.cpp",],cflags: ["-Wall","-Werror",],shared_libs: ["liblog","libutils","libbinder_ndk", // stable version"vendor.trongvq.virtio_rtc-V1-ndk", // stable version],} -
Create Service RC file:
vendor/trongvq/services/virtio_rtc/vendor.trongvq.virtio_rtc-service.rc service vendor.trongvq.virtio_rtc-service /vendor/hw/vendor.trongvq.virtio_rtc-serviceinterface aidl vendor.trongvq.virtio_rtc.IVirtio_RTC/defaultclass haluser systemgroup system -
Create Service XML file:
vendor/trongvq/services/virtio_rtc/vendor.trongvq.virtio_rtc-service.xml <manifest version="1.0" type="device"><hal format="aidl"><name>vendor.trongvq.virtio_rtc</name><version>1</version><fqname>IVirtio_RTC/default</fqname></hal></manifest> -
Add Service to target device:
device/google/cuttlefish/shared/trongvq.mk PRODUCT_PACKAGES += vendor.trongvq.virtio_rtcPRODUCT_PACKAGES += vendor.trongvq.virtio_rtc-serviceHowever, when rebuild system, it fails:
ERROR: files are incompatible: The following instances are in the device manifest but not specified in framework compatibility matrix:vendor.trongvq.virtio_rtc.IVirtio_RTC/default (@1)Suggested fix:1. Update deprecated HALs to the latest version.2. Check for any typos in device manifest or framework compatibility matrices with FCM version >= 202404.3. For new platform HALs, add them to any framework compatibility matrix with FCM version >= 202404 where applicable.4. For device-specific HALs, add to DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE or DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILETo fix this, move to the next step.
-
Add Service to Device Framework Compatibility Matrix (FCM):
The framework compatibility matrix consists of the system compatibility matrix, the product compatibility matrix, and the system_ext compatibility matrix.
The requirements of the FCM must be satisfied by the device manifest (requirements enforced at build time, runtime, and in VTS):
- correct name
- compatible versions
- compatible interface instances
vendor/trongvq/device_framework_matrix.xml <compatibility-matrix version="1.0" type="framework"><hal format="aidl" optional="true"><name>vendor.trongvq.virtio_rtc</name><version>1</version><interface><name>IVirtio_RTC</name><instance>default</instance></interface></hal></compatibility-matrix>Add to vendor packages:
device/google/cuttlefish/shared/trongvq.mk DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE := vendor/trongvq/device_framework_matrix.xmlPRODUCT_PACKAGES += vendor.trongvq.virtio_rtcPRODUCT_PACKAGES += vendor.trongvq.virtio_rtc-service -
Rebuild again
The service binary is built and copied into output folder at
vendor/bin/hw
(noted that Android.bp uses relative pathhw
):./out/target/product/vsoc_x86_64_only/vendor/bin/hw/vendor.trongvq.virtio_rtc-service
Set SE Policy
Directorydevice/google/cuttlefish/shared/sepolicy/vendor
- file_contexts
- hal_virtio_rtc_default.te
Directoryvendor/trongvq/
- device_framework_matrix.xml # compatibility
Directoryinterfaces/virio_rtc
- Android.bp
Directoryvendor/trongvq/virtio_rtc
- IVirtio_RTC.aidl
Directoryservices/virtio_rtc
- Android.bp
- inc
Directorysrc
- Virtio_RTC_Service.cpp
- vendor.trongvq.virtio_rtc-service.rc # start service at startup
- vendor.trongvq.virtio_rtc-service.xml # declare and configure interface
Launch Cuttlefish device and check in logcat or dmesg to see that the service could not start:
dmesg | grep virtio_rtc
Could not start service 'vendor.trongvq.virtio_rtc-service' as part of class 'hal': File /vendor/bin/hw/vendor.trongvq.virtio_rtc-service(labeled "u:object_r:vendor_file:s0") has incorrect label or no domain transition from u:r:init:s0 to another SELinux domain defined. Have you configured your service correctly? https://source.android.com/security/selinux/device-policy#label_new_services_and_address_denials. Note: this error shows up even in permissive mode in order to make auditing denials possible.
File vendor.trongvq.virtio_rtc-service
is labeled as u:object_r:vendor_file:s0
which is incorrect. On target shell, use ls -lZ
to see the label.
That default label is defined in file system/sepolicy/private/file_contexts
:
# Vendor files/(vendor|system/vendor)(/.*)? u:object_r:vendor_file:s0
-
Add SE Policy for vendor service:
The vendor service should have the label
hal_virtio_rtc_default_exec
defined in Device SE Policy:device/google/cuttlefish/shared/sepolicy/vendor/file_contexts /vendor/bin/hw/vendor\.trongvq\.virtio_rtc-service u:object_r:hal_virtio_rtc_default_exec:s0When rebuild, it fails due to type
hal_virtio_rtc_default_exec
is not defined. -
Create vendor SE Policy file:
Add a new file
hal_virtio_rtc_default.te
:device/google/cuttlefish/shared/sepolicy/vendor/hal_virtio_rtc_default.te type hal_virtio_rtc_default, domain;type hal_virtio_rtc_default_exec, exec_type, vendor_file_type, file_type;init_daemon_domain(hal_virtio_rtc_default);domain
means it can be assigned to processes and that it is allowed to execute code.exec_type
means it can be executed, applied forvendor_file_type
and generalfile_type
.init_daemon_domain
is an SELinux macro that’s defined in the Android public policies, details insystem/sepolicy/public/te_macros
. It’s used to transition the domain context from init to hal_virtio_rtc_default.
-
Rebuild the target and it should be compiled.
Go to the device shell, verify the label of the service binary:
ls -lZ vendor/bin/hw/vendor.trongvq.virtio_rtc-service-rwxr-xr-x 1 root shell u:object_r:hal_virtio_rtc_default_exec:s0 vendor/bin/hw/vendor.trongvq.virtio_rtc-serviceand check the
logcat
ordmesg
:dmesg | grep virtio_rtcinit: starting service 'vendor.trongvq.virtio_rtc-service'...init: ... started service 'vendor.trongvq.virtio_rtc-service' has pid 508
Implement Service
Directorydevice/google/cuttlefish/shared/sepolicy/vendor
- service.te
- service_contexts
- file_contexts
- hal_virtio_rtc_default.te
Directoryvendor/trongvq/
- device_framework_matrix.xml # compatibility
Directoryinterfaces/virio_rtc
- Android.bp
Directoryvendor/trongvq/virtio_rtc
- IVirtio_RTC.aidl
Directoryservices/virtio_rtc
- Android.bp
Directoryinc
- Virtio_RTC.h
Directorysrc
- Virtio_RTC.cpp
- Virtio_RTC_Service.cpp
- vendor.trongvq.virtio_rtc-service.rc # start service at startup
- vendor.trongvq.virtio_rtc-service.xml # declare and configure interface
The AIDL interface is generated as NDK stable source code:
tree out/soong/.intermediates/vendor/trongvq/interfaces/virtio_rtc/vendor.trongvq.virtio_rtc-V1-ndk-source/gen/
├── include│ ├── aidl│ │ └── vendor│ │ └── trongvq│ │ └── virtio_rtc│ │ ├── BnVirtio_RTC.h│ │ ├── BpVirtio_RTC.h│ │ └── IVirtio_RTC.h└── vendor └── trongvq └── virtio_rtc ├── IVirtio_RTC.cpp └── IVirtio_RTC.cpp.d
-
The AIDL interace is defined in class
IVirtio_RTC
(inheriates::ndk::ICInterface
). -
The Binder Proxy is defined in class
BpVirtio_RTC
(inheriates::ndk::BpCInterface<IVirtio_RTC>
), and implemented inIVirtio_RTC.cpp
. The methods of interface are fully implemented for Binder Proxy. Any process having a Binder Proxy object can call its methods to communicate with the Binder Native Stub. -
The Binder Native is defined in class
BnVirtio_RTC
(inheriates::ndk::BnCInterface<IVirtio_RTC>
), but partially impplemented inIVirtio_RTC.cpp
. It is required to implement virtual methods declared in the AIDL interfaces. These methods are called through the Binder IPC, and they are user-defined functionanities.
-
Create Service Header in
Virtio_RTC.h
:vendor/trongvq/services/virtio_rtc/inc/Virtio_RTC.h #pragma once#include <aidl/vendor/trongvq/virtio_rtc/BnVirtio_RTC.h>namespace aidl::vendor::trongvq::virtio_rtc {class Virtio_RTC : public BnVirtio_RTC {public:::ndk::ScopedAStatus getTime(std::string *_aidl_return) override;::ndk::ScopedAStatus setTime(const std::string &in_seconds, bool *_aidl_return) override;};} // namespace aidl::vendor::trongvq::virtio_rtc -
Implement Service Methods in
Virtio_RTC.cpp
:vendor/trongvq/services/virtio_rtc/src/Virtio_RTC.cpp #include "Virtio_RTC.h"#include <fcntl.h>#include <utils/Log.h>namespace aidl::vendor::trongvq::virtio_rtc {static const char VIRTIO_RTC_PATH[] = "/dev/virtio_rtc";::ndk::ScopedAStatus Virtio_RTC::getTime(std::string *_aidl_return) {int fd = open(VIRTIO_RTC_PATH, O_RDONLY);if (fd < 0) {ALOGE("Failed to open %s", VIRTIO_RTC_PATH);return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_SERVICE_SPECIFIC));}char buf[64];int len = read(fd, buf, sizeof(buf));if (len < 0) {close(fd);ALOGE("Failed to read %s", VIRTIO_RTC_PATH);return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_SERVICE_SPECIFIC));}close(fd);buf[len] = '\0';ALOGI("Current time: %s", buf);*_aidl_return = buf;return ndk::ScopedAStatus::ok();}::ndk::ScopedAStatus Virtio_RTC::setTime(const std::string &in_seconds, bool *_aidl_return) {int fd = open(VIRTIO_RTC_PATH, O_WRONLY);if (fd < 0) {ALOGE("Failed to open %s", VIRTIO_RTC_PATH);return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_SERVICE_SPECIFIC));}int len = write(fd, in_seconds.c_str(), in_seconds.size());if (len < 0) {close(fd);ALOGE("Failed to write %s", VIRTIO_RTC_PATH);return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_SERVICE_SPECIFIC));}close(fd);ALOGI("Setting time to %s", in_seconds.c_str());*_aidl_return = true;return ndk::ScopedAStatus::ok();}} // namespace aidl::vendor::trongvq::virtio_rtc -
Update SE Policy:
Rebuild target and check service in the logcat or dmesg, expect it fails with
avc: denied
error:W binder:3962_2: type=1400 audit(0.0:147): avc: denied { call } for scontext=u:r:hal_virtio_rtc_default:s0 tcontext=u:r:servicemanager:s0 tclass=binder permissive=0When service calls
AServiceManager_addService()
, the process calls the Service Manager via the Binder to register its service. This step needs a permission!
-
Use tool
audit2allow
to convert SELinux audit messages into SELinux allow rules:sudo apt install policycoreutils-python-utils -
Now pull the policy file, and read logcat to check audit message:
mkdir ~/tempcd ~/tempadb pull /sys/fs/selinux/policyadb logcat -b all -d | grep virtio_rtc | audit2allow -p policy#============= hal_virtio_rtc_default ==============allow hal_virtio_rtc_default servicemanager:binder call; -
Add suggested statement to vendor policy:
device/google/cuttlefish/shared/sepolicy/vendor/hal_virtio_rtc_default.te allow hal_virtio_rtc_default servicemanager:binder call;Rebuild again, and check service in the logcat or dmesg, expect it fails with another
avc: denied
error:W binder:3914_2: type=1400 audit(0.0:124): avc: denied { transfer } for scontext=u:r:hal_virtio_rtc_default:s0 tcontext=u:r:servicemanager:s0 tclass=binder permissive=0 -
Run the tool and add suguested statement to vendor policy:
device/google/cuttlefish/shared/sepolicy/vendor/hal_virtio_rtc_default.te allow hal_virtio_rtc_default servicemanager:binder call;allow hal_virtio_rtc_default servicemanager:binder { call transfer }; -
Rebuild again, and check service in the logcat or dmesg, expect it fails with another
avc: denied
error:I auditd : avc: denied { add } for pid=3947 uid=1000 name=vendor.trongvq.virtio_rtc.IVirtio_RTC/default scontext=u:r:hal_virtio_rtc_default:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager permissive=0 -
Run the tool and add suguested statement to vendor policy:
device/google/cuttlefish/shared/sepolicy/vendor/hal_virtio_rtc_default.te allow hal_virtio_rtc_default default_android_service:service_manager add; -
Building again and expect the following SELinux
neverallow
build error due toservice_manager add
permission:neverallow check failed at out/soong/.intermediates/system/sepolicy/plat_pub_versioned.cil/android_common/vsoc_x86_64_only/plat_pub_versioned.cil:6162(neverallow base_typeattr_224_202404 default_android_service_202404 (service_manager (add find list)))<root>allow at out/soong/.intermediates/system/sepolicy/vendor_sepolicy.cil/android_common/vsoc_x86_64_only/vendor_sepolicy.cil:1697(allow hal_virtio_rtc_default default_android_service_202404 (service_manager (add)))Open
system/sepolicy/public/domain.te
, it has a specific neverallow rule that does not allow service_manager to add a default_android_service:system/sepolicy/public/domain.te # Do not allow service_manager add for default service labels.# Instead domains should use a more specific type such as# system_app_service rather than the generic type.# New service_types are defined in {,hw,vnd}service.te and new mappings# from service name to service_type are defined in {,hw,vnd}service_contexts.neverallow * default_android_service:service_manager *;neverallow * default_android_vndservice:service_manager *;neverallow * default_android_hwservice:hwservice_manager *;To fix this, need to define a specific service type:
device/google/cuttlefish/shared/sepolicy/vendor/service.te # Virtio_RTC Servicetype hal_virtio_rtc_service, service_manager_type, hal_service_type;then assign it a new label:
device/google/cuttlefish/shared/sepolicy/vendor/service_contexts # Virtio_RTC Servicevendor.trongvq.virtio_rtc.IVirtio_RTC/default u:object_r:hal_virtio_rtc_service:s0then change
default_android_service
tohal_virtio_rtc_service
inservice_manager add
:device/google/cuttlefish/shared/sepolicy/vendor/hal_virtio_rtc_default.te allow hal_virtio_rtc_default default_android_service:service_manager add;allow hal_virtio_rtc_default hal_virtio_rtc_service:service_manager add;
-
-
Rebuild and verify service is working well
service list | grep virtio_rtc292 vendor.trongvq.virtio_rtc.IVirtio_RTC/default: [vendor.trongvq.virtio_rtc.IVirtio_RTC]
Interface Native Test App
Directorydevice/google/cuttlefish/shared/sepolicy/vendor
- service.te
- service_contexts
- file.te
- file_contexts
- hal_virtio_rtc_default.te
Directoryvendor/trongvq/
- device_framework_matrix.xml # compatibility
Directoryinterfaces/virio_rtc
- Android.bp
Directoryvendor/trongvq/virtio_rtc
- IVirtio_RTC.aidl
Directorytest
- Android.bp
- Virtio_RTC_Test.cpp
Directoryservices/virtio_rtc
- Android.bp
Directoryinc
- Virtio_RTC.h
Directorysrc
- Virtio_RTC.cpp
- Virtio_RTC_Service.cpp
- vendor.trongvq.virtio_rtc-service.rc # start service at startup
- vendor.trongvq.virtio_rtc-service.xml # declare and configure interface
-
Create
Android.bp
to declare a test binary:vendor/trongvq/interfaces/virtio_rtc/test/Android.bp cc_binary {name: "Virtio_RTC_Test",vendor: true,relative_install_path: "hw",srcs: ["Virtio_RTC_Test.cpp"],shared_libs: ["libbinder_ndk","vendor.trongvq.virtio_rtc-V1-ndk",],} -
Create
Virtio_RTC_Test.cpp
to implement the test binary:vendor/trongvq/interfaces/virtio_rtc/test/Virtio_RTC_Test.cpp #include <aidl/vendor/trongvq/virtio_rtc/IVirtio_RTC.h>#include <android/binder_manager.h>#include <chrono>#include <iostream>#include <thread>using aidl::vendor::trongvq::virtio_rtc::IVirtio_RTC;int main(int argc, char **argv) {std::string instance = std::string(IVirtio_RTC::descriptor) + "/default";std::shared_ptr<IVirtio_RTC> rtc = IVirtio_RTC::fromBinder(ndk::SpAIBinder(AServiceManager_getService(instance.c_str())));std::string time;rtc->getTime(&time);std::cout << "Current time: " << time; // returned string has newlinestd::this_thread::sleep_for(std::chrono::seconds(1));rtc->getTime(&time);std::cout << "Current time: " << time;bool success = false;rtc->setTime("1234", &success);rtc->getTime(&time);std::cout << "Current time: " << time;std::this_thread::sleep_for(std::chrono::seconds(1));rtc->getTime(&time);std::cout << "Current time: " << time;return 0;} -
Change owner of
/dev/virtio_rtc
:When build and run
vendor/bin/hw/Virtio_RTC_Test
, it prints out:E vendor.trongvq.virtio_rtc-service: Failed to open /dev/virtio_rtcDevice is created for
root
user:ls -al /dev/virtio_rtccrw------- 1 root root 488, 0 2024-10-27 13:12 /dev/virtio_rtcService is running under
system
user:ps -AZ | grep virtio_rtcu:r:hal_virtio_rtc_default:s0 system binder_ioctl_write_read 0 S vendor.trongvq.virtio_rtc-serviceNeed to add an action at start up:
vendor/trongvq/services/virtio_rtc/vendor.trongvq.virtio_rtc-service.rc on bootchown system root /dev/virtio_rtc -
Add SE Policy for
/dev/virtio_rtc
:When build and run again,
vendor/bin/hw/Virtio_RTC_Test
prints out audit error:W binder:506_1: type=1400 audit(0.0:113): avc: denied { read } for name="virtio_rtc" dev="tmpfs" ino=1297 scontext=u:r:hal_virtio_rtc_default:s0 tcontext=u:object_r:device:s0 tclass=chr_file permissive=0W binder:506_1: type=1400 audit(0.0:113): avc: denied { write } for name="virtio_rtc" dev="tmpfs" ino=1297 scontext=u:r:hal_virtio_rtc_default:s0 tcontext=u:object_r:device:s0 tclass=chr_file permissive=0Run
audit2allow
to get:#============= hal_virtio_rtc_default ==============allow hal_virtio_rtc_default device:chr_file { read write };However, it conflics with a neverallow rule for general device:
system/sepolicy/public/domain.te # Don't allow raw read/write/open access to generic devices.# Rather force a relabel to a more specific type.neverallow domain device:chr_file { open read write };Therefore, define a new label
virtio_rtc_device
:device/google/cuttlefish/shared/sepolicy/vendor/file.te # Virtio_RTC Devicetype virtio_rtc_device, dev_type;Then assign new label to the dev
/dev/virtio_rtc
:device/google/cuttlefish/shared/sepolicy/vendor/file_contexts # Virtio_RTC Device/dev/virtio_rtc u:object_r:virtio_rtc_device:s0Finally, allow service to access the device with defined label:
device/google/cuttlefish/shared/sepolicy/vendor/hal_virtio_rtc_default.te allow hal_virtio_rtc_default virtio_rtc_device:chr_file { open read write }; -
Rebuild and run, verify that the test binary can get and set Virtio_RTC seconds:
vendor/bin/hw/Virtio_RTC_Testoutput Current time: 86Current time: 87Current time: 1234Current time: 1235logcat I vendor.trongvq.virtio_rtc-service: Current time: 86I vendor.trongvq.virtio_rtc-service: Current time: 87I vendor.trongvq.virtio_rtc-service: Setting time to 1234I vendor.trongvq.virtio_rtc-service: Current time: 1234I vendor.trongvq.virtio_rtc-service: Current time: 1235
Vendor Test Suite
Refer: https://source.android.com/docs/core/tests/vts.
The Android Vendor Test Suite (VTS) provides extensive testing on the following:
- Kernel
- Hardware abstraction layer (HAL)
VTS runs on a desktop machine and executes test cases directly on attached devices or on the emulators. The test cases can be GTest-style tests, kernel tests, or JUnit-style tests written in Java.
Directorydevice/google/cuttlefish/shared/sepolicy/vendor
- service.te
- service_contexts
- file.te
- file_contexts
- hal_virtio_rtc_default.te
Directoryvendor/trongvq/
- device_framework_matrix.xml # compatibility
Directoryinterfaces/virio_rtc
- Android.bp
Directoryvendor/trongvq/virtio_rtc
- IVirtio_RTC.aidl
Directorytest
- Android.bp
- Virtio_RTC_Test.cpp
Directoryservices/virtio_rtc
- Android.bp
Directoryinc
- Virtio_RTC.h
Directorysrc
- Virtio_RTC.cpp
- Virtio_RTC_Service.cpp
- vendor.trongvq.virtio_rtc-service.rc # start service at startup
- vendor.trongvq.virtio_rtc-service.xml # declare and configure interface
Directoryvts
- Android.bp
- Vts_Virtio_RTC_Test.cpp
-
Create
Android.bp
to declare VTS Test Suite:vendor/trongvq/vts/Android.bp cc_test {name: "VtsVirtioRTCTest",defaults: ["VtsHalTargetTestDefaults","use_libaidlvintf_gtest_helper_static",],srcs: ["Vts_Virtio_RTC_Test.cpp",],cflags: ["-Wall","-Werror",],shared_libs: ["liblog","libutils","libbinder_ndk","vendor.trongvq.virtio_rtc-V1-ndk",],static_libs : [],test_suites: ["general-tests", // atest"vts", // vts run],compile_multilib: "64"} -
Create
Vts_Virtio_RTC_Test.cpp
to impelement test cases:vendor/trongvq/vts/Vts_Virtio_RTC_Test.cpp #include <android/binder_manager.h>#include <android/binder_process.h>#include <gtest/gtest.h>#include <thread>#include <aidl/vendor/trongvq/virtio_rtc/IVirtio_RTC.h>using aidl::vendor::trongvq::virtio_rtc::IVirtio_RTC;class VirtioRTCServiceTest : public testing::Test {public:void SetUp() override {std::string instance = std::string(IVirtio_RTC::descriptor) + "/default";mService = IVirtio_RTC::fromBinder(ndk::SpAIBinder(AServiceManager_waitForService(instance.c_str())));ASSERT_NE(mService, nullptr);}std::shared_ptr<IVirtio_RTC> mService;};TEST_F(VirtioRTCServiceTest, GetTime) {std::string time1;ASSERT_TRUE(mService->getTime(&time1).isOk());ASSERT_FALSE(time1.empty());std::this_thread::sleep_for(std::chrono::milliseconds(1100));std::string time2;ASSERT_TRUE(mService->getTime(&time2).isOk());ASSERT_FALSE(time2.empty());ASSERT_NE(time1, time2);}TEST_F(VirtioRTCServiceTest, SetTime) {std::string time("1234\n");bool success = false;std::string time1;ASSERT_TRUE(mService->getTime(&time1).isOk());ASSERT_FALSE(time1.empty());ASSERT_NE(time1, time);ASSERT_TRUE(mService->setTime(time, &success).isOk());ASSERT_TRUE(success);std::string time2;ASSERT_TRUE(mService->getTime(&time2).isOk());ASSERT_FALSE(time2.empty());ASSERT_EQ(time2, time);}int main(int argc, char **argv) {ABinderProcess_setThreadPoolMaxThreadCount(1);ABinderProcess_startThreadPool();std::thread([] { ABinderProcess_joinThreadPool(); }).detach();testing::InitGoogleTest(&argc, argv);return RUN_ALL_TESTS();} -
Export AIDL for vendor access:
When buid, there is an error that AIDL NDK variant is missing:
error: vendor/trongvq/vts/Android.bp:1:1: dependency "vendor.trongvq.virtio_rtc-V1-ndk" of "VtsVirtioRTCTest" missing variant:os:android,image:,arch:x86_64_silvermont,sdk:,link:sharedExport the ADIL using keyword
vendor_available
:vendor/trongvq/interfaces/virtio_rtc/Android.bp vendor: true, // installed in /vendorvendor_available: true, // export for vendorsThen rebuild the system.
-
Run
atest
:atest VtsVirtioRTCTestx86_64 VtsVirtioRTCTest-----------------------VtsVirtioRTCTest (2 Tests)[1/2] VirtioRTCServiceTest#GetTime: PASSED (1.101s)[2/2] VirtioRTCServiceTest#SetTime: PASSED (0ms)Summary (Test executed with 1 devices.)-------x86_64 VtsVirtioRTCTest: Passed: 2, Failed: 0, Ignored: 0, Assumption Failed: 0All tests passed! -
Run
VTS
:Firstly, build VTS Trade Federation test framework:
m vts -j10Then enter the VTS Trade Federation Console:
vts-tradefedThen execute a VTS Test Suite:
run vts -m VtsVirtioRTCTest================= Results ================================= Consumed Time ==============x86_64 VtsVirtioRTCTest: 7sTotal aggregated tests run time: 7s============== TOP 1 Slow Modules ==============x86_64 VtsVirtioRTCTest: 0.27 tests/sec [2 tests / 7282 msec]============== Modules Preparation Times ==============x86_64 VtsVirtioRTCTest => prep = 2887 ms || clean = 5982 msTotal preparation time: 2s || Total tear down time: 5s====================================================================== Summary ===============Total Run time: 1m 2s1/1 modules completedTotal Tests : 2PASSED : 2FAILED : 0============== End of Results ==============Note: VTS Trade Federation test framework will not execute the tests immmediately, it will take upto a minute to probe, set up the Device. Test is scheduled, and re-run after a device is found.
-
Customize the test configuration:
Run make command to build the config, then search for a generated config file.
m VtsVirtioRTCTestfind out/ -name VtsVirtioRTCTest.configout/target/product/vsoc_x86_64_only/testcases/VtsVirtioRTCTest/VtsVirtioRTCTest.config <configuration description="Runs VtsVirtioRTCTest."><option name="test-suite-tag" value="apct" /><option name="test-suite-tag" value="apct-native" /><!-- Use Root --><target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"></target_preparer><!-- Target location --><target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"><option name="cleanup" value="true" /><option name="push" value="VtsVirtioRTCTest->/data/local/tmp/VtsVirtioRTCTest" /></target_preparer><!-- Test Type --><test class="com.android.tradefed.testtype.GTest" ><option name="native-test-device-path" value="/data/local/tmp" /><option name="module-name" value="VtsVirtioRTCTest" /></test></configuration>Custom config file can be set in
Android.bp
:Android.bp test_config: "Vts_Virtio_RTC_Test.xml",