Xposed注册系统服务

Author Avatar
发表:12月 29, 2018 更新:3月 09, 2019
字数统计:1.4k 字 阅读时长:6 分

我们知道像 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()

    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()

    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 方法:

    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()

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

    追踪 SystemServiceManager#startService:

    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() 方法:

    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()

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

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

自定义系统服务实现

  1. 自定义 ICustomService.aidl

    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

    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,用来注册系统服务:

    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() 方法用来注册系统服务:

    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 实现:

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));
    }
}

调用:

  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添加自定义系统服务