| <html devsite><head> |
| <title>Android 接口和架构</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> |
| Android 可让您自由实现您自己的设备规格和驱动程序。硬件抽象层 (HAL) 提供了一种用于在 Android 平台堆叠和硬件之间创建软件钩的标准方法。Android 操作系统也是开放源代码系统,因此您可以贡献您自己的接口和增强功能。 |
| </p> |
| |
| <p> |
| 为确保设备能够保持较高的质量水平并提供一致的用户体验,每部设备都必须通过兼容性测试套件 (CTS) 中的测试。CTS 可验证设备是否符合一定的质量标准,此类标准可确保应用稳定运行并提供良好的用户体验。若想详细了解 CTS,请参阅<a href="/compatibility/index.html">兼容性</a>。 |
| </p> |
| |
| <p> |
| 在将 Android 移植到您的硬件之前,请花点时间从更高层面上了解 Android 系统架构。由于您的驱动程序和 HAL 会与 Android 进行交互,因此了解 Android 的工作原理可帮助您浏览 Android 开放源代码项目 (AOSP) 源代码树中的多个代码层。 |
| </p> |
| |
| <img src="images/ape_fwk_all.png"/> |
| |
| <p class="img-caption"><strong>图 1.</strong> Android 系统架构</p> |
| |
| <h2 id="Application-framework">应用框架</h2> |
| <p> |
| 应用框架最常被应用开发者使用。作为硬件开发者,您应该非常了解开发者 API,因为很多此类 API 都可直接映射到底层 HAL 接口,并可提供与实现驱动程序相关的实用信息。 |
| </p> |
| |
| <h2 id="Binder-IPC">Binder IPC</h2> |
| <p> |
| Binder 进程间通信 (IPC) 机制允许应用框架跨越进程边界并调用 Android 系统服务代码,从而使得高级框架 API 能与 Android 系统服务进行交互。在应用框架级别,开发者无法看到此类通信的过程,但一切似乎都在“按部就班地运行”。 |
| </p> |
| |
| <h2 id="System-services">系统服务</h2> |
| <p> |
| 应用框架 API 所提供的功能可与系统服务通信,以访问底层硬件。服务是集中的模块化组件,例如窗口管理器、搜索服务或通知管理器。Android 包含两组服务:“系统”(诸如窗口管理器和通知管理器之类的服务)和“媒体”(与播放和录制媒体相关的服务)。<em></em><em></em> |
| </p> |
| |
| <h2 id="Hardware-Abstraction-Layer">硬件抽象层 (HAL)</h2> |
| <p> |
| 硬件抽象层 (HAL) 会定义一个标准接口以供硬件供应商实现,并允许 Android 忽略较低级别的驱动程序实现。借助 HAL,您可以顺利实现相关功能,而不会影响或无需更改更高级别的系统。HAL 实现会被封装成模块 (<code>.so</code>) 文件,并会由 Android 系统适时地加载。 |
| </p> |
| |
| <img src="images/ape_fwk_hal.png"/> |
| |
| <p class="img-caption"><strong>图 2.</strong> 硬件抽象层 (HAL) 组件</p> |
| |
| <p> |
| 您必须为您的产品所提供的特定硬件实现相应的 HAL(和驱动程序)。HAL 实现通常会内置在共享库模块(<code>.so</code> 文件)中。Android 并不要求您的 HAL 实现与设备驱动程序之间进行标准交互,因此您可以自由地根据您的具体情况执行适当的操作。不过,要使 Android 系统能够与您的硬件正确互动,您<strong>必须</strong>遵守各个针对特定硬件的 HAL 接口中定义的合同。 |
| </p> |
| |
| <h3 id="structure">标准 HAL 结构</h3> |
| <p> |
| 每个针对特定硬件的 HAL 接口均具有 <code>hardware/libhardware/include/hardware/hardware.h</code> 中定义的属性,这些属性可保证 HAL 具有可预测的结构。此类接口允许 Android 系统以一致的方式加载 HAL 模块的正确版本。HAL 接口包含两个通用组件:一个模块和一个设备。 |
| </p> |
| <p> |
| 模块表示被封装且存储为共享库 (<code>.so file</code>) 的 HAL 实现。它会包含模块的版本、名称和作者等元数据,这些元数据有助于 Android 找到并正确加载该模块。<code>hardware/libhardware/include/hardware/hardware.h</code> 标头文件会定义一个表示模块的结构体 (<code>hw_module_t</code>),其中会包含模块的版本、作者和名称等信息。</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> |
| <p> |
| 设备会提取产品的实际硬件。例如,音频模块可能会包含主音频设备、USB 音频设备或蓝牙 A2DP 音频设备。设备由 <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> |
| |
| <h3 id="modules">HAL 模块</h3> |
| <p>HAL 实现会内置在模块 (<code>.so</code>) 文件中,并会由 Android 适时地动态关联。您可通过为每个 HAL 实现创建 <code>Android.mk</code> 文件并指向源文件来构建模块。一般来说,您的共享库必须以某种格式命名,以便被找到并正确加载。各模块的命名方案略有不同,但它们都遵循以下通用模式:<code><module_type>.<device_name></code>。</p> |
| |
| <p>若想详细了解如何为每个 HAL 设置模块构建,请参阅各 HAL 对应的文档。</p> |
| |
| <h2 id="Linux-kernel">Linux 内核</h2> |
| <p> |
| 开发设备驱动程序与开发典型的 Linux 设备驱动程序类似。Android 使用的 Linux 内核版本包含一些特殊的补充功能,例如:唤醒锁(这是一种内存管理系统,可更主动地保护内存)、Binder IPC 驱动程序以及对移动嵌入式平台非常重要的其他功能。这些补充功能主要用于增强系统功能,不会影响驱动程序开发。 |
| |
| </p><p> |
| 您可以使用任一版本的内核,只要它支持所需功能(如 Binder 驱动程序)。不过,我们建议您使用 Android 内核的最新版本。若想详细了解 Android 内核的最新版本,请参阅<a href="/source/building-kernels.html">构建内核</a>。 |
| </p> |
| |
| </body></html> |