Compile the JNI method for the hardware abstraction layer (HAL) module of Android in Ubuntu to provide the Java access hardware service interface (Lao Luo study note 4), androidjni
In the last two articles, we introduced how to write drivers for Android hardware, including how to implement kernel drivers in Linux kernel space and Hardware Abstraction Layer interfaces in user space. The purpose of both is to provide a hardware access interface to the previous layer, that is, to provide hardware services for the Android Application Frameworks layer. We know that Android applications are written in Java and hardware drivers are implemented in C,How does the Java interface access the C interface?As we all know, Java provides JNI method calls. Similarly, in Android systems, Java applications call the hardware abstraction layer interface through JNI. In this article, we will introduce how to compile the JNI method for the Android hardware abstraction layer interface so that upper-layer Java applications can use the underlying hardware services.
I. refer to add the hardware abstraction layer (HAL) module to Android on Ubuntu to access the Linux kernel driver. Prepare the hardware abstraction layer module to ensure the Android system image file system. img already contains hello. default module.
2. Go to the frameworks/base/services/jni directory and create the com_android_server_HelloService.cpp file:
USER-NAME @ MACHINE-NAME :~ /Android $ cd frameworks/base/services/jni
USER-NAME @ MACHINE-NAME :~ /Android/frameworks/base/services/jni $ vi com_android_server_HelloService.cpp
In the com_android_server_HelloService.cpp file, implement the JNI method. Note the command method of the file. The com_android_server prefix indicates the package name, indicating that the hardware service HelloService is placed in the com/android/server directory under the frameworks/base/services/java directory, that is, a command named com. android. server. helloService class. Here, we will skip the description of the HelloService class for the moment. In the next article, we will return to the HelloService class. Simply put,HelloService is a hardware access service class that provides Java interfaces..
First, it contains the corresponding header file:
#define LOG_TAG "HelloService" //
#include "jni.h" Some function definitions used by the // jni layer
#include "JNIHelp.h" //? ? The role of each header file, seek expert guidance? ? ? ? ? ? ? ? ? ? ? ? Thank you
#include "android_runtime / AndroidRuntime.h" //?
#include <utils / misc.h> //?
#include <utils / Log.h> //?
#include <hardware / hardware.h> // need to call the underlying interface such as: hello_device
#include <hardware / hello.h> #include <stdio.h>
Then define the three JNI methods hello_init, hello_getVal and hello_setVal:
namespace android
{
/ * The hardware access structure defined in the hardware abstraction layer, refer to <hardware / hello.h> * /
struct hello_device_t * hello_device = NULL;
/ * Set the value of the hardware register val through the hardware access interface defined by the hardware abstraction layer * /
/ * Write * /
static void hello_setVal (JNIEnv * env, jobject clazz, jint value) {// JNIEnv *, jobject, jint type
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); // Execute the bottom layer: set_val
}
/ * Read the value of the hardware register val through the hardware access interface defined by the hardware abstraction layer * /
/ *-Read-* /
Static jint hello_getVal (JNIEnv * env, jobject clazz) {
int val = 0;
if (! hello_device) {
LOGI ("Hello JNI: device is not open.");
return val;
}
hello_device-> get_val (hello_device, & val); // Execute the bottom layer: get_val (just run it)
LOGI ("Hello JNI: get value% d from device.", Val);
return val;
}
/ * Open the hardware device through the hardware module definition interface defined by the hardware abstraction layer * /
static inline int hello_device_open (const hw_module_t * module, struct hello_device_t ** device) {// inline: built-in function
return module-> methods-> open (module, HELLO_HARDWARE_MODULE_ID, (struct hw_device_t **) device);
}
/ * Load the specified hardware abstraction layer module by hardware module ID and turn on the hardware * /
/ *-Bool is the variable type in C, jboolean is the variable type in JNI, and boolean is the variable type in Java;
The definition of jboolean in C language is:
Typedef unsigned char jboolean;-* /
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) {// call the hello_device_open () function
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;
}
/ * JNI method table * /
static const JNINativeMethod method_table [] = {// top-level only
{"init_native", "() Z", (void *) hello_init},
{"setVal_native", "(I) V", (void *) hello_setVal},
{"getVal_native", "() I", (void *) hello_getVal},
};
/ * Register JNI method * /
int register_android_server_HelloService (JNIEnv * env) {//http://blog.csdn.net/horkychen/article/details/10952249
return jniRegisterNativeMethods (env, "com / android / server / HelloService", method_table, NELEM (method_table));
}
};
Note that in the hello_init function, the hardware abstraction layer module whose module ID is HELLO_HARDWARE_MODULE_ID is loaded by the hw_get_module method provided by the Android hardware abstraction layer, where HELLO_HARDWARE_MODULE_ID is defined in <hardware / hello.h>. The Android hardware abstraction layer will find the corresponding module in the / system / lib / hw directory of the Android system according to the value of HELLO_HARDWARE_MODULE_ID, then load it up, and return the hw_module_t interface for the caller to use. In the jniRegisterNativeMethods function, the value of the second parameter must correspond to the path of the package where HelloService is located, that is, com.android.server.HelloService.
3. Modify the onload.cpp file in the same directory, first add the register_android_server_HelloService function declaration in namespace android:
namespace android {
........................................ ............................
int register_android_server_HelloService (JNIEnv * env);
};
Add the register_android_server_HelloService function call in JNI_onLoad: extern "C" jint JNI_onLoad (JavaVM * vm, void * reserved) {................. ........................................ .................... register_android_server_HelloService (env); ......... ........................................ ...} In this way, when the Android system is initialized, the JNI method call table is automatically loaded. 4. Modify the Android.mk file in the same directory, and add a line to the LOCAL_SRC_FILES variable: LOCAL_SRC_FILES: = \ com_android_server_AlarmManagerService.cpp \ com_android_server_BatteryService.cpp \ com_android_server_Input_.Manager_cpp \ com_android_server_LightsService.com_cpp \ pp \ com_android_server_VibratorService.cpp \ com_android_server_location_GpsLocationProvider.cpp \ com_android_server_HelloService.cpp / onload.cpp V. Compile and re-find billion system.img: USER-NAME @ MACHINE-NAME: ~ / Android $ mmm frameworks / base / services / jni USER-NAME @ MACHINE-NAME: ~ / Android $ make snod In this way, the repackaged system.img image file contains the JNI method we just wrote, that is, we can call these through the hardware service HelloService provided by the Application Frameworks layer of the Android system JNI method, The hardware abstraction layer calls the low-level interface to access the hardware. As mentioned earlier, in this article, we temporarily ignore the implementation of the HelloService class. In the next article, we will describe how to implement the hardware service HelloService, so stay tuned.
1.
make: enter directory '/opt/FriendlyARM/tiny4412/android/android-4.1.2'
make: *** There are no rules to create the target "out / target / product / generic / obj / SHARED_LIBRARIES / libandroid_servers_intermediates / import_includes" "out / target / product / generic / obj / SHARED_LIBRARIES / libc_intermediates / export_includes". stop.
make: leave the directory "/opt/FriendlyARM/tiny4412/android/android-4.1.2"
root @ phone-desktop: /opt/FriendlyARM/tiny4412/android/android-4.1.2#
Solution:
. setenv
Output:
out / target / product / tiny4412 / system / lib / libandroid_servers.so