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 vendor.tests.hardware.hello@1.0;

import types;
import IHelloCallback;

interface IHello {
    get_data_char() generates(Status st, vec<int8_t> version);
    
    write_data_char(vec<int8_t>data, uint32_t size) generates(int32_t result);
    
    write_data_string(string data) generates(int32_t result);
};
2. types.hal 代码
package vendor.tests.hardware.hello@1.0;

enum Status : int32_t{
    SUCCESS,
    FAILURE
};
3. IHelloCallback.hal 代码
package vendor.tests.hardware.hello@1.0;

interface IHelloCallback {
     oneway onNotifyHelloEvent(string event);
};
4. Android.bp 代码
如果 HAL 代码是在hardware/interfaces 目录下面,则可以在 hardware/interfaces/ 目录执行下面自动生成下面的 Android.bp

./update-makefiles.sh
hidl_interface {
    name: "vendor.tests.hardware.hello@1.0",
    root: "vendor.tests.hardware",
    srcs: [
        "types.hal",
        "IHello.hal",
        "IHelloCallback.hal",
    ],
    interfaces: [
        "android.hidl.base@1.0",
    ],
    types: [
        "Status",
    ],
    gen_java: true,
}

注意,由于 "vendor.test.hardware.hello@1.0" 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" 目录下面,比如 "vendor.tests.hardware.hello@1.0" 就在 "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. 配置临时变量,包名,生成代码路径

// 包名
PACKAGE=vendor.tests.hardware.hello@1.0

// 生成代码路径
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 <package:path root>: 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 <vendor/tests/hardware/hello/1.0/IHello.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.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::sp;

class Hello : public IHello {
public:
    // Methods from ::vendor::tests::hardware::hello::V1_0::IHello follow.
    Return<void> get_data_char(get_data_char_cb _hidl_cb) override;
    Return<int32_t> write_data_char(const hidl_vec<int8_t>& data, uint32_t size) override;
    Return<int32_t> 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 <vendor/tests/hardware/hello/1.0/IHelloCallback.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.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::sp;

class HelloCallback : public IHelloCallback {
    // Methods from ::vendor::tests::hardware::hello::V1_0::IHelloCallback follow.
    Return<void> 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<void> 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 <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#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<IBase>& 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 <log/log.h>

#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<IBase>& 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<int8_t> 实际为 vector<char>,可进行数据转换。
get_data_char() generates(Status st, vec<int8_t> version);

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

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


// Hello.cpp 实现:
#include "Hello.h"
#include <string.h>
#include <log/log.h>
#include <android/log.h>

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<void> Hello::get_data_char(get_data_char_cb _hidl_cb) {
    static char buffer[] = "hello return data!";
    std::vector<int8_t> data(buffer, buffer+strlen(buffer));
    
    _hidl_cb(Status::SUCCESS, (const hidl_vec<int8_t>)data);
    return Void();
}

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

    return int32_t {0};
}

Return<int32_t> 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 "vendor.tests.hardware.hello@1.0-service"

#include <stdio.h>
#include <android/log.h>
#include <utils/SystemClock.h>
#include <hidl/HidlTransportSupport.h>
#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<Hello>();
    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: "vendor.tests.hardware.hello@1.0-impl",
    relative_install_path: "hw",
    defaults: ["hello_defaults"],
    proprietary: true,
    srcs: [
        "Hello.cpp",
        "HelloCallback.cpp",
        "HelloDeathListener.cpp",
    ],
    shared_libs: [
        "libhidlbase",
        "libhidltransport",
        "libutils",
        "vendor.tests.hardware.hello@1.0",
    ],
}

// new add
cc_binary {
    name: "vendor.tests.hardware.hello@1.0-service",
    relative_install_path: "hw",
    defaults: ["hello_defaults"],
    init_rc: ["vendor.tests.hardware.hello@1.0-service.rc"],
    rtti: false,
    srcs: [
        "HelloService.cpp"
    ],
	header_libs: [],
    shared_libs: [
        "libbase",
        "libprotobuf-cpp-lite",
        "libcommon-base",
        "vendor.tests.hardware.hello@1.0",
        "vendor.tests.hardware.hello@1.0-impl",
    ],
	cppflags: [
        "-fexceptions"
    ]
}

6.  HAL service 启动 rc文件

//vendor.tests.hardware.hello@1.0-service.rc
service vendor.tests.hardware.hello-1.0 /vendor/bin/hw/vendor.tests.hardware.hello@1.0-service
    class hal
    user system
    group system inet

7. selinux 标签修改

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

// file_contexs
/(vendor|system/vendor)/bin/hw/vendor.tests.hardware.hello@1.0-service           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 += \
    vendor.tests.hardware.hello@1.0 \
    vendor.tests.hardware.hello@1.0-impl \
    vendor.tests.hardware.hello@1.0-service \
    

三、client 实现

#define LOG_TAG "HelloClient"

#include <log/log.h>
#include <android/log.h>

#include <hidl/HidlSupport.h>
#include <hidl/Status.h>
#include <vendor/tests/hardware/hello/1.0/IHello.h>

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<IHello> helloService = IHello::getService();
    if (helloService == nullptr) {
        LOGE("can't not get IHello service!");
        return -1; 
    }
    
    Status status = FAILURE;
    std::vector<int8_t> readBuffer;
    helloService->get_data_char([&](Status st, std::vector<int8_t> data){
        status = st; readBuffer = data;
    });


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

}

四. 完整测试代码

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

  • 4
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值