原文: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
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); }; |
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:
Now the directory hardware/interfaces/simple should look like this:
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 #include #include
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
// 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 // 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]
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
#include
#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 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 |
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
...
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 #include #include #include #include #include #include
#include
using android::hardware::simple::V2_0::ISimphw; using android::sp;
int main() { int res; android::sp
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 |
|
Build the ROM again and test our service:
Google BookmarkFacebookMore
Tagged Android, Android Internals, AOSP