Android Framework 添加新的系统服务

基于 上一篇 对 AMS 的类图结构的学习,
AMS 类图结构
想自己 添加 一个新的 系统服务,看看是否能实现,加深理解及学以致用。于是有了下文。
开发环境:

  • Android SDK 31 (Android12 平台)
  • Android Studio version 2020.3.1
  • Gradle 依赖 6.8.3

一、总体涉及修改的文件:

1. 新增 的 服务

(1) 服务AIDL文件,定义服务的接口:
frameworks/base/core/java/android/app/IDemoManager.aidl
(2) 服务管理类,提供给客户端调用,以访问 服务端的接口 (即持有 服务端 的引用, Binder 引用)
frameworks/base/core/java/android/app/DemoManager.java
(3) 服务实现类, 实现AIDL 文件
frameworks/base/services/core/java/com/android/server/DemoManagerService.java

2. 创建 及 启动服务 涉及的修改

(1) 定义服务的标识
frameworks/base/core/java/android/content/Context.java
(2) 创建 及 启动 服务
frameworks/base/services/java/com/android/server/SystemServer.java
(3)创建服务管理类(可同时获取服务端的代理对象,由服务管理对象持有)
frameworks/base/core/java/android/app/SystemServiceRegistry.java

3. SELinux sepolicy 的权限 修改

device/qcom/sepolicy/…/service.te
device/qcom/sepolicy/…/service_contexts *备注: 其中路径中的 …
表示可能不同厂商的实际路径不一致, 参考项目的目录配置

4. 其它平台限制的修改

根据 异常log分析,添加对应 修改 即可, 例如 ServiceManager.addService可能还有其它限制,如白名单service等

二、具体过程

1. 新增 服务

1.1 服务AIDL文件:IDemoManager.aidl , 定义接口
方便起见,我们是添加在 android.app 包中 (平台可能会限制我们添加到自定义的目录)
这里仅 声明了 一个 plus 函数,实现对两个 int 值的加法, 并返回 int 值的结果, 相当简单

// IDemoManager.aidl
package android.app;

// Declare any non-default types here with import statements

interface IDemoManager {
    int plus(int a, int b);
}

1.2 服务管理类: DemoManager.java
这里是参考 ActivityManager 源码的实现, 获取 服务的 代理对象(Binder引用) 时,使用了 单例模式;
Context.DEMO_SERVICE 是新增服务的 标识, 见下面的 Context.java 的修改;
提供两个方法, 静态方法 plus 和 非静态方法 plusA, 最终调用的都是 服务端的 plus 方法;

package android.app;

import android.annotation.SystemService;

import android.content.Context;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
import android.util.Singleton;

@SystemService(Context.DEMO_SERVICE)
public class DemoManager {
    private static String TAG = "DemoManager";

    /**
     * @hide
     */
    @UnsupportedAppUsage
    public static IDemoManager getService() {
        return IDemoManagerSingleton.get();
    }

    @UnsupportedAppUsage
    private static final Singleton<IDemoManager> IDemoManagerSingleton =
            new Singleton<IDemoManager>() {
                @Override
                protected IDemoManager create() {
                    final IBinder b = ServiceManager.getService(Context.DEMO_SERVICE);
                    final IDemoManager am = IDemoManager.Stub.asInterface(b);
                    return am;
                }
            };

    public static int plus(int a, int b) throws RemoteException {
        Log.d(TAG, "plus");
        return getService().plus(a, b);
    }

    public int plusA(int a, int b) throws RemoteException {
        Log.d(TAG, "plusA");
        return getService().plus(a, b);
    }


    /**
     * @hide
     */
    public DemoManager() {
    }
}


1.3 服务实现类: DemoManagerService.java
继承IDemoManager.Stub,实现接口;
内部静态类 Lifecycle 继承了 SystemService, 则可由 系统 管理它的生命周期 (启动、添加到SericeManager等); (不熟悉的可以看 SystemServie 的源码)
Context.DEMO_SERVICE 是新增服务的 标识, 见下面的 Context.java 的修改

package com.android.server;

import android.app.IDemoManager;
import android.content.Context;
import android.os.RemoteException;
import android.util.Log;

import com.android.server.SystemService;

import androidx.annotation.NonNull;

public class DemoManagerService extends IDemoManager.Stub{
    private static String TAG = "DemoManagerService";

    @Override
    public int plus(int a, int b) throws RemoteException {
        Log.d(TAG, "plus - a=" + a + ", b=" + b);
        return a + b;
    }

    public static final class Lifecycle extends SystemService {
        private final DemoManagerService mService;

