源码分析系列:app启动流程-进程创建
作为一个Android开发者,不了解Android启动流程,app启动流程,难免有点掉相,而且面试中也是经常被问到这一块的内容,掌握这些知识必将为自己增加竞争的筹码。之前断断续续看了一些文章,但大多都比较古老,并且很多都是抄来抄去的,很多关键的细节都没有讲清楚,比如zygote进程是如何调用app进程的main()方法的。此系列文章将带你彻底掌握Android启动->app启动。
本篇主要分析app的启动流程--进程创建,基于Android 11。
整体流程预览
Launcher3进程
首先我们启动app都是通过点击桌面的app图标来启动的,而桌面其实也是一个app,名叫Launcher3,它是一个System app,并且这个app只有一个Activity,就是我们看到的桌面界面,其源码位于packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
,它的继承关系是这样的
/**
* Default launcher application.
*/
public class Launcher extends StatefulActivity<LauncherState> implements LauncherExterns,
Callbacks, InvariantDeviceProfile.OnIDPChangeListener, PluginListener<OverlayPlugin> {
//省略部分代码
}
/**
* Abstract activity with state management
* @param <STATE_TYPE> Type of state object
*/
public abstract class StatefulActivity<STATE_TYPE extends BaseState<STATE_TYPE>>
extends BaseDraggingActivity {
}
/**
* Extension of BaseActivity allowing support for drag-n-drop
*/
public abstract class BaseDraggingActivity extends BaseActivity
implements WallpaperColorInfo.OnChangeListener, DisplayInfoChangeListener {
}
/**
* Launcher BaseActivity
*/
public abstract class BaseActivity extends Activity implements ActivityContext {
}
在我们点击桌面app图标时,触发点击事件,执行ItemClickHandler
中OnClickListener
的onClick()
方法
private static void onClick(View v, String sourceContainer) {
// Make sure that rogue clicks don't get through while allapps is launching, or after the
// view has detached (it's possible for this to happen if the view is removed mid touch).
if (v.getWindowToken() == null) return;
Launcher launcher = Launcher.getLauncher(v.getContext());
if (!launcher.getWorkspace().isFinishedSwitchingState()) return;
Object tag = v.getTag();
if (tag instanceof WorkspaceItemInfo) {
//点击快捷方式
onClickAppShortcut(v, (WorkspaceItemInfo) tag, launcher, sourceContainer);
} else if (tag instanceof FolderInfo) {
if (v instanceof FolderIcon) {
//点击分类文件夹
onClickFolderIcon(v);
}
} else if (tag instanceof AppInfo) {
//点击app
startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher,
sourceContainer == null ? CONTAINER_ALL_APPS: sourceContainer);
} else if (tag instanceof LauncherAppWidgetInfo) {
if (v instanceof PendingAppWidgetHostView) {
//点击桌面小控件
onClickPendingWidget((PendingAppWidgetHostView) v, launcher);
}
}
}
当点击app时执行startAppShortcutOrInfoActivity()
private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher,
@Nullable String sourceContainer) {
//省略部分代码
//执行Launcher中的方法
launcher.startActivitySafely(v, intent, item, sourceContainer);
}
@Override
public boolean startActivitySafely(View v, Intent intent, ItemInfo item,
@Nullable String sourceContainer) {
//省略部分代码
//执行父类BaseDraggingActivity的方法
boolean success = super.startActivitySafely(v, intent, item, sourceContainer);
if (success && v instanceof BubbleTextView) {
// This is set to the view that launched the activity that navigated the user away
// from launcher. Since there is no callback for when the activity has finished
// launching, enable the press state and keep this reference to reset the press
// state when we return to launcher.
BubbleTextView btv = (BubbleTextView) v;
btv.setStayPressed(true);
addOnResumeCallback(btv);
}
return success;
}
public boolean startActivitySafely(View v, Intent intent, @Nullable ItemInfo item,
@Nullable String sourceContainer) {
//省略部分代码
try {
boolean isShortcut = (item instanceof WorkspaceItemInfo)
&& (item.itemType == Favorites.ITEM_TYPE_SHORTCUT
|| item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)
&& !((WorkspaceItemInfo) item).isPromise();
if (isShortcut) {
// Shortcuts need some special checks due to legacy reasons.
startShortcutIntentSafely(intent, optsBundle, item, sourceContainer);
} else if (user == null || user.equals(Process.myUserHandle())) {
// Could be launching some bookkeeping activity
//执行父类Activity的startActivity()
startActivity(intent, optsBundle);
AppLaunchTracker.INSTANCE.get(this).onStartApp(intent.getComponent(),
Process.myUserHandle(), sourceContainer);
//省略部分代码
}
//省略部分代码
return false;
}
可以看到最终也是执行了Activity的startActivity()
方法,这很好理解,启动app,无非就是先创建app进程,然后创建第一个Activity,也就是我们在AndroidManifest.xml里面配置了android.intent.category.LAUNCHER
的Activity。下面具体分析一下startActivity()
的执行流程,看看系统是如何创建进程和Activity的
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
//省略部分代码
if (options != null) {
//继续调用startActivityForResult()
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) {
//启动app时,因为是启动的第一个activity,所以mParent为空
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
//执行Instrumentation的execStartActivity
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
//向ActivityThread发送上一步的返回值
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
//省略部分代码
} else {
//省略部分代码
}
}
这里执行了两步操作
- 通过Instrumentation得到创建Activity所需要的配置项ActivityResult
- 向ActivityThread发送ActivityResult数据,从而创建Activity
先看看mInstrumentation.execStartActivity()
@UnsupportedAppUsage
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
//省略部分代码
try {
intent.migrateExtraStreamToClipData(who);
intent.prepareToLeaveProcess(who);
//aidl调用远程ActivityTaskManagerService的方法
int result = ActivityTaskManager.getService().startActivity(whoThread,
who.getBasePackageName(), who.getAttributionTag(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()), token,
target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
SystemServer进程
这里远程调用了ActivityTaskManagerService
的功能,ActivityTaskManager.getService()
得到IActivityTaskManager
,它是ActivityTaskManagerService
的binder引用,看看ActivityTaskManagerService
对startActivity()
的实现逻辑
@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) {
//调用startActivityAsUser
return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
@Override
public int startActivityAsUser(IApplicationThread caller, String callingPackage,
String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
Bundle bOptions, int userId) {
//调用startActivityAsUser重载方法
return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
true /*validateIncomingUser*/);
}
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) {
assertPackageMatchesCallingUid(callingPackage);
enforceNotIsolatedCaller("startActivityAsUser");
userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
// TODO: Switch to user app stacks here.
//获取ActivityStartController,进而获取ActivityStarter,然后交由ActivityStarter来完成
return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
.setCaller(caller)
.setCallingPackage(callingPackage)
.setCallingFeatureId(callingFeatureId)
.setResolvedType(resolvedType)
.setResultTo(resultTo)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
.setProfilerInfo(profilerInfo)
.setActivityOptions(bOptions)
.setUserId(userId)
.execute();
}
ActivityTaskManagerService
的startActivity()
最终交由ActivityStarter
来完成,首先是一系列Activity的配置,最后执行execute()
@VisibleForTesting
Request mRequest = new Request();
int execute() {
try {
//省略部分代码
synchronized (mService.mGlobalLock) {
//省略部分代码
//通知Activity正在启动
launchingState = mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(
mRequest.intent, caller);
}
//执行创建Activity的请求
res = executeRequest(mRequest);
//省略部分代码
// Notify ActivityMetricsLogger that the activity has launched.
// ActivityMetricsLogger will then wait for the windows to be drawn and populate
// WaitResult.
//通知Activity启动完成
mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState, res,
mLastStartActivityRecord);
//省略部分代码
} finally {
onExecutionComplete();
}
}
executeRequest()
方法代码比较多,大概360行代码,源码对其有注释,我将翻译贴出来
/**
* 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}.
* 执行Activity启动请求并开始启动Activity的旅程。这里从执行几个初步检查开始。正常的活动启动流将经过{@link #startActivityUnchecked}到{@link #startActivityInner}。
*/
private int executeRequest(Request request) {
if (TextUtils.isEmpty(request.reason)) {
throw new IllegalArgumentException("Need to specify a reason.");
}
//省略部分代码
final ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
callingPackage, callingFeatureId, intent, resolvedType, aInfo,
mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode,
request.componentSpecified, voiceSession != null, mSupervisor, checkedOptions,
sourceRecord);
mLastStartActivityRecord = r;
//省略部分代码
mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,
restrictedBgActivity, intentGrants);
if (request.outActivity != null) {
request.outActivity[0] = mLastStartActivityRecord;
}
return mLastStartActivityResult;
}
方法主要是进行各种参数检查,已经构建创建Activity所需要的参数,比如ActivityRecord
,最后执行startActivityUnchecked()
,然后按照方法注释的说明,执行完startActivityUnchecked()
,它应该继续执行startActivityInner()
,我们看看是否是这样的顺序
/**
* 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, boolean doResume, ActivityOptions options, Task inTask,
boolean restrictedBgActivity, NeededUriGrants intentGrants) {
int result = START_CANCELED;
final ActivityStack startedActivityStack;
try {
mService.deferWindowLayout();
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
//执行startActivityInner
result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
startedActivityStack = handleStartResult(r, result);
mService.continueWindowLayout();
}
postStartActivityProcessing(r, result, startedActivityStack);
return result;
}
果然执行了startActivityInner()
,这个方法内容也很多,主要功能也在注释里说明了
/**
* 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 stack/display.
*
* Note: This method should only be called from {@link #startActivityUnchecked}.
* 启动一个activity,并确定该activity是应该添加到现有任务的顶部,还是应该向现有activity交付新的意图。还操作activity任务到请求的或有效的堆栈/显示。
*/
// 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, boolean doResume, ActivityOptions options, Task inTask,
boolean restrictedBgActivity, NeededUriGrants intentGrants) {
//省略部分代码
if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
if (!mTargetStack.isTopActivityFocusable()
|| (topTaskActivity != null && topTaskActivity.isTaskOverlay()
&& mStartActivity != topTaskActivity)) {
//省略部分代码
} else {
// If the target stack was not previously focusable (previous top running activity
// on that stack was not visible) then any prior calls to move the stack to the
// will not update the focused stack. If starting the new activity now allows the
// task stack to be focusable, then ensure that we now update the focused stack
// accordingly.
if (mTargetStack.isTopActivityFocusable()
&& !mRootWindowContainer.isTopDisplayFocusedStack(mTargetStack)) {
mTargetStack.moveToFront("startActivityInner");
}
//将目标Activity Stack的移到前台显示
mRootWindowContainer.resumeFocusedStacksTopActivities(
mTargetStack, mStartActivity, mOptions);
}
}
//更新Activity Stack
mRootWindowContainer.updateUserStack(mStartActivity.mUserId, mTargetStack);
// Update the recent tasks list immediately when the activity starts
//将Activity Stack添加到最新任务列表
mSupervisor.mRecentTasks.add(mStartActivity.getTask());
mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(),
mPreferredWindowingMode, mPreferredTaskDisplayArea, mTargetStack);
return START_SUCCESS;
}
这里主要是处理Activity Stack,我们知道,Activity需要用Activity Stack来存放,resumeFocusedStacksTopActivities()
先将目标Activity Stack移到前台,然后创建好Activity后放到Stack里,用户就能直接看到了,所以,创建Activity的逻辑还在resumeFocusedStacksTopActivities()中
boolean resumeFocusedStacksTopActivities(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (!mStackSupervisor.readyToResume()) {
return false;
}
boolean result = false;
if (targetStack != null && (targetStack.isTopStackInDisplayArea()
|| getTopDisplayFocusedStack() == targetStack)) {
//执行resumeTopActivityUncheckedLocked()
result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
//省略部分代码
return result;
}
@GuardedBy("mService")
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
if (mInResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean result = false;
try {
// Protect against recursion.
mInResumeTopActivity = true;
//执行resumeTopActivityInnerLocked()
result = resumeTopActivityInnerLocked(prev, options);
// When resuming the top activity, it may be necessary to pause the top activity (for
// example, returning to the lock screen. We suppress the normal pause logic in
// {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the
// end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here
// to ensure any necessary pause logic occurs. In the case where the Activity will be
// shown regardless of the lock screen, the call to
// {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped.
final ActivityRecord next = topRunningActivity(true /* focusableOnly */);
if (next == null || !next.canTurnScreenOn()) {
checkReadyForSleep();
}
} finally {
mInResumeTopActivity = false;
}
return result;
}
@GuardedBy("mService")
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
if (!mAtmService.isBooting() && !mAtmService.isBooted()) {
// Not ready yet!
return false;
}
// Find the next top-most activity to resume in this stack that is not finishing and is
// focusable. If it is not focusable, we will fall into the case below to resume the
// top activity in the next focusable task.
ActivityRecord next = topRunningActivity(true /* focusableOnly */);
//省略部分代码
if (next.attachedToProcess()) {
//省略部分代码
//执行startSpecificActivity()
mStackSupervisor.startSpecificActivity(next, true, false);
return true;
//省略部分代码
} else {
// Whoops, need to restart this activity!
if (!next.hasBeenLaunched) {
next.hasBeenLaunched = true;
} else {
if (SHOW_APP_STARTING_PREVIEW) {
next.showStartingWindow(null /* prev */, false /* newTask */,
false /* taskSwich */);
}
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
}
if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
//执行startSpecificActivity()
mStackSupervisor.startSpecificActivity(next, true, true);
}
return true;
}
最终都执行startSpecificActivity()
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);
boolean knownToBeDead = false;
//判断app有没有启动,如果已经启动了,则直接启动Activity
if (wpc != null && wpc.hasThread()) {
try {
realStartActivityLocked(r, wpc, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
knownToBeDead = true;
}
r.notifyUnknownVisibilityLaunchedForKeyguardTransition();
final boolean isTop = andResume && r.isTopRunningActivity();
//app没有启动,说明是第一次启动,则需要先创建进程
mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
}
wpc.hasThread()
返回的是IApplicationThread
,它是ActivityThread.ApplicationThread
的binder引用,只有app启动之后才会创建ActivityThread.ApplicationThread
对象,所以第一次启动app时,wpc.hasThread()
显然不满足条件,那么就执行启动逻辑,首先要启动app进程,看看startProcessAsync()
void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,
String hostingType) {
try {
if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "dispatchingStartProcess:"
+ activity.processName);
}
// 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);
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
通过Handler发送了一条Message,最终在ActivityManagerInternal.startProcess()
中处理此Message
/** Starts a given process. */
public abstract void startProcess(String processName, ApplicationInfo info,
boolean knownToBeDead, boolean isTop, String hostingType, ComponentName hostingName);
startProcess()
是一个抽象方法,由ActivityManagerInternal
的子类ActivityManagerService.LocalService
实现
@Override
public void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead,
boolean isTop, String hostingType, ComponentName hostingName) {
try {
if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "startProcess:"
+ processName);
}
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.
//执行AMS的startProcessLocked()
startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
new HostingRecord(hostingType, hostingName, isTop),
ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false /* allowWhileBooting */,
false /* isolated */, true /* keepIfLarge */);
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
@GuardedBy("this")
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,
boolean isolated, boolean keepIfLarge) {
//执行ProcessList.startProcessLocked()
return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,
keepIfLarge, null /* ABI override */, null /* entryPoint */,
null /* entryPointArgs */, null /* crashHandler */);
}
@GuardedBy("mService")
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord,
int zygotePolicyFlags, boolean allowWhileBooting, boolean isolated, int isolatedUid,
boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs,
Runnable crashHandler) {
long startTime = SystemClock.uptimeMillis();
ProcessRecord app;
//省略部分源码
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;
}
此方法中,先构建创建进程所需要的配置ProcessRecord
,然后执行startProcessLocked()
重载方法
@GuardedBy("mService")
final boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
int zygotePolicyFlags, String abiOverride) {
//执行startProcessLocked()重载方法
return startProcessLocked(app, hostingRecord, zygotePolicyFlags,
false /* disableHiddenApiChecks */, false /* disableTestApiChecks */,
false /* mountExtStorageFull */, abiOverride);
}
/**
* @return {@code true} if process start is successful, false otherwise.
*/
@GuardedBy("mService")
boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks,
boolean mountExtStorageFull, String abiOverride) {
//省略部分代码
try {
//省略部分代码
//执行startProcessLocked()重载方法
return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,
instructionSet, invokeWith, startTime);
} catch (RuntimeException e) {
Slog.e(ActivityManagerService.TAG, "Failure starting process " + app.processName, e);
// Something went very wrong while trying to start this process; one
// common case is when the package is frozen due to an active
// upgrade. To recover, clean up any active bookkeeping related to
// starting this process. (We already invoked this method once when
// the package was initially frozen through KILL_APPLICATION_MSG, so
// it doesn't hurt to use it again.)
mService.forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
false, false, true, false, false, app.userId, "start failure");
return false;
}
}
@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 startTime) {
//省略部分代码
if (mService.mConstants.FLAG_PROCESS_START_ASYNC) {
//异步启动进程
if (DEBUG_PROCESSES) Slog.i(TAG_PROCESSES,
"Posting procStart msg for " + app.toShortString());
//处理进程启动,最终还是调用的startProcess()
mService.mProcStartHandler.post(() -> handleProcessStart(
app, entryPoint, gids, runtimeFlags, zygotePolicyFlags, mountExternal,
requiredAbi, instructionSet, invokeWith, startSeq));
return true;
} else {
//同步启动进程
try {
//启动进程
final Process.ProcessStartResult startResult = startProcess(hostingRecord,
entryPoint, app,
uid, gids, runtimeFlags, zygotePolicyFlags, mountExternal, seInfo,
requiredAbi, instructionSet, invokeWith, startTime);
handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
startSeq, false);
} catch (RuntimeException e) {
//省略部分代码
}
return app.pid > 0;
}
}
无论是同步启动还是异步启动,最终都是执行的ProcessList.startProcess()
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) {
try {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
app.processName);
//请求zygote开启进程
checkSlow(startTime, "startProcess: asking zygote to start proc");
//省略部分代码
final Process.ProcessStartResult startResult;
//根据进程的类型,用不同的方式创建
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.mDisabledCompatChanges,
new String[]{PROC_START_SEQ_IDENT + app.startSeq});
} 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.mDisabledCompatChanges, pkgDataInfoMap, whitelistedAppDataInfoMap,
false, false,
new String[]{PROC_START_SEQ_IDENT + app.startSeq});
} else {
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.mDisabledCompatChanges, pkgDataInfoMap,
whitelistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,
new String[]{PROC_START_SEQ_IDENT + app.startSeq});
}
checkSlow(startTime, "startProcess: returned from zygote!");
return startResult;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
hostingRecord描述了启动一个进程所需要的各种信息,根据进程类型的不同,用不同的方式创建,普通app的进程由Process.start()
创建
/**
* State associated with the zygote process.
* @hide
*/
public static final ZygoteProcess ZYGOTE_PROCESS = new ZygoteProcess();
public static ProcessStartResult start(@NonNull final String processClass,
@Nullable 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>>
whitelistedDataInfoMap,
boolean bindMountAppsData,
boolean bindMountAppStorageDirs,
@Nullable String[] zygoteArgs) {
//调用zygoteProcess的方法
return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, packageName,
zygotePolicyFlags, isTopApp, disabledCompatChanges,
pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData,
bindMountAppStorageDirs, zygoteArgs);
}
Process.start()
又调用了ZygoteProcess.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>>
whitelistedDataInfoMap,
boolean bindMountAppsData,
boolean bindMountAppStorageDirs,
@Nullable String[] zygoteArgs) {
// TODO (chriswailes): Is there a better place to check this value?
if (fetchUsapPoolEnabledPropWithMinInterval()) {
informZygotesOfUsapPoolStatus();
}
try {
//调用startViaZygote()
return startViaZygote(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges,
pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData,
bindMountAppStorageDirs, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
throw new RuntimeException(
"Starting VM process through Zygote failed", ex);
}
}
private Process.ProcessStartResult startViaZygote(@NonNull final String processClass,
@Nullable final String niceName,
final int uid, final int gid,
@Nullable final int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
@Nullable String seInfo,
@NonNull String abi,
@Nullable String instructionSet,
@Nullable String appDataDir,
@Nullable String invokeWith,
boolean startChildZygote,
@Nullable String packageName,
int zygotePolicyFlags,
boolean isTopApp,
@Nullable long[] disabledCompatChanges,
@Nullable Map<String, Pair<String, Long>>
pkgDataInfoMap,
@Nullable Map<String, Pair<String, Long>>
whitelistedDataInfoMap,
boolean bindMountAppsData,
boolean bindMountAppStorageDirs,
@Nullable String[] extraArgs)
throws ZygoteStartFailedEx {
//收集进程参数
ArrayList<String> argsForZygote = new ArrayList<>();
// --runtime-args, --setuid=, --setgid=,
// and --setgroups= must go first
argsForZygote.add("--runtime-args");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
argsForZygote.add("--runtime-flags=" + runtimeFlags);
//省略部分代码
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.
//想zygote进程发送要创建的进程参数
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
zygotePolicyFlags,
argsForZygote);
}
}
@GuardedBy("mLock")
private Process.ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, int zygotePolicyFlags, @NonNull ArrayList<String> args)
throws ZygoteStartFailedEx {
// Throw early if any of the arguments are malformed. This means we can
// avoid writing a partial response to the zygote.
//校验参数
for (String arg : args) {
// Making two indexOf calls here is faster than running a manually fused loop due
// to the fact that indexOf is a optimized intrinsic.
if (arg.indexOf('\n') >= 0) {
throw new ZygoteStartFailedEx("Embedded newlines not allowed");
} else if (arg.indexOf('\r') >= 0) {
throw new ZygoteStartFailedEx("Embedded carriage returns not allowed");
}
}
//省略部分代码
//调用attemptZygoteSendArgsAndGetResult()
return attemptZygoteSendArgsAndGetResult(zygoteState, msgStr);
}
private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult(
ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx {
try {
final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;
final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;
//向zygote进程发送数据
zygoteWriter.write(msgStr);
zygoteWriter.flush();
// Always read the entire result from the input stream to avoid leaving
// bytes in the stream for future process starts to accidentally stumble
// upon.
//获取zygote进程返回的启动结果
Process.ProcessStartResult result = new Process.ProcessStartResult();
result.pid = zygoteInputStream.readInt();
result.usingWrapper = zygoteInputStream.readBoolean();
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
return result;
} catch (IOException ex) {
zygoteState.close();
Log.e(LOG_TAG, "IO Exception while communicating with Zygote - "
+ ex.toString());
throw new ZygoteStartFailedEx(ex);
}
}
Zygote进程
在最后的attemptZygoteSendArgsAndGetResult()
方法中,通过输入流向zygote进程发送数据,实际上这里是通过socket通信来完成的,我们知道常用的进程通信的方式有两种,binder和socket,在上面方法中有一个重要的参数ZygoteState
,它是ZygoteProcess的内部类,定义了zygote服务端的地址以及IO通道,作用就是跟zygote进程进行通信,详见类定义
/**
* State for communicating with the zygote process.
*/
private static class ZygoteState implements AutoCloseable {
//zygote服务端地址
final LocalSocketAddress mZygoteSocketAddress;
final LocalSocketAddress mUsapSocketAddress;
//定义socket通道
private final LocalSocket mZygoteSessionSocket;
//定义IO通道
final DataInputStream mZygoteInputStream;
final BufferedWriter mZygoteOutputWriter;
private final List<String> mAbiList;
private boolean mClosed;
private ZygoteState(LocalSocketAddress zygoteSocketAddress,
LocalSocketAddress usapSocketAddress,
LocalSocket zygoteSessionSocket,
DataInputStream zygoteInputStream,
BufferedWriter zygoteOutputWriter,
List<String> abiList) {
this.mZygoteSocketAddress = zygoteSocketAddress;
this.mUsapSocketAddress = usapSocketAddress;
this.mZygoteSessionSocket = zygoteSessionSocket;
this.mZygoteInputStream = zygoteInputStream;
this.mZygoteOutputWriter = zygoteOutputWriter;
this.mAbiList = abiList;
}
/**
* Create a new ZygoteState object by connecting to the given Zygote socket and saving the
* given USAP socket address.
*
* @param zygoteSocketAddress Zygote socket to connect to
* @param usapSocketAddress USAP socket address to save for later
* @return A new ZygoteState object containing a session socket for the given Zygote socket
* address
* @throws IOException
*/
static ZygoteState connect(@NonNull LocalSocketAddress zygoteSocketAddress,
@Nullable LocalSocketAddress usapSocketAddress)
throws IOException {
DataInputStream zygoteInputStream;
BufferedWriter zygoteOutputWriter;
final LocalSocket zygoteSessionSocket = new LocalSocket();
if (zygoteSocketAddress == null) {
throw new IllegalArgumentException("zygoteSocketAddress can't be null");
}
try {
zygoteSessionSocket.connect(zygoteSocketAddress);
zygoteInputStream = new DataInputStream(zygoteSessionSocket.getInputStream());
zygoteOutputWriter =
new BufferedWriter(
new OutputStreamWriter(zygoteSessionSocket.getOutputStream()),
Zygote.SOCKET_BUFFER_SIZE);
} catch (IOException ex) {
try {
zygoteSessionSocket.close();
} catch (IOException ignore) { }
throw ex;
}
return new ZygoteState(zygoteSocketAddress, usapSocketAddress,
zygoteSessionSocket, zygoteInputStream, zygoteOutputWriter,
getAbiList(zygoteOutputWriter, zygoteInputStream));
}
LocalSocket getUsapSessionSocket() throws IOException {
final LocalSocket usapSessionSocket = new LocalSocket();
usapSessionSocket.connect(this.mUsapSocketAddress);
return usapSessionSocket;
}
boolean matches(String abi) {
return mAbiList.contains(abi);
}
public void close() {
try {
mZygoteSessionSocket.close();
} catch (IOException ex) {
Log.e(LOG_TAG,"I/O exception on routine close", ex);
}
mClosed = true;
}
boolean isClosed() {
return mClosed;
}
}
按照socket的通信规则,服务端必定会有一个死循环时刻去轮训客户端发送过来的消息,此方法就是ZygoteServer.runSelectLoop()
/**
* Runs the zygote process's select loop. Accepts new connections as
* they happen, and reads commands from connections one spawn-request's
* worth at a time.
*/
Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> socketFDs = new ArrayList<>();
ArrayList<ZygoteConnection> peers = new ArrayList<>();
socketFDs.add(mZygoteSocket.getFileDescriptor());
peers.add(null);
mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
//来一个死循环,不断轮训客户端发来的数据
while (true) {
//省略部分代码
// Session socket accepted from the Zygote server socket
try {
ZygoteConnection connection = peers.get(pollIndex);
//从socket中读取启动命令,并执行
final Runnable command = connection.processOneCommand(this);
//省略部分代码
return command;
//省略部分代码
} catch (Exception e) {
} finally {
}
//省略部分代码
}
}
runSelectLoop()
方法在zygote进程启动时被调用,见ZygoteInit
@UnsupportedAppUsage
public static void main(String argv[]) {
ZygoteServer zygoteServer = null;
// Mark zygote start. This ensures that thread creation will throw
// an error.
//启动Zygote进程
ZygoteHooks.startZygoteNoThreadCreation();
//省略部分代码
Zygote.initNativeState(isPrimaryZygote);
ZygoteHooks.stopZygoteNoThreadCreation();
zygoteServer = new ZygoteServer(isPrimaryZygote);
if (startSystemServer) {
//启动system server
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) {
r.run();
return;
}
}
Log.i(TAG, "Accepting command socket connections");
// The select loop returns early in the child process after a fork and
// loops forever in the zygote.
//开启socket轮训,返回一个runnable
caller = zygoteServer.runSelectLoop(abiList);
//省略部分代码
// We're in the child process and have exited the select loop. Proceed to execute the
// command.
//代码1:执行runnable的run方法
if (caller != null) {
caller.run();
}
}
轮训到客户端要创建进程的消息,会执行创建进程的命令,也就是调用processOneCommand()
Runnable processOneCommand(ZygoteServer zygoteServer) {
String[] args;
//读取要创建的进程参数
try {
args = Zygote.readArgumentList(mSocketReader);
} catch (IOException ex) {
throw new IllegalStateException("IOException on command socket", ex);
}
//省略部分代码
//创建进程,得到进程id
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.mWhitelistedDataInfoList,
parsedArgs.mBindMountAppDataDirs, parsedArgs.mBindMountAppStorageDirs);
try {
if (pid == 0) {
// in child
//如果pid为0,说明是idle进程,此时需要继续创建其子进程,也就是我们的目标进程
zygoteServer.setForkChild();
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
//处理子进程的创建
return handleChildProc(parsedArgs, childPipeFd, parsedArgs.mStartChildZygote);
} else {
// In the parent. A pid < 0 indicates a failure and will be handled in
// handleParentProc.
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
//处理父进程的创建
handleParentProc(pid, serverPipeFd);
return null;
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
通过Zygote.forkAndSpecialize()创建一个进程,得到进程id,如果进程id为0,说明目标进程运行在父进程中,需要继续处理子进程的启动
private Runnable handleChildProc(ZygoteArguments parsedArgs,
FileDescriptor pipeFd, boolean isZygote) {
/*
* By the time we get here, the native code has closed the two actual Zygote
* socket connections, and substituted /dev/null in their place. The LocalSocket
* objects still need to be closed properly.
*/
closeSocket();
//设置app进程名称
Zygote.setAppProcessName(parsedArgs, TAG);
// End of the postFork event.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
if (parsedArgs.mInvokeWith != null) {
WrapperInit.execApplication(parsedArgs.mInvokeWith,
parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
VMRuntime.getCurrentInstructionSet(),
pipeFd, parsedArgs.mRemainingArgs);
// Should not get here.
throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
} else {
if (!isZygote) {
//执行app进程的初始化
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mDisabledCompatChanges,
parsedArgs.mRemainingArgs, null /* classLoader */);
} else {
return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mRemainingArgs, null /* classLoader */);
}
}
}
public static final 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();
//在native层初始化
ZygoteInit.nativeZygoteInit();
//执行app的初始化,也就是调用main函数
return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
classLoader);
}
目标进程的创建是在native层完成,在AndroidRuntime.cpp
中
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}
onZygoteInit()
实现在app_main.cpp
中
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
进程创建完,就要开始执行它的main()
方法了,看RuntimeInit.applicationInit()
是如何调用main()
方法的
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
//寻找静态main方法
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
//通过反射找到main方法,
Class<?> cl;
//打印看看是调用的哪个类的main方法
Log.d("jasonwan","className="+className);
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);
}
//main方法必须是public static
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.
*/
//构建一个MethodAndArgsCaller,包含main方法和其参数
return new MethodAndArgsCaller(m, argv);
}
最终返回的MethodAndArgsCaller
是Runnable的子类,返回的Runnable最终会执行其run方法,见代码1处,而MethodAndArgsCaller
的run方法就是执行了main()
方法
/**
* 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 {
//执行main方法
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);
}
}
}
此时app进程已经启动,通过日志打印,得知是ActivityThread的main方法被执行,此时开始创建Application对象以及Launch Activity。
时序图
总结
参考资料
转载自:https://juejin.cn/post/7231439815647789113