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;
}

验证方法

  1. 编译服务端:mmm vendor/test/led,确认生成vendor.led.hidl-service
  2. 推送并启动服务:adb push vendor.led.hidl-service /vendor/bin/hw/,执行adb shell /vendor/bin/hw/vendor.led.hidl-service
  3. 检查服务注册:adb shell lshal | grep vendor.test.led,应看到vendor.test.led@1.0::ILed/default
  4. 编译并运行客户端: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库路径正确
客户端进程 Client.cpp 应用逻辑 ILed::getService() HIDL代理 setState() / getState() Binder事务封装 Binder 驱动 进程间通信 数据序列化 权限校验 HIDL服务端进程 LedImpl(ILed实现) registerAsService("default") setState() 实现 write() 到设备节点 getState() 实现 read() 从设备节点 传统HAL层 /dev/virtual_led HIDL接口:vendor.test.led@1.0::ILed