• 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 {

     

                                                 

  • 相关阅读:
    分析模式的位置
    SAP .Net Connector for C#
    NETBPM开源工作流讲座
    BW处理链的时间为什么会每天推迟2秒钟?
    如何在SubScreen中取得上一screen中的值
    flash弹出窗口被ie屏蔽的解决方法
    用Eclipse 开发Flex (配置安装Flex插件)
    rtmp和http方式在播放flv方面的各自优势和劣势
    FMS4 P2P直播解决方案
    [AS3]URLLoader+URLRequest+JPGEncoder实现BitmapData图片数据保存
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3186896.html
Copyright © 2020-2023  润新知