結合HelloWrold整理Android Hal層訪問原理

HAL需要實現的核心數據結構

rootdir/hardware/libhardware/include/hardware/hardware.h

struct hw_module_t;

struct hw_module_methods_t;

struct hw_device_t;

 

typedef structhw_module_t {

         uint32_ttag;

 

         uint16_tmodule_api_version;

#define version_major module_api_version

 

   uint16_t hal_api_version;

#define version_minor hal_api_version

 

   /** Identifier of module */

   const char *id;

 

   /** Name of this module */

   const char *name;

 

   /** Author/owner/implementor of the module */

   const char *author;

 

   /** Modules methods */

   struct hw_module_methods_t* methods;

 

   /** module's dso */

   void* dso;

 

#ifdef __LP64__

   uint64_t reserved[32-7];

#else

   /** padding to 128 bytes, reserved for future use */

   uint32_t reserved[32-7];

#endif

} hw_module_t;

 

typedef structhw_module_methods_t {

   /** Open a specific device */

   int (*open)(const struct hw_module_t* module, const char* id,

           struct hw_device_t** device);

 

} hw_module_methods_t;

 

typedef structhw_device_t {

 

   uint32_t tag;

   uint32_t version;

   struct hw_module_t* module;

 

#ifdef __LP64__

   uint64_t reserved[12];

#else

   uint32_t reserved[12];

#endif

   int (*close)(struct hw_device_t* device);

 

} hw_device_t;

具體實現過程中,會繼承以上三個數據結構,實現模塊特定的功能

 

如何註冊以及調用HAL

Hal層實現上面數據結構後,會編譯生成.so放在/system/lib64/hw、vendor/lib64/hw或者/odm/lib/hw目錄下,當App有需要時依如下流程加載調用

app -> javaService -> jniService-> hal(.so)->drv

TranHello調用過程

App

App啓動時通過ServiceManager獲取服務HelloService

   protected void onCreate(Bundle savedInstanceState) {

       super.onCreate(savedInstanceState);

       setContentView(R.layout.activity_main);

 

        helloService =IHelloService.Stub.asInterface(

               ServiceManager.getService("hello"));

                   ......

         }

Framwork Java Service

HelloService實例化

   public HelloService() {

                Slog.v(TAG,"HelloService");

       init_native();

    }

實例化時候會調用init_native()函數,改函數在Framwork Jni Service實現

 

Framwork Jni Service

         開機的時候init_native()函數會被註冊到JVM

   int register_android_server_HelloService(JNIEnv *env) {

           return jniRegisterNativeMethods(env, "com/android/server/hello/HelloService",method_table, NELEM(method_table));

    }

 

extern "C" jintJNI_OnLoad(JavaVM* vm, void* /* reserved */)

{

         ......

    register_android_server_HelloService(env);

         returnJNI_VERSION_1_4;

}

 

         init_native函數簽名

   static const JNINativeMethod method_table[] = {

       {"init_native", "()Z",(void*)hello_init},

       {"setVal_native", "(I)V", (void*)hello_setVal},

       {"getVal_native", "()I", (void*)hello_getVal},

   };

 

         最終會調到hello_init函數

   static jboolean hello_init(JNIEnv* env,jclass clazz) {

       hello_module_t* module;

 

       if(

                            hw_get_module(HELLO_HARDWARE_MODULE_ID,

                            (const struct hw_module_t**)&module)== 0

                   ){

           ALOGE("Hello JNI: hello Stub found.");

           if(hello_device_open(&(module->common),&hello_device) == 0) {

                ALOGE("Hello JNI: hellodevice is open.");

                return 0;

           }

           ALOGE("Hello JNI: failed to open hello device.");

           return -1;

       }

       ALOGE("Hello JNI: failed to get hello stub module.");

       return -1;

    }

 

hello_init函數首先會調用hw_get_module加載hello.mt6763.so得到操作so的對象hw_module_t對象HMI

【關於hw_get_module函數的實現原理可參考[3] hello_framworks_jni_test_ok/JNI.docx

 

hello_init接着會調用hello_device_open函數得到hello_device

   static inline int hello_device_open(const hw_module_t* module, structhello_device_t** device) {

       return module->methods->open(module, HELLO_HARDWARE_MODULE_ID, (structhw_device_t**)device);

    }

hello_init函數執行完成之後會得到一個初始化好的hello_device_t對象,之後JNI層的所有操作都是通過這個hello_device_t完成的

Hal Interface

/*模塊方法表*/

static struct hw_module_methods_thello_module_methods = {

   open: hello_device_open

};

 

/*模塊實例變量*/

struct hello_module_t HAL_MODULE_INFO_SYM ={

   common: {

       tag: HARDWARE_MODULE_TAG,

       version_major: 1,

       version_minor: 0,

       id: HELLO_HARDWARE_MODULE_ID,

       name: MODULE_NAME,

       author: MODULE_AUTHOR,

       methods: &hello_module_methods,

    }

};

 

//hello_device_open

/***************************************************************************************************************************************************/

static int hello_device_open(const structhw_module_t* module, const char* name, struct hw_device_t** device) {

   struct hello_device_t* dev;

       dev = (struct hello_device_t*)malloc(sizeof(struct hello_device_t));

  

       ALOGE("Hello Stub: hello_device_open start");

 

   if(!dev) {

       ALOGE("Hello Stub: failed to alloc space");

       return -EFAULT;

    }

 

   memset(dev, 0, sizeof(struct hello_device_t));

   dev->common.tag = HARDWARE_DEVICE_TAG;

   dev->common.version = 0;

   dev->common.module = (hw_module_t*)module;

   dev->common.close = hello_device_close;

   dev->set_val = hello_set_val;dev->get_val = hello_get_val;

 

   if((dev->fd = open(DEVICE_NAME, O_RDWR)) == -1) {

       ALOGE("Hello Stub: failed to open /dev/hello -- %s.",strerror(errno));free(dev);

       return -EFAULT;

    }

 

    *device = &(dev->common);

   ALOGE("Hello Stub: open /dev/hello successfully.");

 

   return 0;

}

最終到hello_device_open完成之後就將hello模塊的所有操作方法註冊到hello_device對象並返回給Framwork Jni Service,Framwork Jni Service在通過JNI簡介呈現給Framwork Java Service的HelloService,最終App就可以通過HelloService操作整個hello模塊了

 

總結

當App onCreate時,通過ServiceManager獲取Framwork Java Service的時候,實際上會實例化一個Service,在Service實例化過程中,實際上是會通過JNI規則在JNI層通過hw_get_module函數調用load函數加載對應的so獲取到對應的hw_module_t對象,進而通過hw_module_methods_t對象的open接口將模塊的操作方法加載到hw_device_t對象中返回給JNI層,JNI層通過hw_device_t的子類對象實現模塊的各種操作方法,並並通過JNI_Onload函數註冊到JVM中,以滿足Framwork Java Service的調用,Framwork Java Service需要實現AIDL接口中定義的方法,在這些方法中通過JNI調用Framwork Jni Service封裝的各種操作方法

 

Hal層數據結構

hw_get_module() -> hw_module_t ->hw_module_method_t -> open -> hw_device_t

 

jni實現

         staticvoid hello_setVal(JNIEnv* env, jobject clazz, jint value) {

       int val = value;

 

       if(!hello_device) {

           return;

       }

 

       hello_device->set_val(hello_device,val);

    }

   static jint hello_getVal(JNIEnv* env, jobject clazz) {

       int val = 0;

 

        if(!hello_device) {

           return val;

       }

       hello_device->get_val(hello_device,&val);

 

       return val;

    }

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