目录
正文
从前文# Android 10 启动分析之SystemServer篇 (四)中可以得知,系统在完成所有的初始化工作后,会通过
mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
这条语句,来启动android系统的第一个App,即Launcher应用。这篇文章,我们便以Launcher为引子来探讨一下App的启动流程,在启动App时,系统究竟做了哪些操作?
在AMS
调用startHomeOnAllDisplays
方法后,经过层层追溯,我们最终将目光定位到RootActivityContainer
中的startHomeOnDisplay
方法。
RootActivityContainer
RootActivityContainer
源码路径为 /frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java
,其相关代码如下:
boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting, boolean fromHomeKey) { // 如果displayId无效,则退回到顶层拥有焦点的显示设备 if (displayId == INVALID_DISPLAY) { displayId = getTopDisplayFocusedStack().mDisplayId; } Intent homeIntent = null; ActivityInfo aInfo = null; if (displayId == DEFAULT_DISPLAY) { //获取lancher的第一个页面的intent,其category为Intent.CATEGORY_HOME homeIntent = mService.getHomeIntent(); //通过intent找到launcher中AndroidManifest对应的activity标签,解析出相应的ActivityInfo和applicationInfo信息 aInfo = resolveHomeActivity(userId, homeIntent); } else if (shouldPlaceSecondaryHomeOnDisplay(displayId)) { //多屏显示功能,具体参考https://source.android.google.cn/devices/tech/display/multi_display/system-decorations#launcher,在此不做分析 Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, displayId); aInfo = info.first; homeIntent = info.second; } if (aInfo == null || homeIntent == null) { return false; } //在启动前,校验是否满足启动条件,大概校验了 displayId的有效性、对应activity的启动模式、是否处于工厂测试模式等等 if (!canStartHomeOnDisplay(aInfo, displayId, allowInstrumenting)) { return false; } // 更新component信息 homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name)); homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK); // 传入的fromHomeKey的值为false if (fromHomeKey) { homeIntent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, true); } // Update the reason for ANR debugging to verify if the user activity is the one that // actually launched. final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId( aInfo.applicationInfo.uid) + ":" + displayId; //转到ActivityStartController类中继续调用startHomeActivity方法 mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason, displayId); return true; }
我们继续往下追踪:
ActivityStartController
ActivityStartController
的源码路径为 /frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java
相关代码如下:
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason, int displayId) { //这句话只是创建了一个ActivityOptions的对象 final ActivityOptions options = ActivityOptions.makeBasic(); //FULLSCREEN模式启动Activity options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN); if (!ActivityRecord.isResolverActivity(aInfo.name)) { // 判断当前是否拥有多个launcher并处于选择launcher状态,否的话设置ACTIVITY_TYPE_HOME属性,直接启动launcher的activity options.setLaunchActivityType(ACTIVITY_TYPE_HOME); } options.setLaunchDisplayId(displayId); //执行启动任务 mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason) .setOutActivity(tmpOutRecord) .setCallingUid(0) .setActivityInfo(aInfo) .setActivityOptions(options.toBundle()) .execute(); mLastHomeActivityStartRecord = tmpOutRecord[0]; final ActivityDisplay display = mService.mRootActivityContainer.getActivityDisplay(displayId); final ActivityStack homeStack = display != null ? display.getHomeStack() : null; if (homeStack != null && homeStack.mInResumeTopActivity) { // If we are in resume section already, home activity will be initialized, but not // resumed (to avoid recursive resume) and will stay that way until something pokes it // again. We need to schedule another resume. mSupervisor.scheduleResumeTopActivities(); } }
我们从obtainStarter
这行代码开始看起,这段代码的执行,意味着开始进入了activity的启动流程。
ActivityStarter obtainStarter(Intent intent, String reason) { return mFactory.obtain().setIntent(intent).setReason(reason); }
这里mFactory
是一个Factory
接口,其实现类为DefaultFactory
。
public ActivityStarter obtain() { ActivityStarter starter = mStarterPool.acquire(); if (starter == null) { starter = new ActivityStarter(mController, mService, mSupervisor, mInterceptor); } return starter; }
调用obtain
方法时,会首先尝试从缓存池中获取一个ActivityStarter
对象,如果获取不到,才去新建一个。
我们将目光回转,重新聚焦到execute
这个方法上。
int execute() { try { if (mRequest.mayWait) { return startActivityMayWait(mRequest.caller, mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid, mRequest.realCallingUid, mRequest.intent, mRequest.resolvedType, mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo, mRequest.resultWho, mRequest.requestCode, mRequest.startFlags, mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig, mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId, mRequest.inTask, mRequest.reason, mRequest.allowPendingRemoteAnimationRegistryLookup, mRequest.originatingPendingIntent, mRequest.allowBackgroundActivityStart); } else { return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent, mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo, mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo, mRequest.resultWho, mRequest.requestCode, mRequest.callingPid, mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid, mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.componentSpecified, mRequest.outActivity, mRequest.inTask, mRequest.reason, mRequest.allowPendingRemoteAnimationRegistryLookup, mRequest.originatingPendingIntent, mRequest.allowBackgroundActivityStart); } } finally { onExecutionComplete(); } }
mayWait为false,进入else分支。
private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent, String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, int realCallingPid, int realCallingUid, int startFlags, SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup, PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) { ... //创建被启动的activity对应的ActivityRecord对象 ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid, callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null, mSupervisor, checkedOptions, sourceRecord); if (outActivity != null) { outActivity[0] = r; } final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack(); //如果我们启动的activity与当前恢复的activity的uid不同,请检查是否允许应用程序切换。 if (voiceSession == null && (stack.getResumedActivity() == null || stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) { if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, realCallingPid, realCallingUid, "Activity start")) { if (!(restrictedBgActivity && handleBackgroundActivityAbort(r))) { mController.addPendingActivityLaunch(new PendingActivityLaunch(r, sourceRecord, startFlags, stack, callerApp)); } ActivityOptions.abort(checkedOptions); return ActivityManager.START_SWITCHES_CANCELED; } } mService.onStartActivitySetDidAppSwitch(); mController.doPendingActivityLaunches(false); final int res = startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask, outActivity, restrictedBgActivity); mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(res, outActivity[0]); return res; }
在最后,代码会进入如下分支:
private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity, boolean restrictedBgActivity) { int result = START_CANCELED; final ActivityStack startedActivityStack; try { mService.mWindowManager.deferSurfaceLayout(); result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags, doResume, options, inTask, outActivity, restrictedBgActivity); } finally { final ActivityStack currentStack = r.getActivityStack(); startedActivityStack = currentStack != null ? currentStack : mTargetStack; if (ActivityManager.isStartResultSuccessful(result)) { if (startedActivityStack != null) { // If there is no state change (e.g. a resumed activity is reparented to // top of another display) to trigger a visibility/configuration checking, // we have to update the configuration for changing to different display. final ActivityRecord currentTop = startedActivityStack.topRunningActivityLocked(); if (currentTop != null && currentTop.shouldUpdateConfigForDisplayChanged()) { mRootActivityContainer.ensureVisibilityAndConfig( currentTop, currentTop.getDisplayId(), true /* markFrozenIfConfigChanged */, false /* deferResume */); } } } else { // If we are not able to proceed, disassociate the activity from the task. // Leaving an activity in an incomplete state can lead to issues, such as // performing operations without a window container. final ActivityStack stack = mStartActivity.getActivityStack(); if (stack != null) { stack.finishActivityLocked(mStartActivity, RESULT_CANCELED, null /* intentResultData */, "startActivity", true /* oomAdj */); } // Stack should also be detached from display and be removed if it's empty. if (startedActivityStack != null && startedActivityStack.isAttached() && startedActivityStack.numActivities() == 0 && !startedActivityStack.isActivityTypeHome()) { startedActivityStack.remove(); } } mService.mWindowManager.continueSurfaceLayout(); } postStartActivityProcessing(r, result, startedActivityStack); return result; }
调用startActivityUnchecked方法
其中,调用了startActivityUnchecked方法。
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity, boolean restrictedBgActivity) { ... //如果正在启动的activity与当前在顶部的activity相同,那么我们需要检查它是否应该只启动一次 final ActivityStack topStack = mRootActivityContainer.getTopDisplayFocusedStack(); final ActivityRecord topFocused = topStack.getTopActivity(); final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop); final boolean dontStart = top != null && mStartActivity.resultTo == null && top.mActivityComponent.equals(mStartActivity.mActivityComponent) && top.mUserId == mStartActivity.mUserId && top.attachedToProcess() && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)) // This allows home activity to automatically launch on secondary display when // display added, if home was the top activity on default display, instead of // sending new intent to the home activity on default display. && (!top.isActivityTypeHome() || top.getDisplayId() == mPreferredDisplayId); if (dontStart) { // For paranoia, make sure we have correctly resumed the top activity. topStack.mLastPausedActivity = null; if (mDoResume) { mRootActivityContainer.resumeFocusedStacksTopActivities(); } ActivityOptions.abort(mOptions); if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) { // We don't need to start a new activity, and the client said not to do // anything if that is the case, so this is it! return START_RETURN_INTENT_TO_CALLER; } deliverNewIntent(top); // Don't use mStartActivity.task to show the toast. We're not starting a new activity // but reusing 'top'. Fields in mStartActivity may not be fully initialized. mSupervisor.handleNonResizableTaskIfNeeded(top.getTaskRecord(), preferredWindowingMode, mPreferredDisplayId, topStack); return START_DELIVERED_TO_TOP; } ... //往ActivityStack中写入启动的activity记录,同时更新TaskRecord信息 mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition, mOptions); if (mDoResume) { final ActivityRecord topTaskActivity = mStartActivity.getTaskRecord().topRunningActivityLocked(); if (!mTargetStack.isFocusable() || (topTaskActivity != null && topTaskActivity.mTaskOverlay && mStartActivity != topTaskActivity)) { //如果activity无焦点的,我们不能恢复它,但仍然希望确保它在启动时时变得可见(这也将触发入场动画)。此外,我们不希望在当前有覆盖层的Task中恢复activity,因为正在启动的activity只需要处于可见的暂停状态,直到覆盖层被移除。 mTargetStack.ensureActivitiesVisibleLocked(mStartActivity, 0, !PRESERVE_WINDOWS); // Go ahead and tell window manager to execute app transition for this activity // since the app transition will not be triggered through the resume channel. mTargetStack.getDisplay().mDisplayContent.executeAppTransition(); } 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.isFocusable() && !mRootActivityContainer.isTopDisplayFocusedStack(mTargetStack)) { mTargetStack.moveToFront("startActivityUnchecked"); } mRootActivityContainer.resumeFocusedStacksTopActivities( mTargetStack, mStartActivity, mOptions); } } else if (mStartActivity != null) { mSupervisor.mRecentTasks.add(mStartActivity.getTaskRecord()); } mRootActivityContainer.updateUserStack(mStartActivity.mUserId, mTargetStack); mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTaskRecord(), preferredWindowingMode, mPreferredDisplayId, mTargetStack); return START_SUCCESS; }
我们关注一下这行代码,
mRootActivityContainer.resumeFocusedStacksTopActivities( mTargetStack, mStartActivity, mOptions);
它调用了RootActivityContainer
的resumeFocusedStacksTopActivities
方法,启动目标ActivityStack的最顶层activity。
我们接着往下追踪,它调用了 ActivityStack
的resumeTopActivityInnerLocked
方法。
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) { ... //暂停上一个activity boolean pausing = getDisplay().pauseBackStacks(userLeaving, next, false); if (mResumedActivity != null) { if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Pausing " + mResumedActivity); pausing |= startPausingLocked(userLeaving, false, next, false); } ... // 如果最近的activity没有历史记录,但由于设备进入睡眠状态而被停止,而不是停止+销毁,我们需要确保销毁它,因为我们正在使一个新的activity处于最顶层。 if (shouldSleepActivities() && mLastNoHistoryActivity != null && !mLastNoHistoryActivity.finishing) { if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + mLastNoHistoryActivity + " on new resume"); requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED, null, "resume-no-history", false); mLastNoHistoryActivity = null; } if (prev != null && prev != next && next.nowVisible) { /*下一个activity已经可见,所以现在隐藏前一个activity的窗口,以便我们可以尽快显示新的activity。 我们只有在前一个结束时才这样做,这意味着它在resume的那个之上,所以快速隐藏它是有好处的。 否则,我们希望按照正常的方式显示resume的activity, 这样我们就可以根据新activity是否全屏来决定是否应该隐藏以前的activity。*/ if (prev.finishing) { prev.setVisibility(false); if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Not waiting for visible to hide: " + prev + ", nowVisible=" + next.nowVisible); } else { if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Previous already visible but still waiting to hide: " + prev + ", nowVisible=" + next.nowVisible); } } // Launching this app's activity, make sure the app is no longer // considered stopped. try { AppGlobals.getPackageManager().setPackageStoppedState( next.packageName, false, next.mUserId); /* TODO: Verify if correct userid */ } catch (RemoteException e1) { } catch (IllegalArgumentException e) { Slog.w(TAG, "Failed trying to unstop package " + next.packageName + ": " + e); } // 我们正在启动下一个activity,所以告诉window manager,上一个activity很快就会被隐藏。这样,它可以知道在计算所需的屏幕方向时忽略它。 boolean anim = true; final DisplayContent dc = getDisplay().mDisplayContent; if (prev != null) { if (prev.finishing) { if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare close transition: prev=" + prev); if (mStackSupervisor.mNoAnimActivities.contains(prev)) { anim = false; dc.prepareAppTransition(TRANSIT_NONE, false); } else { dc.prepareAppTransition( prev.getTaskRecord() == next.getTaskRecord() ? TRANSIT_ACTIVITY_CLOSE : TRANSIT_TASK_CLOSE, false); } prev.setVisibility(false); } else { if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: prev=" + prev); if (mStackSupervisor.mNoAnimActivities.contains(next)) { anim = false; dc.prepareAppTransition(TRANSIT_NONE, false); } else { dc.prepareAppTransition( prev.getTaskRecord() == next.getTaskRecord() ? TRANSIT_ACTIVITY_OPEN : next.mLaunchTaskBehind ? TRANSIT_TASK_OPEN_BEHIND : TRANSIT_TASK_OPEN, false); } } } else { if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous"); if (mStackSupervisor.mNoAnimActivities.contains(next)) { anim = false; dc.prepareAppTransition(TRANSIT_NONE, false); } else { dc.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false); } } if (anim) { next.applyOptionsLocked(); } else { next.clearOptionsLocked(); } mStackSupervisor.mNoAnimActivities.clear(); if (next.attachedToProcess()) { ... //只有启动过的activity才会进入此分支 } else { // Whoops, need to restart this activity! if (!next.hasBeenLaunched) { next.hasBeenLaunched = true; } else { if (SHOW_APP_STARTING_PREVIEW) { //冷启动的过渡页,在这里会载入manifest配置的主题背景,如果没有的话,默认白屏或黑屏 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); mStackSupervisor.startSpecificActivityLocked(next, true, true); } return true; }
通过源码,我们可以得知:先对上一个Activity执行pause操作,再启动目标activity,最终进入到了ActivityStackSupervior.startSpecificActivityLocked方法中。在启动Activity之前,调用了next.showStartingWindow方法来展示一个window,这就是冷启动时出现白屏的原因。
我们继续往下追踪:
ActivityStackSupervisor
ActivityStackSupervisor
的源码路径为 /frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
void startSpecificActivityLocked(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; 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; } // Suppress transition until the new activity becomes ready, otherwise the keyguard can // appear for a short amount of time before the new process with the new activity had the // ability to set its showWhenLocked flags. if (getKeyguardController().isKeyguardLocked()) { r.notifyUnknownVisibilityLaunched(); } try { if (Trace.isTagEnabled(TRACE_TAG_ACTIVITY_MANAGER)) { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dispatchingStartProcess:" + r.processName); } //发布消息以启动进程,从而避免在ATMS锁被持有的情况下调用AMS时可能出现的死锁 final Message msg = PooledLambda.obtainMessage( ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName, r.info.applicationInfo, knownToBeDead, "activity", r.intent.getComponent()); mService.mH.sendMessage(msg); } finally { Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } }
上面这段方法里有个很重要的判断,if(wpc != null && wpc.hasThread())
,通过进程名和application uid 获取的WindowProcessController
对象进行校验,判断要启动的activity进程是否已启动。显然,app第一次启动时,进程还不存在,首先先得创建应用进程。
final Message msg = PooledLambda.obtainMessage( ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName, r.info.applicationInfo, knownToBeDead, "activity", r.intent.getComponent()); mService.mH.sendMessage(msg);
这里通过Handler,发送了一条Message,以避免在ATMS锁被持有的情况下调用AMS时可能出现的死锁。这条Message实际调用的是ActivityManagerService
的startProcess
方法。
启动进程
ActivityManagerService
的源码位置为 /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
startProcess
实际调用的是startProcessLocked
方法,我们直接从它看起。
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord, boolean allowWhileBooting, boolean isolated, boolean keepIfLarge) { return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingRecord, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge, null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */, null /* crashHandler */); }
这里调用的是 ProcessList
类里的startProcessLocked
的方法,我们继续往下看。
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord, boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) { ... ProcessRecord app; // 以下三种情况,我们不需要做任何额外的处理 // (1) 存在一个application 记录 // (2) 调用者认为它仍然存活,或者没有线程对象连接到它,所以我们知道它没有crash // (3) 有一个pid分配给它,所以它要么正在启动,要么已经运行 if (app != null && app.pid > 0) { if ((!knownToBeDead && !app.killed) || app.thread == null) { // 我们已经有应用程序在运行,或者正在等待它出现(我们有一个pid,但还没有它的线程),所以保持它 if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App already running: " + app); // If this is a new package in the process, add the package to the list app.addPackage(info.packageName, info.longVersionCode, mService.mProcessStats); checkSlow(startTime, "startProcess: done, added package to proc"); return app; } // An application record is attached to a previous process, // clean it up now. if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App died: " + app); checkSlow(startTime, "startProcess: bad proc running, killing"); ProcessList.killProcessGroup(app.uid, app.pid); mService.handleAppDiedLocked(app, true, true); checkSlow(startTime, "startProcess: done killing old proc"); } if (app == null) { checkSlow(startTime, "startProcess: creating new process record"); //创建一条ProcessRecord app = new ProcessRecordLocked(info, processName, isolated, isolatedUid, hostingRecord); if (app == null) { Slog.w(TAG, "Failed making new process record for " + processName + "/" + info.uid + " isolated=" + isolated); return null; } app.crashHandler = crashHandler; app.isolatedEntryPoint = entryPoint; app.isolatedEntryPointArgs = entryPointArgs; checkSlow(startTime, "startProcess: done creating new process record"); } else { // If this is a new package in the process, add the package to the list app.addPackage(info.packageName, info.longVersionCode, mService.mProcessStats); checkSlow(startTime, "startProcess: added package to existing proc"); } // If the system is not ready yet, then hold off on starting this // process until it is. if (!mService.mProcessesReady && !mService.isAllowedWhileBooting(info) && !allowWhileBooting) { if (!mService.mProcessesOnHold.contains(app)) { mService.mProcessesOnHold.add(app); } if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "System not ready, putting on hold: " + app); checkSlow(startTime, "startProcess: returning with proc on hold"); return app; } checkSlow(startTime, "startProcess: stepping in to startProcess"); final boolean success = startProcessLocked(app, hostingRecord, abiOverride); checkSlow(startTime, "startProcess: done starting proc!"); return success ? app : null; }
可以看到,在启动一个新的进程时,有两个比较重要的步骤。一是通过newProcessRecordLocked
方法首先创建一条进程记录,然后再通过startProcessLocked
方法去创建一个进程。
boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord, boolean disableHiddenApiChecks, boolean mountExtStorageFull, String abiOverride) { int uid = app.uid; int[] gids = null; int mountExternal = Zygote.MOUNT_EXTERNAL_NONE; if (!app.isolated) { ... final String entryPoint = "android.app.ActivityThread"; return startProcessLocked(hostingRecord, entryPoint, app, uid, gids, runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith, startTime); } catch (RuntimeException e) { Slog.e(ActivityManagerService.TAG, "Failure starting process " + app.processName, e); mService.forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid), false, false, true, false, false, app.userId, "start failure"); return false; } }
这里请注意一下entryPoint
这个变量的值————android.app.ActivityThread
,它会经过一段漫长的调用链,最终在RuntimeInit
这个类中发挥它的作用。
boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint, ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal, String seInfo, String requiredAbi, String instructionSet, String invokeWith, long startTime) { app.pendingStart = true; app.killedByAm = false; app.removed = false; app.killed = false; ... final long startSeq = app.startSeq = ++mProcStartSeqCounter; app.setStartParams(uid, hostingRecord, seInfo, startTime); app.setUsingWrapper(invokeWith != null || SystemProperties.get("wrap." + app.processName) != null); mPendingStarts.put(startSeq, app); if (mService.mConstants.FLAG_PROCESS_START_ASYNC) { //默认以异步方式启动 mService.mProcStartHandler.post(() -> { try { final Process.ProcessStartResult startResult = startProcess(app.hostingRecord, entryPoint, app, app.startUid, gids, runtimeFlags, mountExternal, app.seInfo, requiredAbi, instructionSet, invokeWith, app.startTime); synchronized (mService) { handleProcessStartedLocked(app, startResult, startSeq); } } catch (RuntimeException e) { synchronized (mService) { Slog.e(ActivityManagerService.TAG, "Failure starting process " + app.processName, e); mPendingStarts.remove(startSeq); app.pendingStart = false; mService.forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid), false, false, true, false, false, app.userId, "start failure"); } } }); return true; } else { try { final Process.ProcessStartResult startResult = startProcess(hostingRecord, entryPoint, app, uid, gids, runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith, startTime); handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper, startSeq, false); } catch (RuntimeException e) { Slog.e(ActivityManagerService.TAG, "Failure starting process " + app.processName, e); app.pendingStart = false; mService.forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid), false, false, true, false, false, app.userId, "start failure"); } return app.pid > 0; } }
继续看startProcess
方法:
private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint, ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal, String seInfo, String requiredAbi, String instructionSet, String invokeWith, long startTime) { try { final Process.ProcessStartResult startResult; //hostingRecord初始化参数为null,并未指定mHostingZygote属性,因此会进入最后一个分支 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, new String[] {PROC_START_SEQ_IDENT + app.startSeq}); } else if (hostingRecord.usesAppZygote()) { final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app); 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, /*useUsapPool=*/ 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, new String[] {PROC_START_SEQ_IDENT + app.startSeq}); } checkSlow(startTime, "startProcess: returned from zygote!"); return startResult; } finally { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } }
Process
的源码位置为 frameworks/base/core/java/android/os/Process.java
。
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, @Nullable String[] zygoteArgs) { return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids, runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, packageName, /*useUsapPool=*/ true, zygoteArgs); }
其中ZYGOTE_PROCESS
是一个ZygoteProcess
对象,它实际调用的是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, boolean useUsapPool, @Nullable String[] zygoteArgs) { // TODO (chriswailes): Is there a better place to check this value? if (fetchUsapPoolEnabledPropWithMinInterval()) { informZygotesOfUsapPoolStatus(); } try { return startViaZygote(processClass, niceName, uid, gid, gids, runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false, packageName, useUsapPool, 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, boolean useUsapPool, @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); if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) { argsForZygote.add("--mount-external-default"); } else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) { argsForZygote.add("--mount-external-read"); } else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) { argsForZygote.add("--mount-external-write"); } else if (mountExternal == Zygote.MOUNT_EXTERNAL_FULL) { argsForZygote.add("--mount-external-full"); } else if (mountExternal == Zygote.MOUNT_EXTERNAL_INSTALLER) { argsForZygote.add("--mount-external-installer"); } else if (mountExternal == Zygote.MOUNT_EXTERNAL_LEGACY) { argsForZygote.add("--mount-external-legacy"); } argsForZygote.add("--target-sdk-version=" + targetSdkVersion); // --setgroups is a comma-separated list if (gids != null && gids.length > 0) { StringBuilder sb = new StringBuilder(); sb.append("--setgroups="); int sz = gids.length; for (int i = 0; i < sz; i++) { if (i != 0) { sb.append(','); } sb.append(gids[i]); } argsForZygote.add(sb.toString()); } if (niceName != null) { argsForZygote.add("--nice-name=" + niceName); } if (seInfo != null) { argsForZygote.add("--seinfo=" + seInfo); } if (instructionSet != null) { argsForZygote.add("--instruction-set=" + instructionSet); } if (appDataDir != null) { argsForZygote.add("--app-data-dir=" + appDataDir); } if (invokeWith != null) { argsForZygote.add("--invoke-with"); argsForZygote.add(invokeWith); } if (startChildZygote) { argsForZygote.add("--start-child-zygote"); } if (packageName != null) { argsForZygote.add("--package-name=" + packageName); } argsForZygote.add(processClass); if (extraArgs != null) { Collections.addAll(argsForZygote, extraArgs); } 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), useUsapPool, argsForZygote); } }
值得注意的是上面这段代码的openZygoteSocketIfNeeded
这个方法,它采用socket通信方式,尝试连接路径为/dev/socket/
、名称为zygote
的服务端。
zygoteSendArgsAndGetResult
方法里实际调用了attemptZygoteSendArgsAndGetResult
方法,内容如下:
private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult( ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx { try { final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter; final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream; 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. 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); } }
请注意上述方法的zygoteWriter
这个变量,它负责将进程启动参数发送给服务端,由服务端去孵化进程。那么,这个服务端到底是哪个类呢?
答案是ZygoteServer.java
,源码路径为 frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
.
ZygoteServer
会在系统启动的时候,创建一个Socket服务端,用于接收客户端的fork请求。ZygoteServer
在初始化结束后,会调用runSelectLoop
方法,用于处理客户端的消息。当客户端请求fork进程时,runSelectLoop
方法会转交给ZygoteConnection
类的processOneCommand
方法去处理。
(ps : 如需了解更多关于Zegote的信息,请参考文章 Android 10 启动分析之Zygote篇)
Runnable processOneCommand(ZygoteServer zygoteServer) { String args[]; ZygoteArguments parsedArgs = null; FileDescriptor[] descriptors; ... 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.mTargetSdkVersion); try { if (pid == 0) { // in child zygoteServer.setForkChild(); zygoteServer.closeServerSocket(); IoUtils.closeQuietly(serverPipeFd); serverPipeFd = null; return handleChildProc(parsedArgs, descriptors, 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, descriptors, serverPipeFd); return null; } } finally { IoUtils.closeQuietly(childPipeFd); IoUtils.closeQuietly(serverPipeFd); } }
public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir, int targetSdkVersion) { ZygoteHooks.preFork(); // Resets nice priority for zygote process. resetNicePriority(); int pid = nativeForkAndSpecialize( uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, instructionSet, appDataDir); // Enable tracing as soon as possible for the child process. if (pid == 0) { Zygote.disableExecuteOnly(targetSdkVersion); Trace.setTracingEnabled(true, runtimeFlags); // Note that this event ends at the end of handleChildProc, Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork"); } ZygoteHooks.postForkCommon(); return pid; }
上述Zygote
类在这个过程中主要做了以下几点工作:
- 调用dalvik中
ZygoteHooks
的preFrok
进行预处理,主要是停止4个Daemon子线程,HeapTaskDaemon、ReferenceQueueDaemon、FinalizerDaemon、FinalizerWatchdogDaemon,等待所有的子线程结束,最后完成gc堆的初始化工作。 - 调用
com_android_internal_os_zygote.cpp
中的nativeForkAndSpecialize
方法,主要工作是通过linux机制fork一个子进程,以及进程的一些资源处理,selinux权限处理,JAVA堆线程的一些处理。 - 调用
ZygoteHooks
的postForkCommon
方法,启动Zygote的4个Daemon线程。
在执行forkAndSpecialize
方法后,代码将继续执行ZygoteConnection
中的handleChildProc
这个方法。
private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, boolean isZygote) { ... 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) { //进入此分支 return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion, parsedArgs.mRemainingArgs, null /* classLoader */); } else { return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion, parsedArgs.mRemainingArgs, null /* classLoader */); } } }
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) { ... //初始化运行环境 RuntimeInit.commonInit(); //启动binder线程池 ZygoteInit.nativeZygoteInit(); //程序入口函数 return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader); }
RuntimeInit.applicationInit这个方法
protected static Runnable applicationInit(int targetSdkVersion, 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); // We want to be fairly aggressive about heap utilization, to avoid // holding on to a lot of memory that isn't needed. VMRuntime.getRuntime().setTargetHeapUtilization(0.75f); VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion); 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); }
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); }
这里通过反射获得了className
变量中的main方法,并传递给MethodAndArgsCaller用于构造一个Runnable。只要执行此Runnable,就会开始执行className
变量中的main方法。
className
变量的值究竟是什么呢?
还记得我们前文重点强调的entryPoint
这个变量吗?不记得的读者请自行返回再查看一下。android.app.ActivityThread
就是我们要执行的目标类。
ActivityThread
类main方法的调用,标识着 应用已全部完成进程的创建和初始化过程,下面将进入Application
和Activity
的创建与启动流程。下一篇文章,我们再来继续探讨剩下的内容。
最后,让我们用图表对上述流程做一个总结归纳:
[ActivityManagerService.java] mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady"); | [RootActivityContainer.java] startHomeOnDisplay() //获取lancher的第一个页面的intent,其category为Intent.CATEGORY_HOME | [ActivityStartController.java] startHomeActivity() | [ActivityStarter.java] execute() //开始进入activity启动流程 startActivity() startActivityUnchecked() | [RootActivityContainer.java] resumeFocusedStacksTopActivities() //启动目标ActivityStack的最顶层activity | [ActivityStack.java] resumeTopActivityInnerLocked() //暂停上一个activity,载入manifest的主题背景 | [ActivityStackSupervisor.java] startSpecificActivityLocked() //检查进程是否已启动,通过handler消息机制启动新的进程 | [ActivityManagerService.java] startProcessLocked() | [ProcessList.java] startProcessLocked() //指定了进程创建成功后程序启动入口类为android.app.ActivityThread startProcess() | [Process.java] start() | [ZygoteProcess.java] start() startViaZygote() //初始化Zygote的启动参数,连接ZygoteServer服务端 attemptZygoteSendArgsAndGetResult() | [ZygoteServer.java] processOneCommand() | | | [Zygote.java] | forkAndSpecialize() | | | [ZygoteHooks.java] | preFrok() //停止4个子线程,等待所有的子线程结束,最后完成gc堆的初始化工作 | | | [com_android_internal_os_zygote.cpp] | nativeForkAndSpecialize() //fork子进程 | | | [ZygoteHooks.java] | postForkCommon() //启动Zygote的4个Daemon线程 | [ZygoteConnection.java] handleChildProc() | [ZygoteInit.java] zygoteInit() //初始化运行环境、启动binder线程池 | [RuntimeInit.java] applicationInit() | [ActivityThread.java] main()
以上就是Android10 App 启动分析进程创建源码解析的详细内容,更多关于Android10 App启动进程创建的资料请关注其它相关文章!