您的位置:首页 > 移动开发 > Android开发

Android HAL实例解析(2)

2012-08-07 21:13 489 查看


4、第一种方法:直接调用service方法的实现过程

下面分析第一种方法中,各层的关键代码。


(1)HAL层

一般来说HAL moudle需要涉及的是三个关键结构体:

struct hw_module_t;

struct hw_module_methods_t;

struct hw_device_t;

下面结合代码说明这3个结构的用法。部分代码经过修改,后面的章节会给出修改的原因。

文件:mokoid-read-only/hardware/modules/include/mokoid/led.h



struct led_module_t {
struct hw_module_t common;
};
//HAL 规定不能直接使用hw_module_t结构,因此需要做这么一个继承。
struct led_control_device_t {
//自定义的一个针对Led控制的结构,包含hw_device_t和支持的API操作
struct hw_device_t common;
/* attributes */
int fd; //可用于具体的设备描述符
/* supporting control APIs go here */
int (*set_on)(struct led_control_device_t *dev, int32_t led);
int (*set_off)(struct led_control_device_t *dev, int32_t led);
};
#define LED_HARDWARE_MODULE_ID "led"
//定义一个MODULE_ID,HAL层可以根据这个ID找到我们这个HAL stub

文件:mokoid-read-only/hardware/modules/led/led.c

#define LOG_TAG "MokoidLedStub"
#include <hardware/hardware.h>
#include <fcntl.h>
#include <errno.h>
#include <cutils/log.h>
#include <cutils/atomic.h>
//#include <mokoid/led.h>
#include "../include/mokoid/led.h"
/*****************************************************************************/
int fd; //硬件led的设备描述符 。你也可以用led_control_device_t结构中定义的fd
#define GPG3DAT2_ON 0x4800 //ioctl控制命令
#define GPG3DAT2_OFF 0x4801
int led_device_close(struct hw_device_t* device)
{
struct led_control_device_t* ctx = (struct led_control_device_t*)device;
if (ctx) {
free(ctx);
}
close(fd);
return 0;
}
int led_on(struct led_control_device_t *dev, int32_t led)
{
LOGI("LED Stub: set %d on.", led);
ioctl(fd,GPG3DAT2_ON,NULL); //控制Led亮灭,和硬件相关
return 0;
}
int led_off(struct led_control_device_t *dev, int32_t led)
{
LOGI("LED Stub: set %d off.", led);
return 0;
}
static int led_device_open(const struct hw_module_t* module, const char* name,
struct hw_device_t** device)
{
struct led_control_device_t *dev;
dev = (struct led_control_device_t *)malloc(sizeof(*dev));
memset(dev, 0, sizeof(*dev));
dev->common.tag = HARDWARE_DEVICE_TAG;
dev->common.version = 0;
dev->common.module = module;
dev->common.close = led_device_close;
dev->set_on = led_on; //实例化支持的操作
dev->set_off = led_off;
*device = &dev->common; //将实例化后的led_control_device_t地址返回给jni层
//这样jni层就可以直接调用led_on、led_off、led_device_close方法了。
if((fd=open("/dev/led",O_RDWR))==-1) //打开硬件设备
{
LOGE("LED open error");
}
else
LOGI("open ok");
success:
return 0;
}
static struct hw_module_methods_t led_module_methods = {
open: led_device_open
};
const struct led_module_t HAL_MODULE_INFO_SYM = {
//定义这个对象等于向系统注册了一个ID为LED_HARDWARE_MODULE_ID的stub。注意这里HAL_MODULE_INFO_SYM的名称不能改。
common: {
tag: HARDWARE_MODULE_TAG,
version_major: 1,
version_minor: 0,
id: LED_HARDWARE_MODULE_ID,
name: "Sample LED Stub",
author: "The Mokoid Open Source Project",
methods: &led_module_methods, //实现了一个open的方法供jni层调用,
//从而实例化led_control_device_t
}
/* supporting APIs go here */
};


(2)JNI层

文件:mokoid-read-only/frameworks/base/service/jni/com_mokoid_server_LedService.cpp

struct led_control_device_t *sLedDevice = NULL;

static jboolean mokoid_setOn(JNIEnv* env, jobject thiz, jint led)
{
LOGI("LedService JNI: mokoid_setOn() is invoked.");

if (sLedDevice == NULL) {
LOGI("LedService JNI: sLedDevice was not fetched correctly.");
return -1;
} else {
return sLedDevice->set_on(sLedDevice, led);//调用hal层的注册的方法
}
}

