Android中内核的结构和标准的Linux 2.6内核是基本相同的,不过Android在其基础上增加了私有内容。Android在Linux内核中增加的主要是一些驱动程序,这些驱动程主要分为两种:Android专用驱动和Android使用的设备驱动。

Android专用驱动

   Android专用驱动程序不是Linux的标准驱动,它们的作用是辅助系统运行,一般不操作实际硬件。

  • Ashmem: 匿名共享内存驱动。
  • Logger: 轻量级的log驱动。
  • Binder驱动(Binder Driver): 基于OpenBinder驱动,为Android平台提供IPC(进程间通信)的支持。
  • 电源管理(Android Power Management ): 轻量级的能源管理,基于Linux的能源管理,为嵌入式系统做了优化。
  • Android Power Management: 定时器驱动,用于唤醒设备。
  • Low Memory Killer: 在缺少内存的情况卜,杀死进程。
  • Android PMFM: 物理内存驱动。
  • USB Gadget: USB 驱动(基于 gaeget 框架)。
  • Ram Console: 用于调试写入日志信息的设备。
  • Time Device: 定时控制设备。
  • Android Alarm: 硬件时钟。

  下面将主要介绍Android专用驱动中最重要的3个驱动:

Ashmem:匿名共享内存驱动

  Ashmem ( Anonymous Shared Memory ),即匿名共享内存,通过内核的机制,为用户空间程序提供分配内存的机制。
  Ashmem设备节点名称为/dev/ashmem,主设备号为10 ( Misc Driver ),次设备号动态生成。
  Ashmem的代码路径如下:
  kernel/include/linux/ashmem.h
  kernel/mm/ashmem.c

Logger:轻量级的log驱动

   Android的Logger驱动程序为用户层程序提供log的支持,这个驱动作为一个工具来使用。
   Logger有3个设备节点,分别为:/dev/log/main, /dev/log/event, /dev/log/radioo
   主设备号为10 (Misc Driver),次设备号动态生成。
   Logger驱动的代码路径如下:
  kernel/include/linux/logger.h
  kernel/drivers/misc/logger.c
   在用户空间logcat程序调用Logger驱动: system/core/logcat/可执行程序。

Binder驱动(Binder Driver)

  Android的Binder驱动程序为用户层程序提供IPC(进程间通信)支持,Android整个系统的运行依赖Binder驱动。
  Binder设备节点名称为/dev/binder,主设备号为10 ( Misc Driver ),次设备号动态生成。

  Binder的代码路径:
  kernel/include/linux/binder.h
  kernel/drivers/misc/binder.c
  Android系统上层用户空间的libutil 工具库和ServiceManager守护进程都是调用Binder接口驱动提供对整个系统进程间通信功能的支持,它们的代码路径为:

    frameworks/base/curds/servicemanager/    frameworks/base/include/utils/    frameworks/base/libs/utils/

   Binder是Android中主要使用的IPC方式,通常需要按照模板定义相关的类,不需要直接调用Binde驱动程序的设备节点。

其它专用驱动

  • Android Power Management
    一个基于标准 linux 电源管理的轻量级 Android 电源管理系统。
    源码位置:
    drivers/android/power.c
    kernel/power/

  • Low Memory Killer
    它在用户空间中指定了一组内存临界值,当其中某个值与进程描述中的 oom_adj 值在同一范围时,该进程将被Kill掉(在parameters/adj中指定oome_adj 的最小值)。它与标准的Linux OOM机制类似,只是实现方法不同。
    源码位置:drivers/misc/lowmemorykiller.c

  • Android PMEM
    PMEM 主要作用就是向用户空间提供连续的物理内存区域。
    ① 让 GPU 或 VPU 缓冲区共享 CPU 核心。
    ② 用于 Android service 堆。
    源码位置:include/linux/android_pmem.h drivers/android/pmem.c

  • USB Gadget
    基于标准 Linux USB gaeget 驱动框架的设备驱动。
    源码位置:drivers/usb/gadet/

  • Ram Console
    为了提供调试功能,android 允许将调试日志信息写入这个设备,它是基于 RAM 的 buffer
    源码位置: drivers/staging/android/ram_console.c

  • Time Device
    定时控制,提供了对设备进行定时控制的功能。
    源码位置:drivers/staging/android/timed_output.c(timed_gpio.c)

  • Android Alarm
    提供一个定时器,用于把设备从睡眠状态唤醒,同时它还提供了一个即使在设备睡眠时也会运行的时钟基准。
    设备节点:/dev/alarm
    源码位置:drivers/trc/alarm.c

