1. Activity的启动的基本介绍

因为关于AMS内部类的关系,例如stack、task,已有了相关的文档做介绍,本文不再赘述细说,基于相关文档以及代码的学习,本文主要集中篇幅集中于第三章,描述在Activity进程的启动流程中,启动应用进程以及应用进程中启动Activity的流程,也就是Activity启动的后半段流程。第二章关于Activity启动的前期准备主要涉及AMS的重点地方也会做详细描述。

  1. 启动模式

Android定义了4种Activity的启动模式,分别为Standard、SingleTop、SingleTask和SingleInstance

Standard模式

我们平时创建的Activity都是默认采用这种模式。

这种模式的特点是你创建启动一个Activity,就会创造一个实例,并加入到当前的任务栈,退出的时候就会销毁它。

在一个task可以存在多个关于该Activity的对象

SingleTop模式

这种模式启动新的Activity的时候,先判断是否有相同Activity的实例存在于栈顶,如果有直接复用,没有创建新的实例。

SingleTask模式

在该种模式下,只要Activity在一个栈中存在,那么多次启动此Activity都不会重新创建实例。

例如启动一个singleTask模式的Activity a,系统先查找是否已经存在a的task。

如果不存在task,就重新创建一个task,然后创建a的实例后,把a放到task中。

如果存在a所需的task,那么系统将判断该task是否有实例a。

如果有实例a,那么系统就将a调到task顶并调用其onNewIntent方法(会清空a之上的Activity)。

如果没有实例a,那么系统就创建实例a并task中。

SingleInstance模式

SingleTask模式加强模式,Activity只能单独地放在一个task中。

  1. 启动方法

    1. am命令启动

启动命令:

am start -W -n 包名(package)/包名.activity名称

例子:am start -W -n com.example.android365/com.example.android365.MainActivity

-W是一个可选项,表示等待目标activity启动后,am才返回结果;

-n ,表示后接COMPONENT。

am脚本的文件路径是frameworks/base/cms/am

调用am命令同样最终会调用到Am.java(frameworks/base/cmds/am/src/com/android/commands/am)的main函数。

此处只是做简单介绍am命令,最后它会调用AMS的startActivityAndWait函数启动Activity。

  1. launcher启动

点击应用图标,launcher会调用Activity.java的startActivity

==》Activity.startActivityForResult

==》mInstrumentation.execStartActivity

==>ActivityManagerNative.getDefault().startActivity

==>AMS.startActivity

==》ActivityManagerService.startActivityAsUser

==>ActivityStater.startActivityMayWait

  1. Activity启动的前期准备

    1. ActivityStater.startActivityMayWait

首先这个方法传入的参数非常多,这里对一些参数做简单介绍:

IApplicationThread caller = ApplicationThreadProxy,IApplicationThread是应用进程和AMS交互的通道,用于跟调用者进程和AMS进行通信的binder代理类.

String callingPackage = ContextImpl.getBasePackageName(),获取调用者Activity所在包名

Intent intent: 这是启动Activity时传递过来的参数;

String resolvedType = intent.resolveTypeIfNeeded //启动使用的resolvedType

IBinder resultTo = Activity.mToken, 其中Activity是指调用者所在Activity, mToken对象保存自己所处的ActivityRecord信息

String resultWho = Activity.mEmbeddedID, 其中Activity是指调用者所在Activity

int startFlags = 0;启动Activity的对应flag

ProfilerInfo profilerInfo = null;//性能统计有关

Bundle options = null;指定Activity要加入的task

int userId = AMS.handleIncomingUser, 当调用者userId跟当前处于同一个userId,则直接返回该userId;当不相等时则根据调用者userId来决定是否需要将callingUserId转换为mCurrentUserId.

下面我们将这个方法中主要的代码逻辑进行摘录分析:

//先从Intent中读取组件(Activity)名

boolean componentSpecified = intent.getComponent() != null;

//创建新的Intent对象

intent = new Intent(intent);

// mSupervisor的类型为ActivityStackSupervisor, 负责管理Activity和对应Task之间的关系.

这里调用resolveIntent,取出对应的ActivityInfo

ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);

得到option

ActivityOptions options = ActivityOptions.fromBundle(bOptions);

//要是从一个Activity启动其他Activity,该Activity必须依据resume

if (container != null && container.mParentActivity != null &&

container.mParentActivity.state != RESUMED) {

// Cannot start a child activity if the parent is not resumed.

return ActivityManager.START_CANCELED;

}

选择启动stack

