android sensor 框架--Java层

一个简单的注册流程图:

--调用registerListener()函数,实际调用抽象函数registerListenerImpl

--子类SystemSensorManager实现了registerListenerImpl

--如果有sensor事件,则JNI层android_hardware_SensorManager.cpp就调用dispatchSensorEvent()方法发送

--onSensorChanged()处理事件




SensorManager是一个抽象类,应用程序使用/监听Sensor都通过它。

public abstract class SensorManager {//抽象类
    /** @hide */
    protected static final String TAG = "SensorManager";

...
}

它定义了一些主要的方法,给应用层使用,提供了什么接口?

    public boolean registerListener(SensorEventListener listener, Sensor sensor,//提供接口,给应用层注册监听器
            int samplingPeriodUs, Handler handler) {
        
        int delay = getDelay(samplingPeriodUs);		
        return registerListenerImpl(listener, sensor, delay, handler, 0, 0);
    }

    public void unregisterListener(SensorEventListener listener) {//提供接口,给应用层卸载监听器
        if (listener == null) {
            return;
        } 
 
        unregisterListenerImpl(listener, null);
    }

注册/听器函数registerListener(SensorEventListener,Sensor,int,int)

SensorEventListener是监听器对象,负责接收和处理SensorEvent的事件。Sensor是要监听的sensor,如TYPE_PROXIMITY类型的.

如果Sensor有数据上报,那么SensorEventListener监听器对象就会收到消息,里面的onSensorChanged()函数就负责处理。

public boolean requestTriggerSensor(TriggerEventListener listener, Sensor sensor) {//注册one-shot trigger类sensor
        return requestTriggerSensorImpl(listener, sensor);
    }

    public boolean cancelTriggerSensor(TriggerEventListener listener, Sensor sensor) {
        return cancelTriggerSensorImpl(listener, sensor, true);
    }
r equestTriggerSensor/cancelTriggerSensor与上面的registerListener/unregisterListener一样注册/卸载监听器用的,

只不过,监听器收到事件后就自动disable,如果要继续监听,就要在事件处理函数里再次调用requestTriggerSensor。

//抽象方法,由子类实现
    protected abstract boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
            int delayUs, Handler handler, int maxReportLatencyUs, int reservedFlags);

    protected abstract void unregisterListenerImpl(SensorEventListener listener, Sensor sensor);

    protected abstract boolean requestTriggerSensorImpl(TriggerEventListener listener,
            Sensor sensor);

    protected abstract boolean cancelTriggerSensorImpl(TriggerEventListener listener,
            Sensor sensor, boolean disable);
上面的注册/卸载函数最终都调用xxImpl(),它是一个抽象方法,须在子类中实现
protected abstract List<Sensor> getFullSensorList();//获取当前Sensor列表
另外getFullSensorList()也是抽象方法,须子类实现,为什么这样呢?为什么有SensorManager这个抽象类,不把活全干完,非要定义几个抽象方法让子类实现尼,我个人认为android把高度相同性质的函数放在抽象类中实现,而把一些相当灵活又与navtive层有交互的函数定义为抽象方法是有好处的,充份体现了面向对象设计的精髓:类是各种具有相同性质对象的抽象。细读SensorManager.java,特别是注释,有些人看代码不看注释,非常不好,一下子就读fucking code会很痛苦,注释至少告诉我函数/类是干吗用的,对把握了解整个代码逻辑非常有好处。


了解SensorManager后,是不是很想知道,应用层应该怎么使用它?

案例:

DisplayPowerController需要监听proximity sensor。打电话,手挡住psensor灭屏,离开则亮屏。

首先--建立一个SensorEventListener监听器对象mProximitySensorListener

再次--实现事件处理函数onSensorChanged()。(SensorEventListener是一个接口类可以用implements实现接口,也可以new)

然后--把此监听器对象注册入SensorManager。

即mSensorManager.registerListener(mProximitySensorListener,mProximitySensor,SensorManager.SENSOR_DELAY_NORMAL,mHandler);

mProximitySensorListener是SensorEventListener监听器对象,而mProximitySensor是Sensor对象,类型是TYPE_PROXIMITY,祥见Sensor类。Sensor类定义了目前android支持的所有Sensor类型,像acc,mag,gyr就更不用说了,还支持hear rate心率计数,step count步数,ambient temperature环境温度,relative humidity相当湿度等等,Sensor类还为每个sensor类型规定了value的大小,一个Sensor对象就代表一个sensor,通过这个对象你可以指定sensor的类型,是否支持wakeup,事件发送的delay是多少,有兴趣的可以细读Sensor.java。

