Android P HIDL demo code writing (original)

Previous articles have analyzed the registration and invocation of HIDL service, and this article summarizes how to write the next HIDL service.

Abbreviated HAL file

First of all, you need to confirm the package name of the folder and interface, because this is related to the use of script to generate some code. Generally, it is placed in the hardware/interfaces directory by default. We write a simple IDemo.hal (hardware/interface/demo/1.0/IDemo.hal)

package android.hardware.demo@1.0;

interface IDemo {
    init(int32_t level) generates (int32_t initRet);

    getProperty(string key) generates (int32_t getResult, string value);
};

Generate execution code for interface

Use the following command to generate the execution file:

hidl-gen -o hardware/interfaces/demo/1.0/default -Lc++-impl -randroid.hardware:hardware/intefaces -randroid.hidl:system/libhidl/transport android.hardware.demo@1.0

This command will generate Demo.cpp and Demo.h files under hardware/interfaces/demo/1.0/default. In the interface file above, there are two return values in getProperty. Generally, there is only one return value in a function. What are the two return values? Let's see what the generated execution code looks like?

#include "Demo.h"

namespace android {
namespace hardware {
namespace demo {
namespace V1_0 {
namespace implementation {

Return<int32_t> Demo::init(int32_t level) {
//In this way, you can return a parameter as a normal function, and the return value is OK
return int32_t{}; } Return<void> Demo::getProperty(const hidl_string& key, getProperty_cb _hidl_cb ) { //Here, two return values are encapsulated in a callback function and passed to the caller, using the following int result = 0; //Use map Li value to return
  std::Map<hidl_string, hidl_string> demoMap = {
    {"one", "first"},
    {"two", "second"},
    {"three", "third"}
  };

  int result = -1;
  hidl_string value = "";
  auto findRet = demoMap.find(key);
  if(findRet != demoMap.end()){
    result = 0;
    value = findRet->second;
  }
  //Here, the result and value are directly called back to the caller as parameters
  _hidl_cb(result, value); return Void(); } } } } }

Generate Android.bp

After the method is implemented, you need to use the command to regenerate an Android.bp

hidl-gen -o hardware/interfaces/demo/1.0/default -Landroidbp-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.demo@1.0

After the command is executed, it will be displayed in the hardware / interfaces / demo / 1.0/default/android.bp

Enter the hardware/interface directory and execute. / update-makefiles.sh to generate the demo/1.0/Android.bp file

Now that we have two Android.bp, we need to use binding mode to create a Demo service, and create a service.cpp under demo/1.0/default

Add service code for binding mode

#include <android-base/logging.h>
#include <hidl/HidlTransportSupport.h>
#include <android/hardware/demo/1.0/IDemo.h>

#undef LOG_TAG
#define LOG_TAG "android.hardware.demo@1.0-service"

#include <hidl/LegacySupport.h>
#include "Demo.h"
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::hardware::demo::V1.0::implementation::Demo;

int main(){
    configureRpcThreadpool(4, true);
    Demo demo = new Demo();
    auto status = demo.registerAsService();
    if(status != android::OK){
        ALOGE("register demo As Service failed");
        return -1;
    }
    joinRpcThreadpool();
}

Then create android.hardware.demo@1.0-service.rc under demo/1.0/default

service demo_hal_service /vendor/bin/hw/android.hardware.demo@1.0-service
    class hal
    user  system
    group  system

In demo/1.0/default/Android.bp, add the compile items of init? RC and service.cpp, and change CC? Library? Shared to CC? Binary, as follows:

cc_binary {
    name: "android.hardware.demo@1.0-service",
    relative_install_path: "hw",
    proprietary: true,
    init_rc: ["android.hardware.demo@1.0-service.rc"],
    srcs: [
        "Demo.cpp",
        "service.cpp"
    ],  
    shared_libs: [
        "libhidlbase",
        "libhidltransport",
        "libutils",
     "liblog",
"android.hardware.demo@1.0", ], }

Then you can compile android.hardware.demo@1.0-service and android.hardware.demo@1.0-service.rc services through mmm or mm.

If you want to self run and add the relevant permissions of selinux, you can refer to selinux of other HIDL services.

As for the interface to call HIDL, we have analyzed it in the previous article. Let's write the core code as follows:

#include <android/hardware/demo/1.0/IDemo.h>
sp<IDemo> mDemo = IDemo::getService();
mDemo->init(1);
string mValue;
mDemo->getProperty("two", [&](int result, string value) {
       if(result == 0)
             mVaule = value;
});

At this point, the Demo service code of HIDL can be finished, and the complex Icallback HIDL interface related code can be added later.

Tags: C++ Android SELinux

Posted on Thu, 07 May 2020 07:08:55 -0400 by Ph0enix