static jboolean mokoid_setOff(JNIEnv* env, jobject thiz, jint led)
{
LOGI("LedService JNI: mokoid_setOff() is invoked.");


if (sLedDevice == NULL) {
LOGI("LedService JNI: sLedDevice was not fetched correctly.");
return -1;
} else {
return sLedDevice->set_off(sLedDevice, led); //调用hal层的注册的方法
}
}

/** helper APIs */
static inline int led_control_open(const struct hw_module_t* module,
struct led_control_device_t** device) {
return module->methods->open(module,
LED_HARDWARE_MODULE_ID, (struct hw_device_t**)device);
//这个过程非常重要,jni通过LED_HARDWARE_MODULE_ID找到对应的stub
}

static jboolean mokoid_init(JNIEnv *env, jclass clazz)
{
led_module_t* module;
LOGI("jni init-----------------------.");
if (hw_get_module(LED_HARDWARE_MODULE_ID, (const hw_module_t**)&module) == 0) {
//根据LED_HARDWARE_MODULE_ID找到hw_module_t,参考hal层的实现
LOGI("LedService JNI: LED Stub found.");
if (led_control_open(&module->common, &sLedDevice) == 0) {
//通过hw_module_t找到led_control_device_t
LOGI("LedService JNI: Got Stub operations.");
return 0;
}
}

LOGE("LedService JNI: Get Stub operations failed.");
return -1;
}

/*
* Array of methods.
* Each entry has three fields: the name of the method, the method
* signature, and a pointer to the native implementation.
*/
static const JNINativeMethod gMethods[] = {
{ "_init", "()Z", (void *)mokoid_init },//Framework层调用_init时促发
{ "_set_on", "(I)Z", (void *)mokoid_setOn },
{ "_set_off", "(I)Z", (void *)mokoid_setOff },
};
/*
*JNINativeMethod是jni层注册的方法,Framework层可以使用这些方法
*_init 、_set_on、_set_off是在Framework中调用的方法名称,函数的类型及返回值如下:
*()Z 无参数 返回值为bool型
* (I)Z 整型参数 返回值为bool型
*/
static int registerMethods(JNIEnv* env) {
static const char* const kClassName =
"com/mokoid/server/LedService";//注意:必须和你Framework层的service类名相同
jclass clazz;
/* look up the class */
clazz = env->FindClass(kClassName);
if (clazz == NULL) {
LOGE("Can't find class %s/n", kClassName);
return -1;
}
/* register all 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 out the rest of the ID cache */
return 0;
}
jint JNI_OnLoad(JavaVM* vm, void* reserved) {//Framework层加载jni库时调用
JNIEnv* env = NULL;
jint result = -1;
LOGI("JNI_OnLoad LED");
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
LOGE("ERROR: GetEnv failed/n");
goto fail;
}
assert(env != NULL);
if (registerMethods(env) != 0) { //注册你的JNINativeMethod
LOGE("ERROR: PlatformLibrary native registration failed/n");
goto fail;
}
/* success -- return valid version number */
result = JNI_VERSION_1_4;
fail:
return result;
}

(3)service (属于Framework层)

文件:frameworks/base/service/java/com/mokoid/server/LedService.java

package com.mokoid.server;
import Android.util.Config;
import Android.util.Log;
import Android.content.Context;
import Android.os.Binder;
import Android.os.Bundle;
import Android.os.RemoteException;
import Android.os.IBinder;
import mokoid.hardware.ILedService;
public final class LedService extends ILedService.Stub {
//对于这种直接模式不需要进程通讯,所以可以不加extends ILedService.Stub,此处加上主要是为了后面的第二种模式.
static {
System.load("/system/lib/libmokoid_runtime.so");//加载jni的动态库
}
public LedService() {
Log.i("LedService", "Go to get LED Stub...");
_init();
}
/*
* Mokoid LED native methods.
*/
public boolean setOn(int led) {
Log.i("MokoidPlatform", "LED On");
return _set_on(led);
}
public boolean setOff(int led) {
Log.i("MokoidPlatform", "LED Off");
return _set_off(led);
}
private static native boolean _init(); //声明jni库可以提供的方法
private static native boolean _set_on(int led);
private static native boolean _set_off(int led);
}


(4)APP 测试程序 (属于APP层)

文件:apps/LedClient/src/com/mokoid/LedClient/LedClient.java



package com.mokoid.LedClient;
import com.mokoid.server.LedService;// 导入Framework层的LedService
import Android.app.Activity;
import Android.os.Bundle;
import Android.widget.TextView;

public class LedClient extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Call an API on the library.
LedService ls = new LedService(); //实例化LedService
ls.setOn(1); //通过LedService提供的方法,控制底层硬件
ls.setOff(2);

TextView tv = new TextView(this);
tv.setText("LED 1 is on. LED 2 is off.");
setContentView(tv);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: