Android接口与架构

Android在设备的规格与驱动方面给了你很大的自由来实现。HAL层提供了一个标准的方式来打通Android系统层与硬件层。Android系统是开源的,所以你能够在接口和性能方面贡献自己的力量。

为了保证设备维持一个高水平的质量,并且提供一个持续稳定的用户体验,每个设备必须通过兼容性测试(CTS).CTS确保设备符合质量标准,用来保证app可靠的运行,并且有一个好的用户体验。如需了解更多,请看Compatiblity

在将android移植到硬件之前,请花些时间从一个比较高的层次了解下android系统的架构。因为你的驱动和HAL层通过android进行通信,所以了解android如何工作有助于你定位android源代码各个层次的代码。

图1 android系统结构

Application framework

Application framework 被开发者接触的最多。作为一个硬件开发者,你应该意识到,应用层的API能够映射到HAL层的接口,也能够在开发驱动的过程中提供很多有用的信息。

Binder IPC

Binder 进程内通信机制允许应用程序框架透过进程的边界,并且调用android system services 的代码。这样能够保证上层的框架代码与底层的android system services之间的通信。在 应用framwork层,这种通信对开发者是透明的,这样看起来这两个层之间通信是理所当然。

System services

应用framework层暴露的一些实际功能是通过与system services通信来达到访问底层硬件的目的。services是模块化的,主要的几个组件比如Window Manager,Search Service,Notifycation Manager.Android 包含了两个组的service,系统(比如Window Manager,Search Service)和媒体(比如播放与录制)

Hardware abstraction layer (HAL)

硬件抽象层(HAL)为硬件厂商定义了一个标准的接口,让厂商自己实现。同时android也能向开发者隐藏掉底层驱动的实现细节。HAL层让开发者不影响上层系统的情况下,开发功能。HAL的实现被打包进so文件中,并且在适当的时机被系统加载。

图2硬件抽象层的组件

你必须为硬件提供商提供的指定的硬件实现相符合的HAL(和驱动)。HAL的实现通常是编译到共享库的模块中(.so文件).Android没有在HAL实现层与硬件层指定一个标准的通信方式,这样你可以根据自己的情况实现最好的方案。当然,为了能让Android系统正确的与硬件通信,你必须遵守已有的约定,这个约定是在每个硬件特殊指定的HAL接口中定义的。

标准的HAL结构

每一个指定的HAL接口有指定的属性,这些属性定义在hardware/libhardware/include/hardware/hardware.h这个文件中,这样能够保证HAL用户可控的结构。这个接口让Android系统一致的加载正确版本的HAL模块。在这里包含了两种通常的组件,一个module,一个device.

module 代表了你的HAL层的实现,存储在共享的ligrary中(.so文件)。里面包含了metadata包含了比如版本,名字,作者,这有助于帮助Android发现并且正确的加载。hardware/libhardware/include/hardware/hardware.h这个头文件定义了一个hw_module_t结构,这个结构代表一个module,里面包含了刚刚提到的版本,名字和作者。

另外 hw_module_t这个结构包含了一个指向一个另外hw_module_methods_t结构的指针,而hw_module_methods_t这个结构包含了了一个指针指向一个开放的方法。这个开放的方法是用来初始化HAL与硬件的通信。每一个硬件指定的HAL通常都会包含hw_module_t这个结构,用来为硬件添加额外的信息。例如在camera 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,并且创建了一个module 结构,你必须把他命名为HAL_MODULE_INFO_SYM,例如,这里有了Nexus 9 audio 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,
},
};

另外一个组件device,把实际的硬件中抽象出来。例如,一个audio module能够包含一个私有的audio device,一个 USB audio device 或者一个蓝牙A2DP audio device。一个device是由hw_device_t结构代表的。就跟module一样,每种类型的device定义了一个更加详细版本的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接口都能定义自己的特性和需求。请看HAL reference documentation ,这是个独立的文档,来介绍每个HAL在实现特定接口时候更多的信息。

HAL modules

HAL的实现被编译到modules(.so)文件中,Android系统会在适当的时机动态链接他们。你可以通过为每个HAL实现创建Android.mk文件,然后指向你的源文件。通常,你的共享的libraries必须有一个格式命名,这样他们才能被正确找到并加载。命名策略在不同的module中有些许的不同,但是他们都遵循下面的模式<module_type>.<device_name>.

要得到更多的关于创建HAL,请看他们各自的文档。

linux kernel

开发一个设备驱动跟开发一个标准的Linux设备驱动很像。Android使用的linux版本是添加了一些额外的功能,比如弱锁(一个内存管理系统,更加好的保护内存),Binder IPC driver,还有一些对于移动手机平台更加重要的特性。这些额外的添加主要是为了系统的功能,并且不会影响驱动的开发。

你可以使用任何版本的内核,只要他它支持我们需要的特性。不过,我们还是建议使用最近的Android 内核,有关最近的android内核相关,请看Building Kernels.

版权声明:本文为gaoteng原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/gaoteng/p/5505930.html