Android hal

发布时间 2024-01-04 10:34:53作者: 梦过无声

HAL介绍

hidl-gen 工具

$ out/soong/host/linux-x86/bin/hidl-gen
usage: out/soong/host/linux-x86/bin/hidl-gen [-p <root path>] -o <output path> -L <language> [-O <owner>] (-r <interface root>)+ [-R] [-v] [-d <depfile>] FQNAME...

Process FQNAME, PACKAGE(.SUBPACKAGE)*@[0-9]+.[0-9]+(::TYPE)?, to create output.

         -h: Prints this menu.
         -L <language>: The following options are available:
            check           : Parses the interface to see if valid but doesn't write any files.
            c++             : (internal) (deprecated) Generates C++ interface files for talking to HIDL interfaces.
            c++-headers     : (internal) Generates C++ headers for interface files for talking to HIDL interfaces.
            c++-sources     : (internal) Generates C++ sources for interface files for talking to HIDL interfaces.
            export-header   : Generates a header file from @export enumerations to help maintain legacy code.
            c++-impl        : Generates boilerplate implementation of a hidl interface in C++ (for convenience).
            c++-impl-headers: c++-impl but headers only.
            c++-impl-sources: c++-impl but sources only.
            c++-adapter     : Takes a x.(y+n) interface and mocks an x.y interface.
            c++-adapter-headers: c++-adapter but helper headers only.
            c++-adapter-sources: c++-adapter but helper sources only.
            c++-adapter-main: c++-adapter but the adapter binary source only.
            java            : (internal) Generates Java library for talking to HIDL interfaces in Java.
            java-constants  : (internal) Like export-header but for Java (always created by -Lmakefile if @export exists).
            vts             : (internal) Generates vts proto files for use in vtsd.
            makefile        : (removed) Used to generate makefiles for -Ljava and -Ljava-constants.
            androidbp       : (internal) Generates Soong bp files for -Lc++-headers, -Lc++-sources, -Ljava, -Ljava-constants, and -Lc++-adapter.
            androidbp-impl  : Generates boilerplate bp files for implementation created with -Lc++-impl.
            hash            : Prints hashes of interface in `current.txt` format to standard out.
            function-count  : Prints the total number of functions added by the package or interface.
            dependencies    : Prints all depended types.
         -O <owner>: The owner of the module for -Landroidbp(-impl)?.
         -o <output path>: Location to output files.
         -p <root path>: Android build root, defaults to $ANDROID_BUILD_TOP or pwd.
         -R: Do not add default package roots if not specified in -r.
         -r <package:path root>: E.g., android.hardware:hardware/interfaces.
         -v: verbose output.
         -d <depfile>: location of depfile to write to.

创建HAL接口文件

mkdir -p hardware/interfaces/haldemo/1.0/default
# hardware/interfaces/haldemo/1.0/IHalDemo.hal
package android.hardware.haldemo@1.0;
 
interface IHalDemo {
    add(uint32_t num, string name) generates (Result result);
    // delete c++ 关键字,不允许使用
    remove(Student student) generates (Result result);
    getall() generates (Result result, vec<Student> student);
};
# hardware/interfaces/haldemo/1.0/types.hal

package android.hardware.haldemo@1.0;

enum Result: uint32_t {
    OK,
    UNKNOWN_ERROR,
    BAD_VALUE,
    UNSUPPORTED_OPERATION
};

struct Student {
	uint32_t num;
	string  name;
};

hidl-gen生成代码C代码和Android.bp


hidl=out/host/linux-x86/bin/hidl-gen
PACKAGE=android.hardware.haldemo@1.0
LOC=hardware/interfaces/haldemo/1.0/default
${hidl} -L androidbp -r android.hardware.haldemo:hardware/interfaces/haldemo/ -r android.hidl:system/libhidl/transport -o hardware/interfaces/haldemo/1.0/default $PACKAGE
${hidl} -L c++-impl -r android.hardware.haldemo:hardware/interfaces/haldemo/ -r android.hidl:system/libhidl/transport -o hardware/interfaces/haldemo/1.0/default  $PACKAGE
${hidl} -Landroidbp-impl -r android.hardware.haldemo:hardware/interfaces/haldemo/ -r android.hidl:system/libhidl/transport -o hardware/interfaces/haldemo/1.0/default  $PACKAGE

