Android传感器开发与智能设备案例实战
上QQ阅读APP看书,第一时间看更新

第5章 Android传感器系统分析

传感器是近年来随着物联网这一概念的流行而推出的,现在人们已经逐渐认识了传感器这一概念。其实传感器在大家日常的生活中经常见到甚至是用到,例如楼宇的声控楼梯灯和马路上的路灯等。在本章的内容中,将详细讲解Android系统中传感器系统的基本知识,为读者步入本书后面知识的学习打下基础。

5.1 Android传感器系统概述

在Android系统中提供的主要传感器有加速度、磁场、方向、陀螺仪、光线、压力、温度和接近传感器等。传感器系统会主动对上层报告传感器精度和数据的变化,并且提供了设置传感器精度的接口,这些接口可以在Java应用和Java框架中使用。

Android传感器系统的基本层次结构如图5-1所示。

▲图5-1 传感器系统的层次结构

根据图5-1所示的结构,Android传感器系统从上到下分别是Java应用层、Java框架对传感器的应用、传感器类、传感器硬件抽象层和传感器驱动。各个层的具体说明如下所示。

(1)传感器系统的Java部分

代码路径是:

      frameworks/base/include/core/java/android/hardware

此部分对应的实现文件是Sensor*.java。

(2)传感器系统的JNI部分

代码路径是:

      frameworks/base/core/jni/android_hardware_SensorManager.cpp

在此部分中提供了对类android.hardware.Sensor.Manage的本地支持。

(3)传感器系统HAL层

头文件路径是:

      hardware/libhardware/include/hardware/sensors.h

在Android系统中,传感器系统的硬件抽象层需要特定编码实现。

(4)驱动层

驱动层的代码路径是:

      kernel/driver/hwmon/$(PROJECT)/sensor

在库sensor.so中提供了如下所示的8个API函数。

· 控制方面:在结构体sensors_control_device_t中定义,包括下面所示的函数。

int (*open_data_source)(struct sensors_control_device_t *dev);

int (*activate)(struct sensors_control_device_t *dev, int handle, int enabled);

int (*set_delay)(struct sensors_control_device_t *dev, int32_t ms);

int (*wake)(struct sensors_control_device_t *dev)。

·数据方面:在结构体sensors_data_device_t中定义,包括下面所示的函数。

int (*data_open)(struct sensors_data_device_t *dev, int fd);

int (*data_close)(struct sensors_data_device_t *dev);

int (*poll)(struct sensors_data_device_t *dev, sensors_data_t* data)。

· 模块方面:在结构体sensors_module_t中定义,包括下面一个函数。

      int (*get_sensors_list)(struct sensors_module_t* module, struct sensor_t const** list)

在Android系统的Java层中,Sensor的状态是由SensorService来负责控制的,其Java代码和JNI代码分别位于如下文件中。

      frameworks/base/services/java/com/android/server/SensorService.java
      frameworks/base/services/jni/com_android_server_SensorService.cpp

SensorManager负责在Java层Sensor的数据控制,它的Java代码和JNI代码分别位于如下文件中。

      frameworks/base/core/java/android/hardware/SensorManager.java
      frameworks/base/core/jni/android_hardware_SensorManager.cpp

在Android的Framework中,是通过文件sensorService.java和sensorManager.java实现与Sensor传感器通信的。文件sensorService.java的通信功能是通过JNI调用sensorService.cpp中的方法实现的。

文件sensorManager.java的具体通信功能是通过JNI调用sensorManager.cpp中的方法实现的。文件sensorService.cpp和sensorManager.cpp通过文件hardware.c与sensor.so通信。其中文件sensorService.cpp实现对sensor的状态控制,文件sensorManger.cpp实现对sensor的数据控制。

库sensor.so通过ioctl控制sensor driver的状态,通过打开sensor driver对应的设备文件读取G-sensor采集的数据。

5.2 分析Java层

在Android系统中,传感器系统的Java部分的实现文件是:

      \sdk\apps\SdkController\src\com\android\tools\sdkcontroller\activities\SensorActivit
      y.java

通过阅读文件SensorActivity.java的源码可知,在应用程序中使用传感器需要用到hardware包中的SensorManager、SensorListener等相关的类,具体实现代码如下所示。

      public class SensorActivity extends BaseBindingActivity
              implements android.os.Handler.Callback {

          @SuppressWarnings("hiding")
          public static String TAG = SensorActivity.class.getSimpleName();
          private static boolean DEBUG = true;

          private static final int MSG_UPDATE_ACTUAL_HZ = 0x31415;

          private TableLayout mTableLayout;
          private TextView mTextError;
          private TextView mTextStatus;
          private TextView mTextTargetHz;
          private TextView mTextActualHz;
          private SensorChannel mSensorHandler;

          private final Map<MonitoredSensor, DisplayInfo> mDisplayedSensors =
              new HashMap<SensorChannel.MonitoredSensor, SensorActivity.DisplayInfo>();
          private final android.os.Handler mUiHandler = new android.os.Handler(this);
          private int mTargetSampleRate;
          private long mLastActualUpdateMs;
          /** 第一次创建activity是调用. */
          @Override
          public void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.sensors);
              mTableLayout = (TableLayout) findViewById(R.id.tableLayout);
              mTextError  = (TextView) findViewById(R.id.textError);
              mTextStatus = (TextView) findViewById(R.id.textStatus);
              mTextTargetHz = (TextView) findViewById(R.id.textSampleRate);
              mTextActualHz = (TextView) findViewById(R.id.textActualRate);
              updateStatus("Waiting for connection");

              mTextTargetHz.setOnKeyListener(new OnKeyListener() {
                @Override
                public boolean onKey(View v, int keyCode, KeyEvent event) {
                    updateSampleRate();
                    return false;
                }
              });
              mTextTargetHz.setOnFocusChangeListener(new OnFocusChangeListener() {
                @Override
                public void onFocusChange(View v, boolean hasFocus) {
                    updateSampleRate();
                }
              });
          }

          @Override
          protected void onResume() {
              if (DEBUG) Log.d(TAG, "onResume");
              // BaseBindingActivity绑定后套服务
              super.onResume();
              updateError();
          }

          @Override
          protected void onPause() {
              if (DEBUG) Log.d(TAG, "onPause");
              // BaseBindingActivity.onResume will unbind from (but not stop) the service
              super.onPause();
          }

          @Override
          protected void onDestroy() {
              if (DEBUG) Log.d(TAG, "onDestroy");

    super.onDestroy();
    removeSensorUi();
}
// ----------

@Override
protected void onServiceConnected() {
    if (DEBUG) Log.d(TAG, "onServiceConnected");
    createSensorUi();
}

@Override
protected void onServiceDisconnected() {
    if (DEBUG) Log.d(TAG, "onServiceDisconnected");
    removeSensorUi();
}

@Override
protected ControllerListener createControllerListener() {
    return new SensorsControllerListener();
}

// ----------

private class SensorsControllerListener implements ControllerListener {
    @Override
    public void onErrorChanged() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
              updateError();
            }
        });
    }

    @Override
    public void onStatusChanged() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
              ControllerBinder binder = getServiceBinder();
              if (binder ! = null) {
                  boolean connected = binder.isEmuConnected();
                  mTableLayout.setEnabled(connected);
                  updateStatus(connected ? "Emulated connected" : "Emulator disconnected");
              }
            }
        });
    }
}

private void createSensorUi() {
    final LayoutInflater inflater = getLayoutInflater();
    if (! mDisplayedSensors.isEmpty()) {
        removeSensorUi();
    }
    mSensorHandler = (SensorChannel) getServiceBinder().getChannel(Channel.SENSOR_
    CHANNEL);
    if (mSensorHandler ! = null) {
        mSensorHandler.addUiHandler(mUiHandler);
        mUiHandler.sendEmptyMessage(MSG_UPDATE_ACTUAL_HZ);

        assert mDisplayedSensors.isEmpty();
        List<MonitoredSensor> sensors = mSensorHandler.getSensors();
        for (MonitoredSensor sensor : sensors) {
    final TableRow row = (TableRow) inflater.inflate(R.layout.sensor_row,
                                              mTableLayout,
                                              false);
    mTableLayout.addView(row);
    mDisplayedSensors.put(sensor, new DisplayInfo(sensor, row));
}
}
}

private void removeSensorUi() {
if (mSensorHandler ! = null) {
mSensorHandler.removeUiHandler(mUiHandler);
mSensorHandler = null;
}
mTableLayout.removeAllViews();
for (DisplayInfo info : mDisplayedSensors.values()) {
info.release();
}
mDisplayedSensors.clear();
}

private class DisplayInfo implements CompoundButton.OnCheckedChangeListener {
private MonitoredSensor mSensor;
private CheckBox mChk;
private TextView mVal;

public DisplayInfo(MonitoredSensor sensor, TableRow row) {
mSensor = sensor;

// Initialize displayed checkbox for this sensor, and register
// checked state listener for it
mChk = (CheckBox) row.findViewById(R.id.row_checkbox);
mChk.setText(sensor.getUiName());
mChk.setEnabled(sensor.isEnabledByEmulator());
mChk.setChecked(sensor.isEnabledByUser());
mChk.setOnCheckedChangeListener(this);

//初始化显示该传感器的文本框
mVal = (TextView) row.findViewById(R.id.row_textview);
mVal.setText(sensor.getValue());
}

/**
*相关的复选框选中状态变化处理。当复选框被选中时会注册传感器变化。
*如果不加以控制会取消传感器的变化
*/
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (mSensor ! = null) {
    mSensor.onCheckedChanged(isChecked);
}
}

public void release() {
mChk = null;
mVal = null;
mSensor = null;
}

public void updateState() {
if (mChk ! = null && mSensor ! = null) {
    mChk.setEnabled(mSensor.isEnabledByEmulator());
    mChk.setChecked(mSensor.isEnabledByUser());
}
}
public void updateValue() {
if (mVal ! = null && mSensor ! = null) {

    mVal.setText(mSensor.getValue());
}
}
}

/**实现回调处理程序*/
@Override
public boolean handleMessage(Message msg) {
DisplayInfo info = null;
switch (msg.what) {
case SensorChannel.SENSOR_STATE_CHANGED:
info = mDisplayedSensors.get(msg.obj);
if (info ! = null) {
    info.updateState();
}
break;
case SensorChannel.SENSOR_DISPLAY_MODIFIED:
info = mDisplayedSensors.get(msg.obj);
if (info ! = null) {
    info.updateValue();
}
if (mSensorHandler ! = null) {
    updateStatus(Integer.toString(mSensorHandler.getMsgSentCount())+"events sent");
    //如果值已经修改则更新 "actual rate"
    long ms = mSensorHandler.getActualUpdateMs();
    if (ms ! = mLastActualUpdateMs) {
        mLastActualUpdateMs = ms;
        String hz = mLastActualUpdateMs <= 0 ? "--" :
                      Integer.toString((int) Math.ceil(1000. / ms));
        mTextActualHz.setText(hz);
    }
}
break;
case MSG_UPDATE_ACTUAL_HZ:
if (mSensorHandler ! = null) {
    //如果值已经修改则更新 "actual rate"
    long ms = mSensorHandler.getActualUpdateMs();
    if (ms ! = mLastActualUpdateMs) {
        mLastActualUpdateMs = ms;
        String hz = mLastActualUpdateMs <= 0 ? "--" :
                      Integer.toString((int) Math.ceil(1000. / ms));
        mTextActualHz.setText(hz);
    }
    mUiHandler.sendEmptyMessageDelayed(MSG_UPDATE_ACTUAL_HZ, 1000 /*1s*/);
}
}
return true; // we consumed this message
}

private void updateStatus(String status) {
mTextStatus.setVisibility(status == null ? View.GONE : View.VISIBLE);
if (status ! = null) mTextStatus.setText(status);
}

