官术网_书友最值得收藏!

第5章 Android傳感器系統(tǒng)分析

傳感器是近年來隨著物聯(lián)網(wǎng)這一概念的流行而推出的,現(xiàn)在人們已經(jīng)逐漸認(rèn)識了傳感器這一概念。其實傳感器在大家日常的生活中經(jīng)常見到甚至是用到,例如樓宇的聲控樓梯燈和馬路上的路燈等。在本章的內(nèi)容中,將詳細(xì)講解Android系統(tǒng)中傳感器系統(tǒng)的基本知識,為讀者步入本書后面知識的學(xué)習(xí)打下基礎(chǔ)。

5.1 Android傳感器系統(tǒng)概述

在Android系統(tǒng)中提供的主要傳感器有加速度、磁場、方向、陀螺儀、光線、壓力、溫度和接近傳感器等。傳感器系統(tǒng)會主動對上層報告?zhèn)鞲衅骶群蛿?shù)據(jù)的變化,并且提供了設(shè)置傳感器精度的接口,這些接口可以在Java應(yīng)用和Java框架中使用。

Android傳感器系統(tǒng)的基本層次結(jié)構(gòu)如圖5-1所示。

▲圖5-1 傳感器系統(tǒng)的層次結(jié)構(gòu)

根據(jù)圖5-1所示的結(jié)構(gòu),Android傳感器系統(tǒng)從上到下分別是Java應(yīng)用層、Java框架對傳感器的應(yīng)用、傳感器類、傳感器硬件抽象層和傳感器驅(qū)動。各個層的具體說明如下所示。

(1)傳感器系統(tǒng)的Java部分

代碼路徑是:

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

此部分對應(yīng)的實現(xiàn)文件是Sensor*.java。

(2)傳感器系統(tǒng)的JNI部分

代碼路徑是:

      frameworks/base/core/jni/android_hardware_SensorManager.cpp

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

(3)傳感器系統(tǒng)HAL層

頭文件路徑是:

      hardware/libhardware/include/hardware/sensors.h

在Android系統(tǒng)中,傳感器系統(tǒng)的硬件抽象層需要特定編碼實現(xiàn)。

(4)驅(qū)動層

驅(qū)動層的代碼路徑是:

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

在庫sensor.so中提供了如下所示的8個API函數(shù)。

· 控制方面:在結(jié)構(gòu)體sensors_control_device_t中定義,包括下面所示的函數(shù)。

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)。

·數(shù)據(jù)方面:在結(jié)構(gòu)體sensors_data_device_t中定義,包括下面所示的函數(shù)。

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)。

· 模塊方面:在結(jié)構(gòu)體sensors_module_t中定義,包括下面一個函數(shù)。

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

在Android系統(tǒng)的Java層中,Sensor的狀態(tài)是由SensorService來負(fù)責(zé)控制的,其Java代碼和JNI代碼分別位于如下文件中。

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

SensorManager負(fù)責(zé)在Java層Sensor的數(shù)據(jù)控制,它的Java代碼和JNI代碼分別位于如下文件中。

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

在Android的Framework中,是通過文件sensorService.java和sensorManager.java實現(xiàn)與Sensor傳感器通信的。文件sensorService.java的通信功能是通過JNI調(diào)用sensorService.cpp中的方法實現(xiàn)的。

文件sensorManager.java的具體通信功能是通過JNI調(diào)用sensorManager.cpp中的方法實現(xiàn)的。文件sensorService.cpp和sensorManager.cpp通過文件hardware.c與sensor.so通信。其中文件sensorService.cpp實現(xiàn)對sensor的狀態(tài)控制,文件sensorManger.cpp實現(xiàn)對sensor的數(shù)據(jù)控制。

庫sensor.so通過ioctl控制sensor driver的狀態(tài),通過打開sensor driver對應(yīng)的設(shè)備文件讀取G-sensor采集的數(shù)據(jù)。

5.2 分析Java層

在Android系統(tǒng)中,傳感器系統(tǒng)的Java部分的實現(xiàn)文件是:

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

