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

來源:互聯網
上載者:User

轉自:http://blog.csdn.net/mr_raptor/article/details/8090474

1.      Sensor的概念

Sensor即感應器,在當前智能手機上大量存在:G-Sensor、LightsSensor、ProximitySensor、TemperatureSensor等,其作為Android系統的一個輸入裝置,對於重視使用者體驗的行動裝置來說是必不可少的。Sensor雖然是一個輸入裝置,但是它又不同於觸控螢幕,鍵盤,按鍵等這些常規的輸入裝置,因為Sensor的資料輸入從感應器硬體到裝置的,而常規的輸入裝置是從使用者到裝置的,比如:溫度感應器用於感知溫度的變化,採樣感應器資料上報給裝置。而感應器硬體的工作與否,採樣精度是由使用者來控制的,所以對應Sensor而言是其工作方式是雙向的,即:控制硬體的控制流程,硬體上報的資料流。這也決定了Sensor的架構不同與觸控螢幕等常規輸入子系統。

本章節主要研究的Sensor架構代碼與SensorHAL的實現細節,一切還是從Sensor架構開始,首先來回顧下Led HAL的實現架構。

Led HAL是我們自己實現的,主要分為四部分:

Led App:Led的應用程式

Led Service架構:Led應用的API提供者

LedService本地:LedService服務的本地實現,上層與底層的通訊轉化介面

Led HAL Stub:HAL層代碼,具體硬體驅動操作介面

很明顯,我們寫的Led HAL代碼是典型的控制流程,反饋結果就是Led燈的亮與滅,它的架構不適用於Sensor架構,具體有如下幾點:

l  Led是單純的控制流程,而Sensor是控制流程與資料流

Sensor的資料流不是即時的,而是有採樣速率,並且資料不是連續的,阻塞在讀取硬體裝置資料上,只有資料得到才返回。

l  Sensor是提供給所有感應器的通用架構,不是針對某一特定硬體的架構

Sensor包含多種類型,在上層和底層都有對Sensor具體類型的屏蔽,讓它通用所有感應器。

l  Sensor的服務不是由應用程式建立啟動的,應該是伴隨系統啟動的

任何一個應用程式裡都可以使用Sensor服務,這決定了Sensor服務應該伴隨系統啟動。

2.      Sensor的架構分析

本節是本系列第一個分析的具體裝置的架構,從Android SensorService的註冊啟動開始,到應用程式獲得SensorManager註冊感應器監聽器,詳細分析從應用程式層到Java架構層再到本地代碼,最後調用HAL層全部過程。

1.1  Sensor服務的啟動

由前面Android啟動流程章節可知,Zygote啟動起來後,啟動並執行每一個Java進程是SystemServer,它用來啟動並管理所有的Android服務:

[cpp]
view plaincopyprint?
  1. public staticvoid main(String[] args) { 
  2.     … 
  3.        System.loadLibrary("android_servers"); 
  4.        init1(args); 
  5.       } 
public static void main(String[] args) {    …       System.loadLibrary("android_servers");       init1(args);      }

由SystemServer的main方法可知,其載入了libandroid_servers.so的庫,並且調用了init1()方法。

我們通過下面的命令來找到該庫的編譯目錄:

[plain]
view plaincopyprint?
  1. find ./frameworks/base –name Android.mk –exec grep –l libandroid_servers{}\; 
find ./frameworks/base –name Android.mk –exec grep –l libandroid_servers{}\;

通過列印的資訊知道,其對應的源碼目錄在:frameworks/base/services/jni/下,其實Android架構層的代碼的特點就是Java目錄下存放的是對應的Java架構代碼,對應的jni目錄下是對應的本地代碼。

在這個目錄所有的代碼最重要的就是:com_android_server_SystemServer.cpp:

[cpp]
view plaincopyprint?
  1. namespace android { 
  2.  
  3. extern "C"int system_init(); 
  4. static void android_server_SystemServer_init1(JNIEnv*env, jobject clazz) 
  5.    system_init(); 
  6. /*
  7. * JNIregistration.
  8. */ 
  9. static JNINativeMethod gMethods[] = { 
  10.     /* name,signature, funcPtr */ 
  11.     {"init1", "([Ljava/lang/String;)V", (void*) android_server_SystemServer_init1}, 
  12. }; 
  13.  
  14. int register_android_server_SystemServer(JNIEnv* env) 
  15.     returnjniRegisterNativeMethods(env, "com/android/server/SystemServer", 
  16.            gMethods, NELEM(gMethods)); 
  17.  
  18. }; // namespace android 
