HIDL服务编写实现

Posted by on March 4, 2022

###HIDL则是用来连接Framework和HAL通信,调用HAL层,AOSP的hardware/interfaces/目录下有很多的HIDL

  • 一般目录都是hardware/interfaces/xx下,这里我们看fingerprint,具体的位置在 hardware/interface/biometrics/fingerprint/2.1/ 目录下有个 IBiometricsFingerprint.hal

package android.hardware.biometrics.fingerprint@2.1;

import IBiometricsFingerprintClientCallback;

interface IBiometricsFingerprint {
  /**
   * Set notification callback:
   * Registers a user function that must receive notifications from the HAL
   * This call must block if the HAL state machine is in busy state until HAL
   * leaves the busy state.
   *
   * @return deviceId is a unique handle for this fingerprint device
      这个方法是在HAL层定义的方法
   */
  @callflow(next={"setActiveGroup"})
  @entry
  setNotify(IBiometricsFingerprintClientCallback clientCallback)
      generates (uint64_t deviceId);
 
};


  • 然后就可以使用Android提供的工具hidl-gen来生成HIDL框架,执行如下命令:
 PACKAGE=android.hardware.fingerprint_hidl@2.1
 LOC=hardware/interfaces/biometrics/fingerprint/2.1/default/
 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
  • 执行命令成功之后我们会发现hardware/interface/biometrics/fingerprint/2.1/下多了一个default目录,进入default目录,里面有三个文件Android.bp,BiometricsFingerprint.cpp,BiometricsFingerprint.h

  • 之后再在执行./hardware/interfaces/update-makefiles.sh这个命令,update-makefiles.sh这个脚本目的是为HIDL生成对应Android.bp文件

  • 还需要编写一个 service.cpp

#define LOG_TAG "android.hardware.biometrics.fingerprint@2.1-service"

#include <android/log.h>
#include <hidl/HidlSupport.h>
#include <hidl/HidlTransportSupport.h>
#include <android/hardware/biometrics/fingerprint/2.1/IBiometricsFingerprint.h>
#include <android/hardware/biometrics/fingerprint/2.1/types.h>
#include "BiometricsFingerprint.h"

using android::hardware::biometrics::fingerprint::V2_1::IBiometricsFingerprint;
using android::hardware::biometrics::fingerprint::V2_1::implementation::BiometricsFingerprint;
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::sp;

int main() {
    android::sp<IBiometricsFingerprint> bio = BiometricsFingerprint::getInstance();

    configureRpcThreadpool(1, true /*callerWillJoin*/);

    if (bio != nullptr) {
        if (::android::OK != bio->registerAsService()) {
            return 1;
        }
    } else {
        ALOGE("Can't create instance of BiometricsFingerprint, nullptr");
    }

    joinRpcThreadpool();

    return 0; // should never get here
}
  • 然后再 Android.bp 加上service.cpp
cc_binary {
    name: "android.hardware.biometrics.fingerprint@2.1-service",
    defaults: ["hidl_defaults"],
    init_rc: ["android.hardware.biometrics.fingerprint@2.1-service.rc"],
    vendor: true,
    relative_install_path: "hw",
    srcs: [
        "BiometricsFingerprint.cpp",
        "service.cpp",
    ],

    shared_libs: [
        "libcutils",
        "liblog",
        "libhidlbase",
        "libhidltransport",
        "libhardware",
        "libutils",
        "android.hardware.biometrics.fingerprint@2.1",
    ],

}
  • HIDL想要被Framework获取使用还需要在manifest.xml中注册,将这个hwservice注册到系统(这样getService()才能找到它) 在/device/$(Vender)/$(Product)/manifest.xml中添加: 例如: \device\mediatek\mt6771

  • 然后执行 mmm hardware/interface/biometrics/fingerprint/2.1/ 就会进行编译,并且生成so库

  • 对应java层调用直接可以用这样方式调用

 public synchronized IBiometricsFingerprint getFingerprintDaemon() {
        if (mDaemon == null) {
            Slog.v(TAG, "mDaemon was null, reconnect to fingerprint");
            try {
                mDaemon = IBiometricsFingerprint.getService();
            } catch (java.util.NoSuchElementException e) {
                // Service doesn't exist or cannot be opened. Logged below.
            } catch (RemoteException e) {
                Slog.e(TAG, "Failed to get biometric interface", e);
            }
         
        }
        return mDaemon;
    }

getService 方式就可以引用到HIDL层代码使用

  • 还有在JNI层中也可以通过类似于 IGnss_V1_1::getService() 获取到HIDL层对象来达到调用

  • HIDL中自动在defaut中生成文件xx.cpp以后需要在 HIDL_FETCH_XXX中进行HAL层的初始化操作

IGnss* HIDL_FETCH_IGnss(const char* /* hal */) {
    hw_module_t* module;
    IGnss* iface = nullptr;
    int err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);

    if (err == 0) {
        hw_device_t* device;
        err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
        if (err == 0) {
            iface = new Gnss(reinterpret_cast<gps_device_t*>(device));
        } else {
            ALOGE("gnssDevice open %s failed: %d", GPS_HARDWARE_MODULE_ID, err);
        }
    } else {
      ALOGE("gnss hw_get_module %s failed: %d", GPS_HARDWARE_MODULE_ID, err);
    }
    return iface;
}