閱讀android有關sensor的源碼總結

       雖然這篇文章寫得很差,因爲趕時間,所以就匆匆忙忙地寫出來自己作一個筆記。但是我想對大家應該有一點幫助。

1、有關sensorJava應用程序的編程(以註冊多個傳感器爲例,這程序是我臨時弄出來的,可能有錯)

package com.sensors.acc;

 

import android.app.Activity;

import android.os.Bundle;

 

import android.util.Log;

import android.widget.TextView;

import android.hardware.SensorManager;

import android.hardware.Sensor;

import android.hardware.SensorEvent;

import android.hardware.SensorEventListener;

 

public class acc extends Activity {

    float x, y, z;

    SensorManager sensormanager = null;

    Sensor accSensor = null;

    Sensor lightSensor = null;

    Sensor proximitySensor = null;

    TextView accTextView = null;

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

    sensormanager = (SensorManager)getSystemService(SENSOR_SERVICE);

    accSensor = sensormanager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

    lightSensor = sensormanager.getDefaultSensor(Sensor.TYPE_LIGHT);

    proximitySensor = sensormanager.getDefaultSensor(Sensor.TYPE_PROXIMITY);

    accTextView = (TextView)findViewById(R.id.textview_name);

    }

   

    SensorEventListener lsn = new SensorEventListener() {  

        public void onSensorChanged(SensorEvent e) {

        if (e.sensor == accSensor) {

             Log.d("sensor", "found acc sensor");

                x = e.values[SensorManager.DATA_X];  

                y = e.values[SensorManager.DATA_Y];  

                z = e.values[SensorManager.DATA_Z];

                accTextView.setText("x = " + x + ", /ny = " + y + ", /nz = " + z);

        }

        else if (e.sensor == lightSensor) {

             Log.d("sensor", "found light sensor");

                accTextView.setText("data is " + e.values[0]);

        }

        else if (e.sensor == proximitySensor) {

             Log.d("sensor", "found proximity sensor");

                accTextView.setText("distance is " + e.values[0]);

        }

  //          Log.d("sensor", "found acc sensor");

 

 //           Log.d("sensor", "x = " + x + ", y = " + y + ", z = " + z);

 //           accTextView.setText("x = " + x + ", /ny = " + y + ", /nz = " + z);

        }  

 

        public void onAccuracyChanged(Sensor s, int accuracy) {  

        }  

    };    

    @Override   

    protected void onResume() {       

    super.onResume();      // register this class as a listener for the orientation and accelerometer sensors       

    sensormanager.registerListener(lsn, accSensor, SensorManager.SENSOR_DELAY_NORMAL);

    sensormanager.registerListener(lsn, lightSensor, SensorManager.SENSOR_DELAY_NORMAL);

    sensormanager.registerListener(lsn, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL);

 //     sensormanager.unregisterListener(lsn);

    }       

    @Override   

    protected void onStop() {        // unregister listener        

    sensormanager.unregisterListener(lsn, accSensor);

    sensormanager.unregisterListener(lsn, lightSensor);

sensormanager.unregisterListener(lsn, proximitySensor);

    super.onStop();   

    }  

}

 

onCreate()函數中,調用getSystemService(SENSOR_SERVICE)初始化一個SensorManager實例,爲什麼要用getSystemService函數,而不直接用new SensorManager呢?我們看此函數的實現,在ApplicationContext.java中,

