Android架构实例分析之注册hello HAL的JNI方法表

摘要:

Android JNI是一种技术,提供Java调用Android native代码或者native调用Java代码的一种机制,并不提供策略。本文实现了基于前面两篇文章:

Android标准架构实例分析之编写最简单的hello驱动
http://blog.csdn.net/eliot_shao/article/details/51860229

Android架构实例分析之编写hello驱动的HAL层代码
http://blog.csdn.net/eliot_shao/article/details/51861905

所实现的JNI案例。对HAL层提供的方法进行“翻译”,并转化成android runtime的JNI方法表,当Java代码调用时候可以正确的寻找到native的代码。

JNI原理分析

首先上一张Android JNI技术的工作原理图:

在图中主要描述Java-jni-native的一个调用流程。下面进行按步骤讲解:
1、Java代码通过System.loadLibrary(“android_servers”); 加载JNI静态库;
2、Android runtime自动调用JNI静态库中的JNI_OnLoad函数;
3、JNI_OnLoad调用jniRegisterNativeMethods函数,注册多个或者一个JNINativeMethod到Android runtime的gMthods链表中;
4、Java代码声明并调用相关的native代码;
5、Android runtime查找gMthods链表找到前面注册的本地函数指针,然后执行。

注意:JNI和HAL的衔接是通过JNI的代码

hw_get_module(HELLO_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0) 

实现的。

本文使用的hello的案例是以system_server进程上建立的,后面会创建一个hello的本地服务。下面是对system_server进程调用JNI过程进行分析。

1、frameworks\base\services\java\com\android\server\SystemServer.java

    // Initialize native services.    System.loadLibrary("android_servers");

2、frameworks\base\services\core\jni\onload.cpp

jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)register_android_server_HelloService(env);//add by eliot_shao

3、frameworks\base\services\core\jni\com_android_server_HelloService.cpp

jniRegisterNativeMethods(env, "com/android/server/HelloService", method_table, NELEM(method_table));static const JNINativeMethod method_table[] = {        {"init_native", "()Z", (void*)hello_init},        {"setVal_native", "(I)V", (void*)hello_setVal},        {"getVal_native", "()I", (void*)hello_getVal},    };

4、frameworks\base\services\Android.mk

LOCAL_MODULE:= libandroid_servers

hello JNI实例

rameworks\base\services\core\jni\com_android_server_HelloService.cpp

#define LOG_TAG "HelloService"#include "jni.h"#include "JNIHelp.h"#include "android_runtime/AndroidRuntime.h"#include #include #include #include #include namespace android{    struct hello_device_t* hello_device = NULL;    static void hello_setVal(JNIEnv* env, jobject clazz, jint value) {        int val = value;        ALOGI("Hello JNI: set value %d to device.", val);        if(!hello_device) {            ALOGI("Hello JNI: device is not open.");            return;        }        hello_device->set_val(hello_device, val);    }    static jint hello_getVal(JNIEnv* env, jobject clazz) {        int val = 0;        if(!hello_device) {            ALOGI("Hello JNI: device is not open.");            return val;        }        hello_device->get_val(hello_device, &val);        ALOGI("Hello JNI: get value %d from device.", val);        return val;    }    static inline int hello_device_open(const hw_module_t* module, struct hello_device_t** device) {        return module->methods->open(module, HELLO_HARDWARE_MODULE_ID, (struct hw_device_t**)device);    }    static jboolean hello_init(JNIEnv* env, jclass clazz) {        hello_module_t* module;        ALOGI("Hello JNI: initializing......");        if(hw_get_module(HELLO_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0) {            ALOGI("Hello JNI: hello Stub found.");            if(hello_device_open(&(module->common), &hello_device) == 0) {                ALOGI("Hello JNI: hello device 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;          }    static const JNINativeMethod method_table[] = {        {"init_native", "()Z", (void*)hello_init},        {"setVal_native", "(I)V", (void*)hello_setVal},        {"getVal_native", "()I", (void*)hello_getVal},    };    int register_android_server_HelloService(JNIEnv *env) {    return jniRegisterNativeMethods(env, "com/android/server/HelloService", method_table, NELEM(method_table));    }   };

frameworks\base\services\core\jni\onload.cpp

