Implementing an AIDL HAL service

How To Add An AIDL HAL Service (daemon)

In this step, we will develop the AIDL-HAL service based on the AIDL interface we implemented before. It’s a backend AIDL service that we want to implement with C++.

Let’s break it down into some steps:

  1. Implement/Extend a class from the AIDL interface
  2. Get a binder from the implemented class and add it as a service
  3. Add the required configuration to the new variant

Implement the AIDL interface

First, we need to include a header file like below to import the definitions of the AIDL into our project:

#include <aidl/aospinsight/hardware/dummy_device/BnDummy.h>

Then we will develop a new class and will use BnDummy as the base class. In order to implement it, we should override the methods of the AIDL interface. Here you can find the header file of DummyImpl.

class DummyImpl : public BnDummy {
    virtual ndk::ScopedAStatus getPacketByCallback(const std::shared_ptr<IDummyCallback>& cb) override;
    virtual ndk::ScopedAStatus getPacket(DummyPacket* dummyPacket) override;

protected:
    std::shared_ptr<IDummyCallback> dummyCallback = nullptr;
    std::mutex dummyMutex;

    void onPacketEvent(DummyPacket* dummyPacket);
};

dummyCallback is defined to keep the callback pointer to make it possible to invoke the methods from the application.

How to use the callback and invoke a remote method

void DummyImpl::onPacketEvent(DummyPacket* dummyPacket) {
    LOG(INFO) << "onNewPacket called!";
    dummyCallback->onGetPacket(*dummyPacket);
}

onPacketEvent is a sample of how we can use the callback pointer in the daemon. onGetPacket is a remote method that can be invoked by the callback pointer. We will implement onGetPacket later in an Android app. On receiving a packet the daemon cal call onPacketEvent that will invoke a remote method to send a packet to the client.

Get a binder and add the service

To create a binder we should create a new object of DummyImpl class. This will take place in the main functions of the projects.

std::shared_ptr<DummyImpl> dummy = ndk::SharedRefBase::make<DummyImpl>(); 

Now we need to use the AIDL descriptor to take the next step.

const std::string instance = std::string() + DummyImpl::descriptor + "/default";

And now will take the last step:

binder_status_t status = AServiceManager_addService(dummy->asBinder().get(), instance.c_str());

The service is added successfully If _status_t equals STATUS_OK.

Manifest files

We’ve added the AIDL interface to be built. But we need to define the device manifest file and the framework compatibility manifest file as well.

The daemon will be started automatically

To start the daemon automatically we can add a .rc file in Android.bp that will be processed by the system. You can find dummy-default.rc in the init folder. That’s how it’s defined in the Android.bp file:

init_rc: ["init/dummy-default.rc"],

Build configuration

The dummy service and the manifest files should be added to the build system manually. You can find the configuration in aospinsight_car.mk.


DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE += \
$(VENDOR_PATH)/hardware/dummy_service/manifest/dummy_framework_compatibility_matrix.xml \


PRODUCT_PACKAGES += \
	dummy-service \

How to check the daemon

The first step is that run the emulator. In order to do that, you need to open a new terminal and run the commands below:

source build/envsetup.sh
lunch aospinsight_car-userdebug
emulator -wipe-data -no-audio 

To see if the HAL service is started automatically you can run the command below in your terminal after running the emulator.

adb logcat | grep -i -e dummy

Then you will see something like the screenshot below in your terminal.