if (SENSOR_SERVICE.equals(name)) {

            return getSensorManager();

然後getSensorManager()的實現


    private SensorManager getSensorManager() {

        synchronized (mSync) {

            if (mSensorManager == null) {

                mSensorManager = new SensorManager(mMainThread.getHandler().getLooper());

            }

        }

        return mSensorManager;

}

看到沒有?初始化SensorManager的時候需要mMainThread.getHandler().getLooper()這個參數,之個應該是用來傳遞消息用的,在SensorManager類的構造函數中會把此參數傳給類成員mMainLooper。如果用new SensorManager()就需要另外獲取mainLooper參數傳遞進去。

 

2、在android中跟sensor有關的一些文件有SensorManager.java,位於frameworks/base/core/java/android/hardware目錄下,SensorService.java,位於frameworks/base/services/java/com/android/server目錄下,android_hardware_SensorManager.cpp,位於frameworks/base/core/jni/目錄下,與SensorManager.java相對應,com_android_server_SensorService.cpp,在frameworks/base/services/jni/目錄下,與SensorService.java相對應。還有SystemServer.java文件,Hardware/Libhardware/Include/Hardware目錄下的Sensor.h頭文件。另外我們需要根據Sensor.h實現自己的一個源文件,一般取名爲sensors_xxx.c或者sensors_xxx.cpp

 

3SensorManager類分析

有幾個函數比較重要,必須清晰理解它們的實現,才能瞭解整個傳感器系統的實現。從而更好地去實現硬件抽象層的實現。幾個比較重要的函數有構造函數SensorManager(), registerListener()unregisterListener(),其中registerListener()unregisterListener()有多個,標誌爲  @Deprecated的是過時的,就不要看了。

1)構造函數SensorManager(Looper mainLooper)

這個函數首先獲取得傳感器系統服務,並賦給類成員mSensorService

       mSensorService = ISensorService.Stub.asInterface(

                ServiceManager.getService(Context.SENSOR_SERVICE));

這裏我要說一句,就是關於這個傳感器系統服務,很多書上都說用getSystemService()是獲得傳感器的系統服務,而它返回的是SensorManager類型,所以以爲整個系統都是使用同一個SensorManager類的實例,以爲我們在任何地方使用的SensorManager實例都是同一個,它們的公共成員是共享的。但是經過這兩天的分析,這種說法是錯誤的。其實每次調用getSystemService()函數時都初始化一個新的SensorManager實例,而這個SensorManager實例會在構造函數裏通過取得傳感器系統服務SensorService來實現對下層傳感器的一些控制。而這個SensorService纔是系統的傳感器服務,說服務,不如說它只是SensorService類的一個實例罷了。它只在系統初始化時初始化一次。Android中的系統服務機制應該跟傳感器的都差不多一個樣,都是由不同的Manager調用下層相同的Service。你可以列舉其它的Manager。那它是什麼時候初始化呢?它是系統初始化在SystemServer進程裏創建的,SystemServer是一個管理很多系統服務的進程,我們轉到SystemServer.main函數裏,可以看到一直到調用int2()函數,它會創建一個ServerThread,最終調用AdbSettingsObserver類的run()函數,在run()函數裏有這麼有一句

            // Sensor Service is needed by Window Manager, so this goes first

            Log.i(TAG, "Sensor Service");

            ServiceManager.addService(Context.SENSOR_SERVICE, new SensorService(context));

這裏就創建SensorService實例了。在創建這個實例時會在SensorService構造函數中調用jni函數    public SensorService(Context context) {

        if (localLOGV) Log.d(TAG, "SensorService startup");

        _sensors_control_init();

    }

我們看_sensors_control_init();對應的爲

static jint

android_init(JNIEnv *env, jclass clazz)

{

    sensors_module_t* module;

    if (hw_get_module(SENSORS_HARDWARE_MODULE_ID, (const hw_module_t**)&module) == 0) {

        if (sensors_control_open(&module->common, &sSensorDevice) == 0) {

            const struct sensor_t* list;

            int count = module->get_sensors_list(module, &list);

            return count;

        }

    }

    return 0;

}

它主要調用了sensor.h中的sensors_control_open()

static inline int sensors_control_open(const struct hw_module_t* module,

        struct sensors_control_device_t** device) {

    return module->methods->open(module,

            SENSORS_HARDWARE_CONTROL, (struct hw_device_t**)device);

}

之後在系統任何地方使用的都是這個SensorService實例。最後run()函數調用Looper.loop();就進行消息循環等待了,這就是SystemServer進程的消息服務了。這才真正叫做系統服務嘛。

 

我們繼續看SensorManager類的構造函數,取得SensorService後,

               nativeClassInit();

這是一個jni函數,SensorManager類調用的jni函數都在com_android_server_SensorService.cpp裏,我們看這函數

static void

nativeClassInit (JNIEnv *_env, jclass _this)