mSensorManager.registerListener(mProximitySensorListener, mProximitySensor,//注册监听器
                        SensorManager.SENSOR_DELAY_NORMAL, mHandler);

   private final SensorEventListener mProximitySensorListener = new SensorEventListener() {
        @Override
        public void onSensorChanged(SensorEvent event) {//SensorEvent事件处理
            if (mProximitySensorEnabled) {
                final long time = SystemClock.uptimeMillis();
                final float distance = event.values[0];
                boolean positive = distance >= 0.0f && distance < mProximityThreshold;				
                Slog.d(TAG, "mProximitySensorListener: " + positive + "distance: " + distance + "Threshold: " + mProximityThreshold);			
                handleProximitySensorEvent(time, positive);
            }
        }


来到

SystemSensorManager类,这是SensorManager的子类,实现SensorManager的所有抽象方法

另外还定义了一些数据结构,用于管理监听器和事件

public class SystemSensorManager extends SensorManager {
    private static native void nativeClassInit();
    private static native int nativeGetNextSensor(Sensor sensor, int next);

    private static boolean sSensorModuleInitialized = false;
    private static final Object sSensorModuleLock = new Object();
    private static final ArrayList<Sensor> sFullSensorsList = new ArrayList<Sensor>();
    private static final SparseArray<Sensor> sHandleToSensor = new SparseArray<Sensor>();
...
    public SystemSensorManager(Context context, Looper mainLooper) {
        mMainLooper = mainLooper;
        mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;
        synchronized(sSensorModuleLock) {
            if (!sSensorModuleInitialized) {
                sSensorModuleInitialized = true;

                nativeClassInit();

                // initialize the sensor list
                final ArrayList<Sensor> fullList = sFullSensorsList;
                int i = 0;
                do {
                    Sensor sensor = new Sensor();
                    i = nativeGetNextSensor(sensor, i);
                    if (i>=0) {
                        Log.d(TAG, "found sensor: " + sensor.getName() +
                                ", handle=" + sensor.getHandle());
                        fullList.add(sensor);
                        sHandleToSensor.append(sensor.getHandle(), sensor);
                    }
                } while (i>0);
            }
        }
    }

构造函数

首先--得到Sdkversion,因为不同android版本/不同sensor类型所支持的数据value size 不一样,SensorEvent事件对象在构造时必须指定valuesize。Sensor类的静态函数getMaxLengthValuesArray()可以根据不同的sdkLevel和Sensor类型返回相应的valuesize。可参考SensorEvent.java,Sensor.java。

然后--nativeClassInit(),跑到sensor jni层android_hardware_SensorManager.cpp

static void
nativeClassInit (JNIEnv *_env, jclass _this)
{
    jclass sensorClass = _env->FindClass("android/hardware/Sensor");
    SensorOffsets& sensorOffsets = gSensorOffsets;
    sensorOffsets.name        = _env->GetFieldID(sensorClass, "mName",      "Ljava/lang/String;");
    sensorOffsets.vendor      = _env->GetFieldID(sensorClass, "mVendor",    "Ljava/lang/String;");
    sensorOffsets.version     = _env->GetFieldID(sensorClass, "mVersion",   "I");
    sensorOffsets.handle      = _env->GetFieldID(sensorClass, "mHandle",    "I");
    sensorOffsets.type        = _env->GetFieldID(sensorClass, "mType",      "I");
    sensorOffsets.range       = _env->GetFieldID(sensorClass, "mMaxRange",  "F");
    sensorOffsets.resolution  = _env->GetFieldID(sensorClass, "mResolution","F");
    sensorOffsets.power       = _env->GetFieldID(sensorClass, "mPower",     "F");
    sensorOffsets.minDelay    = _env->GetFieldID(sensorClass, "mMinDelay",  "I");
    sensorOffsets.fifoReservedEventCount =
            _env->GetFieldID(sensorClass, "mFifoReservedEventCount",  "I");
    sensorOffsets.fifoMaxEventCount = _env->GetFieldID(sensorClass, "mFifoMaxEventCount",  "I");
    sensorOffsets.stringType = _env->GetFieldID(sensorClass, "mStringType", "Ljava/lang/String;");
    sensorOffsets.requiredPermission = _env->GetFieldID(sensorClass, "mRequiredPermission",
                                                        "Ljava/lang/String;");
    sensorOffsets.maxDelay    = _env->GetFieldID(sensorClass, "mMaxDelay",  "I");
    sensorOffsets.flags = _env->GetFieldID(sensorClass, "mFlags",  "I");
}
nativeClassInit函数得到Sensor Java类的引用,把Java类里的mName,mVersion在native层做变量映射,目的是后面在native层会初始化这些Java类里的变量。所以你可以从Sensor.java代码里看到,它的构造函数是空的。


最后--回到SystemSensorManager构造函数do 循环就是把设备里支持的sensor挂进来。

new Sensor()对象,调用nativeGetNextSensor(sensor,i)函数从0开始检索,如果找到一个sensor,就传进来的sensor java对象里的变量初始化一下,就是上面讲到的mName,mVersion等等,成功返回值>0。把sensor对象加入到sFullSensorsList中,同时也加入到稀列表sHandleToSensor中。sFullSensorsList是给getFullSensorList()函数用的,而SystemSensorManager真正用到的是sHandleToSensor。

下面是搜索到的sensor:

10181 01-01 04:41:40.415  2818  2905 D SensorManager: found sensor: lis3dh-accel, handle=1
10182 01-01 04:41:40.415  2818  2905 D SensorManager: found sensor: yas537-mag, handle=2
10183 01-01 04:41:40.415  2818  2905 D SensorManager: found sensor: ltr559-light, handle=3
10184 01-01 04:41:40.415  2818  2905 D SensorManager: found sensor: ltr559-proximity, handle=4
10185 01-01 04:41:40.415  2818  2905 D SensorManager: found sensor: yas537-orientation, handle=5

来到registerListenerImpl实现函数

protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
            int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) {
        
        // Invariants to preserve:
        // - one Looper per SensorEventListener
        // - one Looper per SensorEventQueue
        // We map SensorEventListener to a SensorEventQueue, which holds the looper
        synchronized (mSensorListeners) {
            SensorEventQueue queue = mSensorListeners.get(listener);
            if (queue == null) {
                Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
                queue = new SensorEventQueue(listener, looper, this);
                if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs, reservedFlags)) {
                    queue.dispose();
                    return false;
                }
                mSensorListeners.put(listener, queue);
                return true;
            } else {
                return queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs, reservedFlags);
            }
        }
    }
