Android9.0 HAL 层开发

一、生成 HAL 代码

1. 生成 hidl-gen 工具

source source ./build/envsetup.sh
lunch your_project
make hidl-gen -j4

2. 编写接口文件

编写 types.hal, IHello.hal, IHelloCallback.hal,Android.bp

1. IHello.hal 代码
package [email protected];

import types;
import IHelloCallback;

interface IHello {
    get_data_char() generates(Status st, vec version);
    
    write_data_char(vecdata, uint32_t size) generates(int32_t result);
    
    write_data_string(string data) generates(int32_t result);
};
2. types.hal 代码
package [email protected];

enum Status : int32_t{
    SUCCESS,
    FAILURE
};
3. IHelloCallback.hal 代码
package [email protected];

interface IHelloCallback {
     oneway onNotifyHelloEvent(string event);
};
4. Android.bp 代码

hidl_interface {
    name: "[email protected]",
    root: "vendor.tests.hardware",
    srcs: [
        "types.hal",
        "IHello.hal",
        "IHelloCallback.hal",
    ],
    interfaces: [
        "[email protected]",
    ],
    types: [
        "Status",
    ],
    gen_java: true,
}

注意,由于 "[email protected]" root 是 "vendor.test.hardware"
所以这个 root 一定是之前定义过的,如果自己新建的root,可以参考下面新建root,比如:

root 包 bp参考写法:
vendor/tests/hardware/Android.bp
hidl_package_root {
    name: "vendor.tests.hardware",  // root 包名
    path: "vendor/tests/interfaces" // root 路径
}

那么所有依赖 "vendor.tests.hardware" 的都在 "vendor/tests/interfaces" 目录下面,比如 "[email protected]" 就在 "vendor/tests/interfaces" 下面新建 "hello/1.0" 目录,然后在该目录下面新建 "Android.bp"、 "types.hal"、"IHello.hal"、"IHelloCallback.hal" 等。

在"vendor/tests/interfaces/" 目录下面新建具体实现的目录,比如 "impl",在impl下面新建 ”hello“对应的目录,比如 "hello/1.0/default"目录


3. 配置临时变量,包名,生成代码路径

// 包名
[email protected]

// 生成代码路径
LOC=vendor/tests/interfaces/impl/hello/1.0/default/

4. 生成代码

生成 c++ 代码:其中 LOC 指定生成代码的路径:
hidl-gen -o $LOC -Lc++-impl -rvendor.tests.hardware:vendor/tests/interfaces/ -randroid.hidl:system/libhidl/transport $PACKAGE

其中 "-r" 参数作用 "-r : E.g., android.hardware:hardware/interfaces." 生成的 c++ 代码路径由 "-o" 参数指定,即上面的 LOC 变量定义的路径

生成 c++ 代码的 Android.bp:
hidl-gen -o $LOC -Landroidbp-impl -rvendor.tests.hardware:vendor/tests/interfaces/ -randroid.hidl:system/libhidl/transport $PACKAGE

更新代码 bp 文件
vendor/tests/interfaces/update-makefiles.sh
// 该文件一般的 interfaces 的root 目录都会有,参考 hardware/interfaces/update-makefiles.sh

二、修改 c++ 实现代码

1. 通过类方式实现功能

修改 Helllo.cpp HelloCallback.cpp "struct" 为 "class",并实现对应构造方法,析构方法。

// Hello.h 代码
#ifndef VENDOR_TESTS_HARDWARE_HELLO_V1_0_HELLO_H
#define VENDOR_TESTS_HARDWARE_HELLO_V1_0_HELLO_H

#include 
#include 
#include 

namespace vendor {
namespace tests {
namespace hardware {
namespace hello {
namespace V1_0 {
namespace implementation {

using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;

class Hello : public IHello {
public:
    // Methods from ::vendor::tests::hardware::hello::V1_0::IHello follow.
    Return get_data_char(get_data_char_cb _hidl_cb) override;
    Return write_data_char(const hidl_vec& data, uint32_t size) override;
    Return write_data_string(const hidl_string& data) override;