private void updateError() {
ControllerBinder binder = getServiceBinder();
String error = binder == null ? "" : binder.getServiceError();
if (error == null) {
error = "";
}

mTextError.setVisibility(error.length() == 0 ? View.GONE : View.VISIBLE);
mTextError.setText(error);
}
private void updateSampleRate() {
String str = mTextTargetHz.getText().toString();
try {

                int hz = Integer.parseInt(str.trim());
                // Cap the value. 50 Hz is a reasonable max value for the emulator
                if (hz <= 0 || hz > 50) {
                    hz = 50;
                }

                if (hz ! = mTargetSampleRate) {
                    mTargetSampleRate = hz;
                    if (mSensorHandler ! = null) {
                      mSensorHandler.setUpdateTargetMs(hz <= 0 ? 0 : (int)(1000.0f / hz));
                    }
                }
            } catch (Exception ignore) {}
        }
      }

通过上述代码可知,整个Java层利用了大家熟悉的观察者模式对传感器的数据进行了监听处理。

5.3 分析Frameworks层

在Android系统中,传感器系统的Frameworks层的代码路径是:

      frameworks/base/include/core/java/android/hardware

Frameworks层是Android系统提供的应用程序开发接口和应用程序框架。应用程序的调用是通过类实例化或类继承进行的。对应用程序来说,最重要的就是把SensorListener注册到SensorManager上,从而才能以观察者身份接收到数据的变化,因此,要把目光落在SensorManager的构造函数、RegisterListener函数和通知机制相关的代码上。

本节将详细讲解传感器系统的Frameworks层的具体实现流程。

5.3.1 监听传感器的变化

在Android传感器系统的Frameworks层中,文件SensorListener.java用于监听从Java应用层中传递过来的变化。文件SensorListener.java比较简单,具体代码如下所示。

      package android.hardware;
      @Deprecated
      public interface SensorListener {
          public void onSensorChanged(int sensor, float[] values);
          public void onAccuracyChanged(int sensor, int accuracy);
      }

5.3.2 注册监听

当文件SensorListener.java监听到变化之后,会通过文件SensorManager.java来向服务注册监听变化,并调度Sensor的具体任务。例如在开发Android传感器应用程序时,在上层的通用开发流程如下所示。

(1)通过“getSystemService(SENSOR_SERVICE); ”语句得到传感器服务。这样得到一个用来管理分配调度处理Sensor工作的SensorManager。SensorManager并不服务而是运行于后台,真正属于Sensor的系统服务是SensorService,在终端下的“#service list”中可以看到sensorservice:[android.gui.SensorServer]。

(2)通过“getDefaultSensor(Sensor.TYPE_GRAVITY); ”得到传感器类型,当然还有各种功能不同的传感器,具体可以查阅Android官网API或者源码Sensor.java。

(3)注册监听器SensorEventListener。在应用程序中打开一个监听接口,专门用于处理传感器的数据。

(4)通过回调函数onSensorChanged和onAccuracyChanged实现实时监听。例如对重力感应器的xyz值经过算法变换得到左右上下前后方向等,就由这个回调函数实现。

综上所述,传感器顶层的处理流程如图5-2所示。

▲图5-2 传感器顶层的处理流程

文件SensorManager.java的具体实现流程如下所示。

(1)定义类SensorManager,然后设置各种传感器的初始变量值,具体代码如下所示。

      public abstract class SensorManager {
          protected static final String TAG = "SensorManager";
          private static final float[] mTempMatrix = new float[16];

          // Cached lists of sensors by type.  Guarded by mSensorListByType
          private final SparseArray<List<Sensor>> mSensorListByType =
                new SparseArray<List<Sensor>>();

          // Legacy sensor manager implementation. Guarded by mSensorListByType during initialization
          private LegacySensorManager mLegacySensorManager;
          @Deprecated
          public static final int SENSOR_ORIENTATION = 1 << 0;
          @Deprecated
          public static final int SENSOR_ACCELEROMETER = 1 << 1;
          @Deprecated
          public static final int SENSOR_TEMPERATURE = 1 << 2;
          @Deprecated
          public static final int SENSOR_MAGNETIC_FIELD = 1 << 3;
          @Deprecated
          public static final int SENSOR_LIGHT = 1 << 4;
          @Deprecated
          public static final int SENSOR_PROXIMITY = 1 << 5;
          @Deprecated
          public static final int SENSOR_TRICORDER = 1 << 6;
          @Deprecated
          public static final int SENSOR_ORIENTATION_RAW = 1 << 7;
          @Deprecated
          public static final int SENSOR_ALL = 0x7F;
          @Deprecated
          public static final int SENSOR_MIN = SENSOR_ORIENTATION;
          @Deprecated
          public static final int SENSOR_MAX = ((SENSOR_ALL + 1)>>1);

          @Deprecated
          public static final int DATA_X = 0;
          @Deprecated
          public static final int DATA_Y = 1;
          @Deprecated
          public static final int DATA_Z = 2;
          @Deprecated

    public static final int RAW_DATA_INDEX = 3;
    @Deprecated
    public static final int RAW_DATA_X = 3;
    @Deprecated
    public static final int RAW_DATA_Y = 4;
    @Deprecated
    public static final int RAW_DATA_Z = 5;

    /** Standard gravity (g) on Earth. This value is equivalent to 1G */
    public static final float STANDARD_GRAVITY = 9.80665f;

    /** Sun's gravity in SI units (m/s^2) */
    public static final float GRAVITY_SUN = 275.0f;
    /** Mercury's gravity in SI units (m/s^2) */
    public static final float GRAVITY_MERCURY = 3.70f;
    /** Venus' gravity in SI units (m/s^2) */
    public static final float GRAVITY_VENUS = 8.87f;
    /** Earth's gravity in SI units (m/s^2) */
    public static final float GRAVITY_EARTH = 9.80665f;
    /** The Moon's gravity in SI units (m/s^2) */
    public static final float GRAVITY_MOON = 1.6f;
    /** Mars' gravity in SI units (m/s^2) */
    public static final float GRAVITY_MARS = 3.71f;
    /** Jupiter's gravity in SI units (m/s^2) */
    public static final float GRAVITY_JUPITER = 23.12f;
    /** Saturn's gravity in SI units (m/s^2) */
    public static final float GRAVITY_SATURN = 8.96f;
    /** Uranus' gravity in SI units (m/s^2) */
    public static final float GRAVITY_URANUS = 8.69f;
    /** Neptune's gravity in SI units (m/s^2) */
    public static final float GRAVITY_NEPTUNE = 11.0f;
    /** Pluto's gravity in SI units (m/s^2) */
    public static final float GRAVITY_PLUTO = 0.6f;
    /** Gravity (estimate) on the first Death Star in Empire units (m/s^2) */
    public static final float GRAVITY_DEATH_STAR_I = 0.000000353036145f;
    /** Gravity on the island */
    public static final float GRAVITY_THE_ISLAND = 4.815162342f;

    /** Maximum magnetic field on Earth's surface */
    public static final float MAGNETIC_FIELD_EARTH_MAX = 60.0f;
    /** Minimum magnetic field on Earth's surface */
    public static final float MAGNETIC_FIELD_EARTH_MIN = 30.0f;

    /** Standard atmosphere, or average sea-level pressure in hPa (millibar) */
    public static final float PRESSURE_STANDARD_ATMOSPHERE = 1013.25f;

    /** Maximum luminance of sunlight in lux */
    public static final float LIGHT_SUNLIGHT_MAX = 120000.0f;
    /** luminance of sunlight in lux */
    public static final float LIGHT_SUNLIGHT = 110000.0f;
    /** luminance in shade in lux */
    public static final float LIGHT_SHADE = 20000.0f;
    /** luminance under an overcast sky in lux */
    public static final float LIGHT_OVERCAST = 10000.0f;
    /** luminance at sunrise in lux */
    public static final float LIGHT_SUNRISE = 400.0f;
    /** luminance under a cloudy sky in lux */
    public static final float LIGHT_CLOUDY = 100.0f;
    /** luminance at night with full moon in lux */
    public static final float LIGHT_FULLMOON = 0.25f;
    /** luminance at night with no moon in lux*/
    public static final float LIGHT_NO_MOON = 0.001f;

    /** get sensor data as fast as possible */
    public static final int SENSOR_DELAY_FASTEST = 0;

          /** rate suitable for games */
          public static final int SENSOR_DELAY_GAME = 1;
          /** rate suitable for the user interface */
          public static final int SENSOR_DELAY_UI = 2;
          /**(默认值)适合屏幕方向的变化*/
          public static final int SENSOR_DELAY_NORMAL = 3;

          /**
           *返回的值,该传感器是不可信的,需要进行校准或环境不允许读数
           */
          public static final int SENSOR_STATUS_UNRELIABLE = 0;
          /**
           *该传感器是报告的低精度的数据,与环境的校准是必要的
           */
          public static final int SENSOR_STATUS_ACCURACY_LOW = 1;
          /**
           * This sensor is reporting data with an average level of accuracy,
           * calibration with the environment may improve the readings
           */
          public static final int SENSOR_STATUS_ACCURACY_MEDIUM = 2;
          /** This sensor is reporting data with maximum accuracy */
          public static final int SENSOR_STATUS_ACCURACY_HIGH = 3;
          /** see {@link #remapCoordinateSystem} */
          public static final int AXIS_X = 1;
          /** see {@link #remapCoordinateSystem} */
          public static final int AXIS_Y = 2;
          /** see {@link #remapCoordinateSystem} */
          public static final int AXIS_Z = 3;
          /** see {@link #remapCoordinateSystem} */
          public static final int AXIS_MINUS_X = AXIS_X | 0x80;
          /** see {@link #remapCoordinateSystem} */
          public static final int AXIS_MINUS_Y = AXIS_Y | 0x80;
          /** see {@link #remapCoordinateSystem} */
          public static final int AXIS_MINUS_Z = AXIS_Z | 0x80;

(2)定义各种设备类型方法和设备数据的方法,这些方法非常重要,在编写的应用程序中,可以通过AIDL接口远程调用(RPC)的方式得到SensorManager。这样通过在类SensorManager中的方法,可以得到底层的各种传感器数据。上述方法的具体实现代码如下所示。

          public int getSensors() {
              return getLegacySensorManager().getSensors();
          }
          public List<Sensor> getSensorList(int type) {
              // cache the returned lists the first time
              List<Sensor> list;
              final List<Sensor> fullList = getFullSensorList();
              synchronized (mSensorListByType) {
                  list = mSensorListByType.get(type);
                  if (list == null) {
                    if (type == Sensor.TYPE_ALL) {
                        list = fullList;
                    } else {
                        list = new ArrayList<Sensor>();
                        for (Sensor i : fullList) {
                            if (i.getType() == type)
                                list.add(i);
                        }
                    }
                    list = Collections.unmodifiableList(list);
                    mSensorListByType.append(type, list);
                  }
              }
              return list;

    }
    public Sensor getDefaultSensor(int type) {
        // TODO: need to be smarter, for now, just return the 1st sensor
        List<Sensor> l = getSensorList(type);
        return l.isEmpty() ? null : l.get(0);
    }
    @Deprecated
    public boolean registerListener(SensorListener listener, int sensors) {
        return registerListener(listener, sensors, SENSOR_DELAY_NORMAL);
    }
    @Deprecated
    public boolean registerListener(SensorListener listener, int sensors, int rate) {
        return getLegacySensorManager().registerListener(listener, sensors, rate);
    }
    @Deprecated
    public void unregisterListener(SensorListener listener) {
        unregisterListener(listener, SENSOR_ALL | SENSOR_ORIENTATION_RAW);
    }
    @Deprecated
    public void unregisterListener(SensorListener listener, int sensors) {
        getLegacySensorManager().unregisterListener(listener, sensors);
    }
    public void unregisterListener(SensorEventListener listener, Sensor sensor) {
        if (listener == null || sensor == null) {
            return;
        }
        unregisterListenerImpl(listener, sensor);
    }
    public void unregisterListener(SensorEventListener listener) {
        if (listener == null) {
            return;
        }
        unregisterListenerImpl(listener, null);
    }
    protected abstract void unregisterListenerImpl(SensorEventListener listener, Sensor
    sensor);
    public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate)
{
        return registerListener(listener, sensor, rate, null);
    }
    public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate,
            Handler handler) {
        if (listener == null || sensor == null) {
            return false;
        }

        int delay = -1;
        switch (rate) {
            case SENSOR_DELAY_FASTEST:
              delay = 0;
              break;
            case SENSOR_DELAY_GAME:
              delay = 20000;
              break;
            case SENSOR_DELAY_UI:
              delay = 66667;
              break;
            case SENSOR_DELAY_NORMAL:
              delay = 200000;
              break;
            default:
              delay = rate;
              break;
        }
        return registerListenerImpl(listener, sensor, delay, handler);
    }
    protected abstract boolean registerListenerImpl(SensorEventListener listener, Sensor
    sensor, int delay, Handler handler);

    public static boolean getRotationMatrix(float[] R, float[] I,
            float[] gravity, float[] geomagnetic) {
        // TODO: move this to native code for efficiency
        float Ax = gravity[0];
        float Ay = gravity[1];
        float Az = gravity[2];
        final float Ex = geomagnetic[0];
        final float Ey = geomagnetic[1];
        final float Ez = geomagnetic[2];
        float Hx = Ey*Az - Ez*Ay;
        float Hy = Ez*Ax - Ex*Az;
        float Hz = Ex*Ay - Ey*Ax;
        final float normH = (float)Math.sqrt(Hx*Hx + Hy*Hy + Hz*Hz);
        if (normH < 0.1f) {
            // device is close to free fall (or in space? ), or close to
            // magnetic north pole. Typical values are  > 100
            return false;
        }
        final float invH = 1.0f / normH;
        Hx *= invH;
        Hy *= invH;
        Hz *= invH;
        final float invA = 1.0f / (float)Math.sqrt(Ax*Ax + Ay*Ay + Az*Az);
        Ax *= invA;
        Ay *= invA;
        Az *= invA;
        final float Mx = Ay*Hz - Az*Hy;
        final float My = Az*Hx - Ax*Hz;
        final float Mz = Ax*Hy - Ay*Hx;
        if (R ! = null) {
            if (R.length == 9) {
              R[0] = Hx;    R[1] = Hy;    R[2] = Hz;
              R[3] = Mx;    R[4] = My;    R[5] = Mz;
              R[6] = Ax;    R[7] = Ay;    R[8] = Az;
            } else if (R.length == 16) {
              R[0]  = Hx;    R[1]  = Hy;    R[2]  = Hz;   R[3]  = 0;
              R[4]  = Mx;    R[5]  = My;    R[6]  = Mz;   R[7]  = 0;
              R[8]  = Ax;    R[9]  = Ay;    R[10] = Az;   R[11] = 0;
              R[12] = 0;    R[13] = 0;    R[14] = 0;    R[15] = 1;
            }
        }
        if (I ! = null) {
            // compute the inclination matrix by projecting the geomagnetic
            // vector onto the Z (gravity) and X (horizontal component
            // of geomagnetic vector) axes
            final float invE = 1.0f / (float)Math.sqrt(Ex*Ex + Ey*Ey + Ez*Ez);
            final float c = (Ex*Mx + Ey*My + Ez*Mz) * invE;
            final float s = (Ex*Ax + Ey*Ay + Ez*Az) * invE;
            if (I.length == 9) {
              I[0] = 1;    I[1] = 0;    I[2] = 0;
              I[3] = 0;    I[4] = c;    I[5] = s;
              I[6] = 0;    I[7] =-s;    I[8] = c;
            } else if (I.length == 16) {
              I[0] = 1;    I[1] = 0;    I[2] = 0;
              I[4] = 0;    I[5] = c;    I[6] = s;
              I[8] = 0;    I[9] =-s;    I[10]= c;
              I[3] = I[7] = I[11] = I[12] = I[13] = I[14] = 0;
              I[15] = 1;
            }
        }
        return true;
    }
    public static float getInclination(float[] I) {
        if (I.length == 9) {
            return (float)Math.atan2(I[5], I[4]);
        } else {
            return (float)Math.atan2(I[6], I[5]);
        }
    }

    public static boolean remapCoordinateSystem(float[] inR, int X, int Y,
            float[] outR)
    {
        if (inR == outR) {
            final float[] temp = mTempMatrix;
            synchronized(temp) {
              // we don't expect to have a lot of contention
              if (remapCoordinateSystemImpl(inR, X, Y, temp)) {
                  final int size = outR.length;
                  for (int i=0 ; i<size ; i++)
                      outR[i] = temp[i];
                  return true;
              }
            }
        }
        return remapCoordinateSystemImpl(inR, X, Y, outR);
    }

    private static boolean remapCoordinateSystemImpl(float[] inR, int X, int Y,
            float[] outR)
    {
        /*
        * X and Y define a rotation matrix 'r':
        *
        * (X==1)? ((X&0x80)? -1:1):0 (X==2)? ((X&0x80)? -1:1):0 (X==3)? ((X&0x80)? -1:1):0
        * (Y==1)? ((Y&0x80)? -1:1):0 (Y==2)? ((Y&0x80)? -1:1):0 (Y==3)? ((X&0x80)? -1:1):0
        *                          r[0] ^ r[1]
        *
        * where the 3rd line is the vector product of the first 2 lines
        *
        */

        final int length = outR.length;
        if (inR.length ! = length)
            return false;   // invalid parameter
        if ((X & 0x7C)! =0 || (Y & 0x7C)! =0)
            return false;   // invalid parameter
        if (((X & 0x3)==0) || ((Y & 0x3)==0))
            return false;   // no axis specified
        if ((X & 0x3) == (Y & 0x3))
            return false;   // same axis specified

        // Z is "the other" axis, its sign is either +/- sign(X)*sign(Y)
        // this can be calculated by exclusive-or'ing X and Y; except for
        // the sign inversion (+/-) which is calculated below
        int Z = X ^ Y;

        // extract the axis (remove the sign), offset in the range 0 to 2
        final int x = (X & 0x3)-1;
        final int y = (Y & 0x3)-1;
        final int z = (Z & 0x3)-1;

        // compute the sign of Z (whether it needs to be inverted)
        final int axis_y = (z+1)%3;
        final int axis_z = (z+2)%3;
        if (((x^axis_y)|(y^axis_z)) ! = 0)
            Z ^= 0x80;

        final boolean sx = (X>=0x80);
        final boolean sy = (Y>=0x80);
        final boolean sz = (Z>=0x80);

        // Perform R * r, in avoiding actual muls and adds
        final int rowLength = ((length==16)?4:3);
        for (int j=0 ; j<3 ; j++) {
            final int offset = j*rowLength;
            for (int i=0 ; i<3 ; i++) {
              if (x==i)   outR[offset+i] = sx ? -inR[offset+0] : inR[offset+0];

    if (y==i)   outR[offset+i] = sy ? -inR[offset+1] : inR[offset+1];
    if (z==i)   outR[offset+i] = sz ? -inR[offset+2] : inR[offset+2];
}
}
if (length == 16) {
outR[3] = outR[7] = outR[11] = outR[12] = outR[13] = outR[14] = 0;
outR[15] = 1;
}
return true;
}
public static float[] getOrientation(float[] R, float values[]) {

if (R.length == 9) {
values[0] = (float)Math.atan2(R[1], R[4]);
values[1] = (float)Math.asin(-R[7]);
values[2] = (float)Math.atan2(-R[6], R[8]);
} else {
values[0] = (float)Math.atan2(R[1], R[5]);
values[1] = (float)Math.asin(-R[9]);
values[2] = (float)Math.atan2(-R[8], R[10]);
}
return values;
}

