第5章 Android传感器系统分析
传感器是近年来随着物联网这一概念的流行而推出的,现在人们已经逐渐认识了传感器这一概念。其实传感器在大家日常的生活中经常见到甚至是用到,例如楼宇的声控楼梯灯和马路上的路灯等。在本章的内容中,将详细讲解Android系统中传感器系统的基本知识,为读者步入本书后面知识的学习打下基础。
5.1 Android传感器系统概述
在Android系统中提供的主要传感器有加速度、磁场、方向、陀螺仪、光线、压力、温度和接近传感器等。传感器系统会主动对上层报告传感器精度和数据的变化,并且提供了设置传感器精度的接口,这些接口可以在Java应用和Java框架中使用。
Android传感器系统的基本层次结构如图5-1所示。
▲图5-1 传感器系统的层次结构
根据图5-1所示的结构,Android传感器系统从上到下分别是Java应用层、Java框架对传感器的应用、传感器类、传感器硬件抽象层和传感器驱动。各个层的具体说明如下所示。
(1)传感器系统的Java部分
代码路径是:
frameworks/base/include/core/java/android/hardware
此部分对应的实现文件是Sensor*.java。
(2)传感器系统的JNI部分
代码路径是:
frameworks/base/core/jni/android_hardware_SensorManager.cpp
在此部分中提供了对类android.hardware.Sensor.Manage的本地支持。
(3)传感器系统HAL层
头文件路径是:
hardware/libhardware/include/hardware/sensors.h
在Android系统中,传感器系统的硬件抽象层需要特定编码实现。
(4)驱动层
驱动层的代码路径是:
kernel/driver/hwmon/$(PROJECT)/sensor
在库sensor.so中提供了如下所示的8个API函数。
· 控制方面:在结构体sensors_control_device_t中定义,包括下面所示的函数。
int (*open_data_source)(struct sensors_control_device_t *dev);
int (*activate)(struct sensors_control_device_t *dev, int handle, int enabled);
int (*set_delay)(struct sensors_control_device_t *dev, int32_t ms);
int (*wake)(struct sensors_control_device_t *dev)。
·数据方面:在结构体sensors_data_device_t中定义,包括下面所示的函数。
int (*data_open)(struct sensors_data_device_t *dev, int fd);
int (*data_close)(struct sensors_data_device_t *dev);
int (*poll)(struct sensors_data_device_t *dev, sensors_data_t* data)。
· 模块方面:在结构体sensors_module_t中定义,包括下面一个函数。
int (*get_sensors_list)(struct sensors_module_t* module, struct sensor_t const** list)
在Android系统的Java层中,Sensor的状态是由SensorService来负责控制的,其Java代码和JNI代码分别位于如下文件中。
frameworks/base/services/java/com/android/server/SensorService.java frameworks/base/services/jni/com_android_server_SensorService.cpp
SensorManager负责在Java层Sensor的数据控制,它的Java代码和JNI代码分别位于如下文件中。
frameworks/base/core/java/android/hardware/SensorManager.java frameworks/base/core/jni/android_hardware_SensorManager.cpp
在Android的Framework中,是通过文件sensorService.java和sensorManager.java实现与Sensor传感器通信的。文件sensorService.java的通信功能是通过JNI调用sensorService.cpp中的方法实现的。
文件sensorManager.java的具体通信功能是通过JNI调用sensorManager.cpp中的方法实现的。文件sensorService.cpp和sensorManager.cpp通过文件hardware.c与sensor.so通信。其中文件sensorService.cpp实现对sensor的状态控制,文件sensorManger.cpp实现对sensor的数据控制。
库sensor.so通过ioctl控制sensor driver的状态,通过打开sensor driver对应的设备文件读取G-sensor采集的数据。
5.2 分析Java层
在Android系统中,传感器系统的Java部分的实现文件是:
\sdk\apps\SdkController\src\com\android\tools\sdkcontroller\activities\SensorActivit y.java
通过阅读文件SensorActivity.java的源码可知,在应用程序中使用传感器需要用到hardware包中的SensorManager、SensorListener等相关的类,具体实现代码如下所示。
public class SensorActivity extends BaseBindingActivity implements android.os.Handler.Callback { @SuppressWarnings("hiding") public static String TAG = SensorActivity.class.getSimpleName(); private static boolean DEBUG = true; private static final int MSG_UPDATE_ACTUAL_HZ = 0x31415; private TableLayout mTableLayout; private TextView mTextError; private TextView mTextStatus; private TextView mTextTargetHz; private TextView mTextActualHz; private SensorChannel mSensorHandler; private final Map<MonitoredSensor, DisplayInfo> mDisplayedSensors = new HashMap<SensorChannel.MonitoredSensor, SensorActivity.DisplayInfo>(); private final android.os.Handler mUiHandler = new android.os.Handler(this); private int mTargetSampleRate; private long mLastActualUpdateMs; /** 第一次创建activity是调用. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.sensors); mTableLayout = (TableLayout) findViewById(R.id.tableLayout); mTextError = (TextView) findViewById(R.id.textError); mTextStatus = (TextView) findViewById(R.id.textStatus); mTextTargetHz = (TextView) findViewById(R.id.textSampleRate); mTextActualHz = (TextView) findViewById(R.id.textActualRate); updateStatus("Waiting for connection"); mTextTargetHz.setOnKeyListener(new OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { updateSampleRate(); return false; } }); mTextTargetHz.setOnFocusChangeListener(new OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { updateSampleRate(); } }); } @Override protected void onResume() { if (DEBUG) Log.d(TAG, "onResume"); // BaseBindingActivity绑定后套服务 super.onResume(); updateError(); } @Override protected void onPause() { if (DEBUG) Log.d(TAG, "onPause"); // BaseBindingActivity.onResume will unbind from (but not stop) the service super.onPause(); } @Override protected void onDestroy() { if (DEBUG) Log.d(TAG, "onDestroy"); super.onDestroy(); removeSensorUi(); } // ---------- @Override protected void onServiceConnected() { if (DEBUG) Log.d(TAG, "onServiceConnected"); createSensorUi(); } @Override protected void onServiceDisconnected() { if (DEBUG) Log.d(TAG, "onServiceDisconnected"); removeSensorUi(); } @Override protected ControllerListener createControllerListener() { return new SensorsControllerListener(); } // ---------- private class SensorsControllerListener implements ControllerListener { @Override public void onErrorChanged() { runOnUiThread(new Runnable() { @Override public void run() { updateError(); } }); } @Override public void onStatusChanged() { runOnUiThread(new Runnable() { @Override public void run() { ControllerBinder binder = getServiceBinder(); if (binder ! = null) { boolean connected = binder.isEmuConnected(); mTableLayout.setEnabled(connected); updateStatus(connected ? "Emulated connected" : "Emulator disconnected"); } } }); } } private void createSensorUi() { final LayoutInflater inflater = getLayoutInflater(); if (! mDisplayedSensors.isEmpty()) { removeSensorUi(); } mSensorHandler = (SensorChannel) getServiceBinder().getChannel(Channel.SENSOR_ CHANNEL); if (mSensorHandler ! = null) { mSensorHandler.addUiHandler(mUiHandler); mUiHandler.sendEmptyMessage(MSG_UPDATE_ACTUAL_HZ); assert mDisplayedSensors.isEmpty(); List<MonitoredSensor> sensors = mSensorHandler.getSensors(); for (MonitoredSensor sensor : sensors) { final TableRow row = (TableRow) inflater.inflate(R.layout.sensor_row, mTableLayout, false); mTableLayout.addView(row); mDisplayedSensors.put(sensor, new DisplayInfo(sensor, row)); } } } private void removeSensorUi() { if (mSensorHandler ! = null) { mSensorHandler.removeUiHandler(mUiHandler); mSensorHandler = null; } mTableLayout.removeAllViews(); for (DisplayInfo info : mDisplayedSensors.values()) { info.release(); } mDisplayedSensors.clear(); } private class DisplayInfo implements CompoundButton.OnCheckedChangeListener { private MonitoredSensor mSensor; private CheckBox mChk; private TextView mVal; public DisplayInfo(MonitoredSensor sensor, TableRow row) { mSensor = sensor; // Initialize displayed checkbox for this sensor, and register // checked state listener for it mChk = (CheckBox) row.findViewById(R.id.row_checkbox); mChk.setText(sensor.getUiName()); mChk.setEnabled(sensor.isEnabledByEmulator()); mChk.setChecked(sensor.isEnabledByUser()); mChk.setOnCheckedChangeListener(this); //初始化显示该传感器的文本框 mVal = (TextView) row.findViewById(R.id.row_textview); mVal.setText(sensor.getValue()); } /** *相关的复选框选中状态变化处理。当复选框被选中时会注册传感器变化。 *如果不加以控制会取消传感器的变化 */ @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (mSensor ! = null) { mSensor.onCheckedChanged(isChecked); } } public void release() { mChk = null; mVal = null; mSensor = null; } public void updateState() { if (mChk ! = null && mSensor ! = null) { mChk.setEnabled(mSensor.isEnabledByEmulator()); mChk.setChecked(mSensor.isEnabledByUser()); } } public void updateValue() { if (mVal ! = null && mSensor ! = null) { mVal.setText(mSensor.getValue()); } } } /**实现回调处理程序*/ @Override public boolean handleMessage(Message msg) { DisplayInfo info = null; switch (msg.what) { case SensorChannel.SENSOR_STATE_CHANGED: info = mDisplayedSensors.get(msg.obj); if (info ! = null) { info.updateState(); } break; case SensorChannel.SENSOR_DISPLAY_MODIFIED: info = mDisplayedSensors.get(msg.obj); if (info ! = null) { info.updateValue(); } if (mSensorHandler ! = null) { updateStatus(Integer.toString(mSensorHandler.getMsgSentCount())+"events sent"); //如果值已经修改则更新 "actual rate" long ms = mSensorHandler.getActualUpdateMs(); if (ms ! = mLastActualUpdateMs) { mLastActualUpdateMs = ms; String hz = mLastActualUpdateMs <= 0 ? "--" : Integer.toString((int) Math.ceil(1000. / ms)); mTextActualHz.setText(hz); } } break; case MSG_UPDATE_ACTUAL_HZ: if (mSensorHandler ! = null) { //如果值已经修改则更新 "actual rate" long ms = mSensorHandler.getActualUpdateMs(); if (ms ! = mLastActualUpdateMs) { mLastActualUpdateMs = ms; String hz = mLastActualUpdateMs <= 0 ? "--" : Integer.toString((int) Math.ceil(1000. / ms)); mTextActualHz.setText(hz); } mUiHandler.sendEmptyMessageDelayed(MSG_UPDATE_ACTUAL_HZ, 1000 /*1s*/); } } return true; // we consumed this message } private void updateStatus(String status) { mTextStatus.setVisibility(status == null ? View.GONE : View.VISIBLE); if (status ! = null) mTextStatus.setText(status); } private void updateError() { ControllerBinder binder = getServiceBinder(); String error = binder == null ? "" : binder.getServiceError(); if (error == null) { error = ""; } mTextError.setVisibility(error.length() == 0 ? View.GONE : View.VISIBLE); mTextError.setText(error); } private void updateSampleRate() { String str = mTextTargetHz.getText().toString(); try { int hz = Integer.parseInt(str.trim()); // Cap the value. 50 Hz is a reasonable max value for the emulator if (hz <= 0 || hz > 50) { hz = 50; } if (hz ! = mTargetSampleRate) { mTargetSampleRate = hz; if (mSensorHandler ! = null) { mSensorHandler.setUpdateTargetMs(hz <= 0 ? 0 : (int)(1000.0f / hz)); } } } catch (Exception ignore) {} } }
通过上述代码可知,整个Java层利用了大家熟悉的观察者模式对传感器的数据进行了监听处理。
5.3 分析Frameworks层
在Android系统中,传感器系统的Frameworks层的代码路径是:
frameworks/base/include/core/java/android/hardware
Frameworks层是Android系统提供的应用程序开发接口和应用程序框架。应用程序的调用是通过类实例化或类继承进行的。对应用程序来说,最重要的就是把SensorListener注册到SensorManager上,从而才能以观察者身份接收到数据的变化,因此,要把目光落在SensorManager的构造函数、RegisterListener函数和通知机制相关的代码上。
本节将详细讲解传感器系统的Frameworks层的具体实现流程。
5.3.1 监听传感器的变化
在Android传感器系统的Frameworks层中,文件SensorListener.java用于监听从Java应用层中传递过来的变化。文件SensorListener.java比较简单,具体代码如下所示。
package android.hardware; @Deprecated public interface SensorListener { public void onSensorChanged(int sensor, float[] values); public void onAccuracyChanged(int sensor, int accuracy); }
5.3.2 注册监听
当文件SensorListener.java监听到变化之后,会通过文件SensorManager.java来向服务注册监听变化,并调度Sensor的具体任务。例如在开发Android传感器应用程序时,在上层的通用开发流程如下所示。
(1)通过“getSystemService(SENSOR_SERVICE); ”语句得到传感器服务。这样得到一个用来管理分配调度处理Sensor工作的SensorManager。SensorManager并不服务而是运行于后台,真正属于Sensor的系统服务是SensorService,在终端下的“#service list”中可以看到sensorservice:[android.gui.SensorServer]。
(2)通过“getDefaultSensor(Sensor.TYPE_GRAVITY); ”得到传感器类型,当然还有各种功能不同的传感器,具体可以查阅Android官网API或者源码Sensor.java。
(3)注册监听器SensorEventListener。在应用程序中打开一个监听接口,专门用于处理传感器的数据。
(4)通过回调函数onSensorChanged和onAccuracyChanged实现实时监听。例如对重力感应器的xyz值经过算法变换得到左右上下前后方向等,就由这个回调函数实现。
综上所述,传感器顶层的处理流程如图5-2所示。
▲图5-2 传感器顶层的处理流程
文件SensorManager.java的具体实现流程如下所示。
(1)定义类SensorManager,然后设置各种传感器的初始变量值,具体代码如下所示。
public abstract class SensorManager { protected static final String TAG = "SensorManager"; private static final float[] mTempMatrix = new float[16]; // Cached lists of sensors by type. Guarded by mSensorListByType private final SparseArray<List<Sensor>> mSensorListByType = new SparseArray<List<Sensor>>(); // Legacy sensor manager implementation. Guarded by mSensorListByType during initialization private LegacySensorManager mLegacySensorManager; @Deprecated public static final int SENSOR_ORIENTATION = 1 << 0; @Deprecated public static final int SENSOR_ACCELEROMETER = 1 << 1; @Deprecated public static final int SENSOR_TEMPERATURE = 1 << 2; @Deprecated public static final int SENSOR_MAGNETIC_FIELD = 1 << 3; @Deprecated public static final int SENSOR_LIGHT = 1 << 4; @Deprecated public static final int SENSOR_PROXIMITY = 1 << 5; @Deprecated public static final int SENSOR_TRICORDER = 1 << 6; @Deprecated public static final int SENSOR_ORIENTATION_RAW = 1 << 7; @Deprecated public static final int SENSOR_ALL = 0x7F; @Deprecated public static final int SENSOR_MIN = SENSOR_ORIENTATION; @Deprecated public static final int SENSOR_MAX = ((SENSOR_ALL + 1)>>1); @Deprecated public static final int DATA_X = 0; @Deprecated public static final int DATA_Y = 1; @Deprecated public static final int DATA_Z = 2; @Deprecated public static final int RAW_DATA_INDEX = 3; @Deprecated public static final int RAW_DATA_X = 3; @Deprecated public static final int RAW_DATA_Y = 4; @Deprecated public static final int RAW_DATA_Z = 5; /** Standard gravity (g) on Earth. This value is equivalent to 1G */ public static final float STANDARD_GRAVITY = 9.80665f; /** Sun's gravity in SI units (m/s^2) */ public static final float GRAVITY_SUN = 275.0f; /** Mercury's gravity in SI units (m/s^2) */ public static final float GRAVITY_MERCURY = 3.70f; /** Venus' gravity in SI units (m/s^2) */ public static final float GRAVITY_VENUS = 8.87f; /** Earth's gravity in SI units (m/s^2) */ public static final float GRAVITY_EARTH = 9.80665f; /** The Moon's gravity in SI units (m/s^2) */ public static final float GRAVITY_MOON = 1.6f; /** Mars' gravity in SI units (m/s^2) */ public static final float GRAVITY_MARS = 3.71f; /** Jupiter's gravity in SI units (m/s^2) */ public static final float GRAVITY_JUPITER = 23.12f; /** Saturn's gravity in SI units (m/s^2) */ public static final float GRAVITY_SATURN = 8.96f; /** Uranus' gravity in SI units (m/s^2) */ public static final float GRAVITY_URANUS = 8.69f; /** Neptune's gravity in SI units (m/s^2) */ public static final float GRAVITY_NEPTUNE = 11.0f; /** Pluto's gravity in SI units (m/s^2) */ public static final float GRAVITY_PLUTO = 0.6f; /** Gravity (estimate) on the first Death Star in Empire units (m/s^2) */ public static final float GRAVITY_DEATH_STAR_I = 0.000000353036145f; /** Gravity on the island */ public static final float GRAVITY_THE_ISLAND = 4.815162342f; /** Maximum magnetic field on Earth's surface */ public static final float MAGNETIC_FIELD_EARTH_MAX = 60.0f; /** Minimum magnetic field on Earth's surface */ public static final float MAGNETIC_FIELD_EARTH_MIN = 30.0f; /** Standard atmosphere, or average sea-level pressure in hPa (millibar) */ public static final float PRESSURE_STANDARD_ATMOSPHERE = 1013.25f; /** Maximum luminance of sunlight in lux */ public static final float LIGHT_SUNLIGHT_MAX = 120000.0f; /** luminance of sunlight in lux */ public static final float LIGHT_SUNLIGHT = 110000.0f; /** luminance in shade in lux */ public static final float LIGHT_SHADE = 20000.0f; /** luminance under an overcast sky in lux */ public static final float LIGHT_OVERCAST = 10000.0f; /** luminance at sunrise in lux */ public static final float LIGHT_SUNRISE = 400.0f; /** luminance under a cloudy sky in lux */ public static final float LIGHT_CLOUDY = 100.0f; /** luminance at night with full moon in lux */ public static final float LIGHT_FULLMOON = 0.25f; /** luminance at night with no moon in lux*/ public static final float LIGHT_NO_MOON = 0.001f; /** get sensor data as fast as possible */ public static final int SENSOR_DELAY_FASTEST = 0; /** rate suitable for games */ public static final int SENSOR_DELAY_GAME = 1; /** rate suitable for the user interface */ public static final int SENSOR_DELAY_UI = 2; /**(默认值)适合屏幕方向的变化*/ public static final int SENSOR_DELAY_NORMAL = 3; /** *返回的值,该传感器是不可信的,需要进行校准或环境不允许读数 */ public static final int SENSOR_STATUS_UNRELIABLE = 0; /** *该传感器是报告的低精度的数据,与环境的校准是必要的 */ public static final int SENSOR_STATUS_ACCURACY_LOW = 1; /** * This sensor is reporting data with an average level of accuracy, * calibration with the environment may improve the readings */ public static final int SENSOR_STATUS_ACCURACY_MEDIUM = 2; /** This sensor is reporting data with maximum accuracy */ public static final int SENSOR_STATUS_ACCURACY_HIGH = 3; /** see {@link #remapCoordinateSystem} */ public static final int AXIS_X = 1; /** see {@link #remapCoordinateSystem} */ public static final int AXIS_Y = 2; /** see {@link #remapCoordinateSystem} */ public static final int AXIS_Z = 3; /** see {@link #remapCoordinateSystem} */ public static final int AXIS_MINUS_X = AXIS_X | 0x80; /** see {@link #remapCoordinateSystem} */ public static final int AXIS_MINUS_Y = AXIS_Y | 0x80; /** see {@link #remapCoordinateSystem} */ public static final int AXIS_MINUS_Z = AXIS_Z | 0x80;
(2)定义各种设备类型方法和设备数据的方法,这些方法非常重要,在编写的应用程序中,可以通过AIDL接口远程调用(RPC)的方式得到SensorManager。这样通过在类SensorManager中的方法,可以得到底层的各种传感器数据。上述方法的具体实现代码如下所示。
public int getSensors() { return getLegacySensorManager().getSensors(); } public List<Sensor> getSensorList(int type) { // cache the returned lists the first time List<Sensor> list; final List<Sensor> fullList = getFullSensorList(); synchronized (mSensorListByType) { list = mSensorListByType.get(type); if (list == null) { if (type == Sensor.TYPE_ALL) { list = fullList; } else { list = new ArrayList<Sensor>(); for (Sensor i : fullList) { if (i.getType() == type) list.add(i); } } list = Collections.unmodifiableList(list); mSensorListByType.append(type, list); } } return list; } public Sensor getDefaultSensor(int type) { // TODO: need to be smarter, for now, just return the 1st sensor List<Sensor> l = getSensorList(type); return l.isEmpty() ? null : l.get(0); } @Deprecated public boolean registerListener(SensorListener listener, int sensors) { return registerListener(listener, sensors, SENSOR_DELAY_NORMAL); } @Deprecated public boolean registerListener(SensorListener listener, int sensors, int rate) { return getLegacySensorManager().registerListener(listener, sensors, rate); } @Deprecated public void unregisterListener(SensorListener listener) { unregisterListener(listener, SENSOR_ALL | SENSOR_ORIENTATION_RAW); } @Deprecated public void unregisterListener(SensorListener listener, int sensors) { getLegacySensorManager().unregisterListener(listener, sensors); } public void unregisterListener(SensorEventListener listener, Sensor sensor) { if (listener == null || sensor == null) { return; } unregisterListenerImpl(listener, sensor); } public void unregisterListener(SensorEventListener listener) { if (listener == null) { return; } unregisterListenerImpl(listener, null); } protected abstract void unregisterListenerImpl(SensorEventListener listener, Sensor sensor); public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate) { return registerListener(listener, sensor, rate, null); } public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate, Handler handler) { if (listener == null || sensor == null) { return false; } int delay = -1; switch (rate) { case SENSOR_DELAY_FASTEST: delay = 0; break; case SENSOR_DELAY_GAME: delay = 20000; break; case SENSOR_DELAY_UI: delay = 66667; break; case SENSOR_DELAY_NORMAL: delay = 200000; break; default: delay = rate; break; } return registerListenerImpl(listener, sensor, delay, handler); } protected abstract boolean registerListenerImpl(SensorEventListener listener, Sensor sensor, int delay, Handler handler); public static boolean getRotationMatrix(float[] R, float[] I, float[] gravity, float[] geomagnetic) { // TODO: move this to native code for efficiency float Ax = gravity[0]; float Ay = gravity[1]; float Az = gravity[2]; final float Ex = geomagnetic[0]; final float Ey = geomagnetic[1]; final float Ez = geomagnetic[2]; float Hx = Ey*Az - Ez*Ay; float Hy = Ez*Ax - Ex*Az; float Hz = Ex*Ay - Ey*Ax; final float normH = (float)Math.sqrt(Hx*Hx + Hy*Hy + Hz*Hz); if (normH < 0.1f) { // device is close to free fall (or in space? ), or close to // magnetic north pole. Typical values are > 100 return false; } final float invH = 1.0f / normH; Hx *= invH; Hy *= invH; Hz *= invH; final float invA = 1.0f / (float)Math.sqrt(Ax*Ax + Ay*Ay + Az*Az); Ax *= invA; Ay *= invA; Az *= invA; final float Mx = Ay*Hz - Az*Hy; final float My = Az*Hx - Ax*Hz; final float Mz = Ax*Hy - Ay*Hx; if (R ! = null) { if (R.length == 9) { R[0] = Hx; R[1] = Hy; R[2] = Hz; R[3] = Mx; R[4] = My; R[5] = Mz; R[6] = Ax; R[7] = Ay; R[8] = Az; } else if (R.length == 16) { R[0] = Hx; R[1] = Hy; R[2] = Hz; R[3] = 0; R[4] = Mx; R[5] = My; R[6] = Mz; R[7] = 0; R[8] = Ax; R[9] = Ay; R[10] = Az; R[11] = 0; R[12] = 0; R[13] = 0; R[14] = 0; R[15] = 1; } } if (I ! = null) { // compute the inclination matrix by projecting the geomagnetic // vector onto the Z (gravity) and X (horizontal component // of geomagnetic vector) axes final float invE = 1.0f / (float)Math.sqrt(Ex*Ex + Ey*Ey + Ez*Ez); final float c = (Ex*Mx + Ey*My + Ez*Mz) * invE; final float s = (Ex*Ax + Ey*Ay + Ez*Az) * invE; if (I.length == 9) { I[0] = 1; I[1] = 0; I[2] = 0; I[3] = 0; I[4] = c; I[5] = s; I[6] = 0; I[7] =-s; I[8] = c; } else if (I.length == 16) { I[0] = 1; I[1] = 0; I[2] = 0; I[4] = 0; I[5] = c; I[6] = s; I[8] = 0; I[9] =-s; I[10]= c; I[3] = I[7] = I[11] = I[12] = I[13] = I[14] = 0; I[15] = 1; } } return true; } public static float getInclination(float[] I) { if (I.length == 9) { return (float)Math.atan2(I[5], I[4]); } else { return (float)Math.atan2(I[6], I[5]); } } public static boolean remapCoordinateSystem(float[] inR, int X, int Y, float[] outR) { if (inR == outR) { final float[] temp = mTempMatrix; synchronized(temp) { // we don't expect to have a lot of contention if (remapCoordinateSystemImpl(inR, X, Y, temp)) { final int size = outR.length; for (int i=0 ; i<size ; i++) outR[i] = temp[i]; return true; } } } return remapCoordinateSystemImpl(inR, X, Y, outR); } private static boolean remapCoordinateSystemImpl(float[] inR, int X, int Y, float[] outR) { /* * X and Y define a rotation matrix 'r': * * (X==1)? ((X&0x80)? -1:1):0 (X==2)? ((X&0x80)? -1:1):0 (X==3)? ((X&0x80)? -1:1):0 * (Y==1)? ((Y&0x80)? -1:1):0 (Y==2)? ((Y&0x80)? -1:1):0 (Y==3)? ((X&0x80)? -1:1):0 * r[0] ^ r[1] * * where the 3rd line is the vector product of the first 2 lines * */ final int length = outR.length; if (inR.length ! = length) return false; // invalid parameter if ((X & 0x7C)! =0 || (Y & 0x7C)! =0) return false; // invalid parameter if (((X & 0x3)==0) || ((Y & 0x3)==0)) return false; // no axis specified if ((X & 0x3) == (Y & 0x3)) return false; // same axis specified // Z is "the other" axis, its sign is either +/- sign(X)*sign(Y) // this can be calculated by exclusive-or'ing X and Y; except for // the sign inversion (+/-) which is calculated below int Z = X ^ Y; // extract the axis (remove the sign), offset in the range 0 to 2 final int x = (X & 0x3)-1; final int y = (Y & 0x3)-1; final int z = (Z & 0x3)-1; // compute the sign of Z (whether it needs to be inverted) final int axis_y = (z+1)%3; final int axis_z = (z+2)%3; if (((x^axis_y)|(y^axis_z)) ! = 0) Z ^= 0x80; final boolean sx = (X>=0x80); final boolean sy = (Y>=0x80); final boolean sz = (Z>=0x80); // Perform R * r, in avoiding actual muls and adds final int rowLength = ((length==16)?4:3); for (int j=0 ; j<3 ; j++) { final int offset = j*rowLength; for (int i=0 ; i<3 ; i++) { if (x==i) outR[offset+i] = sx ? -inR[offset+0] : inR[offset+0]; if (y==i) outR[offset+i] = sy ? -inR[offset+1] : inR[offset+1]; if (z==i) outR[offset+i] = sz ? -inR[offset+2] : inR[offset+2]; } } if (length == 16) { outR[3] = outR[7] = outR[11] = outR[12] = outR[13] = outR[14] = 0; outR[15] = 1; } return true; } public static float[] getOrientation(float[] R, float values[]) { if (R.length == 9) { values[0] = (float)Math.atan2(R[1], R[4]); values[1] = (float)Math.asin(-R[7]); values[2] = (float)Math.atan2(-R[6], R[8]); } else { values[0] = (float)Math.atan2(R[1], R[5]); values[1] = (float)Math.asin(-R[9]); values[2] = (float)Math.atan2(-R[8], R[10]); } return values; } public static float getAltitude(float p0, float p) { final float coef = 1.0f / 5.255f; return 44330.0f * (1.0f - (float)Math.pow(p/p0, coef)); } public static void getAngleChange( float[] angleChange, float[] R, float[] prevR) { float rd1=0, rd4=0, rd6=0, rd7=0, rd8=0; float ri0=0, ri1=0, ri2=0, ri3=0, ri4=0, ri5=0, ri6=0, ri7=0, ri8=0; float pri0=0, pri1=0, pri2=0, pri3=0, pri4=0, pri5=0, pri6=0, pri7=0, pri8=0; if(R.length == 9) { ri0 = R[0]; ri1 = R[1]; ri2 = R[2]; ri3 = R[3]; ri4 = R[4]; ri5 = R[5]; ri6 = R[6]; ri7 = R[7]; ri8 = R[8]; } else if(R.length == 16) { ri0 = R[0]; ri1 = R[1]; ri2 = R[2]; ri3 = R[4]; ri4 = R[5]; ri5 = R[6]; ri6 = R[8]; ri7 = R[9]; ri8 = R[10]; } if(prevR.length == 9) { pri0 = prevR[0]; pri1 = prevR[1]; pri2 = prevR[2]; pri3 = prevR[3]; pri4 = prevR[4]; pri5 = prevR[5]; pri6 = prevR[6]; pri7 = prevR[7]; pri8 = prevR[8]; } else if(prevR.length == 16) { pri0 = prevR[0]; pri1 = prevR[1]; pri2 = prevR[2]; pri3 = prevR[4]; pri4 = prevR[5]; pri5 = prevR[6]; pri6 = prevR[8]; pri7 = prevR[9]; pri8 = prevR[10]; } // calculate the parts of the rotation difference matrix we need // rd[i][j] = pri[0][i] * ri[0][j] + pri[1][i] * ri[1][j] + pri[2][i] * ri[2][j]; rd1 = pri0 * ri1 + pri3 * ri4 + pri6 * ri7; //rd[0][1] rd4 = pri1 * ri1 + pri4 * ri4 + pri7 * ri7; //rd[1][1] rd6 = pri2 * ri0 + pri5 * ri3 + pri8 * ri6; //rd[2][0] rd7 = pri2 * ri1 + pri5 * ri4 + pri8 * ri7; //rd[2][1] rd8 = pri2 * ri2 + pri5 * ri5 + pri8 * ri8; //rd[2][2] angleChange[0] = (float)Math.atan2(rd1, rd4); angleChange[1] = (float)Math.asin(-rd7); angleChange[2] = (float)Math.atan2(-rd6, rd8); } public static void getRotationMatrixFromVector(float[] R, float[] rotationVector) { float q0; float q1 = rotationVector[0]; float q2 = rotationVector[1]; float q3 = rotationVector[2]; if (rotationVector.length == 4) { q0 = rotationVector[3]; } else { q0 = 1- q1*q1- q2*q2- q3*q3; q0 = (q0 > 0) ? (float)Math.sqrt(q0) : 0; } float sq_q1 = 2 * q1 * q1; float sq_q2 = 2 * q2 * q2; float sq_q3 = 2 * q3 * q3; float q1_q2 = 2 * q1 * q2; float q3_q0 = 2 * q3 * q0; float q1_q3 = 2 * q1 * q3; float q2_q0 = 2 * q2 * q0; float q2_q3 = 2 * q2 * q3; float q1_q0 = 2 * q1 * q0; if(R.length == 9) { R[0] = 1- sq_q2- sq_q3; R[1] = q1_q2- q3_q0; R[2] = q1_q3 + q2_q0; R[3] = q1_q2 + q3_q0; R[4] = 1- sq_q1- sq_q3; R[5] = q2_q3- q1_q0; R[6] = q1_q3- q2_q0; R[7] = q2_q3 + q1_q0; R[8] = 1- sq_q1- sq_q2; } else if (R.length == 16) { R[0] = 1- sq_q2- sq_q3; R[1] = q1_q2- q3_q0; R[2] = q1_q3 + q2_q0; R[3] = 0.0f; R[4] = q1_q2 + q3_q0; R[5] = 1- sq_q1- sq_q3; R[6] = q2_q3- q1_q0; R[7] = 0.0f; R[8] = q1_q3- q2_q0; R[9] = q2_q3 + q1_q0; R[10] = 1- sq_q1- sq_q2; R[11] = 0.0f; R[12] = R[13] = R[14] = 0.0f; R[15] = 1.0f; } } public static void getQuaternionFromVector(float[] Q, float[] rv) { if (rv.length == 4) { Q[0] = rv[3]; } else { Q[0] = 1- rv[0]*rv[0] - rv[1]*rv[1] - rv[2]*rv[2]; Q[0] = (Q[0] > 0) ? (float)Math.sqrt(Q[0]) : 0; } Q[1] = rv[0]; Q[2] = rv[1]; Q[3] = rv[2]; } public boolean requestTriggerSensor(TriggerEventListener listener, Sensor sensor) { return requestTriggerSensorImpl(listener, sensor); } protected abstract boolean requestTriggerSensorImpl(TriggerEventListener listener, Sensor sensor); public boolean cancelTriggerSensor(TriggerEventListener listener, Sensor sensor) { return cancelTriggerSensorImpl(listener, sensor, true); protected abstract boolean cancelTriggerSensorImpl(TriggerEventListener listener, Sensor sensor, boolean disable); private LegacySensorManager getLegacySensorManager() { synchronized (mSensorListByType) { if (mLegacySensorManager == null) { Log.i(TAG, "This application is using deprecated SensorManager API which will " + "be removed someday. Please consider switching to the new API."); mLegacySensorManager = new LegacySensorManager(this); } return mLegacySensorManager; } } }
上述方法的功能非常重要,其实就是人们在开发传感器应用程序时用到的API接口。有关上述方法的具体说明,读者可以查阅官网SDK API中对于类android.hardware.SensorManager的具体说明。
5.4 分析JNI层
在Android系统中,传感器系统的JNI部分的代码路径是:
frameworks/base/core/jni/android_hardware_SensorManager.cpp
在此文件中提供了对类android.hardware.Sensor.Manage的本地支持。上层和JNI层的调用关系如图5-3所示。
▲图5-3 上层和JNI层的调用关系
在上图所示的调用关系中涉及了下面所示的API接口方法。
· nativeClassInit():在JNI层得到android.hardware.Sensor的JNI环境指针;
· sensors_module_init():通过JNI调用本地框架,得到SensorService和SensorService初始化控制流各功能;
· new Sensor():建立一个Sensor对象,具体可查阅官网API android.hardware.Sensor;
· sensors_module_get_next_sensor():上层得到设备支持的所有Sensor,并放入SensorList链表;
· new SensorThread():创建Sensor线程,当应用程序registerListener()注册监听器的时候开启线程run(),注意当没有数据变化时线程会阻塞。
5.4.1 分析android_hardware_SensorManager.cpp
文件android_hardware_SensorManager.cpp的功能是实现文件SensorManager.java中的native(本地)函数,主要是通过调用文件SensorManager.cpp和文件SensorEventQueue.cpp中的相关类来完成相关的工作的。文件android_hardware_SensorManager.cpp的具体实现代码如下所示。
static struct { jclass clazz; jmethodID dispatchSensorEvent; } gBaseEventQueueClassInfo; namespace android { struct SensorOffsets { jfieldID name; jfieldID vendor; jfieldID version; jfieldID handle; jfieldID type; jfieldID range; jfieldID resolution; jfieldID power; jfieldID minDelay; } gSensorOffsets; /* * The method below are not thread-safe and not intended to be */ static void nativeClassInit (JNIEnv *_env, jclass _this) { jclass sensorClass = _env->FindClass("android/hardware/Sensor"); SensorOffsets& sensorOffsets = gSensorOffsets; sensorOffsets.name = _env->GetFieldID(sensorClass, "mName", "Ljava/lang/String; "); sensorOffsets.vendor =_env->GetFieldID(sensorClass, "mVendor", "Ljava/lang/String; "); sensorOffsets.version = _env->GetFieldID(sensorClass, "mVersion", "I"); sensorOffsets.handle = _env->GetFieldID(sensorClass, "mHandle", "I"); sensorOffsets.type = _env->GetFieldID(sensorClass, "mType", "I"); sensorOffsets.range = _env->GetFieldID(sensorClass, "mMaxRange", "F"); sensorOffsets.resolution = _env->GetFieldID(sensorClass, "mResolution", "F"); sensorOffsets.power = _env->GetFieldID(sensorClass, "mPower", "F"); sensorOffsets.minDelay = _env->GetFieldID(sensorClass, "mMinDelay", "I"); } static jint nativeGetNextSensor(JNIEnv *env, jclass clazz, jobject sensor, jint next) { SensorManager& mgr(SensorManager::getInstance()); Sensor const* const* sensorList; size_t count = mgr.getSensorList(&sensorList); if (size_t(next) >= count) return -1; Sensor const* const list = sensorList[next]; const SensorOffsets& sensorOffsets(gSensorOffsets); jstring name = env->NewStringUTF(list->getName().string()); jstring vendor = env->NewStringUTF(list->getVendor().string()); env->SetObjectField(sensor, sensorOffsets.name, name); env->SetObjectField(sensor, sensorOffsets.vendor, vendor); env->SetIntField(sensor, sensorOffsets.version, list->getVersion()); env->SetIntField(sensor, sensorOffsets.handle, list->getHandle()); env->SetIntField(sensor, sensorOffsets.type, list->getType()); env->SetFloatField(sensor, sensorOffsets.range, list->getMaxValue()); env->SetFloatField(sensor, sensorOffsets.resolution, list->getResolution()); env->SetFloatField(sensor, sensorOffsets.power, list->getPowerUsage()); env->SetIntField(sensor, sensorOffsets.minDelay, list->getMinDelay()); next++; return size_t(next) < count ? next : 0; } //---------------------------------------------------------------------------- class Receiver : public LooperCallback { sp<SensorEventQueue> mSensorQueue; sp<MessageQueue> mMessageQueue; jobject mReceiverObject; jfloatArray mScratch; public: Receiver(const sp<SensorEventQueue>& sensorQueue, const sp<MessageQueue>& messageQueue, jobject receiverObject, jfloatArray scratch) { JNIEnv* env = AndroidRuntime::getJNIEnv(); mSensorQueue = sensorQueue; mMessageQueue = messageQueue; mReceiverObject = env->NewGlobalRef(receiverObject); mScratch = (jfloatArray)env->NewGlobalRef(scratch); } ~Receiver() { JNIEnv* env = AndroidRuntime::getJNIEnv(); env->DeleteGlobalRef(mReceiverObject); env->DeleteGlobalRef(mScratch); } sp<SensorEventQueue> getSensorEventQueue() const { return mSensorQueue; } void destroy() { mMessageQueue->getLooper()->removeFd( mSensorQueue->getFd() ); } private: virtual void onFirstRef() { LooperCallback::onFirstRef(); mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0, ALOOPER_EVENT_INPUT, this, mSensorQueue.get()); } virtual int handleEvent(int fd, int events, void* data) { JNIEnv* env = AndroidRuntime::getJNIEnv(); sp<SensorEventQueue> q = reinterpret_cast<SensorEventQueue *>(data); ssize_t n; ASensorEvent buffer[16]; while ((n = q->read(buffer, 16)) > 0) { for (int i=0 ; i<n ; i++) { env->SetFloatArrayRegion(mScratch, 0, 16, buffer[i].data); env->CallVoidMethod(mReceiverObject, gBaseEventQueueClassInfo.dispatchSensorEvent, buffer[i].sensor, mScratch, buffer[i].vector.status, buffer[i].timestamp); if (env->ExceptionCheck()) { ALOGE("Exception dispatching input event."); return 1; } } } if (n<0 && n ! = -EAGAIN) { // FIXME: error receiving events, what to do in this case? } return 1; } }; static jint nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jobject eventQ, jobject msgQ, jfloatArray scratch) { SensorManager& mgr(SensorManager::getInstance()); sp<SensorEventQueue> queue(mgr.createEventQueue()); sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ); if (messageQueue == NULL) { jniThrowRuntimeException(env, "MessageQueue is not initialized."); return 0; } sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQ, scratch); receiver->incStrong((void*)nativeInitSensorEventQueue); return jint(receiver.get()); } static jint nativeEnableSensor(JNIEnv *env, jclass clazz, jint eventQ, jint handle, jint us) { sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ)); return receiver->getSensorEventQueue()->enableSensor(handle, us); } static jint nativeDisableSensor(JNIEnv *env, jclass clazz, jint eventQ, jint handle) { sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ)); return receiver->getSensorEventQueue()->disableSensor(handle); } static void nativeDestroySensorEventQueue(JNIEnv *env, jclass clazz, jint eventQ, jint handle) { sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ)); receiver->destroy(); receiver->decStrong((void*)nativeInitSensorEventQueue); } //---------------------------------------------------------------------------- static JNINativeMethod gSystemSensorManagerMethods[] = { {"nativeClassInit", "()V", (void*)nativeClassInit }, {"nativeGetNextSensor", "(Landroid/hardware/Sensor; I)I", (void*)nativeGetNextSensor }, }; static JNINativeMethod gBaseEventQueueMethods[] = { {"nativeInitBaseEventQueue", "(Landroid/hardware/SystemSensorManager$BaseEventQueue; Landroid/os/MessageQueue; [F)I", (void*)nativeInitSensorEventQueue }, {"nativeEnableSensor", "(III)I", (void*)nativeEnableSensor }, {"nativeDisableSensor", "(II)I", (void*)nativeDisableSensor }, {"nativeDestroySensorEventQueue", "(I)V", (void*)nativeDestroySensorEventQueue }, }; }; // namespace android using namespace android; #define FIND_CLASS(var, className) \ var = env->FindClass(className); \ LOG_FATAL_IF(! var, "Unable to find class " className); \ var = jclass(env->NewGlobalRef(var)); #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \ var = env->GetMethodID(clazz, methodName, methodDescriptor); \ LOG_FATAL_IF(! var, "Unable to find method " methodName); int register_android_hardware_SensorManager(JNIEnv *env) { jniRegisterNativeMethods(env, "android/hardware/SystemSensorManager", gSystemSensorManagerMethods, NELEM(gSystemSensorManagerMethods)); jniRegisterNativeMethods(env, "android/hardware/SystemSensorManager$BaseEventQueue", gBaseEventQueueMethods, NELEM(gBaseEventQueueMethods)); FIND_CLASS(gBaseEventQueueClassInfo.clazz, "android/hardware/SystemSensorManager$BaseEventQueue"); GET_METHOD_ID(gBaseEventQueueClassInfo.dispatchSensorEvent, gBaseEventQueueClassInfo.clazz, "dispatchSensorEvent", "(I[FIJ)V"); return 0; }
5.4.2 处理客户端数据
文件frameworks\native\libs\gui\SensorManager.cpp功能是提供了对传感器数据的部分操作,实现了“sensor_data_XXX()”格式的函数。另外在Native层的客户端,文件SensorManager.cpp还负责与服务端SensorService.cpp之间的通信工作。文件SensorManager.cpp的具体实现代码如下所示。
// ---------------------------------------------------------------------------- namespace android { // ---------------------------------------------------------------------------- ANDROID_SINGLETON_STATIC_INSTANCE(SensorManager) SensorManager::SensorManager() : mSensorList(0) { // okay we're not locked here, but it's not needed during construction assertStateLocked(); } SensorManager::~SensorManager() { free(mSensorList); } void SensorManager::sensorManagerDied() { Mutex::Autolock _l(mLock); mSensorServer.clear(); free(mSensorList); mSensorList = NULL; mSensors.clear(); } status_t SensorManager::assertStateLocked() const { if (mSensorServer == NULL) { // try for one second const String16 name("sensorservice"); for (int i=0 ; i<4 ; i++) { status_t err = getService(name, &mSensorServer); if (err == NAME_NOT_FOUND) { usleep(250000); continue; } if (err ! = NO_ERROR) { return err; } break; } class DeathObserver : public IBinder::DeathRecipient { SensorManager& mSensorManger; virtual void binderDied(const wp<IBinder>& who) { ALOGW("sensorservice died [%p]", who.unsafe_get()); mSensorManger.sensorManagerDied(); } public: DeathObserver(SensorManager& mgr) : mSensorManger(mgr) { } }; mDeathObserver = new DeathObserver(*const_cast<SensorManager *>(this)); mSensorServer->asBinder()->linkToDeath(mDeathObserver); mSensors = mSensorServer->getSensorList(); size_t count = mSensors.size(); mSensorList = (Sensor const**)malloc(count * sizeof(Sensor*)); for (size_t i=0 ; i<count ; i++) { mSensorList[i] = mSensors.array() + i; } } return NO_ERROR; } ssize_t SensorManager::getSensorList(Sensor const* const** list) const { Mutex::Autolock _l(mLock); status_t err = assertStateLocked(); if (err < 0) { return ssize_t(err); } *list = mSensorList; return mSensors.size(); } Sensor const* SensorManager::getDefaultSensor(int type) { Mutex::Autolock _l(mLock); if (assertStateLocked() == NO_ERROR) { // For now we just return the first sensor of that type we find // in the future it will make sense to let the SensorService make // that decision for (size_t i=0 ; i<mSensors.size() ; i++) { if (mSensorList[i]->getType() == type) return mSensorList[i]; } } return NULL; } sp<SensorEventQueue> SensorManager::createEventQueue() { sp<SensorEventQueue> queue; Mutex::Autolock _l(mLock); while (assertStateLocked() == NO_ERROR) { sp<ISensorEventConnection> connection = mSensorServer->createSensorEventConnection(); if (connection == NULL) { // SensorService just died ALOGE("createEventQueue: connection is NULL. SensorService died."); continue; } queue = new SensorEventQueue(connection); break; } return queue; } // ---------------------------------------------------------------------------- }; // namespace android
5.4.3 处理服务端数据
文件frameworks\native\services\sensorservice\SensorService.cpp功能是实现了Sensor真正的后台服务,是服务端的数据处理中心。在Android的传感器系统中,SensorService作为一个轻量级的System Service,运行于SystemServer内,即在system_init<system_init.cpp>中调用了SensorService::instantiate()。SensorService主要功能如下所示。
(1)通过SensorService::instantiate创建实例对象,并增加到ServiceManager中,然后创建并启动线程,并执行threadLoop;
(2)threadLoop从sensor驱动获取原始数据,然后通过SensorEventConnection把事件发送给客户端;
(3)BnSensorServer的成员函数负责让客户端获取sensor列表和创建SensorEventConnection。
文件SensorService.cpp的具体实现代码如下所示。
namespace android { const char* SensorService::WAKE_LOCK_NAME = "SensorService"; SensorService::SensorService() : mInitCheck(NO_INIT) { } void SensorService::onFirstRef() { ALOGD("nuSensorService starting..."); SensorDevice& dev(SensorDevice::getInstance()); if (dev.initCheck() == NO_ERROR) { sensor_t const* list; ssize_t count = dev.getSensorList(&list); if (count > 0) { ssize_t orientationIndex = -1; bool hasGyro = false; uint32_t virtualSensorsNeeds = (1<<SENSOR_TYPE_GRAVITY) | (1<<SENSOR_TYPE_LINEAR_ACCELERATION) | (1<<SENSOR_TYPE_ROTATION_VECTOR); mLastEventSeen.setCapacity(count); for (ssize_t i=0 ; i<count ; i++) { registerSensor( new HardwareSensor(list[i]) ); switch (list[i].type) { case SENSOR_TYPE_ORIENTATION: orientationIndex = i; break; case SENSOR_TYPE_GYROSCOPE: hasGyro = true; break; case SENSOR_TYPE_GRAVITY: case SENSOR_TYPE_LINEAR_ACCELERATION: case SENSOR_TYPE_ROTATION_VECTOR: virtualSensorsNeeds &= ~(1<<list[i].type); break; } } // it's safe to instantiate the SensorFusion object here // (it wants to be instantiated after h/w sensors have been // registered) const SensorFusion& fusion(SensorFusion::getInstance()); if (hasGyro) { // Always instantiate Android's virtual sensors. Since they are // instantiated behind sensors from the HAL, they won't // interfere with applications, unless they looks specifically // for them (by name) registerVirtualSensor( new RotationVectorSensor() ); registerVirtualSensor( new GravitySensor(list, count) ); registerVirtualSensor( new LinearAccelerationSensor(list, count) ); // these are optional registerVirtualSensor( new OrientationSensor() ); registerVirtualSensor( new CorrectedGyroSensor(list, count) ); } // build the sensor list returned to users mUserSensorList = mSensorList; if (hasGyro) { // virtual debugging sensors are not added to mUserSensorList registerVirtualSensor( new GyroDriftSensor() ); } if (hasGyro && (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR))) { // if we have the fancy sensor fusion, and it's not provided by the // HAL, use our own (fused) orientation sensor by removing the // HAL supplied one form the user list if (orientationIndex >= 0) { mUserSensorList.removeItemsAt(orientationIndex); } } // debugging sensor list for (size_t i=0 ; i<mSensorList.size() ; i++) { switch (mSensorList[i].getType()) { case SENSOR_TYPE_GRAVITY: case SENSOR_TYPE_LINEAR_ACCELERATION: case SENSOR_TYPE_ROTATION_VECTOR: if (strstr(mSensorList[i].getVendor().string(), "Google")) { mUserSensorListDebug.add(mSensorList[i]); } break; default: mUserSensorListDebug.add(mSensorList[i]); break; } } run("SensorService", PRIORITY_URGENT_DISPLAY); mInitCheck = NO_ERROR; } } } void SensorService::registerSensor(SensorInterface* s) { sensors_event_t event; memset(&event, 0, sizeof(event)); const Sensor sensor(s->getSensor()); // add to the sensor list (returned to clients) mSensorList.add(sensor); // add to our handle->SensorInterface mapping mSensorMap.add(sensor.getHandle(), s); // create an entry in the mLastEventSeen array mLastEventSeen.add(sensor.getHandle(), event); } void SensorService::registerVirtualSensor(SensorInterface* s) { registerSensor(s); mVirtualSensorList.add( s ); } SensorService::~SensorService() { for (size_t i=0 ; i<mSensorMap.size() ; i++) delete mSensorMap.valueAt(i); } static const String16 sDump("android.permission.DUMP"); status_t SensorService::dump(int fd, const Vector<String16>& args) { const size_t SIZE = 1024; char buffer[SIZE]; String8 result; if (! PermissionCache::checkCallingPermission(sDump)) { snprintf(buffer, SIZE, "Permission Denial: " "can't dump SurfaceFlinger from pid=%d, uid=%d\n", IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid()); result.append(buffer); } else { Mutex::Autolock _l(mLock); snprintf(buffer, SIZE, "Sensor List:\n"); result.append(buffer); for (size_t i=0 ; i<mSensorList.size() ; i++) { const Sensor& s(mSensorList[i]); const sensors_event_t& e(mLastEventSeen.valueFor(s.getHandle())); snprintf(buffer, SIZE, "%-48s| %-32s | 0x%08x | maxRate=%7.2fHz | " "last=<%5.1f, %5.1f, %5.1f>\n", s.getName().string(), s.getVendor().string(), s.getHandle(), s.getMinDelay() ? (1000000.0f / s.getMinDelay()) : 0.0f, e.data[0], e.data[1], e.data[2]); result.append(buffer); } SensorFusion::getInstance().dump(result, buffer, SIZE); SensorDevice::getInstance().dump(result, buffer, SIZE); snprintf(buffer, SIZE, "%d active connections\n", mActiveConnections.size()); result.append(buffer); snprintf(buffer, SIZE, "Active sensors:\n"); result.append(buffer); for (size_t i=0 ; i<mActiveSensors.size() ; i++) { int handle = mActiveSensors.keyAt(i); snprintf(buffer, SIZE, "%s (handle=0x%08x, connections=%d)\n", getSensorName(handle).string(), handle, mActiveSensors.valueAt(i)->getNumConnections()); result.append(buffer); } } write(fd, result.string(), result.size()); return NO_ERROR; } void SensorService::cleanupAutoDisabledSensor(const sp<SensorEventConnection>& connection, sensors_event_t const* buffer, const int count) { SensorInterface* sensor; status_t err = NO_ERROR; for (int i=0 ; i<count ; i++) { int handle = buffer[i].sensor; if (getSensorType(handle) == SENSOR_TYPE_SIGNIFICANT_MOTION) { if (connection->hasSensor(handle)) { sensor = mSensorMap.valueFor(handle); err = sensor ? sensor->resetStateWithoutActuatingHardware(connection. get(), handle): status_t(BAD_VALUE); if (err ! = NO_ERROR) { ALOGE("Sensor Inteface: Resetting state failed with err: %d", err); } cleanupWithoutDisable(connection, handle); } } } } bool SensorService::threadLoop() { ALOGD("nuSensorService thread starting..."); const size_t numEventMax = 16; const size_t minBufferSize = numEventMax + numEventMax * mVirtualSensorList.size(); sensors_event_t buffer[minBufferSize]; sensors_event_t scratch[minBufferSize]; SensorDevice& device(SensorDevice::getInstance()); const size_t vcount = mVirtualSensorList.size(); ssize_t count; bool wakeLockAcquired = false; const int halVersion = device.getHalDeviceVersion(); do { count = device.poll(buffer, numEventMax); if (count<0) { ALOGE("sensor poll failed (%s)", strerror(-count)); break; } // Poll has returned. Hold a wakelock // Todo(): add a flag to the sensors definitions to indicate // the sensors which can wake up the AP for (int i = 0; i < count; i++) { if (getSensorType(buffer[i].sensor) == SENSOR_TYPE_SIGNIFICANT_MOTION) { acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME); wakeLockAcquired = true; break; } } recordLastValue(buffer, count); // handle virtual sensors if (count && vcount) { sensors_event_t const * const event = buffer; const DefaultKeyedVector<int, SensorInterface*> virtualSensors( getActiveVirtualSensors()); const size_t activeVirtualSensorCount = virtualSensors.size(); if (activeVirtualSensorCount) { size_t k = 0; SensorFusion& fusion(SensorFusion::getInstance()); if (fusion.isEnabled()) { for (size_t i=0 ; i<size_t(count) ; i++) { fusion.process(event[i]); } } for (size_t i=0 ; i<size_t(count) && k<minBufferSize ; i++) { for (size_t j=0 ; j<activeVirtualSensorCount ; j++) { if (count + k >= minBufferSize) { ALOGE("buffer too small to hold all events: " "count=%u, k=%u, size=%u", count, k, minBufferSize); break; } sensors_event_t out; SensorInterface* si = virtualSensors.valueAt(j); if (si->process(&out, event[i])) { buffer[count + k] = out; k++; } } } if (k) { // record the last synthesized values recordLastValue(&buffer[count], k); count += k; // sort the buffer by time-stamps sortEventBuffer(buffer, count); } } } // handle backward compatibility for RotationVector sensor if (halVersion < SENSORS_DEVICE_API_VERSION_1_0) { for (int i = 0; i < count; i++) { if (getSensorType(buffer[i].sensor) == SENSOR_TYPE_ROTATION_VECTOR) { // All the 4 components of the quaternion should be available // No heading accuracy. Set it to -1 buffer[i].data[4] = -1; } } } // send our events to clients const SortedVector< wp<SensorEventConnection> > activeConnections( getActiveConnections()); size_t numConnections = activeConnections.size(); for (size_t i=0 ; i<numConnections ; i++) { sp<SensorEventConnection> connection( activeConnections[i].promote()); if (connection ! = 0) { connection->sendEvents(buffer, count, scratch); // Some sensors need to be auto disabled after the trigger cleanupAutoDisabledSensor(connection, buffer, count); } } // We have read the data, upper layers should hold the wakelock if (wakeLockAcquired) release_wake_lock(WAKE_LOCK_NAME); } while (count >= 0 || Thread::exitPending()); ALOGW("Exiting SensorService::threadLoop => aborting..."); abort(); return false; } void SensorService::recordLastValue( sensors_event_t const * buffer, size_t count) { Mutex::Autolock _l(mLock); // record the last event for each sensor int32_t prev = buffer[0].sensor; for (size_t i=1 ; i<count ; i++) { // record the last event of each sensor type in this buffer int32_t curr = buffer[i].sensor; if (curr ! = prev) { mLastEventSeen.editValueFor(prev) = buffer[i-1]; prev = curr; } } mLastEventSeen.editValueFor(prev) = buffer[count-1]; } void SensorService::sortEventBuffer(sensors_event_t* buffer, size_t count) { struct compar { static int cmp(void const* lhs, void const* rhs) { sensors_event_t const* l = static_cast<sensors_event_t const*>(lhs); sensors_event_t const* r = static_cast<sensors_event_t const*>(rhs); return l->timestamp - r->timestamp; } }; qsort(buffer, count, sizeof(sensors_event_t), compar::cmp); } SortedVector< wp<SensorService::SensorEventConnection> > SensorService::getActiveConnections() const { Mutex::Autolock _l(mLock); return mActiveConnections; } DefaultKeyedVector<int, SensorInterface*> SensorService::getActiveVirtualSensors() const { Mutex::Autolock _l(mLock); return mActiveVirtualSensors; } String8 SensorService::getSensorName(int handle) const { size_t count = mUserSensorList.size(); for (size_t i=0 ; i<count ; i++) { const Sensor& sensor(mUserSensorList[i]); if (sensor.getHandle() == handle) { return sensor.getName(); } } String8 result("unknown"); return result; } int SensorService::getSensorType(int handle) const { size_t count = mUserSensorList.size(); for (size_t i=0 ; i<count ; i++) { const Sensor& sensor(mUserSensorList[i]); if (sensor.getHandle() == handle) { return sensor.getType(); } } return -1; } Vector<Sensor> SensorService::getSensorList() { char value[PROPERTY_VALUE_MAX]; property_get("debug.sensors", value, "0"); if (atoi(value)) { return mUserSensorListDebug; } return mUserSensorList; } sp<ISensorEventConnection> SensorService::createSensorEventConnection() { uid_t uid = IPCThreadState::self()->getCallingUid(); sp<SensorEventConnection> result(new SensorEventConnection(this, uid)); return result; } void SensorService::cleanupConnection(SensorEventConnection* c) { Mutex::Autolock _l(mLock); const wp<SensorEventConnection> connection(c); size_t size = mActiveSensors.size(); ALOGD_IF(DEBUG_CONNECTIONS, "%d active sensors", size); for (size_t i=0 ; i<size ; ) { int handle = mActiveSensors.keyAt(i); if (c->hasSensor(handle)) { ALOGD_IF(DEBUG_CONNECTIONS, "%i: disabling handle=0x%08x", i, handle); SensorInterface* sensor = mSensorMap.valueFor( handle ); ALOGE_IF(! sensor, "mSensorMap[handle=0x%08x] is null! ", handle); if (sensor) { sensor->activate(c, false); } } SensorRecord* rec = mActiveSensors.valueAt(i); ALOGE_IF(! rec, "mActiveSensors[%d] is null (handle=0x%08x)! ", i, handle); ALOGD_IF(DEBUG_CONNECTIONS, "removing connection %p for sensor[%d].handle=0x%08x", c, i, handle); if (rec && rec->removeConnection(connection)) { ALOGD_IF(DEBUG_CONNECTIONS, "... and it was the last connection"); mActiveSensors.removeItemsAt(i, 1); mActiveVirtualSensors.removeItem(handle); delete rec; size--; } else { i++; } } mActiveConnections.remove(connection); BatteryService::cleanup(c->getUid()); } status_t SensorService::enable(const sp<SensorEventConnection>& connection, int handle) { if (mInitCheck ! = NO_ERROR) return mInitCheck; Mutex::Autolock _l(mLock); SensorInterface* sensor = mSensorMap.valueFor(handle); SensorRecord* rec = mActiveSensors.valueFor(handle); if (rec == 0) { rec = new SensorRecord(connection); mActiveSensors.add(handle, rec); if (sensor->isVirtual()) { mActiveVirtualSensors.add(handle, sensor); } } else { if (rec->addConnection(connection)) { // this sensor is already activated, but we are adding a // connection that uses it. Immediately send down the last // known value of the requested sensor if it's not a // "continuous" sensor if (sensor->getSensor().getMinDelay() == 0) { sensors_event_t scratch; sensors_event_t& event(mLastEventSeen.editValueFor(handle)); if (event.version == sizeof(sensors_event_t)) { connection->sendEvents(&event, 1); } } } } if (connection->addSensor(handle)) { BatteryService::enableSensor(connection->getUid(), handle); // the sensor was added (which means it wasn't already there) // so, see if this connection becomes active if (mActiveConnections.indexOf(connection) < 0) { mActiveConnections.add(connection); } } else { ALOGW("sensor %08x already enabled in connection %p (ignoring)", handle, connection.get()); } // we are setup, now enable the sensor status_t err = sensor ? sensor->activate(connection.get(), true) : status_t(BAD_VALUE); if (err ! = NO_ERROR) { // enable has failed, reset state in SensorDevice status_t resetErr = sensor ? sensor->resetStateWithoutActuatingHardware (connection.get(), handle) : status_t(BAD_VALUE); // enable has failed, reset our state cleanupWithoutDisable(connection, handle); } return err; } status_t SensorService::disable(const sp<SensorEventConnection>& connection, int handle) { if (mInitCheck ! = NO_ERROR) return mInitCheck; status_t err = cleanupWithoutDisable(connection, handle); if (err == NO_ERROR) { SensorInterface* sensor = mSensorMap.valueFor(handle); err = sensor ? sensor->activate(connection.get(), false) : status_t(BAD_VALUE); } return err; } status_t SensorService::cleanupWithoutDisable(const sp<SensorEventConnection>& connection, int handle) { Mutex::Autolock _l(mLock); SensorRecord* rec = mActiveSensors.valueFor(handle); if (rec) { // see if this connection becomes inactive if (connection->removeSensor(handle)) { BatteryService::disableSensor(connection->getUid(), handle); } if (connection->hasAnySensor() == false) { mActiveConnections.remove(connection); } // see if this sensor becomes inactive if (rec->removeConnection(connection)) { mActiveSensors.removeItem(handle); mActiveVirtualSensors.removeItem(handle); delete rec; } return NO_ERROR; } return BAD_VALUE; } status_t SensorService::setEventRate(const sp<SensorEventConnection>& connection, int handle, nsecs_t ns) { if (mInitCheck ! = NO_ERROR) return mInitCheck; SensorInterface* sensor = mSensorMap.valueFor(handle); if (! sensor) return BAD_VALUE; if (ns < 0) return BAD_VALUE; nsecs_t minDelayNs = sensor->getSensor().getMinDelayNs(); if (ns < minDelayNs) { ns = minDelayNs; } if (ns < MINIMUM_EVENTS_PERIOD) ns = MINIMUM_EVENTS_PERIOD; return sensor->setDelay(connection.get(), handle, ns); } // --------------------------------------------------------------------------- SensorService::SensorRecord::SensorRecord( const sp<SensorEventConnection>& connection) { mConnections.add(connection); } bool SensorService::SensorRecord::addConnection( const sp<SensorEventConnection>& connection) { if (mConnections.indexOf(connection) < 0) { mConnections.add(connection); return true; } return false; } bool SensorService::SensorRecord::removeConnection( const wp<SensorEventConnection>& connection) { ssize_t index = mConnections.indexOf(connection); if (index >= 0) { mConnections.removeItemsAt(index, 1); } return mConnections.size() ? false : true; } // --------------------------------------------------------------------------- SensorService::SensorEventConnection::SensorEventConnection( const sp<SensorService>& service, uid_t uid) : mService(service), mChannel(new BitTube()), mUid(uid) { } SensorService::SensorEventConnection::~SensorEventConnection() { ALOGD_IF(DEBUG_CONNECTIONS, "~SensorEventConnection(%p)", this); mService->cleanupConnection(this); } void SensorService::SensorEventConnection::onFirstRef() { } bool SensorService::SensorEventConnection::addSensor(int32_t handle) { Mutex::Autolock _l(mConnectionLock); if (mSensorInfo.indexOf(handle) < 0) { mSensorInfo.add(handle); return true; } return false; } bool SensorService::SensorEventConnection::removeSensor(int32_t handle) { Mutex::Autolock _l(mConnectionLock); if (mSensorInfo.remove(handle) >= 0) { return true; } return false; } bool SensorService::SensorEventConnection::hasSensor(int32_t handle) const { Mutex::Autolock _l(mConnectionLock); return mSensorInfo.indexOf(handle) >= 0; } bool SensorService::SensorEventConnection::hasAnySensor() const { Mutex::Autolock _l(mConnectionLock); return mSensorInfo.size() ? true : false; } status_t SensorService::SensorEventConnection::sendEvents( sensors_event_t const* buffer, size_t numEvents, sensors_event_t* scratch) { // filter out events not for this connection size_t count = 0; if (scratch) { Mutex::Autolock _l(mConnectionLock); size_t i=0; while (i<numEvents) { const int32_t curr = buffer[i].sensor; if (mSensorInfo.indexOf(curr) >= 0) { do { scratch[count++] = buffer[i++]; } while ((i<numEvents) && (buffer[i].sensor == curr)); } else { i++; } } } else { scratch = const_cast<sensors_event_t *>(buffer); count = numEvents; } // NOTE: ASensorEvent and sensors_event_t are the same type ssize_t size = SensorEventQueue::write(mChannel, reinterpret_cast<ASensorEvent const*>(scratch), count); if (size == -EAGAIN) { // the destination doesn't accept events anymore, it's probably // full. For now, we just drop the events on the floor //ALOGW("dropping %d events on the floor", count); return size; } return size < 0 ? status_t(size) : status_t(NO_ERROR); } sp<BitTube> SensorService::SensorEventConnection::getSensorChannel() const { return mChannel; } status_t SensorService::SensorEventConnection::enableDisable( int handle, bool enabled) { status_t err; if (enabled) { err = mService->enable(this, handle); } else { err = mService->disable(this, handle); } return err; } status_t SensorService::SensorEventConnection::setEventRate( int handle, nsecs_t ns) { return mService->setEventRate(this, handle, ns); } // --------------------------------------------------------------------------- }; // namespace android
通过上述实现代码,可以了解SensorService服务的创建、启动过程,整个过程的“C/S”通信架构如图5-4所示。
▲图5-4 “C/S”通信架构图
在此需要注意,BpSensorServer并没有在系统中被用到,即使从ISensorServer.cpp中把它删除也不会对Sensor的工作有任何影响。这是因为它的工作已经被SensorManager.cpp所取代,ServiceManager会直接获取上面System_init文件中添加的SensorService对象。
5.4.4 封装HAL层的代码
在Android系统中,通过文件frameworks\native\services\sensorservice\SensorDevice.cpp封装了HAL层的代码,主要包含的功能如下所示:
· 获取sensor列表(getSensorList);
· 获取sensor事件(poll);
· Enable或Disable sensor(activate);
· 设置delay时间。
文件SensorDevice.cpp的具体实现代码如下所示。
namespace android { // --------------------------------------------------------------------------- ANDROID_SINGLETON_STATIC_INSTANCE(SensorDevice) SensorDevice::SensorDevice() : mSensorDevice(0), mSensorModule(0) { status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID, (hw_module_t const**)&mSensorModule); ALOGE_IF(err, "couldn't load %s module (%s)", SENSORS_HARDWARE_MODULE_ID, strerror(-err)); if (mSensorModule) { err = sensors_open(&mSensorModule->common, &mSensorDevice); ALOGE_IF(err, "couldn't open device for module %s (%s)", SENSORS_HARDWARE_MODULE_ID, strerror(-err)); if (mSensorDevice) { sensor_t const* list; ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list); mActivationCount.setCapacity(count); Info model; for (size_t i=0 ; i<size_t(count) ; i++) { mActivationCount.add(list[i].handle, model); mSensorDevice->activate(mSensorDevice, list[i].handle, 0); } } } } void SensorDevice::dump(String8& result, char* buffer, size_t SIZE) { if (! mSensorModule) return; sensor_t const* list; ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list); snprintf(buffer, SIZE, "%d h/w sensors:\n", int(count)); result.append(buffer); Mutex::Autolock _l(mLock); for (size_t i=0 ; i<size_t(count) ; i++) { const Info& info = mActivationCount.valueFor(list[i].handle); snprintf(buffer, SIZE, "handle=0x%08x, active-count=%d, rates(ms)={ ", list[i].handle, info.rates.size()); result.append(buffer); for (size_t j=0 ; j<info.rates.size() ; j++) { snprintf(buffer, SIZE, "%4.1f%s", info.rates.valueAt(j) / 1e6f, j<info.rates.size()-1 ? ", " : ""); result.append(buffer); } snprintf(buffer, SIZE, " }, selected=%4.1f ms\n", info.delay / 1e6f); result.append(buffer); } } ssize_t SensorDevice::getSensorList(sensor_t const** list) { if (! mSensorModule) return NO_INIT; ssize_t count = mSensorModule->get_sensors_list(mSensorModule, list); return count; } status_t SensorDevice::initCheck() const { return mSensorDevice && mSensorModule ? NO_ERROR : NO_INIT; } ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) { if (! mSensorDevice) return NO_INIT; ssize_t c; do { c = mSensorDevice->poll(mSensorDevice, buffer, count); } while (c == -EINTR); return c; } status_t SensorDevice::resetStateWithoutActuatingHardware(void *ident, int handle) { if (! mSensorDevice) return NO_INIT; Info& info( mActivationCount.editValueFor(handle)); Mutex::Autolock _l(mLock); info.rates.removeItem(ident); return NO_ERROR; } status_t SensorDevice::activate(void* ident, int handle, int enabled) { if (! mSensorDevice) return NO_INIT; status_t err(NO_ERROR); bool actuateHardware = false; Info& info( mActivationCount.editValueFor(handle) ); ALOGD_IF(DEBUG_CONNECTIONS, "SensorDevice::activate: ident=%p, handle=0x%08x, enabled=%d, count=%d", ident, handle, enabled, info.rates.size()); if (enabled) { Mutex::Autolock _l(mLock); ALOGD_IF(DEBUG_CONNECTIONS, "... index=%ld", info.rates.indexOfKey(ident)); if (info.rates.indexOfKey(ident) < 0) { info.rates.add(ident, DEFAULT_EVENTS_PERIOD); if (info.rates.size() == 1) { actuateHardware = true; } } else { // sensor was already activated for this ident } } else { Mutex::Autolock _l(mLock); ALOGD_IF(DEBUG_CONNECTIONS, "... index=%ld", info.rates.indexOfKey(ident)); ssize_t idx = info.rates.removeItem(ident); if (idx >= 0) { if (info.rates.size() == 0) { actuateHardware = true; } } else { // sensor wasn't enabled for this ident } } if (actuateHardware) { ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w"); err = mSensorDevice->activate(mSensorDevice, handle, enabled); ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle, strerror(-err)); } { // scope for the lock Mutex::Autolock _l(mLock); nsecs_t ns = info.selectDelay(); mSensorDevice->setDelay(mSensorDevice, handle, ns); } return err; } status_t SensorDevice::setDelay(void* ident, int handle, int64_t ns) { if (! mSensorDevice) return NO_INIT; Mutex::Autolock _l(mLock); Info& info( mActivationCount.editValueFor(handle) ); status_t err = info.setDelayForIdent(ident, ns); if (err < 0) return err; ns = info.selectDelay(); return mSensorDevice->setDelay(mSensorDevice, handle, ns); } int SensorDevice::getHalDeviceVersion() const { if (! mSensorDevice) return -1; return mSensorDevice->common.version; } // --------------------------------------------------------------------------- status_t SensorDevice::Info::setDelayForIdent(void* ident, int64_t ns) { ssize_t index = rates.indexOfKey(ident); if (index < 0) { ALOGE("Info::setDelayForIdent(ident=%p, ns=%lld) failed (%s)", ident, ns, strerror(-index)); return BAD_INDEX; } rates.editValueAt(index) = ns; return NO_ERROR; } nsecs_t SensorDevice::Info::selectDelay() { nsecs_t ns = rates.valueAt(0); for (size_t i=1 ; i<rates.size() ; i++) { nsecs_t cur = rates.valueAt(i); if (cur < ns) { ns = cur; } } delay = ns; return ns; } // --------------------------------------------------------------------------- }; // namespace android
这样SensorSevice会把任务交给SensorDevice,而SensorDevice会调用标准的抽象层接口。由此可见,Sensor架构的抽象层接口是最标准的一种,它很好地实现了抽象层与本地框架的分离。
5.4.5 消息队列处理
在Android的传感器系统中,文件frameworks\native\libs\gui\SensorEventQueue.cpp实现了处理消息队列的功能。此文件能够在创建其实例的时候传入SensorEventConnection的实例,SensorEventConnection继承于ISensorEventConnection。SensorEventConnection其实是客户端调用SensorService的createSensorEventConnection()方法创建的,是客户端与服务端沟通的桥梁,通过这个桥梁,可以完成如下所示的任务:
· 获取管道的句柄;
· 往管道读写数据;
· 通知服务端对Sensor可用。
文件frameworks\native\libs\gui\SensorEventQueue.cpp的具体实现代码如下所示。
// ---------------------------------------------------------------------------- namespace android { // ---------------------------------------------------------------------------- SensorEventQueue::SensorEventQueue(const sp<ISensorEventConnection>& connection) : mSensorEventConnection(connection) { } SensorEventQueue::~SensorEventQueue() { } void SensorEventQueue::onFirstRef() { mSensorChannel = mSensorEventConnection->getSensorChannel(); } int SensorEventQueue::getFd() const { return mSensorChannel->getFd(); } ssize_t SensorEventQueue::write(const sp<BitTube>& tube, ASensorEvent const* events, size_t numEvents) { return BitTube::sendObjects(tube, events, numEvents); } ssize_t SensorEventQueue::read(ASensorEvent* events, size_t numEvents) { return BitTube::recvObjects(mSensorChannel, events, numEvents); } sp<Looper> SensorEventQueue::getLooper() const { Mutex::Autolock _l(mLock); if (mLooper == 0) { mLooper = new Looper(true); mLooper->addFd(getFd(), getFd(), ALOOPER_EVENT_INPUT, NULL, NULL); } return mLooper; } status_t SensorEventQueue::waitForEvent() const { const int fd = getFd(); sp<Looper> looper(getLooper()); int events; int32_t result; do { result = looper->pollOnce(-1, NULL, &events, NULL); if (result == ALOOPER_POLL_ERROR) { ALOGE("SensorEventQueue::waitForEvent error (errno=%d)", errno); result = -EPIPE; // unknown error, so we make up one break; } if (events & ALOOPER_EVENT_HANGUP) { // the other-side has died ALOGE("SensorEventQueue::waitForEvent error HANGUP"); result = -EPIPE; // unknown error, so we make up one break; } } while (result ! = fd); return (result == fd) ? status_t(NO_ERROR) : result; } status_t SensorEventQueue::wake() const { sp<Looper> looper(getLooper()); looper->wake(); return NO_ERROR; } status_t SensorEventQueue::enableSensor(Sensor const* sensor) const { return mSensorEventConnection->enableDisable(sensor->getHandle(), true); } status_t SensorEventQueue::disableSensor(Sensor const* sensor) const { return mSensorEventConnection->enableDisable(sensor->getHandle(), false); } status_t SensorEventQueue::enableSensor(int32_t handle, int32_t us) const { status_t err = mSensorEventConnection->enableDisable(handle, true); if (err == NO_ERROR) { mSensorEventConnection->setEventRate(handle, us2ns(us)); } return err; } status_t SensorEventQueue::disableSensor(int32_t handle) const { return mSensorEventConnection->enableDisable(handle, false); } status_t SensorEventQueue::setEventRate(Sensor const* sensor, nsecs_t ns) const { return mSensorEventConnection->setEventRate(sensor->getHandle(), ns); } // ---------------------------------------------------------------------------- }; // namespace android
由此可见,SensorManager负责控制流,通过C/S的Binder机制与SensorService实现通信。具体过程如图5-5所示。
▲图5-5 SensorManager控制流的处理流程
而SensorEventQueue负责数据流,功能是通过管道机制来读写底层的数据。具体过程如图5-6所示。
▲图5-6 SensorEventQueue数据流的处理流程
5.5 分析HAL层
在Android系统中,在HAL层中提供了Android独立于具体硬件的抽象接口。其中HAL层的头文件路径如下。
hardware/libhardware/include/hardware/sensors.h
而具体实现文件需要开发者个人编写,具体可以参考下面内容。
hardware\invensense\libsensors_iio\sensors_mpl.cpp
文件sensors.h的主要实现代码如下所示。
typedef struct { union { float v[3]; struct { float x; float y; float z; }; struct { float azimuth; float pitch; float roll; }; }; int8_t status; uint8_t reserved[3]; } sensors_vec_t; /** * uncalibrated gyroscope and magnetometer event data */ typedef struct { union { float uncalib[3]; struct { float x_uncalib; float y_uncalib; float z_uncalib; }; }; union { float bias[3]; struct { float x_bias; float y_bias; float z_bias; }; }; } uncalibrated_event_t; /** * Union of the various types of sensor data * that can be returned. */ typedef struct sensors_event_t { /* must be sizeof(struct sensors_event_t) */ int32_t version; /* sensor identifier */ int32_t sensor; /* sensor type */ int32_t type; /* reserved */ int32_t reserved0; /* time is in nanosecond */ int64_t timestamp; union { float data[16]; /* acceleration values are in meter per second per second (m/s^2) */ sensors_vec_t acceleration; /* magnetic vector values are in micro-Tesla (uT) */ sensors_vec_t magnetic; /* orientation values are in degrees */ sensors_vec_t orientation; /* gyroscope values are in rad/s */ sensors_vec_t gyro; /* temperature is in degrees centigrade (Celsius) */ float temperature; /* distance in centimeters */ float distance; /* light in SI lux units */ float light; /* pressure in hectopascal (hPa) */ float pressure; /* relative humidity in percent */ float relative_humidity; /* step-counter */ uint64_t step_counter; /* uncalibrated gyroscope values are in rad/s */ uncalibrated_event_t uncalibrated_gyro; /* uncalibrated magnetometer values are in micro-Teslas */ uncalibrated_event_t uncalibrated_magnetic; }; uint32_t reserved1[4]; } sensors_event_t; struct sensor_t; struct sensors_module_t { struct hw_module_t common; int (*get_sensors_list)(struct sensors_module_t* module, struct sensor_t const** list); }; struct sensor_t { /* Name of this sensor. * All sensors of the same "type" must have a different "name". */ const char* name; /* vendor of the hardware part */ const char* vendor; int version; int handle; /* this sensor's type */ int type; /* maximum range of this sensor's value in SI units */ float maxRange; /* smallest difference between two values reported by this sensor */ float resolution; /* rough estimate of this sensor's power consumption in mA */ float power; int32_t minDelay; /* reserved fields, must be zero */ void* reserved[8]; }; struct sensors_poll_device_t { struct hw_device_t common; int (*activate)(struct sensors_poll_device_t *dev, int handle, int enabled); int (*setDelay)(struct sensors_poll_device_t *dev, int handle, int64_t ns); int (*poll)(struct sensors_poll_device_t *dev, sensors_event_t* data, int count); }; typedef struct sensors_poll_device_1 { union { struct sensors_poll_device_t v0; struct { struct hw_device_t common; int (*activate)(struct sensors_poll_device_t *dev, int handle, int enabled); int (*setDelay)(struct sensors_poll_device_t *dev, int handle, int64_t period_ns); int (*poll)(struct sensors_poll_device_t *dev, sensors_event_t* data, int count); }; }; int (*batch)(struct sensors_poll_device_1* dev, int handle, int flags, int64_t period_ns, int64_t timeout); void (*reserved_procs[8])(void); } sensors_poll_device_1_t; /** convenience API for opening and closing a device */ static inline int sensors_open(const struct hw_module_t* module, struct sensors_poll_device_t** device) { return module->methods->open(module, SENSORS_HARDWARE_POLL, (struct hw_device_t**)device); } static inline int sensors_close(struct sensors_poll_device_t* device) { return device->common.close(&device->common); } static inline int sensors_open_1(const struct hw_module_t* module, sensors_poll_device_1_t** device) { return module->methods->open(module, SENSORS_HARDWARE_POLL, (struct hw_device_t**)device); } static inline int sensors_close_1(sensors_poll_device_1_t* device) { return device->common.close(&device->common); } __END_DECLS #endif // ANDROID_SENSORS_INTERFACE_H
而具体的实现文件是Linux Kernel层,也就是具体的硬件设备驱动程序,例如可以将其命名为“sensors.c”,然后编写如下定义struct sensors_poll_device_t的代码。
struct sensors_poll_device_t { struct hw_device_t common; // Activate/deactivate one sensor int (*activate)(struct sensors_poll_device_t *dev, int handle, int enabled); // Set the delay between sensor events in nanoseconds for a given sensor int (*setDelay)(struct sensors_poll_device_t *dev, int handle, int64_t ns); // Returns an array of sensor data int (*poll)(struct sensors_poll_device_t *dev, sensors_event_t* data, int count); };
也可以编写如下定义struct sensors_module_t的代码。
struct sensors_module_t { struct hw_module_t common; /** * Enumerate all available sensors. The list is returned in "list". * @return number of sensors in the list */ int (*get_sensors_list)(struct sensors_module_t* module, struct sensor_t const** list); };
也可以编写如下定义struct sensor_t的代码。
struct sensor_t { /* name of this sensors */ const char*name; /* vendor of the hardware part */ const char*vendor; /* version of the hardware part + driver. The value of this field * must increase when the driver is updated in a way that changes the * output of this sensor. This is important for fused sensors when the * fusion algorithm is updated. */ int version; /* handle that identifies this sensors. This handle is used to activate * and deactivate this sensor. The value of the handle must be 8 bits * in this version of the API. */ int handle; /* this sensor's type. */ int type; /* maximaum range of this sensor's value in SI units */ float maxRange; /* smallest difference between two values reported by this sensor */ float resolution; /* rough estimate of this sensor's power consumption in mA */ float power; /* minimum delay allowed between events in microseconds. A value of zero * means that this sensor doesn't report events at a constant rate, but * rather only when a new data is available */ int32_t minDelay; /* reserved fields, must be zero */ void*reserved[8]; };
也可以编写如下代码定义struct sensors_event_t。
typedef struct { union { float v[3]; struct { float x; float y; float z; }; struct { float azimuth; float pitch; float roll; }; }; int8_t status; uint8_t reserved[3]; } sensors_vec_t; /** * Union of the various types of sensor data * that can be returned. */ typedef struct sensors_event_t { /* must be sizeof(struct sensors_event_t) */ int32_t version; /* sensor identifier */ int32_t sensor; /* sensor type */ int32_t type; /* reserved */ int32_t reserved0; /* time is in nanosecond */ int64_t timestamp; union { float data[16]; /* acceleration values are in meter per second per second (m/s^2) */ sensors_vec_t acceleration; /* magnetic vector values are in micro-Tesla (uT) */ sensors_vec_t magnetic; /* orientation values are in degrees */ sensors_vec_t orientation; /* gyroscope values are in rad/s */ sensors_vec_t gyro; /* temperature is in degrees centigrade (Celsius) */ float temperature; /* distance in centimeters */ float distance; /* light in SI lux units */ float light; /* pressure in hectopascal (hPa) */ float pressure; /* relative humidity in percent */ float relative_humidity; }; uint32_t reserved1[4]; } sensors_event_t;
也可以编写如下代码定义struct sensors_module_t。
static const struct sensor_t sSensorList[] = { { "MMA8452Q 3-axis Accelerometer", "Freescale Semiconductor", 1, SENSORS_HANDLE_BASE+ID_A, SENSOR_TYPE_ACCELEROMETER, 4.0f*9.81f, (4.0f*9.81f)/256.0f, 0.2f, 0, { } }, { "AK8975 3-axis Magnetic field sensor", "Asahi Kasei", 1, SENSORS_HANDLE_BASE+ID_M, SENSOR_TYPE_MAGNETIC_FIELD, 2000.0f, 1.0f/16.0f, 6.8f, 0, { } }, { "AK8975 Orientation sensor", "Asahi Kasei", 1, SENSORS_HANDLE_BASE+ID_O, SENSOR_TYPE_ORIENTATION, 360.0f, 1.0f, 7.0f, 0, { } }, { "ST 3-axis Gyroscope sensor", "STMicroelectronics", 1, SENSORS_HANDLE_BASE+ID_GY, SENSOR_TYPE_GYROSCOPE, RANGE_GYRO, CONVERT_GYRO, 6.1f, 1190, { } }, { "AL3006Proximity sensor", "Dyna Image Corporation", 1, SENSORS_HANDLE_BASE+ID_P, SENSOR_TYPE_PROXIMITY, PROXIMITY_THRESHOLD_CM, PROXIMITY_THRESHOLD_CM, 0.5f, 0, { } }, { "AL3006 light sensor", "Dyna Image Corporation", 1, SENSORS_HANDLE_BASE+ID_L, SENSOR_TYPE_LIGHT, 10240.0f, 1.0f, 0.5f, 0, { } }, }; static int open_sensors(const struct hw_module_t* module, const char* name, struct hw_device_t** device); static int sensors__get_sensors_list(struct sensors_module_t* module, struct sensor_t const** list) { *list = sSensorList; return ARRAY_SIZE(sSensorList); } static struct hw_module_methods_t sensors_module_methods = { .open = open_sensors }; const struct sensors_module_t HAL_MODULE_INFO_SYM = { .common = { .tag = HARDWARE_MODULE_TAG, .version_major = 1, .version_minor = 0, .id = SENSORS_HARDWARE_MODULE_ID, .name = "MMA8451Q & AK8973A & gyro Sensors Module", .author = "The Android Project", .methods = &sensors_module_methods, }, .get_sensors_list = sensors__get_sensors_list }; static int open_sensors(const struct hw_module_t* module, const char* name, struct hw_device_t** device) { return init_nusensors(module, device); //待后面讲解 }
到此为止,整个Android系统中传感器模块的源码分析完毕。由此可见,整个传感器系统的总体调用关系如图5-7所示。
▲图5-7 传感器系统的总体调用关系
客户端读取数据时的调用时序如图5-8所示。
▲图5-8 客户端读取数据时的调用时序图
服务器端的调用时序如图5-9所示。
▲图5-9 服务器端的调用时序图