Android Sensor 概览

本文基于android-10.0.0_r36 – 清华大学开源软件镜像站AOSP
Android 传感器概览:sensors_overview
传感器堆栈:sensor-stack
魅族内核团队:Android Sensor Framework 概览
对照 Android 平台架构

System Apps 调用 Android Senser

Android 平台支持三大类传感器:

  • 动态传感器
    这类传感器测量三个轴向上的加速力和旋转力。这个类别中包含加速度计、重力传感器、陀螺仪和旋转矢量传感器。

  • 环境传感器
    这类传感器测量各种环境参数,如环境气温、气压、照度和湿度。这个类别中包含气压计、光度计和温度计。

  • 位置传感器
    这类传感器测量设备的物理位置。这个类别中包含屏幕方向传感器和磁力计。

传感器 类型 说明 常见用途
TYPE_ACCELEROMETER 硬件 测量在所有三个物理轴向(x、y 和 z)上施加在设备上的加速力(包括重力),以 m/s2 为单位。 动态检测(摇晃、倾斜等)。
TYPE_AMBIENT_TEMPERATURE 硬件 以摄氏度 (°C) 为单位测量环境室温。请参见下面的备注。 监测气温。
TYPE_GRAVITY 软件或硬件 测量在所有三个物理轴向(x、y、z)上施加在设备上的重力,单位为 m/s2。 动态检测(摇晃、倾斜等)。
TYPE_GYROSCOPE 硬件 测量设备在三个物理轴向(x、y 和 z)上的旋转速率,以 rad/s 为单位。 旋转检测(旋转、转动等)。
TYPE_LIGHT 硬件 测量环境光级(照度),以 lx 为单位。 控制屏幕亮度。
TYPE_LINEAR_ACCELERATION 软件或硬件 测量在所有三个物理轴向(x、y 和 z)上施加在设备上的加速力(不包括重力),以 m/s2 为单位。 监测单个轴向上的加速度。
TYPE_MAGNETIC_FIELD 硬件 测量所有三个物理轴向(x、y、z)上的环境地磁场,以 μT 为单位。 创建罗盘。
TYPE_ORIENTATION 软件 测量设备围绕所有三个物理轴(x、y、z)旋转的度数。从 API 级别 3 开始,您可以结合使用重力传感器、地磁场传感器和 getRotationMatrix() 方法来获取设备的倾角矩阵和旋转矩阵。 确定设备位置。
TYPE_PRESSURE 硬件 测量环境气压,以 hPa 或 mbar 为单位。 监测气压变化。
TYPE_PROXIMITY 硬件 测量物体相对于设备显示屏幕的距离,以 cm 为单位。该传感器通常用于确定手机是否被举到人的耳边。 通话过程中手机的位置。
TYPE_RELATIVE_HUMIDITY 硬件 测量环境的相对湿度,以百分比 (%) 表示。 监测露点、绝对湿度和相对湿度。
TYPE_ROTATION_VECTOR 软件或硬件 通过提供设备旋转矢量的三个元素来检测设备的屏幕方向。 动态检测和旋转检测。
TYPE_TEMPERATURE 硬件 测量设备的温度,以摄氏度 (°C) 为单位。该传感器的实现因设备而异。在 API 级别 14 中,该传感器已被 TYPE_AMBIENT_TEMPERATURE 传感器取代 监测温度。

动态传感器

1】使用重力传感器

重力传感器提供指示重力方向和大小的三维矢量。通常,此传感器用于确定设备在空间中的相对屏幕方向。

sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);

2】使用计步器传感器

计步器传感器提供自已激活传感器后最后一次重启以来用户迈出的步数。与步测器传感器相比,计步器的延迟时间更长(最多 10 秒),但精确度更高。

sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);

3】使用步测器传感器

每次用户迈步时,步测器传感器都会触发事件。延迟时间预计将低于 2 秒。

sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);

位置传感器

1】使用近程传感器

近程传感器可让您确定物体与设备的距离。

sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);

近程传感器通常用于确定人的头部距手持设备表面的距离(例如,当用户拨打或接听电话时)。大多数近程传感器返回以厘米为单位的绝对距离,但有些仅返回近距离和远距离值。

public class SensorActivity extends Activity implements SensorEventListener {private SensorManager sensorManager;private Sensor proximity;@Overridepublic final void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);// Get an instance of the sensor service, and use that to get an instance of// a particular sensor.sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);proximity = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);}@Overridepublic final void onAccuracyChanged(Sensor sensor, int accuracy) {// Do something here if sensor accuracy changes.}@Overridepublic final void onSensorChanged(SensorEvent event) {float distance = event.values[0];// Do something with this sensor data.}@Overrideprotected void onResume() {// Register a listener for the sensor.super.onResume();sensorManager.registerListener(this, proximity, SensorManager.SENSOR_DELAY_NORMAL);}@Overrideprotected void onPause() {// Be sure to unregister the sensor when the activity pauses.super.onPause();sensorManager.unregisterListener(this);}
}

2】使用地磁旋转矢量传感器

地磁旋转矢量传感器与旋转矢量传感器类似,但前者使用磁力计而非陀螺仪。此传感器的精度比普通旋转矢量传感器低,但能耗也有所降低。如果您希望在不消耗过多电量的情况下收集后台中的某些旋转信息,则可以仅使用此传感器。

sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR);

环境传感器

1】使用光、压力和温度传感器

从光、压力和温度传感器获取的原始数据通常不需要校准、滤波或修改,因此它们是一些最容易使用的传感器。要从这些传感器获取数据,您需要先创建 SensorManager 类的实例,并用它来获取物理传感器的实例。然后,在 onResume() 方法中注册传感器监听器,并开始在 onSensorChanged() 回调方法中处理传入的传感器数据。

    public class SensorActivity extends Activity implements SensorEventListener {private SensorManager sensorManager;private Sensor pressure;@Overridepublic final void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);// Get an instance of the sensor service, and use that to get an instance of// a particular sensor.sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);pressure = sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE);}@Overridepublic final void onAccuracyChanged(Sensor sensor, int accuracy) {// Do something here if sensor accuracy changes.}@Overridepublic final void onSensorChanged(SensorEvent event) {float millibarsOfPressure = event.values[0];// Do something with this sensor data.}@Overrideprotected void onResume() {// Register a listener for the sensor.super.onResume();sensorManager.registerListener(this, pressure, SensorManager.SENSOR_DELAY_NORMAL);}@Overrideprotected void onPause() {// Be sure to unregister the sensor when the activity pauses.super.onPause();sensorManager.unregisterListener(this);}}

Java API Framework

可以利用 Android 传感器框架来访问这些传感器并获取传感器的原始数据。传感器框架是 android.hardware 软件包的一部分,包含了以下类和接口:

  • SensorManager\SystemSensorManager
    您可以使用这个类来创建传感器服务的实例。该类提供了各种方法来访问和列出传感器,注册和取消注册传感器事件监听器,以及获取屏幕方向信息。它还提供了几个传感器常量,用于报告传感器精确度,设置数据采集频率和校准传感器。
  • Sensor
    您可以使用这个类来创建特定传感器的实例。该类提供了各种方法来确定传感器的特性。
  • SensorEvent
    系统使用这个类来创建传感器事件对象,该对象提供有关传感器事件的信息。传感器事件对象中包含以下信息:原始传感器数据、生成事件的传感器类型、数据的准确度和事件的时间戳。
  • SensorEventListener
    您可以使用此接口创建两种回调方法,以在传感器值或传感器精确度发生变化时接收通知(传感器事件)。

在典型的应用中,您可以使用这些与传感器相关的 API 来执行两个基本任务:

  • 识别传感器和传感器特性
    如果应用具有依赖于特定传感器类型或特性的功能,则在运行时识别传感器和传感器特性非常有用。例如,您可能希望识别设备上的所有传感器,以便于停用依赖于不存在的传感器的应用功能。同样,您可能希望识别特定类型的所有传感器,以便选择可以为应用带来最佳性能的传感器实现。

  • 监控传感器事件
    您可以通过监控传感器事件来获取原始传感器数据。每当传感器检测到它所测量的参数发生变化时,就会发生传感器事件。传感器事件为您提供 4 项信息:触发事件的传感器的名称、事件的时间戳、事件的准确度以及触发事件的原始传感器数据。