public static float getAltitude(float p0, float p) {
final float coef = 1.0f / 5.255f;
return 44330.0f * (1.0f - (float)Math.pow(p/p0, coef));
}

public static void getAngleChange( float[] angleChange, float[] R, float[] prevR) {
float rd1=0, rd4=0, rd6=0, rd7=0, rd8=0;
float ri0=0, ri1=0, ri2=0, ri3=0, ri4=0, ri5=0, ri6=0, ri7=0, ri8=0;
float pri0=0, pri1=0, pri2=0, pri3=0, pri4=0, pri5=0, pri6=0, pri7=0, pri8=0;

if(R.length == 9) {
ri0 = R[0];
ri1 = R[1];
ri2 = R[2];
ri3 = R[3];
ri4 = R[4];
ri5 = R[5];
ri6 = R[6];
ri7 = R[7];
ri8 = R[8];
} else if(R.length == 16) {
ri0 = R[0];
ri1 = R[1];
ri2 = R[2];
ri3 = R[4];
ri4 = R[5];
ri5 = R[6];
ri6 = R[8];
ri7 = R[9];
ri8 = R[10];
}

if(prevR.length == 9) {
pri0 = prevR[0];
pri1 = prevR[1];
pri2 = prevR[2];
pri3 = prevR[3];
pri4 = prevR[4];
pri5 = prevR[5];
pri6 = prevR[6];
pri7 = prevR[7];
pri8 = prevR[8];
} else if(prevR.length == 16) {
pri0 = prevR[0];
pri1 = prevR[1];
pri2 = prevR[2];

    pri3 = prevR[4];
    pri4 = prevR[5];
    pri5 = prevR[6];
    pri6 = prevR[8];
    pri7 = prevR[9];
    pri8 = prevR[10];
}
// calculate the parts of the rotation difference matrix we need
// rd[i][j] = pri[0][i] * ri[0][j] + pri[1][i] * ri[1][j] + pri[2][i] * ri[2][j];

rd1 = pri0 * ri1 + pri3 * ri4 + pri6 * ri7; //rd[0][1]
rd4 = pri1 * ri1 + pri4 * ri4 + pri7 * ri7; //rd[1][1]
rd6 = pri2 * ri0 + pri5 * ri3 + pri8 * ri6; //rd[2][0]
rd7 = pri2 * ri1 + pri5 * ri4 + pri8 * ri7; //rd[2][1]
rd8 = pri2 * ri2 + pri5 * ri5 + pri8 * ri8; //rd[2][2]

angleChange[0] = (float)Math.atan2(rd1, rd4);
angleChange[1] = (float)Math.asin(-rd7);
angleChange[2] = (float)Math.atan2(-rd6, rd8);
}
public static void getRotationMatrixFromVector(float[] R, float[] rotationVector) {

float q0;
float q1 = rotationVector[0];
float q2 = rotationVector[1];
float q3 = rotationVector[2];

if (rotationVector.length == 4) {
    q0 = rotationVector[3];
} else {
    q0 = 1- q1*q1- q2*q2- q3*q3;
    q0 = (q0 > 0) ? (float)Math.sqrt(q0) : 0;
}

float sq_q1 = 2 * q1 * q1;
float sq_q2 = 2 * q2 * q2;
float sq_q3 = 2 * q3 * q3;
float q1_q2 = 2 * q1 * q2;
float q3_q0 = 2 * q3 * q0;
float q1_q3 = 2 * q1 * q3;
float q2_q0 = 2 * q2 * q0;
float q2_q3 = 2 * q2 * q3;
float q1_q0 = 2 * q1 * q0;

if(R.length == 9) {
    R[0] = 1- sq_q2- sq_q3;
    R[1] = q1_q2- q3_q0;
    R[2] = q1_q3 + q2_q0;

    R[3] = q1_q2 + q3_q0;
    R[4] = 1- sq_q1- sq_q3;
    R[5] = q2_q3- q1_q0;

    R[6] = q1_q3- q2_q0;
    R[7] = q2_q3 + q1_q0;
    R[8] = 1- sq_q1- sq_q2;
} else if (R.length == 16) {
    R[0] = 1- sq_q2- sq_q3;
    R[1] = q1_q2- q3_q0;
    R[2] = q1_q3 + q2_q0;
    R[3] = 0.0f;

    R[4] = q1_q2 + q3_q0;
    R[5] = 1- sq_q1- sq_q3;
    R[6] = q2_q3- q1_q0;
    R[7] = 0.0f;

    R[8] = q1_q3- q2_q0;

                R[9] = q2_q3 + q1_q0;
                R[10] = 1- sq_q1- sq_q2;
                R[11] = 0.0f;

                R[12] = R[13] = R[14] = 0.0f;
                R[15] = 1.0f;
            }
        }
        public static void getQuaternionFromVector(float[] Q, float[] rv) {
            if (rv.length == 4) {
                Q[0] = rv[3];
            } else {
                Q[0] = 1- rv[0]*rv[0] - rv[1]*rv[1] - rv[2]*rv[2];
                Q[0] = (Q[0] > 0) ? (float)Math.sqrt(Q[0]) : 0;
            }
            Q[1] = rv[0];
            Q[2] = rv[1];
            Q[3] = rv[2];
        }
        public boolean requestTriggerSensor(TriggerEventListener listener, Sensor sensor) {
            return requestTriggerSensorImpl(listener, sensor);
        }
        protected abstract boolean requestTriggerSensorImpl(TriggerEventListener listener,
                Sensor sensor);
        public boolean cancelTriggerSensor(TriggerEventListener listener, Sensor sensor) {
            return cancelTriggerSensorImpl(listener, sensor, true);
        protected abstract boolean cancelTriggerSensorImpl(TriggerEventListener listener,
                Sensor sensor, boolean disable);
        private LegacySensorManager getLegacySensorManager() {
            synchronized (mSensorListByType) {
                if (mLegacySensorManager == null) {
                    Log.i(TAG, "This application is using deprecated SensorManager API which will "
                          + "be removed someday.  Please consider switching to the new API.");
                    mLegacySensorManager = new LegacySensorManager(this);
                }
                return mLegacySensorManager;
            }
        }
      }