final ActivityStack stack;

if (container == null || container.mStack.isOnHomeDisplay()) {

//am 启动和launch启动,stack为前台stack

stack = mSupervisor.mFocusedStack;

} else {

//如果从其他Activity启动,stack为父stack

stack = container.mStack;

}

//保存启动Activity的ActivityRecord

final ActivityRecord[] outRecord = new ActivityRecord[1];

//继续执行启动流程

int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,

aInfo, rInfo, voiceSession, voiceInteractor,

resultTo, resultWho, requestCode, callingPid,

callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,

options, ignoreTargetSecurity, componentSpecified, outRecord, container,

inTask);

//outResult不等于null,表示等待启动结果目标Activity要运行在一个新的应用进程中,因此需要等待应用进程正常启动并处理相关请求

if (outResult != null) {

......

do {

try {

//一直等待,直到outResult显示Activity对应的Task成为front task

mService.wait();

} catch (InterruptedException e) {

}

} while (outResult.result != START_TASK_TO_FRONT

&& !outResult.timeout && outResult.who == null);

......

if (res == START_TASK_TO_FRONT) {

//Activity对应的task拉到前台后,一直要等到该界面被加载

ActivityRecord r = stack.topRunningActivityLocked();

......

  1. ActivityStarter.startActivityLocked

//err 错误标志位,后面会有各种条件判断,如果有错误err会被置为对应代表值。

int err = ActivityManager.START_SUCCESS;

//保存Activity的进程信息

ProcessRecord callerApp = null;

//如果caller调用者补位空,可以通过找到processrecord找到对应的pid和uid,am启动,调用信息为null

if (caller != null) {

callerApp = mService.getRecordForAppLocked(caller);

if (callerApp != null) {

callingPid = callerApp.pid;

callingUid = callerApp.info.uid;

} else {

err = ActivityManager.START_PERMISSION_DENIED;

}

}

//父Activity

ActivityRecord sourceRecord = null;

//接受启动结果的Activity,在一般情况下,sourceRecord和resultRecord应指向同一个Activity

ActivityRecord resultRecord = null;

//从Intent获取flag

final int launchFlags = intent.getFlags();

//接受启动结果的stack

final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;

//一下两项分别是权限检查,根据IntentFirewall校验Intent是否满足要求,然后设置abort值,abort值为true

//进行通知(ActivityOptions.abort(options);)

boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,

requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,

resultRecord, resultStack, options);

boolean firewallCheck = !mService.mIntentFirewall.checkStartActivity(intent, callingUid,

callingPid, resolvedType, aInfo.applicationInfo);

abort |= firewallCheck;

//创建启动Activity的ActivityRecord

ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,

intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,

requestCode, componentSpecified, voiceSession != null, mSupervisor, container,

options, sourceRecord);

//启动处于pending状态的Activity

doPendingActivityLaunchesLocked(false);

try {

//Window 延迟绘制

mService.mWindowManager.deferSurfaceLayout();

//继续startActivity流程

err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,

true, options, inTask);

Slog.d(TAG,"startActivityUncheckedLocked result : " + err);

} finally {

mService.mWindowManager.continueSurfaceLayout();

}

//通知ActivityStarter, Activity对应的Task被移动到前台

postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);

  1. ActivityStater.startActivityUnchecked()

// 下面这段代码的功能就是判断,当待启动的Activity已经位于前台栈顶时,是否需要重新启动一个实例

final ActivityStack topStack = mSupervisor.mFocusedStack; // 顶栈

final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);//顶栈上正在运行的Activity

final boolean dontStart = top != null && mStartActivity.resultTo == null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId && top.app != null && top.app.thread != null //可以粗略的认为,上面的判断是为了确保待启动的Activity与当前的前台Activity一致 //下面的判断,决定了是否需要重新创建一个实例 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop || mLaunchSingleTask);

if (dontStart) { ................

if (mDoResume) { //resume top activity mSupervisor.resumeFocusedStackTopActivityLocked(); } ............... //调用onNewIntent函数 top.deliverNewIntentLocked( mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage); .............. return START_DELIVERED_TO_TOP;

}

//表示是否创建新的Task boolean newTask = false; //得到Affiliate Task,Activity的归属,也就是Activity应该在哪个Task中,Activity与Task的吸附关系。

这种吸附关系由启动模式和intent flag以及affinity属性共同决定的。

final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null) ? mSourceRecord.task : null;

if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask

&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {

newTask = true;

//如果mReuseTask不为null,那么将mStartActivity的Task设置为mReuseTask

//否则,重新创建一个Task给mStartActivity使用

setTaskFromReuseOrCreateNewTask(taskToAffiliate);

...................

} else if (mSourceRecord != null) {

..................

//待启动的Activity使用父Activity的Task

//其中在必要时将父Activity的Task移动到前台

//若待启动的Activity存在于Task中,但不在Task的顶部,还需要将Activity移动到顶部

final int result = setTaskFromSourceRecord();

.................

} else if (mInTask != null) {

................

//对应于以指定Task启动Activity的情况

final int result = setTaskFromInTask();

................

} else {

// This not being started from an existing activity, and not part of a new task...

// just put it in the top task, though these days this case should never happen.

//待启动的Activity使用前台Task或重新创建一个Task (什么条件决定是否创建一个新Task)

setTaskToCurrentTopOrCreateNewTask();

}

......................

//将待启动的Activity加入到mTargetStack的记录中,同时调用WindowManager准备App切换相关的工作(启动startingWindow)

mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);

if (mDoResume) {

if (!mLaunchTaskBehind) {

// TODO(b/26381750): Remove this code after verification that all the decision

// points above moved targetStack to the front which will also set the focus

// activity. 然后调用focus方法将activity移到front,调用到window,会set app focus到当前的app

//依次调用到WMS的setFocusedApp,并同步到input

//mInputMonitor.setFocusedAppLw(newFocus); ==>mService.mInputManager.setFocusedApplication(handle);

//updateFocusedWindowLocked 然后焦点应用置null

mService.setFocusedActivityLocked(mStartActivity, "startedActivity");

}

final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();

//待启动的Activity不可见的情况

if (!mTargetStack.isFocusable()

|| (topTaskActivity != null && topTaskActivity.mTaskOverlay

&& mStartActivity != topTaskActivity)) {

...........................,.......

} else {

//最终调用resumeFocusedStackTopActivityLocked

mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,

mOptions);

}

} else {

.............

}

  1. ActivityStack.resumeTopActivityInnerLocked

首先上文调用到ActivityStackSupervisor. resumeFocusedStackTopActivityLocked

这里面的处理逻辑比较简单

//待启动Activity对应的Task为前台Task时,调用该Task对应ActivityStack的resumeTopActivityUncheckedLocked函,否则只是调用当前前台栈的resumeTopActivityUncheckedLocked,而resumeTopActivityUncheckedLocked的主要实现函数就是resumeTopActivityInnerLocked。

下面我们主要分析ActivityStack. resumeTopActivityUncheckedLocked()

//从当前ActivityStack的记录中,找到第一个待启动的ActivityRecord

final ActivityRecord next = topRunningActivityLocked();

if (next == null) {

......

//当前的ActivityStack没有等待启动的Activity时,将启动Home

return isOnHomeDisplay() &&

mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, reason);

}

......

// 将待启动的Activity从下面几个队列中移除

mStackSupervisor.mStoppingActivities.remove(next);

mStackSupervisor.mGoingToSleepActivities.remove(next);

next.sleeping = false;

mStackSupervisor.mWaitingVisibleActivities.remove(next);

//如果系统当前正在中断一个Activity,需要先等待那个Activity paus完毕

if (!mStackSupervisor.allPausedActivitiesComplete()) {

......

return false;

}

mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);

// We need to start pausing the current activity so the top one can be resumed...

final boolean dontWaitForPause = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;

//mResumedActivity指向上一次启动的Activity,也就是当前界面显示的Activity

if (mResumedActivity != null) {

......

//如果当前界面显示了一个Activity,那么在启动新的Activity之前,必须中断当前的Activity,现将这个Activity paus

//之后系统会重新调用resumeTopActivityInnerLocked函数,找到下一个要启动的Activity。我会在这节末尾列出调用的相关逻辑情况

pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);

}

if (pausing) {

......

if (next.app != null && next.app.thread != null) {

//在中断当前界面的Activity时,调用待启动Activity所在进程的优先级,保证其不被kill

mService.updateLruProcessLocked(next.app, true, null);

}

......

return true;

} else if (mResumedActivity == next && next.state == ActivityState.RESUMED &&

mStackSupervisor.allResumedActivitiesComplete()){

//特殊情况,上面的代码中断后台栈,同时启动模式指定了FLAG_RESUME_WHILE_PAUSING

mWindowManager.executeAppTransition();

mNoAnimActivities.clear();

......

return true;

}

