背景

    近几年是互联网高速发展的几年,孕育出了如谷歌、阿里巴巴等许多超级互联网公司,随着互联网的发展已经触到了天花板,一个比互联网更大的市场即将打开,那就是物联网(Internet of Things)。IOT就是将现实世界中的物体连到互联网上,使得物与物、人与物可以很方便的互相沟通,将是下一个规模更大网络发展机遇的风口,是一个高科技公司抢占技术高地和风口,谷歌近日发布了第一代物联网平台操作系统Android Things。华为也推出了IOT操作系统LiteOS。

    说到IOT,我们最多的是理解成智能硬件,万物互联;确实,IOT系统的每个节点都是不同的智能硬件,都是不同的网络智能终端设备。咱们丰巢快递智能柜也在某种程度上说也属于IOT设备。所以开发基于Android系统的丰巢智能柜,高铁寄存柜;我们有必要去搞懂Android的硬件系统和HAL层,正好我以前有过Android系统开发和HAL驱动开发的经验,和大家分享讨论下硬件相关知识。

整体架构

    如图,Android系统的整个架构由五层结构组成:

  • 应用层(Applications):这一层主要用于手机应用的安装,如系统自带联系人、短信等程序,或是第三方应用程序;
  • 应用框架层(Application framework):这一层主要提供构建应用程序时可能用到的各种API,Android自带的一些核心应用就是使用这些API完成的,开发者也可通过使用API来构建自己的应用程序;
  • 系统运行库层(Libraries And Runtimes):这一层通过一些C/C++库(so库)来为Android系统提供了主要的特性支持。如SQLite库提供了数据库支持,OpenGL ES库提供了3D绘图支持,Webkit库提供了浏览器内核支持等;
  • 硬件抽象层(hardware abstraction layer):安卓驱动硬件的方式与Linux不尽相同。传统Linux的驱动完全存活于内核空间。硬件抽象层(HAL, Hardware Abstraction Layer),把一部分驱动功能放到HAL层中。安卓为什么费尽麻烦增加一个HAL呢?为了保护源代码。Linux内核采用了GPL协议,所以硬件生产商想要支持Linux系统,必须遵照GPL协议公开硬件驱动的源代码。但这些源代码中包含有许多硬件的设计信息,牵涉到硬件生产商的核心利益。而增加了HAL层之后,硬件厂商就不需要开放所有的驱动代码了。
  • Linux内核层(Linux Kernel):Android系统基于Linux2.6内核,这一层为Android设备各种硬件提供了底层驱动,如显示驱动、音频驱动、照相机驱动、蓝牙驱动、Wi-Fi驱动、电源管理等;

    Android HAL层不是Android一直都存在的,是从android4.0.3开始才加入的。Android的HAL是为了保护一些硬件提供商的知识产权而提出的,是为了避开linux的GPL束缚。思路是把控制硬件的动作都放到了Android HAL中,而linux driver仅仅完成一些简单的数据交互作用,甚至把硬件寄存器空间直接映射到user space。而Android是基于Aparch的license,因此硬件厂商可以只提供二进制代码,所以说Android只是一个开放的平台,并不是一个开源的平台。也许也正是因为Android不遵从GPL,所以Greg Kroah-Hartman才在2.6.33内核将Andorid驱动从linux中删除。GPL和硬件厂商目前还是有着无法弥合的裂痕。Android想要把这个问题处理好也是不容易的。

总结下来,Android HAL存在的原因主要有:

1. 并不是所有的硬件设备都有标准的linux kernel的接口;
2. KERNEL DRIVER涉及到GPL的版权。某些设备制造商并不原因公开硬件驱动,所以才去用HAL方 式绕过GPL;
3. 针对某些硬件,Android有一些特殊的需求

硬件系统架构介绍

    目前存在两种HAL架构,位于libhardware_legacy目录下的“旧硬件架构架构”和位于libhardware目录下的“新HAL架构”。两种框架如下图所示。

    老的硬件架构libhardware_legacy 是将 *.so 文件当作shared library来使用,在runtime(JNI 部份)以 direct function call 使用 HAL module。通过直接函数调用的方式,来操作驱动程序。当然,应用程序也可以不需要通过 JNI 的方式进行,直接加载 .so (dlopen)的做法调用.so 里的符号(symbol)也是一种方式。总而言之是没有经过封装,上层可以直接操作硬件。

    现在的 libhardware HAL架构,就有stub的味道了。HAL stub 是一种代理人(proxy)的概念,stub 虽然仍是以 *.so库的形式存在,但HAL已经将 *.so 库隐藏起来了。Stub 向 HAL提供操作函数(operations),而 runtime 则是向 HAL 取得特定模块(stub)的 operations,再 callback 这些操作函数。这种以 indirect function call 的架构,让HAL stub 变成是一种包含关系,即 HAL 里包含了许许多多的 stub(代理人)。Runtime 只要说明类型,即 module ID,就可以取得操作函数。对于目前的HAL,可以认为Android定义了HAL层结构框架,通过几个接口访问硬件从而统一了调用方式。

