Android启动过程(三)ActivityManagerService—-1

  • Post author:
  • Post category:其他


首先AMS是什么?

ActivityManagerService (AMS)是Android提供的一个用于管理Activity(和其他组件)运行状态的系统流程,也是我们编写APK应用程序时使用最频繁的一个系统服务。

AMS功能概述

首先对AMS的功能进程整体概述,从而为后面分析其内部实现打下基础。


ActivityStack

理解了AMS所需完成的功能后,我们会深入代码层来讲解它们的实现–其中最重要的两个核心就是

ActivityStack



ActivityTask

从名称可以看出,ActivityStack是Activity的记录者与管理者,同时也为AMS管理系统运行情况提供了基础。


ActivityTask

Task 是Android应用程序中的一大利器,而且其中涉及的逻辑关系相对复杂,因而我们专门用一个小节具体描述讲解

和WMS一样,AMS也是寄存于systemServer中的,它会在系统启动时,创建一个线程来循环处理客户的请求。值得一提的是,AMS会向ServiceManager登记多种Binder Server如“activity”,”meminfo”,”cpuinfo”等–不过只有第一个“activity”才是AMS的“主业”,并由ActivityManagerService实现:剩余服务的功能则是由其他类提供的。

先来看看AMS的启动过程。代码如下

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

private void run() {


try {


startBootstrapServices();  //这个方法是启动AMS的方法

startCoreServices();  //启动core服务

startOtherServices(); //启动其他的服务

} catch (Throwable ex) {


Slog.e(“System”, “******************************************”);

Slog.e(“System”, “************ Failure starting system services”, ex);

throw ex;

}

}

private void startBootstrapServices() {

Installer installer = mSystemServiceManager.startService(Installer.class);

// Activity manager runs the show.

mActivityManagerService = mSystemServiceManager.startService(

ActivityManagerService.Lifecycle.class).getService();  //启动MAS

mActivityManagerService.setSystemServiceManager(mSystemServiceManager);

mActivityManagerService.setInstaller(installer);

// Set up the Application instance for the system process and get started.

mActivityManagerService.setSystemProcess(); //通过AMS,将当前进程设置成android的应用程序的环境,安装framework-res.apk,生成进程相关的ProcessRecord

}

public void setSystemProcess() {


try {


ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);//AMS主业

ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);

ServiceManager.addService(“meminfo”, new MemBinder(this)); //使用的内存情况

ServiceManager.addService(“gfxinfo”, new GraphicsBinder(this));

ServiceManager.addService(“dbinfo”, new DbBinder(this));

if (MONITOR_CPU_USAGE) {


ServiceManager.addService(“cpuinfo”, new CpuBinder(this));

}

ServiceManager.addService(“permission”, new PermissionController(this));

ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(

“android”, STOCK_PM_FLAGS);

//注意,这里的mContext是 mSystemContext, 即系统级的上下文, 查找package name为 “android”

//的ApplicationInfo,从以上可知package name为 “android”的 apk是 framework-res.apk,

//即framework的资源文件apk, ApplicationInfo是通过解析framework-res.apk里的AndroidManifest.xml获得的

mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());

//开始为ActivityThread 安装 system application相关信息,将framework-res.apk对应的

//ApplicationInfo安装到LoadedApk中的mApplicationInfo



} catch (PackageManager.NameNotFoundException e) {


throw new RuntimeException(

“Unable to find android system package”, e);

}

}

由上可知AMS注册到ServiceManager不只注册了自己的一个Server,而是一系列与进程管理相关的服务。

现对AMS进行分类描述:


1.组件状态管理

这里的组件不仅仅指的是Activity,而是所有的四大组件,状态管理包括组件的开启,关闭等一系列操作,如startActivity,startActivityAndWait,activityPaused,startService,stopService,removeContentProvider等。


2组件状态查询

这类函数用于查询组件当前的运行情况,如getCallingActivity,getServices等


3.Task相关

Task 相关的函数包括removeSubTask,removeTaskBackwards,moveTaskToFront等

管理当前系统中Activity状态——-Activity Stack

从名称上看,ActivityStack 是管理当前系统中所有Activity状态的一个数据结构。那么是不是这样的呢?

以下内容是从ActivityStack.java 中提取出来的。


1ActivityState

描述了一个Activity所可能经历的所有状态。其定义如下

enum ActivityState {


INITIALIZING, //正在初始化

RESUMED,  //恢复

PAUSING, //正在暂停

PAUSED, //已经暂停

STOPPING,//正在停止

STOPPED,//已经停止

FINISHING,//正在完成

DESTROYING,//正在销毁

DESTROYED//已经销毁

}

