行业知识
Android12 AIDL native层实现
本文主要是讲解如何实现一个完整的AIDL HAL层的例子,包括aidl文件的编写、service的实现、测试用例的实现、开机启动以及编译过程中和运行时的错误如何解决。此文不讲解AIDL的原理,具体原理的了解请参考官方资料:https://source.android.com/docs/core/architecture/aidl?hl=zh-cn
生成中间库
创建code路径:vendor/xxxx/proprietary/hardware/interfaces/helloworld
在上面的目录下创建子路径:aidl/vendor/hardware/helloworld
创建Android.bp和IHelloWorld.aidl,文件位置如下:
1.vendor/xxxx/proprietary/hardware/interfaces/helloworld$ tree 2.. 3.└── aidl 4. ├── Android.bp 5. └── vendor 6. └── hardware 7. └── helloworld 8. └── IHelloWorld.aidl
Android.bp内容:
1.aidl_interface { 2. name: "vendor.hardware.helloworld", 3. vendor_available: true, 4. srcs: ["vendor/hardware/ helloworld /*.aidl"], 5. stability: "vintf", 6. owner: "yezhiqiang", 7. backend: { 8. java: { 9. enabled: true, 10. platform_apis: true, 11. }, 12. ndk: { 13. enabled: true, 14. }, 15. cpp: { 16. enabled: true, 17. }, 18. }, 19.} IHelloWorld.aidl内容:
1.package vendor.hardware.helloworld; 2. 3.@VintfStability 4.interface IHelloWorld { 5. void sayWhat(String what); 6.} 尝试编译:mmm vendor/xxxx/proprietary/hardware/interfaces/helloworld/aidl/
发生错误如下:
FAILED: out/soong/.intermediates/vendor/xxxx/proprietary/hardware/interfaces/helloworld/aidl/vendor.hardware.helloworld-api/checkapi_current.timestamp echo "API dump for the current version of AIDL interface vendor.hardware.helloworld does not exist." && echo Run "m vendor.hardware.helloworld-update-api", or add "unstable: true" to the build rule for the interface if it does not need to be versioned && false # hash of input list: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 API dump for the current version of AIDL interface vendor.hardware.helloworld does not exist. Run m vendor.hardware.helloworld-update-api, or add unstable: true to the build rule for the interface if it does not need to be versioned
虽然出错,但此时已经在out目录下创建了部分目录:
1.//out/soong/.intermediates/vendor/xxxx/proprietary/hardware/interfaces/helloworld/aidl/ 2.vendor.hardware.helloworld-api/ 3.vendor.hardware.helloworld-V1-java/
根据提示,需要执行命令:m vendor.hardware.helloworld-update-api
成功时打印如下信息:
[100% 13/13] //vendor/xxxx/proprietary/hardware/interfaces/helloworld/aidl:vendor.hardware.helloworld-api Making AIDL API of vendor.hardware.helloworld as version c
此时,会在aidl_api/vendor.hardware.helloworld/目录下生成current及其内部的内容。
回过头来,再次执行:
mmm vendor/xxxx/proprietary/hardware/interfaces/helloworld/aidl/,编译成功。
此时发现out目录下生成了很多目录:
那么执行到这一步,其实在out目录下已经生成了binder的各种类型的源文件以及各种IBinder库了。
编写services
创建default目录及相应服务程序,文件列表如下:
vendor/xxxx/proprietary/hardware/interfaces/helloworld/aidl/default$ tree . ├── Android.bp ├── HelloWorld.cpp ├── HelloWorld.h ├── service.cpp ├── vendor.hardware.helloworld-service.rc └── vendor.hardware.helloworld-service.xml
Android.bp内容:
1.cc_binary { 2. name: "vendor.hardware.helloworld-service", 3. relative_install_path: "hw", 4. init_rc: ["vendor.hardware.helloworld-service.rc"], 5. vintf_fragments: ["vendor.hardware.helloworld-service.xml"], 6. vendor: true, 7. srcs: [ 8. "service.cpp", 9. "HelloWorld.cpp", 10. ], 11. shared_libs: [ 12. "vendor.hardware.helloworld-V1-ndk_platform", 13. "liblog", 14. "libbase", 15. "libbinder_ndk", 16. ], 17.} HelloWorld.h内容:
1.#pragma once 2. 3.#include 4. 5.namespace aidl { 6.namespace vendor { 7.namespace hardware { 8.namespace helloworld { 9.class HelloWorld : public BnHelloWorld { 10.public: 11. HelloWorld() = default; 12. 13. ::ndk::ScopedAStatus sayWhat(const std::string& in_what); 14.}; 15. 16. 17.} // namespace helloworld 18.} // namespace hardware 19.} // namespace vendor 20.} // namespace aidl HelloWorld.cpp内容:
1.#include "HelloWorld.h" 2.#include 3.#include 4. 5.namespace aidl { 6.namespace vendor { 7.namespace hardware { 8.namespace helloworld { 9. 10.::ndk::ScopedAStatus HelloWorld::sayWhat(const std::string& in_what) { 11. ALOGI("client say:%s.", in_what.c_str());12.13. return ::ndk::ScopedAStatus::ok();14.} 15. 16.} // namespace helloworld 17.} // namespace hardware 18.} // namespace vendor 19.} // namespace aidl service.cpp内容:
1.#include 2.#include 3.#include 4. 5.#include "HelloWorld.h" 6. 7.using ::aidl::vendor::hardware::helloworld::HelloWorld; 8. 9.int main() { 10. ABinderProcess_setThreadPoolMaxThreadCount(0); 11. std::shared_ptr hello = ndk::SharedRefBase::make(); 12. 13. const std::string instance = std::string() + HelloWorld::descriptor + "/default"; 14. binder_status_t status = AServiceManager_addService(hello->asBinder().get(), instance.c_str()); 15. CHECK(status == STATUS_OK); 16. 17. ABinderProcess_joinThreadPool(); 18. return -1; // Should never be reached 19.} vendor.hardware.helloworld-service.rc内容:
1.service vendor_helloworld_default /vendor/bin/hw/vendor.hardware.helloworld-service 2. class hal 3. user root 4. group root
vendor.hardware.helloworld-service.xml内容:
1. 2. 3. vendor.hardware.helloworld 4. 1 5. 6. IHelloWorld 7. default 8. 9. 10.
解决启动问题
验证service能否正常启动,将如下文件分别push入系统:
1.//push to vendor/lib/ 2.vendor.hardware.helloworld-V1-ndk_platform.so 3.//push to vendor/etc/vintf/manifest 4.vendor.hardware.helloworld-service.xml 5.//push to vendor/etc/init/ 6.vendor.hardware.helloworld-service.rc 7.//push to vendor/bin/hw/ 8.vendor.hardware.helloworld-service
手动执行./vendor/bin/hw/vendor.hardware.helloworld-service,报错如下:
1.05-16 10:10:34.484 208 208 E servicemanager: Could not find vendor.hardware.hw.IHelloWorld/default in the VINTF manifest. 2.05-16 10:10:34.484 4696 4696 F vendor.hardware.helloworld-service: Check failed: status == STATUS_OK 3.--------- beginning of crash 4.05-16 10:10:34.484 4696 4696 F libc : Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 4696 (vendor.hardware), pid 4696 (vendor.hardware) 5.05-16 10:10:34.500 4701 4701 I crash_dump32: obtaining output fd from tombstoned, type: kDebuggerdTombstoneProto 6.05-16 10:10:34.501 258 258 I tombstoned: received crash request for pid 4696 7.05-16 10:10:34.501 4701 4701 I crash_dump32: performing dump of process 4696 (target tid = 4696) 8.05-16 10:10:34.520 4701 4701 F DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 9.05-16 10:10:34.520 4701 4701 F DEBUG : Build fingerprint: 'Xxxxx/xx_evb_xxxx/xx_evb_xxxx:12/SQ1D.220205.004/eng.E00023.20240314.110003:userdebug/release-keys' 10.05-16 10:10:34.520 4701 4701 F DEBUG : Revision: '0' 11.05-16 10:10:34.520 4701 4701 F DEBUG : ABI: 'arm' 12.05-16 10:10:34.520 4701 4701 F DEBUG : Timestamp: 2024-05-16 10:10:34.503272142+0800 13.05-16 10:10:34.521 4701 4701 F DEBUG : Process uptime: 0s 14.05-16 10:10:34.521 4701 4701 F DEBUG : Cmdline: ./vendor.hardware.helloworld-service 15.05-16 10:10:34.521 4701 4701 F DEBUG : pid: 4696, tid: 4696, name: vendor.hardware >>> ./vendor.hardware.helloworld-service 2.