Activity启动流程

1 冷启动与热启动

应用启动分为冷启动和热启动。

冷启动:点击桌面图标,手机系统不存在该应用进程,这时系统会重新fork一个子进程来加载Application并启动Activity,这个启动方式就是冷启动。
热启动:应用的热启动比冷启动简单得多,开销也更低。在热启动中,因为系统里已有该应用的进程,所以系统的所有工作就是将Activity 带到前台。

2 Activity的启动流程

2.1 启动准备

当我们点击Launcher上的应用图标时,最终会调用到activity的startActivity()函数。我们就从activity的startActivity()开始。

@Override
public void startActivity(Intent intent, @Nullable Bundle options) {getAutofillClientController().onStartActivity(intent, mIntent);if (options != null) {startActivityForResult(intent, -1, options);} else {// Note we want to go through this call for compatibility with// applications that may have overridden the method.startActivityForResult(intent, -1);}
}public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,@Nullable Bundle options) {if (mParent == null) {options = transferSpringboardActivityOptions(options);Instrumentation.ActivityResult ar =mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this,intent, requestCode, options);if (ar != null) {mMainThread.sendActivityResult(mToken, mEmbeddedID, requestCode, ar.getResultCode(),ar.getResultData());}} else {}
}

这里调到了Instrumentation.execStartActivity。

Instrumentation 负责调用 Activity 和 Application 的生命周期,具有跟踪 Application 和 Activity 生命周期的功能。

public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options) {try {intent.migrateExtraStreamToClipData(who);intent.prepareToLeaveProcess(who);int result = ActivityTaskManager.getService().startActivity(whoThread,who.getOpPackageName(),nwho.getAttributionTag(), intent,intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null,requestCode, 0, null, options);notifyStartActivityResult(result, options);checkStartActivityResult(result, intent);} catch (RemoteException e) {throw new RuntimeException("Failure from system", e);}
}

调用了 ActivityTaskManager.getService() 方法来获取 ATMS 的代理对象,接着调用了它的 startActivity 方法。

ActivityTaskManager:是实现 Activity 与 ATMS 跨进程交互的接口,ATMS 的辅助类。

而ActivityTaskManagerService是管理 Activity 以及其容器(task、stacks、displays)的系统服务,负责 Activity 管理和调度工作(Android 10 中新增)。ATMS 是 AMS 的一个辅助类,分担了 AMS 的一部分功能,继承自 IActivityTaskManager.Stub。

@Override
public final int startActivity(IApplicationThread caller, String callingPackage,String callingFeatureId, Intent intent, String resolvedType,IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,Bundle bOptions) {return startActivityAsUser(caller, callingPackage, callingFeatureId, intent,resolvedType,resultTo, resultWho, requestCode, startFlags,profilerInfo, bOptions,UserHandle.getCallingUserId());
}private int startActivityAsUser(IApplicationThread caller, String callingPackage,@Nullable String callingFeatureId, Intent intent, String resolvedType,IBinder resultTo, String resultWho, int requestCode, int startFlags,ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {...return getActivityStartController().obtainStarter(intent, "startActivityAsUser").setCaller(caller).setCallingPackage(callingPackage).setCallingFeatureId(callingFeatureId).setResolvedType(resolvedType).setResultTo(resultTo).setResultWho(resultWho).setRequestCode(requestCode).setStartFlags(startFlags).setProfilerInfo(profilerInfo).setActivityOptions(opts).setUserId(userId).execute();
}

ActivityStartController 是用于 Activity 启动的控制器。 通过调用其 obtainStarter 方法来获取 ActivityStarter 对象:

ActivityStarter obtainStarter(Intent intent, String reason) {return mFactory.obtain().setIntent(intent).setReason(reason);
}

ActivityStarter 是 Android 7.0 中新加入的类,是 Activity 的控制器,讲如何启动一个 Activity,会收集所有的逻辑来决定如何将 Intent 和 Flags 转换为 Activity,并将 Activity 和 Task 以及 Stack 相关联。

//framework/base/services/core/java/com/android/server/wm/ActivityStarter.java
/*** Controller for interpreting how and then launching an activity.** This class collects all the logic for determining how an intent and flags should be turned into* an activity and associated task and root task.*/
class ActivityStarter {}

2.2 ActivityRecord的创建

看看ActivityStarter的execute()是如何执行的。

/*** Resolve necessary information according the request parameters provided earlier, and execute* the request which begin the journey of starting an activity.* @return The starter result.*/
int execute() {try {onExecutionStarted();...try {res = executeRequest(mRequest);} finally {mRequest.logMessage.append(" result code=").append(res);Slog.i(TAG, mRequest.logMessage.toString());mRequest.logMessage.setLength(0);}...} finally {onExecutionComplete();}
}
/*** Executing activity start request and starts the journey of starting an activity. Here* begins with performing several preliminary checks. The normally activity launch flow will* go through {@link #startActivityUnchecked} to {@link #startActivityInner}.*/
private int executeRequest(Request request) {...final ActivityRecord r = new ActivityRecord.Builder(mService).setCaller(callerApp).setLaunchedFromPid(callingPid).setLaunchedFromUid(callingUid).setLaunchedFromPackage(callingPackage).setLaunchedFromFeature(callingFeatureId).setIntent(intent).setResolvedType(resolvedType).setActivityInfo(aInfo).setConfiguration(mService.getGlobalConfiguration()).setResultTo(resultRecord).setResultWho(resultWho).setRequestCode(requestCode).setComponentSpecified(request.componentSpecified).setRootVoiceInteraction(voiceSession != null).setActivityOptions(checkedOptions).setSourceRecord(sourceRecord).build();mLastStartActivityRecord = r;mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,request.voiceInteractor, startFlags, checkedOptions,inTask, inTaskFragment, balCode, intentGrants, realCallingUid);return mLastStartActivityResult;
}

这里创建了新activity的ActivityRecord对象,然后调用startActivityUnchecked。

2.3 Task的创建

/*** Start an activity while most of preliminary checks has been done and caller has been* confirmed that holds necessary permissions to do so.* Here also ensures that the starting activity is removed if the start wasn't successful.*/
private int startActivityUnchecked(final ActivityRecord r,ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, ActivityOptions options, Task inTask, TaskFragment inTaskFragment,@BalCode int balCode, NeededUriGrants intentGrants, int realCallingUid) {result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,startFlags, options, inTask, inTaskFragment, balCode,intentGrants, realCallingUid);
}/*** Start an activity and determine if the activity should be adding to the top of an existing* task or delivered new intent to an existing activity. Also manipulating the activity task* onto requested or valid root-task/display.** Note: This method should only be called from {@link #startActivityUnchecked}.*/// TODO(b/152429287): Make it easier to exercise code paths through startActivityInner
@VisibleForTesting
int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,int startFlags, ActivityOptions options, Task inTask,TaskFragment inTaskFragment, @BalCode int balCode,NeededUriGrants intentGrants, int realCallingUid) {...// Compute if there is an existing task that should be used for.final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask();final boolean newTask = targetTask == null;mTargetTask = targetTask;...if (mTargetRootTask == null) {mTargetRootTask = getOrCreateRootTask(mStartActivity, mLaunchFlags,targetTask,mOptions);}if (newTask) {final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)? mSourceRecord.getTask() : null;setNewTask(taskToAffiliate);} else if (mAddingToTask) {addOrReparentStartingActivity(targetTask, "adding to task");}...final boolean isTaskSwitch = startedTask != prevTopTask;mTargetRootTask.startActivityLocked(mStartActivity, topRootTask, newTask,isTaskSwitch, mOptions, sourceRecord);if (mDoResume) {...} else {mRootWindowContainer.resumeFocusedTasksTopActivities(mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);}mRootWindowContainer.updateUserRootTask(mStartActivity.mUserId, mTargetRootTask);// Update the recent tasks list immediately when the activity startsmSupervisor.mRecentTasks.add(startedTask);mSupervisor.handleNonResizableTaskIfNeeded(startedTask, mPreferredWindowingMode,mPreferredTaskDisplayArea, mTargetRootTask);...
}