硬件架构源码分析

    下面我们从普通的振动器硬件的控制vibrate使用开始,从振动器服务的获取getSystemService方法,然后到硬件服务的调用,然后通过HAL硬件抽象层打开硬件驱动节点文件读写等操作,然后到Linux内核态驱动程序,以及处理器芯片引脚的控制与芯片时序驱动,一步一步讲解Android的新的硬件系统架构HAL架构是怎么进行硬件设备调度和控制的…
         [外链图片转存失败]

APP层

Android应用层对振动器的调用形式一般是,通过获取到Vibrator实例后,通过实例方法vibrate来控制震动器的振动操作

Vibrator mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
mVibrator.vibrate(500);

通过源码跟踪,通常调getSystemService调的是ContextImpl里面的getSystemService方法

framework层

位置:frameworks\base\core\java\android\app\ContextImpl.java

@Override
public Object getSystemService(String name) {ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);return fetcher == null ? null : fetcher.getService(this);
}

可以看出是从SYSTEM_SERVICE_MAP集合里面通过那么作为key进行取出ServiceFetcher,然后getService获取到服务的实例。那SYSTEM_SERVICE_MAP集合里面存的服务实例是从哪里来呢?

private static final HashMap<String, ServiceFetcher> SYSTEM_SERVICE_MAP =new HashMap<String, ServiceFetcher>();private static void registerService(String serviceName, ServiceFetcher fetcher) {if (!(fetcher instanceof StaticServiceFetcher)) {fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++;}SYSTEM_SERVICE_MAP.put(serviceName, fetcher);
}private static void registerService(String serviceName, ServiceFetcher fetcher) {if (!(fetcher instanceof StaticServiceFetcher)) {fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++;}SYSTEM_SERVICE_MAP.put(serviceName, fetcher);}static {...registerService(VIBRATOR_SERVICE, new ServiceFetcher() {public Object createService(ContextImpl ctx) {return new SystemVibrator(ctx);}});...
}

实际上SYSTEM_SERVICE_MAP里面添加的服务Fetcher是通过类静态块进行registerService注册进去的。接下来我们看看SystemVibrator类的实现

位置:frameworks\base\core\java\android\os\SystemVibrator.java


public class SystemVibrator extends Vibrator {private static final String TAG = "Vibrator";private final IVibratorService mService;private final Binder mToken = new Binder();public SystemVibrator() {mService = IVibratorService.Stub.asInterface(ServiceManager.getService("vibrator"));}public SystemVibrator(Context context) {super(context);mService = IVibratorService.Stub.asInterface(ServiceManager.getService("vibrator"));}@Overridepublic boolean hasVibrator() {...return mService.hasVibrator();}/*** @hide*/@Overridepublic void vibrate(int uid, String opPkg, long milliseconds, AudioAttributes attributes) {...mService.vibrate(uid, opPkg, milliseconds, usageForAttributes(attributes), mToken);}...@Overridepublic void cancel() {...mService.cancelVibrate(mToken);}
}

SystemVibrator类相当于一个代理类,主要是通过Binder通信拿到IVibratorService,然后去远程调用对应的方法
,我们看到远程的Service IBinder是怎么获取过来的,看看ServiceManager.getService(“vibrator”)查找ServiceManager的getService方法的具体实现

位置:frameworks\base\core\java\android\os\ServiceManager.java

