AMS的起源,SystemServer的前世今生

作者:OpenGL

前世

SystemServer的创建还得追溯到之前的Zygote进程中的ZygoteInit代码中。这里的Zygote.forkSystemServer()方法就是实现分裂的关键代码。它内部调用了native方法实现了进程分裂。

执行完这行代码之后。我们的系统中就会出现两个一模一样的进程,只不过进程id不一样。这两个进程都会继续执行之后的代码。一个是Zygote进程,一个是分裂出来的子进程(此时还没给该进程命名SystemServer)。

1. 梦回Zygote进程

这里精简了一下ZygoteInit的代码,只留了几个重要的方法。并且重要代码都加了注释,不必深究代码内部做了什么。这样可以更加方便理解。让我们先看下代码,再接着往后看。

  class ZygoteInit {public static void main(String argv[]) {// ...代码忽略...// 此处的startSystemServer为trueif (startSystemServer) {// 调用forkSystemServer方法Runnable r = forkSystemServer();if (r != null) {r.run();return;}}// runselectloop内部是一个while(true)的循环,// 只有在退出while循环时,会return一个runnable// 一旦执行完成,意味着zygote进程所有代码执行完成。Runnable caller = zygoteServer.runSelectLoop(abiList);if (caller != null) {caller.run();}}private static Runnable forkSystemServer() {// 内部通过native方法分裂进程,// 分裂之后,一个zygote进程,一个子进程。int pid = Zygote.forkSystemServer();// 这里之后的代码,Zygote进程和分裂出的子进程都会继续执行if (pid == 0) {// 子进程关闭socketzygoteServer.closeServerSocket(); // 这里给进程命名,并启动Systemserver.javareturn handleSystemServerProcess(parsedArgs);}// Zygote进程,执行完forkSystemServer方法会返回nullreturn null;}private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) // niceName是进程名字,即SystemServer。// 在这里把这个分裂出来的进程,重新命名为SystemServerif (parsedArgs.mNiceName != null) {Process.setArgV0(parsedArgs.mNiceName);}// ...代码忽略...// 此处调用native方法开启Binder线程池// 这里通过SystemServer的全类名,用反射的方式,启动SystemServer的main方法return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,parsedArgs.mDisabledCompatChanges,parsedArgs.mRemainingArgs, cl);}}

我们在main方法里调用了forkSystemServer方法。forkSystemServer方法中通过 int pid = Zygote.forkSystemServer(); 分裂了一个进程出来,并返回分裂出的进程的pid值。这里分裂进程是调用的native方法,即底层的c++代码。所以这里一笔带过。有兴趣的同学可以进源码中查看。

此时已经有了两个进程。一个Zygote进程,一个分裂出来的子进程。并且两个进程都会继续执行未执行完的代码

2. 两条不同的路

我们再将目光转回到 int pid = Zygote.forkSystemServer();,这句代码可以理解为,分裂进程并返回子进程的pid。

进程在分裂后,都会返回一个pid的值,且继续执行。只不过Zygote进程返回的是子进程的pid,而 子进程由于它是被分裂出来的进程,所以Zygote.forkSystemServer();方法返回的是0。从这里开始两个进程的命运就开始走向了两条不同的道路。

3. 前提假设

这里为了方便理解,我们做个假设,假设Zygote的进程id为1000,分裂出的子进程id为2000。

4. Zygote进程

假设在Zygote进程中,返回的pid的值是分裂出的子进程的2000。

我们在看回上面ZygoteInit代码中,由于Zygote进程返回的pid的值是非0的数,所以forkSystemServer() 这个方法对于Zygote进程来说返回的是null,再看ZygoteInit的代码可知,Zygote进程将会执行zygoteServer.runSelectLoop(abiList) 这行代码。

即在分裂进程后,将会进入循环等待。

5. 分裂出的子进程

而在子进程中,由于 int pid = Zygote.forkSystemServer(); 返回的pid是0,所以会执行if (pid == 0) 这个代码块里的handleSystemServerProcess(parsedArgs) 方法。

这个方法里会给分裂出来的进程重新命名SystemServer,并且会通过反射执行SystemServer.java中的main方法。

至此,SystemServer就正式和Zygote分离开了。


今生

上面说到,分裂出的子进程会执行SystemServer的main方法。所以为了方便理解,先上一个SystemServer大致的功能图。同时后面加上SystemServer精简过的代码。以方便大家加深记忆。从图中可知SystemServer大概做了7件事。不过,准备Looper和Looper.loop()也可以看做一件事。

public final class SystemServer {/*** The main entry point from zygote.*/public static void main(String[] args) {new SystemServer().run();}private void run() {// 1. Prepare the main looper thread (this thread).android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND);Looper.prepareMainLooper();// Initialize native services.System.loadLibrary("android_servers");// 2. Initialize the system context.createSystemContext();// 3. Create the system service manager.mSystemServiceManager = new SystemServiceManager(mSystemContext);// Start services.// 4. 启动引导类服务startBootstrapServices(t); // 5. 启动核心类服务startCoreServices(t); // 6. 启动其他类服务startOtherServices(t); // 7. Loop forever.Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");}
}

1. 准备Looper

这里做的第一件事,就是给当前的线程设置了优先级。紧接着就是大家特别熟悉的一句代码Looper.prepareMainLooper();

熟悉Handler的童鞋看到这个肯定特别亲切。这就是为什么在主线程中可以直接使用Handler的原因,这个的话涉及Handler和Looper的关系,这里不做过多的赘述,感兴趣的同学可以上网搜一下,或者让我出一篇这个的文章。不过网上已经有太多的人写这个了。 后面的ActivityThread类的main方法中会出现这个方法。大家可以找一下这个方法。

这里的Looper.prepareMainLooper(); 和后面的 Looper.loop(); 是相对应的。

2. 创建上下文啦

这里会初始化系统类上下文,并且会出现我们很熟悉的一个类ActivityThread。调用它的systemMain() 方法。

public final class SystemServer {// 省略其他代码private void createSystemContext() {ActivityThread activityThread = ActivityThread.systemMain();mSystemContext = activityThread.getSystemContext();final Context systemUiContext = activityThread.getSystemUiContext();}
}

下面有ActivityThread的相关代码。systemMain方法中创建了ActivityThread对象,并且执行了attach方法。由于这里的参数system是true,所以执行的是else里的代码块。

attach方法里,创建了context上下文,同时通过Instrumentation创建了application。为了控制文章长度,就不在这里贴相关代码了。

public final class ActivityThread{public static void main(String[] args) {// 准备looperLooper.prepareMainLooper();// 主线程进入循环等待Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");}@UnsupportedAppUsagepublic static ActivityThread systemMain() {ActivityThread thread = new ActivityThread();thread.attach(true, 0);return thread;}Application mInitialApplication;private void attach(boolean system, long startSeq) {if (!system) {// 内容很重要,涉及App启动,但是此处用不到所以省略.......} else {mInstrumentation = new Instrumentation();mInstrumentation.basicInit(this);// 创建上下文,context持有该ActivityThread对象ContextImpl context = ContextImpl.createAppContext(this, getSystemContext().mPackageInfo);// mPackageInfo是LoadedApk,LoadedApk内部含有Instrumentation,// makeApplication内部通过Instrumentation的newApplication方法创建了Application。mInitialApplication = context.mPackageInfo.makeApplication(true, null);mInitialApplication.onCreate();}}
}

ContextImpl是Context的具体实现类。同时创建了LoadedApk对象。LoadedApk记录了当前要加载的apk的相关信息,例如PackageName,LibDir,ResDir等。


/*** Common implementation of Context API, which provides the base* context object for Activity and other application components.*/
class ContextImpl extends Context {@UnsupportedAppUsagestatic ContextImpl createSystemContext(ActivityThread mainThread) {LoadedApk packageInfo = new LoadedApk(mainThread);ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, null,0, null, null);return context;}
}

3. SystemServiceManager

SystemServiceManager官方的注释解释是,管理SystemService的创建、开始以及其他生命周期事件。通过反射的方式,调用SystemService以及其子类的start方法。后面的startCoreServices方法里有相关代码。

/*** Manages creating, starting, and other lifecycle events of system services* {@link com.android.server.SystemService system services}.** {@hide}*/
public class SystemServiceManager {/*** Starts a service by class name.*/public SystemService startService(String className) {final Class<SystemService> serviceClass = loadClassFromLoader(className,this.getClass().getClassLoader());return startService(serviceClass);}/*** Creates and starts a system service. The class must be a subclass of* {@link com.android.server.SystemService}.*/public <T extends SystemService> T startService(Class<T> serviceClass) {// Create the service.Constructor<T> constructor = serviceClass.getConstructor(Context.class);final T service = constructor.newInstance(mContext);startService(service);return service;}public void startService(@NonNull final SystemService service) {// Register it.mServices.add(service);// Start it.service.onStart();}
}

4. startBootstrapServices

开启系统服务,这里有很多很多的Service被启动。其中最关键的几个Service就是ActivityManagerService,简称AMS。另外一个是ActivityTaskManagerService,简称ATMS 。还有PackageManagerService ,即PMS

其实AMSATMS 他们两个其实是有些渊源的。最开始四大组件的启动服务都在ActivityManagerService中,不过等到了Android10.0之后,可能是研发人员觉得AMS的工作量太大了,所以给他找了个小弟ATMS,将activity的相关工作放到了ActivityTaskManagerService中。不过AMS还会持有ATMS引用,这波属实是让AMS从一个底层员工变成了一个带新人的老员工。

private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {mPackageManagerService = PackageManagerService.main(mSystemContext, installer,mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);// Activity manager runs the show.ActivityTaskManagerService atm = mSystemServiceManager.startService(ActivityTaskManagerService.Lifecycle.class).getService();mActivityManagerService = ActivityManagerService.Lifecycle.startService(mSystemServiceManager, atm);mActivityManagerService.setSystemServiceManager(mSystemServiceManager);//省略很多代码...
}

startBootstrapServices这里创建了很多service,其中最引人注意的是PMS,AMS以及ATMS。


5. startCoreServices

核心服务这里的话,没有太多可说的。如果各位有感兴趣的可以直接看代码中的英文注释自行理解。我就不多做加工了,可能原汁原味比我加工过的更好理解。

不过从这里通过SystemServeiceManagerstart方法,启动了很多SystemService的子类。

/*** Starts some essential services that are not tangled up in the bootstrap process.*/
private void startCoreServices(@NonNull TimingsTraceAndSlog t) {// Service for system configmSystemServiceManager.startService(SystemConfigService.class);// Tracks the battery level.  Requires LightService.mSystemServiceManager.startService(BatteryService.class);// Tracks application usage stats.mSystemServiceManager.startService(UsageStatsService.class);mActivityManagerService.setUsageStatsManager(LocalServices.getService(UsageStatsManagerInternal.class));// Tracks whether the updatable WebView is in a ready state and watches for update installs.if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_WEBVIEW)) {mWebViewUpdateService = mSystemServiceManager.startService(WebViewUpdateService.class);}// Tracks and caches the device state.mSystemServiceManager.startService(CachedDeviceStateService.class);// Tracks cpu time spent in binder callsmSystemServiceManager.startService(BinderCallsStatsService.LifeCycle.class);// Tracks time spent in handling messages in handlers.mSystemServiceManager.startService(LooperStatsService.Lifecycle.class);// Manages apk rollbacks.mSystemServiceManager.startService(ROLLBACK_MANAGER_SERVICE_CLASS);// Service to capture bugreports.mSystemServiceManager.startService(BugreportManagerService.class);// Serivce for GPU and GPU driver.mSystemServiceManager.startService(GpuService.class);
}

6. startOtherServices

他来了他来了,他带着Launcher走来了。这里面创建了windowsManagerService,而且调用了AMS的systemReady方法启动了Launcher这个app。

这里稍微挖个坑,启动Launcher的流程,留到AMS里面在进行讲解,这里只说结果。那就是startOtherServices里创建了Launcher。

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {WindowManagerService wm = null;wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
}

7. Looper.loop

最后的最后,和我们的开头相呼应。我们的SystemServer进程的主线程通过Looper.loop进入循环等待。一旦有handler传递消息,就会在systemServer的这个线程中进行处理。

最后

SystemServer到此就结束了,其实还有一些东西没有说,比如SystemManager如何注册服务,比如AMS如何启动Launcher。这些如果各位感兴趣的话,可以给我留言,我会再写相应的文章进行讲解。

另外,只看文章真的只能是暂时记住。真的想加深记忆,需要自己走一遍源码流程。好记性不如烂笔头,在走源码的时候,将重要的点进行记录,也是加深记忆的一种方式。

如果各位觉得本文写的还算凑合,请大家帮忙点个赞加个关注,你们的点赞关注,就是我更新文章的最大动力。让我们一起学习,一起进步,最后给各位一个图解,让我们一起加油~

图解


如果你还没有掌握Framework,现在想要在最短的时间里吃透它,可以参考一下《Android Framework核心知识点》,里面内容包含了:Init、Zygote、SystemServer、Binder、Handler、AMS、PMS、Launcher……等知识点记录。

《Framework 核心知识点汇总手册》:https://qr18.cn/AQpN4J

Handler 机制实现原理部分:
1.宏观理论分析与Message源码分析
2.MessageQueue的源码分析
3.Looper的源码分析
4.handler的源码分析
5.总结

Binder 原理:
1.学习Binder前必须要了解的知识点
2.ServiceManager中的Binder机制
3.系统服务的注册过程
4.ServiceManager的启动过程
5.系统服务的获取过程
6.Java Binder的初始化
7.Java Binder中系统服务的注册过程

Zygote :

  1. Android系统的启动过程及Zygote的启动过程
  2. 应用进程的启动过程

AMS源码分析 :

  1. Activity生命周期管理
  2. onActivityResult执行过程
  3. AMS中Activity栈管理详解

深入PMS源码:

1.PMS的启动过程和执行流程
2.APK的安装和卸载源码分析
3.PMS中intent-filter的匹配架构

WMS:
1.WMS的诞生
2.WMS的重要成员和Window的添加过程
3.Window的删除过程

《Android Framework学习手册》:https://qr18.cn/AQpN4J

  1. 开机Init 进程
  2. 开机启动 Zygote 进程
  3. 开机启动 SystemServer 进程
  4. Binder 驱动
  5. AMS 的启动过程
  6. PMS 的启动过程
  7. Launcher 的启动过程
  8. Android 四大组件
  9. Android 系统服务 - Input 事件的分发过程
  10. Android 底层渲染 - 屏幕刷新机制源码分析
  11. Android 源码分析实战

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/68394.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

对任意类型数都可以排序的函数:qsort函数

之前我们学习过冒泡排序&#xff1a; int main() {int arr[] { 9,7,8,6,5,4,3,2,1,0 };int sz sizeof(arr)/sizeof(arr[0]);int i 0;for (i 0; i < sz-1; i) {int j 0;for (j 0; j < sz-1-i; j) {if (arr[j] > arr[j 1]){int temp 0;temp arr[j];arr[j] ar…

Java通过文件流和文件地址下载文件

通过文件流下载文件 如何使用 MultipartFile 进行文件上传、下载到本地&#xff0c;并返回保存路径呢&#xff1a; import org.springframework.web.multipart.MultipartFile;import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOExcep…

laravel框架中批量更新数据

在php框架中 tp中就有批量更新封装好的 SaveAll 在laravel中有批量插入没有批量更新操作;因此我们可以自己去封装一个 然后批量进行更新操作 封装参考代码: /*** 批量更新** param $tableName 表名称* param string $pk 更新的字段* param array $multipleData 要更新的数据*…

多智能体共识算法的粗略数学证明

这篇文章是对论文《Consensus and Cooperation in Networked Multi-Agent Systems》中定理一的粗略数学证明。 论文中的定理一&#xff1a; 对一个由 n 个智能体以拓扑结构 G 组成的网络&#xff0c;使用以下共识算法&#xff1a; x ˙ i ( t ) Σ j ∈ N i a i j ( x j ( t…

【BEV】3D视觉 PRELIMINARY

这里的知识来自于论文 Delving into the Devils of Bird’s-eye-view Perception: A Review, Evaluation and Recipe 的 Appendix B.1 部分来自 这篇文章 从透视图转向鸟瞰图。&#xff08;Xw、Yw、Zw&#xff09;、&#xff08;Xc、Yc、Zc&#xff09;表示世界World坐标和相…

React - useEffect函数的理解和使用

文章目录 一&#xff0c;useEffect描述二&#xff0c;它的执行时机三&#xff0c;useEffect分情况使用1&#xff0c;不写第二个参数 说明监测所有state&#xff0c;其中一个变化就会触发此函数2&#xff0c;第二个参数如果是[]空数组&#xff0c;说明谁也不监测3&#xff0c;第…

Word 2019打开.doc文档后图片和公式不显示(呈现为白框)的解决办法

Word 2019打开.doc文档后图片和公式不显示&#xff08;呈现为白框&#xff09;的解决办法 目录 Word 2019打开.doc文档后图片和公式不显示&#xff08;呈现为白框&#xff09;的解决办法一、问题描述二、解决方法1.打开 WORD 2019&#xff0c;点击菜单中的“文件”&#xff1b;…

无服务器架构发布啦!

导读Serverless 1.15.2 已发布。The Serverless Framework (无服务器架构&#xff09;允许你自动扩展、按执行付费、将事件驱动的功能部署到任何云。 目前支持 AWS Lambda、Apache OpenWhisk、Microsoft Azure&#xff0c;并且正在扩展以支持其他云提供商。 Serverless 降低了…

iOS-砸壳篇(两种砸壳方式)

CrackerXI砸壳呢&#xff0c;当时你要是使用 frida-ios-dump 也是可以的&#xff1b; https://github.com/AloneMonkey/frida-ios-dump frida-ios-dump: 代码中需要更改的&#xff1a;手机中的内网ip 密码 等 最后放到我的砸壳路径里&#xff1a; python dump.py -l查看应用…

uniapp 自定义手机顶部状态栏不生效问题

想要的效果想淘宝一样&#xff0c;底色覆盖到手机顶部&#xff0c;找了两天都没找到原因&#xff0c;过程很艰苦&#xff0c;直接上结果吧 项目是后来接手的&#xff0c;最终原因出在这&#xff0c; "immersed" : false>设置为 true 就可以了&#xff0c;沉浸式样…

每日一题——合并二叉树

题目 已知两颗二叉树&#xff0c;将它们合并成一颗二叉树。合并规则是&#xff1a;都存在的结点&#xff0c;就将结点值加起来&#xff0c;否则空的位置就由另一个树的结点来代替。例如&#xff1a; 两颗二叉树是: Tree 1 Tree 2 合并后的树为 数据范围&#xff1a;树上节点数…

【1572. 矩阵对角线元素的和】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 给你一个正方形矩阵 mat&#xff0c;请你返回矩阵对角线元素的和。 请你返回在矩阵主对角线上的元素和副对角线上且不在主对角线上元素的和。 示例 1&#xff1a; 输入&#xff1a;mat [[1,2,3]…