| <html devsite><head> |
| <title>硬件抽象层 (HAL)</title> |
| <meta name="project_path" value="/_project.yaml"/> |
| <meta name="book_path" value="/_book.yaml"/> |
| </head> |
| <body> |
| <!-- |
| Copyright 2017 The Android Open Source Project |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| <p>HAL 可定义一个标准接口以供硬件供应商实现,这可让 Android 忽略较低级别的驱动程序实现。借助 HAL,您可以顺利实现相关功能,而不会影响或更改更高级别的系统。HAL 实现会被封装成模块,并由 Android 系统适时地加载。</p> |
| |
| <img src="../images/ape_fwk_hal.png"/> |
| |
| <p class="img-caption"><strong>图 1.</strong> HAL 组件</p> |
| |
| <p>您必须为您的产品所提供的特定硬件实现相应的 HAL(和驱动程序)。HAL 实现通常会内置在共享库模块(<code>.so</code> 文件)中,但 Android 并不要求 HAL 实现与设备驱动程序之间进行标准交互,因此您可以视情况采取适当的做法。不过,要使 Android 系统能够与您的硬件正确互动,您<strong>必须</strong>遵守各个特定于硬件的 HAL 接口中定义的合同。</p> |
| |
| <p>为了保证 HAL 具有可预测的结构,每个特定于硬件的 HAL 接口都要具有 <code>hardware/libhardware/include/hardware/hardware.h</code> 中定义的属性。这类接口可让 Android 系统以一致的方式加载 HAL 模块的正确版本。HAL 接口包含两个组件:模块和设备。 |
| </p> |
| |
| <h2 id="hal-module">HAL 模块</h2> |
| <p>模块表示被封装且存储为共享库 (<code>.so file</code>) 的 HAL 实现。<code>hardware/libhardware/include/hardware/hardware.h</code> 标头文件会定义一个表示模块的结构体 (<code>hw_module_t</code>),其中包含模块的版本、名称和作者等元数据。Android 会根据这些元数据来找到并正确加载 HAL 模块。</p> |
| |
| <p>另外,<code>hw_module_t</code> 结构体还包含指向另一个结构体 <code>hw_module_methods_t</code> 的指针,后面这个结构体会包含一个指向相应模块的 open 函数的指针。此 open 函数用于与相关硬件(此 HAL 是其抽象形式)建立通信。每个特定于硬件的 HAL 通常都会使用附加信息为该特定硬件扩展通用的 <code>hw_module_t</code> 结构体。例如,在相机 HAL 中,<code>camera_module_t</code> 结构体会包含一个 <code>hw_module_t</code> 结构体以及其他特定于相机的函数指针:</p> |
| |
| <pre class="devsite-click-to-copy"> |
| typedef struct camera_module { |
| hw_module_t common; |
| int (*get_number_of_cameras)(void); |
| int (*get_camera_info)(int camera_id, struct camera_info *info); |
| } camera_module_t; |
| </pre> |
| |
| <p>实现 HAL 并创建模块结构体时,您必须将其命名为 <code>HAL_MODULE_INFO_SYM</code>。以下是 Nexus 9 音频 HAL 的示例:</p> |
| |
| <pre class="devsite-click-to-copy"> |
| struct audio_module HAL_MODULE_INFO_SYM = { |
| .common = { |
| .tag = HARDWARE_MODULE_TAG, |
| .module_api_version = AUDIO_MODULE_API_VERSION_0_1, |
| .hal_api_version = HARDWARE_HAL_API_VERSION, |
| .id = AUDIO_HARDWARE_MODULE_ID, |
| .name = "NVIDIA Tegra Audio HAL", |
| .author = "The Android Open Source Project", |
| .methods = &hal_module_methods, |
| }, |
| }; |
| </pre> |
| |
| <h2 id="hal-device">HAL 设备</h2> |
| <p>设备是产品硬件的抽象表示。例如,一个音频模块可能包含主音频设备、USB 音频设备或蓝牙 A2DP 音频设备。</p> |
| |
| <p>设备由 <code>hw_device_t</code> 结构体表示。与模块类似,每类设备都定义了一个通用 <code>hw_device_t</code> 的详细版本,其中包含指向硬件特定功能的函数指针。例如,<code>audio_hw_device_t</code> 结构体类型会包含指向音频设备操作的函数指针:</p> |
| |
| <pre class="devsite-click-to-copy"> |
| struct audio_hw_device { |
| struct hw_device_t common; |
| |
| /** |
| * used by audio flinger to enumerate what devices are supported by |
| * each audio_hw_device implementation. |
| * |
| * Return value is a bitmask of 1 or more values of audio_devices_t |
| */ |
| uint32_t (*get_supported_devices)(const struct audio_hw_device *dev); |
| ... |
| }; |
| typedef struct audio_hw_device audio_hw_device_t; |
| </pre> |
| |
| <p>除了这些标准属性之外,每个特定于硬件的 HAL 接口都可以定义更多的自有功能和要求。有关详情,请参阅 <a href="/reference/hal/">HAL 参考文档</a>以及各 HAL 的单独说明。</p> |
| |
| <h2 id="hal-building">编译 HAL 模块</h2> |
| <p>HAL 实现会内置在模块 (<code>.so</code>) 文件中,并由 Android 适时地动态链接。您可以为每个 HAL 实现创建 <code>Android.mk</code> 文件并指向源文件,从而编译模块。一般来说,您的共享库必须以特定格式命名,以方便找到并正确加载。各模块的命名方案略有不同,但它们都遵循以下通用模式:<code><module_type>.<device_name></code>。 |
| </p> |
| |
| <p>要详细了解如何为每个 HAL 设置模块编译,请参阅本网站“移植”部分中特定于 HAL 的文档。</p> |
| |
| </body></html> |