深入淺出 – Android系統移植與平台開發(十三) – Sensor HAL架構分析之三

來源:互聯網
上載者:User

讓我們來看看SensorManager的代碼

SensorManager架構層代碼

@frameworks/base/core/java/android/hardware/SensorManager.java

public SensorManager(Looper mainLooper) {       mMainLooper = mainLooper;    // 上面說了,這是Activity的Looper       synchronized(sListeners) {            if(!sSensorModuleInitialized) {                sSensorModuleInitialized = true;                nativeClassInit();        // 好像是調用本地方法初始化                  sWindowManager = IWindowManager.Stub.asInterface(                       ServiceManager.getService("window"));  // 獲得Windows服務,不管它                  if (sWindowManager != null) {                   // if it's null we're running in the system process                   // which won't get the rotated values                   try {                       sRotation = sWindowManager.watchRotation(                                newIRotationWatcher.Stub() {                                    public voidonRotationChanged(int rotation) {                                       SensorManager.this.onRotationChanged(rotation);                                    }                                }                        );                   } catch (RemoteException e) {                   }                }               // initialize the sensor list               sensors_module_init();         // 初始化sensor module               final ArrayList<Sensor> fullList = sFullSensorsList;  // SensorManager維護的Sensor列表                 int i = 0;               do {                   Sensor sensor = new Sensor(); // 建立sensor對象,這個是傳遞給App的哦                   //調用module的方法,獲得每一個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); // 添加到SM維護的Sensor列表(嘿嘿)                       sHandleToSensor.append(sensor.getHandle(), sensor);                   }                }while (i>0);                sPool= new SensorEventPool( sFullSensorsList.size()*2 );               sSensorThread = new SensorThread(); // 喲,建立線程了好像            }        }    }

很明顯nativeClassInit(),sensors_module_init(),sensors_module_get_next_sensor()都是本地實現的方法。

private static native void nativeClassInit();private static native int sensors_module_init();private static native intsensors_module_get_next_sensor(Sensor sensor, int next);

根據之前看代碼的經驗可知,很可能在frameworks/base/core/對應一個jni目錄下的存在其對應的本地代碼:

frameworks/base/core/java/android/hardware/SensorManager.javaframeworks/base/core/jni/android_hardware_SensorManager.cpp

果不其然,在jni存在其本地代碼,讓我們來看下nativeClassInit函數:

@frameworks/base/core/jni/android_hardware_SensorManager.cpp

static voidnativeClassInit (JNIEnv *_env, jclass _this){   jclasssensorClass = _env->FindClass("android/hardware/Sensor");   SensorOffsets& sensorOffsets = gSensorOffsets;   sensorOffsets.name        =_env->GetFieldID(sensorClass, "mName",      "Ljava/lang/String;");   sensorOffsets.vendor      =_env->GetFieldID(sensorClass, "mVendor",    "Ljava/lang/String;");   sensorOffsets.version     =_env->GetFieldID(sensorClass, "mVersion",   "I");   sensorOffsets.handle      =_env->GetFieldID(sensorClass, "mHandle",    "I");   sensorOffsets.type        = _env->GetFieldID(sensorClass,"mType",      "I");   sensorOffsets.range       =_env->GetFieldID(sensorClass, "mMaxRange",  "F");   sensorOffsets.resolution  =_env->GetFieldID(sensorClass, "mResolution","F");   sensorOffsets.power       =_env->GetFieldID(sensorClass, "mPower",     "F");   sensorOffsets.minDelay    =_env->GetFieldID(sensorClass, "mMinDelay",  "I");}

其代碼比較簡單,將Java架構層的Sensor類中的成員儲存在本地代碼中的gSensorOffsets 結構體中將來使用。

         sensors_module_init()本地方法的實現:

static jintsensors_module_ini(JNIEnv *env, jclass clazz){   SensorManager::getInstance();    return 0;}

         在本地代碼中調用了SensorManager的getInstance方法,這又是一個典型的單例模式獲得類的對象,注意這兒的SensorManager是本地的類,而不是Java層的SensorManager類。

本地SensorManager的定義

@frameworks/base/include/gui/SensorManager.h

class SensorManager :    publicASensorManager,    publicSingleton<SensorManager>{public:   SensorManager();   ~SensorManager();    ssize_tgetSensorList(Sensor const* const** list) const;    Sensor const*getDefaultSensor(int type);   sp<SensorEventQueue> createEventQueue();private:    //DeathRecipient interface    voidsensorManagerDied();    status_tassertStateLocked() const;private:    mutable MutexmLock;    mutablesp<ISensorServer> mSensorServer;    mutableSensor const** mSensorList;    mutableVector<Sensor> mSensors;    mutablesp<IBinder::DeathRecipient> mDeathObserver;};

注意SensorManager又繼承了ASensorManager和泛型類Singleton<SensorManager>,而SensorManager類定義裡沒有getInstance所以其定義肯定是在ASensorManager或Singleton中。

@frameworks/base/include/utils/Singleton.h

template <typename TYPE>class ANDROID_API Singleton{public:    staticTYPE& getInstance() {       Mutex::Autolock _l(sLock);        TYPE*instance = sInstance;        if(instance == 0) {           instance = new TYPE();           sInstance = instance;        }        return*instance;    }    static boolhasInstance() {       Mutex::Autolock _l(sLock);        returnsInstance != 0;    }protected:    ~Singleton(){ };    Singleton() {};private:   Singleton(const Singleton&);   Singleton& operator = (const Singleton&);    static MutexsLock;    static TYPE*sInstance;};//---------------------------------------------------------------------------}; // namespace android

第一次調用getInstance方法時,建立泛型對象即:SensorManager,隨後再調用該方法時返回第一次建立的泛型對象。

1)    本地SensorManager的建立

本地SensorManager是一個單例模式,其構造方法相對比較簡單,它的主要工作交給了assertStateLocked方法:

@frameworks/base/libs/gui/SensorManager.cpp

SensorManager::SensorManager()          :mSensorList(0){    // okay we'renot locked here, but it's not needed during construction   assertStateLocked();}status_t SensorManager::assertStateLocked() const {    if(mSensorServer == NULL) {        // try for one second        constString16 name("sensorservice");        for (inti=0 ; i<4 ; i++) {            status_t err = getService(name,&mSensorServer);            if(err == NAME_NOT_FOUND) {               usleep(250000);               continue;            }            if(err != NO_ERROR) {               return err;            }            break;        }        classDeathObserver : public IBinder::DeathRecipient {           SensorManager& mSensorManger;           virtual void binderDied(const wp<IBinder>& who) {               LOGW("sensorservice died [%p]", who.unsafe_get());               mSensorManger.sensorManagerDied();            }        public:           DeathObserver(SensorManager& mgr) : mSensorManger(mgr) { }        };       mDeathObserver = new DeathObserver(*const_cast<SensorManager*>(this));        mSensorServer->asBinder()->linkToDeath(mDeathObserver);        mSensors= mSensorServer->getSensorList();       size_tcount = mSensors.size();       mSensorList = (Sensor const**)malloc(count * sizeof(Sensor*));        for(size_t i=0 ; i<count ; i++) {           mSensorList[i] = mSensors.array() + i;        }    }    returnNO_ERROR;}

在assertStateLocked方法裡,先通過getService獲得SensorService對象,然後註冊了對SensorService的死亡監聽器,SensorManager與SensorService不求同年同月同日,只求同年同月同日死。拜完了兄弟之後,調用getSensorList得到所有感應器的對象,存放到mSensorList中,儲存在本地空間裡。

2)    本地SensorManager中列表的擷取

在上面函數調用中首先調用getService來獲得SensorService服務,然後執行mSensorServer->getSensorList來獲得服務提供的感應器列表:

Vector<Sensor> SensorService::getSensorList(){    return mUserSensorList;}

大家要注意啊,上面的getSensorList函數只是返回了mUserSensorList,而這個變數是在什麼時候初始化的呢?

根據2.1節可知,SensorService在本地被初始化時,建構函式裡並沒有對mUserSensorList進行初始化,而SensorService裡有一個onFirstRef方法,這個方法當SensorService第一次被強引用時被自動調用。那SensorService第一次被強引用是在什麼時候呢?

在SensorManager::assertStateLocked方法裡調用getService獲得SensorService儲存到mSensorServer成員變數中。

mSensorServer的定義在frameworks/base/include/gui/SensorManager.h中:

class SensorManager :    public ASensorManager,    public Singleton<SensorManager>{ mutable sp<ISensorServer>mSensorServer; mutable Sensorconst** mSensorList; mutable Vector<Sensor> mSensors;};

可以看出mSensroServer為強參考型別。所以在建立本地中的SensorManager類對象時,自動強引用SensorService,自動調用onFirstRef方法:

@frameworks/base/services/sensorservice/SensorService.cpp的onFirstRef簡化方法如下:

void SensorService::onFirstRef(){      LOGD("nuSensorService starting...");   SensorDevice& dev(SensorDevice::getInstance());                //建立SensorDevice對象dev        if(dev.initCheck() == NO_ERROR) {        sensor_tconst* list;        ssize_tcount = dev.getSensorList(&list);                          //獲得感應器裝置列表        if (count> 0) {            …             for(ssize_t i=0 ; i<count ; i++) {                registerSensor( new HardwareSensor(list[i]) );  // 註冊在本地獲得的感應器                           …                      }            constSensorFusion& fusion(SensorFusion::getInstance());                                 if(hasGyro) {            // 如果有陀螺儀裝置,則先註冊和陀螺儀有關的虛擬感應器裝置                registerVirtualSensor( newRotationVectorSensor() );     // 虛擬旋轉感應器               registerVirtualSensor( new GravitySensor(list, count) ); // 虛擬重力感應器               registerVirtualSensor( new LinearAccelerationSensor(list, count) ); // 虛擬加速器                // these are optional               registerVirtualSensor( new OrientationSensor() ); // 虛擬方向感應器               registerVirtualSensor( new CorrectedGyroSensor(list, count) );        // 真正陀螺儀               // virtual debugging sensors...                char value[PROPERTY_VALUE_MAX];               property_get("debug.sensors", value, "0");               if (atoi(value)) {                   registerVirtualSensor( new GyroDriftSensor() );      // 虛擬陀螺測漂感應器                }            }                                // build the sensor list returned tousers            mUserSensorList = mSensorList;            if(hasGyro &&                   (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR))) {               // if we have the fancy sensor fusion, and it's not provided by the               // HAL, use our own (fused) orientation sensor by removing the               // HAL supplied one form the user list.               if (orientationIndex >= 0) {                   mUserSensorList.removeItemsAt(orientationIndex);                }            }            run("SensorService",PRIORITY_URGENT_DISPLAY);           mInitCheck = NO_ERROR;        }    }}

上面代碼首先通過SensorDevice::getInstance()建立對象dev,調用dev.getSensorList(&list)獲得感應器列表,將取出的sensor_t類型list感應器列表,塑造了HardwareSensor對象,傳遞給了registerSensor方法,通過registerSensor註冊感應器,然後通過單例模型建立了SensorFusion對象,建立並註冊了一系列的虛擬感應器,疑惑,極大的疑惑,怎麼感應器還有虛擬??其實你注意看這幾個感應器最前面的條件,if(hasGyro),表示如果存在陀螺儀的話,會建立這些虛擬設備,再看這些虛擬設備:旋轉,重力,加速器,方向等,這些裝置都對應一個物理硬體:陀螺儀,所以這些邏輯上存在,物理上不存在的裝置叫虛擬設備。在初始化了虛擬設備後,將mSensorList感應器列表賦值給mUserSensorList,mSensorList是由registerSensor初始化的,mUserSensorList是要提交給Java架構層的感應器列表,最後通過run方法運行了SensorService線程,我們先來看下registerSensor的代碼:

void SensorService::registerSensor(SensorInterface* s){    sensors_event_t event;    memset(&event,0, sizeof(event));    const Sensorsensor(s->getSensor());    // add to thesensor list (returned to clients)    mSensorList.add(sensor);    // add to ourhandle->SensorInterface mapping   mSensorMap.add(sensor.getHandle(), s);    // create anentry in the mLastEventSeen array   mLastEventSeen.add(sensor.getHandle(), event);}

通過分析上面代碼可知,將傳入的HardwareSensor對象塑造了Sensor,添加到mSensorList向量表裡,然後將HardwareSensor對象添加到mSensroMap索引值對裡,將建立的感應器事件數目據封裝對象event添加到mLastEventSeen索引值對中。

我們通過下面的時序圖來看下Sensor列表的擷取過程。

1)    SensorService監聽線程及感應器事件的捕獲

讓我們再來看看SensorService線程,還記得前面SensorService的父類中有一個Thread類,當調用run方法時會建立線程並調用threadLoop方法。

bool SensorService::threadLoop(){   LOGD("nuSensorService thread starting...");    const size_tnumEventMax = 16 * (1 + mVirtualSensorList.size());   sensors_event_t buffer[numEventMax];   sensors_event_t scratch[numEventMax];   SensorDevice& device(SensorDevice::getInstance());    const size_tvcount = mVirtualSensorList.size();    ssize_tcount;    do {             // 調用SensorDevice的poll方法看樣子要多路監聽了        count = device.poll(buffer,numEventMax);             if(count<0) {           LOGE("sensor poll failed (%s)", strerror(-count));           break;        }              // 記錄poll返回的每一個感應器中的最後一個資料資訊到mLastEventSeen中        recordLastValue(buffer, count);        // handlevirtual sensors 處理虛擬感應器資料        if (count&& vcount) {           sensors_event_t const * const event = buffer;                      // 獲得虛擬感應器列表            constDefaultKeyedVector<int, SensorInterface*> virtualSensors(                   getActiveVirtualSensors());            constsize_t activeVirtualSensorCount = virtualSensors.size();  // 虛擬感應器個數            if(activeVirtualSensorCount) {               size_t k = 0;               SensorFusion& fusion(SensorFusion::getInstance());               if (fusion.isEnabled()) {                   for (size_t i=0 ; i<size_t(count) ; i++) {                       fusion.process(event[i]);              //處理虛擬感應器裝置事件                    }                }               for (size_t i=0 ; i<size_t(count) ; i++) {                   for (size_t j=0 ; j<activeVirtualSensorCount ; j++) {                       sensors_event_t out;                       if (virtualSensors.valueAt(j)->process(&out, event[i])) {                            buffer[count + k] =out;                            k++;                       }                   }                }               if (k) {                   // record the last synthesized values                   recordLastValue(&buffer[count], k);                   count += k;                   // sort the buffer by time-stamps                   sortEventBuffer(buffer, count);                }            }        }        // sendour events to clients...              // 獲得感應器連線物件列表        constSortedVector< wp<SensorEventConnection> > activeConnections(               getActiveConnections());        size_tnumConnections = activeConnections.size();        for(size_t i=0 ; i<numConnections ; i++) {           sp<SensorEventConnection> connection(                   activeConnections[i].promote());            if(connection != 0) {                               // 向指定的感應器串連用戶端發送感應器資料資訊                connection->sendEvents(buffer, count, scratch);            }        }    } while (count>= 0 || Thread::exitPending());   // 感應器迴圈監聽線程   LOGW("Exiting SensorService::threadLoop => aborting...");    abort();    return false;}

我們看到device.poll方法,阻塞在了SensorDevice的poll方法上,它肯定就是讀取Sensor硬體上的資料了,將感應器資料儲存在buff中,然後調用recordLastValue方法,只儲存同一類型感應器的最新資料(最後採集的一組資料)到索引值對象mLastEventSeen裡對應感應器的範圍中。如果感應器裝置是虛擬設備則調用SensorFusion.Process()方法對虛擬設備資料進行處理。SensorFusion關聯一個SensorDevice,它是虛擬感應器裝置的一個加工類,負責虛擬感應器資料的計算、處理、裝置啟用、設定延遲、獲得功耗資訊等操作。

讓我們來回顧下整個過程吧。

1. SensorManager對象建立並調用assertStateLocked方法

2. 在assertStateLocked方法中調用getService,獲得SensorService服務

3. 當SensorService第一次強引用時,自動調用OnFirstRef方法

4.獲得SensorDevice單例對象

6. 調用SensorDevice.getSensorList方法sensor_t列表儲存在SensorService中

8. 調用registerSensor註冊感應器,添加到mSensorList列表中

9. 啟動SensorService線程,準備監聽所有註冊的感應器裝置

12. 多路監聽註冊的感應器裝置,當有感應器事件時,返回sensor_event_t封裝的事件資訊

16. 記錄產生感應器事件的裝置資訊

17. 調用getActiveConnections獲得所有的活動的用戶端SensorEventConnection類對象

19.向用戶端發送感應器事件資訊

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.