为Android系统的Application Frameworks层增加硬件访问服务
在数字科技日新月异的今天,软件和硬件的完美结合,造就了智能移动设备的流行。今天大家对iOS和Android系统的趋之若鹜,一定程度上是由于这两个系统上有着丰富多彩的各种应用软件。因此,软件和硬件的关系,在一定程度上可以说,硬件是为软件服务的。硬件工程师研发出一款硬件设备,自然少了软件工程师为其编写驱动程序;而驱动程序的最终目的,是为了使得最上层的应用程序能够使用这些硬件提供的服务来为用户提供软件功能。对Android系统上的应用软件来说,就是要在系统的Application Frameworks层为其提供硬件服务。在前面的几篇文章中,我们着重介绍了Linux内核层、硬件抽象层和运行时库层提供的自定义硬件服务接口,这些接口都是通过C或者C++语言来实现的。在这一篇文章中,我们将介绍如何在Android系统的Application Frameworks层提供Java接口的硬件服务。
Android系统的硬件访问服务通常运行在系统进程System中,而使用这些硬件访问服务的应用程序运行在另外的进程中,即应用程序需要通过进程间通信机制来访问这些硬件访问服务。Android系统提供了一种高效的进程间通信机制--Binder进程间通信机制,应用程序就是通过它来访问运行在系统进程System中的硬件访问服务的。Binder进程间通信机制要求提供服务的一方必须实现一个具有跨进程访问能力的服务端口,以便使用服务的一方可以通过这个服务接口来访问它。因此,在实现硬件访问服务之前,我们首先定义它的服务接口。
代码结构:
/alps/frameworks/base
----core
---java/android/os
--IFregService.aidl
---Android.mk
---services/java/com/android/server
--FregService.java
--SystemServer.java
1:定义硬件访问服务接口
Android系统提供了一种描述语言来定义具有跨进程访问能力的服务接口,这种语言称之为Android接口描述语言(Android Interface Defination Language,AIDL).以AIDL定义的服务接口文件是以aidl为后缀名的,在编译时,编译系统会将它们转换成一个java文件,然后在对它们进行编译。接下来,我们定义硬件访问服务接口IFregService的文件IFregService.aidl.
IFregService.aidl文件:
package android.os;
interface IFregService {
void setVal(int val);
int getVal();
}
在看Android.mk文件:
LOCAL_SRC_FILES += \
core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl \
core/java/android/accessibilityservice/IEventListener.aidl \
core/java/android/accounts/IAccountManager.aidl \
core/java/android/accounts/IAccountManagerResponse.aidl \
core/java/android/os/IVibratorService.aidl \
core/java/android/os/IFregService.aidl \
core/java/android/service/urlrenderer/IUrlRendererService.aidl \
IFregService接口主要提供了设备和获取硬件寄存器val的值的功能,分别通过setVal和getVal两个函数来实现。
编译IFregService.aidl接口:./mk mm /frameworks/base
这样就会根据IFregService.aidl生成相应的IFregService.Stub接口。
2:进入到frameworks/base/services/java/com/android/server目录,新增FregService.java文件:
package com.android.server;
import android.content.Context;
import android.os.IFregService;
import android.util.Slog;
public class FregService extends IFregService.Stub {
private static final String TAG = "FregService";
private int mPtr = 0;
FregService() {
mPtr = init_native();
if(mPtr == 0) {
Slog.e(TAG, "Failed to initialize freg service.");
}
}
public void setVal(int val) {
if(mPtr == 0) {
Slog.e(TAG, "Freg service is not initialized.");
return;
}
setVal_native(mPtr, val);
}
public int getVal() {
if(mPtr == 0) {
Slog.e(TAG, "Freg service is not initialized.");
return 0;
}
return getVal_native(mPtr);
}
private static native int init_native();
private static native void setVal_native(int ptr, int val);
private static native int getVal_native(int ptr);
};
FregService主要是通过调用JNI方法init_native、setVal_native和getVal_native来提供硬件服务。
@Override
public void run() {
....................................................................................
try {
Slog.i(TAG, "DiskStats Service");
ServiceManager.addService("diskstats", new DiskStatsService(context));
} catch (Throwable e) {
Slog.e(TAG, "Failure starting DiskStats Service", e);
}
try {
Slog.i(TAG, "Hello Service");
ServiceManager.addService("hello", new HelloService());
} catch (Throwable e) {
Slog.e(TAG, "Failure starting Hello Service", e);
}
......................................................................................
}
编译FregService和重新打包system.img:
./mk mm frameworks/base/services/java
./mk snod
这样,重新打包后的system.img系统镜像文件就在Application Frameworks层中包含了我们自定义的硬件服务FregService,
并且会在系统启动的时候,自动加载FregService。这时,应用程序就可以通过Java接口来访问Freg硬件服务了。
接下来介绍: