前面两篇博客记录了实现Linux驱动和使用HAL层访问Linux驱动的代码,我们分别对这两部分做了测试,他们都正常工作。有了前面的基础,我们就可以实现service层了,我们想系统注册我们自己的service,在service中访问HAL层,在HAL层中访问linux驱动…当然,我们要在应用程序中访问service,这要留到下一节来实现。
应用程序访问service设计到了进程间的通信,这要求我们使用(Android Interface definition language)来描述我们的service提供的接口,然后应用程序就可以通过binder来访问service 了。所以,我们先从aidl开始,逐步搭建我们的service层。
一.aidl
首先在frameworks/base/core/java/android/os/目录下新建HelloTestService.aidl文件,用来描述我们的service提供的接口:
package android.os;
interface IHelloTestService {
int wirteString(String str);
String readString();
}
我们的service只提供两个方法,一个写字符串,另一个读字符串。写好aidl文件后,执行mmm framework/base进行编译,编译后会在out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/os/目录下生成IHelloTestService.java文件。
IHelloTestService.java文件中实现了使用binder通信的一些方法,同时还包含了我们在接口中定义的两个方法。接下来,我们需要实现这两个方法。
二.HelloTestService.java
在framework/base/service/core/java/com/android/server/下新建HelloTestService.java文件,也就是创建HelloTestService类,这个类继承了IHelloTestService中的Stub内部类,我们需要复写其中的我们在aidl中定义的两个方法。
package com.android.server;
import android.content.Context;
import android.os.IHelloTestService;
import android.util.Slog;
public class HelloTestService extends IHelloTestService.Stub {
private static final String TAG = "HelloTestService";
HelloTestService() {
init_native();
}
public int wirteString(java.lang.String str){
return wirteString_native(str);
}
public java.lang.String readString() {
return readString_native();
}
private static native boolean init_native();
private static native int wirteString_native(String str);
private static native String readString_native();
};
这个类中是java中的类,java是不能直接访问C/C++代码的,必须使用jni来实现。因此,我们在这里简单调用jni中对应的方法即可。
三.实现jni访问HAL
在java对应native代码中,就可以使用C/C++来访问C/C++代码了,回想下我们在上节测试hal层代码时写的测试代码,这部分代码将与之类似,只不过,因为这部分代码需要供java层调用,所以它需要遵寻固定的格式。
jni层代码如下:
#define LOG_TAG "HelloTestService"
#include "JNIHelp.h"
#include "jni.h"
#include <utils/Log.h>
#include <utils/misc.h>
#include <utils/String8.h>
#include <dirent.h>
#include &l