Android系统服务(一)解析ActivityManagerService(AMS)

相关文章 Android系统启动流程系列 Android应用进程系列 Android深入四大组件系列

前言

1.概述

AMS是系统的引导服务,应用进程的启动、切换和调度、四大组件的启动和管理都需要AMS的支持。从这里可以看出AMS的功能会十分的繁多,当然它并不是一个类承担这个重责,它有一些关联类,这在文章后面会讲到。AMS的涉及的知识点非常多,这篇文章主要会讲解AMS的以下几个知识点:

  • AMS的启动流程。
  • AMS与进程启动。
  • AMS家族。

2.AMS的启动流程

AMS的启动是在SyetemServer进程中启动的,Android系统启动流程(三)解析SyetemServer进程启动过程这篇文章中提及过,这里从SyetemServer的main方法开始讲起: frameworks/base/services/java/com/android/server/SystemServer.java

main方法中只调用了SystemServer的run方法,如下所示。 frameworks/base/services/java/com/android/server/SystemServer.java

在注释1处加载了动态库libandroid_servers.so。接下来在注释2处创建SystemServiceManager,它会对系统的服务进行创建、启动和生命周期管理。在注释3中的startBootstrapServices方法中用SystemServiceManager启动了ActivityManagerService、PowerManagerService、PackageManagerService等服务。在注释4处的startCoreServices方法中则启动了BatteryService、UsageStatsService和WebViewUpdateService。注释5处的startOtherServices方法中启动了CameraService、AlarmManagerService、VrManagerService等服务。这些服务的父类均为SystemService。从注释3、4、5的方法可以看出,官方把系统服务分为了三种类型,分别是引导服务、核心服务和其他服务,其中其他服务是一些非紧要和一些不需要立即启动的服务。系统服务总共大约有80多个,我们主要来查看引导服务AMS是如何启动的,注释3处的startBootstrapServices方法如下所示。

frameworks/base/services/java/com/android/server/SystemServer.java

在注释1处调用了SystemServiceManager的startService方法,方法的参数是ActivityManagerService.Lifecycle.class: frameworks/base/services/core/java/com/android/server/SystemServiceManager.java

startService方法传入的参数是Lifecycle.class,Lifecycle继承自SystemService。首先,通过反射来创建Lifecycle实例,注释1处得到传进来的Lifecycle的构造器constructor,在注释2处调用constructor的newInstance方法来创建Lifecycle类型的service对象。接着在注释3处将刚创建的service添加到ArrayList类型的mServices对象中来完成注册。最后在注释4处调用service的onStart方法来启动service,并返回该service。Lifecycle是AMS的内部类,代码如下所示。 frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

上面的代码结合SystemServiceManager的startService方法来分析,当通过反射来创建Lifecycle实例时,会调用注释1处的方法创建AMS实例,当调用Lifecycle类型的service的onStart方法时,实际上是调用了注释2处AMS的start方法。在SystemServer的startBootstrapServices方法的注释1处,调用了如下代码:

我们知道SystemServiceManager的startService方法最终会返回Lifecycle类型的对象,紧接着又调用了Lifecycle的getService方法,这个方法会返回AMS类型的mService对象,见注释3处,这样AMS实例就会被创建并且返回。

3.AMS与进程启动

Android系统启动流程(二)解析Zygote进程这篇文章中,我提到了Zygote的Java框架层中,会创建一个Server端的Socket,这个Socket用来等待AMS来请求Zygote来创建新的应用程序进程。要启动一个应用程序,首先要保证这个应用程序所需要的应用程序进程已经被启动。AMS在启动应用程序时会检查这个应用程序需要的应用程序进程是否存在,不存在就会请求Zygote进程将需要的应用程序进程启动。Service的启动过程中会调用ActiveServices的bringUpServiceLocked方法,如下所示。 frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

在注释1处得到ServiceRecord的processName的值赋值给procName ,其中ServiceRecord用来描述Service的android:process属性。注释2处将procName和Service的uid传入到AMS的getProcessRecordLocked方法中,来查询是否存在一个与Service对应的ProcessRecord类型的对象app,ProcessRecord主要用来记录运行的应用程序进程的信息。注释5处判断Service对应的app为null则说明用来运行Service的应用程序进程不存在,则调用注释6处的AMS的startProcessLocked方法来创建对应的应用程序进程, 具体的过程请查看Android应用程序进程启动过程(前篇)。

4.AMS家族

ActivityManager是一个和AMS相关联的类,它主要对运行中的Activity进行管理,这些管理工作并不是由ActivityManager来处理的,而是交由AMS来处理,ActivityManager中的方法会通过ActivityManagerNative(以后简称AMN)的getDefault方法来得到ActivityManagerProxy(以后简称AMP),通过AMP就可以和AMN进行通信,而AMN是一个抽象类,它会将功能交由它的子类AMS来处理,因此,AMP就是AMS的代理类。AMS作为系统核心服务,很多API是不会暴露给ActivityManager的,因此ActivityManager并不算是AMS家族一份子。 为了讲解AMS家族,这里拿Activity的启动过程举例,Activity的启动过程中会调用Instrumentation的execStartActivity方法,如下所示。 frameworks/base/core/java/android/app/Instrumentation.java

