因为关于AMS内部类的关系,例如stack、task,已有了相关的文档做介绍,本文不再赘述细说,基于相关文档以及代码的学习,本文主要集中篇幅集中于第三章,描述在Activity进程的启动流程中,启动应用进程以及应用进程中启动Activity的流程,也就是Activity启动的后半段流程。第二章关于Activity启动的前期准备主要涉及AMS的重点地方也会做详细描述。
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中。
启动命令:
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。
点击应用图标,launcher会调用Activity.java的startActivity
==》Activity.startActivityForResult
==》mInstrumentation.execStartActivity
==>ActivityManagerNative.getDefault().startActivity
==>AMS.startActivity
==》ActivityManagerService.startActivityAsUser
==>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();
......
//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);
// 下面这段代码的功能就是判断,当待启动的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 {
.............
}
-
- 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
//从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);
//指定反射的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);
}
}
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();
}
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();
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 {
.............
}
........
}
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);
}
}
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);
}
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接口
//通过反射创建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);
该方法主要调用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
==》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更新相关的状态,并进行一些结尾工作。