本文旨在实现一个 android O 上简单的 HAL 库,并用 C++ 实现一个客户端的测试程序。
如果按照以下步骤依次创建并编辑相关文件的话,相信最终来完成这个测试应该是没有什么问题的。
首先在 hardware/interfaces 下新建 hidldebug 文件夹,进入该文件夹,
来吧,一起从"0"开始,先来看一下最终的目录结构:
1 . 2 ├── 1.0 3 │ ├── Android.bp 4 │ ├── Android.mk 5 │ ├── default 6 │ │ ├── Android.bp 7 │ │ ├── Hidldebug.cpp 8 │ │ ├── Hidldebug.h 9 │ │ └── service.cpp 10 │ ├── hidldebug_test 11 │ │ ├── Android.bp 12 │ │ └── client.cpp 13 │ └── IHidldebug.hal 14 └── Android.bp
当然,你的目录是现在空的,别急,我们一步一步进行,接下来会依次创建每一个文件,
请紧跟操作步骤,缺少的文件夹要自己补充啊。
一、服务端实现
① 创建 .hal 文件 [ IHidldebug.hal ]:
1 IHidldebug.hal 2 3 package android.hardware.hidldebug@1.0; 4 5 interface IHidldebug { 6 helloWorld(string name) generates (string result); 7 };
② 生成相应的 .cpp 及 .h 文件:
1 PACKAGE=android.hardware.hidldebug@1.0 2 3 LOC=hardware/interfaces/hidldebug/1.0/default/ 4 5 out/host/linux-x86/bin/hidl-gen -o $LOC -Lc++-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport $PACKAGE
③ 修改文件内容并加入函数的实现 [ Hidldebug.cpp ]:
1 #include "Hidldebug.h" 2 3 namespace android { 4 namespace hardware { 5 namespace hidldebug { 6 namespace V1_0 { 7 namespace implementation { 8 9 // Methods from ::android::hardware::hidldebug::V1_0::IHidldebug follow. 10 Return<void> Hidldebug::helloWorld(const hidl_string& name, helloWorld_cb _hidl_cb) { 11 // TODO implement 12 char buf[100]; 13 ::memset(buf, 0x00, 100); 14 ::snprintf(buf, 100, "[Test Routine] Hello, %s", name.c_str()); 15 hidl_string result(buf); 16 17 _hidl_cb(result); 18 return Void(); 19 } 20 21 22 // Methods from ::android::hidl::base::V1_0::IBase follow. 23 24 //IHidldebug* HIDL_FETCH_IHidldebug(const char* /* name */) { 25 // return new Hidldebug(); 26 //} 27 28 } // namespace implementation 29 } // namespace V1_0 30 } // namespace hidldebug 31 } // namespace hardware 32 } // namespace android
④ 头文件基本不变 [ Hidldebug.h ]:
1 #ifndef ANDROID_HARDWARE_HIDLDEBUG_V1_0_HIDLDEBUG_H 2 #define ANDROID_HARDWARE_HIDLDEBUG_V1_0_HIDLDEBUG_H 3 4 #include <android/hardware/hidldebug/1.0/IHidldebug.h> 5 #include <hidl/MQDescriptor.h> 6 #include <hidl/Status.h> 7 8 namespace android { 9 namespace hardware { 10 namespace hidldebug { 11 namespace V1_0 { 12 namespace implementation { 13 14 using ::android::hardware::hidldebug::V1_0::IHidldebug; 15 using ::android::hidl::base::V1_0::DebugInfo; 16 using ::android::hidl::base::V1_0::IBase; 17 using ::android::hardware::hidl_array; 18 using ::android::hardware::hidl_memory; 19 using ::android::hardware::hidl_string; 20 using ::android::hardware::hidl_vec; 21 using ::android::hardware::Return; 22 using ::android::hardware::Void; 23 using ::android::sp; 24 25 struct Hidldebug : public IHidldebug { 26 // Methods from ::android::hardware::hidldebug::V1_0::IHidldebug follow. 27 Return<void> helloWorld(const hidl_string& name, helloWorld_cb _hidl_cb) override; 28 29 // Methods from ::android::hidl::base::V1_0::IBase follow. 30 31 }; 32 33 //extern "C" IHidldebug* HIDL_FETCH_IHidldebug(const char* name); 34 35 } // namespace implementation 36 } // namespace V1_0 37 } // namespace hidldebug 38 } // namespace hardware 39 } // namespace android 40 41 #endif // ANDROID_HARDWARE_HIDLDEBUG_V1_0_HIDLDEBUG_H
⑤ 创建 service.cpp:
1 touch hardware/interfaces/hidldebug/1.0/default/service.cpp
⑥ 在 service.cpp 文件中以下内容 [ service.cpp ]:
1 #define LOG_TAG "android.hardware.hidldebug@1.0-service" 2 3 #include <hidl/HidlSupport.h> 4 #include <hidl/HidlTransportSupport.h> 5 6 #include "Hidldebug.h" 7 8 using ::android::hardware::configureRpcThreadpool; 9 using ::android::hardware::hidldebug::V1_0::IHidldebug; 10 using ::android::hardware::hidldebug::V1_0::implementation::Hidldebug; 11 using ::android::hardware::joinRpcThreadpool; 12 using ::android::OK; 13 using ::android::sp; 14 15 int main(int /* argc */, char* /* argv */ []) { 16 sp<IHidldebug> hidldebug = new Hidldebug; 17 configureRpcThreadpool(1, true /* will join */); 18 if (hidldebug->registerAsService() != OK) { 19 ALOGE("Could not register service."); 20 return 1; 21 } 22 joinRpcThreadpool(); 23 24 ALOGE("Service exited!"); 25 return 1; 26 }
⑦ 创建 android.hardware.hidldebug@1.0-service.rc 文件并填入以下内容:
1 service hidldebug_hal_service /vendor/bin/hw/android.hardware.hidldebug@1.0-service 2 class hal 3 user root 4 group root
⑧ 创建服务端的 Android.bp 编译脚本并填入以下内容:
1 cc_binary { 2 name: "android.hardware.hidldebug@1.0-service", 3 relative_install_path: "hw", 4 vendor: true, 5 srcs: [ 6 "Hidldebug.cpp", 7 "service.cpp" 8 ], 9 init_rc: ["android.hardware.hidldebug@1.0-service.rc"], 10 shared_libs: [ 11 "liblog", 12 "libhidlbase", 13 "libhidltransport", 14 "libutils", 15 "libhardware", 16 "android.hardware.hidldebug@1.0", 17 ], 18 }
二、客户端实现
① 客户端代码实现 [ client.cpp ]:
1 # include <android/hardware/hidldebug/1.0/IHidldebug.h> 2 # include <hidl/Status.h> 3 # include <hidl/LegacySupport.h> 4 # include <utils/misc.h> 5 # include <hidl/HidlSupport.h> 6 # include <stdio.h> 7 8 using android::hardware::hidldebug::V1_0::IHidldebug; 9 using android::sp; 10 using android::hardware::hidl_string; 11 12 int main() 13 { 14 int ret; 15 16 android::sp<IHidldebug> service = IHidldebug::getService(); 17 if(service == nullptr) { 18 printf("Failed to get service "); 19 return -1; 20 } 21 22 service->helloWorld("Zackary.Liu", [&](hidl_string result) { 23 printf("%s ", result.c_str()); 24 }); 25 26 return 0; 27 }
② 客户端的编译脚本内容 [ Android.bp ]:
1 cc_binary { 2 name: "hidldebug_test", 3 vendor: true, 4 srcs: [ 5 "client.cpp", 6 ], 7 shared_libs: [ 8 "liblog", 9 "libhidlbase", 10 "libutils", 11 "android.hardware.hidldebug@1.0", 12 ], 13 }
三、编译所有文件
① 执行更新脚本,让系统帮我们创建其它需要的脚本文件:
1 hardware/interfaces/update-makefiles.sh
② 比对一下最终的文件结构是否和开篇时说的一样
③ 进行最终的编译:
1 mmm hardware/interfaces/hidldebug/
④ 如果编译成功,将会产出以下的库和可执行文件:
1 system/lib64/android.hardware.hidldebug@1.0.so 2 vendor/bin/hw/android.hardware.hidldebug@1.0-service 3 vendor/etc/init/android.hardware.hidldebug@1.0-service.rc 4 vendor/bin/hidldebug_test
四、运行测试
1 / # vendor/bin/hw/android.hardware.hidldebug@1.0-service & 2 / # hidldebug_test 3 [Test Routine] Hello, Zackary.Liu
执行完成,成功调用到我们在服务端实现的函数,拼接了客户端输入的字符串并将其打印出来。
目前只是完成在 hal 层的一个测试,接下来还需要了解下 APP 层的调用流程,并实现一个直接的客户端再来进行测试。