    // Methods from ::android::hidl::base::V1_0::IBase follow.
    Hello();
    ~Hello();
    void onServiceDied();
};

// FIXME: most likely delete, this is only for passthrough implementations
// extern "C" IHello* HIDL_FETCH_IHello(const char* name);

}  // namespace implementation
}  // namespace V1_0
}  // namespace hello
}  // namespace hardware
}  // namespace tests
}  // namespace vendor

#endif  // VENDOR_TESTS_HARDWARE_HELLO_V1_0_HELLO_H
// HelloCallback.h 代码
#ifndef VENDOR_TESTS_HARDWARE_HELLO_V1_0_HELLOCALLBACK_H
#define VENDOR_TESTS_HARDWARE_HELLO_V1_0_HELLOCALLBACK_H

#include 
#include 
#include 

namespace vendor {
namespace tests {
namespace hardware {
namespace hello {
namespace V1_0 {
namespace implementation {

using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;

class HelloCallback : public IHelloCallback {
    // Methods from ::vendor::tests::hardware::hello::V1_0::IHelloCallback follow.
    Return onNotifyHelloEvent(const hidl_string& event) override;

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

};

// FIXME: most likely delete, this is only for passthrough implementations
// extern "C" IHelloCallback* HIDL_FETCH_IHelloCallback(const char* name);

}  // namespace implementation
}  // namespace V1_0
}  // namespace hello
}  // namespace hardware
}  // namespace tests
}  // namespace vendor

#endif  // VENDOR_TESTS_HARDWARE_HELLO_V1_0_HELLOCALLBACK_H


// HelloCallback.cpp 代码
#include "HelloCallback.h"

namespace vendor {
namespace tests {
namespace hardware {
namespace hello {
namespace V1_0 {
namespace implementation {

// Methods from ::vendor::tests::hardware::hello::V1_0::IHelloCallback follow.
Return HelloCallback::onNotifyHelloEvent(const hidl_string& event) {
    // TODO implement
    return Void();
}


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

//IHelloCallback* HIDL_FETCH_IHelloCallback(const char* /* name */) {
    //return new HelloCallback();
//}
//
}  // namespace implementation
}  // namespace V1_0
}  // namespace hello
}  // namespace hardware
}  // namespace tests
}  // namespace vendor

2. 实现 HelloDeathListener 类

该类继承于 "android::hardware::hidl_death_recipient",并实现 “serviceDied” 方法,在该方法中调用 Helllo 类的 "onServiceDied"方法

// HelloDeathListener.h 代码
#ifndef VENDOR_TESTS_HARDWARE_HELLO_V1_0_HELLO_DEATH_LISTENE_H
#define VENDOR_TESTS_HARDWARE_HELLO_V1_0_HELLO_DEATH_LISTENE_H

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "Hello.h"
#include "HelloCallback.h"

namespace vendor {
namespace tests {
namespace hardware {
namespace hello {
namespace V1_0 {
namespace implementation {

using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hidl::base::V1_0::IBase;
using ::android::sp;
using ::android::wp;

class Hello;

class HelloDeathListener : public android::hardware::hidl_death_recipient {
public:
    HelloDeathListener(Hello *hello);
    virtual ~HelloDeathListener();
    virtual void serviceDied(uint64_t cookie, const wp& who) override;
private:
    Hello *mHello;
};

}  // namespace implementation
}  // namespace V1_0
}  // namespace hello
}  // namespace hardware
}  // namespace tests
}  // namespace vendor

#endif  // VENDOR_TESTS_HARDWARE_HELLO_V1_0_HELLO_DEATH_LISTENE_H


// HelloDeathListener.cpp 代码
#include "HelloDeathListener.h"
#include 

#undef LOG_TAG
#define LOG_TAG "Hello@DeathListener"

namespace vendor {
namespace tests {
namespace hardware {
namespace hello {
namespace V1_0 {
namespace implementation {

using namespace android::base;
using namespace std;

HelloDeathListener::HelloDeathListener(Hello *hello) {
    ALOGE("%s", __FUNCTION__);
    if (hello != nullptr) {
        mHello = hello;
    }
}

HelloDeathListener:: ~HelloDeathListener() {}

void HelloDeathListener::serviceDied(uint64_t cookie, const wp& who) {
    ALOGE("%s", __FUNCTION__);
    if (mHello != nullptr) {
        mHello->onServiceDied();
    }
}

}  // namespace implementation
}  // namespace V1_0
}  // namespace hello
}  // namespace hardware
}  // namespace tests
}  // namespace vendor

