当前位置 主页 > 服务器问题 > Linux/apache问题 >

    Android 添加系统服务的方法详解(4)

    栏目:Linux/apache问题 时间:2020-02-06 08:25

    注册后, 如果你在App里面通过 getSystemService(SystemEventManager.SERVICE); 获取Manager并调用接口, 会发现又会出错, 又是Selinux权限问题:

    E SELinux : avc:  denied  { find } for service=test_systemevent pid=4123 uid=10035 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:test_systemevent_service:s0 tclass=service_manager permissive=0

    说是没有 find 权限, 因此又要加权限, 修改代码如下:

    system/sepolicy/untrusted_app.te

    # 允许 untrusted_app 查找 test_systemevent_service
    allow untrusted_app test_systemevent_service:service_manager find;
    
    

    这个 Selinux 的知识有兴趣自己去学一下, 报了什么权限, 就按照错误信息去对应文件添加权限.

    至此, 系统代码修改完成了, 编译系统刷机, 下面通过App调用.

    七、App调用

    文件拷贝和准备:
    我们需要复制三个文件到App中, 两个AIDL文件, 一个Manager文件:

    IEventCallback.aidl
    ISystemEvent.aidl
    SystemEventManager.java

    所有AIDL文件和java文件, 在App工程中的包名和路径都需要和系统保持一致, 这三个文件App不能做任何修改, 除非系统源码中也做对应修改, 总的来说, 这三个文件App和系统中要完全保持一致, 类名包名和包路径都需一致, 复制这三个文件到工程中后, 编译后, 调用方式如下.

    获取服务:

    SystemEventManager eventManager = (SystemEventManager)
        context.getSystemService(SystemEventManager.SERVICE);
    
    

    这里Android Studio可能会报 getSystemService() 参数不是Context里面的某个服务的错误, 可以直接忽略, 不影响编译.

    注册/取消注册:

    eventManager.register(eventCallback);
    
    eventManager.unregister(eventCallback);
    
    private IEventCallback.Stub eventCallback = new IEventCallback.Stub() {
      @Override
      public void onSystemEvent(int type, String value) throws RemoteException {
        Log.d("SystemEvent", "type:" + type + " value:" + value);
      }
    };
    
    

    调用:

    eventManager.sendEvent(1, "test string");
    
    

    测试Log如下:

    D SystemEventManager: SystemEventManager init
    D SystemEventService: register pid:3944 uid:10035 result:true
    D SystemEventService: remote callback count:1
    D SystemEvent: type:1 value:test string remote
    D SystemEventService: unregister pid:3944 uid:10035 result:true

    可以看到调用了服务端并成功收到服务端拼接的字符串.

    八、添加JNI部分代码

    我们一般添加系统服务, 可能是为了调用驱动里面的代码, 所有一般要用JNI部分代码, 这里不是讲怎么编写JNI代码, 而是说下系统服务中已有的JNI代码, 我们可以直接在这基础上增加我们的功能.

    JNI部分代码位置为:

    frameworks/base/services/core/jni/

    编译对应mk为:

    frameworks/base/services/Android.mk
    frameworks/base/services/core/jni/Android.mk

    此部分代码直接编译为 libandroid_servers 动态库, 在SystemServer进行加载:
    frameworks/base/services/java/com/android/server/SystemServer.java