Android Sensor 概覽

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;

    @Override
    public 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);
    }

    @Override
    public final void onAccuracyChanged(Sensor sensor, int accuracy) {
        // Do something here if sensor accuracy changes.
    }

    @Override
    public final void onSensorChanged(SensorEvent event) {
        float distance = event.values[0];
        // Do something with this sensor data.
    }

    @Override
    protected void onResume() {
        // Register a listener for the sensor.
        super.onResume();
        sensorManager.registerListener(this, proximity, SensorManager.SENSOR_DELAY_NORMAL);
      }

    @Override
    protected 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;

        @Override
        public 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);
        }

        @Override
        public final void onAccuracyChanged(Sensor sensor, int accuracy) {
          // Do something here if sensor accuracy changes.
        }

        @Override
        public final void onSensorChanged(SensorEvent event) {
          float millibarsOfPressure = event.values[0];
          // Do something with this sensor data.
        }

        @Override
        protected void onResume() {
          // Register a listener for the sensor.
          super.onResume();
          sensorManager.registerListener(this, pressure, SensorManager.SENSOR_DELAY_NORMAL);
        }

        @Override
        protected 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接口,啓動SensorService
            traceLog.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>() {
            @Override
            public 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 list
        for (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 looper
        synchronized (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;
        }

        @Override
        public void addSensorEvent(Sensor sensor) {
            SensorEvent t = new SensorEvent(Sensor.getMaxLengthValuesArray(sensor,
                    mManager.mTargetSdkLevel));
            synchronized (mSensorsEvents) {
                mSensorsEvents.put(sensor.getHandle(), t);
            }
        }

        @Override
        public void removeSensorEvent(Sensor sensor) {
            synchronized (mSensorsEvents) {
                mSensorsEvents.delete(sensor.getHandle());
            }
        }

        // Called from native code.
        @SuppressWarnings("unused")
        @Override
        protected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,
                long timestamp) {
            final Sensor sensor = mManager.mHandleToSensor.get(handle);
            if (sensor == null) {
                // sensor disconnected
                return;
            }

            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 changes
            final 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")
        @Override
        protected void dispatchFlushCompleteEvent(int handle) {
            if (mListener instanceof SensorEventListener2) {
                final Sensor sensor = mManager.mHandleToSensor.get(handle);
                if (sensor == null) {
                    // sensor disconnected
                    return;
                }
                ((SensorEventListener2) mListener).onFlushCompleted(sensor);
            }
            return;
        }

        // Called from native code.
        @SuppressWarnings("unused")
        @Override
        protected 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 disconnected
                    return;
                }
                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 set
            return mActiveSensors.indexOfValue(true) >= 0;
        }

        @Override
        protected 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());
        }
        @UnsupportedAppUsage
        protected abstract void dispatchSensorEvent(int handle, float[] values, int accuracy,
                long timestamp);
        @UnsupportedAppUsage
        protected abstract void dispatchFlushCompleteEvent(int handle);

        @UnsupportedAppUsage
        protected 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 只會調用一次),包括名稱、類型等參數。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Z8H1Yrs8-1591458897694)(http://kernel.meizu.com/images/posts/2016/05/android_sensor_framework_5.png)]

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.Sensor
    SensorOffsets& 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 intern
    StringOffsets& 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)); //創建SensorEventQueue

    if (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 floats
                    float 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(),將數據給SensorManager
                    if (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功能,傳感融合。它的主要作用就是,按照一定的算法計算系統的多個傳感器對某一個值的上報的數據,得到更準確的值。
④ registerVirtualSensor註冊虛擬傳感器:這些虛擬的傳感器步會產生真的數據,而是通過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 sensors
        if (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 values
                    recordLastValueLocked(&mSensorEventBuffer[count], k);
                    count += k;
                    // sort the buffer by time-stamps
                    sortEventBuffer(mSensorEventBuffer, count);
                }
            }
        }

        // handle backward compatibility for RotationVector sensor
        if (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 -1
                    mSensorEventBuffer[i].data[4] = -1;
                }
            }
        }

        // Cache the list of active connections, since we use it in multiple places below but won't
        // modify it here
        const 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 set
                        s.flags |= DYNAMIC_SENSOR_MASK;
                        // force the handle to be consistent
                        s.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_SEQPACKET
    LOG_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_SEQPACKET
        err = 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_CONNECTIONS
    mEventsReceived = 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 microAmp

    checkReturn(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實現的那部分,
即: [email protected],這一層通過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 found
            connectionStatus = 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 continue
            connectionStatus = 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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章