//若之前存在未正常结束的Activity,那么要优先结束掉这些Activity

if (mService.isSleepingLocked() && mLastNoHistoryActivity != null &&

!mLastNoHistoryActivity.finishing) {

.......

vityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED,

null, "resume-no-history", false);

mLastNoHistoryActivity = null;

.......

}

.......

try {

//通过PKMS,修改待启动Activity对应Package的stop状态

AppGlobals.getPackageManager().setPackageStoppedState(

next.packageName, false, next.userId); /* TODO: Verify if correct userid */

} catch (RemoteException e1) {

} catch (IllegalArgumentException e) {

.......

}

//处理动画相关的选项

Bundle resumeAnimOptions = null;

if (anim) {

ActivityOptions opts = next.getOptionsForTargetActivityLocked();

if (opts != null) {

resumeAnimOptions = opts.toBundle();

}

next.applyOptionsLocked();

} else {

next.clearOptionsLocked();

}

.......

if (next.app != null && next.app.thread != null) {

//如果待启动的Activity已有对应的进程存在,则只需要重启Activity

mStackSupervisor.scheduleResumeTopActivities();

.......

} else {

启动应用进程

mStackSupervisor.startSpecificActivityLocked(next, true, true);

.......

}

......

return true;

}

Activity pause的调用情况:

IApplicationThread.schedulePauseActivity()

==>ActivityThread.schedulePauseActivity()

==>ActivityThread.sendMessage()

==>ActivityThread.H.sendMessage()

==>ActivityThread.H.handleMessage()

==>ActivityThread.handlePauseActivity()

==>ActivityThread.performPauseActivity()

==>Instrumentation.callActivityOnPause()

==>Activity.performPause()

==>Activity.onPause()

==>ActivityManagerNative.getDefault().activityPaused()

==>ActivityManagerService.activityPaused()

==>ActivityStack.activityPausedLocked()

==>ActivityStack.completePauseLocked()

==> ActivityStack. resumeFocusedStackTopActivityLocked

  1. 启动应用进程和Activity

    1. 启动应用进程

      1. mStackSupervisor.startSpecificActivityLocked

//从AMS中查询是否已经存在满足要求的进程

ProcessRecord app = mService.getProcessRecordLocked(r.processName,

r.info.applicationInfo.uid, true);

//如果对应进程已经存在,并向AMS注册过

if (app != null && app.thread != null)

//通知进程启动目标Activity

realStartActivityLocked(r, app, andResume, checkConfig);

//如果进程不存在,利用AMS的startProcessLocked函数,创建一个新的进程

mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,

"activity", r.intent.getComponent(), false, false, true);

  1. ActivityManagerService.startProcessLocked

//指定反射的className

if (entryPoint == null) entryPoint = "android.app.ActivityThread";

//Process.java的start函数,将通过socket发送消息给zygote

//zygote将派生出一个子进程,子进程将通过反射调用ActivityThread的main函数

//注意此时传递给zygote的参数并没有包含任何与Activity相关的信息

Process.ProcessStartResult startResult = Process.start(entryPoint,

app.processName, uid, uid, gids, debugFlags, mountExternal,

app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,

app.info.dataDir, entryPointArgs);

synchronized (mPidsSelfLocked) {

//AMS以键值对的形式,保存pid和processRecord

this.mPidsSelfLocked.put(startResult.pid, app);

if (isActivityProcess) {

Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);

msg.obj = app;

//发送一个延迟消息

//在消息被处理前,若新创建的进程没有和AMS交互,那么该进程启动失败

//正常延迟时间为10s

//若通过wrapper(例如valgrind)加载,应用程序将在wrapper的运行环境中工作,耗时较长,延迟时间在N中定义为1200s

mHandler.sendMessageDelayed(msg, startResult.usingWrapper

? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);

}

}

  1. Process.start()

public static final ProcessStartResult(){

startViaZygote(processClass, niceName, uid, gid, gids,

debugFlags, mountExternal, targetSdkVersion, seInfo,

abi, instructionSet, appDataDir, zygoteArgs);

}

private static ProcessStartResult startViaZygote{

在string 数组argsForZygote中加入相关的启动参数。

zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);

}

