HIDL SIMPLE
原文:https://devarea.com/android-hidl-and-project-treble/#.XLgyn7Ejw4A
One of the problems in Android is the fact that when a new version is released only a few devices can be updated. Actually, if you want to enjoy the latest version, you need to buy a new smartphone every 6 months. Google solution is the Project trebel that separates the vendor implementation from the Android OS framework via a new vendor interface
HIDL
HAL interface definition language used to describe the interface between the framework and the vendor. All hardware interfaces are located in hardware/interfaces in .hal files
Let’s go over simple example
Create all the path
1 2 |
# cd ~/aosp # mkdir -p hardware/interfaces/simple/2.0/default |
Create a hal file in ISimphw.hal in hardware/interfaces/simple/2.0
1 2 3 4 5 |
package [email protected];
interface ISimphw { simpfn(int32_t valueIn) generates (int32_t valueRet); }; |
Generate the HAL files
To generate the HAL files you need to use the hidl-gen tool run:
1 2 3 4 5 |
# LOC=hardware/interfaces/simple/2.0/default/ # make hidl-gen -j64 # 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 |
And to update all makefile (Android.mk, Android.bp) run:
1 |
# ./hardware/interfaces/update-makefiles.sh |
Now add 2 empty files to hardware/interfaces/simple/2.0/default:
- [email protected]
- service.cpp
Now the directory hardware/interfaces/simple should look like this:
Implementing the HAL shared object:
we need to add a new static function to return the service object (usually as a singleton)
Simphw.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
#ifndef ANDROID_HARDWARE_SIMPLE_V2_0_SIMPHW_H #define ANDROID_HARDWARE_SIMPLE_V2_0_SIMPHW_H
#include <android/hardware/simple/2.0/ISimphw.h> #include <hidl/MQDescriptor.h> #include <hidl/Status.h>
namespace android { namespace hardware { namespace simple { namespace V2_0 { namespace implementation {
using ::android::hardware::hidl_array; using ::android::hardware::hidl_memory; using ::android::hardware::hidl_string; using ::android::hardware::hidl_vec; using ::android::hardware::Return; using ::android::hardware::Void; using ::android::sp;
struct Simphw : public ISimphw { // Methods from ISimphw follow. Return<int32_t> simpfn(int32_t valueIn) override;
// Methods from ::android::hidl::base::V1_0::IBase follow. static ISimphw* getInstance(void); };
// FIXME: most likely delete, this is only for passthrough implementations //extern "C" ISimphw* HIDL_FETCH_ISimphw(const char* name);
} // namespace implementation } // namespace V2_0 } // namespace simple } // namespace hardware } // namespace android
#endif // ANDROID_HARDWARE_SIMPLE_V2_0_SIMPHW_H |
Simphw.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
#include "Simphw.h"
namespace android { namespace hardware { namespace simple { namespace V2_0 { namespace implementation {
// Methods from ISimphw follow. Return<int32_t> Simphw::simpfn(int32_t valueIn) { // TODO implement return valueIn+100; }
ISimphw *Simphw::getInstance(void){ return new Simphw(); }
// Methods from ::android::hidl::base::V1_0::IBase follow.
//ISimphw* HIDL_FETCH_ISimphw(const char* /* name */) { // return new Simphw(); //}
} // namespace implementation } // namespace V2_0 } // namespace simple } // namespace hardware } // namespace android |
Note that if you want to support pass-through mode, you need to uncomment the HIDL_FETCH_ISimphw function
In this example, we implemented the function as simple as possible (usually we will load the hardware module here)
The generated Android.bp file build a shared library with the implementation – [email protected]
Creating the Service
To host the library we need to create a simple executable:
service.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
#define LOG_TAG "[email protected]"
#include <android/hardware/simple/2.0/ISimphw.h>
#include <hidl/LegacySupport.h>
#include "Simphw.h"
using android::hardware::simple::V2_0::ISimphw; using android::hardware::simple::V2_0::implementation::Simphw; using android::hardware::configureRpcThreadpool; using android::hardware::joinRpcThreadpool; using android::sp;
int main() { int res; android::sp<ISimphw> ser = Simphw::getInstance(); ALOGE("simp main"); configureRpcThreadpool(1, true /*callerWillJoin*/);
if (ser != nullptr) { res = ser->registerAsService(); if(res != 0) ALOGE("Can't register instance of SimpleHardware, nullptr"); } else { ALOGE("Can't create instance of SimpleHardware, nullptr"); }
joinRpcThreadpool();
return 0; // should never get here } |
We create an instance of our implementation, Create a thread pool for the binder and register the current process as a service
Note that the function regsiterAsService() is auto-generated by hidl-gen tool
To make this service run automatically add init file:
1 2 3 4 5 |
service simphwserv /vendor/bin/hw/[email protected] class hal user root group root seclabel u:r:su:s0 |
For testing purpose I set the security label to su , we need to set SE Linux rules (I wrote it in the init.te file):
1 2 |
allow init vendor_file:file { execute }; allow init su:process { transition }; |
To tell the build system to build the service add the following to Android.bp (in directory default)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
cc_binary { name: "[email protected]", defaults: ["hidl_defaults"], proprietary: true, relative_install_path: "hw", srcs: ["service.cpp"], init_rc: ["[email protected]"],
shared_libs: [ "libhidlbase", "libhidltransport", "liblog", "libutils", ], } |
Add the following components to build/make/target/product/emulator.mk
1 2 |
Now build the ROM and run it, connect with adb and run ps -A to see all the hardware services:
The lshal tool list all the hardware services by categories:
1 |
# lshal |
Writing the Client
To use the service we will write a simple client application. Usually, it will be part of the Android framework written by Google. For example, if the generic framework wants to access the vibrator service:
In file frameworks/base/services/core/jni/com_android_server_VibratorService.cpp
1 2 3 4 5 6 7 8 9 |
static sp<IVibrator> mHal;
...
mHal = IVibrator::getService(); ... Status retStatus = mHal->on(timeout_ms); ... Status retStatus = mHal->off(); |
Add a new directory in device/generic/goldfish – simphaltest
Add the source and Android.bp files:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#define LOG_TAG "[email protected]"
#include <android/hardware/simple/2.0/ISimphw.h> #include <hidl/Status.h> #include <hidl/LegacySupport.h> #include <utils/misc.h> #include <utils/Log.h> #include <hardware/hardware.h> #include <hidl/HidlSupport.h>
#include<stdio.h>
using android::hardware::simple::V2_0::ISimphw; using android::sp;
int main() { int res; android::sp<ISimphw> ser = ISimphw::getService();
res = ser->simpfn(200);
printf("val=%d\n",res);
return 0; } |
Android.bp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
cc_binary { name: "mysimptest", defaults: ["hidl_defaults"], proprietary: true, srcs: ["servtest.cpp"],
shared_libs: [ "libhidlbase", "libhidltransport", "liblog", "libutils", ], } |
Add the client test to build/make/target/product/emulator.mk
1 |
mysimptest \ |
Add hal entry to the Manifest.xml file of your device (device/generic/goldfish/Manifest.xml in this case)
1 2 3 4 5 6 7 8 9 |
<hal format="hidl"> <name>android.hardware.simple</name> <transport>hwbinder</transport> <version>2.0</version> <interface> <name>ISimphw</name> <instance>default</instance> </interface> </hal> |
Build the ROM again and test our service:
Tagged Android, Android Internals, AOSP
Post navigation
← AOSP – CREATING A SYSTEM APPLICATION
UNDERSTANDING SED – PRACTICAL GUIDE →
33 THOUGHTS ON “ANDROID HIDL AND PROJECT TREBLE”
-
CHRIS_CW
This is the best DEMONSTRATION of How to get a HAL going I have found, Unfortunately When following it through on OREO my service fails to load the impl library from the ‘HW’ dir, if I push the library up a level to the lib64, it is found. I see nearly all the other standard(or BSP) HALS are lOAded from ‘HW’ but I cant see what they have different. Whats the trick ?
MARCH 21, 2018
I get:
“library “[email protected]” not found”
Although it is clearly there and it does load if I move it up to lib64- REPLY
-
KEN
Hello,
MAY 25, 2018
HAVE you FIGURED OUT WHY THIS IS HAPPENING? I AM CURRENTLY HAVING THIS ISSUE. PLEASE LET ME KNOW IF YOU FIND ANY SOLUTION.
THANKS- REPLY
-
JIHYUN
hi
i also have this problem.
JUNE 25, 2018
a simple way to avoid it, just copy so file to /system/lib. then it’s gone.
but it seems not a good way. if anyone knows it.
please share.- REPLY
-
JIHYUN
Hi I resolved it by avoding linking *-impl.so file.
I removed getInstance method and added below methodISimphw* HIDL_FETCH_ISimphw(const char* /* name */) {
return new Simphw();
}
and modified service.cpp as below.int main() {
JUNE 25, 2018
return defaultPassthroughServiceImplementation();
}
maybe linking *-impl.so in /vendor/lib/hw is not allowed.
instead, I’m guessing that it’s automatically loaded by using HIDL_FETCH_ISIMPHW.- REPLY
-
RAJU KHANAL
@JIHYUN: I followed your steps but still get the following error.
hwservicemanager: getTransport: Cannot find entry [email protected]::ISimphw/default in either framework or device manifest.
10-18 01:06:20.990 1577 1577 E ServiceManagement: Passthrough lookup opened [email protected] but could not find symbol HIDL_FETCH_ISimphw: undefined symbol: HIDL_FETCH_ISimphw
10-18 01:06:20.990 1577 1577 E [email protected]: Could not get passthrough implementation for [email protected]::ISimphw/default.I do the the hidl fetch method but don’t know why it is coming this way. Any suggestions? I have been stuck in this.
OCTOBER 17, 2018-
-
RAJU KHANAL
Please note the error is not with the naming convention.
So the proper error would be:
@JIHYUN: I followed your steps but still get the following error.
hwservicemanager: getTransport: Cannot find entry [email protected]::ISimphw/default in either framework or device manifest.
10-18 01:06:20.990 1577 1577 E ServiceManagement: Passthrough lookup opened [email protected] but could not find symbol HIDL_FETCH_ISimphw: undefined symbol: HIDL_FETCH_ISimphw
10-18 01:06:20.990 1577 1577 E [email protected]: Could not get passthrough implementation for [email protected]::ISimphw/default.Kindly ignore the part where the name is [email protected] I have the correct impl file name.
OCTOBER 17, 2018-
-
-
-
-
-
PHONG
What IDE to run the code?
MARCH 26, 2018- REPLY
-
RAKESH VERMA
thanks a lot, works great. Required to update dev/*/* in Android.bp in root directory to dev/*/*/* to access the Android.bp created in device/generic/goldfish/simphaltest.
MARCH 27, 2018- REPLY
-
AJINATH
hI,
I tried steps given for “[email protected]″ HIDL interface and thats worked. I like the simple steps/command to generate HIDL impl and HIDL service, it really gives the confidence for who are new into Android HAL framework.
Thanks a lot.
One more change is required to build HIDL impl lib, just add “2.0/default” into Android.bp to include default dir Android.bp
hardware/interfaces/simple/Android.bp
subdirs = [
“2.0”,
“2.0/default”,
]@CHRIS_CW,
As per hardware/interfaces/simple/2.0/default/Android.bp rule,
name: “[email protected]”,
relative_install_path: “hw”,
proprietary: true,the impl lib should build at below location in vendor.img
vendor/lib/hw
vendor/lib64/hwcan check your HIDL package name ? from error it seems to be UPPER case string issue “library “[email protected]” not found”
”and also check product packages should include in devicexx.mk
PRODUCT_PACKAGES += \
APRIL 9, 2018
[email protected] \
[email protected] \- REPLY
-
1STPIE
it so good refference. thanks
APRIL 19, 2018- REPLY
-
AARTI
Hi
I followed the steps given above but i am getting following error while trying to generate the HIDL files:ERROR: Unable to automatically import ‘[email protected]::IBase’ at /home/AOSP/hardware/interfaces/simple/2.0/ISimple.hal
APRIL 20, 2018
ERROR: Could not parse [email protected]::ISimple Aborting- REPLY
-
1STPIE
hello.
i have a question.
i dont make android.mk files about simple directory.
i try to execute hardware/interfaces/update-makefiels.sh
and i got a message about this.
Updating [email protected]but in the directory of simple/2.0/
APRIL 24, 2018
dont find a android.mk file.- REPLY
-
ANONYMOUS
In service.cpp, should “return 1” “if(res != 0)”, else would “joinRpcThreadpool();” without a registered instance of SimpleHardware.
P/S: Sorry about all caps. something wrong somewhere i can’t type in lowercase.
MAY 11, 2018- REPLY
-
ANONYMOUS
Also need “return 1” “if(ser == nullptr)”.
MAY 11, 2018- REPLY
-
ANONYMOUS
@Rakesh Verma
MAY 13, 2018
How did you get “hidl-gen” and “update-makefiles.sh” to detect your *.hal files if you put your source code under device/generic/goldfish/simphaltest? or did you generate everything under hardware/interfaces and moved them to device/generic/goldfish/simphaltest later?- REPLY
-
LIRAN B.H
update-makefiles.sh only generates the makefiles under hardware/interfaces
MAY 13, 2018
follow the instructions and create the testapp makefile manually- REPLY
-
ANONYMOUS
Thanks! IS THERE A WAY TO IMPLEMENT A BOARD/TARGET SPECIFIC VERSION OF THIS AND ‘OVERWRITE’ (OR NOT USE) THE DEFAULT IMPLEMENTATION? E.g. using device/generic/marlin/SIMPLE rather than hardware/interfaces/SIMPLE? As you’d mentioned, update-makefiles.sh doesn’t seem to detect *.hal files under devices/*, so this has to be done manually, but how should the terms [email protected] and [email protected] AND [email protected] be renamed for the BOARD/TARGET? Thanks in advance.
MAY 17, 2018- REPLY
-
ANONYMOUS
Sorry again for caps!
MAY 17, 2018- REPLY
-
-
-
RATNESH PAL
Hope you resolved your error, I follow the same instruction everything is working fine but try to run test code getting error. I could not understand the mean so please help me,
APRIL 13, 2019
My test code path is here aosp8/device/generic/goldfish/mysimptest.
127|generic_x86:/ $ mysimptest/
mysimptest/
/system/bin/sh: mysimptest/: not found
127|generic_x86:/ $- REPLY
-
-
RAJIV RANJAN
superb link till now.
MAY 16, 2018- REPLY
-
SAI PHANI TEJA SREERAM
The best tutorial of hidl so far got in the internet. Thanks
JULY 17, 2018- REPLY
-
DEEPTIMAN PATTNAIK
it’s a great tutorial to get started with HIDL implementation.
I am just facing an issue, while build the hidl modules.
ERROR: Could not open package path hardware/interfaces/simple/2.0/ for package [email protected]:
AUGUST 1, 2018- REPLY
-
BRIAN
Hi All,
I am trying to implement an I2C DAC in android to allow the driving of specific voltages from an app. This isn’t a DAC for audio etc, it is an embedded application. I will also be implementing ADC, GPIO etc.
I have found a kernel driver for the specific DAC I am using, and can control the DAC via the sysfs interface, e.g. “echo 3000 > /sys/bus/iio/devices/iio:device0/out_voltage0_raw”
Now I am trying to understand how HIDL, HAL etc fit in to this.
– I have found an example (https://elinux.org/images/f/fb/Android_Customization-_From_the_Kernel_to_the_Apps.pdf) which seems to create a custom service to control a hardware device, however this edits some of the internal files in android to start the service etc, and therefore I think this is NOT the “Andriod Oreo” way of doing it, since these modifications will be wiped during an upgrade.
– Other examples I have found seem to be for sensor implementation. Since the DAC is an output, I don’t think the sensor API is compatible with what I am trying to achieve.
As I understand it, Android Oreo 8.0 introduced the treble concept to allow the operating system to be updated while keeping the vendor specific changes intact. Am I correct in saying that this example is compatible with communicating with a custom device? e.g. instead of doing “return valueIn+100;”, I could “open(DEV, O_WRONLY);” etc and interface with my device?
AUGUST 6, 2018- REPLY
-
BRIAN
Does anyone know how I would call the function from within an Android App using Android Studio? I have generated an SDK after implementing this but I don’t know what Java API is exposed, if any?
AUGUST 7, 2018- REPLY
-
ANIL KUMAR
I am not able to send data to another shared library from my HIDL server, I am sending some data form client to server, from server i am trying to send to another library which is normal C implementation, i am able to call but data is not reaching. Can you please help.
AUGUST 16, 2018- REPLY
-
YUZHOU
Hi,
Thanks for the detailed documentation. A question regarding the init_rc file and SELinux init.te rule. As you mentioned:FOR TESTING PURPOSE I SET THE SECURITY LABEL TO SU , WE NEED TO SET SE LINUX RULES (I WROTE IT IN THE INIT.TE FILE):
ALLOW INIT VENDOR_FILE:FILE { EXECUTE };
ALLOW INIT SU:PROCESS { TRANSITION };Could you please clarify what should be the setting for normal use case? I have tried to copy the init_rc file from audio, omx HAL and the service won’t load up unless I use your sepolicy here. Is there a formal way to tell the system to load up the hal service while booting?
AUGUST 28, 2018- REPLY
-
WANG ZHIKAI
hi
SEPTEMBER 12, 2018
as you said “we need to set SE Linux rules (I wrote it in the init.te file):”
i don’t know which init.te file should config, could you tell me the location of init.te file?
thank you very much!- REPLY
-
RAJU KHANAL
When I do an lshal I can see that it is getting generated as passthrough and not binderized
All available passthrough implementations (all -impl.so files).
These may return subclasses through their respective HIDL_FETCH_I* functions.
R Interface
[email protected]::I*/* (/vendor/lib/hw/)Should I not get this in the category binderized as default and looking something like what you have shown in the figure:
[email protected]::ISimphw/defaultWhat I am missing here if anyone can help?
OCTOBER 16, 2018
Sorry for the capslock. i could not change the case- REPLY
-
RAJU KHANAL
Also i cannot see the same in ls -a. However I can see the so file in system/lib and in lshal as above.
OCTOBER 16, 2018- REPLY
-
-
ARINDAM
IMPORTANT :
I NEED to use an HIDL service( in CPP) while my client is in java (telephony fw).
I need to register call backs in the service from my java module, so that i can receive notifications in telephony when there is an update in the c++ service.
thanks
DECEMBER 27, 2018- REPLY
-
ANONYMOUS
Nice post
MARCH 27, 2019- REPLY
-
RATNESH
Hi,
APRIL 4, 2019
Thank you very much for nice tutorial, I am stuck in init.te file.
Can you please tell me location of init.te file so i will set the given rules.
allow init vendor_file:file { execute };
allow init su:process { transition };
Waiting for your response!- REPLY
-
RATNESH
After Adding
allow init vendor_file:file { execute };
allow init su:process { transition };
at bottom of /system/sepolicy/public/init.te
…………………………………………….
PRODUCT_PACKAGES += \
[email protected] \
[email protected] \
and also added emualtor.mkafter build rom getting this error
[email protected]:~/android8$ make -j4
APRIL 4, 2019
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=8.1.0
TARGET_PRODUCT=aosp_x86_64
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_ARCH=x86_64
TARGET_ARCH_VARIANT=x86_64
TARGET_2ND_ARCH=x86
TARGET_2ND_ARCH_VARIANT=x86_64
HOST_ARCH=x86_64
HOST_2ND_ARCH=x86
HOST_OS=linux
HOST_OS_EXTRA=Linux-4.18.0-16-generic-x86_64-with-Ubuntu-18.04-bionic
HOST_CROSS_OS=windows
HOST_CROSS_ARCH=x86
HOST_CROSS_2ND_ARCH=x86_64
HOST_BUILD_TYPE=release
BUILD_ID=OPM7.181205.001
OUT_DIR=out
============================================
[2/2] bootstrap out/soong/.minibootstrap/build.ninja.in
[1/1] out/soong/.bootstrap/bin/minibp out/soong/.bootstrap/build.ninja
[78/79] glob hardware/interfaces/wifi/1.1/Android.bp
[4/4] out/soong/.bootstrap/bin/soong_build out/soong/build.ninja
FAILED: out/soong/build.ninja
out/soong/.bootstrap/bin/soong_build -t -b out/soong -d out/soong/build.ninja.d -o out/soong/build.ninja Android.bp
error: hardware/interfaces/simple/2.0/default/Android.bp:1:1: “[email protected]” depends on undefined module “[email protected]”
ninja: build stopped: subcommand failed.
23:45:48 soong failed with: exit status 1- REPLY