上述方法的功能非常重要,其实就是人们在开发传感器应用程序时用到的API接口。有关上述方法的具体说明,读者可以查阅官网SDK API中对于类android.hardware.SensorManager的具体说明。

5.4 分析JNI层

在Android系统中,传感器系统的JNI部分的代码路径是:

      frameworks/base/core/jni/android_hardware_SensorManager.cpp

在此文件中提供了对类android.hardware.Sensor.Manage的本地支持。上层和JNI层的调用关系如图5-3所示。

▲图5-3 上层和JNI层的调用关系

在上图所示的调用关系中涉及了下面所示的API接口方法。

· nativeClassInit():在JNI层得到android.hardware.Sensor的JNI环境指针;

· sensors_module_init():通过JNI调用本地框架,得到SensorService和SensorService初始化控制流各功能;

· new Sensor():建立一个Sensor对象,具体可查阅官网API android.hardware.Sensor;

· sensors_module_get_next_sensor():上层得到设备支持的所有Sensor,并放入SensorList链表;

· new SensorThread():创建Sensor线程,当应用程序registerListener()注册监听器的时候开启线程run(),注意当没有数据变化时线程会阻塞。

5.4.1 分析android_hardware_SensorManager.cpp

文件android_hardware_SensorManager.cpp的功能是实现文件SensorManager.java中的native(本地)函数,主要是通过调用文件SensorManager.cpp和文件SensorEventQueue.cpp中的相关类来完成相关的工作的。文件android_hardware_SensorManager.cpp的具体实现代码如下所示。

        static struct {
            jclass clazz;
            jmethodID dispatchSensorEvent;
        } gBaseEventQueueClassInfo;

        namespace android {

        struct SensorOffsets
        {
            jfieldID    name;
            jfieldID    vendor;
            jfieldID    version;
            jfieldID    handle;
            jfieldID    type;
            jfieldID    range;
            jfieldID    resolution;
            jfieldID    power;
            jfieldID    minDelay;
        } gSensorOffsets;

        /*
         * The method below are not thread-safe and not intended to be
         */

        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");
        }

    static jint
    nativeGetNextSensor(JNIEnv *env, jclass clazz, jobject sensor, jint next)
    {
        SensorManager& mgr(SensorManager::getInstance());

        Sensor const* const* sensorList;
        size_t count = mgr.getSensorList(&sensorList);
        if (size_t(next) >= count)
            return -1;

        Sensor const* const list = sensorList[next];
        const SensorOffsets& sensorOffsets(gSensorOffsets);
        jstring name = env->NewStringUTF(list->getName().string());
        jstring vendor = env->NewStringUTF(list->getVendor().string());
        env->SetObjectField(sensor, sensorOffsets.name, name);
        env->SetObjectField(sensor, sensorOffsets.vendor, vendor);
        env->SetIntField(sensor, sensorOffsets.version, list->getVersion());
        env->SetIntField(sensor, sensorOffsets.handle, list->getHandle());
        env->SetIntField(sensor, sensorOffsets.type, list->getType());
        env->SetFloatField(sensor, sensorOffsets.range, list->getMaxValue());
        env->SetFloatField(sensor, sensorOffsets.resolution, list->getResolution());
        env->SetFloatField(sensor, sensorOffsets.power, list->getPowerUsage());
        env->SetIntField(sensor, sensorOffsets.minDelay, list->getMinDelay());

        next++;
        return size_t(next) < count ? next : 0;
    }

    //----------------------------------------------------------------------------

    class Receiver : public LooperCallback {
        sp<SensorEventQueue> mSensorQueue;
        sp<MessageQueue> mMessageQueue;
        jobject mReceiverObject;
        jfloatArray mScratch;
    public:
        Receiver(const sp<SensorEventQueue>& sensorQueue,
              const sp<MessageQueue>& messageQueue,
              jobject receiverObject, jfloatArray scratch) {
            JNIEnv* env = AndroidRuntime::getJNIEnv();
            mSensorQueue = sensorQueue;
            mMessageQueue = messageQueue;
            mReceiverObject = env->NewGlobalRef(receiverObject);
            mScratch = (jfloatArray)env->NewGlobalRef(scratch);
        }
        ~Receiver() {
            JNIEnv* env = AndroidRuntime::getJNIEnv();
            env->DeleteGlobalRef(mReceiverObject);
            env->DeleteGlobalRef(mScratch);
        }
        sp<SensorEventQueue> getSensorEventQueue() const {
            return mSensorQueue;
        }

        void destroy() {
            mMessageQueue->getLooper()->removeFd( mSensorQueue->getFd() );
        }

    private:
        virtual void onFirstRef() {
            LooperCallback::onFirstRef();
            mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0,
                  ALOOPER_EVENT_INPUT, this, mSensorQueue.get());
        }

        virtual int handleEvent(int fd, int events, void* data) {
            JNIEnv* env = AndroidRuntime::getJNIEnv();
            sp<SensorEventQueue> q = reinterpret_cast<SensorEventQueue *>(data);
            ssize_t n;

    ASensorEvent buffer[16];
    while ((n = q->read(buffer, 16)) > 0) {
        for (int i=0 ; i<n ; i++) {

            env->SetFloatArrayRegion(mScratch, 0, 16, buffer[i].data);

            env->CallVoidMethod(mReceiverObject,
                  gBaseEventQueueClassInfo.dispatchSensorEvent,
                  buffer[i].sensor,
                  mScratch,
                  buffer[i].vector.status,
                  buffer[i].timestamp);

            if (env->ExceptionCheck()) {
              ALOGE("Exception dispatching input event.");
              return 1;
            }
        }
    }
    if (n<0 && n ! = -EAGAIN) {
        // FIXME: error receiving events, what to do in this case?
    }

    return 1;
}
};

static jint nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jobject eventQ, jobject
msgQ, jfloatArray scratch) {
SensorManager& mgr(SensorManager::getInstance());
sp<SensorEventQueue> queue(mgr.createEventQueue());

sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);
if (messageQueue == NULL) {
    jniThrowRuntimeException(env, "MessageQueue is not initialized.");
    return 0;
}

sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQ, scratch);
receiver->incStrong((void*)nativeInitSensorEventQueue);
return jint(receiver.get());
}

static jint nativeEnableSensor(JNIEnv *env, jclass clazz, jint eventQ, jint handle, jint
us) {
sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
return receiver->getSensorEventQueue()->enableSensor(handle, us);
}

static jint nativeDisableSensor(JNIEnv *env, jclass clazz, jint eventQ, jint handle) {
sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
return receiver->getSensorEventQueue()->disableSensor(handle);
}

static void nativeDestroySensorEventQueue(JNIEnv *env, jclass clazz, jint eventQ, jint
handle) {
sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
receiver->destroy();
receiver->decStrong((void*)nativeInitSensorEventQueue);
}

//----------------------------------------------------------------------------

static JNINativeMethod gSystemSensorManagerMethods[] = {
{"nativeClassInit",
        "()V",
        (void*)nativeClassInit },

          {"nativeGetNextSensor",
                  "(Landroid/hardware/Sensor; I)I",
                  (void*)nativeGetNextSensor },
      };

      static JNINativeMethod gBaseEventQueueMethods[] = {
          {"nativeInitBaseEventQueue",

      "(Landroid/hardware/SystemSensorManager$BaseEventQueue; Landroid/os/MessageQueue; [F)I",
                  (void*)nativeInitSensorEventQueue },

          {"nativeEnableSensor",
                  "(III)I",
                  (void*)nativeEnableSensor },

          {"nativeDisableSensor",
                  "(II)I",
                  (void*)nativeDisableSensor },

          {"nativeDestroySensorEventQueue",
                  "(I)V",
                  (void*)nativeDestroySensorEventQueue },
      };

      }; // namespace android

      using namespace android;

      #define FIND_CLASS(var, className) \
              var = env->FindClass(className); \
              LOG_FATAL_IF(! var, "Unable to find class " className); \
              var = jclass(env->NewGlobalRef(var));

      #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
              var = env->GetMethodID(clazz, methodName, methodDescriptor); \
              LOG_FATAL_IF(! var, "Unable to find method " methodName);

      int register_android_hardware_SensorManager(JNIEnv *env)
      {
          jniRegisterNativeMethods(env, "android/hardware/SystemSensorManager",
                  gSystemSensorManagerMethods, NELEM(gSystemSensorManagerMethods));

          jniRegisterNativeMethods(env,
      "android/hardware/SystemSensorManager$BaseEventQueue",
                  gBaseEventQueueMethods, NELEM(gBaseEventQueueMethods));

          FIND_CLASS(gBaseEventQueueClassInfo.clazz,
      "android/hardware/SystemSensorManager$BaseEventQueue");

          GET_METHOD_ID(gBaseEventQueueClassInfo.dispatchSensorEvent,
                  gBaseEventQueueClassInfo.clazz,
                  "dispatchSensorEvent", "(I[FIJ)V");

          return 0;
      }

5.4.2 处理客户端数据

