结合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;

    }

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