How to provide an interface summary through the JNI method in Android

Source: Internet
Author: User

References:

Http://blog.csdn.net/luoshengyang/article/details/6575988

Http://www.androidmi.com/Androidkaifa/rumen/201005/633.html

1. What is JNI?

JNI is the abbreviation of Java Native Interface, that is, Java Local interface. since Java, the JNI standard has become part of the Java platform. It allows Java code to interact with code written in other languages. JNI is a local programming interface that enables the Java code running inside the Java Virtual Machine (VM) to work with other programming languages (such as C, C ++, and assembly languages) to interact with the database.

The JNI method provided in Android allows Java programs to call C language programs. Many Java classes in Android have native interfaces. These native interfaces are implemented locally and then registered to the system.

Shows the role of JNI In the android hierarchy:

In Android, the main JNI code is in the following path:

Android source code root directory/frameworks/base/CORE/JNI/

The content in this path will be compiled into the library libandroid_runtime.so, which is a common dynamic library and placed in the/system/lib directory of the target system.

In addition, Android also contains other JNI libraries. For example, the JNI directory of the Media Section, frameworks/base/Media/JNI/, is compiled into the library libmedia_jni.so.

Each file in JNI is actually a common file in C ++, and its name generally corresponds to the supported Java classes. This relationship is a habit of writing, not forced.

The JNI library implemented in Android needs to be connected to the dynamic library libnativehelper. So.

2. register the JNI Method

There is an onload. cpp file in the root directory of the android source code/frameworks/base/services/JNI/directory. Its content is as follows:

/* * 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_BatteryService(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_UsbDeviceManager(JNIEnv* env);int register_android_server_UsbHostManager(JNIEnv* env);int register_android_server_VibratorService(JNIEnv* env);int register_android_server_SystemServer(JNIEnv* env);int register_android_server_location_GpsLocationProvider(JNIEnv* env);int register_android_server_connectivity_Vpn(JNIEnv* env);int register_android_server_HelloService(JNIEnv *env);};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) {        LOGE("GetEnv failed!");        return result;    }    LOG_ASSERT(env, "Could not retrieve the env!");    register_android_server_PowerManagerService(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_BatteryService(env);    register_android_server_UsbDeviceManager(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_connectivity_Vpn(env);    register_android_server_HelloService(env);    return JNI_VERSION_1_4;}

The upper part of the onload. cpp file is the registration function declaration, and the lower part is the registration function that calls various registration functions. These registration functions are the registration functions of the JNI method! Only through these registration functions can the upper layer call the registered JNI method.

These registration functions are composed of other functions in the same directory. in the CPP file, the above register_android_server_helloservice (ENV) function is implemented in the com_android_service_helloservice.cpp file. then how does the compiler know this? The answer is of course the Android. mk file. open the file with the following content:

LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_SRC_FILES:= \    com_android_server_AlarmManagerService.cpp \    com_android_server_BatteryService.cpp \    com_android_server_InputApplicationHandle.cpp \    com_android_server_InputManager.cpp \    com_android_server_InputWindowHandle.cpp \    com_android_server_LightsService.cpp \    com_android_server_PowerManagerService.cpp \    com_android_server_SystemServer.cpp \    com_android_server_UsbDeviceManager.cpp \    com_android_server_UsbHostManager.cpp \    com_android_server_VibratorService.cpp \    com_android_server_location_GpsLocationProvider.cpp \    com_android_server_connectivity_Vpn.cpp \    com_android_server_HelloService.cpp \    onload.cppLOCAL_C_INCLUDES += \    $(JNI_H_INCLUDE) \    frameworks/base/services \    frameworks/base/core/jni \    external/skia/include/coreLOCAL_SHARED_LIBRARIES := \    libandroid_runtime \    libcutils \    libhardware \    libhardware_legacy \    libnativehelper \    libsystem_server \    libutils \    libui \    libinput \    libskia \    libgui \    libusbhostifeq ($(WITH_MALLOC_LEAK_CHECK),true)    LOCAL_CFLAGS += -DMALLOC_LEAK_CHECKendifLOCAL_MODULE:= libandroid_serversinclude $(BUILD_SHARED_LIBRARY)

The paths of all implementation files (CPP files) are provided in local_src_file. Therefore, the Implementation files corresponding to each registration function can be found during compilation.

Next, let's take a look at the specific implementation process of one of the registration functions. For example, register_android_server_helloservice (ENV), open the com_android_service_helloservice.cpp file, and the implementation code of the registration function is as follows:

int register_android_server_HelloService(JNIEnv *env) {    return jniRegisterNativeMethods(env, "com/android/server/HelloService", method_table, NELEM(method_table));}

Among them, jniregisternativemethods is the registered JNI method function, which is very important in JNI method usage. The second parameter of this function corresponds to the Java class helloservice. java file name. The third parameter is the registered method table:

/* JNI 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 },};

The following is the implementation code of each interface in the method table.

For example, the implementation of the hello_setval function:

/* Set the Val value of the hardware register through the hardware access interface defined in the hardware abstraction layer */static void hello_setval (jnienv * ENV, jobject clazz, jint value) {int val = value; logi ("Hello JNI: Set Value % d to device. ", Val); If (! Hello_device) {Logi ("Hello JNI: device is not open."); return;} hello_device-> set_val (hello_device, Val );}

