2、Android系统架构与硬件抽象层:Android系统分层、HAL层的作用、HAL与内核驱动的关系、HIDL与AIDL简介

各位同学,咱们今天聊聊Android系统的骨架。说白了,就是搞清楚Android到底是怎么一层层搭起来的,以及我们做车载传感器驱动时,最常打交道的那个“中间人”——硬件抽象层(HAL)。

我刚开始接触Android BSP时,也觉得很懵。上层跑着Java,底层全是C代码,中间还夹着一堆.so库。后来做车载项目多了,才慢慢摸清门道。嗯,咱们今天就把它彻底理清楚。

2.1 Android系统分层:从应用到硬件的五层结构

Android系统不是铁板一块,它被分成了五层。你想想看,从你手指点一下屏幕,到传感器真正开始采集数据,中间要经过多少关卡?

这五层从上到下分别是:

  • 应用层(Application Layer):你手机上那些App,地图、音乐、车载HMI界面,都在这一层。它们用Java或Kotlin写,跑在ART虚拟机上。
  • 应用框架层(Application Framework Layer):这是给App开发者用的API。比如你想获取GPS位置,调一下LocationManager就行。框架层帮你封装好了。
  • 系统运行库层(Libraries & Android Runtime):这一层很关键。C/C++核心库(比如libc、libhardware)和ART虚拟机都在这里。我习惯把这一层看作是“承上启下”的枢纽。
  • 硬件抽象层(HAL Layer):这就是咱们今天的重点。它把底层硬件的差异给“抹平”了。上层不用管你是用的哪家芯片厂的传感器,只要调HAL接口就行。
  • Linux内核层(Linux Kernel Layer):真正的硬件驱动在这里。中断处理、DMA传输、寄存器读写,都是内核的事。

核心理解: 上层调用下层,下层为上层服务。但每一层都只跟相邻层打交道,不能越级。这就是分层设计的好处——解耦。

我在项目中遇到过一个问题:车载的陀螺仪数据总是延迟。查了半天,发现是应用层直接去读内核节点了,跳过了HAL层。这就是典型的“越级调用”,导致数据同步出了问题。所以,规矩就是规矩,别乱跳层。

2.2 HAL层的作用:为什么需要这个“中间人”?

你可能会问:既然内核已经有驱动了,为什么还要搞个HAL层?

原因很简单:内核驱动是GPL协议的。如果芯片厂商把传感器驱动直接放在内核里,那他们的核心算法就得开源。谁愿意?

HAL层的作用,说白了就是:

  • 屏蔽硬件差异:同一类传感器,不同厂商的寄存器配置可能完全不同。HAL层提供统一接口,上层不用关心底层细节。
  • 保护厂商知识产权:核心算法可以放在HAL层的.so库里,闭源发布。内核只做最基础的读写操作。
  • 支持热插拔与动态加载:HAL模块可以在系统运行时动态加载和卸载。这在车载多摄像头切换时特别有用。

避坑指南: 我曾经在调试一款激光雷达时,发现HAL层加载失败。后来排查发现是.so库的依赖没打全。记住,HAL层的库是运行在用户空间的,它的依赖链必须完整。用ldd命令检查一下,能省很多事。

2.3 HAL与内核驱动的关系:分工明确,各司其职

很多新手搞不清HAL和内核驱动的边界。我打个比方:

  • 内核驱动:像个“搬运工”。它只负责从硬件寄存器里把原始数据搬出来,或者把指令写进去。它不做数据处理,也不做算法。
  • HAL层:像个“加工厂”。它从内核拿到原始数据,然后进行校准、滤波、坐标变换,最后输出上层能用的标准数据。

举个例子,车载加速度传感器:

层级 职责 代码示例
内核驱动 读取寄存器,上报原始ADC值 input_report_abs(dev, ABS_X, raw_value);
HAL层 将ADC值转换为m/s²,做低通滤波 sensor->accel = raw_to_accel(raw) * filter_coeff;
框架层 提供SensorEventListener回调 onSensorChanged(SensorEvent event)

你看,内核只管“搬砖”,HAL负责“精加工”。我在做车载IMU(惯性测量单元)集成时,就遇到过内核上报的数据抖动很大。如果不在HAL层做滤波,上层拿到的数据根本没法用。所以,HAL层不是可有可无的,它是保证数据质量的关键环节。

2.4 HIDL与AIDL简介:接口定义语言

说到HAL,就绕不开HIDL和AIDL。这两个东西,说白了就是用来定义“接口”的。

2.4.1 AIDL:老牌选手

AIDL(Android Interface Definition Language)从Android诞生就有了。它主要用于同一进程或跨进程的Binder通信。在Android 8.0之前,HAL层和框架层通信,用的就是AIDL。

但AIDL有个问题:它跟Android框架层绑定太紧。如果你想单独升级HAL模块,往往需要跟着升级整个系统。这在车载这种需要长期维护的场景下,很痛苦。

// AIDL示例:定义传感器服务接口
interface ISensorService {
    boolean enableSensor(int sensorType);
    void disableSensor(int sensorType);
    SensorData readSensorData(int sensorType);
}

2.4.2 HIDL:后来居上

HIDL(HAL Interface Definition Language)是Android 8.0引入的。它的设计目标很明确:让HAL模块和框架层彻底解耦

HIDL最大的特点是:它定义的是“稳定的接口”。什么意思?就是HAL模块可以独立升级,只要接口不变,框架层不用动。这对车载系统来说太重要了。你想,车厂可能要用同一套系统适配不同年份的传感器,HIDL的稳定性就体现出来了。

// HIDL示例:定义加速度传感器HAL接口
package vendor.samsung.hardware.sensor@2.0;

interface IAccelerometer {
    getAccelerometerData() generates (vec3_t data);
    setAccelerometerConfig(AccelConfig config) generates (Result result);
};

注意: HIDL和AIDL不是互斥的。在Android 10之后,Google开始推动“HIDL转AIDL”的迁移。但核心思想没变:接口要稳定,模块要解耦。我个人习惯在新项目中直接用AIDL(稳定版),因为工具链更成熟,调试更方便。

我记得有一次,客户要求把一颗老款陀螺仪换成新款。因为HAL层用的是HIDL接口,我只需要重新实现HAL层的.so库,上层框架完全不用改。整个替换工作,我一个人两天就搞定了。这就是接口解耦带来的好处。

2.5 小结

今天咱们把Android系统架构的骨架理了一遍。从五层结构,到HAL层的定位,再到HIDL和AIDL的区别。你想想看,这些知识点不是孤立的,它们串起来就是一条完整的数据通路:

应用层 → 框架层 → HAL层 → 内核驱动 → 硬件

做车载传感器开发,你至少要知道:数据从哪来,经过谁处理,最后到哪去。下次遇到问题,你就能快速定位是哪个环节出了岔子。

下一章,咱们会深入HAL层的具体实现,手把手教你写一个传感器HAL模块。到时候,你会更深刻地理解今天讲的这些概念。