Android HIDL and Project Treble

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

 

Create a hal file in ISimphw.hal in  hardware/interfaces/simple/2.0

Generate the HAL files

To generate the HAL files you need to use the hidl-gen tool run:

And to update all makefile (Android.mk, Android.bp) run:

Now add 2 empty files to hardware/interfaces/simple/2.0/default:

  • android.hardware.simple@2.0-service.rc
  • 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

Simphw.cpp

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 – android.hardware.simple@2.0-impl

Creating the Service

To host the library we need to create a simple executable:

service.cpp

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:

android.hardware.simple@2.0-service.rc

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):

To tell the build system to build the service add the following to Android.bp (in directory default)

Add the following components to build/make/target/product/emulator.mk

 

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:

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

Add a new directory in device/generic/goldfish – simphaltest

Add the source and Android.bp files:

Android.bp

Add the client test to build/make/target/product/emulator.mk

Add hal entry to the Manifest.xml file of your device (device/generic/goldfish/Manifest.xml in this case)

Build the ROM again and test our service:

 

Tagged , ,

24 thoughts on “Android HIDL and Project Treble

  1. 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 ?
    I get:
    “library “android.hardware.SIMPLE@2.0-impl.so” not found”
    Although it is clearly there and it does load if I move it up to lib64

    1. Hello,
      HAVE you FIGURED OUT WHY THIS IS HAPPENING? I AM CURRENTLY HAVING THIS ISSUE. PLEASE LET ME KNOW IF YOU FIND ANY SOLUTION.
      THANKS

      1. hi

        i also have this problem.
        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.

        1. Hi I resolved it by avoding linking *-impl.so file.
          I removed getInstance method and added below method

          ISimphw* HIDL_FETCH_ISimphw(const char* /* name */) {
          return new Simphw();
          }
          and modified service.cpp as below.

          int main() {
          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.

  2. What IDE to run the code?

  3. 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.

  4. hI,

    I tried steps given for “android.hardware.simple@2.0″ 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: “android.hardware.simple@2.0-impl”,
    relative_install_path: “hw”,
    proprietary: true,

    the impl lib should build at below location in vendor.img

    vendor/lib/hw
    vendor/lib64/hw

    can check your HIDL package name ? from error it seems to be UPPER case string issue “library “android.hardware.SIMPLE@2.0-impl.so” not found”

    and also check product packages should include in devicexx.mk

    PRODUCT_PACKAGES += \
    android.hardware.simple@2.0-impl \
    android.hardware.simple@2.0-service \

  5. it so good refference. thanks

  6. 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 ‘android.hidl.base@1.0::IBase’ at /home/AOSP/hardware/interfaces/simple/2.0/ISimple.hal
    ERROR: Could not parse android.hardware.simple@2.0::ISimple Aborting

  7. 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 android.hardware.simple@2.0

    but in the directory of simple/2.0/
    dont find a android.mk file.

  8. 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.

  9. Also need “return 1” “if(ser == nullptr)”.

  10. @Rakesh Verma
    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?

    1. update-makefiles.sh only generates the makefiles under hardware/interfaces
      follow the instructions and create the testapp makefile manually

      1. 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 android.hardware.SIMPLE@2.0-impl and android.hardware.SIMPLE@2.0-service AND android.hardware.SIMPLE@2.0-service.rc be renamed for the BOARD/TARGET? Thanks in advance.

        1. Sorry again for caps!

  11. superb link till now.

  12. The best tutorial of hidl so far got in the internet. Thanks

  13. 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 android.hardware.simple@2.0:

  14. 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?

  15. 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?

  16. 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.

  17. 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?

  18. hi
    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!

Leave a Reply

Your email address will not be published. Required fields are marked *