{

    jclass sensorClass = _env->FindClass("android/hardware/Sensor");

    SensorOffsets& sensorOffsets = gSensorOffsets;

    sensorOffsets.name        = _env->GetFieldID(sensorClass, "mName",      "Ljava/lang/String;");

    sensorOffsets.vendor      = _env->GetFieldID(sensorClass, "mVendor",    "Ljava/lang/String;");

    sensorOffsets.version     = _env->GetFieldID(sensorClass, "mVersion",   "I");

    sensorOffsets.handle      = _env->GetFieldID(sensorClass, "mHandle",    "I");

    sensorOffsets.type        = _env->GetFieldID(sensorClass, "mType",      "I");

    sensorOffsets.range       = _env->GetFieldID(sensorClass, "mMaxRange",  "F");

    sensorOffsets.resolution  = _env->GetFieldID(sensorClass, "mResolution","F");

    sensorOffsets.power       = _env->GetFieldID(sensorClass, "mPower",     "F");

}

這個函數只是獲取和設置一些信息吧,我們不關心。接着

                sensors_module_init();

我們看這函數

static jint

sensors_module_init(JNIEnv *env, jclass clazz)

{

    int err = 0;

    sensors_module_t const* module;

    err = hw_get_module(SENSORS_HARDWARE_MODULE_ID, (const hw_module_t **)&module);

    if (err == 0)

        sSensorModule = (sensors_module_t*)module;

    return err;

}

它獲取了sensor的模塊信息,並把它賦給sSensorModule全局變量,之後傳的modules參數都爲這個。

接着在構造函數裏

            final ArrayList<Sensor> fullList = sFullSensorsList;

                int i = 0;

                do {

                    Sensor sensor = new Sensor();

                    i = sensors_module_get_next_sensor(sensor, i);

 

                    if (i>=0) {

                        Log.d(TAG, "found sensor: " + sensor.getName() +

                                ", handle=" + sensor.getHandle());

                        sensor.setLegacyType(getLegacySensorType(sensor.getType()));

                        fullList.add(sensor);

                        sHandleToSensor.append(sensor.getHandle(), sensor);

                    }

                } while (i>0);

這裏主要是通過jni函數sensors_module_get_next_sensor(sensor, i);獲取傳感器列表,並把它加入自己的fullList列表中。我們看sensors_module_get_next_sensor()函數

static jint

sensors_module_get_next_sensor(JNIEnv *env, jobject clazz, jobject sensor, jint next)

{

    if (sSensorModule == NULL)

        return 0;

 

    SensorOffsets& sensorOffsets = gSensorOffsets;

    const struct sensor_t* list;

    int count = sSensorModule->get_sensors_list(sSensorModule, &list);

    if (next >= count)

        return -1;

   

    list += next;

 

    jstring name = env->NewStringUTF(list->name);

    jstring vendor = env->NewStringUTF(list->vendor);

    env->SetObjectField(sensor, sensorOffsets.name,      name);

    env->SetObjectField(sensor, sensorOffsets.vendor,    vendor);

    env->SetIntField(sensor, sensorOffsets.version,      list->version);

    env->SetIntField(sensor, sensorOffsets.handle,       list->handle);

    env->SetIntField(sensor, sensorOffsets.type,         list->type);

    env->SetFloatField(sensor, sensorOffsets.range,      list->maxRange);

    env->SetFloatField(sensor, sensorOffsets.resolution, list->resolution);

    env->SetFloatField(sensor, sensorOffsets.power,      list->power);

   

    next++;

    return next<count ? next : 0;

}

它主要是調用HAL層的get_sensors_list()函數取得傳感器列表信息。

接着在sensorManger構造函數最後

                sSensorThread = new SensorThread();

創建一個SensorThread()線程。但並未運行,但在SensorThread類的構造函數裏會執行jni函數            sensors_data_init();

我們看此函數static jint

sensors_data_init(JNIEnv *env, jclass clazz)

{

    if (sSensorModule == NULL)

        return -1;

    int err = sensors_data_open(&sSensorModule->common, &sSensorDevice);

    return err;

}

它調用了HAL層的sensors_data_open函數,而這個函數位於sensor.h中,它調用的是