namespace android {extern "C" int system_init();static void android_server_SystemServer_init1(JNIEnv*env, jobject clazz){   system_init();}/* * JNIregistration. */static JNINativeMethod gMethods[] = {    /* name,signature, funcPtr */    {"init1", "([Ljava/lang/String;)V", (void*) android_server_SystemServer_init1},};int register_android_server_SystemServer(JNIEnv* env){    returnjniRegisterNativeMethods(env, "com/android/server/SystemServer",           gMethods, NELEM(gMethods));}}; // namespace android

代碼不是很多,也比較好讀,調用jniRegisterNativeMethods方法註冊SystemServer的Java方法也本地方法映射關係,jniRegisterNativeMethods是一個本地方法的註冊Helper方法。

SystemServer.java在載入了libandroid_servers.so庫之後,調用了init1(),通過上面代碼中的映射關係可知,它調用了本地的android_server_SystemServer_init1方法,該方法直接調用system_init(),其實現在frameworks/base/cmds/system_server/library/system_init.cpp中實現:

[cpp]
view plaincopyprint?
  1. extern "C" status_t system_init() 
  2.    LOGI("Entered system_init()"); 
  3.    sp<ProcessState> proc(ProcessState::self()); 
  4.    sp<IServiceManager> sm = defaultServiceManager(); 
  5.    LOGI("ServiceManager: %p\n", sm.get()); 
  6.    sp<GrimReaper> grim = new GrimReaper(); 
  7.    sm->asBinder()->linkToDeath(grim, grim.get(), 0); 
  8.  
  9.     charpropBuf[PROPERTY_VALUE_MAX]; 
  10.    property_get("system_init.startsurfaceflinger", propBuf,"1"); 
  11.     if(strcmp(propBuf, "1") == 0) { 
  12.         // Startthe SurfaceFlinger 
  13.        SurfaceFlinger::instantiate(); 
  14.     } 
  15.  
  16.     property_get("system_init.startsensorservice", propBuf,"1"); 
  17.     if(strcmp(propBuf, "1") == 0) { 
  18.         // Startthe sensor service 
  19.        SensorService::instantiate(); 
  20.     } 
  21.     LOGI("Systemserver: starting Android runtime.\n"); 
  22.    AndroidRuntime* runtime = AndroidRuntime::getRuntime(); 
  23.  
  24.    LOGI("System server: starting Android services.\n"); 
  25.     JNIEnv* env =runtime->getJNIEnv(); 
  26.     if (env ==NULL) { 
  27.         returnUNKNOWN_ERROR; 
  28.     } 
  29.  
  30.     jclass clazz= env->FindClass("com/android/server/SystemServer"); 
  31.     if (clazz ==NULL) { 
  32.         returnUNKNOWN_ERROR; 
  33.     } 
  34.  
  35.     jmethodIDmethodId = env->GetStaticMethodID(clazz,
    "init2","()V"); 
  36.     if (methodId== NULL) { 
  37.         returnUNKNOWN_ERROR; 
  38.     } 
  39.    env->CallStaticVoidMethod(clazz, methodId); 
  40.  
  41.     LOGI("System server: entering thread pool.\n"); 
  42.    ProcessState::self()->startThreadPool(); 
  43.    IPCThreadState::self()->joinThreadPool(); 
  44.    LOGI("System server: exiting thread pool.\n"); 
