美文网首页
Android Sensor Framework Java层数据

Android Sensor Framework Java层数据

作者: 蜗牛是不是牛 | 来源:发表于2022-11-23 15:43 被阅读0次

本篇文章主要分析安卓Sensor框架 Java层的几个主要类的数据结构和使用,以便给鸿蒙系统上的Sensor API框架提供借鉴与参考,下表为我主要分析的类的源码路径:
源码路径
frameworks/base/core/java/android/hardware/Sensor.java
frameworks/base/core/java/android/hardware/SensorAdditionalInfo.java
frameworks/base/core/java/android/hardware/SensorDirectChannel.java
frameworks/base/core/java/android/hardware/SensorEvent.java
frameworks/base/core/java/android/hardware/SystemSensorManager.java
frameworks/base/core/java/android/hardware/TriggerEvent.java
frameworks/base/core/java/android/hardware/SensorEventListener.java
frameworks/base/core/java/android/hardware/SensorEventListener2.java
frameworks/base/core/java/android/hardware/SensorEventCallback.java
frameworks/base/core/java/android/hardware/TriggerEventListener.java

1.Sensor.java

Sensor类是传感器的数据抽象类,作为传感器的实体抽象,在框架中使用较为频繁,其持有标志传感器类型的静态整型值(TYPE_)和标志传感器类型名称的静态字符串(STRING_TYPE_),还标记了4种传感器上报模式:


一个名为sSensorReportingModes的私有int数组,其标记了每种Sensor对应在SensorEvent中每帧数据的有效长度。其主要用在getMaxLengthValuesArray方法中。接下来是对应Native层Sensor.cpp的一些属性:
    private String  mName; //名称
    private String  mVendor;//供应商
    private int     mVersion;//版本
    private int     mHandle;//对应在Native层的句柄
    private int     mType;//类型值
    private float   mMaxRange;//最大范围
    private float   mResolution;//解析度
    private float   mPower;//使用时的耗电量 单位mA
    private int     mMinDelay;//事件之间的最低延迟 单位微秒
    private int     mFifoReservedEventCount;//这个值决定了传感器最小上传批量
    private int     mFifoMaxEventCount;//传感器最多可以批量上传的值
    private String  mStringType;//传感器类型字符串值
    private String  mRequiredPermission;//连接这个传感器需要的权限
    private int     mMaxDelay;//最大延迟
    private int     mFlags;//标记各种属性的int值:上报模式,是否是唤醒类的Sensor,是否是动态传感器,
                            //是否支持附加信息,是否支持数据注入,最高支持的评率等级
    private int     mId;//id

这个Sensor类中,没有用到很高级的数据结构,都是常规的标记值和属性值,只有一个mFlags用到了位标记,将各个属性的开关(有无)存放在对应位上面,用固定的mask去取值。

2.SensorAdditionalInfo.java

该类代表Sensor 一帧额外数据,用于android.hardware.SensorEventCallback#onSensorAdditionnalInfo 回调方法中,其持有一个Sensor对象,一个标志该帧类型的type 整型,该帧的帧序列号,一个浮点数数组作为数据载体,整型数组作为整型数据载体。

public final Sensor sensor;//持有sensor对象
public final int type;//该帧所属的类型取值范围如下
@IntDef({TYPE_FRAME_BEGIN, TYPE_FRAME_END, TYPE_UNTRACKED_DELAY, TYPE_INTERNAL_TEMPERATURE,
             TYPE_VEC3_CALIBRATION, TYPE_SENSOR_PLACEMENT, TYPE_SAMPLING})
@Retention(RetentionPolicy.SOURCE)
public @interface AdditionalInfoType {}
public final int serial;//对特定类型的帧数据的帧序列号
public final float[] floatValues;//浮点数据载体
public final int[] intValues;//整形数据载体

该类也是一个普通的数据类,相比SensorEvent 主要增加了接收处理帧数据的能力,作为对SensorEvent的补充。

3.SensorDirectChannel.java

该类代表一个传感器的直接管道,使用SensorManager.createDirectChannel(android.os.MemoryFile)或SensorManager。createDirectChannel(android.hardware.HardwareBuffer)来创建一个实例,该类的主要作用是给传感器建立一个通道,传递传感器事件到共享内存缓存中。它没有对外暴露的属性,但有几个静态常量标记管道的类型:

public static final int TYPE_MEMORY_FILE = 1; //文件类型的管道
public static final int TYPE_HARDWARE_BUFFER = 2;//Socket 类型的管道

//下面是几个标志传感器数据传送频率的静态常量
public static final int RATE_STOP = 0;//传感停止了数据发送
public static final int RATE_NORMAL = 1;//50Hz
public static final int RATE_FAST =2;//200Hz
public static final int RATE_VERY_FAST = 3;//800Hz

4.SensorEvent.java

该类代表传感器的一个上报事件,数据比较简单:

public final float[] values;//数据载体
public Sensor sensor;//数据对应的传感器
public int accuracy;//传感器的准确度
public long timestamp;//该传感器事件发生时的时间戳

该类主要面向App用户使用,主要在在用户注册的android.hardware.SensorEventListener#onSensorChanged(SensorEvent event)中调用,虽然数据及其简单,但面对不同的传感器,数据载体对应不同的解析方式,详情见该源码文件的注解;

5.SystemSensorManager.java

前面《Android SensorJava层 源码分析》中,我们知道了SystemSensorManager是SensorManager的具体实现,它是Java层提供功能的核心模块,文件中还定义了BaseEventQueue等静态类,下面逐个分析其数据:

5.1 SensorManager

该类提供了大量的整型静态常量数据用于标记各种传感器的属性,很多用于位标记的值被定义为过时的(就不细讲了),下面几个常量标记了传感器的状态:

public static final int SENSOR_STATUS_NO_CONTACT = -1;//传感器没有连接到它的测量宿主(例如:心率传感器没有连接到用户)
public static final int SENSOR_STATUS_UNRELIABLE = 0;//传感器不可信,可能是传感器需要校准或环境不允许读取数据
public static final int SENSOR_STATUS_ACCURACY_LOW = 1;//传感器准确度较低,需要根据使用环境来校准
public static final int SENSOR_STATUS_ACCURACY_MEDIUM = 2;//传感器准确度一般
public static final int SENSOR_STATUS_ACCURACY_HIGH = 3;//传感器准确度较高

Android Sensor框架对传感器的准确度关注较为精细,在鸿蒙Sensor框架中,传感器的准确度也是不可忽略的一个细节,也需要在每帧数据中实时上报其准确度。

5.2 自有属性

systemSensorManager定义了几个List和HashMap来装载Sensor和监听:

private final ArrayList<Sensor> mFullSensorsList = new ArrayList<>();//持有全部的sensor的列表
    private List<Sensor> mFullDynamicSensorsList = new ArrayList<>();//持有全部动态sensor的列表

    private final HashMap<Integer, Sensor> mHandleToSensor = new HashMap<>();//native sensor的句柄和java sensor一一对应的hashmap,用于根据句柄获取sensor

    // Listener list
    private final HashMap<SensorEventListener, SensorEventQueue> mSensorListeners =
            new HashMap<SensorEventListener, SensorEventQueue>();//sensor监听和EventQueue一一对应的hashmap
    private final HashMap<TriggerEventListener, TriggerEventQueue> mTriggerListeners =
            new HashMap<TriggerEventListener, TriggerEventQueue>();//触发类sensor监听和TriggerEventQueue一一对应的hashmap

    // Dynamic Sensor callbacks
    private HashMap<DynamicSensorCallback, Handler>
            mDynamicSensorCallbacks = new HashMap<>();//动态传感器回调和Handler一一对应的监听

上面的mFullSensorsList 和mHandleToSensor是在SystemSensorManager初始化时,通过JNI方法nativeGetSensorAtIndex(mNativeInstance, sensor, index)来初始化数据的,这些数据和Native层数据联系紧密,也可以理解为native层数据在Java层的映射,鸿蒙sensor框架肯定也会用到native数据映射到java层,也可以在相关类初始化时获取,mFullDynamicSensorsList主要是在updateDynamicSensorList()方法中调用,而updateDynamicSensorList()方法又是在DynamicSensorBroadcastReceiver广播接收中回调。而mSensorListener是在registerListenerImpl()方法中添加数据,在unregisterListenerImpl中移除数据,同样,mTriggerListeners是在requestTriggerSensorImpl()方法中添加数据,在cancelTriggerSensorImpl()方法中移除数据。mDynamicSensorCallbacks是在registerDynamicSensorCallbackImpl()方法中添加数据,在unregisterDynamicSensorCallbackImpl()方法中移除数据,listener是 对应应用层的回调,对native层的处理还是要看BaseEventQueue。
下面几个属性是跟系统调用环境相关的:

    private final Looper mMainLooper;//SystemSensor 实例化时,所在线程的Looper
    private final int mTargetSdkLevel;//目标Sdk等级,用于兼容老的版本
    private final Context mContext;//安卓 context
    private final long mNativeInstance;//native层的sensorManager的实例句柄