static inline int sensors_data_open(const struct hw_module_t* module,

        struct sensors_data_device_t** device) {

    return module->methods->open(module,

            SENSORS_HARDWARE_DATA, (struct hw_device_t**)device);

}

Modules->methods->open函數。而在SensorThread類的析構函數finalize()裏會調用

            sensors_data_uninit();

static jint

sensors_data_uninit(JNIEnv *env, jclass clazz)

{

    int err = 0;

    if (sSensorDevice) {

        err = sensors_data_close(sSensorDevice);

        if (err == 0)

            sSensorDevice = 0;

    }

    return err;

}

sensor.h

static inline int sensors_data_close(struct sensors_data_device_t* device) {

    return device->common.close(&device->common);

}

那什麼時候sSensorThread線程會運行呢?我們在下面看registerListener()函數。

 

2    public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate) {

        return registerListener(listener, sensor, rate, null);

}

它調用的是    public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate,

            Handler handler)

在這函數中,先驗證rate,然後檢測註冊的listener在不在本類的sListeners列表中。

                for (ListenerDelegate i : sListeners) {

                    if (i.getListener() == listener) {

                        l = i;

                        break;

                    }

                }

如果不在就申請一個listener,並把它加入全局列表sListener中,並調用mSensorServiceenableSensor()函數使能傳感器,這個enableSensor()函數最終會調用HAL層的active函數和set_delay()函數,使用後然後判斷sListener列表是否爲空,當然,第一次爲空時加入一個新的listener就不爲空了,此時就執行sSensorThreadstartLocked運行sSensorThread線程了

          l = new ListenerDelegate(listener, sensor, handler);

                    result = mSensorService.enableSensor(l, name, handle, delay);

                    if (result) {

                        sListeners.add(l);

                        sListeners.notify();

                    }

                    if (!sListeners.isEmpty()) {

                        sSensorThread.startLocked(mSensorService);

                    }

另一方面,如果註冊的listenersListeners列表中,則先調用mSensorServiceenableSensor()函數使能傳感器,然後把註冊的傳感器加入到已存在的listener中。

                 result = mSensorService.enableSensor(l, name, handle, delay);

                    if (result) {

                        l.addSensor(sensor);

                    }

接下來我們看看startLocked函數,它在SensorThread中,

        void startLocked(ISensorService service) {

            try {

                if (mThread == null) {

                    Bundle dataChannel = service.getDataChannel();

                    mThread = new Thread(new SensorThreadRunnable(dataChannel),

                            SensorThread.class.getName());

                    mThread.start();

                }

            } catch (RemoteException e) {

                Log.e(TAG, "RemoteException in startLocked: ", e);

            }

        }

第一次mThreadnull,然後它調用了service.getDataChannel()函數,此函數在SensorService類中,主要調用了jni函數_sensors_control_open()

    public Bundle getDataChannel() throws RemoteException {

        // synchronize so we do not require sensor HAL to be thread-safe.

        synchronized(mListeners) {

            return _sensors_control_open();

        }

}

SensorService類中調用的jni函數主要都在com_android_server_SensorService.cpp文件 中,我們看一下這個函數

static jobject

android_open(JNIEnv *env, jclass clazz)

{

    native_handle_t* handle = sSensorDevice->open_data_source(sSensorDevice);

    if (!handle) {

        return NULL;

    }

 

    // new Bundle()

    jobject bundle = env->NewObject(

            gBundleOffsets.mClass,

            gBundleOffsets.mConstructor);

 

    if (handle->numFds > 0) {

        jobjectArray fdArray = env->NewObjectArray(handle->numFds,

                gParcelFileDescriptorOffsets.mClass, NULL);

        for (int i = 0; i < handle->numFds; i++) {

            // new FileDescriptor()

            jobject fd = env->NewObject(gFileDescriptorOffsets.mClass,

                    gFileDescriptorOffsets.mConstructor);

            env->SetIntField(fd, gFileDescriptorOffsets.mDescriptor, handle->data[i]);

            // new ParcelFileDescriptor()

            jobject pfd = env->NewObject(gParcelFileDescriptorOffsets.mClass,

                    gParcelFileDescriptorOffsets.mConstructor, fd);

            env->SetObjectArrayElement(fdArray, i, pfd);

        }

        // bundle.putParcelableArray("fds", fdArray);

        env->CallVoidMethod(bundle, gBundleOffsets.mPutParcelableArray,

                env->NewStringUTF("fds"), fdArray);

    }

 

    if (handle->numInts > 0) {

        jintArray intArray = env->NewIntArray(handle->numInts);

        env->SetIntArrayRegion(intArray, 0, handle->numInts, &handle->data[handle->numInts]);

        // bundle.putIntArray("ints", intArray);

        env->CallVoidMethod(bundle, gBundleOffsets.mPutIntArray,

                env->NewStringUTF("ints"), intArray);

    }

 

    // delete the file handle, but don't close any file descriptors

    native_handle_delete(handle);

    return bundle;

}

