Xposed注册系统服务

我们知道像 ClipboardManager, ActivityManager 实际上底层都是通过 Binderaidl 接口的形式实现的,对应的服务端类名都是 xxxService 的形式,例如 ClipboardService, ActivityManagerService。幸运的是,在 Xposed 框架支持下,我们也可以注册自定义的系统服务。

系统服务注册流程分析

不想看源码分析过程的,可以直接跳到 自定义系统服务实现

在这里以 API 27(Android 8.1)ActivityManagerService 为例,ActivityManagerService 是系统主进程的开端,这个类是 “核心Java系统” 开始以及 “系统上下文” 创建的地方。

SystemServerZygote 进程 fork 而来,其进程名为 system_server,大概流程为:
ZygoteInit#main() -> Zygote#forkSystemServer() -> com_android_internal_os_Zygote#nativeForkSystemServer() -> com_android_internal_os_Zygote#ForkAndSpecializeCommon() -> ZygoteInit#handleSystemServerProcess() -> ZygoteInit#zygoteInit() -> RuntimeInit#applicationInit() -> RuntimeInit#findStaticMain() -> SystemServer#main()

关于 SystemServer 更详细的生成过程分析,请参看 Android系统启动-SystemServer上篇

下面分析 SystemServer 方法都做了什么:

  • SystemServer#main()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public static void main(String[] args) {
    new SystemServer().run();
    }

    private void run() {
    // 创建主线程 Looper
    Looper.prepareMainLooper();
    // 创建系统Context
    createSystemContext();
    // 创建SystemServiceManager
    mSystemServiceManager = new SystemServiceManager(mSystemContext);

    // 启动各种系统服务
    // 1. 启动引导服务
    startBootstrapServices();
    // 2. 启动核心服务
    startCoreServices();
    // 3. 启动其他服务
    startOtherServices();

    Looper.loop();
    }
  • 创建系统Context - createSystemContext()

    1
    2
    3
    4
    5
    6
    7
    8
    private void createSystemContext() {
    ActivityThread activityThread = ActivityThread.systemMain();
    mSystemContext = activityThread.getSystemContext();
    mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);

    final Context systemUiContext = activityThread.getSystemUiContext();
    systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
    }

    关于 ActivityThread#systemMain() 中创建了 ActivityThread 对象,并调用其 attach 方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    public static ActivityThread systemMain() {
    ActivityThread thread = new ActivityThread();
    thread.attach(true);
    }

    ActivityThread() {
    mResoureceManager = ResoureceManager.getInstance();
    }

    private void attach(boolean attach) {
    if(!system) {
    ...
    } else {
    // 系统Context
    android.ddm.DdmHandleAppName.setAppName("system_process",UserHandle.myUserId());
    mInstrumentation = new Instrumentation();
    ContextImpl context = ContextImpl.createAppContext(this, getSystemContext().mPackageInfo);
    mInitialApplication = context.mPackageInfo.makeApplication(true, null);
    mInitialApplication.onCreate();
    }
    }

    关于 Application 的创建过程,就不再分析了。

  • 启动引导服务 - startBootstrapServices()

    1
    2
    3
    4
    5
    // 初始化 ActivityManagerService
    mActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();
    ...
    // 设置系统进程
    mActivityManagerService.setSystemProcess();

    追踪 SystemServiceManager#startService:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public <T extends SystemService> T startService(Class<T> serviceClass) {
    final String name = serviceClass.getName();
    final T service;
    Constructor<T> constructor = serviceClass.getConstructor(Context.class);
    service = constructor.newInstance(mContext);
    startService(service);
    return service;
    }

    public void startService(final SystemService service) {
    service.onStart();
    }

    SystemServiceManager#startService() 最终会调用 SystemService 实现类的 onStart() 方法。

    也就是说,会调用 ActivityManagerService.Lifecycle#onStart() 方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public static final class Lifecycle extends SystemService {
    private final ActivityManagerService mService;
    public Lifecycle(Context context) {
    super(context);
    mService = new ActivityManagerService();
    }

    @Override
    public void onStart() {
    mService.start();
    }

    public ActivityManagerService getService() {
    return mService();
    }
    }

    最终会调用 ActivityManagerService 的构造方法和 start 方法,完成其初始化和初步配置。

    再看一下 ActivityManagerService#setSystemProcess()

    1
    2
    3
    4
    public void setSystemProcess() {
    ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
    ...
    }

    至此,ActivityServiceManager 作为系统服务被注册添加到 ServiceManager 当中。