这里reusedTask明显是null,我们走的是computeTargetTask()。先来看computeTargetTask

/** Returns the leaf task where the target activity may be placed. */
private Task computeTargetTask() {if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {// A new task should be created instead of using existing one.return null;} else if (mSourceRecord != null) {return mSourceRecord.getTask();} else if (mInTask != null) {// The task is specified from AppTaskImpl, so it may not be attached yet.if (!mInTask.isAttached()) {// Attach the task to display area. Ignore the returned root task (though usually// they are the same) because "target task" should be leaf task.getOrCreateRootTask(mStartActivity, mLaunchFlags, mInTask, mOptions);}return mInTask;} else {final Task rootTask = getOrCreateRootTask(mStartActivity, mLaunchFlags, null /* task */,mOptions);final ActivityRecord top = rootTask.getTopNonFinishingActivity();if (top != null) {return top.getTask();} else {// Remove the root task if no activity in the root task.rootTask.removeIfPossible("computeTargetTask");}}return null;
}

启动根 Activity 时会将 Intent 的 Flag 设置为 FLAG_ACTIVITY_NEW_TASK,表示要创建一个新的 Task:这里返回null。因此final boolean newTask = targetTask == null;这句就是true。

然后判断mTargetRootTask是否为空,也就是TaskDisplayArea。

接着就到了setNewTask(taskToAffiliate);

private void setNewTask(Task taskToAffiliate) {final boolean toTop = !mLaunchTaskBehind && !mAvoidMoveToFront;final Task task = mTargetRootTask.reuseOrCreateTask(mStartActivity.info, mIntent, mVoiceSession,mVoiceInteractor, toTop, mStartActivity, mSourceRecord, mOptions);task.mTransitionController.collectExistenceChange(task);addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask");ProtoLog.v(WM_DEBUG_TASKS, "Starting new activity %s in new task %s",mStartActivity, mStartActivity.getTask());if (taskToAffiliate != null) {mStartActivity.setTaskToAffiliateWith(taskToAffiliate);}
}

Task 就是用户在执行某项工作时与之相关联的 Activity 集合。系统通过任务栈来管理这些 Activity,它们按照打开的顺序进入任务栈中。这些 Activity 可以来自同一个 APP,也可以来自不同的 APP,Activity 之间不一定非要有关联。

比如当我们点recent键或者上滑进入Recent界面时,屏幕上展示的就是一个个的 Task。

class Task extends TaskFragment {
}
class TaskFragment extends WindowContainer<WindowContainer> {
}

Task继承TaskFragment,而TaskFragment是一个容器,可以用来放 activities 或者其它的 TaskFragment,也能够管理 activity 的生命周期或者更新 * activities 的可见性。

task affinity:在 manifest 文件中,注册 activity 时如果不申明 taskAffinity 属性,就是 APP 程序的默认包名,默认情况下,一个 APP 中所有的 Activity 都在一个 Task 中:

<activityandroid:taskAffinity=""...
/>

接着调用task的startActivityLocked,调用的是 RootWindowContainer.resumeFocusedTasksTopActivities 方法

先来看startActivityLocked。

void startActivityLocked(ActivityRecord r, @Nullable Task topTask, boolean newTask,boolean isTaskSwitch, ActivityOptions options, @Nullable ActivityRecord sourceRecord) {...boolean doShow = true;if (newTask) {if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {resetTaskIfNeeded(r, r);doShow = topRunningNonDelayedActivityLocked(null) == r;}} else if (options != null && options.getAnimationType()== ActivityOptions.ANIM_SCENE_TRANSITION) {doShow = false;}if (options != null && options.getDisableStartingWindow()) {doShow = false;}if (r.mLaunchTaskBehind) {// Don't do a starting window for mLaunchTaskBehind. More importantly make sure we// tell WindowManager that r is visible even though it is at the back of the root// task.r.setVisibility(true);ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);// If launching behind, the app will start regardless of what's above it, so mark it// as unknown even before prior `pause`. This also prevents a race between set-ready// and activityPause. Launch-behind is basically only used for dream now.if (!r.isVisibleRequested()) {r.notifyUnknownVisibilityLaunchedForKeyguardTransition();}// Go ahead to execute app transition for this activity since the app transition// will not be triggered through the resume channel.mDisplayContent.executeAppTransition();} else if (SHOW_APP_STARTING_PREVIEW && doShow) {// Figure out if we are transitioning from another activity that is// "has the same starting icon" as the next one.  This allows the// window manager to keep the previous window it had previously// created, if it still had one.Task baseTask = r.getTask();final ActivityRecord prev = baseTask.getActivity(a -> a.mStartingData != null && a.showToCurrentUser());mWmService.mStartingSurfaceController.showStartingWindow(r, prev, newTask,isTaskSwitch, sourceRecord);}
}

这里走的是mWmService.mStartingSurfaceController.showStartingWindow,也就是显示闪屏页。

继续看startActivityInner,对于我们新启动的activity来说,mDoResume肯定是false,因此走的是else 分支。

//framework/base/services/core/java/com/android/server/wm/Task.java
mRootWindowContainer.resumeFocusedTasksTopActivities(mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);

继续到RootWindowContainer.resumeFocusedTasksTopActivities

//framework/base/services/core/java/com/android/server/wm/RootWindowContainer.java
boolean resumeFocusedTasksTopActivities(Task targetRootTask, ActivityRecord target, 							ActivityOptions targetOptions, boolean deferPause) {boolean result = false;if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()|| getTopDisplayFocusedRootTask() == targetRootTask)) {result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions, deferPause);}
}

这里targetRootTask是一个task。

/*** Ensure that the top activity in the root task is resumed.** @param prev The previously resumed activity, for when in the process* of pausing; can be null to call from elsewhere.* @param options Activity options.* @param deferPause When {@code true}, this will not pause back tasks.** @return Returns true if something is being resumed, or false if* nothing happened.** NOTE: It is not safe to call this method directly as it can cause an activity in a*       non-focused root task to be resumed.*       Use {@link RootWindowContainer#resumeFocusedTasksTopActivities} to resume the*       right activity for the current system state.*/
@GuardedBy("mService")
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev,ActivityOptions options, boolean deferPause) {if (isLeafTask()) {if (isFocusableAndVisible()) {someActivityResumed = resumeTopActivityInnerLocked(prev, options, deferPause);}}
}@GuardedBy("mService")
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options, boolean deferPause) {resumed[0] = topFragment.resumeTopActivity(prev, options, deferPause);return resumed[0];
}

继续到TaskFragment的resumeTopActivity。

2.4 启动进程

final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options,boolean deferPause) {boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);if (mResumedActivity != null) {ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Pausing %s",mResumedActivity);pausing |= startPausing(mTaskSupervisor.mUserLeaving, false /* uiSleeping */,next, "resumeTopActivity");}
}

首先通知当前的activity走Pause逻辑。

if (pausing) {if (next.attachedToProcess()) {next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,true /* activityChange */, false /* updateOomAdj */,false /* addPendingTopUid */);} else if (!next.isProcessRunning()) {// Since the start-process is asynchronous, if we already know the process of next// activity isn't running, we can start the process earlier to save the time to wait// for the current activity to be paused.final boolean isTop = this == taskDisplayArea.getFocusedRootTask();mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop,isTop ? HostingRecord.HOSTING_TYPE_NEXT_TOP_ACTIVITY: HostingRecord.HOSTING_TYPE_NEXT_ACTIVITY);}
}