它主要調用了HAL層的open_data_source()函數。取得一些文件描述符等信息。

接下來SensorThread創建一個線程,調用start()就進入SensorThreadRunnable類的run()函數了,所以我們接着去看run()函數,它首先調用open()函數

                if (!open()) {

                    return;

                }

open()函數中調用了  jni函數sensors_data_open(fds, ints);

static jint

sensors_data_open(JNIEnv *env, jclass clazz, jobjectArray fdArray, jintArray intArray)

{

    jclass FileDescriptor = env->FindClass("java/io/FileDescriptor");

    jfieldID fieldOffset = env->GetFieldID(FileDescriptor, "descriptor", "I");

    int numFds = (fdArray ? env->GetArrayLength(fdArray) : 0);

    int numInts = (intArray ? env->GetArrayLength(intArray) : 0);

    native_handle_t* handle = native_handle_create(numFds, numInts);

    int offset = 0;

 

    for (int i = 0; i < numFds; i++) {

        jobject fdo = env->GetObjectArrayElement(fdArray, i);

        if (fdo) {

            handle->data[offset++] = env->GetIntField(fdo, fieldOffset);

        } else {

            handle->data[offset++] = -1;

        }

    }

    if (numInts > 0) {

        jint* ints = env->GetIntArrayElements(intArray, 0);

        for (int i = 0; i < numInts; i++) {

            handle->data[offset++] = ints[i];

        }

        env->ReleaseIntArrayElements(intArray, ints, 0);

    }

 

    // doesn't take ownership of the native handle

    return sSensorDevice->data_open(sSensorDevice, handle);

}

