1. 程式人生 > >AOSP新增AIDL呼叫

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服務 進行呼叫就是了.