public final class ServiceManager {private static final String TAG = "ServiceManager";private static IServiceManager sServiceManager;private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();private static IServiceManager getIServiceManager() {if (sServiceManager != null) {return sServiceManager;}// Find the service managersServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());return sServiceManager;}....public static IBinder getService(String name) {try {IBinder service = sCache.get(name);if (service != null) {return service;} else {return getIServiceManager().getService(name);}} catch (RemoteException e) {Log.e(TAG, "error in getService", e);}return null;}public static void addService(String name, IBinder service) {try {getIServiceManager().addService(name, service, false);} catch (RemoteException e) {Log.e(TAG, "error in addService", e);}}....}

ServiceManager.getService(“vibrator”)获取到的IBinder是从sCache HashMap里面获取到的,我们查查是怎么添加进去的。

位置:frameworks\base\services\java\com\android\server\SystemServer.java

public static void main(String[] args) {new SystemServer().run();
}//run
private void run() {...//开始启动服务startBootstrapServices();//开启核心服务startCoreServices();//开启另外一些服务startOtherServices();...
}
//startOtherServices
private void startOtherServices() {...Slog.i(TAG, "Vibrator Service");vibrator = new VibratorService(context);ServiceManager.addService("vibrator", vibrator);
}

系统在初始化时候,SystemServer.main()方法,然后调用run调用了startOtherServices()这时候可以看出其实是在SystemServer注册了VibratorService服务,然后加入了ServiceManager里面去管理.想知道Android系统启动流程,可以看看我的另外一篇博客:https://blog.csdn.net/zgkxzx/article/details/88623498

位置:frameworks\base\services\core\java\com\android\server\VibratorService.java

public class VibratorService extends IVibratorService.Stubimplements InputManager.InputDeviceListener {native static boolean vibratorExists();native static void vibratorOn(long milliseconds);native static void vibratorOff();...@Override // Binder callpublic void vibrate(int uid, String opPkg, long milliseconds, int usageHint,IBinder token) {...startVibrationLocked(vib);}//private void startVibrationLocked(final Vibration vib) {...//开启VibrateThread线程mThread = new VibrateThread(vib);mThread.start();}}private class VibrateThread extends Thread {public void run() {...VibratorService.this.doVibratorOn(duration, uid, usageHint);}}private void doVibratorOn(long millis, int uid, int usageHint) {...//调用JNI Native本地方法vibratorOn(millis);}}}

VibratorService服务通过创建了VibrateThread线程,然后去调用Native本地端的振动器的接口vibratorOn方法

HAL层

位置:frameworks\base\services\core\jni\com_android_server_VibratorService.cpp

#include <hardware_legacy/vibrator.h>#include <stdio.h>namespace android
{static hw_module_t *gVibraModule = NULL;
static vibrator_device_t *gVibraDevice = NULL;static void vibratorInit(JNIEnv /* env */, jobject /* clazz */)
{...int err = hw_get_module(VIBRATOR_HARDWARE_MODULE_ID, (hw_module_t const**)&gVibraModule);}static void vibratorOn(JNIEnv* /* env */, jobject /* clazz */, jlong timeout_ms)
{...int err = gVibraDevice->vibrator_on(gVibraDevice, timeout_ms);}static void vibratorOff(JNIEnv* /* env */, jobject /* clazz */)
{...int err = gVibraDevice->vibrator_off(gVibraDevice);
}static const JNINativeMethod method_table[] = {{ "vibratorExists", "()Z", (void*)vibratorExists },{ "vibratorInit", "()V", (void*)vibratorInit },{ "vibratorOn", "(J)V", (void*)vibratorOn },{ "vibratorOff", "()V", (void*)vibratorOff }
};int register_android_server_VibratorService(JNIEnv *env)
{return jniRegisterNativeMethods(env, "com/android/server/VibratorService",method_table, NELEM(method_table));
}};

com_android_server_VibratorService.cpp 这个典型的HAL抽象层,通过hw_get_module获取到hw_module_t硬件模块描述结构体对象,然后对改对象进行vibratorOn或vibratorOff调用控制。

位置:hardware/libhardware/modules/vibrator/vibrator.c

#include <hardware/vibrator.h>
#include <hardware/hardware.h>static const char THE_DEVICE[] = "/sys/class/timed_output/vibrator/enable";static int sendit(unsigned int timeout_ms)
{int to_write, written, ret, fd;...//获取到驱动设备节点的文件描述符fd = TEMP_FAILURE_RETRY(open(THE_DEVICE, O_RDWR));//对设备文件进行写操作written = TEMP_FAILURE_RETRY(write(fd, value, to_write));//关闭文件close(fd);return ret;
}static int vibra_on(vibrator_device_t* vibradev __unused, unsigned int timeout_ms)
{return sendit(timeout_ms);
}static int vibra_off(vibrator_device_t* vibradev __unused)
{return sendit(0);
}static int vibra_close(hw_device_t *device)
{free(device);return 0;
}static int vibra_open(const hw_module_t* module, const char* id __unused,hw_device_t** device __unused) {vibradev->common.tag = HARDWARE_DEVICE_TAG;vibradev->common.module = (hw_module_t *) module;vibradev->common.version = HARDWARE_DEVICE_API_VERSION(1,0);vibradev->common.close = vibra_close;vibradev->vibrator_on = vibra_on;vibradev->vibrator_off = vibra_off;*device = (hw_device_t *) vibradev;return 0;
}static struct hw_module_methods_t vibrator_module_methods = {.open = vibra_open,
};struct hw_module_t HAL_MODULE_INFO_SYM = {.tag = HARDWARE_MODULE_TAG,.module_api_version = VIBRATOR_API_VERSION,.hal_api_version = HARDWARE_HAL_API_VERSION,.id = VIBRATOR_HARDWARE_MODULE_ID,.name = "Default vibrator HAL",.author = "The Android Open Source Project",.methods = &vibrator_module_methods,
};

这里是com_android_server_VibratorService.cpp文件的头文件,主要是HAL的接口描述映射关系,以及Linux用户层的驱动文件打开与控制,vibra_on与vibra_off实际上最终能调用的是sendit函数,通过open方法打开驱动节点/sys/class/timed_output/vibrator/enable进行写操作,来实现振动器Vibrator硬件设备的控制。

Linux驱动层

位置:drivers/misc/misc_sysfs.c

#include <linux/kernel.h>
...
#include <mach/gpio.h>// vibrator 对应的GPIO#define  VIBRATOR_POWER_PORT (EXYNOS4_GPD(1))static unsigned char vibrator_status = 0;static void vibrate_init(void){int ret;ret = gpio_request(VIBRATOR_POWER_PORT, "GPX1");if(ret)printk("open  vibrator device fail\n");//VIBRATOR_POWER_PORT引脚加入上拉配置s3c_gpio_setpull(VIBRATOR_POWER_PORT, S3C_GPIO_PULL_UP);//VIBRATOR_POWER_PORT引脚输出低电平gpio_direction_output(VIBRATOR_POWER_PORT, vibrator_status);}//读函数static ssize_t show_vibrator_onoff (struct device *dev, struct device_attribute *attr, char *buf){return    vibrator_status;}//写函数static ssize_t set_vibrator_onoff (struct device *dev, struct device_attribute *attr, const char *buf, size_t count){unsigned int    vibrator_status;if(!(sscanf(buf, "%u\n", &vibrator_status)))     return    -EINVAL;if(!vibrator_status )    {vibrator_status = 0;//VIBRATOR_POWER_PORT引脚输出低电平gpio_direction_output(VIBRATOR_POWER_PORT, GPIO_LOW);} else  {vibrator_status = 1;//VIBRATOR_POWER_PORT引脚输出高电平gpio_direction_output(VIBRATOR_POWER_PORT, GPIO_HIGH);}return count;}static    ssize_t show_vibrator_onoff    (struct device *dev, struct device_attribute *attr, char *buf);static     ssize_t set_vibrator_onoff    (struct device *dev, struct device_attribute *attr, const char *buf, size_t count);static DEVICE_ATTR(vibrator_onoff, S_IRWXUGO, show_vibrator_onoff, set_vibrator_onoff);static struct attribute *control_sysfs_entries[] = {&dev_attr_vibrator_onoff.attr,NULL};static struct attribute_group control_sysfs_attr_group = {.name   = NULL,.attrs  = control_sysfs_entries,};
//探测函数,驱动框架第一个初始化的函数static int control_sysfs_probe(struct platform_device *pdev)    {printk("vibrator probe");vibrate_init();return    sysfs_create_group(&pdev->dev.kobj, &control_sysfs_attr_group);}staticint control_sysfs_remove(struct platform_device *pdev)    {sysfs_remove_group(&pdev->dev.kobj, &control_sysfs_attr_group);return    0;}static struct platform_driver control_sysfs_driver = {.driver = {.name = "misc_ctl",.owner = THIS_MODULE,},.probe         = control_sysfs_probe,.remove     = control_sysfs_remove,};// 将vibrator注册到platform总线static int __init control_sysfs_init(void){    return platform_driver_register(&control_sysfs_driver);}static void __exit control_sysfs_exit(void){platform_driver_unregister(&control_sysfs_driver);}module_init(control_sysfs_init);module_exit(control_sysfs_exit);MODULE_DESCRIPTION("misc control driver for zgkxzx");MODULE_AUTHOR("other");MODULE_LICENSE("GPL");

Android HAL硬件抽象层与硬件系统架构相关推荐

