深入浅出 - Android系统移植与平台开发(十一) - Sensor HAL框架分析之一

来源:互联网 发布:淘宝1个好评是几分 编辑:程序博客网 时间:2024/06/06 11:41

作者:唐老师,华清远见嵌入式学院讲师。

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?

                   . 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

更多相关嵌入式免费资料查看华清远见讲师博文

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 合约机移动违约不返话费我该怎么办 电信手机卡合约套餐要到期了怎么办 苹果6s联通4g网速慢怎么办 营业厅买到的不是全网通手机怎么办 全网通手机联通卡被禁用怎么办 红米5手机关机充电自动开机怎么办 华为平板怎么解锁密码忘了怎么办 华为荣耀手机开锁密码忘记了怎么办 畅玩7x密码忘了怎么办 过了时的手机没有刷机包怎么办? 刷了个刷机包游戏玩不了了怎么办? 华为麦芒5手机外放声音小怎么办 微信显示存储卡已拔出怎么办 储存卡已拔出微信头像不可用怎么办 智能手机的电话卡取不出来了怎么办 换了苹果手机通讯录没了怎么办 手机玻璃膜一角翘起来了怎么办 华为畅玩7x耗电快怎么办 魅蓝5s充电器死机了怎么办 苹果手机乐动力不计步数怎么办 意大利居留按手印时间过了怎么办 酷派t1手机解析包出现问题怎么办 p新买的手机壳有味怎么办 门锁钥匙口竖着钥匙放不进去怎么办 摩拜单车被别人骑走了怎么办 捡到苹果8p手机怎么办才能自己用 用力按压导致玻尿酸变形移位怎么办 华为麦芒5应用锁密码忘了怎么办 华为麦芒6应用锁密码忘了怎么办 华为手机的设置不在桌面了怎么办 华为手机所有应用都不在桌面怎么办 华为麦芒5设置页面不显示怎么办 华为麦芒5主屏页面不显示怎么办 6s p换屏幕原装太贵怎么办 4g手机开不开机黑屏怎么办 华为麦芒5 4g信号差怎么办 华为麦芒手机锁屏密码忘了怎么办 华为麦芒5相机拍相片倒了怎么办 红米5a开不了机怎么办 华为沾了海水打不开机怎么办 华为麦芒手机忘记锁屏密码怎么办