文件frameworks\native\libs\gui\SensorManager.cpp功能是提供了对传感器数据的部分操作,实现了“sensor_data_XXX()”格式的函数。另外在Native层的客户端,文件SensorManager.cpp还负责与服务端SensorService.cpp之间的通信工作。文件SensorManager.cpp的具体实现代码如下所示。

      // ----------------------------------------------------------------------------
      namespace android {
      // ----------------------------------------------------------------------------

      ANDROID_SINGLETON_STATIC_INSTANCE(SensorManager)

    SensorManager::SensorManager()
        : mSensorList(0)
    {
        // okay we're not locked here, but it's not needed during construction
        assertStateLocked();
    }

    SensorManager::~SensorManager()
    {
        free(mSensorList);
    }

    void SensorManager::sensorManagerDied()
    {
        Mutex::Autolock _l(mLock);
        mSensorServer.clear();
        free(mSensorList);
        mSensorList = NULL;
        mSensors.clear();
    }

    status_t SensorManager::assertStateLocked() const {
        if (mSensorServer == NULL) {
            // try for one second
            const String16 name("sensorservice");
            for (int i=0 ; i<4 ; i++) {
              status_t err = getService(name, &mSensorServer);
              if (err == NAME_NOT_FOUND) {
                  usleep(250000);
                  continue;
              }
              if (err ! = NO_ERROR) {
                  return err;
              }
              break;
            }

            class DeathObserver : public IBinder::DeathRecipient {
              SensorManager& mSensorManger;
              virtual void binderDied(const wp<IBinder>& who) {
                  ALOGW("sensorservice died [%p]", who.unsafe_get());
                  mSensorManger.sensorManagerDied();
              }
            public:
              DeathObserver(SensorManager& mgr) : mSensorManger(mgr) { }
            };

            mDeathObserver = new DeathObserver(*const_cast<SensorManager *>(this));
            mSensorServer->asBinder()->linkToDeath(mDeathObserver);

            mSensors = mSensorServer->getSensorList();
            size_t count = mSensors.size();
            mSensorList = (Sensor const**)malloc(count * sizeof(Sensor*));
            for (size_t i=0 ; i<count ; i++) {
              mSensorList[i] = mSensors.array() + i;
            }
        }

        return NO_ERROR;
    }

    ssize_t SensorManager::getSensorList(Sensor const* const** list) const
    {
        Mutex::Autolock _l(mLock);
        status_t err = assertStateLocked();
        if (err < 0) {
            return ssize_t(err);
        }

          *list = mSensorList;
          return mSensors.size();
      }

      Sensor const* SensorManager::getDefaultSensor(int type)
      {
          Mutex::Autolock _l(mLock);
          if (assertStateLocked() == NO_ERROR) {
              // For now we just return the first sensor of that type we find
              // in the future it will make sense to let the SensorService make
              // that decision
              for (size_t i=0 ; i<mSensors.size() ; i++) {
                  if (mSensorList[i]->getType() == type)
                    return mSensorList[i];
              }
          }
          return NULL;
      }

      sp<SensorEventQueue> SensorManager::createEventQueue()
      {
          sp<SensorEventQueue> queue;

          Mutex::Autolock _l(mLock);
          while (assertStateLocked() == NO_ERROR) {
              sp<ISensorEventConnection> connection =
                    mSensorServer->createSensorEventConnection();
              if (connection == NULL) {
                  // SensorService just died
                  ALOGE("createEventQueue: connection is NULL. SensorService died.");
                  continue;
              }
              queue = new SensorEventQueue(connection);
              break;
          }
          return queue;
      }

      // ----------------------------------------------------------------------------
      }; // namespace android

5.4.3 处理服务端数据

文件frameworks\native\services\sensorservice\SensorService.cpp功能是实现了Sensor真正的后台服务,是服务端的数据处理中心。在Android的传感器系统中,SensorService作为一个轻量级的System Service,运行于SystemServer内,即在system_init<system_init.cpp>中调用了SensorService::instantiate()。SensorService主要功能如下所示。

(1)通过SensorService::instantiate创建实例对象,并增加到ServiceManager中,然后创建并启动线程,并执行threadLoop;

(2)threadLoop从sensor驱动获取原始数据,然后通过SensorEventConnection把事件发送给客户端;

(3)BnSensorServer的成员函数负责让客户端获取sensor列表和创建SensorEventConnection。

文件SensorService.cpp的具体实现代码如下所示。

      namespace android {

      const char* SensorService::WAKE_LOCK_NAME = "SensorService";

      SensorService::SensorService()
          : mInitCheck(NO_INIT)
      {
      }

      void SensorService::onFirstRef()

    {
        ALOGD("nuSensorService starting...");

        SensorDevice& dev(SensorDevice::getInstance());

        if (dev.initCheck() == NO_ERROR) {
            sensor_t const* list;
            ssize_t count = dev.getSensorList(&list);
            if (count > 0) {
              ssize_t orientationIndex = -1;
              bool hasGyro = false;
              uint32_t virtualSensorsNeeds =
                      (1<<SENSOR_TYPE_GRAVITY) |
                      (1<<SENSOR_TYPE_LINEAR_ACCELERATION) |
                      (1<<SENSOR_TYPE_ROTATION_VECTOR);

              mLastEventSeen.setCapacity(count);
              for (ssize_t i=0 ; i<count ; i++) {
                  registerSensor( new HardwareSensor(list[i]) );
                  switch (list[i].type) {
                      case SENSOR_TYPE_ORIENTATION:
                          orientationIndex = i;
                          break;
                      case SENSOR_TYPE_GYROSCOPE:
                          hasGyro = true;
                          break;
                      case SENSOR_TYPE_GRAVITY:
                      case SENSOR_TYPE_LINEAR_ACCELERATION:
                      case SENSOR_TYPE_ROTATION_VECTOR:
                          virtualSensorsNeeds &= ~(1<<list[i].type);
                          break;
                  }
              }

              // it's safe to instantiate the SensorFusion object here
              // (it wants to be instantiated after h/w sensors have been
              // registered)
              const SensorFusion& fusion(SensorFusion::getInstance());

              if (hasGyro) {
                  // Always instantiate Android's virtual sensors. Since they are
                  // instantiated behind sensors from the HAL, they won't
                  // interfere with applications, unless they looks specifically
                  // for them (by name)

                  registerVirtualSensor( new RotationVectorSensor() );
                  registerVirtualSensor( new GravitySensor(list, count) );
                  registerVirtualSensor( new LinearAccelerationSensor(list, count) );

                  // these are optional
                  registerVirtualSensor( new OrientationSensor() );
                  registerVirtualSensor( new CorrectedGyroSensor(list, count) );
              }

              // build the sensor list returned to users
              mUserSensorList = mSensorList;

              if (hasGyro) {
                  // virtual debugging sensors are not added to mUserSensorList
                  registerVirtualSensor( new GyroDriftSensor() );
              }

              if (hasGyro &&
                      (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR))) {
                  // if we have the fancy sensor fusion, and it's not provided by the
                  // HAL, use our own (fused) orientation sensor by removing the
                  // HAL supplied one form the user list
                  if (orientationIndex >= 0) {
                      mUserSensorList.removeItemsAt(orientationIndex);

    }
}

// debugging sensor list
for (size_t i=0 ; i<mSensorList.size() ; i++) {
    switch (mSensorList[i].getType()) {
        case SENSOR_TYPE_GRAVITY:
        case SENSOR_TYPE_LINEAR_ACCELERATION:
        case SENSOR_TYPE_ROTATION_VECTOR:
            if (strstr(mSensorList[i].getVendor().string(), "Google")) {
              mUserSensorListDebug.add(mSensorList[i]);
            }
            break;
        default:
            mUserSensorListDebug.add(mSensorList[i]);
            break;
    }
}

run("SensorService", PRIORITY_URGENT_DISPLAY);
mInitCheck = NO_ERROR;
}
}
}

void SensorService::registerSensor(SensorInterface* s)
{
sensors_event_t event;
memset(&event, 0, sizeof(event));

const Sensor sensor(s->getSensor());
// add to the sensor list (returned to clients)
mSensorList.add(sensor);
// add to our handle->SensorInterface mapping
mSensorMap.add(sensor.getHandle(), s);
// create an entry in the mLastEventSeen array
mLastEventSeen.add(sensor.getHandle(), event);
}

void SensorService::registerVirtualSensor(SensorInterface* s)
{
registerSensor(s);
mVirtualSensorList.add( s );
}

SensorService::~SensorService()
{
for (size_t i=0 ; i<mSensorMap.size() ; i++)
delete mSensorMap.valueAt(i);
}

static const String16 sDump("android.permission.DUMP");

status_t SensorService::dump(int fd, const Vector<String16>& args)
{
const size_t SIZE = 1024;
char buffer[SIZE];
String8 result;
if (! PermissionCache::checkCallingPermission(sDump)) {
snprintf(buffer, SIZE, "Permission Denial: "
    "can't dump SurfaceFlinger from pid=%d, uid=%d\n",
    IPCThreadState::self()->getCallingPid(),
    IPCThreadState::self()->getCallingUid());
result.append(buffer);
} else {
Mutex::Autolock _l(mLock);
snprintf(buffer, SIZE, "Sensor List:\n");
result.append(buffer);
for (size_t i=0 ; i<mSensorList.size() ; i++) {

    const Sensor& s(mSensorList[i]);
    const sensors_event_t& e(mLastEventSeen.valueFor(s.getHandle()));
    snprintf(buffer, SIZE,
            "%-48s| %-32s | 0x%08x | maxRate=%7.2fHz | "
            "last=<%5.1f, %5.1f, %5.1f>\n",
            s.getName().string(),
            s.getVendor().string(),
            s.getHandle(),
            s.getMinDelay() ? (1000000.0f / s.getMinDelay()) : 0.0f,
            e.data[0], e.data[1], e.data[2]);
    result.append(buffer);
}
SensorFusion::getInstance().dump(result, buffer, SIZE);
SensorDevice::getInstance().dump(result, buffer, SIZE);

snprintf(buffer, SIZE, "%d active connections\n",
        mActiveConnections.size());
result.append(buffer);
snprintf(buffer, SIZE, "Active sensors:\n");
result.append(buffer);
for (size_t i=0 ; i<mActiveSensors.size() ; i++) {
    int handle = mActiveSensors.keyAt(i);
    snprintf(buffer, SIZE, "%s (handle=0x%08x, connections=%d)\n",
            getSensorName(handle).string(),
            handle,
            mActiveSensors.valueAt(i)->getNumConnections());
    result.append(buffer);
}
}
write(fd, result.string(), result.size());
return NO_ERROR;
}

void SensorService::cleanupAutoDisabledSensor(const sp<SensorEventConnection>& connection,
sensors_event_t const* buffer, const int count) {
SensorInterface* sensor;
status_t err = NO_ERROR;
for (int i=0 ; i<count ; i++) {
int handle = buffer[i].sensor;
if (getSensorType(handle) == SENSOR_TYPE_SIGNIFICANT_MOTION) {
    if (connection->hasSensor(handle)) {
        sensor = mSensorMap.valueFor(handle);
        err = sensor ? sensor->resetStateWithoutActuatingHardware(connection.
        get(), handle): status_t(BAD_VALUE);
        if (err ! = NO_ERROR) {
            ALOGE("Sensor Inteface: Resetting state failed with err: %d", err);
        }
        cleanupWithoutDisable(connection, handle);
    }
}
}
}

bool SensorService::threadLoop()
{
ALOGD("nuSensorService thread starting...");

const size_t numEventMax = 16;
const size_t minBufferSize = numEventMax + numEventMax * mVirtualSensorList.size();
sensors_event_t buffer[minBufferSize];
sensors_event_t scratch[minBufferSize];
SensorDevice& device(SensorDevice::getInstance());
const size_t vcount = mVirtualSensorList.size();

ssize_t count;
bool wakeLockAcquired = false;
const int halVersion = device.getHalDeviceVersion();
do {
count = device.poll(buffer, numEventMax);

    if (count<0) {
        ALOGE("sensor poll failed (%s)", strerror(-count));
        break;
    }

    // Poll has returned. Hold a wakelock
    // Todo(): add a flag to the sensors definitions to indicate
    // the sensors which can wake up the AP
    for (int i = 0; i < count; i++) {
        if (getSensorType(buffer[i].sensor) == SENSOR_TYPE_SIGNIFICANT_MOTION) {
            acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
            wakeLockAcquired = true;
            break;
        }
    }

    recordLastValue(buffer, count);

    // handle virtual sensors
    if (count && vcount) {
        sensors_event_t const * const event = buffer;
        const DefaultKeyedVector<int, SensorInterface*> virtualSensors(
              getActiveVirtualSensors());
        const size_t activeVirtualSensorCount = virtualSensors.size();
        if (activeVirtualSensorCount) {
            size_t k = 0;
            SensorFusion& fusion(SensorFusion::getInstance());
            if (fusion.isEnabled()) {
              for (size_t i=0 ; i<size_t(count) ; i++) {
                  fusion.process(event[i]);
              }
            }
            for (size_t i=0 ; i<size_t(count) && k<minBufferSize ; i++) {
              for (size_t j=0 ; j<activeVirtualSensorCount ; j++) {
                  if (count + k >= minBufferSize) {
                      ALOGE("buffer too small to hold all events: "
                            "count=%u, k=%u, size=%u",
                            count, k, minBufferSize);
                      break;
                  }
                  sensors_event_t out;
                  SensorInterface* si = virtualSensors.valueAt(j);
                  if (si->process(&out, event[i])) {
                      buffer[count + k] = out;
                      k++;
                  }
              }
            }
            if (k) {
              // record the last synthesized values
              recordLastValue(&buffer[count], k);
              count += k;
              // sort the buffer by time-stamps
              sortEventBuffer(buffer, count);
            }
        }
    }

    // handle backward compatibility for RotationVector sensor
    if (halVersion < SENSORS_DEVICE_API_VERSION_1_0) {
        for (int i = 0; i < count; i++) {
            if (getSensorType(buffer[i].sensor) == SENSOR_TYPE_ROTATION_VECTOR) {
              // All the 4 components of the quaternion should be available
              // No heading accuracy. Set it to -1
              buffer[i].data[4] = -1;
            }
        }
    }

    // send our events to clients
    const SortedVector< wp<SensorEventConnection> > activeConnections(
            getActiveConnections());
    size_t numConnections = activeConnections.size();
    for (size_t i=0 ; i<numConnections ; i++) {
        sp<SensorEventConnection> connection(
              activeConnections[i].promote());
        if (connection ! = 0) {
            connection->sendEvents(buffer, count, scratch);
            // Some sensors need to be auto disabled after the trigger
            cleanupAutoDisabledSensor(connection, buffer, count);
        }
    }

    // We have read the data, upper layers should hold the wakelock
    if (wakeLockAcquired) release_wake_lock(WAKE_LOCK_NAME);

} while (count >= 0 || Thread::exitPending());

ALOGW("Exiting SensorService::threadLoop => aborting...");
abort();
return false;
}