  1. Android源码之Camera系统架构

    2019独角兽企业重金招聘Python工程师标准>>> https://blog.csdn.net/ljsbuct/article/details/7094670 https://w ...

  2. Android Automotive (二)系统架构

    Android Automotive (二)系统架构 前面简单介绍了一下Android Automotive 的架构,具体Android Automotive 在系统的每个层,都做了哪些东西,这里总结 ...

  3. 【Android 源码学习】系统架构和启动流程

    Android 源码学习 系统架构和启动流程 望舒课堂 学习记录整理.以及以下参考文章的整理汇总.便于我个人的学习记录. 感谢IngresGe,Gityuan的精彩文章.为我们这些初探android系 ...

  4. Android开发精要1--Android系统架构

    1.1 Android系统架构概况 下图是Android系统架构图,从图中可以看出,划分为三个部分: 1>应用部分 :包含在Android设备上运行的所有应用,它们是Android系统中直接面向 ...

  5. 如果你是12306网站架构师,你会如何设计网站的软件架构和硬件系统架构?

    今年火车票网上售票的情况大家都见到了,如果让你来设计该订票网站,你会如何设计才能应对如此大规模以及高并发的情况呢? 邵辉 13 票 806 列车在线订票系统的业务逻辑比较简单,不用多说.可能的瓶颈有两 ...

