0. 寫(xiě)在前面的話
上一篇講了各種Service是在何時(shí)啟動(dòng)的什往,最后提到了關(guān)于
HomeActivity
的啟動(dòng)冒萄。HomeActivity
作為Android系統(tǒng)啟動(dòng)后第一個(gè)加載的Activity堂鲜,今天就來(lái)分析下其啟動(dòng)流程累奈。
其實(shí)還有個(gè)時(shí)序圖的趁餐,但是太大了俐芯,截圖也不全,等下次直接上傳喘蟆,方便自己查看缓升。
暫時(shí)的規(guī)劃先是Activity的啟動(dòng)流程,通過(guò)這個(gè)又會(huì)涉及到進(jìn)程間通信——Binder機(jī)制蕴轨,接著Activity啟動(dòng)后港谊,布局是如何繪制到屏幕上,View的事件是如何分發(fā)的橙弱?通過(guò)這條線來(lái)慢慢整理這兩年多我對(duì)Android的理解歧寺,加深自己的印象燥狰。
1. ActivityManagerService.systemReady(new Runnable())
做了什么?
我們先來(lái)看下這個(gè)方法的代碼:
public void systemReady(final Runnable goingCallback) {
synchronized(this) {
//mSystemReady默認(rèn)為false斜筐,所以第一次調(diào)用這個(gè)方法時(shí)不會(huì)執(zhí)行g(shù)oingCallback.run()
if (mSystemReady) {
if (goingCallback != null) {
goingCallback.run();
}
return;
}
......
}
//要?dú)⒌舻倪M(jìn)程(啟動(dòng)時(shí)不允許啟動(dòng)的進(jìn)程)
ArrayList<ProcessRecord> procsToKill = null;
synchronized(mPidsSelfLocked) {
for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
ProcessRecord proc = mPidsSelfLocked.valueAt(i);
if (!isAllowedWhileBooting(proc.info)){
if (procsToKill == null) {
procsToKill = new ArrayList<ProcessRecord>();
}
procsToKill.add(proc);
}
}
}
//殺掉這些進(jìn)程
synchronized(this) {
if (procsToKill != null) {
for (int i=procsToKill.size()-1; i>=0; i--) {
ProcessRecord proc = procsToKill.get(i);
Slog.i(TAG, "Removing system update proc: " + proc);
removeProcessLocked(proc, true, false, "system update done");
}
}
// Now that we have cleaned up any update processes, we
// are ready to start launching real processes and know that
// we won't trample on them any more.
mProcessesReady = true;
}
......
//這里會(huì)調(diào)用Runnable的run()方法
if (goingCallback != null) goingCallback.run();
......
synchronized (this) {
//啟動(dòng)常駐的應(yīng)用
startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
mBooting = true;
if (UserManager.isSplitSystemUser()) {
ComponentName cName = new ComponentName(mContext, SystemUserHomeActivity.class);
try {
//解禁SystemUserHomeActivity
AppGlobals.getPackageManager().setComponentEnabledSetting(cName,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0,
UserHandle.USER_SYSTEM);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
}
//開(kāi)始啟動(dòng)HomeActivity
startHomeActivityLocked(currentUserId, "systemReady");
......
}
}
這個(gè)方法內(nèi)容挺多的龙致,首次進(jìn)入是設(shè)置的Runnable不會(huì)執(zhí)行,后面通過(guò)查找啟動(dòng)時(shí)系統(tǒng)不允許啟動(dòng)的進(jìn)程顷链,并將其kill掉目代。接下來(lái)啟動(dòng)了系統(tǒng)常駐應(yīng)用
startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE)
,通過(guò)使用AppGlobals.getPackageManager().setComponentEnabledSetting
方法解禁SystemUserHomeActivity
蕴潦,其flag為PackageManager.COMPONENT_ENABLED_STATE_ENABLED
像啼,最后通過(guò)startHomeActivityLocked(currentUserId, "systemReady")
來(lái)啟動(dòng)HomeActivity
。
2. startHomeActivityLocked
開(kāi)始啟動(dòng)HomeActivity
這里的代碼不多潭苞,也很好理解:
boolean startHomeActivityLocked(int userId, String reason) {
//測(cè)試模式下不用管
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
&& mTopAction == null) {
// We are running in factory test mode, but unable to find
// the factory test app, so just sit around displaying the
// error message and don't try to start anything.
return false;
}
//得到要啟動(dòng)Activity的Intent
Intent intent = getHomeIntent();
//將Intent解析成ActivityInfo
ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
// Don't do this if the home app is currently being
// instrumented.
aInfo = new ActivityInfo(aInfo);
aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
ProcessRecord app = getProcessRecordLocked(aInfo.processName,
aInfo.applicationInfo.uid, true);
if (app == null || app.instrumentationClass == null) {
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
//啟動(dòng)Activity
mActivityStarter.startHomeActivityLocked(intent, aInfo, reason);
}
} else {
Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
}
return true;
}
Intent getHomeIntent() {
Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent);
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
//不是測(cè)試情況下則設(shè)置Category為Intent.CATEGORY_HOME
if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
intent.addCategory(Intent.CATEGORY_HOME);
}
return intent;
}
首先是判斷當(dāng)前系統(tǒng)是否處于測(cè)試環(huán)境忽冻,接著去獲取(創(chuàng)建)
HomeIntent
此疹,并將其解析成ActivityInfo
僧诚,接下來(lái)調(diào)用ActivityStarter
中的startHomeActivityLocked(intent, aInfo, reason)
方法去啟動(dòng)HomeActivity
。
3. startHomeActivityLocked
和startActivityLocked
我們進(jìn)入
ActivityStarter
中可以看到startHomeActivityLocked
調(diào)用了startActivityLocked
方法蝗碎,其中傳入的參數(shù)只有Intent
和ActivityInfo
不為空湖笨,其他的都為null
或者0
或者false
,由于大部分參數(shù)都為null
蹦骑,startActivityLocked
中真正執(zhí)行的代碼并不是很多慈省。
void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
//調(diào)用了參數(shù)居多的方法
startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,
null /*container*/, null /*inTask*/);
if (mSupervisor.inResumeTopActivity) {
// If we are in resume section already, home activity will be initialized, but not
// resumed (to avoid recursive resume) and will stay that way until something pokes it
// again. We need to schedule another resume.
mSupervisor.scheduleResumeTopActivities();
}
}
//這個(gè)參數(shù)是真TM的多啊
final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
TaskRecord inTask) {
//啟動(dòng)結(jié)果代碼
int err = ActivityManager.START_SUCCESS;
ProcessRecord callerApp = null;
//caller == null
if (caller != null) {
......
}
final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
if (err == ActivityManager.START_SUCCESS) {
..Log..
}
ActivityRecord sourceRecord = null;
ActivityRecord resultRecord = null;
//resultTo == null
if (resultTo != null) {
......
}
final int launchFlags = intent.getFlags();
//Activity啟動(dòng)是設(shè)置的flags
if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
......
}
......
//檢查啟動(dòng)Activity的權(quán)限
boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
resultRecord, resultStack, options);
abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
callingPid, resolvedType, aInfo.applicationInfo);
if (mService.mController != null) {
try {
// The Intent we give to the watcher has the extra data
// stripped off, since it can contain private information.
Intent watchIntent = intent.cloneFilter();
abort |= !mService.mController.activityStarting(watchIntent,
aInfo.applicationInfo.packageName);
} catch (RemoteException e) {
mService.mController = null;
}
}
......
// If we have an ephemeral app, abort the process of launching the resolved intent.
// Instead, launch the ephemeral installer. Once the installer is finished, it
// starts either the intent we resolved here [on install error] or the ephemeral
// app [on install success].
if (rInfo != null && rInfo.ephemeralResolveInfo != null) {
intent = buildEphemeralInstallerIntent(intent, ephemeralIntent,
rInfo.ephemeralResolveInfo.getPackageName(), callingPackage, resolvedType,
userId);
resolvedType = null;
callingUid = realCallingUid;
callingPid = realCallingPid;
aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
}
//創(chuàng)建了ActivityRecord,用于存儲(chǔ)保存Activity
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
options, sourceRecord);
......
try {
mService.mWindowManager.deferSurfaceLayout();
//啟動(dòng)Activity
err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
true, options, inTask);
} finally {
mService.mWindowManager.continueSurfaceLayout();
}
postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
return err;
}
雖然上面的方法參數(shù)很多眠菇,但是由于大部分都為
null
或者0
边败,所以真正執(zhí)行的部分很少。先進(jìn)行對(duì)flag
的檢查捎废,我們的intent
只設(shè)置了Intent.FLAG_DEBUG_TRIAGED_MISSING
笑窜,所以對(duì)flag
判斷的部分執(zhí)行也不執(zhí)行。權(quán)限檢查!mSupervisor.checkStartAnyActivityPermission
登疗,如果沒(méi)有權(quán)限排截,則最終不會(huì)啟動(dòng)。我們要啟動(dòng)的是HomeActivity
辐益,所有需要的權(quán)限都有断傲,因此創(chuàng)建一個(gè)ActivityRecord
,用于存放Activity
的信息智政,最后調(diào)用startActivityUnchecked
執(zhí)行啟動(dòng)過(guò)程艳悔。
4. startActivityUnchecked
過(guò)程
startActivityUnchecked
這個(gè)方法做了很多事情,包括了對(duì)當(dāng)前的Activity
的launchMode
的設(shè)置女仰、處理猜年,我們要啟動(dòng)的是HomeActivity
,所以呢疾忍,我們并不care這些東西乔外。
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
//初始化,這里需要注意的一點(diǎn)是doResume這個(gè)參數(shù)我們傳過(guò)來(lái)的是true一罩,下面會(huì)用到
setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
voiceInteractor);
//設(shè)置launchMode flag
computeLaunchingTaskFlags();
computeSourceStack();
mIntent.setFlags(mLaunchFlags);
mReusedActivity = getReusableIntentActivity();
final int preferredLaunchStackId =
(mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
if (mReusedActivity != null) {
// When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
// still needs to be a lock task mode violation since the task gets cleared out and
// the device would otherwise leave the locked task.
if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
(mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
mSupervisor.showLockTaskToast();
Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
if (mStartActivity.task == null) {
mStartActivity.task = mReusedActivity.task;
}
if (mReusedActivity.task.intent == null) {
// This task was started because of movement of the activity based on affinity...
// Now that we are actually launching it, we can assign the base intent.
mReusedActivity.task.setIntent(mStartActivity);
}
// This code path leads to delivering a new intent, we want to make sure we schedule it
// as the first operation, in case the activity will be resumed as a result of later
// operations.
//這里是處理launchMode為FLAG_ACTIVITY_CLEAR_TOP的情況
if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| mLaunchSingleInstance || mLaunchSingleTask) {
// In this situation we want to remove all activities from the task up to the one
// being started. In most cases this means we are resetting the task to its initial
// state.
final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
mStartActivity, mLaunchFlags);
if (top != null) {
if (top.frontOfTask) {
// Activity aliases may mean we use different intents for the top activity,
// so make sure the task now has the identity of the new intent.
top.task.setIntent(mStartActivity);
}
ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
//去掉用Activity的onNewIntent方法
top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
mStartActivity.launchedFromPackage);
}
}
sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
......
}
setTaskFromIntentActivity(mReusedActivity);
if (!mAddingToTask && mReuseTask == null) {
......
}
}
if (mStartActivity.packageName == null) {
if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) {
mStartActivity.resultTo.task.stack.sendActivityResultLocked(
-1, mStartActivity.resultTo, mStartActivity.resultWho,
mStartActivity.requestCode, RESULT_CANCELED, null);
}
ActivityOptions.abort(mOptions);
//啟動(dòng)失敗
return START_CLASS_NOT_FOUND;
}
// If the activity being launched is the same as the one currently at the top, then
// we need to check if it should only be launched once.
//如果當(dāng)前的Activity的launchModeFLAG_ACTIVITY_SINGLE_TOP杨幼,并且是處于任務(wù)棧的棧頂,
//則不用啟動(dòng)聂渊,并調(diào)用Activity的onNewIntent方法
final ActivityStack topStack = mSupervisor.mFocusedStack;
final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
final boolean dontStart = top != null && mStartActivity.resultTo == null
&& top.realActivity.equals(mStartActivity.realActivity)
&& top.userId == mStartActivity.userId
&& top.app != null && top.app.thread != null
&& ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
|| mLaunchSingleTop || mLaunchSingleTask);
if (dontStart) {
ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
// For paranoia, make sure we have correctly resumed the top activity.
topStack.mLastPausedActivity = null;
if (mDoResume) {
mSupervisor.resumeFocusedStackTopActivityLocked();
}
ActivityOptions.abort(mOptions);
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
// We don't need to start a new activity, and the client said not to do
// anything if that is the case, so this is it!
return START_RETURN_INTENT_TO_CALLER;
}
//調(diào)用Activity的onNewIntent方法
top.deliverNewIntentLocked(
mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
// Don't use mStartActivity.task to show the toast. We're not starting a new activity
// but reusing 'top'. Fields in mStartActivity may not be fully initialized.
mSupervisor.handleNonResizableTaskIfNeeded(
top.task, preferredLaunchStackId, topStack.mStackId);
return START_DELIVERED_TO_TOP;
}
boolean newTask = false;
final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
? mSourceRecord.task : null;
// Should this be considered a new task?
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
setTaskFromReuseOrCreateNewTask(taskToAffiliate);
if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
if (!mMovedOtherTask) {
// If stack id is specified in activity options, usually it means that activity is
// launched not from currently focused stack (e.g. from SysUI or from shell) - in
// that case we check the target stack.
updateTaskReturnToType(mStartActivity.task, mLaunchFlags,
preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
}
} else if (mSourceRecord != null) {
if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
final int result = setTaskFromSourceRecord();
if (result != START_SUCCESS) {
return result;
}
} else if (mInTask != null) {
// The caller is asking that the new activity be started in an explicit
// task it has provided to us.
if (mSupervisor.isLockTaskModeViolation(mInTask)) {
Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
final int result = setTaskFromInTask();
if (result != START_SUCCESS) {
return result;
}
} 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.
setTaskToCurrentTopOrCreateNewTask();
}
mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
}
if (newTask) {
EventLog.writeEvent(
EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
}
ActivityStack.logStartActivity(
EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
mTargetStack.mLastPausedActivity = null;
sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
//mDoResume設(shè)置為true
if (mDoResume) {
......
final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {
// If the activity is not focusable, we can't resume it, but still would like to
// make sure it becomes visible as it starts (this will also trigger entry
// animation). An example of this are PIP activities.
// Also, we don't want to resume activities in a task that currently has an overlay
// as the starting activity just needs to be in the visible paused state until the
// over is removed.
mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
// Go ahead and tell window manager to execute app transition for this activity
// since the app transition will not be triggered through the resume channel.
mWindowManager.executeAppTransition();
} else {
//執(zhí)行此方法
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
} else {
mTargetStack.addRecentActivityLocked(mStartActivity);
}
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
mSupervisor.handleNonResizableTaskIfNeeded(
mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
return START_SUCCESS;
}
在這個(gè)方法中差购,我們看到了對(duì)
Activity
的不同的launchMode
的處理,我們要啟動(dòng)的HomeActivity只會(huì)是啟動(dòng)一個(gè)新的Task汉嗽,所以大部分操作還是啟動(dòng)其他Activity時(shí)進(jìn)行的欲逃。代碼里面也講到了,我們?cè)诔跏蓟?code>mDoResume傳入了true
饼暑,代碼會(huì)執(zhí)行mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,mOptions);
稳析。
5. 方法的各種調(diào)用直至resumeTopActivityInnerLocked
上面講到我們會(huì)執(zhí)行
ActivityStackSupervisor
的resumeFocusedStackTopActivityLocked
方法,跟進(jìn)方法后會(huì)發(fā)現(xiàn)其又會(huì)調(diào)用ActivityStack
的resumeTopActivityUncheckedLocked
方法弓叛,這個(gè)方法會(huì)調(diào)用自身的resumeTopActivityInnerLocked
方法彰居,在resumeTopActivityInnerLocked
中,會(huì)根據(jù)當(dāng)前的Activity Task中是否有需要pause的Activity撰筷,如果有先去執(zhí)行pause陈惰,沒(méi)有的話則去啟動(dòng)Activity。
大致代碼
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
// Find the first activity that is not finishing.
//這里看了很久毕籽,后來(lái)從前面的代碼慢慢理清的話抬闯,這個(gè)next就是指的就是當(dāng)前要啟動(dòng)的Activity的Record
//這里是自己的理解,希望不會(huì)有什么差錯(cuò)
final ActivityRecord next = topRunningActivityLocked();
......
final boolean dontWaitForPause = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, dontWaitForPause);
if (mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Pausing " + mResumedActivity);
//執(zhí)行pause
pausing |= startPausingLocked(userLeaving, false, next, dontWaitForPause);
}
......
ActivityStack lastStack = mStackSupervisor.getLastStack();
//要啟動(dòng)的Activity的app是不是為空影钉,顯然是null
if (next.app != null && next.app.thread != null) {
......
} else {
//啟動(dòng)
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
上面的代碼我省略了很多画髓,主要是先拿到最上面運(yùn)行的先判斷其是否為null,不為null則去判斷是否需要執(zhí)行pause平委,我們這里面是不需要執(zhí)行的奈虾,在后面有個(gè)對(duì)
next.app
的非空判斷,因?yàn)槲覀兪堑谝淮螁?dòng)廉赔,所以并沒(méi)有app
肉微,最后會(huì)執(zhí)行mStackSupervisor.startSpecificActivityLocked(next, true, true)
這部分代碼。
6. ActivityStackSupervisor.startSpecificActivityLocked
過(guò)程
這個(gè)過(guò)程就比較簡(jiǎn)單了蜡塌,通過(guò)AMS去啟動(dòng)一個(gè)新的進(jìn)程(Process)碉纳。
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.task.stack.setLaunchTime(r);
//很明顯,這里的app為null馏艾,我們需要?jiǎng)?chuàng)建新的process
if (app != null && app.thread != null) {
......
}
//啟動(dòng)新的process
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
7. AMS啟動(dòng)新的進(jìn)程
AMS中
startProcessLocked
中調(diào)用了Process.start
這個(gè)方法劳曹。Process.start
中調(diào)用了startViaZygote
方法奴愉,接著調(diào)用zygoteSendArgsAndGetResult
方法,通過(guò)socket
進(jìn)行通信執(zhí)行ActivityThread
的main
方法铁孵。
部分代碼:
AMS:
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
......
//去啟動(dòng)進(jìn)程
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);
......
}
Process.java:
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
}
}
private static ProcessStartResult startViaZygote(final String processClass,
final String niceName,
final int uid, final int gid,
final int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String[] extraArgs)
throws ZygoteStartFailedEx {
synchronized(Process.class) {
......
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi)/**這里可以看到通過(guò)socket啟動(dòng)*/, argsForZygote);
}
}
private static ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList<String> args)
throws ZygoteStartFailedEx {
try {
int sz = args.size();
for (int i = 0; i < sz; i++) {
if (args.get(i).indexOf('\n') >= 0) {
throw new ZygoteStartFailedEx("embedded newlines not allowed");
}
}
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();
// Should there be a timeout on this?
ProcessStartResult result = new ProcessStartResult();
// Always read the entire result from the input stream to avoid leaving
// bytes in the stream for future process starts to accidentally stumble
// upon.
result.pid = inputStream.readInt();
result.usingWrapper = inputStream.readBoolean();
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
//返回結(jié)果
return result;
} catch (IOException ex) {
zygoteState.close();
throw new ZygoteStartFailedEx(ex);
}
}
通過(guò)Zygote可以執(zhí)行ActivityThread中的main方法锭硼。
8. ActivityThread
的main
方法
main
方法中在上面一篇中也提到過(guò),上次SystemServer
啟動(dòng)過(guò)程中會(huì)調(diào)用attach(true)
方法蜕劝,而我們通過(guò)Zygote啟動(dòng)的時(shí)候檀头,會(huì)調(diào)用attach(false)
這個(gè)方法。
public static void main(String[] args) {
......
//主線程
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
......
//一直循環(huán)岖沛,如果退出暑始,說(shuō)明程序關(guān)閉
Looper.loop();
......
}
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
ViewRootImpl.addFirstDrawHandler(new Runnable() {
@Override
public void run() {
ensureJitEnabled();
}
});
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());
//獲取AMS的本地代理類
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
//調(diào)用AMS的attachApplication方法
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
// Watch for getting close to heap limit.
BinderInternal.addGcWatcher(new Runnable() {
@Override 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)) {
if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
+ " total=" + (runtime.totalMemory()/1024)
+ " used=" + (dalvikUsed/1024));
mSomeActivitiesChanged = false;
try {
mgr.releaseSomeActivities(mAppThread);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
});
} else {
......
}
......
ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {......});
}
上面的主要是就是通過(guò)Binder調(diào)用AMS的
attachApplication
方法。
9. AMS的attachApplication
方法
attachApplication
中主要是判斷當(dāng)前的Process是否存在婴削,如果存在涧偷,則需要將其kill栈暇。接著通過(guò)thread.bindApplication
來(lái)將一些需要的變量初始化察署,進(jìn)行Application初始化是尔,調(diào)用Application
的onCreate()
方法。最后通過(guò)mStackSupervisor.attachApplicationLocked(app)
方法去真正啟動(dòng)Activity互躬。下面大概看下整個(gè)流程:
//這里沒(méi)啥講的播赁,就是調(diào)用了attachApplicationLocked方法
@Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
// Find the application record that is being attached... either via
// the pid if we are running in multiple processes, or just pull the
// next app record if we are emulating process with anonymous threads.
//從進(jìn)程中查找是否有,如果有的話去殺掉這個(gè)進(jìn)程
ProcessRecord app;
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
} else {
app = null;
}
if (app == null) {
Slog.w(TAG, "No pending application record for pid " + pid
+ " (IApplicationThread " + thread + "); dropping process");
EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
if (pid > 0 && pid != MY_PID) {
Process.killProcessQuiet(pid);
//TODO: killProcessGroup(app.info.uid, pid);
} else {
try {
//退出
thread.scheduleExit();
} catch (Exception e) {
// Ignore exceptions.
}
}
return false;
}
// If this application record is still attached to a previous
// process, clean it up now.
//如果當(dāng)前的Application記錄仍然依附到之前的進(jìn)程中吼渡,則清理掉
if (app.thread != null) {
handleAppDiedLocked(app, true, true);
}
// Tell the process all about itself.
if (DEBUG_ALL) Slog.v(
TAG, "Binding process pid " + pid + " to record " + app);
final String processName = app.processName;
try {
AppDeathRecipient adr = new AppDeathRecipient(
app, pid, thread);
thread.asBinder().linkToDeath(adr, 0);
app.deathRecipient = adr;
} catch (RemoteException e) {
app.resetPackageList(mProcessStats);
startProcessLocked(app, "link fail", processName);
return false;
}
EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName);
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;
// We carefully use the same state that PackageManager uses for
// filtering, since we use this flag to decide if we need to install
// providers when user is unlocked later
app.unlocked = StorageManager.isUserKeyUnlocked(app.userId);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
//mProcessesReady這個(gè)變量在AMS的systemReady中被賦值為true容为,所以這里的normalMode也為true
boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
......
try {
int testMode = IApplicationThread.DEBUG_OFF;
if (mDebugApp != null && mDebugApp.equals(processName)) {
testMode = mWaitForDebugger
? IApplicationThread.DEBUG_WAIT
: IApplicationThread.DEBUG_ON;
app.debugging = true;
if (mDebugTransient) {
mDebugApp = mOrigDebugApp;
mWaitForDebugger = mOrigWaitForDebugger;
}
}
String profileFile = app.instrumentationProfileFile;
ParcelFileDescriptor profileFd = null;
int samplingInterval = 0;
boolean profileAutoStop = false;
if (mProfileApp != null && mProfileApp.equals(processName)) {
mProfileProc = app;
profileFile = mProfileFile;
profileFd = mProfileFd;
samplingInterval = mSamplingInterval;
profileAutoStop = mAutoStopProfiler;
}
boolean enableTrackAllocation = false;
if (mTrackAllocationApp != null && mTrackAllocationApp.equals(processName)) {
enableTrackAllocation = true;
mTrackAllocationApp = null;
}
// If the app is being launched for restore or full backup, set it up specially
boolean isRestrictedBackupMode = false;
if (mBackupTarget != null && mBackupAppName.equals(processName)) {
isRestrictedBackupMode = mBackupTarget.appInfo.uid >= Process.FIRST_APPLICATION_UID
&& ((mBackupTarget.backupMode == BackupRecord.RESTORE)
|| (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
|| (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL));
}
if (app.instrumentationClass != null) {
notifyPackageUse(app.instrumentationClass.getPackageName(),
PackageManager.NOTIFY_PACKAGE_USE_INSTRUMENTATION);
}
if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Binding proc "
+ processName + " with config " + mConfiguration);
ApplicationInfo appInfo = app.instrumentationInfo != null
? app.instrumentationInfo : app.info;
app.compat = compatibilityInfoForPackageLocked(appInfo);
if (profileFd != null) {
profileFd = profileFd.dup();
}
ProfilerInfo profilerInfo = profileFile == null ? null
: new ProfilerInfo(profileFile, profileFd, samplingInterval, profileAutoStop);
//真正執(zhí)行綁定操作是通過(guò)thread的bindApplication方法。
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked());
updateLruProcessLocked(app, false, null);
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
} catch (Exception e) {
......
return false;
}
// Remove this record from the list of starting applications.
mPersistentStartingProcesses.remove(app);
if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,
"Attach application locked removing on hold: " + app);
mProcessesOnHold.remove(app);
boolean badApp = false;
boolean didSomething = false;
// See if the top visible activity is waiting to run in this process...
//上面說(shuō)到寺酪,這里為true坎背,進(jìn)入StackSupervisor的attachApplicationLocked方法去真正啟動(dòng)Activity
if (normalMode) {
try {
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
......
return true;
}
10. StackSupervisor
的attachApplicationLocked
方法
這個(gè)方法會(huì)調(diào)用
realStartActivityLocked
方法,去真正啟動(dòng)Activity
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
final String processName = app.processName;
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (!isFocusedStack(stack)) {
continue;
}
ActivityRecord hr = stack.topRunningActivityLocked();
if (hr != null) {
if (hr.app == null && app.uid == hr.info.applicationInfo.uid
&& processName.equals(hr.processName)) {
try {
//真正啟動(dòng)Activity
if (realStartActivityLocked(hr, app, true, true)) {
didSomething = true;
}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting activity "
+ hr.intent.getComponent().flattenToShortString(), e);
throw e;
}
}
}
}
}
if (!didSomething) {
ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
return didSomething;
}
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
......
try {
......
app.forceProcessStateUpTo(mService.mTopProcessState);
//最主要的就是這里寄雀,也是通過(guò)Activity中的方法去啟動(dòng)Activity得滤。
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
......
} catch (RemoteException e) {
}
......
return true;
}
講到這里基本上啟動(dòng)流程就完成了,后面就是ActivityThread進(jìn)行Activity的啟動(dòng)過(guò)程盒犹,這個(gè)下次在繼續(xù)分析懂更。
11. 總結(jié)
這里面所有的關(guān)于Activity啟動(dòng),resume急膀,pause等等都是通過(guò)ActivityThread來(lái)進(jìn)行操作沮协,而這之中又會(huì)涉及到ActivityThread將任務(wù)交給Instrumentation去處理。這個(gè)處理過(guò)程包括了與跨進(jìn)程與遠(yuǎn)端的AMS進(jìn)行通信卓嫂,AMS又通過(guò)ActivityStarter,ActivityStackSupervisor,ActivityStack等進(jìn)行處理慷暂,最終將所啟動(dòng)的Activity真正啟動(dòng)。
其實(shí)還有個(gè)時(shí)序圖的晨雳,但是太大了行瑞,截圖也不全奸腺,等下次直接上傳,方便自己查看蘑辑。
下面計(jì)劃分析ActivityThread啟動(dòng)Activity洋机。
12. 寫(xiě)在后面的話
想寫(xiě)關(guān)于Activity啟動(dòng)流程想了好久,說(shuō)實(shí)話其中有一部分只能按自己的理解來(lái)解釋洋魂,可能會(huì)有一些問(wèn)題。但是起碼自己認(rèn)為是對(duì)的喜鼓。嗯副砍,這就夠了。