此时可以看到生成的文件

$ tree hardware/interfaces/haldemo/1.0/
hardware/interfaces/haldemo/1.0/
├── default
│   ├── HalDemo.cpp
│   └── HalDemo.h
├── defaulthardware
│   └── interfaces
│       └── haldemo
│           └── 1.0
│               └── Android.bp
├── IHalDemo.hal
└── types.hal

复制出来Makefile

cp hardware/interfaces/haldemo/1.0/defaulthardware/interfaces/haldemo/1.0/Android.bp hardware/interfaces/haldemo/1.0/
rm -rf hardware/interfaces/haldemo/1.0/defaulthardware

实现HAL

完整的代码

$ tree hardware/interfaces/haldemo/
hardware/interfaces/haldemo/
├── 1.0
│   ├── Android.bp
│   ├── default
│   │   ├── Android.bp
│   │   ├── android.hardware.haldemo@1.0-service.rc
│   │   ├── HalDemo.cpp
│   │   ├── HalDemo.h
│   │   ├── HalDemoTest.cpp
│   │   └── service.cpp
│   ├── IHalDemo.hal
│   └── types.hal
└── Android.bp

MakeFile

// hardware/interfaces/haldemo/1.0/default/Android.bp

cc_library_shared {
    name: "android.hardware.haldemo@1.0-impl",
    relative_install_path: "hw",
    proprietary: true,
    srcs: [
        "HalDemo.cpp",
    ],
    shared_libs: [
        "libhidlbase",
        "libhidltransport",
        "libutils",
        "libbase",
        "liblog",
        "android.hardware.haldemo@1.0",
    ],
}

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

cc_binary {
    name: "haldemo-test",
    vendor: true,
    srcs: ["HalDemoTest.cpp"],

    // defaults: ["hidl_defaults"],

    shared_libs: [
        "liblog",
        "libhardware",
        "libhidlbase",
        "libhidltransport",
        "libutils",
        "android.hardware.haldemo@1.0",
    ],
} 

开机启动服务

// hardware/interfaces/haldemo/1.0/default/service.cpp
#define LOG_TAG "android.hardware.haldemo@1.0-service"
                        
#include <android/hardware/haldemo/1.0/IHalDemo.h>
#include <hidl/LegacySupport.h>
                        
using android::hardware::haldemo::V1_0::IHalDemo;
using android::hardware::defaultPassthroughServiceImplementation;
                                                  
int main() {                                      
    return defaultPassthroughServiceImplementation<IHalDemo>();
}  
// hardware/interfaces/haldemo/1.0/default/android.hardware.haldemo@1.0-service.rc
service haldemo-hal-1-0 /vendor/bin/hw/android.hardware.haldemo@1.0-service
    class hal
    user system
    group system

实现库 hardware/interfaces/haldemo/1.0/default/HalDemo.cpp

#include "HalDemo.h"
#include <android-base/logging.h>

using ::android::hardware::haldemo::V1_0::Result;
using ::android::hardware::haldemo::V1_0::Student;