Android设备驱动

  Android中常使用的设备主要有Framebuffer驱动、输入设备驱动、v412摄像头—视频驱动、OSS音频驱动、ALSA音频驱动、MTD驱动、蓝牙驱动、Wlan驱动等。

Framebuffe显示驱动

  Framebuffer 驱动在 Linux 中是标准的显示设备的驱动。

  • 对于 PC 系统,它是显卡的驱动 ;
  • 对于嵌入式 SOC 处理器系统,它是 LCD 控制器或者其他显示控制器的驱动。

  它是一个字符设备,在文件系统中设备节点通常是 /dev/fbx 。 每个系统可以有多个显示设备 ,依次用 /dev/fb0、/dev/fb l等来表示。在 Android 系统中主设备号为 29 ,次设备号递增生成。
  Android 对 Framebuffer 驱动的使用方式是标准的,在 / dev / graphie / 中的 Framebuffer 设备节点由 init 进程自动创建,被 libui 库调用。Android 的 GUI 系统中 , 通过调用 Framebuffer 驱动的标准接口,实现显示设备的抽象。
  代码路径:include/linux/fb.h, drivers/video/fbmem.c

输入设备驱动

  Android中的输入设备设备驱动主要包括:游戏杆(Joystick、鼠标(Mouse)和事件设备(Event)。

  • 其中事件设备驱动程序是目前通用的程序,可支持键盘 、 鼠标、触摸屏等多种输入设备。 Input 驱动程序的主设备号是13 ,每一种Input设备从设备号占用5位 ,3种从设备号分配是 : 游戏杆 0~61 ; Mouse 鼠标33~62 ; Mice鼠标63 ; 事件设备64 ~ 95,各个具体的设备在misc 、touchscreen 、keyboard 等目录中。
  • Event设备在用户空问使用read 、ioctl 、poll 等文件系统的接口操作,read 用于读取输入信息,ioctl 用于获取和设置信息,poll 用于用户空间的阻塞,当内核有按键等中断时,通过在中断中唤醒内核的 poll 实现。

  输入设备驱动同样也是字符设备,这个输入设备驱动程序那是相当相当的复杂。在Android内核中主要需要关注以下儿个文件:

include/linux/input.h(驱动头文件)。driver/input/input.c(驱动核心实现,包含大量的操作接口)。driver/input/event.c ( event机制)。driver/input/joydev.c ( joystick驱动)。driver/input/mousedev.c(鼠标驱动)。

  上面这些都不需我们去实现,内核已经帮我们实现好了,不过在写硬件驱动时需要和Inputcore交互,所以需要用到上面这些函数中的接口,也就是说上面这些函数是透明的。

V4L2摄像头—视频驱动

  摄像头(Camera)——视频驱动驱动通常使用Video For Linux。
  V4L2是V4L的升级版本,为linux下视频设备程序提供了一套接口规范。包括一套数据结构和底层V4L2驱动接口。V4L2提供了很多访问接口,可以根据具体需要选择操作方法。
  注意:很少有驱动完全实现了所有的接口功能。所以在使用时需要参考驱动源码,或仔细阅读驱动提供者的使用说明。
  V4L2的主设备号是81,次设备号:0~255,这些次设备号里也有好几种设备(视频设备、Radio设备、Teletext、VBI)。

  • V4L2的设备节点: /dev/videoX, /dev/vbiX 和 /dev/radioX
  • V4L2驱动主要头文件路径:
include/linux/videodev.h:  v4L第一版的头文件。include/linux/videodev2.h: 定义主要的数据接日和常量。include/media/v412-dev.h: 设备头文件,具体设备使用其中的接口注册。
  • V4L2驱动核心实现路径:driver/media/video/v412-dev.c

          Android驱动_第1张图片
                        V4L2框架图

OSS音频驱动

   OSS(Open Sound System开放声音系统)是 linux 上最早出现的声卡驱动。OSS 由一套完整的内核驱动程序模块组成,可以为绝大多数声卡提供统一的编程接口。
   OSS 是字符设备,主设备号14,主要包括下面几种设备文件:

  • /dev/sndstat
    它是声卡驱动程序提供的简单接口,它通常是一个只读文件,作用也只限于汇报声卡的当前状态。(用于检测声卡)
  • /dev/dsp
    用于数字采样和数字录音的设备文件。对于音频编程很重要。实现模拟信号和数字信号的转换。
  • /dev/audio
    类似于/dev/dsp,使用的是 mu-law 编码方式。
  • /dev/mixer
    用于多个信号组合或者叠加在一起,对于不同的声卡来说,其混音器的作用可能各不相同。
  • /dev/sequencer
    这个设备用来对声卡内建的波表合成器进行操作,或者对 MIDI 总线上的乐器进行控制。

  OSS 驱动所涉及的文件主要包括:

     kernel/include/linux/soundcard.h  OSS驱动的主要头文件。     kernel/include/linux/sound.h   定义 OSS 驱动的次设备号和注册函数     kernel/sound_core.c    OSS核心实现部分

MTD驱动

  Flash驱动通常使用MTD ( Memory Technology Device内存技术设备)
  MTD 驱动程序是 Linux 下专门为嵌入式环境开发的新一类驱动程序。Linux 下的 MTD 驱动程序接口被划分为用户模块和硬件模块

  • 用户模块
    提供从用户空间直接使用的接口:原始字符访问、原始块访问、FTL (Flash Transition Layer)和JFS(Journaled File System)。
  • 硬件模块
    提供内存设备的物理访问,但不直接使用它们,二十通过上述的用户模块来访问。这些模块提供了闪存上读、写和擦除等操作的实现。

  MTD的字符设备:/dev/mtdX,主设备号为90。
  MTD的块设备:/dev/block/mtdblockX,主设备号为13。
  MTD驱动程序头文件路径:include/linux/mtd/mtd.h
  MTD源代码路径:

   drivers/mtd/mtdcore.c:  MTD核心,定义MTD原始设备。   drivers/mtd/mtdchar.c:  MTD字符设备。   drivers/mtd/mtdblock.c:  MTD块设备。

  MTD驱动工作原理如图所示:
        Android驱动_第2张图片
                        MTD工作原理图

ALSA音频驱动

  ALSA ( Advanced Linux Sound Architecture)即高级Linux声音体系。
  高级 Linux 声音体系ALSA是为音频系统提供驱动 的Linux 内核组件,以替代原先的开发声音系统 OSS 。它是一个完全开放源代码的音频驱动程序集 ,除了像 OSS 那样提供一组内核驱动程序模块之外 ,ALSA 还专门为简化应用程序的编写提供相应的函数库,与 OSS 提供的基于 ioctl 等原始编程接口相比, ALSA 函数库使用起来要更加方便一些 。
  利用该函数库,开发人员可以方便、快捷地开发出自己的应用程序,细节则留给函数库进行内部处理 。所以虽然 ALSA 也提供了类似于 OSS 的系统接口,但建议应用程序开发者使用音频函数库,而不是直接调用驱动函数。
  ALSA 驱动的主设备号为 116 ,次设备号由各个设备单独定义,主要的设备节点如下:

       / dev / snd / contmlCX —— 主控制 ;       / dev / snd / pcmXXXc —— PCM 数据通道 ;       / dev / snd / seq —— 顺序器;       / dev / snd / timer —— 定义器。

  在用户空间中 , ALSA 驱动通常配合 ALSA 库使用,库通过 ioctl 等接口调用 ALSA 驱动程序的设备节点。对于 AIJSA 驱动的调用,调用的是用户空间的 ALsA 库的接口,而不是直接调用 ALSA 驱动程序。

  • ALSA驱动程序的头文件:
   include/sound/asound.h:  ALSA驱动的主要头文件。   include/sound/core.h:  ALSA驱动核心数据结构和具体驱动的注册函数。
  • ALSA驱动程序的核心实现:
    sound/core/sound.c

ALSA 音频驱动的架构如下图所示:
            Android驱动_第3张图片
                       ALSA系统架构图

蓝牙驱动

  在Linux中,蓝牙设备驱动是网络设备,使用网络接口。
  Android 的蓝牙协议栈使用BlueZ实现来对GAP, SDP以及RFCOMM等应用规范的支持,并获得了SIG认证。由于Bluez使用GPL授权, 所以Android 框架通过D-BUS IPC来与bluez的用户空间代码交互以避免使用未经授权的代码。

  • 蓝牙设备的网络协议:协议族AF BLUETOOTH ( 31) 。
  • 蓝牙协议部分头文件:
    include/net/bluetooth/hci core.h    include/net/bluetooth/bluetooth.h 
  • 蓝牙协议源代码文件:net/bluetooth/*
  • 蓝牙驱动程序部分的文件::rivers/bluetooth/*

WLAN驱动

   在Linux中,WLAN设备驱动是网络设备,使用网络接口。WLAN在用户空间使用标准的Socket接口进行控制。

  • WiFi协议部分头文件: include/net/wireless.h
  • WiFi协议部分源文件: net/wireless/*
  • WiFi驱动程序部分: drivers/net/wireless/*

Android驱动移植

  驱动开发是Android开发系统中最底层的应用,属于Linux内核层的工作,因为驱动是系统和硬件之间的载体,涉及了不同硬件的应用问题,所以需要做系统移植的工作。

Android移植的任务

  Android移植开发的最终目的是为了开发手机产品,从开发者的角度来看,这种类型的开发以具有硬件系统为前提,在硬件系统的基础上构建Android软件系统,这种类型的开发工作在Android系统的底层。在软件系统方面,主要工作集中在如下两个方面:

  • Linux中的相关设备驱动程序
    驱动程序是硬件和上层软件的接口,在Android手机系统中,需要基本的屏幕、触摸屏、键盘等驱动程序,以及音频、摄像头、电话的Modem,HIFi、蓝牙等多种设备驱动程序。
  • Android本地框架中的硬件抽象层
    在Android中,硬件抽象层工作在用户空间,介于驱动程序和Android系统之间。Android系统对硬件抽象层通常都有标准的接口定义,在开发过程中,实现这些接口也就给Android系统提供了硬件抽象层。

  上述两个部分相互结合,共同完成了Android系统的软件移植。移植成功与否取决于驱动程序的品质和对Android硬件抽象层接口的理解程度。Android移植开发的工作由核心库、Dalvik虚拟机、硬件抽象层、Linux内核层和硬件系统协同完成,具体结构如图:
             Android驱动_第4张图片
                    Android移植结构图

Android移植的内容

  在移植过程中主要移植驱动方面的内容,具体来说,Android的移植主要分为下面的几个类型

  • 基本图形用户界面(GUI)部分:包括显示部分、用户输入部分和硬件相关的加速部分,还包括媒体编解码和OpenGL等,还包括媒体编解码和OpenGL等。
  • 音视频输入输出部分:包括音频、视频输出和摄像头等。
  • 连接部分:包括无线局域网、蓝牙、GPS等。
  • 电话部分:包括通话、GSM等。
  • 附属部件:包括传感器、背光、振动器等。

  具体需要移植的内容如下所示
① Display显示部分: 包括FrameBuffer驱动和Gralloc模块。
② Input用户输入部分: 包括Event驱动和EventHube
③ Codec多媒体编解码: 包括硬件Codec驱动和Codec插件,例如OpenMax o
④ 3D Accelerator ( 3D加速器)部分: 包括硬件OpenGL驱动和OpenGL插件。
⑤ Audi音频部分: 包括Audi、驱动和Audi、硬件抽象层。
⑥ Video Out视频输出部分: 包括视频显示驱动和Overlay硬件抽象层。
⑦ Camera摄像头部分: 包括Camera驱动(通常是v412)和Camera硬件抽象层。
⑧ Phone电话部分: 包括Modem驱动程序和RIL库。
⑨ GPS全球定位系统部分: 包括GPS驱动(例如串口)和GPS硬件抽象层。
⑩ Wi-Fi无线局域网部分: 包括Wlan驱动和协议以及Wi-Fi的适配层。
⑪ Blue Tooth蓝牙部分: 包括BT驱动和协议以及BT的适配层。
⑫ Sensor传感器部分: 包括Sensor驱动以及Sensor硬件抽象层。
⑬ Vibrator震动器部分: 包括Vibrator驱动和Vibrator硬件抽象层。
⑭ Light背光部分: 包括Light驱动和Light硬件抽象层。
⑮ Alarm警告器部分: 包括Alarm驱动和RTC系统以及用户空间调用。
⑯ Battery电池部分: 包括电池部分驱动和电池的硬件抽象层。
  Android系统有很多组件,但并不是每一个部件都需要移植,例如浏览器引擎虽然需要下层的网络支持,但实际上并不需要直接为其移植网络接口,而是通过无线局域网或者电话系统数据连接来完成标准的网络接口,所以就不需要移植。

驱动开发要做的工作

  驱动开发的任务是,为某一个将要在Android系统上使用的硬件开发一个驱动程序。因为Android是基于Linux的,所以开发Android驱动其实就是开发Linux驱动。
  对于大部分子系统来说,硬件抽象层和驱动程序都需要根据实际系统的情况来实现,例如传感器部分、音频部分、视频部分、摄像头部分和电话部分。另外也有一些子系统的硬件抽象层是标准的,只需要实现Linux内核中的驱动程序即可,例如输入部分、振动器部分、无线局域网部分和蓝牙部分等。对于有标准的硬件抽象层的系统,有的时候通常也需要做一些配置工作。
  随着Android系统的更新和发展,它已经不仅仅是一个移动设备的平台,而且可以用于消费类电子和智能家电,例如从3.0以后的版本主要是针对平板电脑的,另外电子书、数字电视、机顶盒、固定电话等都逐渐使用Android系统。
  在这些平台上,通常需要实现比移动设备更少的部件。一般来说,包括显示和用户输入的基本用户界面部分是需要移植的,其他部分是可选的。例如电话系统、振动器、背光、传感器等一般不需要在非移动设备系统来实现,一些固定位置设备通常不需要实现GPS系统。

Android在Linux基础上的改进

  Android内核是基于Linux 2.6内核的,这是一个增强内核版本,除了修改部分Bug外,还提供了用于支持Android平台的设备驱动。Android不但使用了Linux内核的基本功能,而且对Linux进行了改造,以实现更为强大的通信功能。

Android构建Linux系统

  如果以一个原始的Linux操作系统为基础,将其改造成为一个适合于Android的系统所做的工作其实非常简单,就是增加适用于Android的驱动程序。在Android中有很多Linux系统的驱动程序,将这些驱动程序移植到新系统非常简单,具体来说有以下三个步骤。
① 编写新的源代码。
② 在KConfig配置文件中增加新内容。
③ 在Makefile中增加新内容。
  在Android系统中,最常用的驱动程序有FrameBuffer驱动、Event驱动、Flash MTD驱动、WiFi驱动、蓝牙驱动和串口等驱动程序,并且还需要音频、视频、传感器等驱动和sysfs接口。所以说移植的过程就是移植上述驱动的过程,底层程序员的工作是在Linux下开发适用于Android的驱动程序,并移植到Android系统。
  在Android中添加扩展驱动程序的基本步骤介绍如下:
① 在Linux内核中移植硬件驱动程序,实现系统调用接口;
② 把硬件驱动程序的调用在HAL中封装成Stub;
③ 为上层应用的服务实现本地库,由Dalvik虚拟机调用本地库来完成上层Java代码的实现;
④ 最后编写Android应用程序,提供Android应用服务和用户操作界面。
          Android驱动_第5张图片
                Android中的Linux内核和设备驱动结构

Andrid硬件抽象层(HAL)

   HAL层又被称为硬件抽象层,HAL在Android体系中有着深远的意义,因为Android是开放的而不是开源的原因就是在这一层上。因为HAL层的代码没有开源,所以Google将硬件厂商的驱动程序放在HAL层。也正是这个原因,所以Android被Linux家族删除。

Android HAL定义和概述

  HAL层(硬件抽象层)是位于操作系统内核与硬件电路之间的接口层,其目的在于将硬件抽象化。它隐藏了特定平台的硬件接口细节,为操作系统提供虚拟硬件平台,使其具有硬件无关性,这样就可以在多种平台上进行移植。

  从软硬件测试的角度来看,软硬件的测试工作都可分别基于硬件抽象层来完成,从此使软硬件测试工作的并行进行成为可能。HAL层的位置结构如图所示。
      Android驱动_第6张图片
                       HAL层结构
  由上图可以看出,HAL的功能是把Android Framework< Android框架)与Linux内核隔离。这样做的目的是让Android不过度依赖Linux Kemel,从而让Android Framework开发可以在不考虑驱动程序的前提下进行。在HAL层主要包含了GPS, Vibrator, Wi-Fi, Copybit, Audio,Camera, Lights, Ril, Overlay等模块。

Android HAL层的分类和结构

  Android HAL层的分类,Android硬件抽象层可以分为如下六种HAL

  • 上层软件
  • 内部以太网
  • 内部通信CLIENT
  • 用户接入口
  • 虚拟驱动,设置管理模块
  • 内部通信SERVER

  定义硬件抽象层接口的代码具有以下五个特点

  • 硬件抽象层具有与硬件的密切相关性。
  • 硬件抽象层具有与操作系统无关性。
  • 接口定义的功能应包含硬件或系统所需硬件支持的所有功能。
  • 接口定义简单明了,太多接口函数会增加软件模拟的复杂性。
  • 具有可测性的接口设计有利于系统的软硬件测试和集成。

  Android HAL层的目录结构,在Android源码中,HAL主要被保存在下面的目录中:

  • libhardware_legacy: 过去的目录,采取了链接库模块观念来架构。
  • libhardware: 新版的目录,被调整为用I-3AL stub观念来架构。
  • ril: 是Radio接口层。
  • msm7k:和QUAL平台相关的信息。
      当然Android的HAL层仍旧散布在不同的地方,例如分为Camera, Wi-Fi等,因此上述的目录并不包含所有的HAL程序代码。在HAL架构成熟前的结构如左图所示,现在HAL层的结构如图所示:
    Android驱动_第7张图片Android驱动_第8张图片
           HAL架构成熟前的结构             HAL架构成熟后的结构

  从现在HAL层的结构可以看出,当前的HAL stub模式是一种代理(proxy)的概念,虽然stub仍以“.so”档的形式存在,但是HAL已经将“.so”档隐藏了。Stub向HAL提供了功能强大的操作函数(operation ),而runtime则从HAL获取特定模块(stub)的函数,然后再回调这些操作函数。这种以Indirect Function Call模式的架构,让HAL stub变成了一种“包含”关系,也就是说在HAL里包含了许多stub(模块)。Runtime只要说明module ID(类型)就可以取得操作函数。
  在当前的HAL模式中,Android定义了HAL层结构框架,这样通过接口访问硬件时就形成了统一的调用方式。

HAL_legacy和HAL的比较

  • HAL_legacy:这是过去HAL的模块,采用共享库形式,在编译时会调用到。由于采用function call形式来调用,因此可被多个进程使用,但会被映射到多个进程空间中造成浪费,同时需要考虑代码能否安全重入的问题(thread safe )。
  • HAL:这是新式的HAL,采用了HAI module和HAI stub结合形式。HAL stub不是一个共享库,在编译时上层只拥有访问HAL stub的函数指针,并不需要HAL stub。在上层通过HAL module提供的统一接口获取并操作HAL stub,所以文件只会被映射到一个进程,而不会存在重复映射和重入问题。

HAL层的调用

重要的结构体

  在HAL module中主要有如下三个结构:

  • struct hw_module_t
    hw_module_t 结构体是通用模块结构体,是具体模块的一个基类,如果你要实现类似音频、相机等模块就需要继承这个通用模块,对应的结构为:
typedef struct hw_module_t {    /** tag必须初始化为HARDWARE_MODULE_TAG*/    uint32_t tag;    uint16_t module_api_version;#define version_major module_api_version    uint16_t hal_api_version;#define version_minor hal_api_version    /** 模块id */    const char *id;    /** 模块名称*/    const char *name;    /** 模块作者 */    const char *author;    /**模块方法*/    struct hw_module_methods_t* methods;    /** 模块的dso */    void* dso;    uint32_t reserved[32-7]; } hw_module_t;
  • struct hw_module_methods t
    hw_module_methods_t 结构体定义一个打开具体设备的函数open ,结构为:
typedef struct hw_module_methods_t {    /** 打开设备的函数*/    int (*open)(const struct hw_module_t* module, const char* id,              struct hw_device_t** device); } hw_module_methods_t;
  • struct hw_device_t
    hw_device_t 结构体是通用设备结构体,上层找到对应模块之后需要定位具体设备,一个模块可以有多个设备(根据device id来区别),上面的open函数就是去初始化这个设备的各个参数的,具体结构为:
typedef struct hw_device_t {    /** tag必须初始化为HARDWARE_MODULE_TAG*/    uint32_t tag;    uint32_t version;    /** 设备所属的模块 */    struct hw_module_t* module;    /**留填充*/    uint32_t reserved[12];    /**关闭设备函数,对应上面hw_module_methods_t 结构体的开启函数*/    int (*close)(struct hw_device_t* device);} hw_device_t;

  HAL_MODULE_INFO_SYM是定义具体模块的结构体变量,结构体内部是一个hw_module_t结构体,这种包含关系可以理解为,具体模块继承通用模块hw_module_t结构体
  #define HAL_MODULE_INFO_SYM HMI

  这三个结构体之间的关系为:
        Android驱动_第9张图片
                  三种结构之间的关系

HAL调用(Android 中实现调用 HAL 是通过 hw_get_module 实现的)

  函数hw_get_module()能够根据模块ID寻找硬件模块动态链接库的地址,然后调用load打开动态链接库从中获取硬件模块结构体地址。
  执行后首先是根据固定的符号HAL_MODULE_INFO_SYM寻找到hw module t结构体,然后是在hw_moule_t中hw_module_ methods_t结构体成员函数提供的结构open打开相应的模块,并同时进行初始化操作。因为用户在调用open()时通常会传入一个指向hw device t指针的指针。这样函数open()将对模块的操作函数结构保存到结构体hw_device_t中,用户通过它可以和模块进行交互。

① Native code通过hw_get_module调用获取HAL stub
  hw_get_module (XXX_HARDWARE_MODULE_ID, (const hw_module_t**)&module)

② 通过继承hw_module_methods_t的callback来 open设备
  module->methods->open(module,XXX_HARDWARE_MODULE_ID, (struct hw_device_t**)device);

③ 通过继承 hw_device_t的callback来控制设备(比如LED灯)
  sLedDevice->set_on(sLedDevice, led);
  sLedDevice->set_off(sLedDevice, led);
  这一部分主要了解了Android架构里的HAL层,HAL在Android的Linux内核和应用层之间架起一架桥梁,帮助实现了底层硬件和软件的通信,主要封装了一些硬件厂商的设备驱动程序使其便于商用。

更多相关文章

  1. Android 9.0 Launcher源码分析(三)——Launcher的布局与多设备适配
  2. Android架构分析之Android驱动程序开发
  3. 连线:纯正Android已死 “Android兼容设备”大行其道
  4. 分享终端控制传感器或设备,形成回路控制实例
  5. C#编程如何获取电脑硬件信息的方法?
  6. 仪器设备改造技术,实现测量数据上传到服务器的功能
  7. c语言可以直接对硬件进行操作吗
  8. 升级华为网络设备(路由器,防火墙和交换机),提示空间不足,怎么解决?
  9. 在ADC设备上安装SSL证书时出现错误:“证书无效”

随机推荐

  1. Android实现控件滑动的几种方法
  2. 从零开始--系统深入学习android(实践-让我
  3. 中国电信已加盟Android阵营
  4. Android逆向之旅---Android中的sharedUse
  5. 人工智能交互集成在线语音合成能力的Tips
  6. Android Building System
  7. Android扫盲篇
  8. ContentProvider
  9. Android M新控件之FloatingActionButton,T
  10. 【Android Dev Guide - 01】 - What Is A