通過閱讀文件SensorActivity.java的源碼可知,在應(yīng)用程序中使用傳感器需要用到hardware包中的SensorManager、SensorListener等相關(guān)的類,具體實現(xiàn)代碼如下所示。

      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;
          /** 第一次創(chuàng)建activity是調(diào)用. */
          @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綁定后套服務(wù)
              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());
}

/**
*相關(guān)的復(fù)選框選中狀態(tài)變化處理。當(dāng)復(fù)選框被選中時會注冊傳感器變化。
*如果不加以控制會取消傳感器的變化
*/
@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());
}
}
}

/**實現(xiàn)回調(diào)處理程序*/
@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");
    //如果值已經(jīng)修改則更新 "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) {
    //如果值已經(jīng)修改則更新 "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層利用了大家熟悉的觀察者模式對傳感器的數(shù)據(jù)進(jìn)行了監(jiān)聽處理。

5.3 分析Frameworks層

在Android系統(tǒng)中,傳感器系統(tǒng)的Frameworks層的代碼路徑是:

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

Frameworks層是Android系統(tǒng)提供的應(yīng)用程序開發(fā)接口和應(yīng)用程序框架。應(yīng)用程序的調(diào)用是通過類實例化或類繼承進(jìn)行的。對應(yīng)用程序來說,最重要的就是把SensorListener注冊到SensorManager上,從而才能以觀察者身份接收到數(shù)據(jù)的變化,因此,要把目光落在SensorManager的構(gòu)造函數(shù)、RegisterListener函數(shù)和通知機(jī)制相關(guān)的代碼上。

本節(jié)將詳細(xì)講解傳感器系統(tǒng)的Frameworks層的具體實現(xiàn)流程。

5.3.1 監(jiān)聽傳感器的變化

在Android傳感器系統(tǒng)的Frameworks層中,文件SensorListener.java用于監(jiān)聽從Java應(yīng)用層中傳遞過來的變化。文件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 注冊監(jiān)聽

當(dāng)文件SensorListener.java監(jiān)聽到變化之后,會通過文件SensorManager.java來向服務(wù)注冊監(jiān)聽變化,并調(diào)度Sensor的具體任務(wù)。例如在開發(fā)Android傳感器應(yīng)用程序時,在上層的通用開發(fā)流程如下所示。

(1)通過“getSystemService(SENSOR_SERVICE); ”語句得到傳感器服務(wù)。這樣得到一個用來管理分配調(diào)度處理Sensor工作的SensorManager。SensorManager并不服務(wù)而是運行于后臺,真正屬于Sensor的系統(tǒng)服務(wù)是SensorService,在終端下的“#service list”中可以看到sensorservice:[android.gui.SensorServer]。

(2)通過“getDefaultSensor(Sensor.TYPE_GRAVITY); ”得到傳感器類型,當(dāng)然還有各種功能不同的傳感器,具體可以查閱Android官網(wǎng)API或者源碼Sensor.java。

(3)注冊監(jiān)聽器SensorEventListener。在應(yīng)用程序中打開一個監(jiān)聽接口,專門用于處理傳感器的數(shù)據(jù)。

(4)通過回調(diào)函數(shù)onSensorChanged和onAccuracyChanged實現(xiàn)實時監(jiān)聽。例如對重力感應(yīng)器的xyz值經(jīng)過算法變換得到左右上下前后方向等,就由這個回調(diào)函數(shù)實現(xiàn)。

綜上所述,傳感器頂層的處理流程如圖5-2所示。

▲圖5-2 傳感器頂層的處理流程

文件SensorManager.java的具體實現(xiàn)流程如下所示。

(1)定義類SensorManager,然后設(shè)置各種傳感器的初始變量值,具體代碼如下所示。

      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;
          /**(默認(rèn)值)適合屏幕方向的變化*/
          public static final int SENSOR_DELAY_NORMAL = 3;

          /**
           *返回的值,該傳感器是不可信的,需要進(jìn)行校準(zhǔn)或環(huán)境不允許讀數(shù)
           */
          public static final int SENSOR_STATUS_UNRELIABLE = 0;
          /**
           *該傳感器是報告的低精度的數(shù)據(jù),與環(huán)境的校準(zhǔn)是必要的
           */
          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)定義各種設(shè)備類型方法和設(shè)備數(shù)據(jù)的方法,這些方法非常重要,在編寫的應(yīng)用程序中,可以通過AIDL接口遠(yuǎn)程調(diào)用(RPC)的方式得到SensorManager。這樣通過在類SensorManager中的方法,可以得到底層的各種傳感器數(shù)據(jù)。上述方法的具體實現(xiàn)代碼如下所示。

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