/** Copyright (C) 2014 MediaTek Inc.* Modification based on code covered by the mentioned copyright* and/or permission notice(s).*//* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#include "JNIHelp.h"#include "jni.h"#include "utils/Log.h"#include "utils/misc.h"namespace android {int register_android_server_AlarmManagerService(JNIEnv* env);int register_android_server_AssetAtlasService(JNIEnv* env);int register_android_server_BatteryStatsService(JNIEnv* env);int register_android_server_ConsumerIrService(JNIEnv *env);int register_android_server_InputApplicationHandle(JNIEnv* env);int register_android_server_InputWindowHandle(JNIEnv* env);int register_android_server_InputManager(JNIEnv* env);int register_android_server_LightsService(JNIEnv* env);int register_android_server_PowerManagerService(JNIEnv* env);int register_android_server_SerialService(JNIEnv* env);int register_android_server_SystemServer(JNIEnv* env);int register_android_server_UsbDeviceManager(JNIEnv* env);int register_android_server_UsbMidiDevice(JNIEnv* env);int register_android_server_UsbHostManager(JNIEnv* env);int register_android_server_VibratorService(JNIEnv* env);int register_android_server_location_GpsLocationProvider(JNIEnv* env);int register_android_server_location_FlpHardwareProvider(JNIEnv* env);int register_android_server_connectivity_Vpn(JNIEnv* env);int register_android_server_hdmi_HdmiCecController(JNIEnv* env);int register_android_server_tv_TvInputHal(JNIEnv* env);int register_android_server_PersistentDataBlockService(JNIEnv* env);int register_android_server_Watchdog(JNIEnv* env);int register_com_mediatek_perfservice_PerfServiceManager(JNIEnv* env);#if defined (MTK_HDMI_SUPPORT)int register_com_mediatek_hdmi_MtkHdmiManagerService(JNIEnv* env);#endif// Mediatek AAL supportint register_android_server_display_DisplayPowerController(JNIEnv* env);#ifndef MTK_BSP_PACKAGEint register_com_android_internal_app_ShutdownManager(JNIEnv *env);#endifint register_android_server_HelloService(JNIEnv *env);//add by eliot_shao};using namespace android;extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */){    JNIEnv* env = NULL;    jint result = -1;    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {        ALOGE("GetEnv failed!");        return result;    }    ALOG_ASSERT(env, "Could not retrieve the env!");    register_android_server_PowerManagerService(env);    register_android_server_SerialService(env);    register_android_server_InputApplicationHandle(env);    register_android_server_InputWindowHandle(env);    register_android_server_InputManager(env);    register_android_server_LightsService(env);    register_android_server_AlarmManagerService(env);    register_android_server_UsbDeviceManager(env);    register_android_server_UsbMidiDevice(env);    register_android_server_UsbHostManager(env);    register_android_server_VibratorService(env);    register_android_server_SystemServer(env);    register_android_server_location_GpsLocationProvider(env);    register_android_server_location_FlpHardwareProvider(env);    register_android_server_connectivity_Vpn(env);    register_android_server_AssetAtlasService(env);    register_android_server_ConsumerIrService(env);    register_android_server_BatteryStatsService(env);    register_android_server_hdmi_HdmiCecController(env);    register_android_server_tv_TvInputHal(env);    register_android_server_PersistentDataBlockService(env);    register_android_server_Watchdog(env);    register_com_mediatek_perfservice_PerfServiceManager(env);#if defined (MTK_HDMI_SUPPORT)    register_com_mediatek_hdmi_MtkHdmiManagerService(env);#endif    // Mediatek AAL support    register_android_server_display_DisplayPowerController(env);#ifndef MTK_BSP_PACKAGE    register_com_android_internal_app_ShutdownManager(env);#endif    register_android_server_HelloService(env);//add by eliot_shao    return JNI_VERSION_1_4;}

编译:

android 2.3 和android 6.0版本的JNI位置发生了一点变化。
将com_android_server_HelloService.cpp放入frameworks\base\services\core\jni\
修改: LOGI–>ALOGI
LOGE–>ALOGE
修改onload.cpp 和 Android.mk
编译:mmm frameworks/base/services/

生成system/lib/libandroid_servers.so

更多相关文章

  1. LoganSquare——快速解析和序列化JSON对象的Android类库
  2. Android(安卓)MonkeyRunner测试NotePad例子(SDK中的源码实例)
  3. android中apk反编译
  4. OpenGL.Shader:1-重新认识Android上OpenGL(纯Cpp)
  5. Android(Java):对应用进行单元测试
  6. Android之MVP 模式:简单易懂的介绍方式
  7. Android(安卓)使用Glide加载图片
  8. android Aspectj实践问题
  9. android 一个很漂亮的控件ObservableScrollView(含片段代码和源码

随机推荐

  1. go-carbon1.2.5版本发布,新增两个互转方法
  2. 解决golang中vendor引起的相同类型,却提示
  3. 你知道为啥不再建议使用GOPATH以及如何使
  4. go语言有goto吗
  5. go语言都用什么框架
  6. go语言make的用法有哪些
  7. centos go语言环境怎么搭建
  8. go语言适合于哪些领域
  9. 有哪些大公司已经用Go语言了
  10. go语言有指针吗