namespace android {
namespace hardware {
namespace haldemo {
namespace V1_0 {
namespace implementation {

std::vector<Student> gStudents = {
    {0, "zhang san"},
    {1, "li si"}
};

void show()
{
    for (const Student& item : gStudents) {
        LOG(INFO) << "ID: " << item.num << ", Name: " << item.name;
    }
}


// Methods from IHalDemo follow.
Return<Result> HalDemo::add(uint32_t num, const hidl_string& name) {
    // TODO implement
    
    for (int index = 0; index < gStudents.size(); index++) {
        if (gStudents[index].num == num) {
            LOG(ERROR) << "add same student num " << num;
            return Result::BAD_VALUE;
        }
    }

    Student student;
    student.num = num;
    student.name = name;
    gStudents.push_back(student);
    return Result::OK;
}

Return<Result> HalDemo::remove(const Student& student) {
    // TODO implement

    gStudents.erase(std::remove_if(gStudents.begin(), gStudents.end(), [=](const Student& s) {
        return s.num == student.num;
    }), gStudents.end());

    return Result::OK;
}

Return<void> HalDemo::getall(getall_cb _hidl_cb) {
    // TODO implement
    show();
    std::vector<Student> copy = gStudents;
    _hidl_cb(Result::OK, copy);
    return Void();
}

// Methods from ::android::hidl::base::V1_0::IBase follow.

IHalDemo* HIDL_FETCH_IHalDemo(const char* /* name */) {
    return new HalDemo();
}

}  // namespace implementation
}  // namespace V1_0
}  // namespace haldemo
}  // namespace hardware
}  // namespace android

测试客户端

// hardware/interfaces/haldemo/1.0/default/HalDemoTest.cpp
#include <stdio.h>
#include <string>
#include "HalDemo.h"

using namespace std;

using ::android::hardware::hidl_string;
using ::android::sp;
using ::android::hardware::haldemo::V1_0::IHalDemo;
using ::android::hardware::haldemo::V1_0::Student;
using ::android::hardware::haldemo::V1_0::Result;

int main(){
    // 自动生成的头文件路径
    // out/soong/.intermediates/hardware/interfaces/haldemo/1.0/android.hardware.haldemo@1.0_genc++_headers/gen/android/hardware/haldemo/1.0/IHalDemo.h
    //
    android::sp<IHalDemo> service = IHalDemo::getService();
    if (service == nullptr){
        printf("Failed to get service\n");
        return -1;
    }
    
    // using getall_cb = std::function<void(Result result, const ::android::hardware::hidl_vec<Student>& student)>;

    auto callback = [](Result result, const ::android::hardware::hidl_vec<Student> &students) {
        printf("getall call back students %d\n", students.size());
    };

    service->getall(callback);
    
    Student student;
    student.num = 100;
    student.name = "hi hal";

    service->add(100, "hi hal 100");
    service->add(100, "hi hal 101 ");
    service->remove(student);

    service->add(101, "wang xi");
    service->getall(callback);
    return 0;
}

添加到device product中

PRODUCT_PACKAGES += \
	android.hardware.haldemo@1.0-service \
	android.hardware.haldemo@1.0-impl

最终效果

# haldemo-test                                                                                                                                                                                       
getall call back students 2
getall call back students 3
hikay960q4:/ # logcat
--------- beginning of main
01-03 09:36:22.441   763   813 E BandwidthController: Updating quota globalAlert failed (Status[code: 2, msg: "[No such file or directory] : fopen("/proc/net/xt_quota/globalAlert", "we") failed"])
01-03 09:36:29.945   748   748 W /system/bin/hwservicemanager: getTransport: Cannot find entry android.hardware.haldemo@1.0::IHalDemo/default in either framework or device manifest.
01-03 09:36:29.946   775   775 I /vendor/bin/hw/android.hardware.haldemo@1.0-service: ID: 0, Name: zhang san
01-03 09:36:29.946   775   775 I /vendor/bin/hw/android.hardware.haldemo@1.0-service: ID: 1, Name: li si
01-03 09:36:29.946   775   775 E /vendor/bin/hw/android.hardware.haldemo@1.0-service: add same student num 100
01-03 09:36:29.946   775   775 I /vendor/bin/hw/android.hardware.haldemo@1.0-service: ID: 0, Name: zhang san
01-03 09:36:29.946   775   775 I /vendor/bin/hw/android.hardware.haldemo@1.0-service: ID: 1, Name: li si
01-03 09:36:29.946   775   775 I /vendor/bin/hw/android.hardware.haldemo@1.0-service: ID: 101, Name: wang xi