AOSP新增AIDL呼叫
阿新 • • 發佈:2018-12-14
在做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);
}});
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服務 進行呼叫就是了.