The implementation code of hello_init in the method list shows how to call the interface provided by the lower-level Hal. Remember the previous chapter:
In Android, how does Hal provide interfaces to the upper layer? How does Hal provide interfaces to the upper layer? The implementation of the hello_init function is a typical example of calling the initialization interface provided by Hal. See the implementation code of the hello_init function below:

/* Open the hardware device through the hardware module interface defined in the hardware abstraction layer */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 );} /* use the hardware module ID to load the specified Hardware Abstraction Layer module and open the hardware */static jboolean hello_init (jnienv * ENV, jclass clazz) {hello_module_t * module; logi ("Hello JNI: initializing ...... "); If (hw_get_module (hello_hardware_module_id, (const struct hw_module_t **) & module) = 0) {Logi (" Hello JNI: Hello stub found. "); If (hello_device_open (& (module-> common), & hello_device) = 0) {Logi (" Hello JNI: Hello device is open. "); Return 0;} LogE (" Hello JNI: failed to open Hello device. "); Return-1;} LogE (" Hello JNI: failed to get Hello stub module. "); Return-1 ;}

The preceding module-> methods-> OPEN function is the interface provided by Hal. Its function prototype is in hardware. the H header file is defined and can only return pointers of the struct hw_device_t type. In the JNI method, we are concerned about struct hello_device_t, only through struct hello_device_t, we can obtain all of its member functions (interface functions provided by Hal). Because the first member of struct hello_device_t is the data of the struct hw_device_t type, the obtained struct
Hw_device_t is forcibly converted to struct hello_device_t for use. If you haven't understood this yet, I suggest you go back to the previous article: how to provide an interface summary to the upper layer of Hal in Android.

3. Method list description

The following is a prototype of the static const jninativemethod method_table [] method list:

typedef struct {const char* name;const char* signature;void* fnPtr;} JNINativeMethod;

Andoird uses a different traditional Java JNI method to define its native function. An important difference is that andorid uses a ing table array of Java and C functions, and describes the parameters and return values of the functions. The type of this array is jninativemethod. See the preceding definition.

The first variable name is the name of the function in Java. The second variable signature describes the parameters and return values of the function using a string. The third variable fnptr is a function pointer pointing to the C function.

The second parameter is hard to understand, for example:

"() V"

"(Ii) V"

"(Ljava/lang/string;) V"

In fact, these characters correspond to the function parameter types one by one.

The character in "()" represents a parameter, and the subsequent character represents the return value. For example, "() V" indicates void func ();

"(Ii) V" indicates void func (INT, INT );

The relationship between each character is as follows:
Character Java type C type

V void
Z jboolean Boolean
I jint int
J jlong long
D jdouble double
F jfloat float
B jbyte byte
C jchar char
S jshort short

The array starts with "[" and is represented by two characters.

[I jintarray int []
[F jfloatarray float []
[B jbytearray byte []
[C jchararray char []
[S jshortarray short []
[D jdoublearray double []
[J jlongarray long []
[Z jbooleanarray Boolean []

The above are all basic types. If the Java function parameter is a class, it starts with "L" and ends with ";". The package and class name are separated by "/" in the middle. The parameter of the corresponding C function name is jobject. An exception is the string class, and its corresponding class is jstring.

Ljava/lang/string; string jstring
Ljava/NET/socket; socket jobject

If a Java function is located in an embedded class, $ is used as the delimiter between class names.

For example, "(ljava/lang/string; landroid/OS/fileutils $ filestatus;) z"

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.