新手必看!Android Light HAL开发实战(Rockchip 15 AIDL版)

电子说

1.4w人已加入

描述

Android底层开发的同学,肯定绕不开灯光控制”——手机屏幕背光、按键灯、呼吸灯,这些功能的底层实现都依赖Light HAL。今天就以Rockchip(瑞芯微)Android 15平台为例,用最通俗的语言拆解Light HAL的核心逻辑,新手也能看懂!

 

 

一、先搞懂:什么是Light HAL

 

 

在开始看代码前,先理清3个核心概念,避免越看越懵:

 

 

1. HAL是什么?

 

 

HAL(硬件抽象层)是Android系统“Framework硬件驱动之间的桥梁。Framework层负责上层逻辑(比如APP调亮屏幕),驱动负责直接操作硬件,HAL则把驱动接口封装成标准形式,让Framework不用关心不同厂商的硬件差异。

 

 

2. Light HAL的作用?

 

 

专门负责灯光类硬件的控制,比如:

 

 

屏幕背光(BACKLIGHT)的亮度调节;

 

 

按键灯(BUTTONS)的开关;

 

 

通知灯(NOTIFICATIONS)的呼吸/常亮效果;

 

 

电池灯(BATTERY)的颜色/闪烁控制。

 

 

3. AIDLHAL

 

 

Android 10+后,HAL逐渐从旧的HIDL迁移到AIDLAndroid接口定义语言),核心是用Binder通信,让HAL服务以进程形式运行,更稳定、权限控制更清晰。

 

 

二、核心代码拆解:Rockchip Light HAL文件全解析

 

 

瑞芯微的Light HAL代码都在light_aidl目录下,核心文件就5个,我们逐个讲清楚作用:

 

 

