AOSP新增AIDL調用

    在做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服務 進行調用就是了.


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章