Android 14 Binderized HAL开发实战指南(AIDL版)
环境要求
- Android 14源码编译环境
- AOSP
android-14.0.0_r7
分支 - Soong build系统
- Java 17 & NDK r25c
项目结构
hardware/interfaces/myservice/
├── 1.0
│ ├── IMyHalService.aidl
│ └── Android.bp
├── impl
│ ├── MyHalService.cpp
│ ├── service.cpp
│ └── Android.bp
└── sepolicy└── myservice.te
完整实现步骤
1. 定义AIDL接口
// hardware/interfaces/myservice/1.0/IMyHalService.aidl
package android.hardware.myservice@1.0;@Backing(type="int")
enum ErrorCode {OK,DEVICE_BUSY,INVALID_PARAM
}interface IMyHalService {@nullableString getHardwareId();@error(ErrorCode)int sendControlCommand(in int cmdId, in byte[] payload);oneway void registerCallback(in ICallback callback);oneway void unregisterCallback(in ICallback callback);
}interface ICallback {oneway void onEvent(int eventId, in byte[] data);
}
2. 实现HAL服务
#include <android/binder_ibinder.h>
#include <aidl/android/hardware/myservice/BnMyHalService.h>using namespace aidl::android::hardware::myservice;class MyHalService : public BnMyHalService {
public:ndk::ScopedAStatus getHardwareId(std::string* _aidl_return) override {*_aidl_return = "MY_HAL_1.0";return ndk::ScopedAStatus::ok();}ndk::ScopedAStatus sendControlCommand(int cmdId, const std::vector<uint8_t>& payload, int* _aidl_return) override {if (cmdId < 0 || cmdId > 255) {*_aidl_return = static_cast<int>(ErrorCode::INVALID_PARAM);return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);}*_aidl_return = static_cast<int>(ErrorCode::OK);return ndk::ScopedAStatus::ok();}ndk::ScopedAStatus registerCallback(const std::shared_ptr<ICallback>& callback) override {std::lock_guard<std::mutex> lock(mMutex);mCallbacks.insert(callback);return ndk::ScopedAStatus::ok();}ndk::ScopedAStatus unregisterCallback(const std::shared_ptr<ICallback>& callback) override {std::lock_guard<std::mutex> lock(mMutex);mCallbacks.erase(callback);return ndk::ScopedAStatus::ok();}private:std::mutex mMutex;std::unordered_set<std::shared_ptr<ICallback>> mCallbacks;
};
3. 服务入口实现
#include <binder/ProcessState.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>using aidl::android::hardware::myservice::MyHalService;int main() {ABinderProcess_setThreadPoolMaxThreadCount(4);std::shared_ptr<MyHalService> service = ndk::SharedRefBase::make<MyHalService>();const std::string instance = std::string() + IMyHalService::descriptor + "/default";binder_status_t status = AServiceManager_addService(service->asBinder().get(), instance.c_str());if (status != STATUS_OK) {ALOGE("Failed to register service");return 1;}ABinderProcess_joinThreadPool();return 0;
}
构建配置
接口层配置
// hardware/interfaces/myservice/1.0/Android.bp
aidl_interface {name: "android.hardware.myservice.IMyHalService",srcs: ["IMyHalService.aidl"],stability: "vintf",backend: {cpp: {enabled: true,},java: {enabled: false,},},versions: ["1"],
}
实现层配置
// hardware/interfaces/myservice/impl/Android.bp
cc_library_shared {name: "android.hardware.myservice-service",srcs: ["MyHalService.cpp","service.cpp",],shared_libs: ["android.hardware.myservice.IMyHalService","libbinder_ndk","libbase","liblog",],cflags: ["-Wall","-Werror",],
}cc_binary {name: "android.hardware.myservice@1.0-service",relative_install_path: "hw",vendor: true,init_rc: ["myservice.rc"],srcs: [":android.hardware.myservice-service"],shared_libs: ["android.hardware.myservice.IMyHalService","libbinder_ndk","libbase","liblog",],
}
SELinux配置
//myservice.te
type myservice_hwservice, hwservice_manager_type;
type myservice_default, domain;# HAL服务权限
allow myservice_default hwservicemanager:binder { call transfer };
allow myservice_default hwservicemanager:service_manager add;# 客户端权限
allow hal_client_domain myservice_hwservice:hwservice_manager { find };
VINTF配置
<hal format="aidl"><name>android.hardware.myservice</name><version>1.0</version><interface><name>IMyHalService</name><instance>default</instance></interface>
</hal>
客户端调用示例
// 在SystemServer中获取服务IMyHalService service = IMyHalService.Stub.asInterface(ServiceManager.waitForService("android.hardware.myservice.IMyHalService/default"));// 发送控制命令
byte[] payload = new byte[]{0x01, 0x02};
int result = service.sendControlCommand(0x20, payload);// 注册回调
service.registerCallback(new ICallback.Stub() {@Overridepublic void onEvent(int eventId, byte[] data) {// 处理硬件事件}
});