如果要启动activity的进程没有启动,就先调用ATMS的startProcessAsync启动进程。

void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,String hostingType) {// Post message to start process to avoid possible deadlock of calling // into AMS with the ATMS lock held.final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess, mAmInternal, activity.processName,activity.info.applicationInfo, knownToBeDead, isTop, hostingType,activity.intent.getComponent());mH.sendMessage(m);
}

继续走AMS的startProcess

@Override
public void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead, boolean isTop, String hostingType,ComponentName hostingName) {synchronized (ActivityManagerService.this) {// If the process is known as top app, set a hint so when the process is// started, the top priority can be applied immediately to avoid cpu being// preempted by other processes before attaching the process of top app.startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,new HostingRecord(hostingType, hostingName, isTop),ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false /* allowWhileBooting */,false /* isolated */);}
}@GuardedBy("this")
final ProcessRecord startProcessLocked(String processName,ApplicationInfo info,boolean knownToBeDead, int intentFlags,HostingRecord hostingRecord,int zygotePolicyFlags, boolean allowWhileBooting, boolean isolated) {return mProcessList.startProcessLocked(processName, info, knownToBeDead,intentFlags, hostingRecord, zygotePolicyFlags, allowWhileBooting,isolated, 0 /* isolatedUid */,false /* isSdkSandbox */, 0 /* sdkSandboxClientAppUid */,null /* sdkSandboxClientAppPackage */,null /* ABI override */, null /* entryPoint */,null /* entryPointArgs */, null /* crashHandler */);
}

继续到ProcessList.startProcessLocked

@GuardedBy("mService")
ProcessRecord startProcessLocked(String processName, ApplicationInfo info,boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord,int zygotePolicyFlags, boolean allowWhileBooting, boolean isolated, int isolatedUid,boolean isSdkSandbox, int sdkSandboxUid, String sdkSandboxClientAppPackage,String abiOverride, String entryPoint, String[] entryPointArgs,Runnable crashHandler) {checkSlow(startTime, "startProcess: stepping in to startProcess");final boolean success =startProcessLocked(app, hostingRecord, zygotePolicyFlags, abiOverride);checkSlow(startTime, "startProcess: done starting proc!");return success ? app : null;
}@GuardedBy("mService")
boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks, String abiOverride) {return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,instructionSet, invokeWith, startUptime, startElapsedTime);
}

这里startProcessLocked比较长,主要是为进程启动根据条件来添加参数。

@GuardedBy("mService")
boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint,ProcessRecord app,int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags, int mountExternal,String seInfo, String requiredAbi, String instructionSet, String invokeWith,long startUptime, long startElapsedTime) {final Process.ProcessStartResult startResult = startProcess(hostingRecord,entryPoint, app,uid, gids, runtimeFlags, zygotePolicyFlags,mountExternal, seInfo,requiredAbi, instructionSet, invokeWith,startUptime);handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,startSeq, false);
}private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,ProcessRecord app, int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags,int mountExternal, String seInfo, String requiredAbi, String instructionSet,String invokeWith, long startTime) {if (hostingRecord.usesWebviewZygote()) {startResult = startWebView(entryPoint, app.processName, uid, uid, gids,runtimeFlags, mountExternal,app.info.targetSdkVersion, seInfo, requiredAbi,instructionSet,app.info.dataDir, null, app.info.packageName,app.getDisabledCompatChanges(),new String[]{PROC_START_SEQ_IDENT +app.getStartSeq()});} else if (hostingRecord.usesAppZygote()) {final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);// We can't isolate app data and storage data as parent zygote already did that.startResult = appZygote.getProcess().start(entryPoint,app.processName, uid,uid, gids, runtimeFlags, mountExternal,app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,app.info.dataDir, null, app.info.packageName,/*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,app.getDisabledCompatChanges(), pkgDataInfoMap,allowlistedAppDataInfoMap,false, false,new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});} else {regularZygote = true;startResult = Process.start(entryPoint,app.processName, uid, uid, gids,runtimeFlags, mountExternal,app.info.targetSdkVersion, seInfo, requiredAbi,instructionSet,app.info.dataDir, invokeWith,app.info.packageName, zygotePolicyFlags,isTopApp, app.getDisabledCompatChanges(), pkgDataInfoMap,allowlistedAppDataInfoMap, bindMountAppsData,bindMountAppStorageDirs,new String[]{PROC_START_SEQ_IDENT +app.getStartSeq()});// By now the process group should have been created by zygote.app.mProcessGroupCreated = true;}
}

直接看appZygote.getProcess().start

