[Android的系统移植与平台开发]led HAL案例分析(4)
让我们来到底层本地代码,先看下底层代码的Android.mk文件:
@ frameworks/Android.mk:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE:= libled_runtime # 编译目标模块
LOCAL_SRC_FILES:= \
services/jni/com_farsight_LedService.cpp
LOCAL_SHARED_LIBRARIES := \ # 编译时依赖的动态库
libandroid_runtime \
libnativehelper \
libcutils\
libutils\
libhardware
LOCAL_C_INCLUDES += \ #编译时用到的头文件目录
$(JNI_H_INCLUDE)
LOCAL_PRELINK_MODULE := false # 本目标为非预链接模块
include $(BUILD_SHARED_LIBRARY) # 编译生成共享动态库
结合前面分析的Android.mk不难看懂这个mk文件。之前的mk文件是编译成Android apk文件,这儿编译成so共享库,所以LOCAL_MODULE和include $(BUILD_SHARED_LIBRARY)与前面mk文件不同,关于Android.mk文件里的变量作用,请查看Android编译系统章节。
总而言之,本地代码编译生成的目标是libled_runtime.so文件。
4) Led本地服务代码分析
我们来看下本地服务的源码:
@ frameworks/services/jni/com_hello_LedService.cpp:
#define LOG_TAG "LedService"
#include "utils/Log.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <jni.h>
#include "../../../hardware/led.h"
static led_control_device_t *sLedDevice = 0;
static led_module_t* sLedModule=0;
static jint get_count(void)
{
LOGI("%sE", __func__);
if(sLedDevice)
returnsLedDevice->get_led_count(sLedDevice);
else
LOGI("sLedDevice is null");
return 0;
}
static jint led_setOn(JNIEnv* env, jobject thiz) {
LOGI("%sE", __func__);
if(sLedDevice) {
sLedDevice->set_on(sLedDevice);
}else{
LOGI("sLedDevice is null");
}
return 0;
}
static jintled_setOff(JNIEnv* env, jobject thiz) {
LOGI("%s E", __func__);
if(sLedDevice) {
sLedDevice->set_off(sLedDevice);
}else{
LOGI("sLedDevice is null");
}
return 0;
}
static inline int led_control_open(const structhw_module_t* module,
structled_control_device_t** device) {
LOGI("%s E ", __func__);
returnmodule->methods->open(module,
LED_HARDWARE_MODULE_ID, (struct hw_device_t**)device);
}
static jintled_init(JNIEnv *env, jclass clazz)
{
led_module_tconst * module;
LOGI("%s E ", __func__);
if(hw_get_module(LED_HARDWARE_MODULE_ID, (const hw_module_t**)&module) == 0){
LOGI("get Module OK");
sLedModule = (led_module_t *) module;
if(led_control_open(&module->common, &sLedDevice) != 0) {
LOGI("led_init error");
return-1;
}
}
LOGI("led_init success");
return 0;
}
/*
*
* Array ofmethods.
* Each entryhas three fields: the name of the method, the method
* signature,and a pointer to the native implementation.
*/
static constJNINativeMethod gMethods[] = {
{"_init", "()Z",(void*)led_init},
{"_set_on", "()I",(void*)led_setOn },
{"_set_off", "()I",(void*)led_setOff },
{"_get_count", "()I",(void*)get_count },
};
static intregisterMethods(JNIEnv* env) {
static constchar* const kClassName = "com/hello/LedService";
jclassclazz;
/* look upthe class */
clazz =env->FindClass(kClassName);
if (clazz ==NULL) {
LOGE("Can't find class %s\n", kClassName);
return-1;
}
/* registerall the methods */
if(env->RegisterNatives(clazz, gMethods,
sizeof(gMethods) / sizeof(gMethods[0])) != JNI_OK)
{
LOGE("Failed registering methods for %s\n", kClassName);
return -1;
}
/* fill outthe rest of the ID cache */
return 0;
}
/*
* This iscalled by the VM when the shared library is first loaded.
*/
jintJNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env= NULL;
jint result= -1;
LOGI("JNI_OnLoad");
if(vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
LOGE("ERROR: GetEnv failed\n");
gotofail;
}
assert(env!= NULL);
if(registerMethods(env) != 0) {
LOGE("ERROR: PlatformLibrary nativeregistration failed\n");
gotofail;
}
/* success-- return valid version number */
result =JNI_VERSION_1_4;
fail:
returnresult;
}