21 thoughts on “How To Add An AIDL HAL Service (daemon)”

    1. Mohammad Hossein Heydarchi

      If you can explain more about the problem or what you’re looking for I might be able to help. The source code I’ve provided in Github includes everything you need to put it up and running. But of course, based on the implementation of the HAL service or the app you might need to add some SEPolicies.

      1. it ws giving an error like this
        [ 67% 661/985] Verify hardware/interfaces/dummy_device/aidl/aidl_api/android.hardware.dummy_device/1 files have not been modified
        FAILED: out/soong/.intermediates/hardware/interfaces/dummy_device/aidl/android.hardware.dummy_device-api/checkhash_1.timestamp
        if [ $(cd ‘hardware/interfaces/dummy_device/aidl/aidl_api/android.hardware.dummy_device/1’ && { find ./ -name “*.aidl” -print0 | LC_ALL=C sort -z | xargs -0 sha1sum && echo latest-version; } | sha1sum | cut -d ” ” -f 1) = $(read -r <'hardware/interfaces/dummy_device/aidl/aidl_api/android.hardware.dummy_device/1/.hash' hash extra; printf %s $hash) ]; then touch out/soong/.intermediates/hardware/interfaces/dummy_device/aidl/android.hardware.dummy_device-api/checkhash_1.timestamp; else cat 'system/tools/aidl/build/message_check_integrity.txt' && exit 1; fi
        ###############################################################################
        # ERROR: Modification detected of stable AIDL API file #
        ###############################################################################
        Above AIDL file(s) has changed, resulting in a different hash. Hash values may
        be checked at runtime to verify interface stability. If a device is shipped
        with this change by ignoring this message, it has a high risk of breaking later
        when a module using the interface is updated, e.g., Mainline modules.
        17:05:07 ninja failed with: exit status 1

  1. it ws giving an error like this
    [ 67% 661/985] Verify hardware/interfaces/dummy_device/aidl/aidl_api/android.hardware.dummy_device/1 files have not been modified
    FAILED: out/soong/.intermediates/hardware/interfaces/dummy_device/aidl/android.hardware.dummy_device-api/checkhash_1.timestamp
    if [ $(cd ‘hardware/interfaces/dummy_device/aidl/aidl_api/android.hardware.dummy_device/1’ && { find ./ -name “*.aidl” -print0 | LC_ALL=C sort -z | xargs -0 sha1sum && echo latest-version; } | sha1sum | cut -d ” ” -f 1) = $(read -r <'hardware/interfaces/dummy_device/aidl/aidl_api/android.hardware.dummy_device/1/.hash' hash extra; printf %s $hash) ]; then touch out/soong/.intermediates/hardware/interfaces/dummy_device/aidl/android.hardware.dummy_device-api/checkhash_1.timestamp; else cat 'system/tools/aidl/build/message_check_integrity.txt' && exit 1; fi
    ###############################################################################
    # ERROR: Modification detected of stable AIDL API file #
    ###############################################################################
    Above AIDL file(s) has changed, resulting in a different hash. Hash values may
    be checked at runtime to verify interface stability. If a device is shipped
    with this change by ignoring this message, it has a high risk of breaking later
    when a module using the interface is updated, e.g., Mainline modules.
    17:05:07 ninja failed with: exit status 1

        1. Mohammad Hossein Heydarchi

          You can find the sepolicy folders/files in device/devboard/sepolicy. Find the right file to add the new domain/rule/etc.

          1. Could you please help to resolve this error.

            FAILED: out/target/product/AGN_H164YO_MT8788R/obj/FAKE/sepolicy_neverallows_intermediates/sepolicy_neverallows
            /bin/bash -c “(ASAN_OPTIONS=detect_leaks=0 out/host/linux-x86/bin/checkpolicy -M -c 30 -o out/target/product/AGN_H164YO_MT8788R/obj/FAKE/sepolicy_neverallows_intermediates/sepolicy_neverallows.tmp out/target/product/AGN_H164YO_MT8788R/obj/FAKE/sepolicy_neverallows_intermediates/policy.conf ) && (out/host/linux-x86/bin/sepolicy-analyze out/target/product/AGN_H164YO_MT8788R/obj/FAKE/sepolicy_neverallows_intermediates/sepolicy_neverallows.tmp neverallow -w -f out/target/product/AGN_H164YO_MT8788R/obj/FAKE/sepolicy_neverallows_intermediates/policy_2.conf || ( echo \”\” 1>&2; echo \”sepolicy-analyze failed. This is most likely due to the use\” 1>&2; echo \”of an expanded attribute in a neverallow assertion. Please fix\” 1>&2; echo \”the policy.\” 1>&2; exit 1 ) ) && (touch out/target/product/AGN_H164YO_MT8788R/obj/FAKE/sepolicy_neverallows_intermediates/sepolicy_neverallows.tmp ) && (mv out/target/product/AGN_H164YO_MT8788R/obj/FAKE/sepolicy_neverallows_intermediates/sepolicy_neverallows.tmp out/target/product/AGN_H164YO_MT8788R/obj/FAKE/sepolicy_neverallows_intermediates/sepolicy_neverallows )”
            ‘ on line 110424:t6771/sepolicy/basic/hal_wifi_default.te:3:WARNING ‘unrecognized character’ at token ‘
            allow hal_wifi_default self:capability sys_module;
            #============= hal_wifi_default ==============
            ‘ on line 110425:t6771/sepolicy/basic/hal_wifi_default.te:4:WARNING ‘unrecognized character’ at token ‘
            allow hal_wifi_default self:capability sys_module;
            allow hal_wifi_default vendor_file:system module_load;
            system/sepolicy/public/hal_hongxi.te:4:ERROR ‘unknown type hal_hongxi_service’ at token ‘;’ on line 18523:
            #line 4
            allow hal_hongxi_server hal_hongxi_service:service_manager { add find };
            checkpolicy: error(s) encountered while parsing configuration

          2. Mohammad Hossein Heydarchi

            It means that hal_hongxi_service is not defined, or it’s defined but the sequence of processing the SELinux files is incorrect. To process that rule both of hal_hongxi_server and hal_hongxi_service should be seen before by the build system. Otherwise, it raises an error.

        2. Hi Arun ,
          I am facing same problem could you please help me out ?
          Is it possible to connect with you via mail or call ?

  2. I have recently started working on Android side and end up with one issue. As from Android U onwards all Android HALs will be migrated to AIDLs, I am currently trying to do this migration for my project. With the hidl2aidl tool I am successfully able to generate *.aidl files.

    But I am observing the below fixme line in my generated aidl file.

    // FIXME: AIDL does not allow int to be an out parameter. // Move it to return, or add it to a Parcelable.

    Is there any know fix for these kind of FixMes? Is there any issue in setting out parameter with AIDL? What if I have multiple out parameters from a function?

    1. Mohammad Hossein Heydarchi

      Yeah, it’s not allowed to use the out parameter. So what you can do is this:
      – create a new aidl file and define a parcelable. You can find an example of that in the example in my Github.
      – Then, use that parcelable as a return type for the method in your aidl interface.The parcelable includes all the parameters you want to return. The build system will create a class based on the parcelable.

      https://github.com/Heydarchi/AIDL-HAL-Service
      https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/light/aidl/aidl_api/android.hardware.light/1/android/hardware/light/

  3. Hi, Great post. I’m finding the error that I see you also have in your last screenshot above!
    “Could not start service dummy-server” Take a look above. Any idea how to fix?

    1. Mohammad Hossein Heydarchi

      Hi,
      The screenshot is for an emulator running in SELinux enforcement. As a temporary solution you should run the emulator or device in permissive mode.
      But if you can have a llok at the source code located in Github you can find the SELinux policies required to solve it. You will find those files in the device folder.
      https://github.com/Heydarchi/AIDL-HAL-Service

  4. Hi,
    I really appreciate your topics. But I don’t understand why we have the below header, and where it’s generated
    #include

    Thanks

    1. Mohammad Hossein Heydarchi

      Though your message is not complete and the header file is missed, I think you meant:

      BnDummy.h

      If yes, creating the AIDL interface produced this header file as one of the results. I would say that the AIDL interface module that we add to AOSP would generate some libraries and header files. Its Andoird.bp file contains a definition of the created libraries. Afterward, based on it, the necessary source code will also be accessible.
      For instance, the AOSP build system will provide the header and source code if you request C++/NDK libraries so that you can include them in your project.

      1. Thank you for your quick response.
        That’s exactly what I need.
        Could you write the article to use AIDL Service from the user application?
        Thanks

        1. Mohammad Hossein Heydarchi

          No worries!
          If you mean to communicate from a user app to an AIDL HAL service I would say that it’s not a good idea.
          But, I have planne to implement AIDL interface for the user applications as well when I can find some time.

  5. Hello. I have a question after reading these posts that I was wondering about. If I built the AOSP, can I use these same concepts that you showed us to call an AIDL interface that is already on the device? For example, the camera HAL?

    I am wondering if I can create my own daemon and then from there control the camera or microphone using the HAL already on the device. Thank you.

Leave a Comment

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