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 starts
mSupervisor.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 中:
<activity
android: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); // 1
try {
if (pid == 0) {
// in child
zygoteServer.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 一般是 false
return 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 main
return 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 interception
AndroidOs.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 certificates
final 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(new
LogPrinter(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 debugger
Process.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/36951662
if (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 discrepancies
NetworkSecurityConfigProvider.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> {
@Override
public 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> {
@Override
public 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 starting
ensureActivitiesVisible(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 {
@Override
public 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 {
@Override
public 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 instrumentation
mInstrumentation.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 流程图
本文完。
本站资源均来自互联网,仅供研究学习,禁止违法使用和商用,产生法律纠纷本站概不负责!如果侵犯了您的权益请与我们联系!
转载请注明出处: 免费源码网-免费的源码资源网站 » Activity启动流程
发表评论 取消回复