1. 头文件:Lights.h(定义骨架

 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
// 关键代码片段class BacklightPath {public:    int physic_id;       // 显示屏物理ID(多屏场景用)    char backlight_path[128]; // 背光驱动的sysfs路径};class Lights : public BnLights {    // Framework调用的核心接口:设置灯光状态(比如调亮度)    ndk::ScopedAStatus setLightState(int id, const HwLightState& state) override;    // Framework调用的核心接口:获取设备支持的灯光类型    ndk::ScopedAStatus getLights(std::vector* types) override;private:    // 辅助函数:添加支持的灯光类型(比如“背光”“按键灯”)    void addLight(int const ordinal, LightType const type);    // 存储支持的灯光列表    std::vector _lights;    // 存储多屏背光的路径(瑞芯微多屏方案的核心)    std::vector _backlights;};

新手理解:这个文件就像设计图,定义了两个核心:

 

 

BacklightPath:解决多屏设备的背光路径问题(比如平板/工控机有多个屏幕);

 

 

Lights类:实现了Android标准的BnLights接口,对外暴露设置灯光获取灯光两个核心方法,是整个HAL的骨架。

 

 

2. 实现文件:Lights.cpp(填充血肉

 

 

这是核心逻辑文件,所有灯光控制的实际操作都在这里,新手重点看3个核心函数:

 

 

1getDriverPath:定义灯光的驱动路径

 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
const chargetDriverPath(LightType type) {    switch (type) {        case LightType:            return "/sys/class/backlight/backlight/brightness"// 背光驱动路径        case LightType:            return "/sys/class/leds/button-backlight/brightness"// 按键灯路径        // 通知灯/电池灯等指向LED驱动目录        case LightType:        case LightType:            return "/sys/class/leds";        default:            return "/not_supported";    }}

新手理解Android控制硬件的核心是操作sysfs(虚拟文件系统),比如想调背光,本质就是往/sys/class/backlight/backlight/brightness文件里写数字(0-255),这个函数就是给不同灯光找对应的文件路径

 

 

2write_int:往驱动文件写值(操作硬件)

 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
static int write_int(const char* path, int value) {    int fd = open(path, O_RDWR); // 打开驱动文件    if (fd >= 0) {        char buf[20];        snprintf(buf, sizeof(buf), "%dn", value); // 把亮度值转成字符串        write(fd, buf, strlen(buf)); // 写入文件(真正调亮度的操作)        close(fd);        return 0;    } else {        ALOGE("打开文件失败:%s"strerror(errno));        return -errno;    }}

新手理解:这是最底层的硬件操作函数,比如Framework要求把背光调到100”,最终就是这个函数往背光路径里写“100”,驱动收到后就会调屏幕亮度。

 

 

3setLightState:处理Framework的调用请求

 

 

  •  
  •  
  •  
  •  
  •  
  •  
ndk::ScopedAStatus Lights::setLightState(int id, const HwLightState& state) {    // 1. 根据id找到对应的灯光类型(比如是背光还是按键灯)    // 2. 找到该灯光的驱动路径    // 3. 调用setLightFromType,最终调用write_int写值到驱动    // 4. 返回操作结果(成功/失败)}

新手理解Framework层调用Light HAL时,直接调用这个函数,它是上层请求底层操作的中转站。

 

 

3. 入口文件:main.cpp(启动HAL服务)

 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
int main() {    // 1. 初始化Binder线程池(AIDL通信的基础)    ABinderProcess_setThreadPoolMaxThreadCount(0);    // 2. 创建Lights实例(真正处理灯光逻辑的对象)    std::shared_ptr<Lights> lights = ndk::SharedRefBase::make();    // 3. 把HAL服务注册到系统的ServiceManagerFramework能找到这个服务)    const std::string instance = std::string() + Lights::descriptor + "/default";    AServiceManager_addService(lights->asBinder().get(), instance.c_str());    // 4. 进入线程池,等待Framework的调用(常驻进程)    ABinderProcess_joinThreadPool();    return EXIT_FAILURE;}

新手理解:这个文件是HAL服务的启动入口,就像你开餐馆,main.cpp就是开门营业的操作:

 

 

初始化通信(Binder线程池);

 

 

准备好厨师(Lights实例);

 

 

告诉顾客(Framework我在这营业(注册服务);

 

 

坐等顾客下单(等待Framework调用)。

 

 

4. 配置文件:lights-rockchip.xml(声明HAL服务)

 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
<manifest version="1.0" type="device">    <hal format="aidl">        <name>android.hardware.lightname>        <version>2version>        <fqname>ILights/defaultfqname>    hal>manifest>

新手理解:这个文件是给系统看的说明书,告诉Android系统:我是Light HAL服务,版本是2,接口名是ILights/default”,系统会通过这个文件校验HAL的兼容性,确保Framework能正确调用。

 

 

5. 启动配置:lights-rockchip.rc(系统启动HAL

 

 

  •  
  •  
  •  
  •  
  •  
service vendor.light-rockchip /vendor/bin/hw/android.hardware.lights-service.rockchip    class hal    user system    group system    shutdown critical

新手理解Android开机后,init进程会扫描这个文件,然后自动启动Light HAL服务:

 

 

class hal:属于HAL类服务,系统启动时会批量启动;

 

 

user system:以system用户运行(保证能读写驱动文件);

 

 

shutdown critical:关键服务,崩溃会重启,关机要等它退出。

 

 

Light HAL服务完整启动流程图

用流程图直观展示系统开机后,HAL服务如何启动,一看就懂:

 

 

 

 

 

Rockchip

三、整体运行流程:从调亮度硬件响应

 

 

新手最容易懵的是代码怎么串起来的,用调屏幕亮度举例子,先看流程图,再看步骤:

 

 

 

 

 

Rockchip

对应流程图,完整流程拆解(7步):

 

 

1.系统开机init进程扫描lights-rockchip.rc,启动android.hardware.lights-service.rockchip可执行文件;

 

 

2.启动HAL服务:执行main.cpp,创建Lights实例,注册服务到ServiceManager,等待调用;

 

 

3.上层发起请求:比如设置里调亮度,Framework层找到“ILights/default”服务,调用setLightState

 

 

4.HAL处理请求setLightState根据灯光id找到背光驱动路径;

 

 

5.底层操作:调用write_int/sys/class/backlight/backlight/brightness写亮度值;

 

 

6.驱动响应:内核驱动收到文件写入操作,控制屏幕背光硬件调亮度;

 

 

7.返回结果HAL把操作结果返回给Framework,整个流程结束。

 

 

四、避坑指南

1.路径错误:驱动路径写错(比如多屏场景背光路径不对),会导致调亮度没反应,重点查getDriverPathdisplay_settings.xml

 

 

2.权限问题HAL服务运行用户不是system,会导致打不开驱动文件,查lights-rockchip.rcuser/group

 

 

3.接口兼容lights-rockchip.xml的版本和接口名不对,Framework找不到服务,重点核对name/version/fqname

 

 

4.多屏场景:瑞芯微多屏设备要注意BacklightPath的物理ID,否则只会调其中一个屏幕。

 

 

五、总结

 

 

Rockchip Light HAL的核心逻辑其实很简单:

 

 

Lights.h定义接口骨架;

 

 

Lights.cpp实现硬件操作逻辑;

 

 

main.cpp启动并注册HAL服务;

 

 

rc/xml配置服务启动和系统识别;

 

 

本质是Framework的请求转成往sysfs文件写值

 

 

对新手来说,先搞懂“sysfs操作硬件这个核心,再顺着“Framework→HAL→驱动的链路看代码,就不会乱。建议先改改背光路径、调个亮度值,动手比只看代码更易理解!

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分