public final Process.ProcessStartResult start(@NonNull final String processClass,final String niceName,int uid, int gid, @Nullable int[] gids,int runtimeFlags, int mountExternal,int targetSdkVersion,@Nullable String seInfo,@NonNull String abi,@Nullable String instructionSet,@Nullable String appDataDir,@Nullable String invokeWith,@Nullable String packageName,int zygotePolicyFlags,boolean isTopApp,@Nullable long[] disabledCompatChanges,@Nullable Map<String, Pair<String, Long>>pkgDataInfoMap,@Nullable Map<String, Pair<String, Long>>allowlistedDataInfoList,boolean bindMountAppsData,boolean bindMountAppStorageDirs,@Nullable String[] zygoteArgs) {return startViaZygote(processClass, niceName, uid, gid, gids,runtimeFlags, mountExternal, targetSdkVersion, seInfo,abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges,pkgDataInfoMap, allowlistedDataInfoList, bindMountAppsData,bindMountAppStorageDirs, zygoteArgs);
}private Process.ProcessStartResult startViaZygote() {synchronized(mLock) {// The USAP pool can not be used if the application will not use// the systems graphics driver.  If that driver is requested // use the Zygote application start path.return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),zygotePolicyFlags, argsForZygote);}
}

这个过程创建了Socket,然后连接zygote,通过socket完成AMS和Zygote之间的通讯。

// frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
Runnable processCommand(ZygoteServer zygoteServer, boolean multipleOK) {ZygoteArguments parsedArgs;try (ZygoteCommandBuffer argBuffer = new ZygoteCommandBuffer(mSocket)) {while (true) {try {parsedArgs = ZygoteArguments.getInstance(argBuffer);// Keep argBuffer around, since we need it to fork.} catch (IOException ex) {throw new IllegalStateException("IOException on command socket", ex);}...if (parsedArgs.mInvokeWith != null || parsedArgs.mStartChildZygote|| !multipleOK || peer.getUid() != Process.SYSTEM_UID) {// Continue using old code for now. TODO: Handle these cases in the other path.pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid,parsedArgs.mGids, parsedArgs.mRuntimeFlags, rlimits,parsedArgs.mMountExternal, parsedArgs.mSeInfo, parsedArgs.mNiceName,fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,parsedArgs.mInstructionSet, parsedArgs.mAppDataDir,parsedArgs.mIsTopApp, parsedArgs.mPkgDataInfoList,parsedArgs.mAllowlistedDataInfoList, parsedArgs.mBindMountAppDataDirs,parsedArgs.mBindMountAppStorageDirs); // 1try {if (pid == 0) {// in childzygoteServer.setForkChild();zygoteServer.closeServerSocket();IoUtils.closeQuietly(serverPipeFd);serverPipeFd = null;return handleChildProc(parsedArgs, childPipeFd,parsedArgs.mStartChildZygote); // 2} else {...}} finally {...}} else {...}}}...throw new AssertionError("Shouldn't get here");
}private Runnable handleChildProc(ZygoteArguments parsedArgs,FileDescriptor pipeFd, boolean isZygote) {...if (parsedArgs.mInvokeWith != null) {...} else {if (!isZygote) { // 3 isZygote 一般是 falsereturn ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,parsedArgs.mDisabledCompatChanges,parsedArgs.mRemainingArgs, null /* classLoader */); // 4} else {return ZygoteInit.childZygoteInit(parsedArgs.mRemainingArgs  /* classLoader */); // }}
}

注释 3 处的 isZygote 一般是 false,注释 4 处调用的是 ZygoteInit.zygoteInit 方法:

// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,String[] argv, ClassLoader classLoader) {if (RuntimeInit.DEBUG) {Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");}Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");RuntimeInit.redirectLogStreams();RuntimeInit.commonInit();ZygoteInit.nativeZygoteInit();return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,classLoader); // 1
}

注释 1 处调用 RuntimeInit.applicationInit 方法:

protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,String[] argv, ClassLoader classLoader) {// If the application calls System.exit(), terminate the process// immediately without running any shutdown hooks.  It is not possible to// shutdown an Android application gracefully.  Among other things, the// Android runtime shutdown hooks close the Binder driver, which can cause// leftover running threads to crash before the process actually exits.nativeSetExitWithoutCleanup(true);VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);final Arguments args = new Arguments(argv);// The end of of the RuntimeInit event (see #zygoteInit).Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);// Remaining arguments are passed to the start class's static mainreturn findStaticMain(args.startClass, args.startArgs, classLoader);
}/*** Invokes a static "main(argv[]) method on class "className".* Converts various failing exceptions into RuntimeExceptions, with* the assumption that they will then cause the VM instance to exit.** @param className Fully-qualified class name* @param argv Argument vector for main()* @param classLoader the classLoader to load {@className} with*/
protected static Runnable findStaticMain(String className, String[] argv,ClassLoader classLoader) {Class<?> cl;try {cl = Class.forName(className, true, classLoader);} catch (ClassNotFoundException ex) {throw new RuntimeException("Missing class when invoking static main " + className,ex);}Method m;try {m = cl.getMethod("main", new Class[] { String[].class });} catch (NoSuchMethodException ex) {throw new RuntimeException("Missing static main on " + className, ex);} catch (SecurityException ex) {throw new RuntimeException("Problem getting static main on " + className, ex);}int modifiers = m.getModifiers();if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {throw new RuntimeException("Main method is not public and static on " + className);}/** This throw gets caught in ZygoteInit.main(), which responds* by invoking the exception's run() method. This arrangement* clears up all the stack frames that were required in setting* up the process.*/return new MethodAndArgsCaller(m, argv);
}/*** Helper class which holds a method and arguments and can call them. * This is used as part of* a trampoline to get rid of the initial process setup stack frames.*/
static class MethodAndArgsCaller implements Runnable {/** method to call */private final Method mMethod;/** argument array */private final String[] mArgs;public MethodAndArgsCaller(Method method, String[] args) {mMethod = method;mArgs = args;}public void run() {try {mMethod.invoke(null, new Object[] { mArgs });} catch (IllegalAccessException ex) {throw new RuntimeException(ex);} catch (InvocationTargetException ex) {Throwable cause = ex.getCause();if (cause instanceof RuntimeException) {throw (RuntimeException) cause;} else if (cause instanceof Error) {throw (Error) cause;}throw new RuntimeException(ex);}}
}

MethodAndArgsCaller.run 方法最终会进入到 ActivityThread.main 方法中。

2.5 ActivityThread创建

public static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");// Install selective syscall interceptionAndroidOs.install();// CloseGuard defaults to true and can be quite spammy.  We// disable it here, but selectively enable it later (via// StrictMode) on debug builds, but using DropBox, not logs.CloseGuard.setEnabled(false);Environment.initForCurrentUser();// Make sure TrustedCertificateStore looks in the right place for CA certificatesfinal File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());TrustedCertificateStore.setDefaultUserDirectory(configDir);// Call per-process mainline module initialization.initializeMainlineModules();Process.setArgV0("<pre-initialized>");Looper.prepareMainLooper();// Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.// It will be in the format "seq=114"long startSeq = 0;if (args != null) {for (int i = args.length - 1; i >= 0; --i) {if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {startSeq = Long.parseLong(args[i].substring(PROC_START_SEQ_IDENT.length()));}}}ActivityThread thread = new ActivityThread();thread.attach(false, startSeq);if (sMainThreadHandler == null) {sMainThreadHandler = thread.getHandler();}if (false) {Looper.myLooper().setMessageLogging(newLogPrinter(Log.DEBUG, "ActivityThread"));}// End of event ActivityThreadMain.Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");
}

2.6 attachApplication

继续到ActivityThread#attachthread.attach(false, startSeq);

private void attach(boolean system, long startSeq) {final IActivityManager mgr = ActivityManager.getService();try {mgr.attachApplication(mAppThread, startSeq);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}
}

走到了AMS的attachApplication

@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {if (thread == null) {throw new SecurityException("Invalid application interface");}synchronized (this) {int callingPid = Binder.getCallingPid();final int callingUid = Binder.getCallingUid();final long origId = Binder.clearCallingIdentity();attachApplicationLocked(thread, callingPid, callingUid, startSeq);Binder.restoreCallingIdentity(origId);}
}@GuardedBy("this")
private void attachApplicationLocked(@NonNull IApplicationThread thread,int pid, int callingUid, long startSeq) {final ActiveInstrumentation instr2 = app.getActiveInstrumentation();if (app.getIsolatedEntryPoint() != null) {} else if (instr2 != null) {thread.bindApplication(processName, appInfo,app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,providerList,instr2.mClass,profilerInfo, instr2.mArguments,instr2.mWatcher,instr2.mUiAutomationConnection, testMode,mBinderTransactionTrackingEnabled, enableTrackAllocation,isRestrictedBackupMode || !normalMode, app.isPersistent(),new Configuration(app.getWindowProcessController().getConfiguration()),app.getCompat(), getCommonServicesLocked(app.isolated),mCoreSettingsObserver.getCoreSettingsLocked(),buildSerial, autofillOptions, contentCaptureOptions,app.getDisabledCompatChanges(), serializedSystemFontMap,app.getStartElapsedTime(), app.getStartUptime());} else {thread.bindApplication(processName, appInfo,app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,providerList, null, profilerInfo, null, null, null, testMode,mBinderTransactionTrackingEnabled, enableTrackAllocation,isRestrictedBackupMode || !normalMode, app.isPersistent(),new Configuration(app.getWindowProcessController().getConfiguration()),app.getCompat(), getCommonServicesLocked(app.isolated),mCoreSettingsObserver.getCoreSettingsLocked(),buildSerial, autofillOptions, contentCaptureOptions,app.getDisabledCompatChanges(), serializedSystemFontMap,app.getStartElapsedTime(), app.getStartUptime());}if (!mConstants.mEnableWaitForFinishAttachApplication) {finishAttachApplicationInner(startSeq, callingUid, pid);} else {app.setPendingFinishAttach(true);}
}

继续看ApplicationThread#bindApplication

@Override
public final void bindApplication(String processName, ApplicationInfo appInfo,String sdkSandboxClientAppVolumeUuid, String sdkSandboxClientAppPackage,ProviderInfoList providerList, ComponentName instrumentationName,ProfilerInfo profilerInfo, Bundle instrumentationArgs,IInstrumentationWatcher instrumentationWatcher,IUiAutomationConnection instrumentationUiConnection, int debugMode,boolean enableBinderTracking, boolean trackAllocation,boolean isRestrictedBackupMode, boolean persistent,Configuration config,CompatibilityInfo compatInfo, Map services, Bundle coreSettings,String buildSerial, AutofillOptions autofillOptions,ContentCaptureOptions contentCaptureOptions, long[] disabledCompatChanges,SharedMemory serializedSystemFontMap,long startRequestedElapsedTime, long startRequestedUptime) {AppBindData data = new AppBindData();data.processName = processName;data.appInfo = appInfo;data.sdkSandboxClientAppVolumeUuid = sdkSandboxClientAppVolumeUuid;data.sdkSandboxClientAppPackage = sdkSandboxClientAppPackage;data.providers = providerList.getList();data.instrumentationName = instrumentationName;data.instrumentationArgs = instrumentationArgs;data.instrumentationWatcher = instrumentationWatcher;data.instrumentationUiAutomationConnection = instrumentationUiConnection;data.debugMode = debugMode;data.enableBinderTracking = enableBinderTracking;data.trackAllocation = trackAllocation;data.restrictedBackupMode = isRestrictedBackupMode;data.persistent = persistent;data.config = config;data.compatInfo = compatInfo;data.initProfilerInfo = profilerInfo;data.buildSerial = buildSerial;data.autofillOptions = autofillOptions;data.contentCaptureOptions = contentCaptureOptions;data.disabledCompatChanges = disabledCompatChanges;data.mSerializedSystemFontMap = serializedSystemFontMap;data.startRequestedElapsedTime = startRequestedElapsedTime;data.startRequestedUptime = startRequestedUptime;updateCompatOverrideScale(compatInfo);CompatibilityInfo.applyOverrideScaleIfNeeded(config);sendMessage(H.BIND_APPLICATION, data);
}public void handleMessage(Message msg) {if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));switch (msg.what) {case BIND_APPLICATION:Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,"bindApplication");AppBindData data = (AppBindData)msg.obj;handleBindApplication(data);Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);break;}
}