5.3 BaseEventQueue

在源码分析中,我们知道BaseEventQueue是SensorManager和 SensorService通讯的通道,下面来看看其内部持有的数据结构:

        private long mNativeSensorEventQueue;//持有nativeSensorEventQueue的句柄
        private final SparseBooleanArray mActiveSensors = new SparseBooleanArray();//标记已经激活的Sensor
        protected final SparseIntArray mSensorAccuracies = new SparseIntArray();//标记senser对应的准确度
        private final CloseGuard mCloseGuard = CloseGuard.get();//内存泄露监听
        protected final SystemSensorManager mManager;//systemSensorManager实例

        protected static final int OPERATING_MODE_NORMAL = 0;//正常操作模式
        protected static final int OPERATING_MODE_DATA_INJECTION = 1;//数据注入模式

其中重要的数据是mActiveSensors 和 mSensorAccuracies,mActiveSensors用sensor的句柄作为key,是否激活true or false 作为value,达到标记该句柄对应的sensor是否激活的功能,同样用sensor的句柄作为key,该sensor的准确度作为value,达到标记该句柄对应sensor准确度的功能。每一个listener都对应于一个EventQueue,当添加监听时,将其配对加入相应的hashmap中

5.3.1 SensorEventQueue

SensorEventQueue是BaseEventQueue的子类,其主要功能是用于实现SensorEvent的回调,下列是其主要的数据属性:

        private final SensorEventListener mListener;//对应的监听回调,在dispachSensorEvent中使用
        private final SparseArray<SensorEvent> mSensorsEvents = new SparseArray<SensorEvent>();//sensorEvent列表

mLisener是回调发生的关键,它在SensorEventQueue构造时根据传入参数来初始化,后期在dispatchSensorEvent()方法中调用,而dispatchSensorEvent()方法在Native层调用,从这里联系到了native层的数据回调,这也再次说明了BaseSensorEventQueue是和SensorService通讯的通道,具体需要在Native层中追踪。mSensorEvents 是在void addSensorEvent(Sensor)方法中添加数据的,而该方法是在BaseEventQueue中boolean addSensor()方法中调用的,而addSensor()方法是在registerListenerImpl()中调用,根据调用链,mSensorEvents是在注册listener时,添加数据的。同样对应的,根据调用链可知,mSensorEvents是在取消注册listener时,删除数据的。

5.3.2 TriggerEventQueue

TriggerEventQueue是和SensorEventQueue一样的数据结构,也是BaseEventQueue的子类,不过它用于处理触发类Sensor的监听回调:

        private final TriggerEventListener mListener;//对应的监听回调,在dispachSensorEvent中使用
        private final SparseArray<TriggerEvent> mTriggerEvents = new SparseArray<TriggerEvent>();//triggerEvent列表

其处理方式与SensorEventQueue一致,这里不做重复阐述。

6.TriggerEvent.Java

该类代表了一个触发类型的Sensor事件,它对应一个触发类型的传感器,除了没有传感器准确度其它和SensorEvent数据一样,它用在android.hardware.TriggerEventListener#onTrigger(TriggerEvent)回调中。

public final float[] values;//数据载体
public Sensor sensor;//数据对应的传感器
public long timestamp;//该传感器事件发生时的时间戳

7. 总结

Java层的Sensor Api的数据结构较为简单,其主要数据都在Native层有对应,比如Sensor 对应Native层的Sensor,在Java层以整型句柄的形式出现,BaseEventQueue有对应Native层的EventQueue,Java层Sensor框架的主要功能就是管理(添加和移除)sensor事件的监听,每次在添加监听时,获取或创建对应的EventQueue,当事件发生时,在native层调用dispatchSensorEvent()方法,进而回调监听方法。更加深入细致的细节,还是需要进入Native层的EventQueue中分析。

来自:https://www.yuque.com/zestzone/bdds6v/kmug7b

相关文章

网友评论

      本文标题:Android Sensor Framework Java层数据

      本文链接:https://www.haomeiwen.com/subject/nbmzxdtx.html