识别传感器和传感器特性

使用 SensorManager 和Sensor 获取

sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
List<Sensor> deviceSensors = sensorManager.getSensorList(Sensor.TYPE_ALL); //列出所有传感器
pressure = sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE);           //获取特定传感器

SENSOR_SERVICE 启动

SystemServer 负责启动,在引导服务 startBootstrapServices 中启动 startSensorService()

    /*** Start the sensor service. This is a blocking call and can take time.*/private static native void startSensorService();private void startBootstrapServices() {...traceBeginAndSlog("StartSensorPrivacyService");mSystemServiceManager.startService(new SensorPrivacyService(mSystemContext));traceEnd();...// The sensor service needs access to package manager service, app ops// service, and permissions service, therefore we start it after them.// Start sensor service in a separate thread. Completion should be checked// before using it.mSensorServiceStart = SystemServerInitThreadPool.get().submit(() -> {TimingsTraceLog traceLog = new TimingsTraceLog(SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);traceLog.traceBegin(START_SENSOR_SERVICE);startSensorService();//调用JNI接口,启动SensorServicetraceLog.traceEnd();}, START_SENSOR_SERVICE);}

SensorPrivacyService初步了解:
 
在飞行模式下,设备仍可以访问某些传感器以启用特定功能,比如屏幕旋转和拍照。Android 10 提供了一个开发者选项设置,用于关闭设备中的所有传感器。(设置 > 系统 > 开发者选项 > 快捷设置开发者图块中可启用传感器已关闭)
管理传感器已关闭状态并向客户端传达状态变更的系统服务位于
frameworks/base/services/core/java/com/android/server/SensorPrivacyService.java
frameworks/base/core/java/android/hardware/SensorPrivacyManager.java。

在其他服务 startOtherServices 中启动 startHidlServices()

    /*** Start all HIDL services that are run inside the system server. This may take some time.*/private static native void startHidlServices();private void startOtherServices() {...// Start receiving calls from HIDL services. Start in in a separate thread// because it need to connect to SensorManager. This have to start// after START_SENSOR_SERVICE is done.SystemServerInitThreadPool.get().submit(() -> {TimingsTraceLog traceLog = new TimingsTraceLog(SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);traceLog.traceBegin(START_HIDL_SERVICES);startHidlServices();traceLog.traceEnd();}, START_HIDL_SERVICES);...}

SensorManager 实际是子类 SystemSensorManager 转换

SystemSensorManager 该类主要实现 SensorManager 控制和数据获取的逻辑。

frameworks/base/core/java/android/app/SystemServiceRegistry.java

    static {//......registerService(Context.SENSOR_SERVICE, SensorManager.class,new CachedServiceFetcher<SensorManager>() {@Overridepublic SensorManager createService(ContextImpl ctx) {return new SystemSensorManager(ctx.getOuterContext(),ctx.mMainThread.getHandler().getLooper());}});//......}

frameworks/base/core/java/android/hardware/SystemSensorManager.java

public class SystemSensorManager extends SensorManager {//....../** {@hide} */public SystemSensorManager(Context context, Looper mainLooper) {synchronized (sLock) {if (!sNativeClassInited) {sNativeClassInited = true;nativeClassInit();}}mMainLooper = mainLooper;mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;mContext = context;mNativeInstance = nativeCreate(context.getOpPackageName());// initialize the sensor listfor (int index = 0;; ++index) {Sensor sensor = new Sensor();if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;mFullSensorsList.add(sensor);mHandleToSensor.put(sensor.getHandle(), sensor);}}

监控传感器事件

注册 SensorEventListener 监听;监控原始传感器数据,需要通过 SensorEventListener 接口公开的回调方法:onAccuracyChanged() 和 onSensorChanged()。

SystemSensorManager.registerListenerImpl注册监听

SystemSensorManager
该类主要实现 SensorManager 控制和数据获取的逻辑。
文件路径:frameworks/base/core/java/android/hardware/SystemSensorManager.java

    protected boolean registerListenerImpl(clistener, Sensor sensor,int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) {if (listener == null || sensor == null) {Log.e(TAG, "sensor or listener is null");return false;}// Trigger Sensors should use the requestTriggerSensor call.if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {Log.e(TAG, "Trigger Sensors should use the requestTriggerSensor.");return false;}if (maxBatchReportLatencyUs < 0 || delayUs < 0) {Log.e(TAG, "maxBatchReportLatencyUs and delayUs should be non-negative");return false;}if (mSensorListeners.size() >= MAX_LISTENER_COUNT) {throw new IllegalStateException("register failed, "+ "the sensor listeners size has exceeded the maximum limit "+ MAX_LISTENER_COUNT);}// Invariants to preserve:// - one Looper per SensorEventListener// - one Looper per SensorEventQueue// We map SensorEventListener to a SensorEventQueue, which holds the loopersynchronized (mSensorListeners) {SensorEventQueue queue = mSensorListeners.get(listener);if (queue == null) {Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;final String fullClassName =listener.getClass().getEnclosingClass() != null? listener.getClass().getEnclosingClass().getName(): listener.getClass().getName();queue = new SensorEventQueue(listener, looper, this, fullClassName);if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs)) {queue.dispose();return false;}mSensorListeners.put(listener, queue);return true;} else {return queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs);}}}

Handler\Looper
将SensorEventListener映射到SensorEventQueue

SensorEventQueue

dispatchSensorEvent分发mListener.onSensorChanged、mListener.onAccuracyChanged(当accuracy值改变时)
还有dispatchFlushCompleteEvent、dispatchAdditionalInfoEvent
 
dispatch事件都有注释Called from native code,通过BaseEventQueue的JNI

static final class SensorEventQueue extends BaseEventQueue {private final SensorEventListener mListener;private final SparseArray<SensorEvent> mSensorsEvents = new SparseArray<SensorEvent>();public SensorEventQueue(SensorEventListener listener, Looper looper,SystemSensorManager manager, String packageName) {super(looper, manager, OPERATING_MODE_NORMAL, packageName);mListener = listener;}@Overridepublic void addSensorEvent(Sensor sensor) {SensorEvent t = new SensorEvent(Sensor.getMaxLengthValuesArray(sensor,mManager.mTargetSdkLevel));synchronized (mSensorsEvents) {mSensorsEvents.put(sensor.getHandle(), t);}}@Overridepublic void removeSensorEvent(Sensor sensor) {synchronized (mSensorsEvents) {mSensorsEvents.delete(sensor.getHandle());}}// Called from native code.@SuppressWarnings("unused")@Overrideprotected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,long timestamp) {final Sensor sensor = mManager.mHandleToSensor.get(handle);if (sensor == null) {// sensor disconnectedreturn;}SensorEvent t = null;synchronized (mSensorsEvents) {t = mSensorsEvents.get(handle);}if (t == null) {// This may happen if the client has unregistered and there are pending events in// the queue waiting to be delivered. Ignore.return;}// Copy from the values array.System.arraycopy(values, 0, t.values, 0, t.values.length);t.timestamp = timestamp;t.accuracy = inAccuracy;t.sensor = sensor;// call onAccuracyChanged() only if the value changesfinal int accuracy = mSensorAccuracies.get(handle);if ((t.accuracy >= 0) && (accuracy != t.accuracy)) {mSensorAccuracies.put(handle, t.accuracy);mListener.onAccuracyChanged(t.sensor, t.accuracy);}mListener.onSensorChanged(t);}// Called from native code.@SuppressWarnings("unused")@Overrideprotected void dispatchFlushCompleteEvent(int handle) {if (mListener instanceof SensorEventListener2) {final Sensor sensor = mManager.mHandleToSensor.get(handle);if (sensor == null) {// sensor disconnectedreturn;}((SensorEventListener2) mListener).onFlushCompleted(sensor);}return;}// Called from native code.@SuppressWarnings("unused")@Overrideprotected void dispatchAdditionalInfoEvent(int handle, int type, int serial, float[] floatValues, int[] intValues) {if (mListener instanceof SensorEventCallback) {final Sensor sensor = mManager.mHandleToSensor.get(handle);if (sensor == null) {// sensor disconnectedreturn;}SensorAdditionalInfo info =new SensorAdditionalInfo(sensor, type, serial, intValues, floatValues);((SensorEventCallback) mListener).onSensorAdditionalInfo(info);}}}

BaseEventQueue

    private abstract static class BaseEventQueue {private static native long nativeInitBaseEventQueue(long nativeManager,WeakReference<BaseEventQueue> eventQWeak, MessageQueue msgQ,String packageName, int mode, String opPackageName);private static native int nativeEnableSensor(long eventQ, int handle, int rateUs,int maxBatchReportLatencyUs);private static native int nativeDisableSensor(long eventQ, int handle);private static native void nativeDestroySensorEventQueue(long eventQ);private static native int nativeFlushSensor(long eventQ);private static native int nativeInjectSensorData(long eventQ, int handle,float[] values, int accuracy, long timestamp);private long mNativeSensorEventQueue;private final SparseBooleanArray mActiveSensors = new SparseBooleanArray();protected final SparseIntArray mSensorAccuracies = new SparseIntArray();private final CloseGuard mCloseGuard = CloseGuard.get();protected final SystemSensorManager mManager;protected static final int OPERATING_MODE_NORMAL = 0;protected static final int OPERATING_MODE_DATA_INJECTION = 1;BaseEventQueue(Looper looper, SystemSensorManager manager, int mode, String packageName) {if (packageName == null) packageName = "";mNativeSensorEventQueue = nativeInitBaseEventQueue(manager.mNativeInstance,new WeakReference<>(this), looper.getQueue(),packageName, mode, manager.mContext.getOpPackageName());mCloseGuard.open("dispose");mManager = manager;}public void dispose() {dispose(false);}public boolean addSensor(Sensor sensor, int delayUs, int maxBatchReportLatencyUs) {// Check if already present.int handle = sensor.getHandle();if (mActiveSensors.get(handle)) return false;// Get ready to receive events before calling enable.mActiveSensors.put(handle, true);addSensorEvent(sensor);if (enableSensor(sensor, delayUs, maxBatchReportLatencyUs) != 0) {// Try continuous mode if batching fails.if (maxBatchReportLatencyUs == 0|| maxBatchReportLatencyUs > 0 && enableSensor(sensor, delayUs, 0) != 0) {removeSensor(sensor, false);return false;}}return true;}public boolean removeAllSensors() {for (int i = 0; i < mActiveSensors.size(); i++) {if (mActiveSensors.valueAt(i) == true) {int handle = mActiveSensors.keyAt(i);Sensor sensor = mManager.mHandleToSensor.get(handle);if (sensor != null) {disableSensor(sensor);mActiveSensors.put(handle, false);removeSensorEvent(sensor);} else {// sensor just disconnected -- just ignore.}}}return true;}public boolean removeSensor(Sensor sensor, boolean disable) {final int handle = sensor.getHandle();if (mActiveSensors.get(handle)) {if (disable) disableSensor(sensor);mActiveSensors.put(sensor.getHandle(), false);removeSensorEvent(sensor);return true;}return false;}public int flush() {if (mNativeSensorEventQueue == 0) throw new NullPointerException();return nativeFlushSensor(mNativeSensorEventQueue);}public boolean hasSensors() {// no more sensors are setreturn mActiveSensors.indexOfValue(true) >= 0;}@Overrideprotected void finalize() throws Throwable {try {dispose(true);} finally {super.finalize();}}private void dispose(boolean finalized) {if (mCloseGuard != null) {if (finalized) {mCloseGuard.warnIfOpen();}mCloseGuard.close();}if (mNativeSensorEventQueue != 0) {nativeDestroySensorEventQueue(mNativeSensorEventQueue);mNativeSensorEventQueue = 0;}}private int enableSensor(Sensor sensor, int rateUs, int maxBatchReportLatencyUs) {if (mNativeSensorEventQueue == 0) throw new NullPointerException();if (sensor == null) throw new NullPointerException();return nativeEnableSensor(mNativeSensorEventQueue, sensor.getHandle(), rateUs,maxBatchReportLatencyUs);}protected int injectSensorDataBase(int handle, float[] values, int accuracy,long timestamp) {return nativeInjectSensorData(mNativeSensorEventQueue, handle, values, accuracy, timestamp);}private int disableSensor(Sensor sensor) {if (mNativeSensorEventQueue == 0) throw new NullPointerException();if (sensor == null) throw new NullPointerException();return nativeDisableSensor(mNativeSensorEventQueue, sensor.getHandle());}@UnsupportedAppUsageprotected abstract void dispatchSensorEvent(int handle, float[] values, int accuracy,long timestamp);@UnsupportedAppUsageprotected abstract void dispatchFlushCompleteEvent(int handle);@UnsupportedAppUsageprotected void dispatchAdditionalInfoEvent(int handle, int type, int serial, float[] floatValues, int[] intValues) {// default implementation is do nothing}protected abstract void addSensorEvent(Sensor sensor);protected abstract void removeSensorEvent(Sensor sensor);}

nativeInitBaseEventQueue : 创建一个接收数据的Receiver对象
addSensor
addSensorEvent
enableSensor : nativeEnableSensor

Sensor JNI

com_android_server_SystemServer.cpp

frameworks/base/services/core/jni/com_android_server_SystemServer.cpp

static void android_server_SystemServer_startSensorService(JNIEnv* /* env */, jobject /* clazz */) {char propBuf[PROPERTY_VALUE_MAX];property_get("system_init.startsensorservice", propBuf, "1");if (strcmp(propBuf, "1") == 0) {SensorService::publish(false /* allowIsolated */,IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);}}static void android_server_SystemServer_startHidlServices(JNIEnv* env, jobject /* clazz */) {using ::android::frameworks::schedulerservice::V1_0::ISchedulingPolicyService;using ::android::frameworks::schedulerservice::V1_0::implementation::SchedulingPolicyService;using ::android::frameworks::sensorservice::V1_0::ISensorManager;using ::android::frameworks::sensorservice::V1_0::implementation::SensorManager;using ::android::hardware::configureRpcThreadpool;status_t err;configureRpcThreadpool(5, false /* callerWillJoin */);JavaVM *vm;LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Cannot get Java VM");sp<ISensorManager> sensorService = new SensorManager(vm);err = sensorService->registerAsService();ALOGE_IF(err != OK, "Cannot register %s: %d", ISensorManager::descriptor, err);sp<ISchedulingPolicyService> schedulingService = new SchedulingPolicyService();err = schedulingService->registerAsService();ALOGE_IF(err != OK, "Cannot register %s: %d", ISchedulingPolicyService::descriptor, err);
}

android_hardware_SensorManager.cpp

frameworks/base/core/jni/android_hardware_SensorManager.cpp

SystemSensorManager.java初始化

该文件负责 jave 层和 native 层通信的 JNI 实现,上层的 Java 代码通过 JNI 调用 Native 层提供的服务。
SystemSensorManager.java构造函数先调用 nativeClassInit 和 nativeGetSensorAtIndex 获取系统支持的所有 Sensor 的参数(nativeClassInit 只会调用一次),包括名称、类型等参数。

nativeClassInit()

nativeClassInit 获取Sensor.java类的成员变量和成员函数保存到gSensorOffsets中

/** nativeClassInit is not inteneded to be thread-safe. It should be called before other native...* functions (except nativeCreate).*/
static void
nativeClassInit (JNIEnv *_env, jclass _this)
{//android.hardware.SensorSensorOffsets& sensorOffsets = gSensorOffsets;jclass sensorClass = (jclass)MakeGlobalRefOrDie(_env, FindClassOrDie(_env, "android/hardware/Sensor"));sensorOffsets.clazz = sensorClass;sensorOffsets.name = GetFieldIDOrDie(_env, sensorClass, "mName", "Ljava/lang/String;");sensorOffsets.vendor = GetFieldIDOrDie(_env, sensorClass, "mVendor", "Ljava/lang/String;");sensorOffsets.version = GetFieldIDOrDie(_env, sensorClass, "mVersion", "I");sensorOffsets.handle = GetFieldIDOrDie(_env, sensorClass, "mHandle", "I");sensorOffsets.range = GetFieldIDOrDie(_env, sensorClass, "mMaxRange", "F");sensorOffsets.resolution = GetFieldIDOrDie(_env, sensorClass, "mResolution","F");sensorOffsets.power = GetFieldIDOrDie(_env, sensorClass, "mPower", "F");sensorOffsets.minDelay = GetFieldIDOrDie(_env, sensorClass, "mMinDelay", "I");sensorOffsets.fifoReservedEventCount =GetFieldIDOrDie(_env,sensorClass, "mFifoReservedEventCount", "I");sensorOffsets.fifoMaxEventCount = GetFieldIDOrDie(_env,sensorClass, "mFifoMaxEventCount", "I");sensorOffsets.stringType =GetFieldIDOrDie(_env,sensorClass, "mStringType", "Ljava/lang/String;");sensorOffsets.requiredPermission =GetFieldIDOrDie(_env,sensorClass, "mRequiredPermission", "Ljava/lang/String;");sensorOffsets.maxDelay = GetFieldIDOrDie(_env,sensorClass, "mMaxDelay", "I");sensorOffsets.flags = GetFieldIDOrDie(_env,sensorClass, "mFlags", "I");sensorOffsets.setType = GetMethodIDOrDie(_env,sensorClass, "setType", "(I)Z");sensorOffsets.setUuid = GetMethodIDOrDie(_env,sensorClass, "setUuid", "(JJ)V");sensorOffsets.init = GetMethodIDOrDie(_env,sensorClass, "<init>", "()V");// java.util.List;ListOffsets& listOffsets = gListOffsets;jclass listClass = (jclass) MakeGlobalRefOrDie(_env, FindClassOrDie(_env, "java/util/List"));listOffsets.clazz = listClass;listOffsets.add = GetMethodIDOrDie(_env,listClass, "add", "(Ljava/lang/Object;)Z");// initialize java.lang.String and empty string internStringOffsets& stringOffsets = gStringOffsets;stringOffsets.clazz = MakeGlobalRefOrDie(_env, FindClassOrDie(_env, "java/lang/String"));stringOffsets.intern =GetMethodIDOrDie(_env, stringOffsets.clazz, "intern", "()Ljava/lang/String;");ScopedLocalRef<jstring> empty(_env, _env->NewStringUTF(""));stringOffsets.emptyString = (jstring)MakeGlobalRefOrDie(_env, _env->CallObjectMethod(empty.get(), stringOffsets.intern));
}

nativeGetSensorAtIndex

nativeGetSensorAtIndex 获取Sensor列表保存到Java层Sensor对象中

static jboolean
nativeGetSensorAtIndex(JNIEnv *env, jclass clazz, jlong sensorManager, jobject sensor, jint index)
{SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);Sensor const* const* sensorList;ssize_t count = mgr->getSensorList(&sensorList);if (ssize_t(index) >= count) {return false;}return translateNativeSensorToJavaSensor(env, sensor, *sensorList[index]) != NULL;
}

mNativeInstance = nativeCreate(context.getOpPackageName());

nativeCreate 创建Native层 SensorManager 建立与SensorService的连接
frameworks/native/libs/sensor/SensorManager.cpp:Sensor 在 Native 层的客户端,负责与服务端 SensorService.cpp 的通信

static jlong
nativeCreate
(JNIEnv *env, jclass clazz, jstring opPackageName)
{ScopedUtfChars opPackageNameUtf(env, opPackageName);return (jlong) &SensorManager::getInstanceForPackage(String16(opPackageNameUtf.c_str()));
}

SensorEventQueue 应用注册sensor监听时创建

nativeInitBaseEventQueue : 创建SensorEventQueue\创建一个接收数据的Receiver对象

static const JNINativeMethod gBaseEventQueueMethods[] = {{"nativeInitBaseEventQueue","(JLjava/lang/ref/WeakReference;Landroid/os/MessageQueue;Ljava/lang/String;ILjava/lang/String;)J",(void*)nativeInitSensorEventQueue },
//......
};static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jlong sensorManager,jobject eventQWeak, jobject msgQ, jstring packageName, jint mode) {SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);ScopedUtfChars packageUtf(env, packageName);String8 clientName(packageUtf.c_str());sp<SensorEventQueue> queue(mgr->createEventQueue(clientName, mode)); //创建SensorEventQueueif (queue == NULL) {jniThrowRuntimeException(env, "Cannot construct native SensorEventQueue.");return 0;}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, eventQWeak);//创建一个接收数据的Receiver对象receiver->incStrong((void*)nativeInitSensorEventQueue);return jlong(receiver.get());
}

Receiver对象

获取套接字fd: mSensorQueue->getFd()
实际获取 SensorEventQueue > SensorEventConnection > BitTube 里边mReceiveFd
mReceiveFd添加到looper里边,在 system/core/libutils/Looper.cpp,会通过epoll监听该fd,当有事件时,就会回调Receiver::handleEvent()

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

通过jni回调SystemSensorManager::dispatchSensorEvent(),将数据给SensorManager

    virtual int handleEvent(int fd, int events, void* data) {JNIEnv* env = AndroidRuntime::getJNIEnv();sp<SensorEventQueue> q = reinterpret_cast<SensorEventQueue *>(data);ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));ssize_t n;ASensorEvent buffer[16];while ((n = q->read(buffer, 16)) > 0) {for (int i=0 ; i<n ; i++) {if (buffer[i].type == SENSOR_TYPE_STEP_COUNTER) {// step-counter returns a uint64, but the java API only deals with floatsfloat value = float(buffer[i].u64.step_counter);env->SetFloatArrayRegion(mFloatScratch, 0, 1, &value);} else if (buffer[i].type == SENSOR_TYPE_DYNAMIC_SENSOR_META) {float value[2];value[0] = buffer[i].dynamic_sensor_meta.connected ? 1.f: 0.f;value[1] = float(buffer[i].dynamic_sensor_meta.handle);env->SetFloatArrayRegion(mFloatScratch, 0, 2, value);} else if (buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {env->SetIntArrayRegion(mIntScratch, 0, 14,buffer[i].additional_info.data_int32);env->SetFloatArrayRegion(mFloatScratch, 0, 14,buffer[i].additional_info.data_float);} else {env->SetFloatArrayRegion(mFloatScratch, 0, 16, buffer[i].data);}if (buffer[i].type == SENSOR_TYPE_META_DATA) {// This is a flush complete sensor event. Call dispatchFlushCompleteEvent// method.if (receiverObj.get()) {env->CallVoidMethod(receiverObj.get(),gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,buffer[i].meta_data.sensor);}} else if (buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {// This is a flush complete sensor event. Call dispatchAdditionalInfoEvent// method.if (receiverObj.get()) {int type = buffer[i].additional_info.type;int serial = buffer[i].additional_info.serial;env->CallVoidMethod(receiverObj.get(),gBaseEventQueueClassInfo.dispatchAdditionalInfoEvent,buffer[i].sensor,type, serial,mFloatScratch,mIntScratch,buffer[i].timestamp);}}else {int8_t status;switch (buffer[i].type) {case SENSOR_TYPE_ORIENTATION:case SENSOR_TYPE_MAGNETIC_FIELD:case SENSOR_TYPE_ACCELEROMETER:case SENSOR_TYPE_GYROSCOPE:case SENSOR_TYPE_GRAVITY:case SENSOR_TYPE_LINEAR_ACCELERATION:status = buffer[i].vector.status;break;case SENSOR_TYPE_HEART_RATE:status = buffer[i].heart_rate.status;break;default:status = SENSOR_STATUS_ACCURACY_HIGH;break;}// 通过jni回调SystemSensorManager::dispatchSensorEvent(),将数据给SensorManagerif (receiverObj.get()) {env->CallVoidMethod(receiverObj.get(),gBaseEventQueueClassInfo.dispatchSensorEvent,buffer[i].sensor,mFloatScratch,status,buffer[i].timestamp);}}if (env->ExceptionCheck()) {mSensorQueue->sendAck(buffer, n);ALOGE("Exception dispatching input event.");return 1;}}mSensorQueue->sendAck(buffer, n);}if (n<0 && n != -EAGAIN) {// FIXME: error receiving events, what to do in this case?}return 1;}

C++ Framework (Native)

SensorService.cpp

frameworks/native/services/sensorservice/SensorService.cpp
SensorService 是 Android Sensor Framework 最核心的模块,它实现了主要的 Sensor控制流和数据流逻辑,完成 Sensor 参数配置,数据分发,Client 请求处理等功能。

SensorService继承自BinderService,启动publish

frameworks/native/services/sensorservice/SensorService.h

class SensorService :public BinderService<SensorService>,public BnSensorServer,protected Thread
{

继承BnSensorServer:frameworks/native/libs/sensor/include/sensor/ISensorServer.h
继承Thread

frameworks/native/libs/binder/include/binder/BinderService.h

template<typename SERVICE>
class BinderService
{public:static status_t publish(bool allowIsolated = false,int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) {sp<IServiceManager> sm(defaultServiceManager());return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated,dumpFlags);}

SERVICE:模板声明是SensorService
defaultServiceManager: 获取ServiceManager对象。
SERVICE::getServiceName():SensorService加入到ServiceManager的key “sensorservice”
new SERVICE():new一个SensorService,然后 以 “sensorservice”为key,把sensorservice实例加入到ServiceManaer

BinderService 是 Android Service 框架的主要类,是个模板类,它提供了 Service 的生命周期管理、进程间通信、请求响应处理等功能。Android 中的绝大部分 Service 都会继承此类。

SensorService 实例创建

当 SensorService 第一个实例创建时,其 onFirstRef 接口将会被调用

void SensorService::onFirstRef() {// ① 在 SensorDevice 的构造函数中,会调用 hw_get_module 接口加载 Sensor HAL 的动态库SensorDevice& dev(SensorDevice::getInstance());//.......if (dev.initCheck() == NO_ERROR) {// ② 通过 SensorDevice,调用 Sensor HAL 提供的 get_sensors_list 接口,获取所支持的 Sensor 信息获,调用registerSensor函数把Sensor保存起来sensor_t const* list;ssize_t count = dev.getSensorList(&list);//.......for (ssize_t i=0 ; i<count ; i++) {//.......if (useThisSensor) {registerSensor( new HardwareSensor(list[i]) );}}
// ③ SensorFusion功能,传感融合。它的主要作用就是,按照一定的算法计算系统的多个传感器对某一个值的上报的数据,得到更准确的值。// it's safe to instantiate the SensorFusion object here// (it wants to be instantiated after h/w sensors have been// registered)SensorFusion::getInstance();
// ④ 注册虚拟传感器:这些虚拟的传感器步会产生真的数据,而是通过SensorFusion功能计算得到的值,作为虚拟传感的数据。//.......registerSensor(new RotationVectorSensor(), !needRotationVector, true);registerSensor(new OrientationSensor(), !needRotationVector, true);registerSensor(new LinearAccelerationSensor(list, count),!needLinearAcceleration, true);registerSensor( new CorrectedGyroSensor(list, count), true, true);registerSensor( new GyroDriftSensor(), true, true);//.......registerSensor(new GravitySensor(list, count), !needGravitySensor, true);//.......registerSensor(new GameRotationVectorSensor(), !needGameRotationVector, true);//.......registerSensor(new GeoMagRotationVectorSensor(), !needGeoMagRotationVector, true);//.......
// ⑤ 初始化一些Buffer,用他们保存sensor硬件上报的数据mLooper = new Looper(false);const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;mSensorEventBuffer = new sensors_event_t[minBufferSize];mSensorEventScratch = new sensors_event_t[minBufferSize];mMapFlushEventsToConnections = new wp<const SensorEventConnection> [minBufferSize];mCurrentOperatingMode = NORMAL;//.......
⑥ 创建一个 Looper 和 SensorEventAckReceiver。其中 Looper 用于 enable sensor 后,进行数据的接收;而 SensorEventAckReceiver 则用于在 dispatch wake up sensor event 给上层后,接收上层返回的确认 ACK。mAckReceiver = new SensorEventAckReceiver(this);mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);
// ⑦ SensorService 不仅是一个服务,而且他还是一个线程,初始化工作的最后就是启动该线程执行threadLoop函数。threadLoop函数主要的工作就是,循环读取sensor硬件上传上来的数据,然后分发给应用。run("SensorService", PRIORITY_URGENT_DISPLAY); //.......
}

① 在 SensorDevice 的构造函数中,会调用 hw_get_module 接口加载 Sensor HAL 的动态库
② 通过 SensorDevice,调用 Sensor HAL 提供的 get_sensors_list 接口,获取所支持的 Sensor 信息获,调用registerSensor函数把Sensor保存起来
③ SensorFusion功能,传感融合。它的主要作用就是,按照一定的算法计算系统的多个传感器对某一个值的上报的数据,得到更准确的值。
④ registerSensor (…, …, true)注册虚拟传感器:这些虚拟的传感器步会产生真的数据,而是通过SensorFusion功能计算得到的值,作为虚拟传感的数据。分发过程中会有分析到。
⑤ 初始化一些Buffer,用他们保存sensor硬件上报的数据
⑥ 创建一个 Looper 和 SensorEventAckReceiver。其中 Looper 用于 enable sensor 后,进行数据的接收;而 SensorEventAckReceiver 则用于在 dispatch wake up sensor event 给上层后,接收上层返回的确认 ACK。
⑦ SensorService 不仅是一个服务,而且他还是一个线程,初始化工作的最后就是启动该线程执行threadLoop函数。threadLoop函数主要的工作就是,循环读取sensor硬件上传上来的数据,然后分发给应用。

SensorService::threadLoop()

bool SensorService::threadLoop() {ALOGD("nuSensorService thread starting...");// each virtual sensor could generate an event per "real" event, that's why we need to size// numEventMax much smaller than MAX_RECEIVE_BUFFER_EVENT_COUNT.  in practice, this is too// aggressive, but guaranteed to be enough.const size_t vcount = mSensors.getVirtualSensors().size();const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;const size_t numEventMax = minBufferSize / (1 + vcount);SensorDevice& device(SensorDevice::getInstance());const int halVersion = device.getHalDeviceVersion();do {ssize_t count = device.poll(mSensorEventBuffer, numEventMax);//①if (count < 0) {if(count == DEAD_OBJECT && device.isReconnecting()) {device.reconnect();continue;} else {ALOGE("sensor poll failed (%s)", strerror(-count));break;}}// Reset sensors_event_t.flags to zero for all events in the buffer.for (int i = 0; i < count; i++) {mSensorEventBuffer[i].flags = 0;}ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);// Poll has returned. Hold a wakelock if one of the events is from a wake up sensor. The// rest of this loop is under a critical section protected by mLock. Acquiring a wakeLock,// sending events to clients (incrementing SensorEventConnection::mWakeLockRefCount) should// not be interleaved with decrementing SensorEventConnection::mWakeLockRefCount and// releasing the wakelock.uint32_t wakeEvents = 0;for (int i = 0; i < count; i++) {if (isWakeUpSensorEvent(mSensorEventBuffer[i])) {wakeEvents++;}}if (wakeEvents > 0) {if (!mWakeLockAcquired) {setWakeLockAcquiredLocked(true);}device.writeWakeLockHandled(wakeEvents);}recordLastValueLocked(mSensorEventBuffer, count);// handle virtual sensorsif (count && vcount) {sensors_event_t const * const event = mSensorEventBuffer;if (!mActiveVirtualSensors.empty()) {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 (int handle : mActiveVirtualSensors) {if (count + k >= minBufferSize) {ALOGE("buffer too small to hold all events: ""count=%zd, k=%zu, size=%zu",count, k, minBufferSize);break;}sensors_event_t out;sp<SensorInterface> si = mSensors.getInterface(handle);if (si == nullptr) {ALOGE("handle %d is not an valid virtual sensor", handle);continue;}if (si->process(&out, event[i])) {mSensorEventBuffer[count + k] = out;k++;}}}if (k) {// record the last synthesized valuesrecordLastValueLocked(&mSensorEventBuffer[count], k);count += k;// sort the buffer by time-stampssortEventBuffer(mSensorEventBuffer, count);}}}// handle backward compatibility for RotationVector sensorif (halVersion < SENSORS_DEVICE_API_VERSION_1_0) {for (int i = 0; i < count; i++) {if (mSensorEventBuffer[i].type == SENSOR_TYPE_ROTATION_VECTOR) {// All the 4 components of the quaternion should be available// No heading accuracy. Set it to -1mSensorEventBuffer[i].data[4] = -1;}}}// Cache the list of active connections, since we use it in multiple places below but won't// modify it hereconst std::vector<sp<SensorEventConnection>> activeConnections = connLock.getActiveConnections();for (int i = 0; i < count; ++i) {// Map flush_complete_events in the buffer to SensorEventConnections which called flush// on the hardware sensor. mapFlushEventsToConnections[i] will be the// SensorEventConnection mapped to the corresponding flush_complete_event in// mSensorEventBuffer[i] if such a mapping exists (NULL otherwise).mMapFlushEventsToConnections[i] = nullptr;if (mSensorEventBuffer[i].type == SENSOR_TYPE_META_DATA) {const int sensor_handle = mSensorEventBuffer[i].meta_data.sensor;SensorRecord* rec = mActiveSensors.valueFor(sensor_handle);if (rec != nullptr) {mMapFlushEventsToConnections[i] = rec->getFirstPendingFlushConnection();rec->removeFirstPendingFlushConnection();}}// handle dynamic sensor meta events, process registration and unregistration of dynamic// sensor based on content of event.if (mSensorEventBuffer[i].type == SENSOR_TYPE_DYNAMIC_SENSOR_META) {if (mSensorEventBuffer[i].dynamic_sensor_meta.connected) {int handle = mSensorEventBuffer[i].dynamic_sensor_meta.handle;const sensor_t& dynamicSensor =*(mSensorEventBuffer[i].dynamic_sensor_meta.sensor);ALOGI("Dynamic sensor handle 0x%x connected, type %d, name %s",handle, dynamicSensor.type, dynamicSensor.name);if (mSensors.isNewHandle(handle)) {const auto& uuid = mSensorEventBuffer[i].dynamic_sensor_meta.uuid;sensor_t s = dynamicSensor;// make sure the dynamic sensor flag is sets.flags |= DYNAMIC_SENSOR_MASK;// force the handle to be consistents.handle = handle;SensorInterface *si = new HardwareSensor(s, uuid);// This will release hold on dynamic sensor meta, so it should be called// after Sensor object is created.device.handleDynamicSensorConnection(handle, true /*connected*/);registerDynamicSensorLocked(si);} else {ALOGE("Handle %d has been used, cannot use again before reboot.", handle);}} else {int handle = mSensorEventBuffer[i].dynamic_sensor_meta.handle;ALOGI("Dynamic sensor handle 0x%x disconnected", handle);device.handleDynamicSensorConnection(handle, false /*connected*/);if (!unregisterDynamicSensorLocked(handle)) {ALOGE("Dynamic sensor release error.");}for (const sp<SensorEventConnection>& connection : activeConnections) {connection->removeSensor(handle);}}}}// Send our events to clients. Check the state of wake lock for each client and release the// lock if none of the clients need it.bool needsWakeLock = false;for (const sp<SensorEventConnection>& connection : activeConnections) {connection->sendEvents(mSensorEventBuffer, count, mSensorEventScratch,mMapFlushEventsToConnections); //②needsWakeLock |= connection->needsWakeLock();// If the connection has one-shot sensors, it may be cleaned up after first trigger.// Early check for one-shot sensors.if (connection->hasOneShotSensors()) {cleanupAutoDisabledSensorLocked(connection, mSensorEventBuffer, count);}}if (mWakeLockAcquired && !needsWakeLock) {setWakeLockAcquiredLocked(false);}} while (!Thread::exitPending());ALOGW("Exiting SensorService::threadLoop => aborting...");abort();return false;
}

①通过poll往hal层取sensor数据, 若没有数据的时候就一直阻塞(该阻塞功能由HAL层实现),当有数据时该函数就会返回
②通过SensorEventConnection 将数据给到每个应用,每个应用都有自己的SensorEventConnection

frameworks/native/services/sensorservice/SensorEventConnection.cpp
SensorService::SensorEventConnection::sendEvents()来将数据进一步处理并 SensorEventQueue::write 发送,这边请注意有多个SensorEventConnection各属于不同应用

SensorManager.cpp创建SensorEventQueue

frameworks/native/libs/sensor/SensorManager.cpp

应用注册sensor监听时,SystemSensorManager.java创建一个java类SensorEventQueue,这里再去创建c++类SensorEventQueue,当sensor数据到来时,SensorEventQueue会通过回调应用实现的onSensorChanged()接口而将数据给到应用,

sp<SensorEventQueue> SensorManager::createEventQueue(String8 packageName, int mode) {sp<SensorEventQueue> queue;Mutex::Autolock _l(mLock);while (assertStateLocked() == NO_ERROR) {sp<ISensorEventConnection> connection =mSensorServer->createSensorEventConnection(packageName, mode, mOpPackageName);if (connection == nullptr) {// SensorService just died or the app doesn't have required permissions.ALOGE("createEventQueue: connection is NULL.");return nullptr;}queue = new SensorEventQueue(connection);break;}return queue;
}

1、SensorService请求创建connection,最后调用 SensorService::createSensorEventConnection()
2、SensorEventConnection传递给SensorEventQueue构造函数,创建SensorEventQueue

SensorEventQueue.cpp

frameworks/native/libs/sensor/SensorEventQueue.cpp

SensorEventQueue::SensorEventQueue(const sp<ISensorEventConnection>& connection): mSensorEventConnection(connection), mRecBuffer(nullptr), mAvailable(0), mConsumed(0),mNumAcksToSend(0) {mRecBuffer = new ASensorEvent[MAX_RECEIVE_BUFFER_EVENT_COUNT];
}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) {if (mAvailable == 0) {ssize_t err = BitTube::recvObjects(mSensorChannel,mRecBuffer, MAX_RECEIVE_BUFFER_EVENT_COUNT);if (err < 0) {return err;}mAvailable = static_cast<size_t>(err);mConsumed = 0;}size_t count = min(numEvents, mAvailable);memcpy(events, mRecBuffer + mConsumed, count * sizeof(ASensorEvent));mAvailable -= count;mConsumed += count;return static_cast<ssize_t>(count);
}

创建mRecBuffer,用来存从SensorEventConnection发送过来的数据,
SensorEventQueue::write()用来给SensorEventConnection发送数据,
SensorEventQueue::read()用来读取数据给应用

frameworks/native/libs/sensor/BitTube.cpp

ssize_t BitTube::sendObjects(const sp<BitTube>& tube,void const* events, size_t count, size_t objSize)
{const char* vaddr = reinterpret_cast<const char*>(events);ssize_t size = tube->write(vaddr, count*objSize);// should never happen because of SOCK_SEQPACKETLOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)),"BitTube::sendObjects(count=%zu, size=%zu), res=%zd (partial events were sent!)",count, objSize, size);//ALOGE_IF(size<0, "error %d sending %d events", size, count);return size < 0 ? size : size / static_cast<ssize_t>(objSize);
}ssize_t BitTube::write(void const* vaddr, size_t size)
{ssize_t err, len;do {len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL);//这边通过 socket 域套接字发出去// cannot return less than size, since we're using SOCK_SEQPACKETerr = len < 0 ? errno : 0;} while (err == EINTR);return err == 0 ? len : -err;
}

通过 socket 域套接字发出去,JNI层 Receiver对象里的 BitTube 里边mReceiveFd接收

SensorEventConnection

frameworks/native/services/sensorservice/SensorEventConnection.cpp

SensorEventConnection 是基于 Bittube 实现的。主要是是 Sensor 数据的传输通道,当 Client 开始监听某一个 Sensor 是,一个对应的 SensorEventConnection 将会被创建,Server 端在接收到 Sensor 数据后,通过写入到 SensorEventConnection 传递给 Client 端。通过socket进行通信。
一个应用拥有多少个SensorEventConnection,取决于应用创建多少个SensorEventListerner,
可能有的应用开发者注册多个sensor时,只创建一个SensorEventListerner,然后在onSensorChanged()里边做类型区分,
有的一个sensor一个SensorEventListerner,从性能的角度考虑建议一个应用创建一个SensorEventListerner就够了,毕竟每创建一个,就要新建立一个socket连接,多一个poll去等待数据。

SensorService::SensorEventConnection::SensorEventConnection(const sp<SensorService>& service, uid_t uid, String8 packageName, bool isDataInjectionMode,const String16& opPackageName, bool hasSensorAccess): mService(service), mUid(uid), mWakeLockRefCount(0), mHasLooperCallbacks(false),mDead(false), mDataInjectionMode(isDataInjectionMode), mEventCache(nullptr),mCacheSize(0), mMaxCacheSize(0), mTimeOfLastEventDrop(0), mEventsDropped(0),mPackageName(packageName), mOpPackageName(opPackageName), mDestroyed(false),mHasSensorAccess(hasSensorAccess) {mChannel = new BitTube(mService->mSocketBufferSize);
#if DEBUG_CONNECTIONSmEventsReceived = mEventsSentFromCache = mEventsSent = 0;mTotalAcksNeeded = mTotalAcksReceived = 0;
#endif
}

SensorDevice.cpp

frameworks/native/services/sensorservice/SensorDevice.cpp
该类负责管理和维护系统中的所有 Sensor,封装了 Sensor 的使能、配置、数据读取等功能。

SensorDevice::SensorDevice(): mHidlTransportErrors(20),mRestartWaiter(new HidlServiceRegistrationWaiter()),mEventQueueFlag(nullptr),mWakeLockQueueFlag(nullptr),mReconnecting(false) {if (!connectHidlService()) {return;}initializeSensorList();mIsDirectReportSupported =(checkReturnAndGetStatus(mSensors->unregisterDirectChannel(-1)) != INVALID_OPERATION);
}void SensorDevice::initializeSensorList() {float minPowerMa = 0.001; // 1 microAmpcheckReturn(mSensors->getSensorsList([&](const auto &list) {const size_t count = list.size();mActivationCount.setCapacity(count);Info model;for (size_t i=0 ; i < count; i++) {sensor_t sensor;convertToSensor(list[i], &sensor);// Sanity check and clamp power if it is 0 (or close)if (sensor.power < minPowerMa) {ALOGI("Reported power %f not deemed sane, clamping to %f",sensor.power, minPowerMa);sensor.power = minPowerMa;}mSensorList.push_back(sensor);mActivationCount.add(list[i].sensorHandle, model);checkReturn(mSensors->activate(list[i].sensorHandle, 0 /* enabled */));}}));
}

SensorDevice继承了Singleton类,设计成单例,用getinstance()的方式调用

connectHidlService()

SensorDevice是实际上与HAL层直接进行交互的类,通过hidl与
sensor在HAL层的服务建立连接(这边所指的HAL层只是指google实现的那部分,
即: android.hardware.sensors@1.0-service,这一层通过dlopen(),会调用第三方如芯片厂商,
手机厂商,开发者等实现的SO库,实际上这些都应该统称为HAL层)。
 
关键性的成员 :
sp<V2_0::ISensors> sensors = V2_0::ISensors::getService();
sp<V1_0::ISensors> sensors = V1_0::ISensors::getService();

bool SensorDevice::connectHidlService() {HalConnectionStatus status = connectHidlServiceV2_0();if (status == HalConnectionStatus::DOES_NOT_EXIST) {status = connectHidlServiceV1_0();}return (status == HalConnectionStatus::CONNECTED);
}SensorDevice::HalConnectionStatus SensorDevice::connectHidlServiceV1_0() {// SensorDevice will wait for HAL service to start if HAL is declared in device manifest.size_t retry = 10;HalConnectionStatus connectionStatus = HalConnectionStatus::UNKNOWN;while (retry-- > 0) {sp<V1_0::ISensors> sensors = V1_0::ISensors::getService();if (sensors == nullptr) {// no sensor hidl service foundconnectionStatus = HalConnectionStatus::DOES_NOT_EXIST;break;}mSensors = new SensorServiceUtil::SensorsWrapperV1_0(sensors);mRestartWaiter->reset();// Poke ISensor service. If it has lingering connection from previous generation of// system server, it will kill itself. There is no intention to handle the poll result,// which will be done since the size is 0.if(mSensors->poll(0, [](auto, const auto &, const auto &) {}).isOk()) {// ok to continueconnectionStatus = HalConnectionStatus::CONNECTED;break;}// hidl service is restarting, pointer is invalid.mSensors = nullptr;connectionStatus = HalConnectionStatus::FAILED_TO_CONNECT;ALOGI("%s unsuccessful, remaining retry %zu.", __FUNCTION__, retry);mRestartWaiter->wait();}return connectionStatus;
}SensorDevice::HalConnectionStatus SensorDevice::connectHidlServiceV2_0() {HalConnectionStatus connectionStatus = HalConnectionStatus::UNKNOWN;sp<V2_0::ISensors> sensors = V2_0::ISensors::getService();if (sensors == nullptr) {connectionStatus = HalConnectionStatus::DOES_NOT_EXIST;} else {mSensors = new SensorServiceUtil::SensorsWrapperV2_0(sensors);mEventQueue = std::make_unique<EventMessageQueue>(SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT,true /* configureEventFlagWord */);mWakeLockQueue = std::make_unique<WakeLockQueue>(SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT,true /* configureEventFlagWord */);hardware::EventFlag::deleteEventFlag(&mEventQueueFlag);hardware::EventFlag::createEventFlag(mEventQueue->getEventFlagWord(), &mEventQueueFlag);hardware::EventFlag::deleteEventFlag(&mWakeLockQueueFlag);hardware::EventFlag::createEventFlag(mWakeLockQueue->getEventFlagWord(),&mWakeLockQueueFlag);CHECK(mSensors != nullptr && mEventQueue != nullptr &&mWakeLockQueue != nullptr && mEventQueueFlag != nullptr &&mWakeLockQueueFlag != nullptr);status_t status = checkReturnAndGetStatus(mSensors->initialize(*mEventQueue->getDesc(),*mWakeLockQueue->getDesc(),new SensorsCallback()));if (status != NO_ERROR) {connectionStatus = HalConnectionStatus::FAILED_TO_CONNECT;ALOGE("Failed to initialize Sensors HAL (%s)", strerror(-status));} else {connectionStatus = HalConnectionStatus::CONNECTED;mSensorsHalDeathReceiver = new SensorsHalDeathReceivier();sensors->linkToDeath(mSensorsHalDeathReceiver, 0 /* cookie */);}}return connectionStatus;
}

传感器 HAL 2.0
传感器硬件抽象层 (HAL) 是 Android 传感器框架与设备传感器(如加速度计或陀螺仪)之间的接口。传感器 HAL 定义了一系列函数,要使传感器框架能够控制传感器,必须先实现这些函数。

传感器 HAL 2.0 适用于搭载 Android 10 及更高版本的新设备和升级设备。传感器 HAL 2.0 基于传感器 HAL 1.0 构建,但与 1.0 版有几个关键的区别,这使得它无法向后兼容。传感器 HAL 2.0 使用快速消息队列 (FMQ) 将传感器事件从 HAL 发送到 Android 传感器框架。

传感器 HAL 1.0
sensors.h 中声明的传感器 HAL 接口表示 Android 框架与硬件专用软件之间的接口。HAL 实现必须定义 sensors.h 中声明的每个函数。
主要函数如下:

  • get_sensors_list - 返回所有传感器的列表。
  • activate - 启动或停止传感器。
  • batch - 设置传感器的参数,如采样率和最大报告延迟。
  • setDelay - 仅用于 1.0 版本的 HAL。设置指定传感器的采样率。
  • flush - 清空指定传感器的 FIFO 并在完成后报告清空完成事件。
  • poll - 返回可用的传感器事件。

实现必须是线程安全的,并且允许从不同线程调用这些函数。

该接口还定义了这些函数使用的几个类型。主要类型如下:

  • sensors_module_t
  • sensors_poll_device_t
  • sensor_t
  • sensors_event_t

sensors.h: hardware/libhardware/include/hardware/sensors.h
sensors.cpp: hardware/libhardware/modules/sensors/dynamic_sensor/sensors.cpp

Sensor HAL

Sensors Hardware Abstraction Layer (HAL) API 是硬件驱动程序和 Android 框架之间的接口。它包含一个 HAL 接口 sensors.h 和一个我们称之为 sensors.cpp 的 HAL 实现。

接口由 Android 和 AOSP 贡献者定义,并由设备制造商提供实现。

传感器 HAL 接口位于 hardware/libhardware/include/hardware 中。有关详情,请参阅 sensors.h。

版本周期

HAL 实现通过设置 your_poll_device.common.version 指定实现的 HAL 接口版本。现有的 HAL 接口版本在 sensors.h 中有所定义,相应功能与这些版本绑定在一起。

Android 框架目前支持版本 1.0 和 1.3,不过版本 1.0 很快将不再受支持。本文档介绍了版本 1.3(所有设备均应升级到该版本)的行为。要详细了解如何升级到版本 1.3,请参阅 HAL 版本弃用。

内核驱动程序

传感器驱动程序可与物理设备进行交互。在某些情况下,HAL 实现和驱动程序是同一软件实体。在其他情况下,硬件集成者会要求传感器芯片制造商提供相应驱动程序,但是它们是用于编写 HAL 实现的驱动程序。

在所有情况下,HAL 实现和内核驱动程序都由硬件制造商负责提供,Android 不提供首选编写方式。

传感器中枢

设备的传感器堆栈可视需要添加传感器中枢。在 SoC 可以处于暂停模式时,传感器中枢对执行一些低功耗的低级计算任务非常有用。例如,计步功能或传感器融合功能可以在这些芯片上执行。此外,它也是实施传感器批处理以及为传感器事件添加硬件 FIFO 的理想位置。有关详情,请参阅批处理。

传感器中枢的具体化方式取决于架构。它有时是一个单独的芯片,有时包含在与 SoC 相同的芯片上。传感器中枢的重要特征是,应该包含足够的内存来进行批处理,并消耗极少的电量以便能实现低功耗 Android 传感器。部分传感器中枢包含一个微控制器(用于通用计算)和硬件加速器(用于针对低电耗传感器实现极低功耗计算)。

传感器中枢的架构方式以及与传感器和 SoC(I2C 总线、SPI 总线等)的通信方式并非由 Android 指定,但应该以最大程度减少整体功耗为目标。

有一种方案似乎会对实现的简单性产生重大影响,即从传感器中枢到 SoC 设置两个中断行:一个用于唤醒中断(适用于唤醒传感器),另一个用于非唤醒中断(适用于非唤醒传感器)。

传感器

传感器是进行测量操作的物理 MEM 芯片。在很多情况下,同一个芯片上会有多个物理传感器。例如,一些芯片中包含加速度计、陀螺仪和磁力计(此类芯片通常称为 9 轴芯片,因为每个传感器基于 3 个轴提供数据)。

此外,其中的部分芯片还包含用于执行常见计算任务(例如运动状态检测、步数检测以及 9 轴传感器融合)的逻辑。

尽管 CDD 功率和精确度的要求与建议针对的是 Android 传感器而非物理传感器,但这些要求会影响物理传感器的选择。例如,游戏旋转矢量传感器的精确度要求会影响物理陀螺仪的精确度要求。设备制造商负责推算物理传感器的相关要求。

Android Sensor Framework 流程

其他资料:

https://blog.csdn.net/goodnight1994/article/details/80259375
https://blog.csdn.net/goodnight1994/article/details/97503586
https://blog.csdn.net/huilin9960/article/details/80654647

Android Sensor 概览相关推荐

  1. Android Sensor 传感器总结

    ref:https://www.jianshu.com/p/8440a5897944 https://developer.android.google.cn/guide/topics/sensors/ ...

  2. pm1 android,Android Sensor SDK

    Android Sensor SDK Step By Step 1.新建工程 Android Studio配置 将sensoro-sensor-kit.jar包放入道libs文件夹下,然后在当前工程下 ...

  3. Android Sensor Framework(狠详)

    1. Overview Android Sensor Framework 的整体架构如图 1 所示: 图片 1 Android Sensor Framework 可以分为 3 大部分,各个部分的主要功 ...

  4. Android Sensor分析

    Android Sensor分析 目标:检测device的状态 非法状态关闭光机 非法移动关闭手势 步骤分为三步: 1.sensor移植(accelerometer and gyro) 2.frame ...

  5. Google Android Sensor -- 004 -- 耗电量

    文章目录 耗电量 低功耗传感器 功耗测量过程 说明:Sensor 系列文章请参考 Android Sensor.此篇搬运自 android官方网站 power-use 耗电量   低功耗传感器 部分传 ...

  6. android Sensor 驱动编写--opt3001光感驱动为例

    分析Android sensor Android sensor Framework 层以及APP如何读取sensor 数据.网上有很多文章不再累述. 由于我使用的是Android 5.1(kernel ...

  7. Android Sensor Development

    Android Sensor Development 本文我们说一下Android中的传感器,这对于我们有时候做一些特殊的应用的时候还是需要的,这里我用小米手机下载了一个安兔兔,我们来看下大致的传感器 ...

  8. 【Based Android】Android Sensor感应器介绍(二)线程中刷新UI 创建一个android测力计...

    上一篇文章http://www.cnblogs.com/octobershiner/archive/2011/11/06/2237880.html介绍了sensor的基本知识以及一个使用其中加速度感应 ...

  9. Android Sensor——传感器

    Android SDK 支持的传感器类型,在Sensor类中的定义: 01.TYPE_ACCELEROMETER  : 加速传感器(硬件) 02.TYPE_AMBIENT_TEMPERATURE : ...

最新文章

  1. 报错:该字符串未被识别为有效的DateTime
  2. 计算机控制z变换例题,计算机控制习题答案.doc
  3. vmstat参数解释
  4. [git]git相关
  5. C# WPF Application 下的文件操作
  6. 数据类型即其相互转换
  7. Windows环境下 node 取消 npm install 采用软连接引用node_modules
  8. Halcon和Opencv区别
  9. Sqlserver交叉连接cross join(笛卡尔积)
  10. win10易升_史上最稳定的win10版本,四大更新内容强势来袭,你敢升级吗?
  11. 图解电动汽车:电动汽车的分类
  12. 搜索python设计题的微信公众号_appium+python自动化42-微信公众号 (可能以后会遇到也遇到切换不了webview的问题 记录再此 还没试)...
  13. 33岁跳槽无路,走投无路之际受贵人指点,成功上岸阿里(Java岗)
  14. uniapp中使用iconfont多色图标
  15. 捕获海康威视IPCamera图像,转成OpenCV可以处理的图像(二)
  16. 行业研究-全球与中国牙科电子病历软件市场现状及未来发展趋势
  17. surfacepro3运行C语言,终于等来USB-C接口!微软 发布 Surface Pro 7 与 Surface Laptop 3 笔记本电脑...
  18. STM32学习笔记1-软件安装
  19. 去大厂面试又栽了,败在了算法的理论面试...
  20. (强烈推荐)移动端音视频从零到上手

热门文章

  1. 手把手教你申请IDEA终极版的许可证
  2. qt emit是什么意思_2020年9月25日 无赞赏QT吗哪 :藐视神的话语也必被藐视
  3. 怎么看电脑的hdmi是输出还是输入_【电脑切换hdmi信号】电脑切换hdmi模式_电脑hdmi输出设置...
  4. 在虚拟机中对阿克曼转向车进行导航及避障的仿真测试
  5. 集合的遍历之迭代器遍历
  6. 微型计算机系统中微处理器又称为什么,微处理器又称为什么
  7. 批改网如何进行复制粘贴
  8. 【多道批处理系统】计算完成两个作业需要的最少时间,并图文叙述
  9. 图片分辨率太低怎么调高?如何更改照片分辨率?
  10. 数据分析36计(15):这个序贯检验方法让 A/B 实验节约一半样本量