继续看handleBindApplication

// frameworks/base/core/java/android/app/ActivityThread.java
private void handleBindApplication(AppBindData data) {...// send up app name; do this *before* waiting for debuggerProcess.setArgV0(data.processName);android.ddm.DdmHandleAppName.setAppName(data.processName,data.appInfo.packageName,UserHandle.myUserId());VMRuntime.setProcessPackageName(data.appInfo.packageName);// Pass data directory path to ART. This is used for caching information and// should be set before any application code is loaded.VMRuntime.setProcessDataDirectory(data.appInfo.dataDir);if (mProfiler.profileFd != null) {mProfiler.startProfiling();}...// Instrumentation info affects the class loader, so load it before// setting up the app context.final InstrumentationInfo ii;if (data.instrumentationName != null) {ii = prepareInstrumentation(data);} else {ii = null;}final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);mConfigurationController.updateLocaleListFromAppContext(appContext);...// Continue loading instrumentation.if (ii != null) {initInstrumentation(ii, data, appContext);} else {mInstrumentation = new Instrumentation();mInstrumentation.basicInit(this);}...// Allow disk access during application and provider setup. This could// block processing ordered broadcasts, but later processing would// probably end up doing the same disk access.Application app;final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();try {// If the app is being launched for full backup or restore, bring it up in// a restricted environment with the base application class.app = data.info.makeApplicationInner(data.restrictedBackupMode, null); // 1...// Do this after providers, since instrumentation tests generally start their// test thread at this point, and we don't want that racing.try {mInstrumentation.onCreate(data.instrumentationArgs);}catch (Exception e) {throw new RuntimeException("Exception thrown in onCreate() of "+ data.instrumentationName + ": " + e.toString(), e);}try {mInstrumentation.callApplicationOnCreate(app); // 2} catch (Exception e) {if (!mInstrumentation.onException(app, e)) {throw new RuntimeException("Unable to create application " + app.getClass().getName()+ ": " + e.toString(), e);}}} finally {// If the app targets < O-MR1, or doesn't change the thread policy// during startup, clobber the policy to maintain behavior of b/36951662if (data.appInfo.targetSdkVersion < Build.VERSION_CODES.O_MR1|| StrictMode.getThreadPolicy().equals(writesAllowedPolicy)) {StrictMode.setThreadPolicy(savedPolicy);}}
}

2.7 makeApplication

首先来看app = data.info.makeApplicationInner(data.restrictedBackupMode, null);

这里data是AppBindData,info是LoadedApk。

private Application makeApplicationInner(boolean forceDefaultAppClass,Instrumentation instrumentation, boolean allowDuplicateInstances) {if (mApplication != null) {return mApplication;}try {final java.lang.ClassLoader cl = getClassLoader();if (!mPackageName.equals("android")) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,"initializeJavaContextClassLoader");initializeJavaContextClassLoader();Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);}// Rewrite the R 'constants' for all library apks.SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers(false, false);for (int i = 0, n = packageIdentifiers.size(); i < n; i++) {final int id = packageIdentifiers.keyAt(i);if (id == 0x01 || id == 0x7f) {continue;}rewriteRValues(cl, packageIdentifiers.valueAt(i), id);}ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);// The network security config needs to be aware of multiple// applications in the same process to handle discrepanciesNetworkSecurityConfigProvider.handleNewApplication(appContext);app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);appContext.setOuterContext(app);} catch (Exception e) {if (!mActivityThread.mInstrumentation.onException(app, e)) {Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);throw new RuntimeException("Unable to instantiate application " + appClass+ " package " + mPackageName + ": " + e.toString(), e);}}mActivityThread.mAllApplications.add(app);mApplication = app;if (!allowDuplicateInstances) {synchronized (sApplications) {sApplications.put(mPackageName, app);}}if (instrumentation != null) {try {instrumentation.callApplicationOnCreate(app);} catch (Exception e) {if (!instrumentation.onException(app, e)) {Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);throw new RuntimeException("Unable to create application " + app.getClass().getName()+ ": " + e.toString(), e);}}}Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);return app;
}

这里首先拿到ClassLoader,然后创建了appContext,最后newApplication

app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
public Application newApplication(ClassLoader cl, String className, Context context)throws InstantiationException, IllegalAccessException, 
ClassNotFoundException {Application app = getFactory(context.getPackageName()).instantiateApplication(cl, className);app.attach(context);return app;
}

然后调用到了Application的attach

/* package */ final void attach(Context context) {attachBaseContext(context);mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}

继续看makeApplicationInner#instrumentation.callApplicationOnCreate(app);

public void callApplicationOnCreate(Application app) {app.onCreate();
}

这就调用到了Application的onCreate,也就是我们经常继承Application的onCreate。

2.8 attachApplication

在ActivityManagerService#attachApplicationLocked中 bindApplication之后,就进入到finishAttachApplicationInner。

private void finishAttachApplicationInner(long startSeq, int uid, int pid) {// See if the top visible activity is waiting to run in this process...if (normalMode) {try {didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());} catch (Exception e) {Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);badApp = true;}}// Find any services that should be running in this process...if (!badApp) {try {didSomething |= mServices.attachApplicationLocked(app, processName);checkTime(startTime, "finishAttachApplicationInner: "+ "after mServices.attachApplicationLocked");} catch (Exception e) {Slog.wtf(TAG, "Exception thrown starting services in " + app, e);badApp = true;}}
}

来看看mAtmInternal.attachApplication(app.getWindowProcessController());

@HotPath(caller = HotPath.PROCESS_CHANGE)
@Override
public boolean attachApplication(WindowProcessController wpc) throws RemoteException {synchronized (mGlobalLockWithoutBoost) {if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "attachApplication:" + wpc.mName);}try {return mRootWindowContainer.attachApplication(wpc);} finally {Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);}}
}

调用到RootWindowContainer.attachApplication。

boolean attachApplication(WindowProcessController app) throws RemoteException {try {return mAttachApplicationHelper.process(app);} finally {mAttachApplicationHelper.reset();}
}boolean process(WindowProcessController app) throws RemoteException {mApp = app;for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {getChildAt(displayNdx).forAllRootTasks(this);if (mRemoteException != null) {throw mRemoteException;}}if (!mHasActivityStarted) {ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,false /* preserveWindows */);}return mHasActivityStarted;
}

先来看getChildAt(displayNdx).forAllRootTasks(this);

// frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java
boolean forAllRootTasks(Predicate<Task> callback) {return forAllRootTasks(callback, true /* traverseTopToBottom */);
}boolean forAllRootTasks(Predicate<Task> callback, boolean traverseTopToBottom) {int count = mChildren.size();if (traverseTopToBottom) {for (int i = count - 1; i >= 0; --i) {if (mChildren.get(i).forAllRootTasks(callback, traverseTopToBottom)) {return true;}}} else {for (int i = 0; i < count; i++) {if (mChildren.get(i).forAllRootTasks(callback, traverseTopToBottom)) {return true;}// Root tasks may be removed from this display. Ensure each task will be processed// and the loop will end.int newCount = mChildren.size();i -= count - newCount;count = newCount;}}return false;
}

继续看Task#forAllRootTasks

// frameworks/base/services/core/java/com/android/server/wm/Task.java
@Override
void forAllRootTasks(Consumer<Task> callback, boolean traverseTopToBottom) {if (isRootTask()) {callback.accept(this);}
}

这就回到了AttachApplicationHelper

// frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
private class AttachApplicationHelper implements Consumer<Task>, Predicate<ActivityRecord> {@Overridepublic void accept(Task rootTask) {if (mRemoteException != null) {return;}if (rootTask.getVisibility(null /* starting */)== TASK_FRAGMENT_VISIBILITY_INVISIBLE) {return;}mTop = rootTask.topRunningActivity();rootTask.forAllActivities(this);}
}

继续看

// frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java
boolean forAllActivities(Predicate<ActivityRecord> callback) {return forAllActivities(callback, true /*traverseTopToBottom*/);
}boolean forAllActivities(Predicate<ActivityRecord> callback, boolean traverseTopToBottom) {if (traverseTopToBottom) {for (int i = mChildren.size() - 1; i >= 0; --i) {if (mChildren.get(i).forAllActivities(callback, traverseTopToBottom)) return true;}} else {final int count = mChildren.size();for (int i = 0; i < count; i++) {if (mChildren.get(i).forAllActivities(callback, traverseTopToBottom)) return true;}}return false;
}
// frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java
@Override
boolean forAllActivities(Predicate<ActivityRecord> callback, boolean traverseTopToBottom) {return callback.test(this);
}

最后是AttachApplicationHelper#test

// frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
private class AttachApplicationHelper implements Consumer<Task>, Predicate<ActivityRecord> {@Overridepublic boolean test(ActivityRecord r) {if (r.finishing || !r.showToCurrentUser() || !r.visibleIgnoringKeyguard|| r.app != null || mApp.mUid != r.info.applicationInfo.uid|| !mApp.mName.equals(r.processName)) {return false;}try {if (mTaskSupervisor.realStartActivityLocked(r, mApp,mTop == r && r.getTask().canBeResumed(r) /* andResume */,true /* checkConfig */)) {mHasActivityStarted = true;}} catch (RemoteException e) {Slog.w(TAG, "Exception in new application when starting activity " + mTop, e);mRemoteException = e;return true;}return false;}
}

2.9 StartActivity

//framework/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,boolean andResume, boolean checkConfig) throws RemoteException {// Have the window manager re-evaluate the orientation of the screen // based on the new activity order.  Note that as a result of this,// it can call back into the activity manager with a new orientation. // We don't care about that, because the activity is// not currently running so we are just restarting it anyway.if (checkConfig) {// Deferring resume here because we're going to launch new activity shortly.// We don't want to perform a redundant launch of the same // record while ensuring configurations and trying to resume // top activity of focused root task.mRootWindowContainer.ensureVisibilityAndConfig(r, r.getDisplayId(), false /* markFrozenIfConfigChanged */, true /* deferResume */);}// Create activity launch transaction.final ClientTransaction clientTransaction = ClientTransaction.obtain(proc.getThread(), r.token);final boolean isTransitionForward = r.isTransitionForward();final IBinder fragmentToken = r.getTaskFragment().getFragmentToken();final int deviceId = getDeviceIdForDisplayId(r.getDisplayId());clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),System.identityHashCode(r), r.info,// TODO: Have this take the merged configuration instead of separate global// and override configs.mergedConfiguration.getGlobalConfiguration(),mergedConfiguration.getOverrideConfiguration(), deviceId,r.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor,proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(),results, newIntents, r.takeOptions(), isTransitionForward,proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken));// Set desired final state.final ActivityLifecycleItem lifecycleItem;if (andResume) {lifecycleItem = ResumeActivityItem.obtain(isTransitionForward,r.shouldSendCompatFakeFocus());} else {lifecycleItem = PauseActivityItem.obtain();}clientTransaction.setLifecycleStateRequest(lifecycleItem);// Schedule transaction.mService.getLifecycleManager().scheduleTransaction(clientTransaction);
}

这里checkConfig为true

//framework/base/services/core/java/com/android/server/wm/RootWindowContainer.java
/*** Ensure all activities visibility, update orientation and configuration.** @param starting The currently starting activity or {@code null} if there is none.* @param displayId The id of the display where operation is executed.* @param markFrozenIfConfigChanged Whether to set* {@link ActivityRecord#frozenBeforeDestroy} to {@code true} if config changed.* @param deferResume  Whether to defer resume while updating config.* @return 'true' if starting activity was kept or wasn't provided, * 'false' if it was relaunched* because of configuration update.*/
boolean ensureVisibilityAndConfig(ActivityRecord starting, int displayId,boolean markFrozenIfConfigChanged, boolean deferResume) {// First ensure visibility without updating the config just yet. // We need this to know what activities are affecting configuration now.// Passing null here for 'starting' param value, so that visibility of actual startingensureActivitiesVisible(null /* starting */, 0 /* configChanges */,false /* preserveWindows */, false /* notifyClients */);
}

继续看mService.getLifecycleManager().scheduleTransaction(clientTransaction);

//framework/base/services/core/java/com/android/server/wm/ClientLifecycleManager.java
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {final IApplicationThread client = transaction.getClient();transaction.schedule();if (!(client instanceof Binder)) {// If client is not an instance of Binder - it's a remote call and at this point it is// safe to recycle the object. All objects used for local calls will be recycled after// the transaction is executed on client in ActivityThread.transaction.recycle();}
}//framework/base/core/java/android/app/servertransaction/ClientTransaction.java
public void schedule() throws RemoteException {mClient.scheduleTransaction(this);
}//framework/base/core/java/android/app/ActivityThread.java
private class ApplicationThread extends IApplicationThread.Stub {@Overridepublic void scheduleTransaction(ClientTransaction transaction) throws RemoteException {ActivityThread.this.scheduleTransaction(transaction);}
}//framework/base/core/java/android/app/ClientTransactionHandler.java
/** Prepare and schedule transaction for execution. */
void scheduleTransaction(ClientTransaction transaction) {transaction.preExecute(this);sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}case EXECUTE_TRANSACTION:            
final ClientTransaction transaction = (ClientTransaction) msg.obj;
mTransactionExecutor.execute(transaction);
if (isSystem()) {// Client transactions inside system process are recycled on the client side// instead of ClientLifecycleManager to avoid being cleared before this// message is handled.transaction.recycle();
}
// TODO(lifecycler): Recycle locally scheduled transactions.
break;//framework/base/core/java/android/app/servertransaction/TransactionExecutor.java
public void executeCallbacks(ClientTransaction transaction) {for (int i = 0; i < size; ++i) {final ClientTransactionItem item = callbacks.get(i);item.execute(mTransactionHandler, token, mPendingActions);item.postExecute(mTransactionHandler, token, mPendingActions);}
}

这里执行的是ClientTransactionItem#execute

public abstract class ClientTransactionItem implements BaseClientRequest, Parcelable

这里ClientTransactionItem是一个抽象类,结合我们上面传入的是LaunchActivityItem,所以这里item就是LaunchActivityItem。

//framework/base/core/java/android/app/servertransaction/LaunchActivityItem.java
public class LaunchActivityItem extends ClientTransactionItem {@Overridepublic void execute(ClientTransactionHandler client, IBinder token,PendingTransactionActions pendingActions) {Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,mOverrideConfig, mReferrer, mVoiceInteractor, mState, mPersistentState,mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble,mTaskFragmentToken);client.handleLaunchActivity(r, pendingActions, mDeviceId, null /* customIntent */);Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);}
}

