Android接口与架构

翻译自Android Interfaces and Architecture

Android提供给你实现自己的的设备规格与驱动的自由。硬件抽象层(HAL)提供了一个标准的方法用于连接(hook,钩子?)Android平台各层与你的硬件。Android操作系统同时也是开源的,所以你可以贡献你自己的接口与改进。

为了确保设备保持一个高水准的质量并且提供一致的用户体验,每款设备必须通过兼容性测试(CTS)中的测试。兼容性测试验证了设备需要满足一定的质量标准,可以确保app可靠运行并且用户会有一个好的使用体验。要查看兼容性测试的详情,查看Compatibility

在将Android移植到你的硬件之前,花一些时间在一个比较高的角度来理解Android系统架构。由于你的驱动和硬件抽象层与Android发生交互,所以了解Android如何工作可以帮助你在Android开源项目(AOSP)源码树的多层代码之间导航。

android-architecture
图1. Android系统架构

应用框架(Application framework)

通常,应用开发者使用应用框架最多。作为硬件开发者,你应该知道开发者API与直接映射到底层硬件抽象层的接口一样多,并且可以提供有关实现驱动的有用信息。

Binder IPC

Binder跨进程通信机制允许应用框架可以跨越进程边界并且可以调用Android系统服务代码。它使得上层的框架API可与与Android系统服务交互。在应用框架层,这个通信对于开发者透明,事情开起来就是”只是工作(just work)”。

系统服务

应用框架API所暴露出来的功能与系统服务交付可以访问底层硬件。服务是模块化、目标专注的组件,如Window管理器、Search服务或者Notification管理器。Android包括2组服务:system(比如Window管理器和Notification管理器)和media(设计播放和录制媒体的服务)。

硬件抽象层(HAL)

硬件抽象层(HAL)为硬件供应商提供了一个标准的接口来实现,并且可以使得Android对底层驱动的实现不可知。硬件抽象层允许你可以在不影响或者修改上层系统的情况下实现功能。硬件抽象层的实现被打包成模块(.so)文件并且由Android系统在合适的时间加载。

hal
图2. 硬件抽象层(HAL)组件

你必须为你的产品提供的特定硬件实现对应的HAL(和驱动)。HAL实现通常编译成共享库模块(.so文件)。Android在HAL实现与设备驱动之间并没有强制规定一个标准的交互,所以你可以根据你的情况自由定义。不过,为了使得Android系统可以与你的硬件正确交互,你必须遵守每个硬件特定的HAL接口里的协议。

标准HAL结构

每一个硬件特有的HAL接口所拥有的属性都定义在hardware/libhardware/include/hardware/hardware.h文件里,这保证了HAL有一个可预见的结构。这个接口允许Android系统以一种统一的方式加载你的HAL模块的正确版本。一个HAL接口通常由两部分组成:一个模块和一个服务。

一个模块指的是你打包的HAL实现,它存储在一个共享库里(.so文件)。它包含元数据,如模块的版本、名字和作者,以帮助Android可以正确地找到并加载它。头文件hardware/libhardware/include/hardware/hardware.h定义了一个结构 - hw_module_t,它代表一个模块,并且包含信息,如模块的版本、作者和名字。

此外,hw_module_t结构包含了一个指针指向另外一个结构 - hw_module_methods_t,它包含一个指针指向该模块的一个”开放”的方法。这个方法用于初始化与作为硬件抽象的HAL的通信。每一个硬件特有的HAL通常继承自通用的hw_module_t结构,再加上硬件特有的额外信息。比如在相机HAL中,camera_module_t结构包含了一个hw_module_t结构以及其它相机特有功能的指针:

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;

当你实现了一个HAL并且创建了模块结构,你必须将其命名为HAL_MODULE_INFO_SYS。例如,这里有一个来自Nexus 9音频HAL的例子:

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,
    },
};

设备将你的产品的实际硬件抽象起来。例如,一个音频模块可以包含一个主音频设备、一个USB音频设备或者一个蓝牙A2DP音频设备。设备由hw_device_t结构表示。与模块一样,每种类型的设备定义了通用的hw_device_t的一个更加详细的版本,它包含有硬件特有特征的方法的指针。例如,audio_hw_device_t结构类型包含了音频设备操作的方法的指针:

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;

除了这些标准的属性意外,每一个硬件特有的接口可以定义更多的它自己的特征和需求。有关如何实现一个特有接口的更多信息可以查看HAL reference documentation与单独的指令。

HAL模块

HAL实现被编译到模块文件(.so)中,并且在合适的时间会被Android进行动态链接。你可以通过为每一个你的HAL实现创建Android.mk文件并且指向你的源文件来构建你自己的模块。通常,你的共享库以一种特定的形式来命名,这样它们可以被准确地找到并且加载。命名机制在不同模块之间稍有不同,但是他们遵循一个共同的格式:<模块类型>.<设备名>

有关设置构建每个HAL的详细信息,参考它们各自的文档。

Linux内核

开发你的设备的驱动与开发一个经典的Linux设备驱动类似。Android使用了一个版本的Linux驱动与一些特别的附加部分,如wake locks(一个内存管理系统,它在保持内存上更加主动)、Binder IPC驱动和其它的对于一个移动嵌入式系统重要的特性。这些附加的部分主要用于系统的功能,并不会影响驱动开发。

关于wake locks的是不是搞错了?它应该是属于电源管理,而非内存管理。

你可以使用任意的kernel版本,只要它支持所要求的的特性(如binder驱动)。不过,我们推荐使用最新版本的Android kernel。有关最新的Android kernel,参考Building Kernels

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值