extern "C" status_t system_init(){   LOGI("Entered system_init()");   sp<ProcessState> proc(ProcessState::self());   sp<IServiceManager> sm = defaultServiceManager();   LOGI("ServiceManager: %p\n", sm.get());   sp<GrimReaper> grim = new GrimReaper();   sm->asBinder()->linkToDeath(grim, grim.get(), 0);    charpropBuf[PROPERTY_VALUE_MAX];   property_get("system_init.startsurfaceflinger", propBuf,"1");    if(strcmp(propBuf, "1") == 0) {        // Startthe SurfaceFlinger       SurfaceFlinger::instantiate();    }    property_get("system_init.startsensorservice", propBuf,"1");    if(strcmp(propBuf, "1") == 0) {        // Startthe sensor service       SensorService::instantiate();    }    LOGI("Systemserver: starting Android runtime.\n");   AndroidRuntime* runtime = AndroidRuntime::getRuntime();   LOGI("System server: starting Android services.\n");    JNIEnv* env =runtime->getJNIEnv();    if (env ==NULL) {        returnUNKNOWN_ERROR;    }    jclass clazz= env->FindClass("com/android/server/SystemServer");    if (clazz ==NULL) {        returnUNKNOWN_ERROR;    }    jmethodIDmethodId = env->GetStaticMethodID(clazz, "init2","()V");    if (methodId== NULL) {        returnUNKNOWN_ERROR;    }   env->CallStaticVoidMethod(clazz, methodId);    LOGI("System server: entering thread pool.\n");   ProcessState::self()->startThreadPool();   IPCThreadState::self()->joinThreadPool();   LOGI("System server: exiting thread pool.\n");}

如果瞭解Binder機制的話,應該知道,sp<ProcessState> proc(ProcessState::self())開啟Binder驅動並會建立一個ProcessState對象並維持當前進程的Binder通訊的伺服器端。

如果系統屬性裡配置了system_init.startsensorservice 屬性為1,則通過SensorService::instantiate()啟動Sensor服務。

對於初學者最頭疼的就是追物件導向代碼中的重載,重寫的代碼了,SensorService::instantiate()調用的是其父類的方法,我們可以通過子類的定義找其繼承關係,然後順著繼承關係再來尋找方法的實現,如果在子類裡和父類裡都有方法的實現,那麼看參數的匹配,如果參數都相互匹配,那麼就是所謂的重寫,調用的是子類的方法。SensorService的定義如下:

@frameworks/base/services/sensorservice/SensroService.h

[cpp]
view plaincopyprint?
  1. class SensorService : 
  2.         publicBinderService<SensorService>, 
  3.         publicBnSensorServer, 
  4.         protectedThread 
class SensorService :        publicBinderService<SensorService>,        publicBnSensorServer,        protectedThread{

通過SensorService的定義可知,在當前類裡沒有instantiate方法的聲明,說明其調用的是父類的方法,其繼承了BinderService,BnSensorServer,Thread類(難道SensorService是一個線程??),順著繼承關係找,在BinderService裡可以找到instantiate方法的聲明。

@frameworks/base/include/binder/BinderService.h

[cpp]
view plaincopyprint?
  1. template<typename SERVICE> 
  2.  
  3. class BinderService 
  4. public: 
  5.     static status_t publish() { 
  6.        sp<IServiceManager> sm(defaultServiceManager()); 
  7.        returnsm->addService(String16(SERVICE::getServiceName()),
    new SERVICE()); 
  8.     } 
  9.  
  10.     static void publishAndJoinThreadPool() { 
  11.        sp<ProcessState> proc(ProcessState::self()); 
  12.        sp<IServiceManager> sm(defaultServiceManager()); 
  13.        sm->addService(String16(SERVICE::getServiceName()),
    new SERVICE()); 
  14.        ProcessState::self()->startThreadPool(); 
  15.        IPCThreadState::self()->joinThreadPool(); 
  16.     } 
  17.  
  18.     static void instantiate() { publish(); } 
  19.  
  20.     static status_t shutdown() { 
  21.         return NO_ERROR; 
  22.     } 
  23. }; 
template<typename SERVICE>class BinderService{public:    static status_t publish() {       sp<IServiceManager> sm(defaultServiceManager());       returnsm->addService(String16(SERVICE::getServiceName()), new SERVICE());    }    static void publishAndJoinThreadPool() {       sp<ProcessState> proc(ProcessState::self());       sp<IServiceManager> sm(defaultServiceManager());       sm->addService(String16(SERVICE::getServiceName()), new SERVICE());       ProcessState::self()->startThreadPool();       IPCThreadState::self()->joinThreadPool();    }    static void instantiate() { publish(); }    static status_t shutdown() {        return NO_ERROR;    }};

通過上面程式碼分析可知,instantiate方法建立了SensorService並通過addService將自己新建立的SensorService服務添加到Android服務列表裡了。

Ok,那我們來到SensorService服務中。

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

[cpp]
view plaincopyprint?
  1. SensorService::SensorService() 
  2.     :mInitCheck(NO_INIT) 
  3.  
  4. void SensorService::onFirstRef() 
  5.    LOGD("nuSensorService starting..."); 
  6.    SensorDevice& dev(SensorDevice::getInstance()); 
  7. … 
SensorService::SensorService()    :mInitCheck(NO_INIT){}void SensorService::onFirstRef(){   LOGD("nuSensorService starting...");   SensorDevice& dev(SensorDevice::getInstance());…

SensorService的構造方法比較簡單,初始化了成員變數mInitCheck為NO_INIT。

要注意構造方法後面的onFirstRef方法,它是Android系統裡引用計數系統裡的一個方法。當RefBase的子類對象被第一次強引用時自動調用其方法,所以當第一次使用SensorService服務裡該方法被自動回調。

形如:

[cpp]
view plaincopyprint?
  1. sp< ISensorServer> sm(mSensorService); 
sp< ISensorServer> sm(mSensorService);

註:關於引用計數系統,如果讀者不太瞭解,請參考鄧凡平老師的:深入理解:Android系統核心 卷I中的三板斧部分。

SensorService的啟動到此暫停,等待上層應用的使用SensorService服務並調用onFirstRef方法。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.