void SensorService::recordLastValue(
    sensors_event_t const * buffer, size_t count)
{
Mutex::Autolock _l(mLock);

// record the last event for each sensor
int32_t prev = buffer[0].sensor;
for (size_t i=1 ; i<count ; i++) {
    // record the last event of each sensor type in this buffer
    int32_t curr = buffer[i].sensor;
    if (curr ! = prev) {
        mLastEventSeen.editValueFor(prev) = buffer[i-1];
        prev = curr;
    }
}
mLastEventSeen.editValueFor(prev) = buffer[count-1];
}

void SensorService::sortEventBuffer(sensors_event_t* buffer, size_t count)
{
struct compar {
    static int cmp(void const* lhs, void const* rhs) {
        sensors_event_t const* l = static_cast<sensors_event_t const*>(lhs);
        sensors_event_t const* r = static_cast<sensors_event_t const*>(rhs);
        return l->timestamp - r->timestamp;
    }
};
qsort(buffer, count, sizeof(sensors_event_t), compar::cmp);
}

SortedVector< wp<SensorService::SensorEventConnection> >
SensorService::getActiveConnections() const
{
Mutex::Autolock _l(mLock);
return mActiveConnections;
}

DefaultKeyedVector<int, SensorInterface*>
SensorService::getActiveVirtualSensors() const
{
Mutex::Autolock _l(mLock);
return mActiveVirtualSensors;
}

String8 SensorService::getSensorName(int handle) const {

    size_t count = mUserSensorList.size();
    for (size_t i=0 ; i<count ; i++) {
        const Sensor& sensor(mUserSensorList[i]);
        if (sensor.getHandle() == handle) {
            return sensor.getName();
        }
    }
    String8 result("unknown");
    return result;
}

int SensorService::getSensorType(int handle) const {
    size_t count = mUserSensorList.size();
    for (size_t i=0 ; i<count ; i++) {
        const Sensor& sensor(mUserSensorList[i]);
        if (sensor.getHandle() == handle) {
            return sensor.getType();
        }
    }
    return -1;
}

Vector<Sensor> SensorService::getSensorList()
{
    char value[PROPERTY_VALUE_MAX];
    property_get("debug.sensors", value, "0");
    if (atoi(value)) {
        return mUserSensorListDebug;
    }
    return mUserSensorList;
}

sp<ISensorEventConnection> SensorService::createSensorEventConnection()
{
    uid_t uid = IPCThreadState::self()->getCallingUid();
    sp<SensorEventConnection> result(new SensorEventConnection(this, uid));
    return result;
}

void SensorService::cleanupConnection(SensorEventConnection* c)
{
    Mutex::Autolock _l(mLock);
    const wp<SensorEventConnection> connection(c);
    size_t size = mActiveSensors.size();
    ALOGD_IF(DEBUG_CONNECTIONS, "%d active sensors", size);
    for (size_t i=0 ; i<size ; ) {
        int handle = mActiveSensors.keyAt(i);
        if (c->hasSensor(handle)) {
            ALOGD_IF(DEBUG_CONNECTIONS, "%i: disabling handle=0x%08x", i, handle);
            SensorInterface* sensor = mSensorMap.valueFor( handle );
            ALOGE_IF(! sensor, "mSensorMap[handle=0x%08x] is null! ", handle);
            if (sensor) {
              sensor->activate(c, false);
            }
        }
        SensorRecord* rec = mActiveSensors.valueAt(i);
        ALOGE_IF(! rec, "mActiveSensors[%d] is null (handle=0x%08x)! ", i, handle);
        ALOGD_IF(DEBUG_CONNECTIONS,
              "removing connection %p for sensor[%d].handle=0x%08x",
              c, i, handle);

        if (rec && rec->removeConnection(connection)) {
            ALOGD_IF(DEBUG_CONNECTIONS, "... and it was the last connection");
            mActiveSensors.removeItemsAt(i, 1);
            mActiveVirtualSensors.removeItem(handle);
            delete rec;
            size--;
        } else {

    i++;
}
}
mActiveConnections.remove(connection);
BatteryService::cleanup(c->getUid());
}

status_t SensorService::enable(const sp<SensorEventConnection>& connection,
int handle)
{
if (mInitCheck ! = NO_ERROR)
return mInitCheck;
Mutex::Autolock _l(mLock);

SensorInterface* sensor = mSensorMap.valueFor(handle);
SensorRecord* rec = mActiveSensors.valueFor(handle);
if (rec == 0) {
rec = new SensorRecord(connection);
mActiveSensors.add(handle, rec);
if (sensor->isVirtual()) {
    mActiveVirtualSensors.add(handle, sensor);
}
} else {
if (rec->addConnection(connection)) {
    // this sensor is already activated, but we are adding a
    // connection that uses it. Immediately send down the last
    // known value of the requested sensor if it's not a
    // "continuous" sensor
    if (sensor->getSensor().getMinDelay() == 0) {
        sensors_event_t scratch;
        sensors_event_t& event(mLastEventSeen.editValueFor(handle));
        if (event.version == sizeof(sensors_event_t)) {
            connection->sendEvents(&event, 1);
        }
    }
}
}

if (connection->addSensor(handle)) {
BatteryService::enableSensor(connection->getUid(), handle);
// the sensor was added (which means it wasn't already there)
// so, see if this connection becomes active
if (mActiveConnections.indexOf(connection) < 0) {
    mActiveConnections.add(connection);
}
} else {
ALOGW("sensor %08x already enabled in connection %p (ignoring)",
    handle, connection.get());
}

// we are setup, now enable the sensor
status_t err = sensor ? sensor->activate(connection.get(), true) : status_t(BAD_VALUE);

if (err ! = NO_ERROR) {
// enable has failed, reset state in SensorDevice
status_t resetErr = sensor ? sensor->resetStateWithoutActuatingHardware
(connection.get(), handle) : status_t(BAD_VALUE);
// enable has failed, reset our state
cleanupWithoutDisable(connection, handle);
}
return err;
}

status_t SensorService::disable(const sp<SensorEventConnection>& connection,
int handle)
{
if (mInitCheck ! = NO_ERROR)
return mInitCheck;

    status_t err = cleanupWithoutDisable(connection, handle);
    if (err == NO_ERROR) {
        SensorInterface* sensor = mSensorMap.valueFor(handle);
        err = sensor ? sensor->activate(connection.get(), false) : status_t(BAD_VALUE);
    }
    return err;
}

status_t SensorService::cleanupWithoutDisable(const sp<SensorEventConnection>& connection,
        int handle) {
    Mutex::Autolock _l(mLock);
    SensorRecord* rec = mActiveSensors.valueFor(handle);
    if (rec) {
        // see if this connection becomes inactive
        if (connection->removeSensor(handle)) {
            BatteryService::disableSensor(connection->getUid(), handle);
        }
        if (connection->hasAnySensor() == false) {
            mActiveConnections.remove(connection);
        }
        // see if this sensor becomes inactive
        if (rec->removeConnection(connection)) {
            mActiveSensors.removeItem(handle);
            mActiveVirtualSensors.removeItem(handle);
            delete rec;
        }
        return NO_ERROR;
    }
    return BAD_VALUE;
}

status_t SensorService::setEventRate(const sp<SensorEventConnection>& connection,
        int handle, nsecs_t ns)
{
    if (mInitCheck ! = NO_ERROR)
        return mInitCheck;

    SensorInterface* sensor = mSensorMap.valueFor(handle);
    if (! sensor)
        return BAD_VALUE;

    if (ns < 0)
        return BAD_VALUE;

    nsecs_t minDelayNs = sensor->getSensor().getMinDelayNs();
    if (ns < minDelayNs) {
        ns = minDelayNs;
    }

    if (ns < MINIMUM_EVENTS_PERIOD)
        ns = MINIMUM_EVENTS_PERIOD;

    return sensor->setDelay(connection.get(), handle, ns);
}

// ---------------------------------------------------------------------------

SensorService::SensorRecord::SensorRecord(
        const sp<SensorEventConnection>& connection)
{
    mConnections.add(connection);
}

bool SensorService::SensorRecord::addConnection(
        const sp<SensorEventConnection>& connection)
{
    if (mConnections.indexOf(connection) < 0) {
        mConnections.add(connection);

    return true;
}
return false;
}

bool SensorService::SensorRecord::removeConnection(
    const wp<SensorEventConnection>& connection)
{
ssize_t index = mConnections.indexOf(connection);
if (index >= 0) {
    mConnections.removeItemsAt(index, 1);
}
return mConnections.size() ? false : true;
}

// ---------------------------------------------------------------------------

SensorService::SensorEventConnection::SensorEventConnection(
    const sp<SensorService>& service, uid_t uid)
: mService(service), mChannel(new BitTube()), mUid(uid)
{
}

SensorService::SensorEventConnection::~SensorEventConnection()
{
ALOGD_IF(DEBUG_CONNECTIONS, "~SensorEventConnection(%p)", this);
mService->cleanupConnection(this);
}

void SensorService::SensorEventConnection::onFirstRef()
{
}

bool SensorService::SensorEventConnection::addSensor(int32_t handle) {
Mutex::Autolock _l(mConnectionLock);
if (mSensorInfo.indexOf(handle) < 0) {
    mSensorInfo.add(handle);
    return true;
}
return false;
}

bool SensorService::SensorEventConnection::removeSensor(int32_t handle) {
Mutex::Autolock _l(mConnectionLock);
if (mSensorInfo.remove(handle) >= 0) {
    return true;
}
return false;
}

bool SensorService::SensorEventConnection::hasSensor(int32_t handle) const {
Mutex::Autolock _l(mConnectionLock);
return mSensorInfo.indexOf(handle) >= 0;
}

bool SensorService::SensorEventConnection::hasAnySensor() const {
Mutex::Autolock _l(mConnectionLock);
return mSensorInfo.size() ? true : false;
}