上述方法的功能非常重要,其實就是人們在開發(fā)傳感器應(yīng)用程序時用到的API接口。有關(guān)上述方法的具體說明,讀者可以查閱官網(wǎng)SDK API中對于類android.hardware.SensorManager的具體說明。

5.4 分析JNI層

在Android系統(tǒng)中,傳感器系統(tǒng)的JNI部分的代碼路徑是:

      frameworks/base/core/jni/android_hardware_SensorManager.cpp

在此文件中提供了對類android.hardware.Sensor.Manage的本地支持。上層和JNI層的調(diào)用關(guān)系如圖5-3所示。

▲圖5-3 上層和JNI層的調(diào)用關(guān)系

在上圖所示的調(diào)用關(guān)系中涉及了下面所示的API接口方法。

· nativeClassInit():在JNI層得到android.hardware.Sensor的JNI環(huán)境指針;

· sensors_module_init():通過JNI調(diào)用本地框架,得到SensorService和SensorService初始化控制流各功能;

· new Sensor():建立一個Sensor對象,具體可查閱官網(wǎng)API android.hardware.Sensor;

· sensors_module_get_next_sensor():上層得到設(shè)備支持的所有Sensor,并放入SensorList鏈表;

· new SensorThread():創(chuàng)建Sensor線程,當(dāng)應(yīng)用程序registerListener()注冊監(jiān)聽器的時候開啟線程run(),注意當(dāng)沒有數(shù)據(jù)變化時線程會阻塞。

5.4.1 分析android_hardware_SensorManager.cpp

文件android_hardware_SensorManager.cpp的功能是實現(xiàn)文件SensorManager.java中的native(本地)函數(shù),主要是通過調(diào)用文件SensorManager.cpp和文件SensorEventQueue.cpp中的相關(guān)類來完成相關(guān)的工作的。文件android_hardware_SensorManager.cpp的具體實現(xiàn)代碼如下所示。

        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 處理客戶端數(shù)據(jù)

文件frameworks\native\libs\gui\SensorManager.cpp功能是提供了對傳感器數(shù)據(jù)的部分操作,實現(xiàn)了“sensor_data_XXX()”格式的函數(shù)。另外在Native層的客戶端,文件SensorManager.cpp還負(fù)責(zé)與服務(wù)端SensorService.cpp之間的通信工作。文件SensorManager.cpp的具體實現(xiàn)代碼如下所示。

      // ----------------------------------------------------------------------------
      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 處理服務(wù)端數(shù)據(jù)

文件frameworks\native\services\sensorservice\SensorService.cpp功能是實現(xiàn)了Sensor真正的后臺服務(wù),是服務(wù)端的數(shù)據(jù)處理中心。在Android的傳感器系統(tǒng)中,SensorService作為一個輕量級的System Service,運行于SystemServer內(nèi),即在system_init<system_init.cpp>中調(diào)用了SensorService::instantiate()。SensorService主要功能如下所示。

(1)通過SensorService::instantiate創(chuàng)建實例對象,并增加到ServiceManager中,然后創(chuàng)建并啟動線程,并執(zhí)行threadLoop;

(2)threadLoop從sensor驅(qū)動獲取原始數(shù)據(jù),然后通過SensorEventConnection把事件發(fā)送給客戶端;

(3)BnSensorServer的成員函數(shù)負(fù)責(zé)讓客戶端獲取sensor列表和創(chuàng)建SensorEventConnection。

文件SensorService.cpp的具體實現(xiàn)代碼如下所示。

      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

通過上述實現(xiàn)代碼,可以了解SensorService服務(wù)的創(chuàng)建、啟動過程,整個過程的“C/S”通信架構(gòu)如圖5-4所示。

▲圖5-4 “C/S”通信架構(gòu)圖

在此需要注意,BpSensorServer并沒有在系統(tǒng)中被用到,即使從ISensorServer.cpp中把它刪除也不會對Sensor的工作有任何影響。這是因為它的工作已經(jīng)被SensorManager.cpp所取代,ServiceManager會直接獲取上面System_init文件中添加的SensorService對象。

