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

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 <utils/misc.h>
#include <utils/Log.h>
#include <hardware/hardware.h>
#include <hardware/hello.h>
#include <stdio.h>
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 support
int register_android_server_display_DisplayPowerController(JNIEnv* env);
#ifndef MTK_BSP_PACKAGE
int register_com_android_internal_app_ShutdownManager(JNIEnv *env);
#endif

int 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

编译结果

posted @ 2016-12-08 23:14  张同光  阅读(123)  评论(0编辑  收藏  举报