Android hal
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