深入浅出 - Android系统移植与平台开发(十一) - Sensor HAL框架分析之一
作者:唐老师,华清远见嵌入式学院讲师。
1. Sensor的概念
Sensor即传感器,在当前智能手机上大量存在:G-Sensor、LightsSensor、 ProximitySensor、TemperatureSensor等,其作为Android系统的一个输入设备,对于重视用户体验的移动设备来说是必 不可少的。Sensor虽然是一个输入设备,但是它又不同于触摸屏,键盘,按键等这些常规的输入设备,因为Sensor的数据输入从传感器硬件到设备的, 而常规的输入设备是从用户到设备的,比如:温度传感器用于感知温度的变化,采样传感器数据上报给设备。而传感器硬件的工作与否,采样精度是由用户来控制 的,所以对应Sensor而言是其工作方式是双向的,即:控制硬件的控制流,硬件上报的数据流。这也决定了Sensor的框架不同与触摸屏等常规输入子系 统。
本章节主要研究的Sensor框架代码与SensorHAL的实现细节,一切还是从Sensor框架开始,首先来回顾下Led HAL的实现框架。

Led HAL是我们自己实现的,主要分为四部分:
              Led App:Led的应用程序
              Led Service框架:Led应用的API提供者
              LedService本地:LedService服务的本地实现,上层与底层的通信转化接口
              Led HAL Stub:HAL层代码,具体硬件驱动操作接口
很明显,我们写的Led HAL代码是典型的控制流,反馈结果就是Led灯的亮与灭,它的架构不适用于Sensor架构,具体有如下几点:
              l  Led是单纯的控制流,而Sensor是控制流与数据流
              Sensor的数据流不是实时的,而是有采样速率,并且数据不是连续的,阻塞在读取硬件设备数据上,只有数据得到才返回。
              l  Sensor是提供给所有传感器的通用框架,不是针对某一特定硬件的架构
              Sensor包含多种类型,在上层和底层都有对Sensor具体类型的屏蔽,让它通用所有传感器。
              l  Sensor的服务不是由应用程序创建启动的,应该是伴随系统启动的
              任何一个应用程序里都可以使用Sensor服务,这决定了Sensor服务应该伴随系统启动。
2. Sensor的框架分析
本节是本系列第一个分析的具体设备的框架,从Android SensorService的注册启动开始,到应用程序获得SensorManager注册传感器监听器,详细分析从应用层到Java框架层再到本地代码,最后调用HAL层全部过程。
1.1 Sensor服务的启动
由前面Android启动流程章节可知,Zygote启动起来后,运行的每一个Java进程是SystemServer,它用来启动并管理所有的Android服务:
[cpp] view plaincopyprint?
   1.	public static void main(String[] args) {  
           2.  …  
           3.    System.loadLibrary("android_servers");  
           4.    init1(args);  
           5.	      }
由SystemServer的main方法可知,其加载了libandroid_servers.so的库,并且调用了init1()方法。
我们通过下面的命令来找到该库的编译目录:
[plain] view plaincopyprint?
1. find ./frameworks/base –name Android.mk –exec grep –l libandroid_servers{}\;
通过打印的信息知道,其对应的源码目录在:frameworks/base/services/jni/下,其实Android框架层的代码的特点就是Java目录下存放的是对应的Java框架代码,对应的jni目录下是对应的本地代码。
在这个目录所有的代码最重要的就是:com_android_server_SystemServer.cpp:
[cpp] view plaincopyprint?
   1.	namespace android {  
           2.	  
           3.	extern "C" int system_init();  
           4.	static void android_server_SystemServer_init1(JNIEnv*env, jobject clazz)  
           5.	{  
           6.	   system_init();  
           7.	}  
           8.	/* 
           9.	 * JNIregistration. 
           10.	 */  
           11.	static JNINativeMethod gMethods[] = {  
           12.	    /* name,signature, funcPtr */  
           13.	    {"init1", "([Ljava/lang/String;)V", (void*) android_server_SystemServer_init1},  
           14.	};  
           15.	  
           16.	int register_android_server_SystemServer(JNIEnv* env)  
           17.	{  
           18.	    returnjniRegisterNativeMethods(env, "com/android/server/SystemServer",  
           19.	           gMethods, NELEM(gMethods));  
           20.	}  
           21.	  
           22.	}; // namespace android
