Android板级支持与硬件相关子系统
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

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实现的。