自定义系统服务实现

  1. 自定义 ICustomService.aidl

    1
    2
    3
    4
    5
    6
    7
    8
    package com.tianma.customsystemservice.aidl;

    interface ICustomService {
    /* toUppercase */
    String toUpperCase(String str);
    /* add numbers */
    int add(int num1, int num2);
    }
  2. 创建 ICustomService.aidl 的实现类 CustomService.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class CustomService extends ICustomService.Stub {
    @Override
    public String toUpperCase(String str) throws RemoteException {
    return str.toUpperCase();
    }

    @Override
    public int add(int num1, int num2) throws RemoteException {
    return num1 + num2;
    }
    }
  3. 创建 CustomServiceHook 类实现 IXposedHookZygoteInit,用来注册系统服务:

    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
    public class CustomServiceHook implements IXposedHookZygoteInit {
    @Override
    public void initZygote(StartupParam startupParam) throws Throwable {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    // android 5.0+
    Class<?> activityThread = Class.forName("android.app.ActivityThread");
    XposedBridge.hookAllMethods(activityThread, "systemMain", new XC_MethodHook() {
    @Override
    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
    final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    Class<?> ams = XposedHelpers.findClass("com.android.server.am.ActivityManagerService", classLoader);

    XposedHelpers.findAndHookConstructor(ams,
    Context.class,
    new XC_MethodHook() {
    @Override
    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
    CustomService.register((Context) param.args[0], classLoader);
    }
    });
    }
    });
    } else {
    final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    Class<?> ams = XposedHelpers.findClass("com.android.server.am.ActivityManagerService", classLoader);
    XposedBridge.hookAllMethods(ams,
    "main",
    new XC_MethodHook() {
    @Override
    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
    CustomService.register((Context) param.getResult(), classLoader);
    }
    });
    }
    }
    }

    上述代码中,ActivityManagerService 是系统主进程的开端,这个类是 “核心Java系统” 开始以及 “系统上下文” 创建的地方。在 Android L 之前,可以直接访问 ActivityManagerService 这个类;从 Android L 起系统使用了独立的类加载器(ClassLoader),需要先 Hook ActivityThread,因为 ActivityThread 中创建了可以用来访问 ActivityManagerService 的类加载器。

  4. CustomServiceregister() 方法用来注册系统服务:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public static void register(Context context, ClassLoader classLoader) {
    Class<?> svcManager = XposedHelpers.findClass("android.os.ServiceManager", classLoader);

    CustomService customService = new CustomService(context);
    XposedHelpers.callStaticMethod(svcManager,
    /* methodName */"addService",
    /* name */getServiceName(),
    /* service */ customService,
    /* allowIsolated */ true);

    log("register service succeed");
    }

    private static String getServiceName() {
    // 5.0 之后,selinux "user." 前缀
    return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? "user." : "") + "customservice";
    }

    其实就是通过调用 ServiceManager#addService() 来实现,需要注意的是,Android L 起,系统服务名需要加 user. 前缀。

完整的 CustomService 实现:

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package com.tianma.customsystemservice.aidl;

import android.content.Context;
import android.os.Build;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import java.lang.reflect.Method;

import de.robv.android.xposed.XposedHelpers;

public class CustomService extends ICustomService.Stub {
private static final String TAG = "CustomService";

private Context mContext;
private static ICustomService mClient;

private CustomService(Context context) {
mContext = context;
}

@Override
public String toUpperCase(String str) throws RemoteException {
return str.toUpperCase();
}

@Override
public int add(int num1, int num2) throws RemoteException {
return num1 + num2;
}

public static void register(Context context, ClassLoader classLoader) {
Class<?> svcManager = XposedHelpers.findClass("android.os.ServiceManager", classLoader);

CustomService customService = new CustomService(context);
XposedHelpers.callStaticMethod(svcManager,
/* methodName */"addService",
/* name */getServiceName(),
/* service */ customService,
/* allowIsolated */ true);

log("register service succeed");
}

private static String getServiceName() {
// 5.0 之后,selinux "user." 前缀
return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? "user." : "") + "customservice";
}

public static ICustomService getService() {
if (mClient == null) {
try {
Class<?> svcManager = Class.forName("android.os.ServiceManager");
Method getServiceMethod = svcManager.getDeclaredMethod("getService", String.class);
IBinder binder = (IBinder) getServiceMethod.invoke(null, getServiceName());
mClient = ICustomService.Stub.asInterface(binder);
} catch (Exception e) {
e.printStackTrace();
log(e);
}
}
return mClient;
}

private static void log(String text) {
Log.d(TAG, text);
}

private static void log(Throwable t) {
Log.e(TAG, Log.getStackTraceString(t));
}
}

调用:

1
2
3
4
5
ICustomService customService = CustomService.getService();
if (customService != null) {
int sum = customService.add(1, 2);
String upper = customService.toUpperCase("hello world");
}

完整示例源码:CustomSystemService

参考

Custom System Service using XposedBridge
XPrivacy - XPrivacy.java
Xposed Issue - classLoader ClassNotFoundException
Android系统启动-SystemServer上篇
Android系统启动-SystemServer下篇
基于xposed实现android注册系统服务,解决跨进程共享数据问题
使用Xposed添加自定义系统服务

0%