SystemSensorManager为管理SensorEventListener,和SensorEvent。

private final HashMap<SensorEventListener, SensorEventQueue> mSensorListeners =
            new HashMap<SensorEventListener, SensorEventQueue>();
用HashMap为SensorEventListener,SensorEventQueue做map

所以registerListenerImpl

首先--从mSensorListeners里查找listener对应的queue。如果NULL,就new一个SensorEventQueue对象queue,并把传进来的listener,sensor添加到queue。 

然后--mSensorListeners.put(listener,queue)添加map。

unregisterListenerImpl反之。

requestTriggerSensorImpl/cancelTriggerSensorImpl类似,只不过用HashMap mTriggerListeners和TriggerEventQueue

   private final HashMap<TriggerEventListener, TriggerEventQueue> mTriggerListeners =
            new HashMap<TriggerEventListener, TriggerEventQueue>();

TriggerEventQueue queue

注册流程已经跑完,那么应用层的事件处理函数onSensorChanged() / onTrigger()就等着接收SensorEvent事件了。

那么SensorEvent事件如何派发的?

JNI code android_hardware_SensorManager.cpp通过调用SystemSensorManager的dispatchSensorEvent()函数完成。

       // Called from native code.
        @SuppressWarnings("unused")
        @Override
        protected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,
                long timestamp) {
            final Sensor sensor = sHandleToSensor.get(handle);
            SensorEvent t = null;
            synchronized (mSensorsEvents) {
                t = mSensorsEvents.get(handle);
            }
...
            // Copy from the values array.
            System.arraycopy(values, 0, t.values, 0, t.values.length);
            t.timestamp = timestamp;
            t.accuracy = inAccuracy;
            t.sensor = sensor;

            // call onAccuracyChanged() only if the value changes
            final int accuracy = mSensorAccuracies.get(handle);
            if ((t.accuracy >= 0) && (accuracy != t.accuracy)) {
                mSensorAccuracies.put(handle, t.accuracy);
                mListener.onAccuracyChanged(t.sensor, t.accuracy);
            }
            mListener.onSensorChanged(t);
        }
dispatchSensorEvent()函数

首先--通过handle从SystemSensorManager里的sHandleToSensor稀疏列表里找到Sensor对象sensor

final Sensor sensor = sHandleToSensor.get(handle);

通过handle从SensorEventQueue里的mSensorsEvents稀疏列表里找到SensorEvent事件对象t

t = mSensorsEvents.get(handle);

然后--从传进来的float[] values把数据copy到t中。

最后--以t做为参数,调用mListener.onSensorChanged(t),把事件发送出去。

mListener就是通过registerListenerImpl注册进来的,如本例中的mProximitySensorListener。

那么调用mListener.onSensorChanged(t)就是调用mProximitySensorListener.OnSensorChanged(SensorEvent event)

TriggerEvent的派发流程也是类似

       protected void dispatchSensorEvent(int handle, float[] values, int accuracy,
                long timestamp) {
            final Sensor sensor = sHandleToSensor.get(handle);
            TriggerEvent t = null;
            synchronized (mTriggerEvents) {
                t = mTriggerEvents.get(handle);
            }
            ...
            // Copy from the values array.
            System.arraycopy(values, 0, t.values, 0, t.values.length);
            t.timestamp = timestamp;
            t.sensor = sensor;

            // A trigger sensor is auto disabled. So just clean up and don't call native
            // disable.
            mManager.cancelTriggerSensorImpl(mListener, sensor, false);

            mListener.onTrigger(t);
        }
只不过是调用mListener.onTrigger(t)罢了,另外还调用了mManager.cancelTriggerSensorImpl(mListener,sensor,false)

这就是为什么是one-shot trigger sensor只触发一次的原因了。

在Java层已经对如果注册SensorEventListener,如何接收SensorEvent有了大概的了解。

后面打算分析JNI层,JNI层如何做为中间层,怎样把低层消息转发给Java的?


你可能感兴趣的:(android sensor 框架--Java层)