3. 根据 IHello.hal 实现对应接口

IHello.hal 中接口:

// 该方法参数都为 输出参数,即返回值为 Status,返回数据为 vector 实际为 vector,可进行数据转换。
get_data_char() generates(Status st, vec version);

// 该方法参数为 两个输入参赛,一个返回值。
write_data_char(vecdata, uint32_t size) generates(int32_t result);

/ 该方法参数为 一个输入参赛,一个返回值。
write_data_string(string data) generates(int32_t result);


// Hello.cpp 实现:
#include "Hello.h"
#include 
#include 
#include 

namespace vendor {
namespace tests {
namespace hardware {
namespace hello {
namespace V1_0 {
namespace implementation {

Hello::Hello()
{}

Hello::~Hello()
{
	
}

void Hello::onServiceDied()
{
	ALOGE("invoked ");
}
    

// Methods from ::vendor::tests::hardware::hello::V1_0::IHello follow.
Return Hello::get_data_char(get_data_char_cb _hidl_cb) {
    static char buffer[] = "hello return data!";
    std::vector data(buffer, buffer+strlen(buffer));
    
    _hidl_cb(Status::SUCCESS, (const hidl_vec)data);
    return Void();
}

Return Hello::write_data_char(const hidl_vec& data, uint32_t size) {
    ALOGE("data: %s, len: %d", data.data(), size);

    return int32_t {0};
}

Return Hello::write_data_string(const hidl_string& data) {
    ALOGE("data: %s", data.c_str());
    return int32_t {0};
}

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

//IHello* HIDL_FETCH_IHello(const char* /* name */) {
    //return new Hello();
//}
//
}  // namespace implementation
}  // namespace V1_0
}  // namespace hello
}  // namespace hardware
}  // namespace tests
}  // namespace vendor

4. 实现HelloService 

// HelloService.cpp 代码
#define LOG_TAG "[email protected]"

#include 
#include 
#include 
#include 
#include "Hello.h"

using namespace android;
using namespace android::hardware;
using namespace vendor::tests::hardware::hello::V1_0::implementation;
using namespace std::placeholders;

int main(int /* argc */, char * /* argv */[])
{
    auto service = std::make_unique();
    configureRpcThreadpool(4, true /* callerWillJoin */);
    ALOGD("Hello HAL service starting");
    status_t status = service->registerAsService();
    if (status != OK)
    {
        ALOGE("Unable to register Hello HAL service (%d)", status);
        return 1;
    }
    ALOGI("Register Hello Service successfully");
    joinRpcThreadpool();
    return 1;
}

5. 更新 Android.bp

// Android.bp 代码
// new add
cc_defaults {
    name: "hello_defaults",
    shared_libs: [
    	"liblog",
        "libutils",
        "libhidlbase",
        "libhardware",
        "libhidltransport",
    ],
    vendor: true,
    compile_multilib: "64",
    cflags: [
        "-Wall",
        "-Wextra",
        "-Werror",
        "-Wno-unused-parameter"
    ],
}

// modify
cc_library_shared {
    name: "[email protected]",
    relative_install_path: "hw",
    defaults: ["hello_defaults"],
    proprietary: true,
    srcs: [
        "Hello.cpp",
        "HelloCallback.cpp",
        "HelloDeathListener.cpp",
    ],
    shared_libs: [
        "libhidlbase",
        "libhidltransport",
        "libutils",
        "[email protected]",
    ],
}

// new add
cc_binary {
    name: "[email protected]",
    relative_install_path: "hw",
    defaults: ["hello_defaults"],
    init_rc: ["[email protected]"],
    rtti: false,
    srcs: [
        "HelloService.cpp"
    ],
	header_libs: [],
    shared_libs: [
        "libbase",
        "libprotobuf-cpp-lite",
        "libcommon-base",
        "[email protected]",
        "[email protected]",
    ],
	cppflags: [
        "-fexceptions"
    ]
}

6.  HAL service 启动 rc文件

