本篇文章主要分析安卓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中分析。
网友评论