代码不是很多,也比较好读,调用jniRegisterNativeMethods方法注册SystemServer的Java方法也本地方法映射关系,jniRegisterNativeMethods是一个本地方法的注册Helper方法。
SystemServer.java在加载了libandroid_servers.so库之后,调用了
init1(),通过上面代码中的映射关系可知,它调用了本地的android_server_SystemServer_init1方法,该方法直接调
用system_init(),其实现在frameworks/base/cmds/system_server/library
/system_init.cpp中实现:
[cpp] view plaincopyprint?
   1.	extern "C" status_t system_init()  
           2.	{  
           3.	   LOGI("Entered system_init()");
           4.	   sp<ProcessState> proc(ProcessState::self());
           5.	   sp<IServiceManager> sm = defaultServiceManager();
           6.	   LOGI("ServiceManager: %p\n", sm.get()); 
           7.	   sp<GrimReaper> grim = new GrimReaper();
           8.	   sm->asBinder()->linkToDeath(grim, grim.get(), 0);
           9.
           10.	    charpropBuf[PROPERTY_VALUE_MAX]; 
           11.	   property_get("system_init.startsurfaceflinger", propBuf,"1");
           12.	    if(strcmp(propBuf, "1") == 0) { 
           13.	        // Startthe SurfaceFlinger 
           14.	       SurfaceFlinger::instantiate();
           15.	    } 
           16.	  
           17.	    property_get("system_init.startsensorservice", propBuf,"1"); 
           18.	    if(strcmp(propBuf, "1") == 0) { 
           19.	        // Startthe sensor service
           20.	       SensorService::instantiate();
           21.	    }
           22.	    LOGI("Systemserver: starting Android runtime.\n");
           23.	   AndroidRuntime* runtime = AndroidRuntime::getRuntime(); 
           24.
           25.	   LOGI("System server: starting Android services.\n"); 
           26.	    JNIEnv* env =runtime->getJNIEnv(); 
           27.	    if (env ==NULL) { 
           28.	        returnUNKNOWN_ERROR;
           29.	    }
           30.
           31.	    jclass clazz= env->FindClass("com/android/server/SystemServer");
           32.	    if (clazz ==NULL) {  
           33.	        returnUNKNOWN_ERROR; 
           34.	    }
           35.
           36.	    jmethodIDmethodId = env->GetStaticMethodID(clazz, "init2","()V");
           37.	    if (methodId== NULL) {  
           38.	        returnUNKNOWN_ERROR; 
           39.	    } 
           40.	   env->CallStaticVoidMethod(clazz, methodId);
           41.
           42.	    LOGI("System server: entering thread pool.\n");
           43.	   ProcessState::self()->startThreadPool(); 
           44.	   IPCThreadState::self()->joinThreadPool(); 
           45.	   LOGI("System server: exiting thread pool.\n");
           46.	}
