This project focuses on programming a HIDL example on Android after Treble. It is wrote to run on Sony Xperia Z1. Main purpose is to control the notification led
These steps are for creating new HAL layer sketch formated under HIDL(HAL interface definition language)
- Create all necessary folders
# cd android_source_tree
# mkdir -p hardware/interfaces/hvulight/2.0/default
- Create 2 files in
hardware/interfaces/hvulight/2.0: IHvulight.hal and types.hal define interfaces and types of data respectively - IHvulight.hal content
package android.hardware.hvulight@2.0;
interface IHvulight {
setLed(Led led, uint32_t intensity) generates (Status status);
getLed(Led led) generates (int32_t intensity);
};
- types.hal content
package android.hardware.hvulight@2.0;
enum Led : int32_t {
RED,
GREEN,
BLUE,
UNKNOWN,
};
enum Status : int32_t {
SUCCESS,
LED_NOT_SUPPORTED,
BRIGHTNESS_NOT_SUPPORTED,
UNKNOWN,
};
- Next, Use hidl-tools to generate HAL files(source code and Android.bp files in
hardware/interfaces/hvulight/2.0/defaultfor HAL implementation)
# PACKAGE=android.hardware.hvulight@2.0
# LOC=hardware/interfaces/hvulight/2.0/default/
# make hidl-gen -j16
# hidl-gen -o $LOC -Lc++-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport $PACKAGE
# hidl-gen -o $LOC -Landroidbp-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport $PACKAGE
- Update Android.bp makefile for compiling HIDL(.hal file in
hardware/interfaces/hvulight/2.0)
# ./hardware/interfaces/update-makefiles.sh
- Add 2 new empty files into
hardware/interfaces/hvulight/2.0/default. Its content and purpose I'm going to explain later
# touch hardware/interfaces/hvulight/2.0/default/service.cpp
# touch hardware/interfaces/hvulight/2.0/default/android.hardware.hvulight@2.0-service.rc
- Having performed all above steps, We have a folder for HAL layer with structure like below
hardware/interfaces/hvulight/2.0
├── Android.bp
├── default
│ ├── Android.bp
│ ├── android.hardware.hvulight@2.0-service.rc
│ ├── Hvulight.cpp
│ ├── Hvulight.h
│ └── service.cpp
├── IHvulight.hal
└── types.hal
default/Hvulight.his header file of HAL implementationdefault/Hvulight.cppcontains source code of HAL implementaion. After building this file, a shared library namedandroid.hardware.hvulight@2.0-implwhich is invoked by HIDL server in executing time, will be createddefault/service.cppcontains source code of HIDL server. Then it is built intoandroid.hardware.hvulight@2.0-serviceservice binary.
#define LOG_TAG "android.hardware.hvulight@2.0-service"
#include <hidl/HidlSupport.h>
#include <hidl/HidlTransportSupport.h>
#include <android-base/logging.h>
#include <android/hardware/hvulight/2.0/IHvulight.h>
#include "Hvulight.h"
using android::hardware::hvulight::V2_0::IHvulight;
using android::hardware::hvulight::V2_0::implementation::Hvulight;
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::sp;
using android::NO_ERROR;
int main() {
LOG(INFO) << __func__ << " : Start HAL";
android::sp<IHvulight> hvulight = Hvulight::getInstance();
configureRpcThreadpool(1, true /*callerWillJoin*/);
if (hvulight != nullptr) {
auto rc = hvulight->registerAsService();
if (rc != NO_ERROR) {
LOG(ERROR) << "Cannot start Hvulight service: " << rc;
return rc;
}
} else {
LOG(ERROR) << "Can't create instance of Hvulight, nullptr";
}
joinRpcThreadpool();
return 0; // should never get here
}
default/android.hardware.hvulight@2.0-service.rcrc file contains action associated its service(which isandroid.hardware.hvulight@2.0-servicein this case) and it will be parsed by init process. Having parsed and run this rc file,android.hardware.hvulight@2.0-serviceserver will run and be available for invoking by clients since that time.
service vendor.hvulight-hal-2-0 /vendor/bin/hw/android.hardware.hvulight@2.0-service
interface android.hardware.hvulight@2.0::IHvulight default
class hal
user root
group root
shutdown critical
Android.mk(replacesAndroid.bp) is makefile for compilingandroid.hardware.hvulight@2.0-serviceserver binary andandroid.hardware.hvulight@2.0-impl.soshared library.
#===============================================
# Makefile for compliling service binary
#===============================================
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_PROPRIETARY_MODULE := true
LOCAL_MODULE := android.hardware.hvulight@2.0-service
LOCAL_INIT_RC := android.hardware.hvulight@2.0-service.rc
LOCAL_SRC_FILES := \
service.cpp \
LOCAL_SHARED_LIBRARIES := \
libcutils \
libdl \
libbase \
libutils \
libhardware \
libhidlbase \
libhidltransport \
android.hardware.hvulight@2.0 \
android.hardware.hvulight@2.0-impl \
include $(BUILD_EXECUTABLE)
#=================================================
# Makefile for compiling implement shared library
#=================================================
include $(CLEAR_VARS)
LOCAL_MODULE := android.hardware.hvulight@2.0-impl
LOCAL_SRC_FILES := Hvulight.cpp
LOCAL_SHARED_LIBRARIES := \
libbase \
liblog \
libhidlbase \
libhidltransport \
libhardware \
libutils \
android.hardware.hvulight@2.0 \
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
- Attach SElinux context to
android.hardware.hvulight@2.0-serviceHIDL server binary. Add this line tofile_contextsfile in specific device's sepolicy folder(device/sony/sepolicy/vender/file_contextsin my case)
/(system/vendor|vendor)/bin/hw/android\.hardware\.hvulight@2\.0-service u:object_r:hal_hvulight_default_exec:s0
- Create
hal_hvulight_default.teinsystem/sepolicy/vendorand Define rules so that init process can manipulate theandroid.hardware.hvulight@2.0-serviceHIDL server binary.
type hal_hvulight_default, domain;
hal_server_domain(hal_hvulight_default, hal_hvulight)
type hal_hvulight_default_exec, exec_type, vendor_file_type, file_type;
init_daemon_domain(hal_hvulight_default)
I will clarify above rules now. Having parsed sepolicy macros, this is content of above hal_hvulight_default.te file:
# define hal_hvulight_default domain for HIDL server
type hal_hvulight_default, domain;
typeattribute hal_hvulight_default halserverdomain;
typeattribute hal_hvulight_default hal_light_server;
typeattribute hal_hvulight_default hal_light;
type hal_hvulight_default_exec, exec_type, vendor_file_type, file_type;
# Old domain may exec the file and transition to the new domain.
allow init hal_hvulight_default_exec:file { getattr open read execute map };
allow init hal_hvulight_default:process transition;
# New domain is entered by executing the file.
allow hal_hvulight_default hal_hvulight_default_exec:file { entrypoint open read execute getattr map };
# New domain can send SIGCHLD to its caller.
ifelse(init, `init', `', `allow hal_hvulight_default init:process sigchld;')
# Enable AT_SECURE, i.e. libc secure mode.
dontaudit init hal_hvulight_default:process noatsecure;
# XXX dontaudit candidate but requires further study.
allow init hal_hvulight_default:process { siginh rlimitinh };
# Convert from init domain into hal_hvulight_default for HIDL server process
# when init process runs hal_hvulight_default_exec file and forks new process
# This new process will be attach hal_hvulight_default type
type_transition init hal_hvulight_default_exec:process hal_hvulight_default;
- Define rules so that HAL's process can manipulate device file of led in sysfs
# Allow hal_hvulight_default process read and write sysfs_msm_subsys files
r_dir_rw_file(hal_hvulight_default, sysfs_msm_subsys)
# Allow hal_hvulight_default to read and write led device file in sysfs
allow hal_hvulight_default sysfs_leds:file rw_file_perms;