private static ProcessStartResult zygoteSendArgsAndGetResult(

//通过socket发送消息给zygote,zygote将派生出一个子进程,子进程将通过反射调用ActivityThread的main函数

final BufferedWriter writer = zygoteState.writer;

final DataInputStream inputStream = zygoteState.inputStream;

writer.write(Integer.toString(args.size()));

writer.newLine();

for (int i = 0; i < sz; i++) {

String arg = args.get(i);

writer.write(arg);

writer.newLine();

}

writer.flush();

ProcessStartResult result = new ProcessStartResult();

result.pid = inputStream.readInt();

result.usingWrapper = inputStream.readBoolean();

}

  1. 应用进程初始化

    1. ActivityThread.mian()

ActivityThread的main函数最主要工作是:

1、创建出一个Looper,并将主线程加入到消息循环中。

2、创建出ActivityThread,并调用其attach函数。

通过zygote启动进程时,传入的className为android.app.ActivityThread。

因此,当zygote通过反射调用进程的main函数时,ActivityThread的main函数将被启动:

/准备主线程的Looper

Looper.prepareMainLooper();

//创建当前进程的ActivityThread

ActivityThread thread = new ActivityThread();

//调用attach函数

thread.attach(false);

if (sMainThreadHandler == null) {

//保存进程对应的主线程Handler

sMainThreadHandler = thread.getHandler();

}

.........

//进入主线程的消息循环

Looper.loop();

  1. ActivityThread.attach(false)

private void attach(boolean system) {

sCurrentActivityThread = this;

mSystemThread = system;

if (!system) {

ViewRootImpl.addFirstDrawHandler(new Runnable() {

@Override

public void run() {

//JIT是一种提高程序运行效率的方法。通常,程序有两种运行方式:静态编译与动态解释。静态编译的程序在执行前全部被翻译为机器码,而解释执行的则是一句一句边运行边翻译。

//这里开启JIT,应该是为了提高android绘制的速度

ensureJitEnabled();

}

});

//设置在DDMS中看到的进程名为"<pre-initialized>"

android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", UserHandle.myUserId());

//设置RuntimeInit的mApplicationObject参数

RuntimeInit.setApplicationObject(mAppThread.asBinder());

final IActivityManager mgr = ActivityManagerNative.getDefault();

try {

//与AMS通信,调用其attachApplication接口

mgr.attachApplication(mAppThread);

} catch (RemoteException ex) {

throw ex.rethrowFromSystemServer();

}

// 监控GC操作; 当进程内的一些Activity发生变化,同时内存占用量较大时

// 通知AMS释放一些Activity

BinderInternal.addGcWatcher(new Runnable() {

public void run() {

if (!mSomeActivitiesChanged) {

return;

}

Runtime runtime = Runtime.getRuntime();

long dalvikMax = runtime.maxMemory();

long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();

//判断内存占用量是否过大

if (dalvikUsed > ((3*dalvikMax)/4)) {

...........

mSomeActivitiesChanged = false;

try {

//通知AMS释放一些Activity,以缓解内存紧张

mgr.releaseSomeActivities(mAppThread);

} catch (RemoteException e) {

throw e.rethrowFromSystemServer();

}

}

}

});

} else {

.............

}

........

}

  1. ActivityManagerService.attachApplication()

public final void attachApplication(IApplicationThread thread) {

synchronized (this) {

......

attachApplicationLocked(thread, callingPid);

}

}

ActivityManagerService.attachApplicationLocked()

ProcessRecord app;

if (pid != MY_PID && pid >= 0) {

synchronized (mPidsSelfLocked) {

//AMS 启动的进程会保存processRecord,这里根据pid获取app

app = mPidsSelfLocked.get(pid);

}

} else {

if (app == null) {

如果app为null,说明这个进程不是ams启动的,需要kill掉该进程

EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);

if (pid > 0 && pid != MY_PID) {

pid大于0且不是系统进程,则直接kill掉

Process.killProcessQuiet(pid);

} else {

try {

pid<0说明fork失败,做一些上层清理即可,进程退出

thread.scheduleExit();

} catch (Exception e) {

}

}

return false;

}

//判断pid对应processRecord的IApplicationThread是否为null,AMS创建ProcessRecord后,在attach之前,正常情况下IApplicationThread应该为null

// 特殊情况下:如果旧应用进程被杀死,底层对应的pid被释放,在通知到达AMS之前(AMS在下面的代码里注册了进程存活接收对象),用户又启动了一个新的进程,新进程刚好分配到旧进程的pid时此处得到的processRecord可能就是旧进程的,于是app.thread可能不为null,因此需要作判断和处理

if (app.thread != null) {

handleAppDiedLocked(app, true, true);

}

final String processName = app.processName;

