1、概述
本博文配套的硬件是瑞芯微RK3288芯片,跑的是Android5.1的SDK。作为设备开发商,经常有release接口给第三方调用的需求,本文基于实际案例撰写,不同版本的Android Framework架构可能略有不同,但是大同小异,均可作为参考。
2、扩展Framework接口
第三方APP如果要操作硬件,比如通过ioctl操作某个GPIO,大体上来说,应该有以下两种方法:
1、我们封装操作硬件的API,形成一个so库给到第三方,并写好JNI接口打通到Java层,第三方直接调用Java层接口就好。这种方法理论上可行,但是实际操作中一般会有API调用权限问题。操作硬件接口,一般都需要调用者进程需要system权限甚至是root权限,通过release JNI接口的方式给第三方调用,所有的代码都是跑在第三方APP的进程,一般而言,我们是不会随便给第三方APP系统权限,这样既会有安全问题,也会引入第三方APP升级麻烦等问题,不推荐使用。
2、扩展Framework接口:第三方APP调用标准接口,然后通过aidl的方式,跨进程调用到system_server进程中对应的远程接口,由于system_server是系统进程,所以不存在权限问题。本文就是使用该种方式。
2.1、定义Java接口
在 frameworks/base/core/java目录下,根据包名创建一个子目录,比如我创建的是com/wrtsz/api/,在该目录下,新建一个java文件,比如WrtdevManager.java ,对应的代码如下:
package com.wrtsz.api;
import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;
public class WrtdevManager {
private final IWrtdevManager mService;
private Handler mHandler;
private static final String TAG = "WrtdevManager";
public WrtdevManager(IWrtdevManager service, Handler handler)
{
mHandler = handler;
mService = service;
}
public int getMicroWaveState()
{
try{
return mService.getMicroWaveState();
}catch (RemoteException e){
Log.e(TAG, "getMicroWaveState failed");
return -1;
}
}
public byte[] getIcCardNo()
{
try{
return mService.getIcCardNo();
}catch (RemoteException e){
Log.e(TAG, "getIcCardNo failed");
return null;
}
}
public int openLed(int opIndex)
{
try{
return mService.openLed(opIndex);
}catch (RemoteException e){
Log.e(TAG, "openWhiteLed failed");
return -1;
}
}
public int openDoor()
{
try{
return mService.openDoor();
}catch (RemoteException e){
Log.e(TAG, "openDoor failed");
return -1;
}
}
}
以上代码,注意两点:
1、每个接口中,都必须catch RemoteException异常,这个不加上应该编译不过,主要是防止对应的远程接口没有定义,导致APP调用出错;
2、构造函数有两个参数,一个是Handler,一个是IWrtdevManager (继承于android.os.IInterface)
2.2、定义aidl接口
在WrtdevManager.java文件中有用到IWrtdevManager,这是通过编译aidl文件生成,定义的.aidl文件如下:
package com.wrtsz.api;
interface IWrtdevManager
{
int getMicroWaveState();
byte[] getIcCardNo();
int openLed(int opIndex);
int openDoor();
}
需要注意的是:.aidl中的接口必须跟.java中的接口保持一致,否则会编译不过。另外就是aidl语言的语法跟Java语言略有不同,且传递的参数必须是Java基本类型或者是其他实现Parcelable
接口的类,这里不再详述,可以参考官方文档:https://developer.android.com/guide/components/aidl?hl=zh-cn
2.3、编译接口
上面虽然定义了两个文件,但是默认情况下,编译Android的时候是不会编译到这两个文件的,如果要用编译到对应的文件,需要修改frameworks/base/Android.mk文件,在对应的LOCAL_SRC_FILES宏中添加对应的文件即可,相应的patch文件如下:
packages/services/Proxy/com/android/net/IP