4. 使用HIDL封装HAL接口
任务目标
本案例将传统Android HAL接口封装为HIDL服务,实现客户端通过HIDL接口调用服务端HAL功能。以虚拟LED设备为例,完成HIDL接口定义、服务端实现、客户端调用的完整闭环。
环境与依赖
- Android 8.0+(HIDL正式支持版本)
- 需要hidl-gen工具(位于
out/host/linux-x86/bin/) - 目标包名:
vendor.test.led@1.0
HIDL接口定义
创建目录结构并生成HIDL接口。核心接口定义文件ILed.hal:
// vendor/test/led/1.0/ILed.hal
package vendor.test.led@1.0;
interface ILed {
enum LedState : int32_t {
OFF = 0,
ON = 1
};
setState(LedState state) generates (bool result);
getState() generates (LedState state);
};
使用hidl-gen生成接口代码:
hidl-gen -Landroid -rvendor.test.led:vendor/test/led \
-randroid.hidl:system/libhidl/transport \
vendor/test/led/1.0/ILed.hal
服务端实现
创建HIDL服务实现类,封装传统HAL操作:
// Led.cpp
#include <vendor/test/led/1.0/ILed.h>
#include <hidl/LegacySupport.h>
#include <fcntl.h>
#include <unistd.h>
using vendor::test::led::V1_0::ILed;
using vendor::test::led::V1_0::ILedState;
using android::hardware::Return;
using android::hardware::Void;
class LedImpl : public ILed {
private:
int fd_;
static constexpr const char* kDevicePath = "/dev/virtual_led";
public:
LedImpl() : fd_(-1) {
fd_ = open(kDevicePath, O_RDWR);
}
~LedImpl() override {
if (fd_ >= 0) close(fd_);
}
Return<bool> setState(ILed::LedState state) override {
if (fd_ < 0) return false;
uint8_t cmd = (state == ILed::LedState::ON) ? 1 : 0;
return write(fd_, &cmd, sizeof(cmd)) == sizeof(cmd);
}
Return<ILed::LedState> getState() override {
if (fd_ < 0) return ILed::LedState::OFF;
uint8_t buf = 0;
if (read(fd_, &buf, sizeof(buf)) != sizeof(buf)) {
return ILed::LedState::OFF;
}
return (buf == 1) ? ILed::LedState::ON : ILed::LedState::OFF;
}
};
int main() {
android::sp<ILed> service = new LedImpl();
android::status_t status = service->registerAsService("default");
return (status == android::OK) ? 0 : 1;
}
创建Android.bp构建配置:
cc_binary {
name: "vendor.led.hidl-service",
vendor: true,
relative_install_path: "hw",
srcs: ["Led.cpp"],
shared_libs: [
"libhidlbase",
"libhidltransport",
"liblog",
"libutils",
"vendor.test.led@1.0",
],
init_rc: ["led_service.rc"],
}
cc_library_shared {
name: "vendor.test.led@1.0",
vendor: true,
generated_headers: ["vendor.test.led@1.0_genc++_headers"],
shared_libs: ["libhidlbase", "libhidltransport", "libutils"],
}
创建led_service.rc启动脚本:
service led_hal_service /vendor/bin/hw/vendor.led.hidl-service
class hal
user root
group root
seclabel u:r:hal_led:s0
客户端调用
// Client.cpp
#include <vendor/test/led/1.0/ILed.h>
#include <android-base/logging.h>
using vendor::test::led::V1_0::ILed;
int main() {
android::sp<ILed> led = ILed::getService("default");
if (led == nullptr) {
LOG(ERROR) << "Failed to get LED HIDL service";
return -1;
}
// 调用setState
bool setResult = false;
led->setState(ILed::LedState::ON, [&](bool result) {
setResult = result;
});
LOG(INFO) << "Set state result: " << (setResult ? "success" : "failed");
// 调用getState
led->getState([&](ILed::LedState state) {
LOG(INFO) << "Current LED state: "
<< (state == ILed::LedState::ON ? "ON" : "OFF");
});
return 0;
}
验证方法
- 编译服务端:
mmm vendor/test/led,确认生成vendor.led.hidl-service - 推送并启动服务:
adb push vendor.led.hidl-service /vendor/bin/hw/,执行adb shell /vendor/bin/hw/vendor.led.hidl-service - 检查服务注册:
adb shell lshal | grep vendor.test.led,应看到vendor.test.led@1.0::ILed/default - 编译并运行客户端:
adb shell /data/local/tmp/led_client,观察日志输出
通过条件:客户端日志显示Set state result: success且Current LED state: ON,同时lshal能列出服务,即表示HIDL封装通信成功。
常见问题
- 服务注册失败:检查SELinux策略,确认
hal_led域允许注册HIDL服务 - 客户端无法获取服务:确认服务端已启动且设备节点
/dev/virtual_led存在 - hidl-gen生成失败:确认接口包名与目录结构一致,且依赖的
android.hidl库路径正确