上一章,我们理解了如何写一个JNI方法来访问HAL层的接口,这个JNI的方法最终是被Android Framework来进行调用,Android Framework最终又被Android的应用软件进行调用,从而实现从可视应用程序访问驱动寄存器的通路。本章我们一起来学习如何在Android Framework层来写接口供可视应用程序访问,并且访问JNI的接口。
1.新建AIDI代理
服务一般是运行在一个独立的进程中来为各个应用程序提供服务,因此应用程序需要访问服务的接口,就需要通过代理来试下,Android中主要通过AIDI代理实现。
创建方法:
cd /frameworks/base/core/java/android/os
vim IHelloService.aidl
IHelloService.aidl定义了IHelloService接口:
1 | package android.os; |
这个接口定义了setVal\getVal两个函数,用来读写设备的寄存器的值。
2.修改编译环境
cd framework/base
修改Android.mk
在下面一行后面添加黑体内容:1
2
3...
core/java/com/android/internal/widget/IRemoteViewsAdapterConnection.aidl \
core/java/android/os/IHelloService.aidl \
3.编译aidl
mmm framework/base
系统会根据IHelloService.aidl来生成IHelloService.Stub接口
4.新增服务java文件
进入到frameworks/base/services/java/com/android/server目录,新增HelloService.java文件:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20package com.android.server;
import android.content.Context;
import android.os.IHelloService;
import android.util.Slog;
public class HelloService extends IHelloService.Stub {
private static final String TAG = "HelloService";
HelloService() {
init_native();
}
public void setVal(int val) {
setVal_native(val);
}
public int getVal() {
return getVal_native();
}
private static native boolean init_native();
private static native void setVal_native(int val);
private static native int getVal_native();
};
HelloService主要是通过调用JNI方法init_native、setVal_native和getVal_native来提供硬件服务。
5.修改service启动
修改frameworks/base/services/java/com/android/server目录,新增HelloService的SystemServer.java文件,在ServerThread::run函数中增加加载HelloService的代码:1
2
3
4
5
6
7...
try {
Slog.i(TAG, "DiskStats Service");
ServiceManager.addService("diskstats", new DiskStatsService(context));
} catch (Throwable e) {
reportWtf("starting DiskStats Service", e);
}
在这个代码后面添加如下代码:1
2
3
4
5
6try {
Slog.i(TAG, "Hello Service");
ServiceManager.addService("hello", new HelloService());
} catch (Throwable e) {
reportWtf("starting Hello Service", e);
}
6.编译和打包
mmm frameworks/base/services/java
make snod
重新生成后的system.img中就包含了我们自定义的HelloService,可以供JAVA的可视应用程序调用,最终访问Hello驱动,并实现寄存器值的读写。
注:代码程序主要参考《老罗的Android之旅》来完成。