這函數最終調用了HAL層的data_open(),之後run()函數就進入一個while循環了。

         while (true) {

                    // wait for an event

                    final int sensor = sensors_data_poll(values, status, timestamp);

 

                    int accuracy = status[0];

                    synchronized (sListeners) {

                        if (sensor == -1 || sListeners.isEmpty()) {

                            if (sensor == -1) {

                                // we lost the connection to the event stream. this happens

                                // when the last listener is removed.

                                Log.d(TAG, "_sensors_data_poll() failed, we bail out.");

                            }

 

                            // we have no more listeners or polling failed, terminate the thread

                            sensors_data_close();

                            mThread = null;

                            break;

                        }

                        final Sensor sensorObject = sHandleToSensor.get(sensor);

                        if (sensorObject != null) {

                            // report the sensor event to all listeners that

                            // care about it.

                            final int size = sListeners.size();

                            for (int i=0 ; i<size ; i++) {

                                ListenerDelegate listener = sListeners.get(i);

                                if (listener.hasSensor(sensorObject)) {

                                    // this is asynchronous (okay to call

                                    // with sListeners lock held).

                                    listener.onSensorChangedLocked(sensorObject,

                                            values, timestamp, accuracy);

                                }

                            }

                        }

                    }

它調用了jni函數sensors_data_poll()一直讀數據。

static jint

sensors_data_poll(JNIEnv *env, jclass clazz,

        jfloatArray values, jintArray status, jlongArray timestamp)

{

    sensors_data_t data;

    int res = sSensorDevice->poll(sSensorDevice, &data);

    if (res >= 0) {

        jint accuracy = data.vector.status;

        env->SetFloatArrayRegion(values, 0, 3, data.vector.v);

        env->SetIntArrayRegion(status, 0, 1, &accuracy);

        env->SetLongArrayRegion(timestamp, 0, 1, &data.time);

    }

 

    return res;

}

把傳感器得到的值都放在value數組中,根據返回的傳感器標誌sensor,把它分派給在sListener列表中所有的listener,如果listener中有監聽這個sensor,就把它分派給這個listener,此時就會引起onSensorChange()了。

 

好了,獲取傳感器數據主要是這樣一個途徑。最後我們去分析一下unregisterListener()函數。

   private void unregisterListener(Object listener) {

        if (listener == null) {

            return;

        }

        try {

            synchronized (sListeners) {

                final int size = sListeners.size();

                for (int i=0 ; i<size ; i++) {

                    ListenerDelegate l = sListeners.get(i);

                    if (l.getListener() == listener) {

                        // disable all sensors for this listener

                        for (Sensor sensor : l.getSensors()) {

                            String name = sensor.getName();

                            int handle = sensor.getHandle();

                            mSensorService.enableSensor(l, name, handle, SENSOR_DISABLE);

                        }

                        sListeners.remove(i);

                        break;

                    }

                }

            }

        } catch (RemoteException e) {

            Log.e(TAG, "RemoteException in unregisterListener: ", e);

        }

}

不用想這個函數會做一些與registerListener相反的事情,至少差不多。它先在sListeners列表中找到這個listener,然後先調用enableSensor()函數禁止這個傳感器。我們跟蹤一下這函數,在SensorService類中。

      synchronized(mListeners) {

            if (enable!=SENSOR_DISABLE && !_sensors_control_activate(sensor, true)) {

                Log.w(TAG, "could not enable sensor " + sensor);

                return false;

            }

                   

            Listener l = null;

            int minDelay = enable;

            for (Listener listener : mListeners) {

                if (binder == listener.mToken) {

                    l = listener;

                }

                if (minDelay > listener.mDelay)

                    minDelay = listener.mDelay;

            }

           

            if (l == null && enable!=SENSOR_DISABLE) {

                l = new Listener(binder);

                binder.linkToDeath(l, 0);

                mListeners.add(l);

                mListeners.notify();

            }

           

            if (l == null) {

                // by construction, this means we're disabling a listener we

                // don't know about...

                Log.w(TAG, "listener with binder " + binder +

                        ", doesn't exist (sensor=" + name + ", id=" + sensor + ")");

                return false;

            }

           

            if (minDelay >= 0) {

                _sensors_control_set_delay(minDelay);

            }

           

            if (enable != SENSOR_DISABLE) {

                l.addSensor(sensor, enable);

            } else {

                l.removeSensor(sensor);

                deactivateIfUnusedLocked(sensor);

                if (l.mSensors == 0) {

                    mListeners.remove(l);

                    binder.unlinkToDeath(l, 0);

                    mListeners.notify();

                }

            }

           

            if (mListeners.size() == 0) {

                _sensors_control_wake();

                _sensors_control_close();

            }

        }       

        return true;

你們看到它的實現了吧。如果enabletrue的話,就調用_sensors_control_activate(),如果是false的話,就調用deactivateIfUnusedLocked(),它們最終都會調用 HAL層的active()函數。最後,如果是禁止傳感器的話,如果mListeners爲空了,它就會調用

_sensors_control_wake();

                _sensors_control_close();

這兩個jni函數,最終會調用HAL層的wake()close_data_source()函數。當調用wake()函數時,會使SensorManager類線程的run()函數中的sensor_data_poll()函數立即返回,此時在run()函數中調用sensors_data_close();最終會調用HAL層的data_close()函數。至此,一個傳感器從初始到結束的流程就分析完了。

       所以在java使用一個傳感器在HAL層具體調用的函數流程爲:

首先,sensors_control_open(),只在系統初始化時調用一次。用來初始化control_device結構體。

以下的是每次使用傳感器一般經過的流程,注意,是一般而已,有些並不執行

1sensors_data_open

2get_sensors_list

3activate

4set_delay

5open_data_source

6data_open

7poll

一直讀數據。。。。。。。。。。。

退出時

8activate

9sensors_control_close

10data_close

 

當然其它的細節你們可以繼續去研究。也可以在我博客裏提出來大家交流和討論一下!

 

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