这里很清晰了,执行的是client.handleLaunchActivity

//framework/base/core/java/android/app/ActivityThread.java
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,PendingTransactionActions pendingActions,int deviceId, Intent customIntent) {final Activity a = performLaunchActivity(r, customIntent);
}private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {ContextImpl appContext = createBaseContextForActivity(r);Activity activity = null;try {java.lang.ClassLoader cl = appContext.getClassLoader();activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);StrictMode.incrementExpectedActivityCount(activity.getClass());r.intent.setExtrasClassLoader(cl);r.intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo),appContext.getAttributionSource());if (r.state != null) {r.state.setClassLoader(cl);}} Application app = r.packageInfo.makeApplicationInner(false, mInstrumentation);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,r.activityConfigCallback,r.assistToken, r.shareableActivityToken);r.activity = activity;if (r.isPersistable()) {mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);} else {mInstrumentation.callActivityOnCreate(activity, r.state);}
}

performLaunchActivity首先调用mInstrumentation的newActivity创建一个Activity。

public Activity newActivity(ClassLoader cl, String className, Intent intent)throws InstantiationException, IllegalAccessException, ClassNotFoundException {String pkg = intent != null && intent.getComponent() != null? intent.getComponent().getPackageName() : null;return getFactory(pkg).instantiateActivity(cl, className, intent);
}

getFactory(pkg)拿到的是一个AppComponentFactory

public @NonNull Activity instantiateActivity(@NonNull ClassLoader cl, @NonNull String className, @Nullable Intent intent)throws InstantiationException, IllegalAccessException, ClassNotFoundException {return (Activity) cl.loadClass(className).newInstance();
}

Activity创建之后,调用Application app = r.packageInfo.makeApplicationInner(false, mInstrumentation);

由于前面Application 已经创建了所以这里直接返回已经创建的Application。

2.10 Activity Create