//[email protected]
service vendor.tests.hardware.hello-1.0 /vendor/bin/hw/[email protected]
    class hal
    user system
    group system inet

7. selinux 标签修改

在 xxx.te 中对 service 标签进行修改

// file_contexs
/(vendor|system/vendor)/bin/hw/[email protected]           u:object_r:hal_hello_default_exec:s0

// hal_hello_default_exec.te
# add for hello
type hal_hello_default, domain, mlstrustedsubject;
typeattribute hal_hello_default nobohaldomain, mlstrustedsubject;
hal_server_domain(hal_hello_default, hal_hello)
type hal_hello_default_exec, exec_type, vendor_file_type, file_type;

init_daemon_domain(hal_hello_default)

# Allow hwbinder call from hal client to server
binder_call(hal_hello_client, hal_hello_server)

# Add hwservice related rules
add_hwservice(hal_hello_server, hal_hello_hwservice)
allow hal_hello_client hal_hello_hwservice:hwservice_manager find;

#hwbinder_use(hal_hello)
get_prop(hal_hello, hwservicemanager_prop)
allow hal_hello_default mnt_vendor_file:dir rw_dir_perms; 

allow hal_hello_default tee_device:chr_file { ioctl open read write };
allow hal_hello_default ion_device:chr_file { ioctl open read write };


typeattribute hal_hello_default system_writes_vendor_properties_violators;

allow hal_hello_default mnt_vendor_crypto_file:dir create_dir_perms;
allow hal_hello_default mnt_vendor_crypto_file:file create_file_perms;
allow hal_hello_default mnt_vendor_crypto_file:filesystem getattr;
allow hal_hello_default vendor_data_nfs_file:dir search;

allow hal_hello_default pki_sdk_file:file { read open execute getattr map };
allow hal_hello_default default_prop:file { read open execute getattr map };
allow hal_hello_default vendor_bean_prop:file { read open execute getattr map };
allow hal_hello_default property_socket:sock_file { write };
allow hal_hello_default init:unix_stream_socket { connectto };

allow hal_hello_default vfat:dir create_dir_perms;
allow hal_hello_default vfat:file create_file_perms;
allow hal_hello_default vfat:filesystem getattr;
allow hal_hello_default mnt_user_log_file:lnk_file read;
allow hal_hello_default mnt_user_file:dir search;
allow hal_hello_default mnt_user_file:lnk_file read;
allow hal_hello_default unlabeled:dir { search write read add_name open create };
allow hal_hello_default unlabeled:file { read append write open create getattr };
// 其中 hal_hello_default_exec 需要自己定义,具体参考系统中的其他修改
// 同时 attributes、hwservice.te、hwservice_contexts 需要对应修改

// attributes 修改
attribute hal_hello;
expandattribute hal_hello true;
attribute hal_hello_client;
expandattribute hal_hello_client true;
attribute hal_hello_server;
expandattribute hal_hello_server false;

// hwservice.te
type hal_hello_hwservice, hwservice_manager_type;

// hwservice_contexts
vendor.tests.hardware.hello::IHello      u:object_r:hal_hello_hwservice:s0

8. 对应模块加入系统编译

xxx.mk

PRODUCT_PACKAGES += \
    [email protected] \
    [email protected] \
    [email protected] \
    

三、client 实现

#define LOG_TAG "HelloClient"

#include 
#include 

#include 
#include 
#include 

using namespace vendor::tests::hardware::hello::V1_0;

using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using vendor::tests::hardware::hello::V1_0::IHello;
using vendor::tests::hardware::hello::V1_0::Status;
using android::sp;
using android::status_t;

int main(){
    sp helloService = IHello::getService();
    if (helloService == nullptr) {
        LOGE("can't not get IHello service!");
        return -1; 
    }
    
    Status status = FAILURE;
    std::vector readBuffer;
    helloService->get_data_char([&](Status st, std::vector data){
        status = st; readBuffer = data;
    });


    char str[] = "write data string .....";
    std::vector writeBuffer(str, str+strlen(str));
    int len = helloService->write_data_char(writeBuffer, strlen(str));

}

四. 完整测试代码

https://download.csdn.net/download/SHK242673/72544934

你可能感兴趣的:(android,android,android,hal)