美文网首页
Android 11系统服务的添加(java 层)

Android 11系统服务的添加(java 层)

作者: 星辰大海TT | 来源:发表于2021-07-23 17:02 被阅读0次

    目标

    1,创建一个系统服务, TestService

    2,在android11中使用getSystemService方法获取该服务并调用里面的方法。

    环境

    开发板: rk3568
    
    Android系统:  android 11
    
    编译环境: ubuntu 20.04 deskop
    

    添加系统服务步骤

    定义系统服务aidl接口和代理manager类

    因为系统服务是运行在system_server进程中,所以app要调用我们的自定义service需通过跨进程通讯,Android中跨进程通讯使用AIDL,所以我们这里定义一个ITestManager.aidl文件,另外还需要定一个服务的代理manager类,用于app调用。
    1).在/frameworks/base目录下新建一个文件夹myservice,在myservice目录下新建/java/android/mymodule/test 目录,可以根据自己的需要命名。
    在/frameworks/base/myservice/java/android/mymodule/test目录下存放ITestManager.aidl,及TestManager.java。用作系统服务的客户端代理。

    category.png

    ITestManager.aidl及 TestManager.java内容如下:

    package android.mymodule.test;
    
    interface ITestManager {
        void testMethod();
    
    }
    
    package android.mymodule.test;
    
    import android.util.Slog;
    import android.os.RemoteException;
    import android.annotation.SystemService;
    import android.content.Context;
    
    public class TestManager {
    
        private final ITestManager mService;
    
        public TestManager(ITestManager mService) {
            //这里把ITestManager传进来,可以看看系统其它service,都是这样写的
            this.mService = mService;
        }
    
        public void testMethod() {
            try {
                mService.testMethod();
                Slog.i("add_service_test", "TestManager testMethod:");
            } catch (RemoteException ex) {
                ex.printStackTrace();
            }
        }
    //    public native String stringFromJNI();
    }
    

    2). 在base/Android.bp 添加下面patch内容,把刚建立TestManager 和aidl文件加入android的编译文件中。

    diff --git a/Android.bp b/Android.bp
    index bf6c99d0cf29..3f0e1d4f9b03 100644
    --- a/Android.bp
    +++ b/Android.bp
    @@ -216,6 +216,16 @@ filegroup {
         path: "mms/java",
     }
     
    +filegroup {
    +    name: "framework-myservice-source",
    +    srcs: [
    +        "myservice/java/**/*.java",
    +        "myservice/java/**/*.aidl",
    +    ],
    +    path: "myservice/java",
    +}
    +
    +
     filegroup {
         name: "framework-non-updatable-sources",
         srcs: [
    @@ -286,6 +296,7 @@ filegroup {
             ":framework-statsd-sources",
             ":framework-tethering-srcs",
             ":framework-wifi-updatable-sources",
    +                ":framework-myservice-source",
             ":updatable-media-srcs",
         ]
     }
    @@ -1219,8 +1230,10 @@ metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.x
         "--api-lint-ignore-prefix android.icu. " +
         "--api-lint-ignore-prefix java. " +
         "--api-lint-ignore-prefix junit. " +
    +    "--api-lint-ignore-prefix android.mymodule. "+
         "--api-lint-ignore-prefix org. "
     
    +
     build = [
         "StubLibraries.bp",
         "ApiDocs.bp",
    
    
    添加系统服务TestService

    在/frameworks/base/core/java/com/android/server 目录下添加自己的service文件, 继承自ITestManager.stub。我这边建了个TestService.java, 内容如下:

    package com.android.server;
    
    import android.content.Context;
    import android.util.Slog;
    import android.wqmodule.test.ITestManager;
    
    //这里的ITestManager.Stub是固定写法
    public class TestService extends ITestManager.Stub {
        private final Context mContext;
    
        public TestService(Context context) {
            super();
            mContext = context;
        }
    
        public void testMethod() {
            // 测试方法,为了测试执行情况,在这里加log
            Slog.i("add_service_test", "TestService getString " +);
        }
    }
    
    将TestService 加入到android的系统服务

    (1)添加string 变量TEST_SERVICE = "test" 到系统中,这样客户端可以使用 getSystemService(Context.TEST_SERVICE) 获取客户端的实例

    diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
    index 8472144a92cf..93b22eed6e94 100644
    --- a/core/java/android/content/Context.java
    +++ b/core/java/android/content/Context.java
    @@ -3494,6 +3494,7 @@ public abstract class Context {
                 //@hide: TIME_ZONE_DETECTOR_SERVICE,
                 PERMISSION_SERVICE,
                 LIGHTS_SERVICE,
    +            TEST_SERVICE,
         })
         @Retention(RetentionPolicy.SOURCE)
         public @interface ServiceName {}
    @@ -3812,6 +3813,8 @@ public abstract class Context {
          */
         public static final String ALARM_SERVICE = "alarm";
     
    +    public static final String TEST_SERVICE = "test";
    +
         /**
          * Use with {@link #getSystemService(String)} to retrieve a
          * {@link android.app.NotificationManager} for informing the user of
    

    (2)修改 frameworks/base/services/java/com/android/server/SystemServer.java 文件,在 startOtherServices 方法里面增加以下代码:

     // add test service
     t.traceBegin("TestService");
     ServiceManager.addService(Context.TEST_SERVICE, new TestService(context));
     t.traceEnd();
    

    (3) 在frameworks/base/core/java/com/android/app/SystemServiceRegistry.java 注册TestManager

     diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
    index e599a5ce81ef..701a56503988 100644
    --- a/core/java/android/app/SystemServiceRegistry.java
    +++ b/core/java/android/app/SystemServiceRegistry.java
    @@ -213,6 +213,8 @@ import com.android.internal.util.Preconditions;
     import java.util.Map;
     import java.util.Objects;
    
    +import android.mymodule.test.TestManager;
    +import android.mymodule.test.ITestManager;
     /**
    
      * Manages all of the system services that can be returned by {@link Context#getSystemService}.
      * Used by {@link ContextImpl}.
        @@ -257,6 +259,15 @@ public final class SystemServiceRegistry {
                     return new CaptioningManager(ctx);
                 }});
    
    +        registerService(Context.TEST_SERVICE,TestManager.class,
    +        new CachedServiceFetcher<TestManager>(){
    +        @Override
    +        public TestManager createService(ContextImpl ctx) {
    +        IBinder b = ServiceManager.getService(Context.TEST_SERVICE);
    +        Log.i("add_service_test","SystemServiceRegistry registerService method");
    +        return new TestManager(ITestManager.Stub.asInterface(b));
    +        }});
             +
             registerService(Context.ACCOUNT_SERVICE, AccountManager.class,
                     new CachedServiceFetcher<AccountManager>() {
                 @Override
    

    Selinux 规则设置

    Android 11的 selinux 规则是放在 system/sepolicy 目录下的。注意需要修改所有的service.te和service_contexts文件,可以参考network_time_update_service 来修改。修改的patch 如下:

    diff --git a/prebuilts/api/30.0/public/service.te b/prebuilts/api/30.0/public/service.te
    index f27772eab..03792dd74 100644
    --- a/prebuilts/api/30.0/public/service.te
    +++ b/prebuilts/api/30.0/public/service.te
    @@ -39,6 +39,7 @@ type vold_service,              service_manager_type;
     type vr_hwc_service,            service_manager_type;
     type vrflinger_vsync_service,   service_manager_type;
     
    +
     # system_server_services broken down
     type accessibility_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;
     type account_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;
    @@ -134,6 +135,7 @@ type netstats_service, app_api_service, ephemeral_app_api_service, system_server
     type network_management_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;
     type network_score_service, system_api_service, system_server_service, service_manager_type;
     type network_stack_service, system_server_service, service_manager_type;
    +type test_service, system_server_service, service_manager_type;
     type network_time_update_service, system_server_service, service_manager_type;
     type notification_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;
     type oem_lock_service, system_api_service, system_server_service, service_manager_type;
    diff --git a/private/service_contexts b/private/service_contexts
    index 5c6f1a476..10d4315e3 100644
    --- a/private/service_contexts
    +++ b/private/service_contexts
    @@ -150,6 +150,7 @@ network_stack                             u:object_r:network_stack_service:s0
     network_management                        u:object_r:network_management_service:s0
     network_score                             u:object_r:network_score_service:s0
     network_time_update_service               u:object_r:network_time_update_service:s0
    +test_service               u:object_r:test_service:s0
     nfc                                       u:object_r:nfc_service:s0
     notification                              u:object_r:notification_service:s0
     oem_lock                                  u:object_r:oem_lock_service:s0
    diff --git a/public/service.te b/public/service.te
    index f27772eab..b92f169c8 100644
    --- a/public/service.te
    +++ b/public/service.te
    @@ -135,6 +135,7 @@ type network_management_service, app_api_service, ephemeral_app_api_service, sys
     type network_score_service, system_api_service, system_server_service, service_manager_type;
     type network_stack_service, system_server_service, service_manager_type;
     type network_time_update_service, system_server_service, service_manager_type;
    +type test_service, system_server_service, service_manager_type;
     type notification_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;
     type oem_lock_service, system_api_service, system_server_service, service_manager_type;
     type otadexopt_service, system_server_service, service_manager_type;
    

    编译

    切记一定要先在根目录执行make update-api更新一下 api 接口,再整编系统。否则会报错

    测试service添加是否成功

    adb shell下运行service list | grep Test

    可以看到
    154 test: [android.mymodule.test.ITestManager]

    说明添加成功

    app调用

    1. 拷贝代码

      app 开发的时候因为没有引用修改后的framework.jar, 可以先把aidl 和 manager 代码拷贝到项目中。注意包名需要和在framework添加的一致。

    app_manager.png
    1. 编写测试测试代码

      在mainActivity中添加一个button,添加button的点击事件测试service的调用

      testBtn.setOnClickListener {
          val myManager = getSystemService("test") as TestManager
          myManager.testMethod()
      }
      

    遇到的坑及解决方法

    1.make update-api报错:

    /frameworks/base/myservice/java/android/mymodule/test/ITestManager.java:105: e
    rror: Missing nullability on parameter `impl` in method `setDefaultImpl` [Miss
    ingNullability]
    out/soong/.intermediates/frameworks/base/api-stubs-docs/android_common/srcjars
    /frameworks/base/myservice/java/android/mymodule/test/ITestManager.java:118: e
    rror: Missing nullability on method `getDefaultImpl` return [MissingNullabilit
    y]
    frameworks/base/myservice/java/android/mymodule/test/TestManager.java:12: erro
    r: Managers must always be obtained from Context; no direct constructors [Mana
    gerConstructor]
    frameworks/base/myservice/java/android/mymodule/test/TestManager.java:12: erro
    r: Missing nullability on parameter `mService` in method `TestManager` [Missin
    gNullability]
    14 new API lint issues were found.
    See tools/metalava/API-LINT.md for how to handle these.
    metalava detected access to files that are not explicitly specified. See /medi
    a/wxkly/wxkly3/ROCKCHIP_ANDROID11.0_SDK_RELEASE/out/soong/.intermediates/frame
    works/base/api-stubs-docs/android_common/api-stubs-docs-violations.txt for det
    ails.
    $************************************************************\nYour API change
    s are triggering API Lint warnings or errors.\nTo make these errors go away, f
    ix the code according to the\nerror and/or warning messages above.\n\nIf it is
     not possible to do so, there are workarounds:\n\n1. You can suppress the erro
    rs with @SuppressLint("<id>")\n2. You can update the baseline by executing the
     following\n   command:\n       cp \\\n       "/media/wxkly/wxkly3/ROCKCHIP_AN
    DROID11.0_SDK_RELEASE$/out/soong/.intermediates/frameworks/base/api-stubs-docs
    /android_common/api_lint_baseline.txt" \\\n       "/media/wxkly/wxkly3/ROCKCHI
    P_ANDROID11.0_SDK_RELEASE$/frameworks/base/api/lint-baseline.txt"\n   To submi
    t the revised baseline.txt to the main Android\n   repository, you will need a
    pproval.\n************************************************************\n
    

    解决方法:

    这个问题是因为 Android 11 开启了lint代码检查,所以我们需要在framework/base 下的Android.bp忽略掉代码检查

    metalava_framework_docs_args = "
    "--api-lint-ignore-prefix android.mymodule. "
    

    其中 android.mymodule是包名的前缀。

    相关文章

      网友评论

          本文标题:Android 11系统服务的添加(java 层)

          本文链接:https://www.haomeiwen.com/subject/ykzdmltx.html