继续看activity.attach。

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, r.activityConfigCallback,r.assistToken, r.shareableActivityToken);//framework/base/core/java/android/app/Activity.java
final void attach(Context context, ActivityThread aThread,Instrumentation instr, IBinder token, int ident,Application application, Intent intent, ActivityInfo info,CharSequence title, Activity parent, String id,NonConfigurationInstances lastNonConfigurationInstances,Configuration config, String referrer, IVoiceInteractor voiceInteractor,Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken, IBinder shareableActivityToken) {attachBaseContext(context);mWindow = new PhoneWindow(this, window, activityConfigCallback);mUiThread = Thread.currentThread();mMainThread = aThread;mWindow.setWindowManager((WindowManager)context.getSystemService(Context.WINDOW_SERVICE),mToken, mComponent.flattenToString(),(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
}

最后调用callActivityOnCreate。

//framework/base/core/java/android/app/Instrumentation.java
public void callActivityOnCreate(Activity activity, Bundle icicle) {prePerformCreate(activity);activity.performCreate(icicle);postPerformCreate(activity);
}//framework/base/core/java/android/app/Activity.java
final void performCreate(Bundle icicle) {performCreate(icicle, null);
}@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
final void performCreate(Bundle icicle, PersistableBundle persistentState) {if (persistentState != null) {onCreate(icicle, persistentState);} else {onCreate(icicle);}
}

至此,调用到了Activity的onCreate。

2.11 Activity Resume

回到ActivityTaskSupervisor#realStartActivityLocked,再activity创建设为地方也传入了ResumeActivityItem。

//framework/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
if (andResume) {lifecycleItem = ResumeActivityItem.obtain(isTransitionForward,r.shouldSendCompatFakeFocus());
} else {lifecycleItem = PauseActivityItem.obtain();
}//framework/base/core/java/android/app/servertransaction/TransactionExecutor.java
public void execute(ClientTransaction transaction) {executeCallbacks(transaction);executeLifecycleState(transaction);
}
public void executeCallbacks(ClientTransaction transaction) {for (int i = 0; i < size; ++i) {final ClientTransactionItem item = callbacks.get(i);item.execute(mTransactionHandler, token, mPendingActions);item.postExecute(mTransactionHandler, token, mPendingActions);}
}
/** Transition to the final state if requested by the transaction. */
private void executeLifecycleState(ClientTransaction transaction) {final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();// Execute the final transition with proper parameters.lifecycleItem.execute(mTransactionHandler, token, mPendingActions);lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}

执行完ClientTransaction之后,会执行ActivityLifecycleItem。

这里就执行ResumeActivityItem的execute、

//framework/base/core/java/android/app/servertransaction/ResumeActivityItem.java
@Override
public void execute(ClientTransactionHandler client, ActivityClientRecord r,PendingTransactionActions pendingActions) {Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityResume");client.handleResumeActivity(r, true /* finalStateRequest */, mIsForward,mShouldSendCompatFakeFocus, "RESUME_ACTIVITY");Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}//framework/base/core/java/android/app/ActivityThread.java
@Override
public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,boolean isForward, boolean shouldSendCompatFakeFocus, String reason) {if (!performResumeActivity(r, finalStateRequest, reason)) {return;}if (r.window == null && !a.mFinished && willBeVisible) {if (a.mVisibleFromClient) {if (!a.mWindowAdded) {a.mWindowAdded = true;wm.addView(decor, l);}}}if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {if (r.activity.mVisibleFromClient) {r.activity.makeVisible();}}mNewActivities.add(r);if (localLOGV) Slog.v(TAG, "Scheduling idle handler for " + r);Looper.myQueue().addIdleHandler(new Idler());
}
public boolean performResumeActivity(ActivityClientRecord r, boolean finalStateRequest, String reason) {r.activity.performResume(r.startsNotResumed, reason);
}final void performResume(boolean followedByPause, String reason) {// mResumed is set by the instrumentationmInstrumentation.callActivityOnResume(this);
}public void callActivityOnResume(Activity activity) {activity.mResumed = true;activity.onResume();if (mActivityMonitors != null) {synchronized (mSync) {final int N = mActivityMonitors.size();for (int i=0; i<N; i++) {final ActivityMonitor am = mActivityMonitors.get(i);am.match(activity, activity, activity.getIntent());}}}
}

这调用activity的onResume()。

3 流程图

在这里插入图片描述

本文完。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/377601.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度学习中激活函数的演变与应用:一个综述

摘要 本文全面回顾了深度学习中激活函数的发展历程,从早期的Sigmoid和Tanh函数,到广泛应用的ReLU系列,再到近期提出的Swish、Mish和GeLU等新型激活函数。深入分析了各类激活函数的数学表达、特点优势、局限性以及在典型模型中的应用情况。通过系统的对比分析,本文探讨了激…

实验二:图像灰度修正

目录 一、实验目的 二、实验原理 三、实验内容 四、源程序和结果 源程序(python): 结果: 五、结果分析 一、实验目的 掌握常用的图像灰度级修正方法,包括图象的线性和非线性灰度点运算和直方图均衡化法,加深对灰度直方图的理解。掌握对比度增强、直方图增强的原理,…

Git常用命令以及使用IDEA集成Gitee

目录 一、设置用户签名 二、初始化本地库 三、查看本地库状态 四、添加文件到暂存区 五、提交本地库 六、修改文件 七、版本穿梭 八、Git分支 九、分支的操作 9.1、查看分支 9.2、创建分支 9.3、切换分支 9.4、合并分支 十、团队协作 十一、Idea集成Git 11.1、配…

全球DeepFake攻防挑战赛DataWhale AI 夏令营——图像赛道

全球DeepFake攻防挑战赛&DataWhale AI 夏令营——图像赛道 赛题背景 随着人工智能技术的迅猛发展&#xff0c;深度伪造技术&#xff08;Deepfake&#xff09;正成为数字世界中的一把双刃剑。这项技术不仅为创意内容的生成提供了新的可能性&#xff0c;同时也对数字安全构…

CV12_ONNX转RKNN模型(谛听盒子)

暂时简单整理一下&#xff1a; 1.在边缘设备上配置相关环境。 2.配置完成后&#xff0c;获取模型中间的输入输出结果&#xff0c;保存为npy格式。 3.将onnx格式的模型&#xff0c;以及中间输入输出文件传送到边缘设备上。 4.编写一个python文件用于转换模型格式&#xff0c…

零售门店收银系统源码

php收银系统源码-CSDN博客文章浏览阅读268次&#xff0c;点赞6次&#xff0c;收藏4次。收银系统源码https://blog.csdn.net/qh716/article/details/140431477 1.系统开发语言 核心开发语言: PHP、HTML5、Dart后台接口: PHP7.3后合管理网站: HTML5vue2.0element-uicssjs线下收…

2023年高教杯数学建模2023B题解析(仅从代码角度出发)

前言 最近博主正在和队友准备九月的数学建模,在做往年的题目&#xff0c;博主主要是负责数据处理&#xff0c;运算以及可视化&#xff0c;这里分享一下自己部分的工作,相关题目以及下面所涉及的代码后续我会作为资源上传 问题求解 第一题 第一题的思路主要如下&#xff1a;…

win10远程ubuntu服务器桌面且显示图像窗口工具及配置说明

仅需一个MobaXterm_Personal工具就可以实现 网上的教程比较多&#xff0c;实现起来比较复杂&#xff0c;这个是经过自己的钻研找到的方法&#xff08;请勿转载和抄袭&#xff09; 报错&#xff1a;cannot connect to X server :0.0 操作1&#xff1a;export DISPLAY自己windo…

数学建模·熵权法

熵权法 一种计算评价指标之间权重的方法。熵权法是一种客观的方法&#xff0c;没有主观性&#xff0c;比较可靠。 具体定义 熵权法的核心在于计算信息熵&#xff0c;信息熵反映了一个信息的紊乱程度&#xff0c;体现了信息的可靠性 具体步骤 Step1正向化处理 将所以评价指标转…

玩客云刷入海纳思系统

玩客云(晶晨S805)刷机 | 海纳思系统 (ecoo.top) https://www.ecoo.top/update/soft_init/amlproject/USB_Burning_Tool_v2.1.3.exe https://node4.histb.com:9088/update/system/s805/hinas_s805_eMMC.burn.img.zip

LabVIEW液压数据采集测试系统

液压系统是装载机的重要组成部分&#xff0c;通过液压传动和控制实现各项作业功能&#xff0c;如提升、倾斜、转向等。液压系统的性能直接影响装载机的作业效率和稳定性。为了保证装载机液压系统的正常运行和优化设计&#xff0c;需要对其进行数据采集和测试。本文介绍了一套基…

Wireshark 对 https 请求抓包并展示为明文

文章目录 1、目标2、环境准备3、Wireshark 基本使用4、操作步骤4.1、彻底关闭 Chrome 进程4.2、配置 SSLKEYLOGFILE [核心步骤]4.3、把文件路径配置到 Wireshark 指定位置4.4、在浏览器发起请求4.5、抓包配置4.6、过滤4.6.1、过滤域名 http.host contains "baidu.com4.6.2…

通用图形处理器设计GPGPU基础与架构(三)

一、前言 前两篇已经介绍了 GPGPU 的背景 和 GPGPU 的编程模型相关的内容&#xff0c;本文将在 SIMT 计算模型的基础上&#xff0c;介绍 GPGPU 控制核心架构和微体系结构的设计。 二、CPU-GPGPU 异构计算系统 一个由 CPU 和 GPGPU 构成的异构计算平台如下图所示&#xff0c;GP…

树结构添加分组,向上向下添加同级,添加子级

树结构添加分组&#xff0c;向上向下添加同级&#xff0c;添加子级 效果代码实现页面js 效果 代码实现 页面 <el-tree :data"treeData" :props"defaultProps" :expand-on-click-node"false":filter-node-method"filterNode" :ref&…

Hive的基本操作(查询)

1、基础查询 基本语法 select 字段列表|表达式|子查询 from 表(子查询|视图|临时表|普通表) where [not] 条件A and|or 条件B --先&#xff1a;面向原始行进行筛选 group by 字段A[,字段B,...] > 分组【去重处理】 having 聚合条件(非原始字段条件) --再&#x…

iPhone数据恢复:如何从iPhone恢复误删除的短信

来自iPhone的意外删除的短信可能很关键。它们可能是来自您常用应用程序、银行交易、付款收据的重要通知&#xff0c;也可能是来自朋友的重要文本、孩子的学校通知等。 如果您也从iPhone丢失了此类消息&#xff0c;我们在这里分享如何在没有备份以及有备份的情况下在iPhone上恢…

热门软件缺陷管理工具2024:专业评测与建议

国内外主流的10款软件缺陷管理工具软件对比&#xff1a;PingCode、Worktile、禅道、Tapd、Teambition、Tower、JIRA、Bugzilla、MantisBT、Trac。 在软件开发过程中&#xff0c;管理缺陷和漏洞常常成为一项挑战&#xff0c;尤其是在项目规模庞大时。选择一个高效的软件缺陷管理…

object-C 解答算法:两数之和(leetCode-1)

两数之和(leetCode-1) 题目如下图:(也可以到leetCode上看完整题目,题号1) 解答方法一: 最简单的方法就是双指针遍历数组.代码如下 - (NSMutableArray *)sumOfTwoNumbers:(NSMutableArray *)array target:(int)target {NSMutableArray * resultArray [[NSMutableArray alloc…

探索Facebook在人工智能领域的最新进展

在当今快速发展的科技领域中&#xff0c;人工智能&#xff08;AI&#xff09;作为一项关键技术&#xff0c;正在逐步改变着社交媒体的面貌。作为全球最大的社交平台之一&#xff0c;Facebook积极探索和应用人工智能&#xff0c;以提升用户体验、增强平台安全性并推动技术创新。…

数学建模·灰色关联度

灰色关联分析 基本原理 灰色关联分析可以确定一个系统中哪些因素是主要因素&#xff0c;哪些是次要因素&#xff1b; 灰色关联分析也可以用于综合评价&#xff0c;但是由于数据预处理的方式不同&#xff0c;导致结果 有较大出入 &#xff0c;故一般不采用 具体步骤 数据预处理…