try {

//APP存活检测类(AppDeathRecipient),new一个该对象,

AppDeathRecipient adr = new AppDeathRecipient(

app, pid, thread);

//注册该对象到应用进程的ApplicationThread中,当应用进程退出时,该对象的binderDied将被调用,这样AMS就能做相应的处理。

thread.asBinder().linkToDeath(adr, 0);

app.deathRecipient = adr;

} catch (RemoteException e) {

app.resetPackageList(mProcessStats);

startProcessLocked(app, "link fail", processName);

return false;

}

设置app的一些变量,例如调度优先级和oom_adj相关的成员

app.makeActive(thread, mProcessStats);

app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;

app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;

app.forcingToForeground = null;

updateProcessForegroundLocked(app, false, false);

app.hasShownUi = false;

app.debugging = false;

app.cached = false;

app.killedByAm = false;

//对应我们eventLog am_proc_bound

EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName);

//AMS创建一个应用进程后,会设置一个超时时间。 如果超过这个时间,应用进程还没有和AMS交互,AMS就认为该进程创建失败,调用到此处说明启动成功,移除该消息

mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);

mStackSupervisor.attachApplicationLocked(app)

这个方法主要是寻找focus stack的top Activity,然后去启动它。在应用进程没有创建的时候,没有办法将要启动的Activity传给应用进程。

所以我们前期会通过一系列的处理将Activity的task移到focus stack的顶部,Activity移到task的顶部。这样应用进程启动后,和AMS进行交换

就可以知道它要启动的Activity的具体情况

==>realStartActivityLocked(hr, app, true, true)//具体的执行启动工作

{

if (andResume) {

//为显示做准备,先冻结屏幕,然后做动画切换和图像显示准备

r.startFreezingScreenLocked(app, 0);

mWindowManager.setAppVisibility(r.appToken, true);

..........

}

......

if (checkConfig) {

//更新绘制相关的配置

Configuration config = mWindowManager.updateOrientationFromAppTokens(

mService.mConfiguration,

r.mayFreezeScreenLocked(app) ? r.appToken : null);

mService.updateConfigurationLocked(config, r, false);

}

//如果这个新启动的Activity没有保存在activities数组,这里保存一下

int idx = app.activities.indexOf(r);

if (idx < 0) {

app.activities.add(r);

}

......

//更新优先级

mService.updateOomAdjLocked();

......

==>//通知应用进程启动Activity

app.thread.scheduleLaunchActivity(............);

......

if (andResume) {

// Activity进入resumeState后,更新相应的状态

stack.minimalResumeActivityLocked(r);

}

}

  1. 启动Activity

    1. scheduleLaunchActivity

public final void scheduleLaunchActivity(......) {

//更新进程状态

updateProcessState(procState, false);

创建ActivityClientRecord然后把AMS传进的信息进行保存

ActivityClientRecord r = new ActivityClientRecord();

r.token = token;

r.ident = ident;

r.intent = intent;

r.referrer = referrer;

r.voiceInteractor = voiceInteractor;

r.activityInfo = info;

r.compatInfo = compatInfo;

r.state = state;

r.persistentState = persistentState;

r.pendingResults = pendingResults;

r.pendingIntents = pendingNewIntents;

r.startsNotResumed = notResumed;

r.isForward = isForward;

r.profilerInfo = profilerInfo;

r.overrideConfig = overrideConfig;

//更新配置

updatePendingConfiguration(curConfig);

//发送消息交给ActivityThread处理LAUNCH_ACTIVITY,最后是handleLaunchActivity处理的

sendMessage(H.LAUNCH_ACTIVITY, r);

}

  1. handleLaunchActivity

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {

//如果Activity从前台移动到后台,则有可能准备进行Gc操作,现在Activity重新启动,就需要取消Gc操作了,对于新建Activity而言,此处无实际动作。

unscheduleGcIdler();

mSomeActivitiesChanged = true;

//Activity进行性能统计

if (r.profilerInfo != null) {

mProfiler.setProfiler(r.profilerInfo);

mProfiler.startProfiling();

}

// 保证Activity以最新的配置启动,即保证Activity符合最新语言、主题、分辨率等的要求

handleConfigurationChanged(null, null);

// 初始化WindowManagerGlobal

WindowManagerGlobal.initialize();

//执行performLaunchActivity创建Activity,这里面会执行Activity的onCreate,onstart

Activity a = performLaunchActivity(r, customIntent);

if (a != null) {

r.createdConfig = new Configuration(mConfiguration);

reportSizeConfigurations(r);

Bundle oldState = r.state;

//调用执行Activity onResume

handleResumeActivity(r.token, false, r.isForward,

!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);

if (!r.activity.mFinished && r.startsNotResumed) {

// 处理可见但非前台的Activity,这种Activity在启动后将进入到pause状态

performPauseActivityIfNeeded(r, reason);

......

}

} else {

//如果启动错误,则通知AMS stop

try {

ActivityManagerNative.getDefault()

.finishActivity(r.token, Activity.RESULT_CANCELED, null,

Activity.DONT_FINISH_TASK_WITH_ACTIVITY);

} catch (RemoteException ex) {

throw ex.rethrowFromSystemServer();

}

}

}

