6.2 传感器子系统的结构
↘6.2.1 总体结构
Android2.2版本之前的传感器系统比较简单,由JNI部分直接调用硬件抽象层来实现,在本地的框架层中,没有使用其他的库。自Android2.3系统之后,传感器系统的结构进行了调整,自下而上包含了驱动程序、传感器硬件抽象层、本地层次、传感器Java框架类、Java框架中对传感器的使用、Java应用层。传感器系统的结构如图6-1所示。
图6-1 Android的传感器系统结构
Android的传感器系统自下而上,包括以下几个部分的内容。
(1)具体平台实现的传感器驱动程序
(2)传感器的硬件抽象层
传感器的硬件抽象层为标准的sensors硬件模块,其接口头文件路径为:hardware/libhardware/include/hardware/sensors.h,传感器的硬件抽象层实现后,将生成名称为sensors.<hardware>.so的动态库。
(3)传感器的本地框架层
包括传感器服务和传感器框架。
·frameworks/base/services/sensorservice/:传感器服务部分代码。
传感器服务部分生成动态库libsensorservice.so。
传感器框架在libgui中,生成动态库libgui.so。
·frameworks/base/include/gui/:libgui头文件。
·frameworks/base/libs/gui/:libgui源代码。
(4)传感器系统的JNI
·frameworks/base/core/jni/android_hardware_SensorManager.cpp
(5)传感器系统的Java框架
·frameworks/base/include/core/jave/android/hardware/:其中的传感器部分。
本目录中对应包含了android.hardware,Sensor部分的内容为Sensor*.java文件。在Java层对传感器Java API可以分成几个部分。框架层也包括了调用传感器来实现屏幕自动旋转功能的部分。
提示:Android 4.2的SensorService的内容在frameworks/native/的目录中。
↘6.2.2 本地框架层
1.libgui库相关的内容
libgui库包括传感器本地上下层几个头文件和源文件,提供传感器的基本类和为本地层程序所调用的接口。文件如下所示。
·Sensor.*:单一传感器的描述,包括名称、精度、延迟等。
·SensorManager.*:传感器的管理器,可以获得Sensor的列表。
·SensorChannel.*:传感器的通道,提供用于读写的数据接口。
·SensorEventQueue.*:传感器的事件队列,提供读/写和对传感器的控制接口。
其中引用了android/sensor.h头文件,包括Asensor、ASensorEvent等类。传感器的结构自Android2.3改为如此,主要是为了提供NDK所使用的本地接口。
提示:Android 2.3以后的传感器的核心运行于系统服务器的进程,不再是应用进程。
以I开头的几个文件是基于Binder机制的远程接口,需要下层来实现。
·ISensorServer.*:传感器的服务器。
·ISensorEventConnection.*:表示传感器事件的连接。
ISensorServer具有两个函数,用于获得传感器的列表和传感器事件的连接:
virtual Vector<Sensor> getSensorList() = 0; virtual sp<ISensorEventConnection> createSensorEventConnection() = 0;
ISensorEventConnection用于控制传感器,其中的函数如下所示:
virtual sp<SensorChannel> getSensorChannel() const = 0; virtual status_t enableDisable(int handle, bool enabled) = 0; virtual status_t setEventRate(int handle, nsecs_t ns) = 0;
根据以上的调用获取到SensorChannel之后,作为从下层获取传感器信息的通道。这两个远程接口的实现均在本地库sensorservice中完成。
2.sensorservice
sensorservice是实现传感器服务的本地库,主要通过调用传感器硬件抽象层实现libgui定义的远程接口,其客户端则通过libgui的接口在远程对其进行调用。
SensorService.h中定义了sensorservice中的核心内容,SensorService类继承了BnSensorServer,其中的SensorEventConnection类继承了BnSensorEventConnection。SensorService类是Android中一个典型的Binder服务。
SensorDevice表示传感器设备,即传感器的底层实现,也是传感器硬件抽象层的调用者。在其构造函数中,打开了传感器硬件抽象层的模块,然后调用了其中的传感器列表,设置延迟,激活传感器,等待数据返回(poll)等接口。
SensorInterface类表示一个抽象的传感器接口,由于重力加速度、线性加速度、旋转响亮等传感器的信息需要进行额外处理,因此GravitySensor、LinearAccelerationSensor、RotationVectorSensor等几个类是其继承者,在SensorDevice中根据传感器的类型进行了不同的调用处理。
按照一般的Android启动流程,SensorService::instantiate()函数被Java的服务进程(SystemServer)的JNI部分间接调用,因此sensorservice本身将运行SystemServer进程,其初始化一般在SurfaceFlinger服务之后。
↘6.2.3 传感器系统的JNI
android_hardware_SensorManager.cpp是传感器部分的JNI实现,主要实现了Java的android.hardware中的SensorManager类,并设置了Sensor类的信息。
主要通过调用libgui库的Sensor、SensorManager和SensorEventQueue几个类来实现功能,核心的实现是sensors_data_poll()函数,内容如下所示:
static jint sensors_data_poll(JNIEnv *env, jclass clazz, jint nativeQueue, jfloatArray values, jintArray status, jlongArray timestamp) { sp<SensorEventQueue> queue(reinterpret_cast<SensorEventQueue *>(nativeQueue)); if (queue == 0) return -l; status_t res; ASensorEvent event; res = queue->read(&event, l); // 向下层读取数据 // 省略部分内容 jint accuracy = event.vector.status; env->SetFloatArrayRegion(values, 0, 3, event.vector.v); // 设置数值 env->SetIntArrayRegion(status, 0, l, &accuracy); env->SetLongArrayRegion(timestamp, 0, l, &event.timestamp); return event.sensor; }
其中的SensorEventQueue在sensors_create_queue()函数被创建,作为Java层保存的本地句柄,在sensors_data_poll()函数中被使用。
SensorManager的初始化过程如下所示:
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;"); // 省略部分内容 }
android.hardware包的Sensor类具有几个私有成员,它们在Java中没有被赋值,而是在此处被赋值。
↘6.2.4 传感器系统的Java层
1.核心部分
android.hardware包中的具有几个传感器系统的类都是Java层的API,如下所示。
·Sensor:单一传感器的描述性文件。
·SensorManager:实现传感器系统核心的管理类。
·SensorEvent:表示传感器系统的事件类。
·SensorEventListener:传感器事件的监听者接口。
Sensor类用于描述一个具体的传感器,其主要的方法如下所示:
public class Sensor { float getMaximumRange() { // 获得传感器最大的范围 } String getName() { // 获得传感器的名称 } float getPower() { // 获得传感器的耗能 } float getResolution() { // 获得传感器的解析度 } int getType() { // 获得传感器的类型 } String getVendor() { // 获得传感器的Vendor } int getVersion() { // 获得传感器的版本 } }
Sensor类中具有名称为TYPE_*的常量,表示Android中支持的传感器类型,而TYPE_ALL(-1)表示所有的传感器类型。
SensorManager类是Sensor整个系统的核心,几个主要方法如下所示: public class SensorManager extends IRotationWatcher.Stub { public Sensor getDefaultSensor (int type) { // 获得默认的传感器 } public List<Sensor> getSensorList (int type) { // 获得传感器列表 } public boolean registerListener (SensorEventListener listener, Sensor sensor, int rate, Handler handler) { // 注册传感器的监听者 } void unregisterListener(SensorEventListener listener, Sensor sensor) { // 注销传感器的监听者 } }
其中getDefaultSensor()将根据类型获得系统中默认的传感器,getSensorList()可以获得传感器列表,注意,每一种类型的传感器可以有若干个,因此这里返回的是一个列表(List)的形式。registerListener()和unregisterListener()使用接口作为传感器系统的监听者,这里使用Sensor作为参数类型,作为每一个传感器单独设置的事件监听者。
SensorManager类中还定义了其他的一些常量,如GRAVITY_*为重力常量,MAGNETIC_FIELD_*为磁场常量,LIGHT_*为光亮度(亮度)常量。
SensorEvent类表示传感器事件,实际上是Sensor类加上了数值(values)、精度(accuracy)、时间戳(timestamp)等内容,这个类的几个成员都是公共(public)类型。
SensorEventListener接口描述了SensorEvent的监听者,内容如下所示:
public interface SensorEventListener { public void onSensorChanged(SensorEvent event); public void onAccuracyChanged(Sensor sensor, int accuracy); }
SensorEventListener接口需要由传感器系统的调用者来实现,onSensorChanged()在传感器数值改变时被调用,onAccuracyChanged()方法在传感器精度变化时被调用。
2.相关部分
android.view中的OrientationEventListener是一个工具类,提供了方向信息。
OrientationEventListener中包括了一个抽象方法,如下所示:
abstract public void onOrientationChanged(int orientation);
enable()和disable()方法则负责使能和禁止传感器。
OrientationEventListener本身通过调用SensorManager实现,在获取传感器数据后,根据三个方向的加速度信息(X,Y,Z)和重力加速度计算了当前方向的逻辑。
Android系统根据方向自动转动显示的功能就是基于OrientationEventListener实现的。