status_t SensorService::SensorEventConnection::sendEvents(
    sensors_event_t const* buffer, size_t numEvents,
    sensors_event_t* scratch)
{
// filter out events not for this connection
size_t count = 0;
if (scratch) {
    Mutex::Autolock _l(mConnectionLock);
    size_t i=0;

              while (i<numEvents) {
                  const int32_t curr = buffer[i].sensor;
                  if (mSensorInfo.indexOf(curr) >= 0) {
                      do {
                        scratch[count++] = buffer[i++];
                      } while ((i<numEvents) && (buffer[i].sensor == curr));
                  } else {
                      i++;
                  }
              }
          } else {
              scratch = const_cast<sensors_event_t *>(buffer);
              count = numEvents;
          }

          // NOTE: ASensorEvent and sensors_event_t are the same type
          ssize_t size = SensorEventQueue::write(mChannel,
                  reinterpret_cast<ASensorEvent const*>(scratch), count);
          if (size == -EAGAIN) {
              // the destination doesn't accept events anymore, it's probably
              // full. For now, we just drop the events on the floor
              //ALOGW("dropping %d events on the floor", count);
              return size;
          }

          return size < 0 ? status_t(size) : status_t(NO_ERROR);
      }

      sp<BitTube> SensorService::SensorEventConnection::getSensorChannel() const
      {
          return mChannel;
      }

      status_t SensorService::SensorEventConnection::enableDisable(
              int handle, bool enabled)
      {
          status_t err;
          if (enabled) {
              err = mService->enable(this, handle);
          } else {
              err = mService->disable(this, handle);
          }
          return err;
      }

      status_t SensorService::SensorEventConnection::setEventRate(
              int handle, nsecs_t ns)
      {
          return mService->setEventRate(this, handle, ns);
      }

      // ---------------------------------------------------------------------------
      }; // namespace android

通过上述实现代码,可以了解SensorService服务的创建、启动过程,整个过程的“C/S”通信架构如图5-4所示。

▲图5-4 “C/S”通信架构图

在此需要注意,BpSensorServer并没有在系统中被用到,即使从ISensorServer.cpp中把它删除也不会对Sensor的工作有任何影响。这是因为它的工作已经被SensorManager.cpp所取代,ServiceManager会直接获取上面System_init文件中添加的SensorService对象。

5.4.4 封装HAL层的代码

在Android系统中,通过文件frameworks\native\services\sensorservice\SensorDevice.cpp封装了HAL层的代码,主要包含的功能如下所示:

· 获取sensor列表(getSensorList);

· 获取sensor事件(poll);

· Enable或Disable sensor(activate);

· 设置delay时间。

文件SensorDevice.cpp的具体实现代码如下所示。

  namespace android {
  // ---------------------------------------------------------------------------

  ANDROID_SINGLETON_STATIC_INSTANCE(SensorDevice)

  SensorDevice::SensorDevice()
      :  mSensorDevice(0),
        mSensorModule(0)
  {
      status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
            (hw_module_t const**)&mSensorModule);

      ALOGE_IF(err, "couldn't load %s module (%s)",
            SENSORS_HARDWARE_MODULE_ID, strerror(-err));

      if (mSensorModule) {
          err = sensors_open(&mSensorModule->common, &mSensorDevice);

    ALOGE_IF(err, "couldn't open device for module %s (%s)",
            SENSORS_HARDWARE_MODULE_ID, strerror(-err));

    if (mSensorDevice) {
        sensor_t const* list;
        ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
        mActivationCount.setCapacity(count);
        Info model;
        for (size_t i=0 ; i<size_t(count) ; i++) {
            mActivationCount.add(list[i].handle, model);
            mSensorDevice->activate(mSensorDevice, list[i].handle, 0);
        }
    }
}
}

void SensorDevice::dump(String8& result, char* buffer, size_t SIZE)
{
if (! mSensorModule) return;
sensor_t const* list;
ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);

snprintf(buffer, SIZE, "%d h/w sensors:\n", int(count));
result.append(buffer);

Mutex::Autolock _l(mLock);
for (size_t i=0 ; i<size_t(count) ; i++) {
    const Info& info = mActivationCount.valueFor(list[i].handle);
    snprintf(buffer, SIZE, "handle=0x%08x, active-count=%d, rates(ms)={ ",
            list[i].handle,
            info.rates.size());
    result.append(buffer);
    for (size_t j=0 ; j<info.rates.size() ; j++) {
        snprintf(buffer, SIZE, "%4.1f%s",
              info.rates.valueAt(j) / 1e6f,
              j<info.rates.size()-1 ? ", " : "");
        result.append(buffer);
    }
    snprintf(buffer, SIZE, " }, selected=%4.1f ms\n",  info.delay / 1e6f);
    result.append(buffer);
}
}

ssize_t SensorDevice::getSensorList(sensor_t const** list) {
if (! mSensorModule) return NO_INIT;
ssize_t count = mSensorModule->get_sensors_list(mSensorModule, list);
return count;
}

status_t SensorDevice::initCheck() const {
return mSensorDevice && mSensorModule ? NO_ERROR : NO_INIT;
}

ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) {
if (! mSensorDevice) return NO_INIT;
ssize_t c;
do {
    c = mSensorDevice->poll(mSensorDevice, buffer, count);
} while (c == -EINTR);
return c;
}

status_t SensorDevice::resetStateWithoutActuatingHardware(void *ident, int handle)
{
if (! mSensorDevice) return NO_INIT;
Info& info( mActivationCount.editValueFor(handle));
Mutex::Autolock _l(mLock);
info.rates.removeItem(ident);

    return NO_ERROR;
}

status_t SensorDevice::activate(void* ident, int handle, int enabled)
{
    if (! mSensorDevice) return NO_INIT;
    status_t err(NO_ERROR);
    bool actuateHardware = false;

    Info& info( mActivationCount.editValueFor(handle) );

    ALOGD_IF(DEBUG_CONNECTIONS,
            "SensorDevice::activate: ident=%p, handle=0x%08x, enabled=%d, count=%d",
            ident, handle, enabled, info.rates.size());

    if (enabled) {
        Mutex::Autolock _l(mLock);
        ALOGD_IF(DEBUG_CONNECTIONS, "... index=%ld",
              info.rates.indexOfKey(ident));

        if (info.rates.indexOfKey(ident) < 0) {
            info.rates.add(ident, DEFAULT_EVENTS_PERIOD);
            if (info.rates.size() == 1) {
              actuateHardware = true;
            }
        } else {
            // sensor was already activated for this ident
        }
    } else {
        Mutex::Autolock _l(mLock);
        ALOGD_IF(DEBUG_CONNECTIONS, "... index=%ld",
              info.rates.indexOfKey(ident));

        ssize_t idx = info.rates.removeItem(ident);
        if (idx >= 0) {
            if (info.rates.size() == 0) {
              actuateHardware = true;
            }
        } else {
            // sensor wasn't enabled for this ident
        }
    }

    if (actuateHardware) {
        ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w");

        err = mSensorDevice->activate(mSensorDevice, handle, enabled);
        ALOGE_IF(err, "Error %s sensor %d (%s)",
              enabled ? "activating" : "disabling",
              handle, strerror(-err));
    }

    { // scope for the lock
        Mutex::Autolock _l(mLock);
        nsecs_t ns = info.selectDelay();
        mSensorDevice->setDelay(mSensorDevice, handle, ns);
    }

    return err;
}

status_t SensorDevice::setDelay(void* ident, int handle, int64_t ns)
{
    if (! mSensorDevice) return NO_INIT;
    Mutex::Autolock _l(mLock);
    Info& info( mActivationCount.editValueFor(handle) );
    status_t err = info.setDelayForIdent(ident, ns);
    if (err < 0) return err;

          ns = info.selectDelay();
          return mSensorDevice->setDelay(mSensorDevice, handle, ns);
      }

      int SensorDevice::getHalDeviceVersion() const {
          if (! mSensorDevice) return -1;

          return mSensorDevice->common.version;
      }

      // ---------------------------------------------------------------------------

      status_t SensorDevice::Info::setDelayForIdent(void* ident, int64_t ns)
      {
          ssize_t index = rates.indexOfKey(ident);
          if (index < 0) {
              ALOGE("Info::setDelayForIdent(ident=%p, ns=%lld) failed (%s)",
                    ident, ns, strerror(-index));
              return BAD_INDEX;
          }
          rates.editValueAt(index) = ns;
          return NO_ERROR;
      }

      nsecs_t SensorDevice::Info::selectDelay()
      {
          nsecs_t ns = rates.valueAt(0);
          for (size_t i=1 ; i<rates.size() ; i++) {
              nsecs_t cur = rates.valueAt(i);
              if (cur < ns) {
                  ns = cur;
              }
          }
          delay = ns;
          return ns;
      }

      // ---------------------------------------------------------------------------
      }; // namespace android

这样SensorSevice会把任务交给SensorDevice,而SensorDevice会调用标准的抽象层接口。由此可见,Sensor架构的抽象层接口是最标准的一种,它很好地实现了抽象层与本地框架的分离。

5.4.5 消息队列处理

在Android的传感器系统中,文件frameworks\native\libs\gui\SensorEventQueue.cpp实现了处理消息队列的功能。此文件能够在创建其实例的时候传入SensorEventConnection的实例,SensorEventConnection继承于ISensorEventConnection。SensorEventConnection其实是客户端调用SensorService的createSensorEventConnection()方法创建的,是客户端与服务端沟通的桥梁,通过这个桥梁,可以完成如下所示的任务:

· 获取管道的句柄;

· 往管道读写数据;

· 通知服务端对Sensor可用。

文件frameworks\native\libs\gui\SensorEventQueue.cpp的具体实现代码如下所示。

      // ----------------------------------------------------------------------------
      namespace android {
      // ----------------------------------------------------------------------------

      SensorEventQueue::SensorEventQueue(const sp<ISensorEventConnection>& connection)
          : mSensorEventConnection(connection)
      {
      }

    SensorEventQueue::~SensorEventQueue()
    {
    }

    void SensorEventQueue::onFirstRef()
    {
        mSensorChannel = mSensorEventConnection->getSensorChannel();
    }

    int SensorEventQueue::getFd() const
    {
        return mSensorChannel->getFd();
    }

    ssize_t SensorEventQueue::write(const sp<BitTube>& tube,
            ASensorEvent const* events, size_t numEvents) {
        return BitTube::sendObjects(tube, events, numEvents);
    }

    ssize_t SensorEventQueue::read(ASensorEvent* events, size_t numEvents)
    {
        return BitTube::recvObjects(mSensorChannel, events, numEvents);
    }

    sp<Looper> SensorEventQueue::getLooper() const
    {
        Mutex::Autolock _l(mLock);
        if (mLooper == 0) {
            mLooper = new Looper(true);
            mLooper->addFd(getFd(), getFd(), ALOOPER_EVENT_INPUT, NULL, NULL);
        }
        return mLooper;
    }

    status_t SensorEventQueue::waitForEvent() const
    {
        const int fd = getFd();
        sp<Looper> looper(getLooper());

        int events;
        int32_t result;
        do {
            result = looper->pollOnce(-1, NULL, &events, NULL);
            if (result == ALOOPER_POLL_ERROR) {
              ALOGE("SensorEventQueue::waitForEvent error (errno=%d)", errno);
              result = -EPIPE; // unknown error, so we make up one
              break;
            }
            if (events & ALOOPER_EVENT_HANGUP) {
              // the other-side has died
              ALOGE("SensorEventQueue::waitForEvent error HANGUP");
              result = -EPIPE; // unknown error, so we make up one
              break;
            }
        } while (result ! = fd);

        return  (result == fd) ? status_t(NO_ERROR) : result;
    }

    status_t SensorEventQueue::wake() const
    {
        sp<Looper> looper(getLooper());
        looper->wake();
        return NO_ERROR;
    }

      status_t SensorEventQueue::enableSensor(Sensor const* sensor) const {
          return mSensorEventConnection->enableDisable(sensor->getHandle(), true);
      }

      status_t SensorEventQueue::disableSensor(Sensor const* sensor) const {
          return mSensorEventConnection->enableDisable(sensor->getHandle(), false);
      }

      status_t SensorEventQueue::enableSensor(int32_t handle, int32_t us) const {
          status_t err = mSensorEventConnection->enableDisable(handle, true);
          if (err == NO_ERROR) {
              mSensorEventConnection->setEventRate(handle, us2ns(us));
          }
          return err;
      }

      status_t SensorEventQueue::disableSensor(int32_t handle) const {
          return mSensorEventConnection->enableDisable(handle, false);
      }

      status_t SensorEventQueue::setEventRate(Sensor const* sensor, nsecs_t ns) const {
          return mSensorEventConnection->setEventRate(sensor->getHandle(), ns);
      }

      // ----------------------------------------------------------------------------
      }; // namespace android

