2026/5/21 18:12:39
网站建设
项目流程
网站建设的软件介绍,怎样建立自己的公众号,郑州中森网站建设,东莞网站建设相关技术先把结论说在前面#xff1a;在 Android 里#xff0c;HAL#xff08;Hardware Abstraction Layer#xff0c;硬件抽象层#xff09;
就是夹在 系统框架#xff08;Framework#xff09; 和 具体硬件/驱动 中间的那层“翻译 适配 封装”。你可以把 HAL 想象成#xf…先把结论说在前面在 Android 里HALHardware Abstraction Layer硬件抽象层就是夹在系统框架Framework和具体硬件/驱动中间的那层“翻译 适配 封装”。你可以把 HAL 想象成一个会双语的“翻译官”上面懂 Android 规定的“官方术语”下面懂自家摄像头、音频芯片、传感器那一套“土话”所有上层想用硬件的需求都必须先跟它打交道。这篇文章就用大白话从几个角度讲清楚 HALHAL 存在的意义为什么非要搞这么一层HAL 在整个 Android 架构里的位置和内核、驱动、Framework、App 的关系HAL 的主要职责可以拆成哪几块具体举几个典型例子音频 HALAudio HAL摄像头 HALCamera HAL传感器 HALSensor HAL显示 / 指纹等简单看一眼HAL 的实现大致流程从接口定义到 C/C 实现到被系统加载调用Project Treble 后新一代 HALHIDL / AIDL的变化一、先占个位HAL 在 Android 体系里到底在哪儿先用一段通俗的“楼房模型”帮你把 HAL 放在脑子里最底层硬件 Linux 内核驱动CPU、GPU、摄像头、音频芯片、传感器、指纹头……各种内核 Drivercamera driver、audio driver、input driver 等往上一层HAL硬件抽象层一堆用 C/C 写的模块camera HAL、audio HAL、sensor HAL…它只认“Android 规定的统一接口”不直接暴露厂商驱动细节给上层再往上Native Framework / System ServicesCameraService、AudioFlinger、SensorService 等这些是系统服务进程里的 C/Java 混合部分主要通过 Binder 和 App 交互再上一层Java/Kotlin Framework API Apps开发者使用的 Camera API、MediaRecorder、AudioTrack、SensorManager 等普通 App从来没见过 HAL 长啥样只知道有个系统服务给它能力如果把 Android 比作一家大公司硬件 驱动搬砖干活的一线工人不会说人话只懂寄存器和 IO。HAL懂技术的中层经理一边会跟工人沟通一边会跟老板/产品聊需求。Framework 服务高层部门摄像头部、音频部、传感器部制定统一流程和对外接口。App外部客户通过前台系统 API提交需求底下整套组织帮他干完。关键点App 不会直接碰 HALHAL 也不会直接和 App 聊天它只跟“系统服务 / Native 框架”说话。二、HAL 存在的意义为啥要多整这一层直觉上的问题很自然“既然有驱动了系统服务直接调内核驱动不行吗为啥中间又加一层 HAL看起来很啰嗦啊”你可以从三方面来理解解耦、兼容、统一接口。2.1 解耦让“Android 系统”和“具体硬件实现”分手不加 HAL 会怎样CameraService 直接调用某家厂商摄像头驱动提供的 ioctl、sysfs、设备节点。AudioFlinger 直接操作某家音频芯片的寄存器地址。结果是Framework 一改驱动也得改换个芯片厂整个系统的服务代码要重写一半这对“要跑在各种硬件上”的 Android 来说很致命。加了 HAL 之后变成Google 规定一套统一的 HAL 接口标准只要硬件厂按这套接口标准写一层 C/C 模块上层 CameraService/AudioFlinger/其他服务就不用改。换芯片只要厂商提供新的 HAL 实现接口不变上层 Android 基本不用动。这就相当于“标准电源插座 转换头”的思路上层只认“插头形状”具体里面是 220V 还是转了 110V、是国标还是美标全由转换头HAL搞定。2.2 兼容控制 Android 碎片化Android 当年最大的问题之一就是碎片化。各家的 ROM、自带系统服务、一堆私有接口大杂烩。Google 想统一升级很难底下驱动是厂商的私有实现上层 Framework 是 Google 控制的中间没有清晰边界就难以统一升级。HAL 的出现和标准化其实是在做一件事明确“系统上层”和“供应商底层”的分界线上面我管下面你们玩但是中间的接口必须听我的。这在后来 Project Treble 里表现得更彻底系统分为System Image和Vendor ImageHAL 接口被进一步规范成 HIDL/AIDL 模型系统升级可以不动 vendor 分区减少升级成本2.3 统一接口把五花八门的硬件能力整理成“一套 API”比如摄像头有的设备只有一个后摄像头有的有前后双摄、广角 长焦有的还有 TOF、红外、夜视模块如果没有 HAL 标准各家 CameraService 要支持这些功能写法会乱成一锅粥每家厂商一套 API调用方式千奇百怪系统服务为了兼容所有厂商代码变得极其复杂也根本没法对外提供统一 Camera API。有 HAL 之后Google 可以规定摄像头 HAL 必须实现这些方法open_camera()get_camera_info()configure_streams()process_capture_request()支持多个摄像头那就通过camera_id区分。要支持特殊能力如 RAW 输出、HDR 模式定义能力标志。上层代码就变成不管下面的摄像头厂商是索尼、三星、OV 还是自研的只要你按 HAL 标准实现系统服务就能“统一调度”。这就是 HAL 的核心价值之一统一 API、屏蔽差异、让上层有一个干净的世界。三、HAL 的主要职责可以粗暴总结成 4 句用最接地气的说法翻译把 Framework 的“标准化调用”翻译成操作具体硬件的底层动作。适配屏蔽硬件差异让上层不用关心你家是啥芯片、啥寄存器。封装把一堆复杂流程上电、初始化、缓存、错误处理封在内部对外只暴露干净函数。保障负责跟硬件通信的安全性、稳定性尽量不要把脏东西泄露到上层。稍微正式一点可以拆成几块职责定义“硬件能力接口”比如摄像头能拍照、预览、录像音频能播放/录制。实现这些接口时完成初始化 / 反初始化参数配置数据 IO读写 buffer状态和错误报告与底层驱动交互ioctl读写 /dev 设备节点使用 sysfs 节点获取状态做补丁有些底层驱动设计不理想HAL 里做 workaround在不动上层的前提下修 bug、做兼容四、典型 HAL 示例一Audio HAL音频硬件抽象层音频是 HAL 的经典示例。我们先从大流程看再稍微摸一下实现细节。4.1 音频系统大致链路从应用视角App 调用AudioTrack/MediaPlayer播放声音Java 层的 AudioTrack → JNI → C AudioTrack 实现C AudioTrack 向 AudioFlinger系统音频服务注册播放流AudioFlinger 负责混音、多路音频合成、音量控制等最终 AudioFlinger 把混合后的音频数据交给Audio HALAudio HAL 再通过驱动把数据送到真正的音频芯片播放可以理解为App → Framework → AudioFlinger → Audio HAL → 音频驱动 → 声卡 → 喇叭4.2 Audio HAL 做了哪几件关键事打开音频输出设备告诉驱动“我要以 44100Hz、16bit、立体声 使用你。”可能涉及到 mixer 路由、时钟配置。写音频数据到设备AudioFlinger 会定期把 PCM 数据交给 HALHAL 再写到驱动 buffer。要保证写入节奏与硬件采样率匹配否则会出现卡顿、爆音。控制音量、路由比如切换扬声器 / 听筒 / 耳机 / 蓝牙。这些路由设置往往在 HAL 内部根据策略决定然后写入驱动特定寄存器或 mixer 节点。处理录音输入流打开麦克风输入从驱动读取 PCM 数据给上层AudioRecord 或 MediaRecorder支持多种音频接口原生的 Speaker / Mic有线耳机、USB 音频、HDMI、蓝牙 A2DP/HFPHAL 根据设备状态和系统策略动态切换。4.3 Audio HAL 接口结构简化理解早期传统 HAL基本会有一个audio_hw_device的结构体大致类似伪代码structaudio_hw_device{structhw_device_tcommon;// 通用HAL头int(*init_check)(conststructaudio_hw_device*dev);int(*set_voice_volume)(structaudio_hw_device*dev,floatvolume);int(*set_master_volume)(structaudio_hw_device*dev,floatvolume);int(*open_output_stream)(structaudio_hw_device*dev,audio_io_handle_thandle,audio_devices_tdevices,audio_output_flags_tflags,structaudio_config*config,structaudio_stream_out**stream_out);void(*close_output_stream)(structaudio_hw_device*dev,structaudio_stream_out*stream);// 还有一堆其他函数比如输入流、路由、参数设置等等};厂商需要做的事情就是按 Google 定义的接口提供一个实现了这些函数指针的结构体在open_output_stream()里打开底层驱动设备/dev/snd/…设置采样率等在write()函数里把 AudioFlinger 交下来的数据写入驱动出口上层 AudioFlinger 根本不关心你底下硬件长什么样只调用这些函数。4.4 实现流程总结厂商视角按 Google 规定的 Audio HAL 接口版本创建一个 C/C 模块通常编译成audio.primary.board.so等文件放在/system/lib/hw/或/vendor/lib/hw/实现一组标准函数比如open_output_stream(),close_output_stream(),set_parameters(),write()等。在这些函数里通过open()/ioctl()操作/dev/snd/xxx设备或者通过 ALSA 接口等配置通道数、采样率、格式AudioFlinger 启动时加载对应的 HAL 模块通过 hw_get_module 接口拿到audio_hw_device实例。以后系统播放音频就走这个 HAL 模块。五、典型 HAL 示例二Camera HAL摄像头硬件抽象层摄像头 HAL 比音频复杂很多也是面试/系统开发中经常被问的内容。5.1 摄像头调用大致链路从 App 到镜头App 调用 Camera API老的android.hardware.Camera或新的camera2Java 层 → Binder →CameraServicesystem_server 或独立进程CameraService调用 Camera HAL 的接口get_number_of_cameras()get_camera_info()open()configure_streams()process_capture_request()等Camera HAL 内部通过驱动控制传感器、ISP图像信号处理、Sensor、对焦马达、闪光灯等硬件最终图像数据通过 BufferQueue / GraphicBuffer 等机制传给上层可能走到 SurfaceFlinger、MediaRecorder 或直接给 App简单情景如下App我要预览 拍照CameraService行我帮你找对应摄像头并让 HAL 开始输出 YUV buffer。HAL我去配置 sensor、ISP控制硬件按要求出图。HAL 把图像写入 buffer → 上交给上层 → App 在 SurfaceView / TextureView 上看到实时画面。5.2 Camera HAL 的职责有哪些可以拆成几块设备枚举和信息报告有多少个摄像头前置/后置支持哪些分辨率哪些帧率是否支持对焦、闪光灯、OIS、防抖、HDR、RAW 输出等。打开 / 关闭摄像头上电传感器初始化 ISP设置基础参数时钟、总线、时序配置数据流stream预览流、录像流、拍照流分别以什么格式、多大尺寸、帧率多少可能同时有多路输出低分辨率预览 高清录像对焦、曝光、白平衡等控制自动对焦AF自动曝光AE自动白平衡AWB各种拍照模式夜景、人像、连拍等图像数据输出 回调将图像输出到上层配置的 buffer可能是 gralloc buffer通知上层“这一帧已经完成可以拿去用/编码/显示”。5.3 Camera HAL 的几代演进简单认个门Android Camera HAL 大致经历了几个版本Camera HAL v1传统模式偏向老 API预览/拍照接口简单粗暴。Camera HAL v2/v3为了支持camera2高级特性引入了 request/result 模型App 提交一个 CaptureRequest包含曝光、对焦、参数HAL 输出一个 CaptureResult包含实际拍摄结果重点不在记版本号而是理解越往后HAL 越像一个“图像管线调度中心”不再只是简单的“打开摄像头 出图”而是支持半专业级控制手动模式、高速连拍、多摄像头协同等。5.4 Camera HAL 示例概念伪代码简化一下 Camera HAL 里的结构极简示意typedefstructcamera_module{hw_module_tcommon;int(*get_number_of_cameras)(void);int(*get_camera_info)(intcamera_id,structcamera_info*info);int(*open)(conststructhw_module_t*module,constchar*id,structhw_device_t**device);}camera_module_t;厂商提供get_number_of_cameras比如返回 3超广角 主摄 长焦get_camera_info告知每个 camera_id 的 facing前/后、orientation角度等open打开某个摄像头返回camera_device结构里面有 start_preview, take_picture 等函数指针CameraService 会通过hw_get_module(camera, module)加载厂商的 HAL调get_number_of_cameras()得知总数调open()打开具体摄像头把逻辑封装成统一的接口提供给 App对于新式 camera2 API对应的 HAL v3 接口会复杂些但本质仍是同一思路厂商实现一套标准函数上层只管调用不问细节。六、典型 HAL 示例三Sensor HAL传感器传感器 HAL 相对简单些但非常典型。它负责加速计、陀螺仪、光线、距离传感器等。6.1 调用链路App 使用SensorManager注册监听如加速计、重力传感器。Java 层经由 JNI 到 C 层SensorService。SensorService调用 Sensor HAL。HAL 从驱动读取传感器原始数据进行必要处理回传给上层。上层框架将数据转成统一的事件SensorEvent通过回调给 App。6.2 Sensor HAL 的职责枚举可用传感器包括类型加速度、陀螺仪、磁场、光线、压力……精度、范围、功耗、最大输出频率等打开/关闭传感器App 注册监听时传感器 HAL 可能打开对应设备节点并开始采样。没有任何 App 在用时可以关闭节省电量。数据读取和上报从驱动中读原始数据可能是原始物理量转换为标准单位如 m/s²、lux、度/秒按指定频率向上层推送事件做简单的融合或滤波有的 HAL 会做基本滤波去掉噪声或者合成出某些虚拟传感器如倾斜角、线性加速度6.3 一个简化版的 HAL 实现流程对开发传感器 HAL 的厂商工程师来说根据谷歌提供的sensors.h接口定义实现sensors_module_tsensors_poll_device_t在 HAL 中实现函数get_sensors_list()返回支持的传感器列表activate(handle, enabled)打开/关闭某个传感器setDelay(handle, ns)设置数据输出间隔poll()阻塞或轮询方式从驱动读取事件并返回编译生成sensors.board.so放到指定目录。SensorService 启动时加载该模块获取所有传感器信息。后面 App 就可以通过 SensorManager 使用这些传感器了。七、其他常见 HALDisplay / Fingerprint / Bluetooth / Radio这里简单点名不展开细节只让你知道显示 HAL或 Gralloc HAL负责图形 buffer 分配、格式支持、显存管理上层 SurfaceFlinger 通过它来分配/管理显存最后显示到屏幕指纹 HAL提供采集指纹数据、比对、Enroll录入、认证等接口上层 FingerprintService/AUTHFramework 通过 HAL 做指纹识别蓝牙 HAL帮 Bluetooth stack 与底层蓝牙控制器交互扫描设备、配对、传输数据等Radio HALRIL HAL和基带芯片打交道负责电话、短信、移动数据连接上层 TelephonyFramework 调用它完成拨号、接听、短信收发等这些 HAL 的逻辑都类似Google 先定接口标准厂商按标准实现Native/Framework 层统一调度。八、HAL 的实现套路从接口定义到系统加载前面例子都是“散讲”我们这里归纳一下一个典型 HAL 的实现全过程偏工程视角。8.1 Step 1Google 定一个 HAL 接口“标准”以传统 C 风格 HAL 为例在 AOSP 源码中定义一个头文件如audio.h、camera_common.h、sensors.h等。标准中包含模块接口hw_module_t/xxx_module_t设备接口hw_device_t/xxx_device_t一堆函数指针和数据结构描述 HAL 必须实现哪些功能。这一步相当于制定协议以后所有想接入 Android 系统的摄像头/音频设备都得说这套“标准话”。8.2 Step 2设备厂商在 Vendor 源码里实现这个接口厂商拿到芯片手册和驱动实现对应 C/C 模块写一个.so动态库对外导出HAL_MODULE_INFO_SYM这样的符号在库里填好函数指针指向自己实现的函数伪代码示意staticstructhw_module_methods_taudio_module_methods{.openaudio_device_open,};structaudio_moduleHAL_MODULE_INFO_SYM{.common{.tagHARDWARE_MODULE_TAG,.module_api_versionAUDIO_MODULE_API_VERSION_CURRENT,.idAUDIO_HARDWARE_MODULE_ID,.nameMyPhone Audio HW HAL,.authorMy Company,.methodsaudio_module_methods,},// ...};系统通过这个HAL_MODULE_INFO_SYM知道“这是一个音频 HAL 模块”。8.3 Step 3HAL 模块被放入指定路径例如/vendor/lib/hw/audio.primary.mysoc.so/vendor/lib/hw/camera.mysoc.so/vendor/lib/hw/sensors.mysoc.so命名规则一般包含模块类型camera、audio.primary、sensors等芯片/平台 IDmysoc8.4 Step 4系统服务启动时通过 hw_get_module() 找到 HAL 模块并加载系统里有个通用加载逻辑inthw_get_module(constchar*id,conststructhw_module_t**module);比如 CameraService 启动时hw_get_module(CAMERA_HARDWARE_MODULE_ID,(consthw_module_t**)mModule);CAMERA_HARDWARE_MODULE_ID对应的是 “camera”hw_get_module会根据当前设备平台在/vendor/lib/hw//system/lib/hw等路径里找名字匹配的 so找到后dlopen 加载拿到HAL_MODULE_INFO_SYM就能调用 HAL 的方法8.5 Step 5后续所有操作都通过这个 HAL 接口走上层需要开摄像头 → 调用mModule-open()AudioFlinger 需要输出音频 → 调用audio_hw_device-open_output_stream()SensorService 要获取传感器事件 → 调用sensors_poll_device-poll()…从此之后Framework 就不需要关心任何底层细节只和 HAL 标准接口“对话”。九、Project Treble 之后新一代 HALHIDL / AIDL简述前面讲的大多是“传统 C 风格 HAL”。从 Android 8.0Oreo开始Google 推了一个大工程Project Treble其中一个核心是把 Vendor厂商定制部分和 SystemAndroid 框架部分彻底隔离开来让系统升级时尽量不动厂商的 HAL。为此引入了HIDLHAL Interface Definition Language后来又渐渐向 AIDL-based HAL 过渡。9.1 HIDL让 HAL 接口更加“面向对象 支持 Binder”以前 HAL 接口都是 C 结构体 函数指针系统通过dlopen动态链接。HIDL 把 HAL 接口定义为一组 interfaceIDL像 AIDL 一样支持版本化、强类型、继承支持通过 Binder 做 IPC这样 HAL 实现甚至可以在单独进程里跑不一定是 so 模块。新的 HAL 典型调用链Framework Service在 system 分区通过 HIDL/AIDL interface 调用 HAL 实现在 vendor 分区彼此通过 Binder 通信不直接耦合内存空间。好处系统升级更容易System 分区升级但 HIDL 接口版本保持兼容Vendor 分区不动。安全性更高HAL 可以跑在独立进程中用 SELinux 限制权限即便 HAL 崩了也不会把整块 system_server 或 Native 进程带崩。9.2 AIDL HAL进一步统一语言Android 11 及之后Google 趋向用 AIDL 统一 HAL 和上层接口定义HAL 直接使用 AIDL 来描述接口好处是工具链统一、语法一致更方便验证和版本管理对我们理解“HAL 做什么”这件事其实没什么本质影响只是原来 HAL 是 C 层动态库 函数指针现在 HAL 也可以是一个“系统进程”通过 AIDL 与 Framework 交互。职责没变只是“通信方式 形式”更现代、可维护。十、从 App 开发者角度再看一眼 HAL它离你有多远最后我们从普通开发者视角再收一收平时写 App不会直接接触 HAL你只能用 Framework 提供的 Camera、Audio、Sensor 等 API。但当你遇到下面这些问题时背后其实就是 HAL/驱动层在搞事情为什么不同手机上Camera 行为略有差异比如对焦速度不一样、拍照声音强制开启、某些模式不支持。很可能是不同厂商 Camera HAL 实现有区别。为什么有些机型录音有底噪/延迟长Audio HAL 和底层驱动配置不同。有的厂商优化得好有的敷衍。传感器输出频率不稳定、重力感应“歪”传感器 HAL 中滤波、坐标系转换实现有差异。指纹识别体验好坏差距巨大一方面是硬件另一方面也是 Fingerprint HAL 的算法、接入方式不同。系统升级后某些硬件功能异常很有可能是 Framework 升级了但 HAL 没适配好或新的 HIDL/AIDL 接口版本不兼容。大部分时候这些坑不是你作为第三方 App 能解决的但你至少能通过了解 HAL 的存在理解问题的“层级”知道哪些问题是你的代码逻辑问题哪些是底层实现问题在做跨机型适配时有更靠谱的预期和沟通方向比如反馈给 ROM 厂时知道该说什么总结一段话把 HAL 拎起来我们用一段简洁的总结把文收住Android 的 HAL硬件抽象层就是连接“上层 Android 框架”和“底层硬件/驱动”的那层 C/C 模块或进程。它的主要职责是把五花八门的硬件能力抽象成一套统一、稳定的接口Audio、Camera、Sensor 等屏蔽硬件差异解耦上层系统和底层芯片实现缓解 Android 的碎片化问题为系统服务提供可靠的硬件访问方式同时保证一定的性能和安全性。对普通 App 来说HAL 是看不见摸不着的但你每天用的拍照、听歌、旋转屏幕、指纹解锁、打电话、连蓝牙……背后都必然经过这一层翻译和适配。如果 Android 是一栋大楼HAL 就是大楼里所有“电水气设备”的统一接口层——住户App只要会转龙头、按开关就行具体是用什么水管、什么压力、什么电压都交给 HAL 去对接底层工程团队了。