如果了解Binder机制的话,应该知道,sp proc(ProcessState::self())打开Binder驱动并会创建一个ProcessState对象并维持当前进程的Binder通信的服务器端。
如果系统属性里配置了system_init.startsensorservice 属性为1,则通过SensorService::instantiate()启动Sensor服务。
对于初学者最头疼的就是追面向对象代码中的重载,重写的代码
了,SensorService::instantiate()调用的是其父类的方法,我们可以通过子类的定义找其继承关系,然后顺着继承关系再来查找方
法的实现,如果在子类里和父类里都有方法的实现,那么看参数的匹配,如果参数都相互匹配,那么就是所谓的重写,调用的是子类的方法。
SensorService的定义如下:
@frameworks/base/services/sensorservice/SensroService.h
[cpp] view plaincopyprint?
   1.	class SensorService :  
           2.	        publicBinderService,  
           3.	        publicBnSensorServer,  
           4.	        protectedThread  
           5.	{
通过SensorService的定义可知,在当前类里没有instantiate方法的声明,说明其调用
的是父类的方法,其继承了BinderService,BnSensorServer,Thread类(难道SensorService是一个线
程??),顺着继承关系找,在BinderService里可以找到instantiate方法的声明。
@frameworks/base/include/binder/BinderService.h
[cpp] view plaincopyprint?
   1.	template  
           2.	  
           3.	class BinderService  
           4.	{  
           5.	public:  
           6.	    static status_t publish() {  
           7.	       sp sm(defaultServiceManager());  
           8.	       returnsm->addService(String16(SERVICE::getServiceName()), new SERVICE());  
           9.	    }  
           10.	  
           11.	    static void publishAndJoinThreadPool() {  
           12.	       sp proc(ProcessState::self());  
           13.	       sp sm(defaultServiceManager());  
           14.	       sm->addService(String16(SERVICE::getServiceName()), new SERVICE());  
           15.	       ProcessState::self()->startThreadPool();  
           16.	       IPCThreadState::self()->joinThreadPool();  
           17.	    }  
           18.	  
           19.	    static void instantiate() { publish(); }  
           20.	  
           21.	    static status_t shutdown() {  
           22.	        return NO_ERROR;  
           23.	    }  
           24.	};
通过上面代码分析可知,instantiate方法创建了SensorService并通过addService将自己新创建的SensorService服务添加到Android服务列表里了。
Ok,那我们来到SensorService服务中。
@frameworks/base/services/sensorservice/SensorService.cpp
[cpp] view plaincopyprint?
   1.	SensorService::SensorService()  
           2.	    :mInitCheck(NO_INIT)  
           3.	{  
           4.	}  
           5.	  
           6.	void SensorService::onFirstRef()  
           7.	{  
           8.	   LOGD("nuSensorService starting...");  
           9.	   SensorDevice& dev(SensorDevice::getInstance());  
           10.	…
SensorService的构造方法比较简单,初始化了成员变量mInitCheck为NO_INIT。
要注意构造方法后面的onFirstRef方法,它是Android系统里引用计数系统里的一个方法。当RefBase的子类对象被第一次强引用时自动调用其方法,所以当第一次使用SensorService服务里该方法被自动回调。
形如:
[cpp] view plaincopyprint?
1. sp< ISensorServer> sm(mSensorService);
注:关于引用计数系统,如果读者不太了解,请参考邓凡平老师的:深入理解:Android系统核心 卷I中的三板斧部分。
SensorService的启动到此暂停,等待上层应用的使用SensorService服务并调用onFirstRef方法。
文章来源:华清远见嵌入式学院,原文地址:http://www.embedu.org/Column/Column770.htm
深入浅出 - Android系统移植与平台开发(十一) - Sensor HAL框架分析之一的更多相关文章
- 深入浅出 - Android系统移植与平台开发(一)
		
深入浅出 - Android系统移植与平台开发(一) 分类: Android移植2012-09-05 14:16 16173人阅读 评论(12) 收藏 举报 androidgitgooglejdkub ...
 - 深入浅出 - Android系统移植与平台开发(十) - led HAL简单设计案例分析
		
作者:唐老师,华清远见嵌入式学院讲师. 通过前两节HAL框架分析和JNI概述,我们对Android提供的Stub HAL有了比较详细的了解了,下面我们来看下led的实例,写驱动点亮led灯,就如同写程 ...
 - 深入浅出 - Android系统移植与平台开发(十一)- Android系统的定制(瘋耔修改篇一)
		
首先非常感谢原文作者为我们提供的知识库,因为有你们的贡献,我们的开发难度更显简单 原文 : http://blog.csdn.net/mr_raptor/article/details/30113 ...
 - 深入浅出 - Android系统移植与平台开发(三)- 编译并运行Android4.0模拟器
		
作者:唐老师,华清远见嵌入式学院讲师. 1. 编译Android模拟器 在Ubuntu下,我们可以在源码里编译出自己的模拟器及SDK等编译工具,当然这个和在windows里下载的看起来没有什么区别 ...
 - 深入浅出 - Android系统移植与平台开发(五)- 编译Android源码(转)
		
2.3编译Android源码 Android源码体积非常庞大,由Dalvik虚拟机.Linux内核.编译系统.框架代码.Android定制C库.测试套件.系统应用程序等部分组成,在编译Android源 ...
 - 深入浅出 - Android系统移植与平台开发(十)- Android编译系统与定制Android平台系统(瘋耔修改篇二)
		
第四章.Android编译系统与定制Android平台系统 4.1Android编译系统 Android的源码由几十万个文件构成,这些文件之间有的相互依赖,有的又相互独立,它们按功能或类型又被放到不同 ...
 - 深入浅出 - Android系统移植与平台开发(二) - 准备Android开发环境
		
作者:唐老师,华清远见嵌入式学院讲师. 编译Android源码 关于android系统的编译,Android的官方网站上也给出了详细的说明.http://source.android.com/sour ...
 - 深入浅出 - Android系统移植与平台开发(六)- 为Android启动加速
		
作者:唐老师,华清远见嵌入式学院讲师. Android的启动速度一直以来是他的诟病,虽然现在Android设备的硬件速度越来越快,但是随着新 版本的出现,其启动速度一直都比较慢,当然,作为程序员,我们 ...
 - 深入浅出 - Android系统移植与平台开发(七)- 初识HAL
		
作者:唐老师,华清远见嵌入式学院讲师. 1. HAL的module与stub HAL(Hardware AbstractLayer)硬件抽象层是Google开发的Android系统里上层应用对底层硬件 ...
 
随机推荐
- 深入理解JavaScript定时机制和定时器注意问题
			
容易欺骗别人感情的JavaScript定时器 JavaScript的setTimeout与setInterval是两个很容易欺骗别人感情的方法,因为我们开始常常以为调用了就会按既定的方式执行, 我想不 ...
 - android 入门-动画与容器
			
set 动画容器 可作为资源id添加R.anim.xxxx 可用于在样式表中添加 http://blog.csdn.net/liuhe688/article/details/6660823 in ...
 - ARM指令学习,王明学learn
			
ARM指令学习 一.算数和逻辑指令 1— MOV 数据传送指令 2.— MVN 数据取反传送指令 3.— CMP 比较指令 4.— CMN 反值比较指令 5.— TST 位测试 ...
 - Effective C++ 之 Item 3:尽可能使用 const
			
Effective C++ Chapter 1. 让自己习惯C++(Accustoming Yourself to C++) Item 3. 尽可能使用 const (Use const whenev ...
 - 剑指offer系列——二维数组中,每行从左到右递增,每列从上到下递增,设计算法找其中的一个数
			
题目:二维数组中,每行从左到右递增,每列从上到下递增,设计一个算法,找其中的一个数 分析: 二维数组这里把它看作一个矩形结构,如图所示: 1 2 8 2 4 9 12 4 7 10 13 6 8 11 ...
 - 《数据结构与算法分析》学习笔记(五)——二叉树
			
(一)查找二叉树ADT 1.二叉查找树ADT性质: 对于树中的每个节点X,它的左子树中所有关键字值都小于X的关键字值,而它的右子树值的关键字值都大于X的关键字值. 2.一些ADT的基本操作 结 ...
 - SQL.WITH AS.公用表表达式(CTE)(转)
			
一.WITH AS的含义 WITH AS短语,也叫做子查询部分(subquery factoring),可以让你做很多事情,定义一个SQL片断,该SQL片断会被整个SQL语句所用到.有的时候,是 ...
 - express-15 与生产相关的问题
			
执行环境 Express支持执行环境的概念,它是一种在生产.开发或测试模式中运行应用程序的方法.实际上你可以按自己的想法创建很多种不同的环境. 要记住,开发.生产和测试是"标准"环 ...
 - Java 程序员们值得一看的好书推荐[转载]
			
“学习的最好途径就是看书“,这是我自己学习并且小有了一定的积累之后的第一体会.个人认为看书有两点好处: 能出版出来的书一定是经过反复的思考.雕琢和审核的,因此从专业性的角度来说,一本好书的价值远超其他 ...
 - 分享Kali Linux 2016.2第46周镜像文件
			
分享Kali Linux 2016.2第46周镜像文件Kali Linux官网在11月13日发布Kali Linux 2016.2的第46周镜像文件.这次还是保持以往的规模,总共提供了11个镜像文件. ...