handleLaunchActivity的工作主要包括:

1、调用performLaunchActivity创建出Activity;

2、调用handleResumeActivity,完成调用目标Activity的onResume接口等工作;

3、对于可见但非前台的Activity,还需要调用performPauseActivityIfNeeded函数,调用Activity的onPause接口

  1. performLaunchActivity():

//通过反射创建Activity:

java.lang.ClassLoader cl = r.packageInfo.getClassLoader();

activity = mInstrumentation.newActivity(

cl, component.getClassName(), r.intent);

Window window = null;

window = r.mPendingRemoveWindow;

//设置Activity的主要变量,其中实例化phonewindow和window的一些设置操作 ,创建mMainThread、mUiThread等,mMainThread的类型为ActivityThread;mUiThread的类型为Thread,二者实际的工作线程是同一个

activity.attach(appContext, this, getInstrumentation(), r.token,

r.ident, app, r.intent, r.activityInfo, title, r.parent,

r.embeddedID, r.lastNonConfigurationInstances, config,

r.referrer, r.voiceInteractor, window);

//设置主题

int theme = r.activityInfo.getThemeResource();

if (theme != 0) {

activity.setTheme(theme);

}

//调用onCreate

if (r.isPersistable()) {

mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);

} else {

mInstrumentation.callActivityOnCreate(activity, r.state);

}

//调用onstart

if (!r.activity.mFinished) {

activity.performStart();

r.stopped = false;

}

//调用Activity onRestoreInstanceState函数

if (r.isPersistable()) {

if (r.state != null || r.persistentState != null) {

mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,

r.persistentState);

}

} else if (r.state != null) {

mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);

}

//调用Activity的onPostCreate接口

if (r.isPersistable()) {

mInstrumentation.callActivityOnPostCreate(activity, r.state,

r.persistentState);

} else {

mInstrumentation.callActivityOnPostCreate(activity, r.state);

}

//保存Activity

mActivities.put(r.token, r);

  1. handleResumeActivity()

该方法主要调用Activity的onresume

//调用Activity的resume方法

r = performResumeActivity(token, clearHide, reason);

然后做些绘制的操作,具体参考Activity启动涉及WMS的分析

if (!r.onlyLocalRequest) {

//r为刚刚完成onResume的新Activity,mNewActivities保存已经之前onResume的Activity

r.nextIdle = mNewActivities;

//然后将新建的Activity赋值给mNewActivities

mNewActivities = r;

...........

//向ActivityThread的MessageQueue中增加一个IdleHandler

Looper.myQueue().addIdleHandler(new Idler());

}

最后通知AMS该Activity执行完了onresume

ActivityManagerNative.getDefault().activityResumed(token);

向ActivityThread的MessageQueue中增加一个IdleHandler后,会执行下面的代码

private class Idler implements MessageQueue.IdleHandler {

@Override

public final boolean queueIdle() {}

在queueIdle函数里面会执行到am.activityIdle(a.token, a.createdConfig, stopProfiling);调用AMS的activityIdle函数

我们此处关注下Activity启动的最后一步,AMS.activityIdle

  1. AMS.activityIdle

==》ActivityRecord r =   mStackSupervisor.activityIdleInternalLocked(token, false, config);

这个方法主要处理一些扫尾工作,之前启动Activity,我们将之前的Activity进行pause处理,此处则让他们执行onstop,ondestory操作。

//finish 等待结束的Activity

if ((NF = mFinishingActivities.size()) > 0) {

finishes = new ArrayList<>(mFinishingActivities);

mFinishingActivities.clear();

}

//stop 那些因为新启动Activity而处于等待状态的Activity

for (int i = 0; i < NS; i++) {

r = stops.get(i);

final ActivityStack stack = r.task.stack;

if (stack != null) {

if (r.finishing) {

//如果被暂停的Activity已经处于了finishing状态,他们将会执行Destroy操作

stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);

} else {

//如果没有处于finishing状态,执行onstop

stack.stopActivityLocked(r);

}

}

}

