在做AOSP开发的时候可能会遇到这种情况,上层的APP需要调用Api做一些操作,但是这些操作App是没有权限去做的,只有系统进程才有权限去做. 该怎么样实现呢, 其实很简单,仿照其它的Manager去做即可.
1. 写一个AIDL接口文件. 放在framewrok /base/core 包下任意目录, 建议放在android.os包下面. 可以参照里面其它的aidl文件来写就是了. 可以不用 parcelable
package android.os;
/**
* 该接口中定义你要做的操作.
*/
interface IDeviceVoManager {
String readAndroidId(int userId);
}
2. 写一个Service类. 建议放到 frameworks/base/services/core/java/com/android/server/ 目录下 该Service需要继承上面写的AIDL文件
/**
* 该类中的一些操作 可以以system权限来执行. 可以做很多上层被限制了的操作.
*/
public class DeviceVoManagerService extends IDeviceVoManager.Stub {
private static final String TAG = "DeviceVoManagerService";
private Context mContext;
/** @hide **/
public DeviceVoManagerService() {
this.mContext = null;
}
/** @hide **/
public DeviceVoManagerService(Context context) {
Context appContext = context.getApplicationContext();
if (appContext != null) {
mContext = appContext;
} else {
mContext = context;
}
}
/**
* 实现AIDL 接口文件中的方法
*/
@Override
public String readAndroidId(int userId) throws RemoteException {
return "ea8323ea26522";
}
3. 写一个类来调用 Service层 . 注意 DEVICE_VO_SERVICE 是我们自己在Context类中定义的名字.
frameworks/base/core/java/android/content/Context.java 类中修改
public static final String DEVICE_VO_SERVICE="xxxxx";
@StringDef({
//在该注解中加入Service的名字 方便根据名字调用
..
DEVICE_VO_SERVICE
..
})
@Retention(RetentionPolicy.SOURCE)
public @interface ServiceName {}
@SystemService(Context.DEVICE_VO_SERVICE)
public final class DeviceVoManager {
private static final String TAG = "DeviceVoManager";
private final IDeviceVoManager mService;
private final Context mContext;
private static final String UNKNOWN = "UNKNOWN";
/** @hide */
public static DeviceVoManager get(Context context) {
return (DeviceVoManager) context.getSystemService(Context.DEVICE_VO_SERVICE);
}
/** @hide */
public DeviceVoManager(Context context, IDeviceVoManager service) {
mService = service;
mContext = context.getApplicationContext();
Log.i(TAG,"===DeviceVoManager===");
}
}
4. 在frameworks/base/services/java/com/android/server/SystemServer.java 中添加如下片段
try {
//新增加服务 DeviceVoManagerService
traceBeginAndSlog("DeviceVoService");
ServiceManager.addService(Context.DEVICE_VO_SERVICE,new DeviceVoManagerService());
traceEnd();
}catch (Throwable e){
Slog.i("SystemServer","Start DeviceVoManagerService failed !");
}
在 frameworks/base/core/java/android/app/SystemServiceRegistry.java 中添加如下
//注册服务
registerService(Context.DEVICE_VO_SERVICE, DeviceVoManager.class,
new CachedServiceFetcher<DeviceVoManager>() {
@Override
public DeviceVoManager createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(Context.DEVICE_VO_SERVICE);
IDeviceVoManager service = IDeviceVoManager.Stub.asInterface(b);
return new DeviceVoManager(ctx, service);
}});
注意: 如果你的Manager 有被其它服务调用. 要把这两段定义放在调用者的服务之前. 以免调用的时候出现未初始化的的异常.
这两个类中的 各种服务顺序不要随便改动. 有的存在互相调用关系.
5. 在frameworks/base/Android.mk 文件中将我们的aidl文件路径加进去.可以看到很多AIDL文件都在此处.
6. 很重要的一步. 在system/sepolicy 中需要加入相应的SE限制
/system/sepolicy/private/service_contexts 文件中增加如下
//注意 xxxx 指的是 在Context.java类中定义的Service的名字 不要乱写
private/service_contexts:xxxx u:object_r:xxxx_service:s0
public/servicemanager.te文件中新增加如下
allow untrusted_app xxxx_service:service_manager {find };
public/service.te 文件中新增加如下
type xxxx_service,app_api_service, ephemeral_app_api_service, system_server_service,
service_manager_type;
OK, 到此流程就完成了.
仿照其它的Manager服务 进行调用就是了.