android中Sensor 工作流程
| JAVA 程序 我们使用 sensor 接口一般只要注册一下 SensorListener 像下面这样 ************************************************************** ApiDemo: mGraphView = new GraphView(this); mSensorManager.registerListener(mGraphView,....); ************************************************************** 这里的 listener 是因为 sensor 状态变化要产生变化的控件 然后在控件里重载 on SensorChanged 和 onAccuracyChanged 方法 public void onSensorChanged(int sensor, float[] values) public void onAccuracyChanged(int sensor, int accuracy) SensorManager Sensor 主体代码和流程在 frameworks/base/core/java/android/hardware/SensorManager.java 里面 1.registerListener 其实是调用 registerLegacyListener: public boolean registerListener(SensorListener listener, int sensors, int rate) { ... result = registerLegacyListener(...); ... } 2. registerLegacyListener 其实就是构造一个 LegacyListener 对象并将其加入 HashMap 中去 private boolean registerLegacyListener(int legacyType, int type, SensorListener listener, int sensors, int rate) { ... legacyListener = new LegacyListener(listener); mLegacyListenersMap.put(listener, legacyListener); //private HashMap<SensorListener, LegacyListener> mLegacyListenersMap ... } 3. LegacyListener 做了 2 件事 一个是调用我们重载的那 2 个接口 还有一个就是将 sensor 的 数据刷到我们的设备显示界面上去 private class LegacyListener implements SensorEventListener { ... LegacyListener(SensorListener target) { mTarget = target; mSensors = 0; } public void onSensorChanged(SensorEvent event) { ... mapSensorDataToWindow(); mTarget.onSensorChanged(...);//private SensorListener mTarget; ... } public void onAccuracyChanged(Sensor sensor, int accuracy) { ... } } 代码最后是一些 native 方法: private static native void nativeClassInit();//SensorManager 构造函数里调用 private static native int sensors_module_init();//SensorManager 构造函数里调用 private static native int sensors_module_get_next_sensor(Sensor sensor, int next);//SensorManager 构造函数里调用 // Used within this module from outside SensorManager, don't make private static native int sensors_data_init();//SensorThread 构造里调用 static native int sensors_data_uninit();//SensorThread 析构里调用 static native int sensors_data_open(FileDescriptor fd); //SensorThread 的 run()循环调用 static native int sensors_data_close();//SensorThread 的 run()循环调用 static native int sensors_data_poll(float[] values, int[] status, long[] timestamp);//SensorThread 的 run()循环调用 SensorManager 与 IsensorService 的关系 SensorManager 调用 IsensorService 其实只是调用了 service 的方法来控制 thread 是 Lock void startLocked(ISensorService service) { ... ParcelFileDescriptor fd = service.getDataChanel(); ... } 或者打开 mSensorService.enableSensor(l, name, handle, delay); IsensorService 的实例是这么获得的 mSensorService = ISensorService.Stub.asInterface( ServiceManager.getService(Context.SENSOR_SERVICE)); IsensorService 是通过 aidl 定义的 interface ISensorService { ParcelFileDescriptor getDataChanel(); boolean enableSensor(IBinder listener, String name, int sensor, int enable); } SensorService frameworks/base/services/java/com/android/server/SensorService.java class SensorService extends ISensorService.Stub { ... } service 最终被 manager 调到走的是 android 的标准流程我们不 care,我们想知道的其实就是 enableSensor 的实现 首先,得有电 if (enable == SENSOR_DISABLE) { mBatteryStats.noteStopSensor(uid, sensor); } else { mBatteryStats.noteStartSensor(uid, sensor); } 看是不是能打开 sensor if (enable!=SENSOR_DISABLE && !_sensors_control_activate(sensor, true)) { Log.w(TAG, "could not enable sensor " + sensor); return false; } 如果 sensor 打开了 我们要监听状态还要对外面报告状态变化 if (l == null && enable!=SENSOR_DISABLE) { l = new Listener(binder); binder.linkToDeath(l, 0); mListeners.add(l); mListeners.notify(); } 如果 sensor 被关闭了 我们要取消监听并且告诉外面关闭了传感 if (enable != SENSOR_DISABLE) { l.addSensor(sensor, enable); } else { l.removeSensor(sensor); deactivateIfUnused(sensor); if (l.mSensors == 0) { mListeners.remove(l); binder.unlinkToDeath(l, 0); mListeners.notify(); } } 另外还有一些唤醒和设置延迟的动作 if (mListeners.size() == 0) { _sensors_control_wake(); } if (minDelay >= 0) { _sensors_control_set_delay(minDelay); } 从上面可以看出来 对于底层而言只要知道上层怎么调用传感的接口就好 所以最关心的还是 我标绿的 native 方法 上层的传感流程其实比较简单 就是标准的 service 管理和 notify 流程 private static native int _sensors_control_init(); private static native ParcelFileDescriptor _sensors_control_open(); private static native boolean _sensors_control_activate(int sensor, boolean activate); private static native int _sensors_control_set_delay(int ms); private static native int _sensors_control_wake(); native 方法 1. manager 部分 frameworks/base/core/jni/android_hardware_SensorManager.cpp 先看一眼它的方法注册 static JNINativeMethod gMethods[] = { {"nativeClassInit", "()V", (void*)nativeClassInit }, {"sensors_module_init","()I", (void*)sensors_module_init }, {"sensors_module_get_next_sensor","(Landroid/hardware/Sensor;I)I", (void*)sensors_module_get_next_sensor }, {"sensors_data_init", "()I", (void*)sensors_data_init }, {"sensors_data_uninit", "()I", (void*)sensors_data_uninit }, {"sensors_data_open", "(Ljava/io/FileDescriptor;)I", (void*)sensors_data_open }, {"sensors_data_close", "()I", (void*)sensors_data_close }, {"sensors_data_poll", "([F[I[J)I", (void*)sensors_data_poll }, }; 小贴一个例子作为代表 static jint sensors_data_open(JNIEnv *env, jclass clazz, jobject fdo) { jclass FileDescriptor = env->FindClass("java/io/FileDescriptor"); jfieldID offset = env->GetFieldID(FileDescriptor, "descriptor", "I"); int fd = env->GetIntField(fdo, offset); return sSensorDevice->data_open(sSensorDevice, fd); // doesn't take ownership of fd } 调用到最后其实都是用的 sSensorDevice 的方法 /* * The method below are not thread-safe and not intended to be */ static sensors_data_device_t* sSensorDevice = 0; 2.service 部分 frameworks/base/services/jni/com_android_server_SensorService.cpp 先看一眼它的方法注册 static JNINativeMethod gMethods[] = { {"_sensors_control_init", "()I", (void*) android_init }, {"_sensors_control_open", "()Landroid/os/ParcelFileDescriptor;", (void*) android_open }, {"_sensors_control_activate", "(IZ)Z", (void*) android_activate }, {"_sensors_control_wake", "()I", (void*) android_data_wake }, {"_sensors_control_set_delay","(I)I", (void*) android_set_delay }, }; 然后上面的那些方法我就不一一贴了 给出一个例子 其实这么实现的 static jboolean 盛世游戏:http://www.shengshiyouxi.com android_activate(JNIEnv *env, jclass clazz, jint sensor, jboolean activate) { int active = sSensorDevice->activate(sSensorDevice, sensor, activate); return (active<0) ? false : true; } 所以最后调用的其实都是 sSensorDevice 的方法 其他的几个也是这样 sSensorDevice 是这个 (不是线程安全的) /* * The method below are not thread-safe and not intended to be */ static sensors_control_device_t* sSensorDevice = 0; 3.继续追 终于到了硬件层了 最后一切的方法其实就在这里了 hardware/libhardware/include/hardware/sensor.h struct sensors_control_device_t { |
android中Sensor 工作流程的更多相关文章
- zigbee学习:示例程序SampleApp中按键工作流程
zigbee学习:示例程序SampleApp中按键工作流程 本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 环境: 主机:WIN7 开发环境:IAR8. ...
- Android中G-Sensor相关流程
1.使G-sensor正常工作需要做的事: G-sensor driver文件包括: driver/i2c/chips/lis331dl.c driver/i2c/chips/sensorioctl. ...
- Android中View绘制流程以及invalidate()等相关方法分析(转载的文章,出处在正文已表明)
转载请注明出处:http://blog.csdn.net/qinjuning 前言: 本文是我读<Android内核剖析>第13章----View工作原理总结而成的,在此膜拜下作者 .同时 ...
- Android中View绘制流程以及invalidate()等相关方法分析(转)
转自:http://blog.csdn.net/qinjuning 前言: 本文是我读<Android内核剖析>第13章----View工作原理总结而成的,在此膜拜下作者 .同时真挚地向渴 ...
- Android中View绘制流程以及invalidate()等相关方法分析
[原文]http://blog.csdn.net/qinjuning 整个View树的绘图流程是在ViewRoot.java类的performTraversals()函数展开的,该函数做的执行过程可简 ...
- 【转载】Android 中 View 绘制流程分析
创建Window 在Activity的attach方法中通过调用PolicyManager.makeNewWindo创建Window,将一个View add到WindowManager时,Window ...
- Android中measure过程、WRAP_CONTENT详解以及 xml布局文件解析流程浅析
转自:http://www.uml.org.cn/mobiledev/201211221.asp 今天,我着重讲解下如下三个内容: measure过程 WRAP_CONTENT.MATCH_PAREN ...
- android中的事件传递和处理机制
一直以来,都被android中的事件传递和处理机制深深的困扰!今天特意来好好的探讨一下.现在的感觉是,只要你理解到位,其实事件的 传递和处理机制并没有想象中的那么难.总之,不要自己打击自己,要相信自己 ...
- Android中滑屏初探 ---- scrollTo 以及 scrollBy方法使用说明
今天给大家介绍下Android中滑屏功能的一个基本实现过程以及原理初探,最后给大家重点讲解View视图中scrollTo 与 scrollBy这两个函数的区别 . 首先 ,我们必须明白在Android ...
随机推荐
- android第一天-------环境搭建
今天正式第一天学习android的. 1.昨晚下班后回家跟同事刘江龙打了四把dota.还好,都赢了把对面虐成狗了.大多都是1300到1450的局,玩的很爽. 2.dota打完后给在湖南常德的女朋友打了 ...
- No enclosing instance of type Hello is accessible
1.static 关键字 修饰的成员被所有对象共享(包括成员变量和方法). 修饰的成员优先于对象存在. 存储于方法区(共享数据区)的静态区中. 静态方法只能访问静态成员. 静态方法中不可以使用this ...
- [置顶] 让导入的Android项目,运行起来的方法。
Eclipse里面直接import的代码,不能运行出现如下错误: [2013-12-12 12:58:55 - Dex Loader] Unable to execute dex: java.nio. ...
- 安装bower
1.前提事先安装好node 和 npm D:\DEVELOP\HTML>node -v v0.10.29 D:\DEVELOP\HTML>npm -v 1.4.14 2.安装bower n ...
- MFC 关于对话框的注意点
1.对于模态对话框而言,单击确定以后对话框窗口对象即被销毁了,而对于非模态对话框来说,对话框的对象并未销毁而是隐藏起来(EndDialog函数),因此对于非模态对话框,必须重写OnOK这个虚函数,并在 ...
- 后台调用外部程序的完美实现(使用CreateDesktop建立隐藏桌面)
最近在做的一个软件,其中有一部分功能需要调用其它的软件来完成,而那个软件只有可执行文件,根本没有源代码,幸好,我要做的事不难,只需要在我的程序启动后,将那个软件打开,在需要的时候,对其中的一个文本矿设 ...
- Oracle rank和dense_rank排名函数
1.rank函数 rank计算一组值的排名,返回数字类型.排名可能是不连续.如果有5人,其中有2个人排名第一,则rank返回的排名结果为:1 1 3 4 5. 作为一个聚合函数,返回虚拟行在样表中的排 ...
- vscode编写插件
vscode编写插件详细过程 前言 之前编写了一个vscode插件用vscode写博客和发布,然后有园友要求写一篇来介绍如何开发一个vscode扩展插件,或者说介绍开发这个插件的过程.然而文章还没有写 ...
- CRectTracker类的使用--橡皮筋窗口
CRectTracker(俗称“橡皮筋”类)是一个非常有意思的类.你在Windows中经常看到这样的情况:它可以用做显示边界,你也可以扽它的八个角用来放大缩小,或做框选使用.如何通过编程来实现这种功能 ...
- Delphi的字符(Char),字符串(String),字符串指针(PChar),字符数组arrayofchar(来自http://delphi.cjcsoft.net/论坛)
Delphi有三种类型的字符: AnsiChar这是标准的1字节的ANSI字符,程序员都对它比较熟悉. WideChar这是2字节的Unicode字符. Char在目前相当于AnsiChar,但在De ...