execStartActivity方法中会调用AMN的getDefault来获取AMS的代理类AMP。接着调用了AMP的startActivity方法,先来查看AMN的getDefault方法做了什么,如下所示。 frameworks/base/core/java/android/app/ActivityManagerNative.java

getDefault方法调用了gDefault的get方法,我们接着往下看,gDefault 是一个Singleton类。注释1处得到名为”activity”的Service引用,也就是IBinder类型的AMS的引用。接着在注释2处将它封装成AMP类型对象,并将它保存到gDefault中,此后调用AMN的getDefault方法就会直接获得AMS的代理对象AMP。注释2处的asInterface方法如下所示。 frameworks/base/core/java/android/app/ActivityManagerNative.java

asInterface方法的主要作用就是将IBinder类型的AMS引用封装成AMP,AMP的构造方法如下所示。

frameworks/base/core/java/android/app/ActivityManagerNative.java

AMP的构造方法中将AMS的引用赋值给变量mRemote ,这样在AMP中就可以使用AMS了。 其中IActivityManager是一个接口,AMN和AMP都实现了这个接口,用于实现代理模式和Binder通信。 再回到Instrumentation的execStartActivity方法,来查看AMP的startActivity方法,AMP是AMN的内部类,代码如下所示。 frameworks/base/core/java/android/app/ActivityManagerNative.java

首先会将传入的参数写入到Parcel类型的data中。在注释1处,通过IBinder类型对象mRemote(AMS的引用)向服务端的AMS发送一个START_ACTIVITY_TRANSACTION类型的进程间通信请求。那么服务端AMS就会从Binder线程池中读取我们客户端发来的数据,最终会调用AMN的onTransact方法,如下所示。 frameworks/base/core/java/android/app/ActivityManagerNative.java

onTransact中会调用AMS的startActivity方法,如下所示。 frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

startActivity方法会最后return startActivityAsUser方法,如下所示。 frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

startActivityAsUser方法最后会return ActivityStarter的startActivityMayWait方法,这一调用过程已经脱离了本节要讲的AMS家族,因此这里不做介绍了,具体的调用过程可以查看Android深入四大组件(一)应用程序启动过程(后篇)这篇文章。

在Activity的启动过程中提到了AMP、AMN和AMS,它们共同组成了AMS家族的主要部分,如下图所示。

AMP是AMN的内部类,它们都实现了IActivityManager接口,这样它们就可以实现代理模式,具体来讲是远程代理:AMP和AMN是运行在两个进程的,AMP是Client端,AMN则是Server端,而Server端中具体的功能都是由AMN的子类AMS来实现的,因此,AMP就是AMS在Client端的代理类。AMN又实现了Binder类,这样AMP可以和AMS就可以通过Binder来进行进程间通信。

ActivityManager通过AMN的getDefault方法得到AMP,通过AMP就可以和AMN进行通信,也就是间接的与AMS进行通信。除了ActivityManager,其他想要与AMS进行通信的类都需要通过AMP,如下图所示。

原文发布于微信公众号 - 刘望舒(liuwangshuAndroid)

原文发表时间:2017-07-31

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏刘望舒

Android PMS的创建过程

PMS的创建过程分为两个部分进行讲解,分别是SyetemServer处理部分和PMS构造方法。其中SyetemServer处理部分和AMS和WMS的创建过程是类...

11830
来自专栏everhad

笔记:Zygote和SystemServer进程启动过程

简述 Android设备启动过程中,先是Linux内核加载完,接着Android中的第一个进程init启动,它会启动一些需要开机启动的进程。 Zygote就是...

27680
来自专栏Android 研究

APK安装流程详解8——PackageManagerService的启动流程(下)

那我们就来看下scanPackageLI(PackageParser.Package, int, int, long, UserHandle)方法

42510
来自专栏Java帮帮-微信公众号-技术文章全总结

Web-第二十一天 Web商城实战一【悟空教程】

public class BaseServlet extends HttpServlet {

21140
来自专栏分布式系统进阶

ReplicaManager源码解析2-LeaderAndIsr 请求响应

其中最主要的操作调用ReplicaManager.becomeLeaderOrFollower来初始化Partition

7510
来自专栏别先生

一脸懵逼学习Storm的搭建--(一个开源的分布式实时计算系统)

Storm的官方网址:http://storm.apache.org/index.html 1:集群部署的基本流程(基本套路): 集群部署的流程:下载安...

56960
来自专栏JackeyGao的博客

Django小技巧20: 使用多个settings模块

通常来说, 为了保持项目的配置简单,我们会避免使用多个配置文件。但理想很丰满, 现实是随着项目越来越大, settings.py可能也会变得相当复杂. 在那种情...

70110
来自专栏Golang语言社区

写在学习golang一个月后

连接池。由于PHP没有连接池,当高并发时就会有大量的数据库连接直接冲击到MySQL上,最终导致数据库挂掉。虽然Swoole有连接池,但是Swoole只是PHP的...

29020
来自专栏张善友的专栏

HTTP Basic Authentication验证WCF Data Service

WCF Data Service是OData协议,也是RESTFul Service的一种,上篇文章已经介绍了HTTP Basic Authentication...

21680
来自专栏landv

杨格门锁 YGSLockSDK V3.3酒管软件接口_99v

25690

扫码关注云+社区

领取腾讯云代金券