Android自定义系统服务, 应用层调用系统相关方法及其回调

Android自定义系统服务, 应用层调用系统相关方法及其回调

1.首先在framework/base 下添加自己需要的包, 例如framework/base/custom

如果有其他的java 文件, 需要参考 Framework中添加新的模块
在custom包下添加aidl文件 ICCCService.aidl

package android.custom;

interface ICCCService {
   void setVal(String key,String value);
   String getVal(String key);
}

2. 将ICCCService.aidl 文件的完整路径添加至 framework/base/Android.mk LOCAL_SRC_FILES中, 编译源码 make framework -j8, 第一次不能使用mm; 此时会自动根据aidl文件生成对应的stub接口

编译后得到的classes.jar文件就包含有ICCCService接口,它继承了android.os.IInterface接口,classes.jar的路径为:/out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar

3. 创建services文件

public class CCCService extends ICCCService.Stub {
    private static HashMap<String,String> map=new HashMap<>();
    private static String inner_log="";

    public CCCService( ) {
    }

    @Override
    public void setVal(String key, String value) throws RemoteException {
        map.put(key,value);
    }

    @Override
    public String getVal(String key) throws RemoteException {
        return map.get(key);
    }
}

4. 将自定义的service 添加进SystemServer , 以Android 6.0 为例

在SystemServer 中startOtherServices中添加自定义的server, 并在Context 中添加常量: CCC_SERVICE = “ccc”

 try {
         Slog.i(TAG, "CCC Service");
         ServiceManager.addService(Context.CCC_SERVICE, new CCCService());
       } catch (Throwable e) {
          Slog.e(TAG, "Failure starting CCC Service", e);
       }

5. 定义CCCManager

public class CCCManager {
    ICCCService mService;
    public CCCManager(Context ctx,ICCCService service){
        mService=service;
    }
    public void setVal(String key,String value){
        try{
            mService.setVal(key,value);
        }catch(Exception e){
            Log.e("CCCManager",e.toString());
            e.printStackTrace();
        }

    }
    public String getVal(String key){
        try{
            return mService.getVal(key);
        }catch(Exception e){
            Log.e("CCCManager",e.toString());
            e.printStackTrace();
        }
        return null;
    }
}

修改frameworks/base/core/java/android/app/SystemServiceRegistry.java, 在静态代码块中注册自定义的服务

 registerService(Context.CCC_SERVICE, CCCManager.class, new CachedServiceFetcher<CCCManager>() {
       @Override
        public CCCManager createService(ContextImpl ctx) {
            IBinder b = ServiceManager.getService(Context.CCC_SERVICE);
            ICCCService service = ICCCService.Stub.asInterface(b);
            return new CCCManager(ctx, service);
        }});

7. 修改 /external/sepolicy/service.te,在最后一行添加

type ccc_service, system_api_service, system_server_service, service_manager_type;

8. 修改目录 /external/sepolicy/service_contexts 文件中间插入一行

ccc u:object_r:ccc_service:s0 // 前面的ccc 为添加在Contxet中的 ccc_service 是上面添加的系统服务

9. make update-api

10. 验证方法一:

新建项目通过CCCManager manager = (CCCManager)getSystemService(“ccc”);

其中 CCCManager 可能会报错, 可以通过library, 可以新建一个CCCManager类,编译一个jar/aar, 导出jar包到现在目录,引用jar包, 再正常使用。需要注意的是应用层的manager的包名需做成和低层包名一致。

验证时可以不用修改external/sepolicy/service.te/ external/sepolicy/service_contexts 到设备,

如果只是在framework内部使用的话, 就不用做6,7,8,9,10 步。 只需前面1–5 步即可。

11 验证方法二:(此方法需要再考虑可行性)

首先把上面编译出来的classes.jar导入到项目中,(暂时验证未发现后面描述错误 : 注意添加user Library时,要把as system Library勾选上,否则编译时会报Unable to execute dex: Java heap space的错误)
然后需要用的地方

IBinder binder = ServiceManager.getService("ccc");
ICCCService anInterface = ICCCService.Stub.asInterface(binder);

再通过 anInterface 调用 aidl中的方法. 类似manager 注册的地方

同理可以通过这个classes.jar 获取更多的系统中的服务,

12 验证方法三:

应用层复制同样一份aidl文件, 编译后生成对应的java文件, 通过反射拿到系统的服务 IBinder:

    private IBinder getService(String armService) { //armService 为注册时的名称ccc
        IBinder iBinder = null;
        try {
            Class<?> clz = Class.forName("android.os.ServiceManager");
            Method checkService = clz.getMethod("getService", String.class);
            checkService.setAccessible(true);
            iBinder = (IBinder) checkService.invoke(clz.newInstance(), armService);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return iBinder;
    }

ICCCService anInterface = ICCCService.Stub.asInterface(binder);
通过 anInterface 即可调用对应的方法;

13 服务端回调到各客户端

同理在aidl文件夹定义个 ICallBack.aidl 文件,

package android.custom;
interface ICallBack {
    void onProgress(String progressState);
}

在 ICCCService.aidl 中声明注册方法:

package android.custom;
import android.custom.ICallBack;
interface ICCCService {
   void setVal(String key,String value);
   String getVal(String key);
   void registerCallBack(in ICallBack callback);
}

同理应用层需更新对应的 aidl 文件。

ICallBack.Stub callBack = new ICallBack.Stub(){
        @Override
        public void onProgress(String progress) throws RemoteException {
            Log.d(TAG, "onProgress: --------???---------"+progress);
        }
    };

在绑定上服务的时候, 调用 anInterface.registerCallBack(callBack);即可

注意: 在全编系统时可能会报错, 未知包名unknown package name of class file android/custom, 需要在
build/core/tasks/check_boot_jars/package_whitelist.txt 中添加该包名,
参考 https://www.jianshu.com/p/634d71e31a9d 修改

应用层 demo 地址: https://github.com/william-lw/IPC-demo

你可能感兴趣的:(Android自定义系统服务, 应用层调用系统相关方法及其回调)