然后同样finish这些Activity

for (int i = 0; i < NF; i++) {

r = finishes.get(i);

final ActivityStack stack = r.task.stack;

if (stack != null) {

activityRemoved |= stack.destroyActivityLocked(r, true, "finish-idle");

}

}

//如果等待结束的Activity被处理,保证前台栈顶Activity处于Resumed状态

if (activityRemoved) {

resumeFocusedStackTopActivityLocked();

}

本章总结如下:

1、启动进程,创建自己的ActivityThread和ApplicationThread。

2、进程与AMS通信,其实就是完成一个注册过程(将ApplicationThread作为Binder通信接口交给AMS保存)

3、AMS通知进程创建自己的Android运行环境,加入到Android体系。

4、AMS通知进程可以启动进程中的Activity。

5、Activity启动完成后,通知AMS更新相关的状态,并进行一些结尾工作。

Activity启动流程-AMS相关推荐

  1. 【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | AMS 启动前使用动态代理替换掉插件 Activity 类 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  2. 【Android 插件化】Hook 插件化框架总结 ( 插件包管理 | Hook Activity 启动流程 | Hook 插件包资源加载 ) ★★★

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  3. 【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | 主线程创建 Activity 实例之前使用插件 Activity 类替换占位的组件 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  4. 【Android 插件化】Hook 插件化框架 ( 从 Hook 应用角度分析 Activity 启动流程 二 | AMS 进程相关源码 | 主进程相关源码 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  5. android activity启动流程_1307页!一线大厂Android面试全套真题解析!

    /   前言   / 金九银十到了,很多读者都反映有面试的需求,所以我特地给大家准备了一点资料! 下面的题目都是大家在面试一线互联网大厂时经常遇到的面试真题和答案解析,如果大家还有其他好的题目或者好的 ...

  6. framework之Activity启动流程(基于Android11源码)

    一步步看,你就会对activity的启动流程有深刻的认知. 引言 Android11上,Activity的启动流程与Android10的实现(可以参考Activity的启动过程详解(基于10.0源码) ...

  7. 【Android 启动过程】Android 应用启动流程 | Activity 启动流程

    文章目录 一.Android 系统启动流程 二.Activity 启动流程 一.Android 系统启动流程 打开 Android 手机电源键后 , 先运行 BootLoader , 然后使用 Boo ...

  8. 【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | 反射获取 IActivityManager 对象 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  9. 【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | Hook 点分析 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

最新文章

  1. Oracle Internal Event:10235 Heap Checking诊断事件
  2. 浅析Mysql Join语法以及性能优化
  3. hibernate_和ORM的关系
  4. centos7.2 安装mysql5.6_Centos7安装mysql5.6
  5. Kubernetes kubectl proxy命令的妙用
  6. 如何使用 dotTrace 来诊断 netcore 应用的性能问题
  7. 【Java线程池】Java线程池汇总,看这一篇文章就够了
  8. python找图是什么模块-python中模块查找的原理与方法详解
  9. 互联网赚钱,必须聚焦这三件事
  10. Linux目录结构、bash的基础命令学习
  11. fx系列微型可编程控制器 通信_西门子系列资料(64本电子书+PLC视频+软件),整理了很久...
  12. 关于Cookie在顶级域名、二级域名和三级域名之间共享的情况
  13. linux启用日志记录功能,linux开启日志服务器功能
  14. 从零搭建微信机器人(三):定时触发任务
  15. SQLite手机数据库
  16. 洛谷 P4100 [HEOI2013]钙铁锌硒维生素 解题报告
  17. 关于个人对培训的看法
  18. 设计师的可访问性调研指南
  19. 基于python/scipy学习概率统计(0):基础概念
  20. 安科瑞安全用电管理云平台

热门文章

  1. environments
  2. php 危险函数_PHP 危险函数有哪些?
  3. 安科瑞医用隔离电源系统在浙江某医院项目中的应用
  4. 预览窗格无法预览word_使用Word 2010中的导航窗格轻松重组文档
  5. python csv模块 reader_Python之csv模块
  6. LTE网络弱覆盖影响下载速率案例-(陆东明)
  7. 阿里云OSS图片上传
  8. 用FTP修改网站服务器内容
  9. 201912-2 回收站选址(stl方法,很巧妙)
  10. 基于麻雀算法优化LSTM回归预测(matlab)