结合Activity状态改变是其自身所能收到的回调函数,查看如下图与上面做一下对照

图片转自(

https://blog.csdn.net/sam_linux/article/details/14648145


2ArrayList

除了状态管理外,ActivityStack 中还有一系列不同功能的ArrayList成员变量。它们的共同点在于列表元素都是ActivityRecord—这个类负责记录每个Activity的运行时信息。因而也可以看出,ActivityStack确实是AMS管理Activity的“大仓库”。

ActivityStack管理的各ArrayList(部分)
ArrayList
mHistory 所有的Activity的信息在这里都有记录,直到它被destoryed
mLRUActivities 正在运行的Activity的列表集合,以最近的使用情况来排序,即队头元素是最近使用最少的元素
mStoppingActivities 列表中的Activity已经可以被Stop,但是还得等待下一个Activity处于就绪状态
mGoingToSleepActivies

列表中的Activity正在进入睡眠状态

mNoAnimActivities 列表中的Activity不考虑状态间迁移动画
mFinishingActivities 列表中的Activity已经可以被finished,但还需要等待上一个Activity就绪


3记录特殊状态下的Activity

特殊状态下的Activity
ActivityRecord
mPausingActivity 当前正在被暂停(pausing)的Activity
mLastPausedActivity 上一个被暂停的Activity
mResumedActivity 当前被恢复(resumed)的Activity,可以为null
mLastStartedActivity 最近一次被启动的Activity

以上所述的3类变量构成了ActivityStack的主框架。如果用一句话简单概述AMS的功能,就是:

”AMS是通过ActivityStack(和其他数据结构)来记录,管理系统中的Activity(和其他组件)状态,并提供查询功能的一个系统服务。”这句话包含了以下几个重点。


1.AMS的主要工作就是管理,记录,查询

打个比方,AMS就像户籍登记处。所有新加入或者注销的家庭都需要到这里办理业务;而且它还提供对外的查询功能—-这点类似于公安局开具的“户籍证明”,用于表明办证者当前的户口状态。


2.AMS是系统进程的一部分(确切的说它运行于一个独立的线程中)

从内核的角度来说,AMS其实也是普通进程中的一部分,只不过它提供的是全局性的系统服务,接着上面打比方,户籍登记处和家庭一样,也是在一个“房子”(进程)里运行的。它有一套严格的办事规程(线程),来处理户主的各种请求(登记,注销,查询等)。值得一提的是,AMS的任务只是负责保管Activity(及其他组件)的状态信息,而像Activity中描述的UI界面如何在物理屏幕上显示等工作是由WindowManagerService和SurfaceFkinger来完成的(后续描述WMS将讲解)

StartActivity流程

之前的描述了AMS所能提供的功能以及内部的一些重要变量,接下来看一下AMS具体是如何展开工作的。

从启动一个目标Acivity—-具体是哪个Activity则是AMS通过对系统中安装的所有程序包进行“Intent匹配”得到的,并不局限于调用者本身所在的package范围。换句话说,startActivity()最终很可能启动的是其他进程中的组件。当系统匹配到某个目标Activity后分为两种情况。

1如果通过Intent匹配到的目标对象,其所属程序包中已经有其他元素在运行(意味着该程序进程已启动),那么AMS就会通知这个进程来加载运行我们指定的目标Activity

2如果当前Activity所属程序没有进程在运行,AMS就会先启动它的一个实例,然后让其运行目标Activity.

先大概讲解一下startActivity()所经历的函数调用流程,从调用方(Activity1)开始:Activity1→startActivity@ContextImp.java→execStartActivity@Instrumentation.java→startActivity@ActivityManagerService.java

因而经过层层中转后,调用者发起的startActivity最终还是在AMS中实现的。接下来的问题就转化为:AMS内部对startActivity是如何处理的?

看似一个简单的功能,实际上AMS要做的工作还是很多的——首先来辨别一下AMS中的5个“长相”类似startActivity函数,以防后期混淆。统一列出如下:

startActivity@ActivityManagerService

startActivityAsUser@ActivityManagerService.java

startActivityMayWait@ActivityStack.java

startActivityLocked@ActivityStack.java

startActivityUncheckedLocked@ActivityStack.java

这5个函数存在先后调用关系,源码如下:

/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public final int startActivity(IApplicationThread caller, String callingPackage,

Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,

int startFlags, ProfilerInfo profilerInfo, Bundle options) {


return

startActivityAsUser

(caller, callingPackage, intent, resolvedType, resultTo,

resultWho, requestCode, startFlags, profilerInfo, options,

UserHandle.getCallingUserId());

}

可以看到,startActivityAsUser与Activity只多了最后一个参数userId,它表明调用者的用户ID值,因而可以通过Binder机制的getCallingUid获得:(Binder机制后续会讲解)

@Override

public final int startActivityAsUser(IApplicationThread caller, String callingPackage,

Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,

int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {



enforceNotIsolatedCaller

(“startActivity”);

userId =

handleIncomingUser

(Binder.getCallingPid(), Binder.getCallingUid(), userId,

false, ALLOW_FULL_ONLY, “startActivity”, null);

// TODO: Switch to user app stacks here.

return mStackSupervisor.

startActivityMayWait

(caller, -1, callingPackage, intent,

resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,

profilerInfo, null, null, options, userId, null, null);/*这个函数是ActivityStack提供的*/

}

函数startActivityAsUser的一大重点就是做权限检查,包括:


enforceNotIsolatedCaller

检查调用者是否属于被隔离的对象


handleIncomingUser

调用者是否有权力执行这一操作

由此可以看出5个“startActivityXX”其实是5个执行步骤,而且一旦其中的一步出现错误就会终止整个流程。

接着分析

startActivityMayWait

这个函数。我们之间分析核心内容

根据图中描述,在startActivityMayWait中:

是要启动某个符合Intent要求的Activity,那么首先就应该确定这个目标Activity:如果是显示的Activity,问题很好解决,因为Intent信息中已经带有目标Activity的相关信息;否则就调用resolveActivity()进行查找

判断目标Activity所属进程是不是重量级(heavy-weight)的。如果当前系统中已经存在的重量级进程(mService.mHeavy WeightProcess)不是即将要启动的这个,那么就要给Intent重新赋值。

调用startActivityLocked来进一步执行启动工作。

如果outResult不为空,还需要将函数的结果写入这个变量中。因为前面startActivity传入时此参数为null,所以这里可以直接略过

这个函数的名称表明它有可能会“wait”—-具体就表现在对outResult的处理上。

startActivityUncheckedLocked 执行流程

紧接着被调用的函数是startActivityLocked。需要特别注意的是,ActivityStack中存在两个同名的startActivityLocked函数,但参数不同。我们把参数较多的那个称为startActivityLocked(1),另一个则是startActivityLocked(2).Android源码中的很多函数后面都有Locked标志,用于提醒我们必须保证这些函数的线程安全—因为它们涉及不可重入资源的处理。图中所示的是startActivityLocked(1)函数的处理流程。主要工作是:

Strp(1)@startActivityLocked(1),确保调用者本身的进程是存在的,否则就直接返回START_PERMISSION_DENIED错误。

这种情况是有可能发生的,如果调用者被系统杀死,或者异常退出等。

Step2@startActivityLocked(1),处理FLAG_ACTIVITY_FORWARD_RESULT

这个标志具有跨越式传递的作用。比如Activity1正常启动了Activity2,而当Activity2启动Activity3时使用了这个标志,那么当前Activity3调用setResult时,result并不会像一般情况中那样传递给Activity2,而是传递给最初的Activity1。

为了达到这一目的,就需要将新启动的Activity3的caller改为Activity1.具体如下所示:

/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

final int startActivityLocked(IApplicationThread caller,

Intent intent, String resolvedType, ActivityInfo aInfo,

IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,

IBinder resultTo, String resultWho, int requestCode,

int callingPid, int callingUid, String callingPackage,

int realCallingPid, int realCallingUid, int startFlags, Bundle options,

boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer container,

TaskRecord inTask) {



final int launchFlags = intent.getFlags();

if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {


// Transfer the result target from the source activity to the new

// one being started, including any failures.

if (requestCode >= 0) {


ActivityOptions.abort(options);

return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;

}

resultRecord = sourceRecord.resultTo;

resultWho = sourceRecord.resultWho;

requestCode = sourceRecord.requestCode;

sourceRecord.resultTo = null;

if (resultRecord != null) {


resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);

}

}

}

因为在这个标志下,Activity2已经把接受result的目标对象设置为Activity1,因而它自身不能再通过startActivityForResult来启动Activity3了,否则就会报START_FORWARD_AND_REQUEST_CONFLICT的错误



版权声明:本文为qq_27647919原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。