        public Lifecycle(Context context) {
            super(context);
            mService = new DemoManagerService();
            Log.d(TAG, "Lifecycle create");
        }

        @Override
        public void onStart() {
            Log.d(TAG, "Lifecycle onStart start");
            publishBinderService(Context.DEMO_SERVICE, mService);
            Log.d(TAG, "Lifecycle onStart continue");
            mService.start();
            Log.d(TAG, "Lifecycle onStart end");
        }

        @Override
        public void onBootPhase(int phase) {

        }

//        @Override
//        public void onUserStopped(@NonNull TargetUser user) {
//        }

        public DemoManagerService getService() {
            return mService;
        }
    }

    private void start() {
        //todo
    }
}


2. 创建 及 启动 服务

2.1 Context.java
定义 服务的 唯一标识

public static final String DEMO_SERVICE = "demo";

2.2 SystemServer.java
在startOtherServices() 方法中, 启动服务
务必加上 try-catch, 否则,一旦发生异常, 例如SEPolicy限制添加 该 service而抛出 SecurityException, 则会导致 system_server进程挂掉,设备无法开机!!!

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
        // 省略一万行
        t.traceBegin("StartDemoManagerService");
        try {
            mSystemServiceManager.startService(DemoManagerService.Lifecycle.class);
        } catch (Throwable e) {
            reportWtf("starting DemoManagerService", e);
        }
        t.traceEnd();

2.3 SystemServiceRegistry.java
在静态代码块中,新增代码 注册 服务管理 类 对象