5.4.4 封裝HAL層的代碼

在Android系統(tǒng)中,通過文件frameworks\native\services\sensorservice\SensorDevice.cpp封裝了HAL層的代碼,主要包含的功能如下所示:

· 獲取sensor列表(getSensorList);

· 獲取sensor事件(poll);

· Enable或Disable sensor(activate);

· 設(shè)置delay時間。

文件SensorDevice.cpp的具體實現(xiàn)代碼如下所示。

  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會把任務(wù)交給SensorDevice,而SensorDevice會調(diào)用標(biāo)準(zhǔn)的抽象層接口。由此可見,Sensor架構(gòu)的抽象層接口是最標(biāo)準(zhǔn)的一種,它很好地實現(xiàn)了抽象層與本地框架的分離。

5.4.5 消息隊列處理

在Android的傳感器系統(tǒng)中,文件frameworks\native\libs\gui\SensorEventQueue.cpp實現(xiàn)了處理消息隊列的功能。此文件能夠在創(chuàng)建其實例的時候傳入SensorEventConnection的實例,SensorEventConnection繼承于ISensorEventConnection。SensorEventConnection其實是客戶端調(diào)用SensorService的createSensorEventConnection()方法創(chuàng)建的,是客戶端與服務(wù)端溝通的橋梁,通過這個橋梁,可以完成如下所示的任務(wù):

· 獲取管道的句柄;

· 往管道讀寫數(shù)據(jù);

· 通知服務(wù)端對Sensor可用。

文件frameworks\native\libs\gui\SensorEventQueue.cpp的具體實現(xiàn)代碼如下所示。

      // ----------------------------------------------------------------------------
      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負(fù)責(zé)控制流,通過C/S的Binder機(jī)制與SensorService實現(xiàn)通信。具體過程如圖5-5所示。

▲圖5-5 SensorManager控制流的處理流程

而SensorEventQueue負(fù)責(zé)數(shù)據(jù)流,功能是通過管道機(jī)制來讀寫底層的數(shù)據(jù)。具體過程如圖5-6所示。

▲圖5-6 SensorEventQueue數(shù)據(jù)流的處理流程

5.5 分析HAL層

在Android系統(tǒng)中,在HAL層中提供了Android獨立于具體硬件的抽象接口。其中HAL層的頭文件路徑如下。

      hardware/libhardware/include/hardware/sensors.h

而具體實現(xiàn)文件需要開發(fā)者個人編寫,具體可以參考下面內(nèi)容。

      hardware\invensense\libsensors_iio\sensors_mpl.cpp

文件sensors.h的主要實現(xiàn)代碼如下所示。

      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

而具體的實現(xiàn)文件是Linux Kernel層,也就是具體的硬件設(shè)備驅(qū)動程序,例如可以將其命名為“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系統(tǒng)中傳感器模塊的源碼分析完畢。由此可見,整個傳感器系統(tǒng)的總體調(diào)用關(guān)系如圖5-7所示。

▲圖5-7 傳感器系統(tǒng)的總體調(diào)用關(guān)系

客戶端讀取數(shù)據(jù)時的調(diào)用時序如圖5-8所示。

▲圖5-8 客戶端讀取數(shù)據(jù)時的調(diào)用時序圖

服務(wù)器端的調(diào)用時序如圖5-9所示。

▲圖5-9 服務(wù)器端的調(diào)用時序圖

主站蜘蛛池模板: 玛沁县| 泾源县| 铜梁县| 娱乐| 江华| 康马县| 东乡族自治县| 安溪县| 长沙市| 闻喜县| 石楼县| 平谷区| 临沧市| 乐昌市| 濮阳县| 永和县| 旬阳县| 资兴市| 东乌珠穆沁旗| 江山市| 葫芦岛市| 花莲市| 金华市| 莎车县| 新乡市| 红河县| 竹北市| 临猗县| 武夷山市| 华阴市| 遂昌县| 凤阳县| 冕宁县| 当雄县| 怀来县| 桐柏县| 华容县| 天等县| 门头沟区| 郴州市| 弥渡县|