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;
}