Sensor

Sensor輸入子系統

採用了通用的Linux輸入框架,它通過/sys/class/input節點和用戶空間進行交互。

Evdev提供了一種訪問/dev/input/eventX輸入設備事件的通用方法。

系統開機啓動

init 是 zygote的父進程, 而system_server和其他所有的com.xxx結尾的應用程序都是從zygote fork 而來

#init.rc
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
SystemServer 啓動

系統啓動時SystemServer main() 調用android_server_systemserver_nativeInit()

   public static void main(String[] args) {

        /*
         * In case the runtime switched since last boot (such as when
         * the old runtime was removed in an OTA), set the system
         * property so that it is in sync. We can't do this in
         * libnativehelper's JniInvocation::Init code where we already
         * had to fallback to a different runtime because it is
         * running as root and we need to be the system user to set
         * the property. http://b/11463182
         */
        SystemProperties.set("persist.sys.dalvik.vm.lib",
                             VMRuntime.getRuntime().vmLibrary());

        if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
            // If a device's clock is before 1970 (before 0), a lot of
            // APIs crash dealing with negative numbers, notably
            // java.io.File#setLastModified, so instead we fake it and
            // hope that time from cell towers or NTP fixes it
            // shortly.
            Slog.w(TAG, "System clock is before 1970; setting to 1970.");
            SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
        }

        if (SamplingProfilerIntegration.isEnabled()) {
            SamplingProfilerIntegration.start();
            timer = new Timer();
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    SamplingProfilerIntegration.writeSnapshot("system_server", null);
                }
            }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
        }

        // Mmmmmm... more memory!
        dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();

        // The system server has to run all of the time, so it needs to be
        // as efficient as possible with its memory usage.
        VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

        Environment.setUserRequired(true);

        System.loadLibrary("android_servers");

        Slog.i(TAG, "Entered the Android system server!");

        // Initialize native services.
        nativeInit();

        // This used to be its own separate thread, but now it is
        // just the loop we run on the main thread.
        ServerThread thr = new ServerThread();
        thr.initAndLoop();
    }
}
static void android_server_SystemServer_nativeInit(JNIEnv* env, jobject clazz) {
    char propBuf[PROPERTY_VALUE_MAX];
    property_get("system_init.startsensorservice", propBuf, "1");
    if (strcmp(propBuf, "1") == 0) {
        // Start the sensor service
        SensorService::instantiate();
    }
}
systemReady

客戶端實例化PowerManagerService.java中systemReady,初始化SystemSensorManager

SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());

系統開機啓動的時候,會創建SystemSensorManager的實例,在其構造函數中,主要做:

初始化JNI:調用JNI函數nativeClassInit()進行初始化 (android_hardware_SensorManager.cpp)

獲取Sensor列表:調用JNI函數nativeGetNextSensor,對Sensor模塊進行初始化。

創建了native層SensorManager的實例。

    public SystemSensorManager(Context context, Looper mainLooper) {
        mMainLooper = mainLooper;
    mContext = context;
        mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;
        mGsensorDiscard = 0;
        synchronized(sSensorModuleLock) {
            if (!sSensorModuleInitialized) {
                sSensorModuleInitialized = true;

                nativeClassInit();

                // initialize the sensor list
                final ArrayList<Sensor> fullList = sFullSensorsList;
                int i = 0;
                do {
                    Sensor sensor = new Sensor();
                    i = nativeGetNextSensor(sensor, i);
                    if (i>=0) {
                        //Log.d(TAG, "found sensor: " + sensor.getName() +
                        //        ", handle=" + sensor.getHandle());
                        fullList.add(sensor);
                        sHandleToSensor.append(sensor.getHandle(), sensor);
                    }
                } while (i>0);
            }
        }
    }

服務端實現

SensorService初始化

SensorService::onFirstRef()方法,在該方法中完成初始化工作。
  

1.創建SensorDevice實例
2.獲取Sensor列表
3.調用SensorDevice.getSensorList(),獲取Sensor模塊所有傳感器列表
4.爲每個傳感器註冊監聽器

SensorDevice是單例singleton

構造函數 SensorDevice::SensorDevice()

調用HAL層的hw_get_module()方法,加載Sensor模塊so文件
調用sensor.h的sensors_open方法打開設備
調用sensors_poll_device_t->activate()對Sensor模塊使能

在新的線程中讀取HAL層數據

SensorService實現了Thread類,當在onFirstRef中調用run方法後,將在新的線程中調用SensorService::threadLoop()方法

bool SensorService::threadLoop()
{
    ALOGD("nuSensorService thread starting...");
    const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
    const size_t numEventMax = minBufferSize / (1 + mVirtualSensorList.size());
    SensorDevice& device(SensorDevice::getInstance());
    const size_t vcount = mVirtualSensorList.size();
    const int halVersion = device.getHalDeviceVersion();
    do {
        ssize_t count = device.poll(mSensorEventBuffer, numEventMax);//輪詢

APP客戶端 使用方法

SensorManager.java    從android4.1開始,把SensorManager定義爲一個抽象類,定義了一些主要的方法,該類主要是應用層直接使用的類,提供給應用層的接口)

SystemSensorManager.java (這是implement) 應用程序通過獲取其實例,並註冊監聽接 口,獲取sensor數據。

Activity實現了SensorEventListener接口。
  在onCreate方法中,獲取SystemSensorManager,並獲取到加速傳感器的Sensor;
  在onResume方法中調用SystemSensorManager,registerListenerImp
  

Sensor accSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);  
sensorManager.registerListener(this, accSensor, SensorManager.SENSOR_DELAY_NORMAL);  
sensorManager.unregisterListener(this, accSensor);  
//然後在當前Activity中實現以下的兩個函數  
public void onSensorChanged(SensorEvent event)   
public void onAccuracyChanged(Sensor sensor, int accuracy)  

代碼和動態庫so

Framework部分:

frameworks/base/core/Java/Android/hardware/SensorManager.java
frameworks/base/core/jni/android_hardware_sensorManager.cpp

下面的代碼會生成到:libgui.so

frameworks/base/libs/gui/SensorManager.cpp
frameworks/base/libs/gui/SensorEventQueue.cpp
frameworks/base/libs/gui/SensorChannel.cpp
frameworks/base/libs/gui/Sensor.cpp

下面的代碼會生成:libsensorservice.so

frameworks/base/services/sensorservice/SensorService.cpp
frameworks/base/services/sensorservice/SensorDevice.cpp

HAL部分:這部分代碼最終會生成 sensor.default.so 到/system/lib/hw/

hardware/libhardware/include/hardware/Sensors.h
device/qcom/msm7627a/libsensors/Sensors.cpp
device/qcom/msm7627a/libsensors/SensorBase.h
device/qcom/msm7627a/libsensors/AccSensor.cpp
device/qcom/msm7627a/libsensors/ProximitySensor.cpp
device/qcom/msm7627a/libsensors/LightSensor.cpp

安卓的傳感器

安卓的傳感器又可以分爲基於硬件的和基於軟件的。基於硬件的傳感器往往是通過物理組件去實現的,他們通常是通過去測量特殊環境的屬性獲取數據,比如:重力加速度、地磁場強度或方位角度的變化。而基於軟件的傳感器並不依賴物理設備,儘管它們是模仿基於硬件的傳感器的。基於軟件的傳感器通常是通過一個或更多的硬件傳感器獲取數據,並且有時會調用虛擬傳感器或人工傳感器等等,線性加速度傳感器和重力傳感器就是基於軟件傳感器的例子。下面通過官方的一張圖看看安卓平臺支持的所有傳感器類型:

“`
TYPE_ACCELEROMETER
加速度傳感器,單位是m/s2,測量應用於設備X、Y、Z軸上的加速度
傳感器類型值(Sensor Type):1 (0x00000001)

TYPE_AMBIENT_TEMPERATURE
溫度傳感器,單位是℃
傳感器類型值(Sensor Type): 13 (0x0000000d)

TYPE_GAME_ROTATION_VECTOR
遊戲動作傳感器,不收電磁干擾影響
傳感器類型值(Sensor Type):15 (0x0000000f)

TYPE_GEOMAGNETIC_ROTATION_VECTOR
地磁旋轉矢量傳感器,提供手機的旋轉矢量,當手機處於休眠狀態時,仍可以記錄設備的方位
傳感器類型值(Sensor Type):20 (0x00000014)

TYPE_GRAVITY
重力傳感器,單位是m/s2,測量應用於設備X、Y、Z軸上的重力
傳感器類型值(Sensor Type):9 (0x00000009)

TYPE_GYROSCOPE
陀螺儀傳感器,單位是rad/s,測量設備x、y、z三軸的角加速度
傳感器類型值(Sensor Type):4 (0x00000004)

TYPE_GYROSCOPE_UNCALIBRATED
未校準陀螺儀傳感器,提供原始的,未校準、補償的陀螺儀數據,用於後期處理和融合定位數據
傳感器類型值(Sensor Type):16 (0x00000010)

TYPE_LIGHT
光線感應傳感器,單位lx,檢測周圍的光線強度
傳感器類型值(Sensor Type):5 (0x00000005)

TYPE_LINEAR_ACCELERATION
線性加速度傳感器,單位是m/s2,該傳感器是獲取加速度傳感器去除重力的影響得到的數據
傳感器類型值(Sensor Type):10 (0x0000000a)

TYPE_MAGNETIC_FIELD
磁力傳感器,單位是uT(微特斯拉),測量設備周圍三個物理軸(x,y,z)的磁場
傳感器類型值(Sensor Type):2 (0x00000002)

TYPE_MAGNETIC_FIELD_UNCALIBRATED
未校準磁力傳感器,提供原始的,未校準的磁場數據
傳感器類型值(Sensor Type):14 (0x0000000e)

TYPE_ORIENTATION
方向傳感器,測量設備圍繞三個物理軸(x,y,z)的旋轉角度
傳感器類型值(Sensor Type):3 (0x00000003)

TYPE_PRESSURE
壓力傳感器,單位是hPa(百帕斯卡),返回當前環境下的壓強
傳感器類型值(Sensor Type):6 (0x00000006)

TYPE_PROXIMITY
距離傳感器,單位是cm,用來測量某個對象到屏幕的距離
傳感器類型值(Sensor Type):8 (0x00000008)

TYPE_RELATIVE_HUMIDITY
溼度傳感器,單位是%,來測量周圍環境的相對溼度
傳感器類型值(Sensor Type):12 (0x0000000c)

TYPE_ROTATION_VECTOR
旋轉矢量傳感器,旋轉矢量代表設備的方向
傳感器類型值(Sensor Type):11 (0x0000000b)

TYPE_SIGNIFICANT_MOTION
特殊動作觸發傳感器
傳感器類型值(Sensor Type):17 (0x00000011)

TYPE_STEP_COUNTER
計步傳感器
傳感器類型值(Sensor Type):19 (0x00000013)

TYPE_STEP_DETECTOR
步行檢測傳感器,用戶每走一步就觸發一次事件
傳感器類型值(Sensor Type):18 (0x00000012)

TYPE_TEMPERATURE
溫度傳感器,目前已被TYPE_AMBIENT_TEMPERATURE替代
傳感器類型值(Sensor Type):7 (0x00000007)
“`

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