  6. 4D毫米波雷达硬件系统架构

    1 毫米波雷达与自动驾驶系统 4D毫米波雷达与车载自动驾驶系统的关系紧密,聊4D毫米波雷达,肯定抛不开自动驾驶系统.自动驾驶系统分为感知层(sense).决策层(think)和执行层(act). 感知 ...

  7. [转载]如果你是12306网站架构师,你会如何设计网站的软件架构和硬件系统架构?...

    转载至德问网站.链接地址为:http://www.dewen.org/q/963/?ts=edm20121018&e=MzAyNjY5NzU3QHFxLmNvbQ%3D%3D 今年火车票网上售 ...

  8. Minieye-M3 防撞预警产品硬件系统方案---基于AR0132RGB+MTK架构

    (1).产品规格 (2).硬件系统架构 camera sensor:AR0132RGB datesheet: https://docplayer.net/37244212-1-3-inch-cmos- ...

  9. ARM 之十五 扫盲 ARM 架构、指令集、微架构、系统架构、ARM IP、授权方式

      ARM 架构的 MCU 用了好多年,进一步对于 ARM 架构也或多或少的有了一些了解.之前都是遇到啥问题直接去官网找对应的手册,一直没有系统的总结一下.是时候总结一下,以便进行下一步学习了! 总的 ...

最新文章

  1. jdk8飞行记录器配置
  2. 吴恩达老师深度学习视频课笔记:单隐含层神经网络公式推导及C++实现(二分类)
  3. 浅析微信支付:统一下单接口
  4. 安卓移动应用开发考题_Android移动应用试卷试题带答案.doc
  5. Linux中look命令,如何在Linux上使用look命令 | MOS86
  6. python多种推导式的实现
  7. 【Linux】一步一步学Linux——pstree命令(120)
  8. SQL Server T-SQL编程:数据库用户与安全设置
  9. 牛客网CSP-S提高组赛前集训营1题解(仓鼠的石子游戏 [博弈论] + 乃爱与城市的拥挤程度 [树上DP] + 小w的魔术扑克[dfs + 离线])
  10. 从云数据迁移服务看MySQL大表抽取模式
  11. w7设置双显示器_怎么在windows7系统下设置双显示器
  12. Windows Live Writer
  13. 零基础用阿里云服务器搭建网站的步骤
  14. BCD码中的8421码、2421码、5421码和余3码
  15. 使用Spring Validation 完成后端数据校验
  16. 数据中心产业深度报告:IDC产业链景气周期及投资框架分析
  17. 【大二下复习】新视野大学英语(第三版)第四册读写教程答案 + 期末复习翻译的部分题目
  18. BZOJ1189 [HNOI2007]紧急疏散evacuate
  19. ESP8266-Arduino编程实例-LIS3MDL磁场传感器驱动
  20. NFC芯片群读应用,RFID娱乐筹码、棋子FPC定制标签

热门文章

  1. 三中新教学楼信息系统集成方案
  2. 数商云医药医疗行业B2B平台:如何赋能企业数字化转型,破局传统医药通路难题
  3. 京东某被裁员工:虽然公司裁掉了我,但我不能裁掉我的未来!
  4. 百度站长平台召开百度之夜会议:打造良性搜索生态
  5. 想转SAP FICO顾问的必看(转)
  6. 鼎新TIPTOP GP5.25鼎捷易拓GP5.25视频教程26模块操作及开发
  7. matplotlib从折线图入门并解决中文乱码
  8. css3探测光圈_CSS3按钮鼠标悬浮实现光圈效果
  9. 【数位板常见问题】压感笔为什么没有压感了
  10. html取消ul下划线,css – 删除下划线:hover:before