由此可见,SensorManager负责控制流,通过C/S的Binder机制与SensorService实现通信。具体过程如图5-5所示。

▲图5-5 SensorManager控制流的处理流程

而SensorEventQueue负责数据流,功能是通过管道机制来读写底层的数据。具体过程如图5-6所示。

▲图5-6 SensorEventQueue数据流的处理流程

5.5 分析HAL层

在Android系统中,在HAL层中提供了Android独立于具体硬件的抽象接口。其中HAL层的头文件路径如下。

      hardware/libhardware/include/hardware/sensors.h

而具体实现文件需要开发者个人编写,具体可以参考下面内容。

      hardware\invensense\libsensors_iio\sensors_mpl.cpp

文件sensors.h的主要实现代码如下所示。

      typedef struct {
          union {
              float v[3];
              struct {
                float x;
                float y;
                float z;
              };
              struct {
                float azimuth;
                float pitch;
                float roll;
              };
          };
          int8_t status;
          uint8_t reserved[3];
      } sensors_vec_t;

      /**
       * uncalibrated gyroscope and magnetometer event data
       */
      typedef struct {
        union {
          float uncalib[3];
          struct {
            float x_uncalib;
            float y_uncalib;
            float z_uncalib;
          };
        };
        union {
          float bias[3];
          struct {
            float x_bias;
            float y_bias;
            float z_bias;
          };
        };
      } uncalibrated_event_t;

      /**
       * Union of the various types of sensor data
       * that can be returned.
       */
      typedef struct sensors_event_t {
          /* must be sizeof(struct sensors_event_t) */
          int32_t version;

          /* sensor identifier */
          int32_t sensor;

          /* sensor type */
          int32_t type;

    /* reserved */
    int32_t reserved0;

    /* time is in nanosecond */
    int64_t timestamp;

    union {
        float data[16];

        /* acceleration values are in meter per second per second (m/s^2) */
        sensors_vec_t acceleration;

        /* magnetic vector values are in micro-Tesla (uT) */
        sensors_vec_t magnetic;

        /* orientation values are in degrees */
        sensors_vec_t orientation;

        /* gyroscope values are in rad/s */
        sensors_vec_t gyro;

        /* temperature is in degrees centigrade (Celsius) */
        float temperature;

        /* distance in centimeters */
        float distance;

        /* light in SI lux units */
        float light;

        /* pressure in hectopascal (hPa) */
        float pressure;

        /* relative humidity in percent */
        float relative_humidity;

        /* step-counter */
        uint64_t step_counter;

        /* uncalibrated gyroscope values are in rad/s */
        uncalibrated_event_t uncalibrated_gyro;

        /* uncalibrated magnetometer values are in micro-Teslas */
        uncalibrated_event_t uncalibrated_magnetic;
    };
    uint32_t reserved1[4];
} sensors_event_t;

struct sensor_t;
struct sensors_module_t {
    struct hw_module_t common;
    int (*get_sensors_list)(struct sensors_module_t* module,
            struct sensor_t const** list);
};

struct sensor_t {

    /* Name of this sensor.
     * All sensors of the same "type" must have a different "name".
     */
    const char* name;

    /* vendor of the hardware part */
    const char* vendor;
    int version;
    int handle;

    /* this sensor's type */

    int type;

    /* maximum range of this sensor's value in SI units */
    float maxRange;

    /* smallest difference between two values reported by this sensor */
    float resolution;

    /* rough estimate of this sensor's power consumption in mA */
    float power;

    int32_t minDelay;
    /* reserved fields, must be zero */
    void* reserved[8];
};

struct sensors_poll_device_t {
    struct hw_device_t common;
    int (*activate)(struct sensors_poll_device_t *dev,
            int handle, int enabled);
    int (*setDelay)(struct sensors_poll_device_t *dev,
            int handle, int64_t ns);
    int (*poll)(struct sensors_poll_device_t *dev,
            sensors_event_t* data, int count);
};
typedef struct sensors_poll_device_1 {
    union {
        struct sensors_poll_device_t v0;

        struct {
            struct hw_device_t common;
            int (*activate)(struct sensors_poll_device_t *dev,
                  int handle, int enabled);

            int (*setDelay)(struct sensors_poll_device_t *dev,
                  int handle, int64_t period_ns);

            int (*poll)(struct sensors_poll_device_t *dev,
                  sensors_event_t* data, int count);
        };
    };
    int (*batch)(struct sensors_poll_device_1* dev,
            int handle, int flags, int64_t period_ns, int64_t timeout);

    void (*reserved_procs[8])(void);

} sensors_poll_device_1_t;


/** convenience API for opening and closing a device */

static inline int sensors_open(const struct hw_module_t* module,
        struct sensors_poll_device_t** device) {
    return module->methods->open(module,
            SENSORS_HARDWARE_POLL, (struct hw_device_t**)device);
}

static inline int sensors_close(struct sensors_poll_device_t* device) {
    return device->common.close(&device->common);
}

static inline int sensors_open_1(const struct hw_module_t* module,
        sensors_poll_device_1_t** device) {
    return module->methods->open(module,
            SENSORS_HARDWARE_POLL, (struct hw_device_t**)device);
}

static inline int sensors_close_1(sensors_poll_device_1_t* device) {

          return device->common.close(&device->common);
      }

      __END_DECLS
      #endif  // ANDROID_SENSORS_INTERFACE_H

而具体的实现文件是Linux Kernel层,也就是具体的硬件设备驱动程序,例如可以将其命名为“sensors.c”,然后编写如下定义struct sensors_poll_device_t的代码。

      struct sensors_poll_device_t {
          struct hw_device_t common;

          // Activate/deactivate one sensor
          int (*activate)(struct sensors_poll_device_t *dev,
                int handle, int enabled);

          // Set the delay between sensor events in nanoseconds for a given sensor
          int (*setDelay)(struct sensors_poll_device_t *dev,
                int handle, int64_t ns);

          // Returns an array of sensor data
          int (*poll)(struct sensors_poll_device_t *dev,
                sensors_event_t* data, int count);
      };

也可以编写如下定义struct sensors_module_t的代码。

      struct sensors_module_t {
          struct hw_module_t common;

          /**
          * Enumerate all available sensors. The list is returned in "list".
          * @return number of sensors in the list
          */
          int (*get_sensors_list)(struct sensors_module_t* module,
                struct sensor_t const** list);
      };

也可以编写如下定义struct sensor_t的代码。

      struct sensor_t {
          /* name of this sensors */
          const char*name;
          /* vendor of the hardware part */
          const char*vendor;
          /* version of the hardware part + driver. The value of this field
          * must increase when the driver is updated in a way that changes the
          * output of this sensor. This is important for fused sensors when the
          * fusion algorithm is updated.
          */
          int version;
          /* handle that identifies this sensors. This handle is used to activate
          * and deactivate this sensor. The value of the handle must be 8 bits
          * in this version of the API.
          */
          int handle;
          /* this sensor's type. */
          int type;
          /* maximaum range of this sensor's value in SI units */
          float maxRange;
          /* smallest difference between two values reported by this sensor */
          float resolution;
          /* rough estimate of this sensor's power consumption in mA */
          float power;
          /* minimum delay allowed between events in microseconds. A value of zero
          * means that this sensor doesn't report events at a constant rate, but
          * rather only when a new data is available */
          int32_t minDelay;
          /* reserved fields, must be zero */

      void*reserved[8];
  };

也可以编写如下代码定义struct sensors_event_t。

  typedef struct {
      union {
          float v[3];
          struct {
            float x;
            float y;
            float z;
          };
          struct {
            float azimuth;
            float pitch;
            float roll;
          };
      };
      int8_t status;
      uint8_t reserved[3];
  } sensors_vec_t;

  /**
   * Union of the various types of sensor data
   * that can be returned.
   */
  typedef struct sensors_event_t {
      /* must be sizeof(struct sensors_event_t) */
      int32_t version;

      /* sensor identifier */
      int32_t sensor;

      /* sensor type */
      int32_t type;

      /* reserved */
      int32_t reserved0;

      /* time is in nanosecond */
      int64_t timestamp;

      union {
          float data[16];

          /* acceleration values are in meter per second per second (m/s^2) */
          sensors_vec_t acceleration;

          /* magnetic vector values are in micro-Tesla (uT) */
          sensors_vec_t magnetic;

          /* orientation values are in degrees */
          sensors_vec_t orientation;

          /* gyroscope values are in rad/s */
          sensors_vec_t gyro;

          /* temperature is in degrees centigrade (Celsius) */
          float temperature;

          /* distance in centimeters */
          float distance;

          /* light in SI lux units */
          float light;

          /* pressure in hectopascal (hPa) */
          float pressure;

          /* relative humidity in percent */
          float relative_humidity;
      };
      uint32_t reserved1[4];
  } sensors_event_t;

也可以编写如下代码定义struct sensors_module_t。

  static const struct sensor_t sSensorList[] = {
          { "MMA8452Q 3-axis Accelerometer",
                "Freescale Semiconductor",
                1, SENSORS_HANDLE_BASE+ID_A,
                SENSOR_TYPE_ACCELEROMETER, 4.0f*9.81f, (4.0f*9.81f)/256.0f, 0.2f, 0, { } },
          { "AK8975 3-axis Magnetic field sensor",
                "Asahi Kasei",
                1, SENSORS_HANDLE_BASE+ID_M,
                SENSOR_TYPE_MAGNETIC_FIELD, 2000.0f, 1.0f/16.0f, 6.8f, 0, { } },
          { "AK8975 Orientation sensor",
                "Asahi Kasei",
                1, SENSORS_HANDLE_BASE+ID_O,
                SENSOR_TYPE_ORIENTATION, 360.0f, 1.0f, 7.0f, 0, { } },

      { "ST 3-axis Gyroscope sensor",
          "STMicroelectronics",
          1, SENSORS_HANDLE_BASE+ID_GY,
          SENSOR_TYPE_GYROSCOPE, RANGE_GYRO, CONVERT_GYRO, 6.1f, 1190, { } },

      { "AL3006Proximity sensor",
          "Dyna Image Corporation",
          1, SENSORS_HANDLE_BASE+ID_P,
          SENSOR_TYPE_PROXIMITY,
          PROXIMITY_THRESHOLD_CM, PROXIMITY_THRESHOLD_CM,
          0.5f, 0, { } },

          { "AL3006 light sensor",
                "Dyna Image Corporation",
                1, SENSORS_HANDLE_BASE+ID_L,
                SENSOR_TYPE_LIGHT, 10240.0f, 1.0f, 0.5f, 0, { } },
  };

  static int open_sensors(const struct hw_module_t* module, const char* name,
          struct hw_device_t** device);

  static int sensors__get_sensors_list(struct sensors_module_t* module,
          struct sensor_t const** list)
  {
      *list = sSensorList;
      return ARRAY_SIZE(sSensorList);
  }

  static struct hw_module_methods_t sensors_module_methods = {
      .open = open_sensors
  };

  const struct sensors_module_t HAL_MODULE_INFO_SYM = {
      .common = {
          .tag = HARDWARE_MODULE_TAG,
          .version_major = 1,
          .version_minor = 0,
          .id = SENSORS_HARDWARE_MODULE_ID,
          .name = "MMA8451Q & AK8973A & gyro Sensors Module",
          .author = "The Android Project",
          .methods = &sensors_module_methods,
      },
      .get_sensors_list = sensors__get_sensors_list
  };

  static int open_sensors(const struct hw_module_t* module, const char* name,
          struct hw_device_t** device)

      {
          return init_nusensors(module, device); //待后面讲解
      }

到此为止,整个Android系统中传感器模块的源码分析完毕。由此可见,整个传感器系统的总体调用关系如图5-7所示。

▲图5-7 传感器系统的总体调用关系

客户端读取数据时的调用时序如图5-8所示。

▲图5-8 客户端读取数据时的调用时序图

服务器端的调用时序如图5-9所示。

▲图5-9 服务器端的调用时序图