@SystemApi
public final class SystemServiceRegistry {
    // 省略一万行
    static {
       // 省略一万行
       registerService(Context.DEMO_SERVICE, DemoManager.class,
                new CachedServiceFetcher<DemoManager>() {
            @Override
            public DemoManager createService(ContextImpl ctx) {
                return new DemoManager();
            }});

3.SEPolicy 权限修改

SEPolicy 简单可以理解为 Linux 为了 控制 系统服务 的访问权限,
ServiceManager 仅能访问特定类型的服务, 因此 新增的 服务必须声明为 对应的类型!!!
例如在上面修改的基础上,运行不起效,日志提示以下错误信息:

audit:                      avc:  denied  { add } for pid=1222 uid=1000 name=demo scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager permissive=0
即不允许 在 system_server 中, 通过 service_manager 获取到 服务demo(它的类型为: u:object_r:default_android_service:s0) 

则,需要进行以下的修改
3.1 service.te 新增服务 类型
在该文件后面新增:

type demo_service,         system_api_service, system_server_service, service_manager_type;

这里定义服务类型, 服务名最好对应 新增服务 的标识(Context.java —> DEMO_SERVICE = “demo”),
因此这里我们定义了:
服务名:demo_service
类型:system_api_service, system_server_service, service_manager_type
3.2 service_contexts 设置服务上下文 类型
在该文件后面新增:

demo                  u:object_r:demo_service:s0

这里为 新增的服务demo 设置类型为: u:object_r:demo_service:s0,
需要特别注意的是, demo 是对应Context.java 新增的:

public static final String DEMO_SERVICE = "demo";

demo_service 为在 service.te 定义的类型, 必须一一对应,否则无效!!!
则可以得出结论: ServiceManager 访问的类型,必须是 在 service.te 里定义的 类型

4.其它修改

一般是与平台限制有关,
如ServiceManager addService 时提示 仅允许 白名单的service, 按提示 加入 白名单即可

又例如在 DemoManager 获取 service (即使用ServiceManager getService)时报错:

15:41:46.698  4689   4689   DemoManager:             plusA
15:41:46.705  696    795    audit:                   avc:  denied  { find } for pid=4689 uid=10320 name=demo scontext=u:r:untrusted_app:s0:c64,c257,c512,c768 tcontext=u:object_r:demo_service:s0 tclass=service_manager permissive=0
15:41:46.705  696    795    servicemanager:          demo : getService has failed, permission denied.

此时可尝试在 untrusted_app.te 中添加:

allow untrusted_app demo_service:service_manager find;

大概意识是, 允许untrusted_app 通过 service_manager 获取到我们新增的服务 demo_service
( demo_service是我们在service.te 新增的服务类型)

5. 客户端使用

只需根据 Context.getSystemService 获取到 DemoManager,然后调用对应plusA 方法即可

import android.app.DemoManager;

.....
    private DemoManager mDemoManager;
     
    mDemoManager = (DemoManager) mContext.getSystemService(Context.DEMO_SERVICE);
    Log.d(TAG, " mDemoManager="+mDemoManager);
    if (mDemoManager != null ) {
        try {
            int result = mDemoManager.plusA(2,3);
            Log.d(TAG, "result="+result);
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

服务创建、启动 即 使用 日志打印:

03-31 06:11:43.985  1243  1243 I SystemServerTiming: StartDemoManagerService
03-31 06:11:43.985  1243  1243 I SystemServiceManager: Starting com.android.server.DemoManagerService$Lifecycle
03-31 06:11:43.987  1243  1243 D DemoManagerService: Lifecycle create
03-31 06:11:43.987  1243  1243 D DemoManagerService: Lifecycle onStart start

03-31 06:11:43.988   696   795 I servicemanager: Adding 'u:r:system_server:s0' service (demo:1243)

03-31 06:11:43.988  1243  1243 D DemoManagerService: Lifecycle onStart continue
03-31 06:11:43.988  1243  1243 D DemoManagerService: Lifecycle onStart end
03-31 06:11:43.988  1243  1243 D SystemServerTiming: StartDemoManagerService took to complete: 3ms

14:15:08.034  10415  10415  SampleApp mDemoManager=android.app.DemoManager@e8bd8a2
14:15:08.038  10415  10415  SampleApp  result=5

三、遇到的问题

  1. SEPolicy 权限问题详细log:
16:37:47.140  1222   1222   SystemServerTiming:         StartDemoManagerService
16:37:47.140  1222   1222   SystemServiceManager:       Starting com.android.server.DemoManagerService$Lifecycle
16:37:47.142  1222   1222   DemoManagerService:         Lifecycle create
16:37:47.142  1222   1222   DemoManagerService:         Lifecycle onStart start
16:37:47.143  695    706    audit:                      avc:  denied  { add } for pid=1222 uid=1000 name=demo scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager permissive=0
16:37:47.144  1222   1222   SystemServer:               ***********************************************
16:37:47.146  1222   1222   SystemServer:               BOOT FAILURE starting DemoManagerService
16:37:47.146  1222   1222   SystemServer:               java.lang.RuntimeException: Failed to start service com.android.server.DemoManagerService$Lifecycle: onStart threw an exception
16:37:47.146  1222   1222   SystemServer:               at com.android.server.SystemServiceManager.startService(SystemServiceManager.java:244)
16:37:47.146  1222   1222   SystemServer:               at com.android.server.SystemServiceManager.startService(SystemServiceManager.java:225)
16:37:47.146  1222   1222   SystemServer:               at com.android.server.SystemServer.startOtherServices(SystemServer.java:2928)
16:37:47.146  1222   1222   SystemServer:               at com.android.server.SystemServer.run(SystemServer.java:1225)
16:37:47.146  1222   1222   SystemServer:               at com.android.server.SystemServer.main(SystemServer.java:946)
16:37:47.146  1222   1222   SystemServer:               at java.lang.reflect.Method.invoke(Native Method)
16:37:47.146  1222   1222   SystemServer:               at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:567)
16:37:47.146  1222   1222   SystemServer:               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1113)
16:37:47.146  1222   1222   SystemServer:               Caused by: java.lang.SecurityException:
16:37:47.146  1222   1222   SystemServer:               at android.os.Parcel.createExceptionOrNull(Parcel.java:2437)
16:37:47.146  1222   1222   SystemServer:               at android.os.Parcel.createException(Parcel.java:2421)
16:37:47.146  1222   1222   SystemServer:               at android.os.Parcel.readException(Parcel.java:2404)
16:37:47.146  1222   1222   SystemServer:               at android.os.Parcel.readException(Parcel.java:2346)
16:37:47.146  1222   1222   SystemServer:               at android.os.IServiceManager$Stub$Proxy.addService(IServiceManager.java:452)
16:37:47.146  1222   1222   SystemServer:               at android.os.ServiceManagerProxy.addService(ServiceManagerNative.java:72)
16:37:47.146  1222   1222   SystemServer:               at android.os.ServiceManager.addService(ServiceManager.java:249)
16:37:47.146  1222   1222   SystemServer:               at com.android.server.SystemService.publishBinderService(SystemService.java:442)
16:37:47.146  1222   1222   SystemServer:               at com.android.server.SystemService.publishBinderService(SystemService.java:426)
16:37:47.146  1222   1222   SystemServer:               at com.android.server.SystemService.publishBinderService(SystemService.java:413)
16:37:47.146  1222   1222   SystemServer:               at com.android.server.DemoManagerService$Lifecycle.onStart(DemoManagerService.java:33)
16:37:47.146  1222   1222   SystemServer:               at com.android.server.SystemServiceManager.startService(SystemServiceManager.java:238)
16:37:47.146  1222   1222   SystemServer:               ... 7 more
16:37:47.143  0      0      [0:                         Binder:695_2:  706]  avc: denied  { add } for pid=1222 uid=1000 name=demo scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager permissive=0
16:37:47.143  0      0      :                           [0:   Binder:695_2:  706]
16:37:47.146  1222   1222   SystemServerTiming:         StartDemoManagerService took to complete: 7ms

链接:https://www.jianshu.com/p/74971ee85a8b
作者:行走中的3卡

最后

如果你想要深入系统的学习Android Framework框架,这里可以分享一份《Android Framework源码开发揭秘》,其中记录了从系统启动流程到WMS全部源码解析,相信你能优秀地学习整个Framework框架。扫描下方二维码直接领取!

第一章 系统启动流程分析

  • 第一节 Android启动概览
  • 第二节 init.rc解析
  • 第三节 Zygote
  • 第四节 面试题

在这里插入图片描述

第二章 跨进程通信IPC解析

  • 第一节 Sercice 还可以这么理解
  • 第二节 Binder基础
  • 第三节 Binder应用
  • 第四节 AIDL应用(上)
  • 第五节 AIDL应用(下)
  • 第六节 Messenger原理及应用
  • 第七节 服务端回调
  • 第八节 获取服务(IBinder)
  • 第九节 Binder面试题全解析

在这里插入图片描述

第三章 Handler源码解析

  • 第一节 源码分析
  • 第二节 难点问题
  • 第三节 Handler常问面试题
  • 在这里插入图片描述

第四章 AMS源码解析

  • 第一节 引言
  • 第二节 Android架构
  • 第三节 通信方式
  • 第四节 系统启动系列
  • 第五节 AMS
  • 第六节 AMS 面试题解析

在这里插入图片描述

第五章 WMS源码解析

  • 第一节 WMS与activity启动流程
  • 第二节 WMS绘制原理
  • 第三节 WMS角色与实例化过程
  • 第四节 WMS工作原理

在这里插入图片描述

第六章 Surface源码解析

  • 第一节 创建流程及软硬件绘制
  • 第二节 双缓冲及SurfaceView解析
  • 第三节 Android图形系统综述
  • 在这里插入图片描述

第七章 基于Android12.0的SurfaceFlinger源码解析

  • 第一节 应用建立和SurfaceFlinger的沟通的桥梁
  • 第二节 SurfaceFlinger的启动和消息队列处理机制
  • 第三节 SurfaceFlinger 之 VSync(上)
  • 第四节 SurfaceFlinger之VSync(中)
  • 第五节 SurfaceFlinger之VSync(下)
  • 在这里插入图片描述

第八章 PKMS源码解析

  • 第一节 PKMS调用方式
  • 第二节 PKMS启动过程分析
  • 第三节 APK的扫描
  • 第四节 APK的安装
  • 第五节 PKMS之权限扫描
  • 第六节 静默安装
  • 第七节 requestPermissions源码流程解析

在这里插入图片描述

第九章 InputManagerService源码解析

  • 第一节 Android Input输入事件处理流程(1)
  • 第二节 Android Input输入事件处理流程(2)
  • 第三节 Android Input输入事件处理流程(3)

在这里插入图片描述

第十章 DisplayManagerService源码解析

  • 第一节 DisplayManagerService启动
  • 第二节 DisplayAdapter和DisplayDevice的创建
  • 第三节 DMS部分亮灭屏流程
  • 第四节 亮度调节
  • 第五节 Proximity Sensor灭屏原理
  • 第六节 Logical Display和Physical Display配置的更新

在这里插入图片描述

各位小伙伴们如果有需要这份《Android Framework源码开发揭秘》资料,点击下方卡片即可【免费领取】

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Android 9.0和10.0的Framework系统API上添加JNI方法需要经过以下步骤: 1. 在Java层调用JNI方法前,需要先创建定义JNI方法的C++文件和对应的头文件。这些文件应该保存在frameworks/native/libs/目录下的对应模块中。例如,如果想要在WebView模块中添加JNI方法,则应该在frameworks/native/libs/webviewchromium/目录下创建文件并进行定义。 2. 编写C++代码实现JNI方法。在代码中,需要采用JNI函数以及Java Native Interface标准库的方法来实现该方法的功能。具体实现过程可以参考Android源码中frameworks/native/libs/input/Input.cpp文件的实现。 3. 在C++代码的头文件中定义JNI方法。为了让Java层正确调用JNI方法,需要在C++头文件中定义JNI函数名称、Java包名、Java类名以及方法参数的信息。参考Android源码中frameworks/native/libs/webviewchromium/webviewchromium_jni.h文件。 4. 在Java层调用JNI方法。要调用JNI方法,需要在Java代码中加载C++库。可以使用静态代码块System.loadLibrary("yourlibrary")来加载C++库,并在程序中使用对应的Java扩展头文件。在Java代码中,需要使用JNI函数来调用JNI方法。参考Android源码中frameworks/native/libs/webviewchromium/WebBackForwardList.java文件。 通过以上步骤,即可在Android 9.0和10.0的Framework系统API中添加JNI方法。需要注意的是,添加JNI方法需要遵循JNI标准,使用合适的JNI库函数和API接口,以确保程序代码的正确性和稳定性。 ### 回答2: Android 9.0和10.0的Framework系统API都支持添加JNI方法。 首先,要添加一个JNI方法,您需要在Java中编写该方法的实现,然后在C / C ++中编写对应的本地代码,然后使用JNI将二者连接起来。 为了在Framework添加的JNI方法,您需要找到Framework源代码中对应的Java类和C ++代码。然后按照以下步骤进行操作: 1. 在Java类中添加的JNI方法声明,方法名必须与您要添加的本地方法的名称匹配。例如,如果您要添加一个名为newMethod的本地方法,则需要在Java类中声明以下内容: ```java public native void newMethod(int arg1, String arg2); ``` 注意:在声明中,您不能提供方法的实现。 2. 在C / C ++代码中实现的本地方法,方法名称必须与您在Java中声明的方法名称一致。 ```cpp JNIEXPORT void JNICALL Java_com_example_MyClass_newMethod(JNIEnv *env, jobject obj, jint arg1, jstring arg2) { // 实现您的代码 } ``` 3. 最后,在您的C / C ++代码中获取Java类的引用,以便在Native代码中调用该方法。 ```cpp jclass clazz = env->FindClass("com/example/MyClass"); jmethodID methodId = env->GetMethodID(clazz, "newMethod", "(ILjava/lang/String;)V"); ``` 通过此方法ID,您可以使用JNI在C / C ++中调用该方法。 ```cpp env->CallVoidMethod(obj, methodId, arg1, arg2); ``` 这样,您就可以在Android 9.0和10.0的Framework系统API中添加的JNI方法了。 ### 回答3: Android操作系统使用Java语言实现,但是也支持通过JNI机制(Java Native Interface)来调用C/C++编写的代码。在Android 9.0和10.0版本中,如果需要在Framework系统层中添加JNI方法,需要进行以下步骤: 1. 编写C/C++代码实现需要的功能,并将其编译成动态库(.so文件)。 2. 在Framework层中找到对应的Java类,并添加需要的Native方法声明。例如,如果要在TelephonyManager类中添加一个名为getSignalStrengthDbm的方法,则应该在TelephonyManager.java中添加以下Native方法声明: ``` private native int getSignalStrengthDbm(); ``` 3. 在frameworks/base目录下的services/core/jni目录中添加一个名为TelephonyManager.cpp的文件,并实现getSignalStrengthDbm方法: ``` static jint TelephonyManager_getSignalStrengthDbm(JNIEnv *env, jobject thiz){ // TODO: 通过调用C/C++代码实现需要的功能,并返回结果 return 0; } static const JNINativeMethod gMethods[] = { { "getSignalStrengthDbm", "()I", (void*)TelephonyManager_getSignalStrengthDbm}, }; int register_android_telephony_TelephonyManager(JNIEnv* env) { jclass clazz = env->FindClass("android/telephony/TelephonyManager"); if (clazz == NULL) { ALOGE("Can't find android/telephony/TelephonyManager"); return -1; } return env->RegisterNatives(clazz, gMethods, sizeof(gMethods) / sizeof(JNINativeMethod)); } ``` 4. 在frameworks/base目录下的services/core目录中找到文件Android.bp,将添加的TelephonyManager.cpp文件加入build文件中: ``` cc_library_shared { name: "libandroidfw", srcs: [ "jni/Animation.cpp", ... "jni/TelephonyManager.cpp", ], ... } ``` 5. 在Android.mk文件中添加TelephonyManager.cpp的编译规则: ``` LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := TelephonyManager LOCAL_CFLAGS := -Werror LOCAL_SRC_FILES := TelephonyManager.cpp LOCAL_SHARED_LIBRARIES := libutils libcutils libbinder include $(BUILD_SHARED_LIBRARY) ``` 6. 重编译Framework层并运行即可。 以上是在Android 9.0和10.0系统添加JNI方法的步骤,其中涉及到的文件和目录可能有所不同,在实际开发中需要根据具体情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值