• 添加Java服务


    1. 定义接口

    定义aidl接口

    //frameworks/base/core/java/android/hello/IHelloService.aidl
    package android.hello;
    interface IHelloService {
        void hello(String name);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    frameworks/base/Android.bp framework-defaults 模块中添加我们刚刚加的 aidl 文件 "core/java/android/pure/IHelloService.aidl"

    mm成功,会有hello目录IHelloService.java

    2 实现接口

    //frameworks/base/services/core/java/com/android/server
    package com.android.server;
    
    import android.hello.IHelloService;
    import android.util.Log;
    
    public class HelloService extends IHelloService.Stub {
        private final String TAG = "HelloService";
    
        public HelloService() {
            Log.d(TAG, "create hello service");
        }
    
        @Override
        public void hello(String name) {
            Log.d(TAG, "hello " + name);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    3 添加到ServiceManager

    // frameworks/base/services/java/com/android/server/SystemServer.java  startOtherServices 
    // add hello service
    traceBeginAndSlog("HelloService");
    ServiceManager.addService("HelloService", new HelloService());
    traceEnd();
    
    • 1
    • 2
    • 3
    • 4
    • 5

    编译运行,系统起不来,错误log

    12-20 23:46:47.308  1526  1526 E SELinux : avc:  denied  { add } for service=HelloService pid=3521 uid=1000 scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager permissive=0
    
    • 1

    没有添加SELinux规则

    4 selinux规则

    android 10的selinux在sysem/sepolicy,每个版本不尽相同。参考network_time_update_service

    cd system/sepolicy
    grep -nr network_time_update_service
    
    • 1
    • 2

    找到所有service.te 和service_context,参考network_time_update_service加上HelloService配置

    service_context 加上

    HelloService u:object_r:HelloService:s0

    service.te加上

    type HelloService, system_server_service, service_manager_type;

    5 验证

    整编后 service list 发现

    HelloService:[andorid.hello.IHelloService]

    6 客户端使用

    6.1 系统源码中使用

    Android.bp

    android_app {
    	src: ["src/**/*.java"],
    	resource_dirs: ["res"],
    	certificate: "platform",
    	platform_apis: true,
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    platform_apis 要设置为true,不然没法调用系统服务

    public class MainActivity extends Activity {
    
        private static final String TAG = "PureSettings";
        private IHelloService service = null;
        private Button button;
    
        private void test() {
            Log.d(TAG, "test");
            try {
                service.hello("hello");
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            service = IHelloService.Stub.asInterface(ServiceManager.getService("HelloService"));
    
            button = (Button) findViewById(R.id.button);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    test();
                }
            });
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    将模块添加到系统

    pure.mk

    PRODUCT_PACKAGES += PureSettings

    编译运行,闪退,错误日志

    E SELinux : avc: denied { find } for service=HelloService pid=4266 uid=10102 scontext=u:r:platform_app:s0:c512,c768 tcontext=u:object_r:HelloService:s0 tclass=service_manager permissive=0

    看起来还是有selinux权限需要添加,具体分析如下

    • 缺少什么权限 {find}
    • 谁缺少权限 scontext=u:r:platform_app:s0:c512,c768
    • 对哪个文件缺少权限: tcontext=u:object_r:HelloService:s0
    • 什么类型的文件: tclass=service_manager
    • 完整的意思: platform_app 缺少 service_manager 类型的 HelloService 的 find 权限。
    • 在 platform_app.te 中添加 HelloService 的 find 权限即可

    alllo platform_app HelloService:service_manager find;,找到所有private/platform_app.te 都加上,

    重新编译运行就正常。

    6.2 非系统源码使用

    实际项目中,非系统源码使用系统服务,需要封装一层接口出来。apk –> HelloApi –> HelloService
    我们按以下目录结构创建 HelloApi 模块:

    qiushao@qiushao-pc:~/source/android-10/device/qiushao/pure/models$ tree HelloApi/
    HelloApi/
    ├── Android.bp
    └── java
        └── com
            └── pure  
                └── api
                    └── HelloManager.java
    
    4 directories, 2 files
    qiushao@qiushao-pc:~/source/android-10/device/qiushao/pure/models$
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    Android.bp

    java_library {
        name: "com.pure.api",
        installable: true,
        srcs: [
            "java/**/*.java", //文件列表
        ],
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    //device/qiushao/pure/models
    import android.os.RemoteException;
    import android.os.ServiceManager;
    import android.pure.IHelloService;
    
    public class HelloManager {
    
        private static HelloManager mInstance = null;
        public static HelloManager getInstance() {
            if (null == mInstance) {
                mInstance = new HelloManager();
            }
            return mInstance;
        }
    
        private IHelloService mService = null;
        private HelloManager() {
            mService = IHelloService.Stub.asInterface(ServiceManager.getService("HelloService"));
        }
    
        public void sayHello(String name) {
            try {
                mService.hello(name);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    HelloApi 目录 mm 编译模块,得到 out/target/common/obj/JAVA_LIBRARIES/com.pure.api_intermediates/classes.jar 文件
    生成class.har, 复制到as创建的项目中,add as library, 然后我们就可以在 apk 的代码中使用 com.pure.api.jar 的接口了:

    ...
    public class MainActivity extends AppCompatActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            HelloManager.getInstance().sayHello("qiushao");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    编译运行,又有错误

    E SELinux : avc: denied { find } for service=HelloService pid=4266 uid=10102 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:HelloService:s0 tclass=service_manager permissive=0

    alllow untrusted_app HelloService:service_manager find;

    7 添加回调

    //frameworks/base/core/java/android/hello
    package android.pure;
    interface ICallback {
        void onMessage(in String message);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    frameworks/base/Android.bp framework-defaults 模块中添加aidl文件

    "core/java/android/hello/ICallback.aidl",,会生成ICallback.java文件

    8 添加注册回调

    修改 IHelloService.aidl

    package android.hello;
    import android.pure.ICallback;
    interface IHelloService {
        void hello(in String name);
        void registerCallback(in int pid, in ICallback callback);
        void unregisterCallback(in int pid);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    HelloService.java 修改如下:

    package com.android.server;
    
    import android.os.RemoteException;
    import android.pure.IHelloService;
    import android.pure.ICallback;
    import android.util.Log;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class HelloService extends IHelloService.Stub {
        private final String TAG = "HelloService";
        private Map<Integer, ICallback> mClients;
    
        public HelloService() {
            Log.d(TAG, "create hello service");
            mClients = new HashMap<>();
        }
    
        @Override
        public void hello(String name) {
            Log.d(TAG, "hello " + name);
            try {
                for (ICallback callback : mClients.values()) {
                    callback.onMessage("message from service");
                }
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void registerCallback(int pid, ICallback callback) {
            mClients.put(pid, callback);
            Log.d(TAG, "registerCallback client's size = " + mClients.size());
        }
    
        @Override
        public void unregisterCallback(int pid) {
            mClients.remove(pid);
            Log.d(TAG, "unregisterCallback client's size = " + mClients.size());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    9 注册回调接口

    //MainActivity
    public class MainActivity extends Activity {
    
        private static final String TAG = "PureSettings";
        private IHelloService service = null;
    
        private Button button;
    
        private ICallback callback = new ICallback.Stub() {
    
            @Override
            public void onMessage(String message) throws RemoteException {
                Log.d(TAG, "onMessage:" + message);
            }
        };
    
        private void test() {
            Log.d(TAG, "test");
            try {
                service.hello("qiushao");
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            service = IHelloService.Stub.asInterface(ServiceManager.getService("HelloService"));
            button = (Button) findViewById(R.id.button);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    test();
                }
            });
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            try {
                service.registerCallback(android.os.Process.myPid(), callback);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            try {
                service.unregisterCallback(android.os.Process.myPid());
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    编译运行成功

  • 相关阅读:
    Microsoft Office无法重装报错30015-44(3) 0-2031(17004)
    第十三届蓝桥杯 C++ C 组省赛 J 题——重复的数 (AC)
    前端Vue后台管理表格增删/批量删除改查案例(带源码)【一】
    Redisson 实现分布式锁源码浅析
    我复现的第一个神经网络: LeNet
    Shiro学习笔记_01:权限管理+shiro基本概念+shiro核心架构
    uni-app 微信小程序movable-area遮盖 遮挡住 点击事件
    flutter 文字拼接
    网络安全-学习手册
    【首因效应】第一印象
  • 原文地址:https://blog.csdn.net/gangjindianzi/article/details/127680851