系列文章
Android S从桌面点击图标启动APP流程 (一)
Android S从桌面点击图标启动APP流程 (二)
Android S从桌面点击图标启动APP流程 (三)
Android S从桌面点击图标启动APP流程 (四)
Android S从桌面点击图标启动APP流程 (五)
Android S从桌面点击图标启动APP流程 (六)
Android 12的源码链接:
Android 12 AOSPhttp://aospxref.com/android-12.0.0_r3/
一般更新activity的可见性log如下:
确定next activity的可见性
10-11 05:23:15.943 1562 1782 V ActivityTaskManager: ensureActivitiesVisible behind ActivityRecord{be18a2 u0 com.android.calendar/.AllInOneActivity t8} configChanges=0x0
10-11 05:23:15.944 1562 1782 V ActivityTaskManager: Fullscreen: at ActivityRecord{be18a2 u0 com.android.calendar/.AllInOneActivity t8} containerVisible=true behindFullyOccluded=false设置为可见状态
10-11 05:23:15.944 1562 1782 V ActivityTaskManager: Make visible? ActivityRecord{be18a2 u0 com.android.calendar/.AllInOneActivity t8} finishing=false state=INITIALIZINGfree住屏幕
10-11 05:23:15.944 1562 1782 V ActivityTaskManager: Start and freeze screen for ActivityRecord{be18a2 u0 com.android.calendar/.AllInOneActivity t8}开始设置为可见
10-11 05:23:15.944 1562 1782 V ActivityTaskManager: Starting and making visible: ActivityRecord{be18a2 u0 com.android.calendar/.AllInOneActivity t8}
更新next的可见性10-11 05:23:15.946 1562 1782 I ActivityTaskManager: APP_COMPAT_STATE_CHANGED(10075, 2)
10-11 05:23:15.947 1562 1782 I ActivityTaskManager: notifyVisibilityChanged ActivityRecord{be18a2 u0 com.android.calendar/.AllInOneActivity t8} visible=true state=INITIALIZING finishing=false确定prev 的可见性
10-11 05:23:15.947 1562 1782 V ActivityTaskManager: ensureActivitiesVisible behind ActivityRecord{b1a7043 u0 com.android.launcher3/.uioverrides.QuickstepLauncher t6} configChanges=0x0设置前一个prev为不可见
10-11 05:23:15.948 1562 1782 V ActivityTaskManager: Make invisible? ActivityRecord{b1a7043 u0 com.android.launcher3/.uioverrides.QuickstepLauncher t6} finishing=false state=PAUSED containerShouldBeVisible=false behindFullyOccludedContainer=true mLaunchTaskBehind=false立即设置不可见
10-11 05:23:15.948 1562 1782 V ActivityTaskManager: Making invisible: ActivityRecord{b1a7043 u0 com.android.launcher3/.uioverrides.QuickstepLauncher t6}, state=PAUSED将prev加入stopping队列
10-11 05:23:15.949 1562 1782 I wm_add_to_stopping: [0,186282051,com.android.launcher3/.uioverrides.QuickstepLauncher,makeInvisible]
具体过程如下:
void ensureActivitiesVisible(@Nullable ActivityRecord starting, int configChanges,
boolean preserveWindows) {
ensureActivitiesVisible(starting, configChanges, preserveWindows, true /* notifyClients */);
}
通过更新可见activities的配置确定activities的可见性。
void ensureActivitiesVisible(@Nullable ActivityRecord starting, int configChanges,
boolean preserveWindows, boolean notifyClients) {
mTaskSupervisor.beginActivityVisibilityUpdate();
try {
------------
forAllLeafTasks(task -> task.mEnsureActivitiesVisibleHelper.process(
starting, configChanges, preserveWindows, notifyClients),
true /* traverseTopToBottom */);
通知 WM shell task可见性可能已更改
// Notify WM shell that task visibilities may have changed
forAllTasks(task -> task.dispatchTaskInfoChangedIfNeeded(/* force */ false),
true /* traverseTopToBottom */);
if (mTranslucentActivityWaiting != null &&
mUndrawnActivitiesBelowTopTranslucent.isEmpty()) {
// Nothing is getting drawn or everything was already visible, don't wait for timeout. 没有绘制任何内容或所有内容都已可见,不要等待超时。
notifyActivityDrawnLocked(null);
}
} finally {
mTaskSupervisor.endActivityVisibilityUpdate();
}
}
Update and commit visibility with an option to also update the configuration of visible activities.
通过option更新和提交可见性,以更新可见activities的配置。
void process(@Nullable ActivityRecord starting, int configChanges, boolean preserveWindows,
boolean notifyClients) {
reset(starting, configChanges, preserveWindows, notifyClients);
if (DEBUG_VISIBILITY) {
Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible behind " + mTop
+ " configChanges=0x" + Integer.toHexString(configChanges));
}
if (mTop != null) {
mTask.checkTranslucentActivityWaiting(mTop);
}
// We should not resume activities that being launched behind because these activities are actually behind other fullscreen activities, but still required to be visible (such as performing Recents animation).
我们不应resume在后台启动的activities,因为这些activities实际上位于其他全屏activities后面,但仍需要可见(例如执行“最近”动画)。
final boolean resumeTopActivity = mTop != null && !mTop.mLaunchTaskBehind
&& mTask.isTopActivityFocusable()
&& (starting == null || !starting.isDescendantOf(mTask));
mTask.forAllActivities(a -> {
------------遍历activity,更新activity可见性
setActivityVisibilityState(a, starting, resumeTopActivity);
});
if (mTask.mAtmService.getTransitionController().getTransitionPlayer() != null) {
mTask.getDisplayContent().mWallpaperController.adjustWallpaperWindows();
}
}
frameworks/base/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
private void setActivityVisibilityState(ActivityRecord r, ActivityRecord starting,
final boolean resumeTopActivity) {
final boolean isTop = r == mTop;
if (mAboveTop && !isTop) {
return;
}
mAboveTop = false;
r.updateVisibilityIgnoringKeyguard(mBehindFullscreenActivity);
final boolean reallyVisible = r.shouldBeVisibleUnchecked();
// Check whether activity should be visible without Keyguard influence
检查activity是否应该在没有Keyguard影响的情况下可见
if (r.visibleIgnoringKeyguard) {
if (r.occludesParent()) {
// At this point, nothing else needs to be shown in this task.
此时,此任务中不需要显示任何其他内容。
if (DEBUG_VISIBILITY) {
Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r
+ " containerVisible=" + mContainerShouldBeVisible
+ " behindFullscreen=" + mBehindFullscreenActivity);
}
mBehindFullscreenActivity = true;
} else {
mBehindFullscreenActivity = false;
}
}
if (reallyVisible) {
if (r.finishing) {
return;
}
if (DEBUG_VISIBILITY) {
Slog.v(TAG_VISIBILITY, "Make visible? " + r
+ " finishing=" + r.finishing + " state=" + r.getState());
}
// First: if this is not the current activity being started, make sure it matches the current configuration.
首先:如果这不是当前正在启动的activity,请确保它与当前配置匹配。
if (r != mStarting && mNotifyClients) {
r.ensureActivityConfiguration(0 /* globalChanges */, mPreserveWindows,
true /* ignoreVisibility */);
}
if (!r.attachedToProcess()) {//由于是冷启动,此时还未attachedToProcess
------------必要时设置activity可见并restart activity
makeVisibleAndRestartIfNeeded(mStarting, mConfigChanges, isTop,
resumeTopActivity && isTop, r);
-------------后面会有解释
} else if (r.mVisibleRequested) {
// If this activity is already visible, then there is nothing to do here.
如果activity已经可见,则不用做什么事情了
if (DEBUG_VISIBILITY) {
Slog.v(TAG_VISIBILITY, "Skipping: already visible at " + r);
}
if (r.mClientVisibilityDeferred && mNotifyClients) {
r.makeActiveIfNeeded(r.mClientVisibilityDeferred ? null : starting);
r.mClientVisibilityDeferred = false;
}
r.handleAlreadyVisible();
if (mNotifyClients) {
r.makeActiveIfNeeded(mStarting);
}
} else {
r.makeVisibleIfNeeded(mStarting, mNotifyClients);
}
// Aggregate current change flags.整合当前的config flag
mConfigChanges |= r.configChangeFlags;
} else {
if (DEBUG_VISIBILITY) {
Slog.v(TAG_VISIBILITY, "Make invisible? " + r
+ " finishing=" + r.finishing + " state=" + r.getState()
+ " containerShouldBeVisible=" + mContainerShouldBeVisible
+ " behindFullscreenActivity=" + mBehindFullscreenActivity
+ " mLaunchTaskBehind=" + r.mLaunchTaskBehind);
}
------------将前一个activity置为不可见
r.makeInvisible();
------------后面会有解释
}
if (!mBehindFullscreenActivity && mTask.isActivityTypeHome() && r.isRootOfTask()) {
if (DEBUG_VISIBILITY) {
Slog.v(TAG_VISIBILITY, "Home task: at " + mTask
+ " containerShouldBeVisible=" + mContainerShouldBeVisible
+ " behindFullscreenActivity=" + mBehindFullscreenActivity);
}
// No other task in the root home task should be visible behind the home activity. Home activities is usually a translucent activity with the wallpaper behind them. However, when they don't have the wallpaper behind them, we want to show activities in the next application root task behind them vs. another task in the root home task like recents.
根home task中的其他task不应在home activity后面可见。Home activities通常是半透明的activity,后面有wallpaper。但是,当它们后面没有wallpaper时,我们希望在它们后面的下一个应用程序根任务中显示activities,而不是在根home task中显示另一个任务(如最近的任务)。
mBehindFullscreenActivity = true;
}
}
frameworks/base/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
private void makeVisibleAndRestartIfNeeded(ActivityRecord starting, int configChanges,
boolean isTop, boolean andResume, ActivityRecord r) {
// We need to make sure the app is running if it's the top, or it is just made visible from invisible. If the app is already visible, it must have died while it was visible. In this case, we'll show the dead window but will not restart the app. Otherwise we could end up thrashing.
如果app在顶部,我们需要确保应用程序正在运行,,或者它只是从不可见变为可见。如果应用已经可见,则它一定在可见时已死亡。在这种情况下,我们将显示dead window,但不会重新启动应用程序。
if (!isTop && r.mVisibleRequested) {
return;
}
// This activity needs to be visible, but isn't even running... get it started and resume if no other root task in this root task is resumed.
此activity需要可见,但可能没有运行...故启动并resume它,如果此根任务中没有其他根任务可resume。
if (DEBUG_VISIBILITY) {
Slog.v(TAG_VISIBILITY, "Start and freeze screen for " + r);
}
if (r != starting) {
r.startFreezingScreenLocked(configChanges);
}
if (!r.mVisibleRequested || r.mLaunchTaskBehind) {
if (DEBUG_VISIBILITY) {
Slog.v(TAG_VISIBILITY, "Starting and making visible: " + r);
}
将activity可见性设为true
r.setVisibility(true);
}
if (r != starting) {
-----------然后开始去启动将要resume的activity
mTask.mTaskSupervisor.startSpecificActivity(r, andResume, true /* checkConfig */);
-----------后面会展开讲解
}
}
frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java
void makeInvisible() {
if (!mVisibleRequested) {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Already invisible: " + this);
return;
}
// Now for any activities that aren't visible to the user, make sure they no longer are keeping the screen frozen.
if (DEBUG_VISIBILITY) {
Slog.v(TAG_VISIBILITY, "Making invisible: " + this + ", state=" + getState());
}
try {
final boolean canEnterPictureInPicture = checkEnterPictureInPictureState(
"makeInvisible", true /* beforeStopping */);
// Defer telling the client it is hidden if it can enter Pip and isn't current paused, stopped or stopping. This gives it a chance to enter Pip in onPause(). TODO: There is still a question surrounding activities in multi-window mode that want to enter Pip after they are paused, but are still visible. I they should be okay to enter Pip in those cases, but not "auto-Pip" which is what this condition covers and the current contract for "auto-Pip" is that the app should enter it before onPause returns. Just need to confirm this reasoning makes sense.
推迟告诉客户端它是hidden 的,如果它可以进入Pip并且当前没有paused, stopped or stopping。这给了它一个在 onPause() 中进入 Pip 的机会。
TODO:围绕多窗口模式下的活动仍然存在一个问题,这些活动希望在paused进入 Pip,但仍然可见。在这些情况下,他们应该可以进入 Pip,但不是“自动 Pip”,这是这个条件所涵盖的,“自动 Pip”的当前合同是应用程序应该在 onPause 返回之前进入它。只需要确认这个原因是有道理的。
final boolean deferHidingClient = canEnterPictureInPicture
&& !isState(STARTED, STOPPING, STOPPED, PAUSED);
if (deferHidingClient && pictureInPictureArgs.isAutoEnterEnabled()) {
// Go ahead and just put the activity in pip if it supports auto-pip.
mAtmService.enterPictureInPictureMode(this, pictureInPictureArgs);
return;
}
setDeferHidingClient(deferHidingClient);
setVisibility(false);
switch (getState()) {
case STOPPING:
case STOPPED:
// Reset the flag indicating that an app can enter picture-in-picture once the activity is hidden
supportsEnterPipOnTaskSwitch = false;
break;
case RESUMED:
// If the app is capable of entering PIP, we should try pausing it now so it can PIP correctly.
if (deferHidingClient) {
task.startPausingLocked(false /* uiSleeping */,
null /* resuming */, "makeInvisible");
break;
}
case INITIALIZING:
case PAUSING:
case PAUSED:
case STARTED:
-------------------将前一个activity加入stopping队列
addToStopping(true /* scheduleIdle */,
canEnterPictureInPicture /* idleDelayed */, "makeInvisible");
break;
default:
break;
}
} catch (Exception e) {
// Just skip on any failure; we'll make it visible when it next restarts.
Slog.w(TAG, "Exception thrown making hidden: " + intent.getComponent(), e);
}
}
void addToStopping(boolean scheduleIdle, boolean idleDelayed, String reason) {
if (!mTaskSupervisor.mStoppingActivities.contains(this)) {
EventLogTags.writeWmAddToStopping(mUserId, System.identityHashCode(this),
shortComponentName, reason);
-----------10-11 05:23:15.949 1562 1782 I wm_add_to_stopping: [0,186282051,com.android.launcher3/.uioverrides.QuickstepLauncher,makeInvisible]
mTaskSupervisor.mStoppingActivities.add(this);
}
final Task rootTask = getRootTask();
// If we already have a few activities waiting to stop, then give up on things going idle and start clearing them out. Or if r is the last of activity of the last task the root task will be empty and must be cleared immediately.
boolean forceIdle = mTaskSupervisor.mStoppingActivities.size() > MAX_STOPPING_TO_FORCE
|| (isRootOfTask() && rootTask.getChildCount() <= 1);
if (scheduleIdle || forceIdle) {
ProtoLog.v(WM_DEBUG_STATES,
"Scheduling idle now: forceIdle=%b immediate=%b", forceIdle, !idleDelayed);
if (!idleDelayed) {
mTaskSupervisor.scheduleIdle();
} else {
mTaskSupervisor.scheduleIdleTimeout(this);
}
} else {
rootTask.checkReadyForSleep();
}
}
紧接着45.1,即将要去启动将要resume的APP,如果没有进程,则会创建进程。
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Is this activity's application already running?判断activity所在的APP是否已经在运行
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);
boolean knownToBeDead = false;
if (wpc != null && wpc.hasThread()) {
try {如果activity所在的进程没有在运行,但是已经有thread存在了,但此时由于进程还没创建,所以无法进入此方法
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();
--------创建将要启动的activity所在的app进程
mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
}
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
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.
发送一个message消息去启动进程,以避免在调用 ATMS 锁定的情况下出现死锁。
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);
}
}
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@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.
如果该进程是top应用程序,请设置提示,以便在进程启动时,可以立即应用最高优先级,以避免 CPU 在附加顶级应用程序的进程之前被其他进程抢占。
startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
new HostingRecord(hostingType, hostingName, isTop),
ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false /* allowWhileBooting */, false /* isolated */);
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@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 */,
null /* ABI override */, null /* entryPoint */,
null /* entryPointArgs */, null /* crashHandler */);
}
frameworks/base/services/core/java/com/android/server/am/ProcessList.java
ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord,
int zygotePolicyFlags, boolean allowWhileBooting, boolean isolated, int isolatedUid,
String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
long startTime = SystemClock.uptimeMillis();
ProcessRecord app;
if (!isolated) {
app = getProcessRecordLocked(processName, info.uid);
checkSlow(startTime, "startProcess: after getProcessRecord");
if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
// If we are in the background, then check to see if this process is bad. If so, we will just silently fail.
如果我们在后台,请检查此进程是否bad。 如果是这样,我们只会默默地失败。
if (mService.mAppErrors.isBadProcess(processName, info.uid)) {
if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
+ "/" + processName);
return null;
}
} else {
// When the user is explicitly starting a process, then clear its crash count so that we won't make it bad until they see at least one crash dialog again, and make the process good again if it had been bad.
当用户显式启动进程时,请清除其崩溃计数,以便在他们再次看到至少一个崩溃对话框之前我们不会使其变坏,如果进程很糟糕,则使进程再次变好。
if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
+ "/" + processName);
mService.mAppErrors.resetProcessCrashTime(processName, info.uid);
if (mService.mAppErrors.isBadProcess(processName, info.uid)) {
EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
UserHandle.getUserId(info.uid), info.uid,
info.processName);
mService.mAppErrors.clearBadProcess(processName, info.uid);
if (app != null) {
app.mErrorState.setBad(false);
}
}
}
} else {
// If this is an isolated process, it can't re-use an existing process.
app = null;
}
// We don't have to do anything more if:
// (1) There is an existing application record; and
// (2) The caller doesn't think it is dead, OR there is no thread
// object attached to it so we know it couldn't have crashed; and
// (3) There is a pid assigned to it, so it is either starting or
// already running.
if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "startProcess: name=" + processName
+ " app=" + app + " knownToBeDead=" + knownToBeDead
+ " thread=" + (app != null ? app.getThread() : null)
+ " pid=" + (app != null ? app.getPid() : -1));
ProcessRecord predecessor = null;
if (app != null && app.getPid() > 0) {
if ((!knownToBeDead && !app.isKilled()) || app.getThread() == null) {
// We already have the app running, or are waiting for it to come up (we have a pid but not yet its thread), so keep it.
我们已经运行了应用程序,或者正在等待它起来(我们有一个 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
如果这是进程中的新package,请将该包添加到列表中
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.getPid());
checkSlow(startTime, "startProcess: done killing old proc");
if (!app.isKilled()) {
// Throw a wtf if it's not killed
Slog.wtf(TAG_PROCESSES, app.toString() + " is attached to a previous process");
} else {
Slog.w(TAG_PROCESSES, app.toString() + " is attached to a previous process");
}
// We are not going to re-use the ProcessRecord, as we haven't dealt with the cleanup routine of it yet, but we'd set it as the predecessor of the new process.
predecessor = app;
app = null;
} else if (!isolated) {
// This app may have been removed from process name maps, probably because we killed it and did the cleanup before the actual death notification. Check the dying processes.
此应用可能已从进程名称映射中删除,可能是因为我们在实际死亡通知之前杀死了它并进行了清理。检查染色过程。
predecessor = mDyingProcesses.get(processName, info.uid);
if (predecessor != null) {
if (app != null) {
app.mPredecessor = predecessor;
predecessor.mSuccessor = app;
}
Slog.w(TAG_PROCESSES, predecessor.toString() + " is attached to a previous process "
+ predecessor.getDyingPid());
}
}
--------首次创建,ProcessRecord 为null
if (app == null) {
checkSlow(startTime, "startProcess: creating new process record");
------------new ProcessRecord(mService, info, proc, uid);
app = newProcessRecordLocked(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.mErrorState.setCrashHandler(crashHandler);
app.setIsolatedEntryPoint(entryPoint);
app.setIsolatedEntryPointArgs(entryPointArgs);
if (predecessor != null) {
app.mPredecessor = predecessor;
predecessor.mSuccessor = app;
}
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");
--------继续往下,还未通过zygote创建进程呢
final boolean success =
startProcessLocked(app, hostingRecord, zygotePolicyFlags, abiOverride);
checkSlow(startTime, "startProcess: done starting proc!");
return success ? app : null;
}
frameworks/base/services/core/java/com/android/server/am/ProcessList.java
@GuardedBy("mService")
boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
int zygotePolicyFlags, String abiOverride) {
return startProcessLocked(app, hostingRecord, zygotePolicyFlags,
false /* disableHiddenApiChecks */, false /* disableTestApiChecks */,
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,
String abiOverride) {
if (app.isPendingStart()) {
return true;
}
...
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
final String entryPoint = "android.app.ActivityThread";
------------继续往下
return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,
instructionSet, invokeWith, startTime);
...
}
@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());
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) {
Slog.e(ActivityManagerService.TAG, "Failure starting process "
+ app.processName, e);
app.setPendingStart(false);
mService.forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
false, false, true, false, false, app.userId, "start failure");
}
return app.getPid() > 0;
}
}
frameworks/base/services/core/java/com/android/server/am/ProcessList.java
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);
checkSlow(startTime, "startProcess: asking zygote to start proc");
final boolean isTopApp = hostingRecord.isTopApp();
if (isTopApp) {
// Use has-foreground-activities as a temporary hint so the current scheduling
// group won't be lost when the process is attaching. The actual state will be
// refreshed when computing oom-adj.
app.mState.setHasForegroundActivities(true);
}
Map> pkgDataInfoMap;
Map> allowlistedAppDataInfoMap;
boolean bindMountAppStorageDirs = false;
boolean bindMountAppsData = mAppDataIsolationEnabled
&& (UserHandle.isApp(app.uid) || UserHandle.isIsolated(app.uid))
&& mPlatformCompat.isChangeEnabled(APP_DATA_DIRECTORY_ISOLATION, app.info);
// Get all packages belongs to the same shared uid. sharedPackages is empty array
// if it doesn't have shared uid.
final PackageManagerInternal pmInt = mService.getPackageManagerInternal();
final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage(
app.info.packageName, app.userId);
final String[] targetPackagesList = sharedPackages.length == 0
? new String[]{app.info.packageName} : sharedPackages;
pkgDataInfoMap = getPackageAppDataInfoMap(pmInt, targetPackagesList, uid);
if (pkgDataInfoMap == null) {
// TODO(b/152760674): Handle inode == 0 case properly, now we just give it a
// tmp free pass.
bindMountAppsData = false;
}
// Remove all packages in pkgDataInfoMap from mAppDataIsolationAllowlistedApps, so
// it won't be mounted twice.
final Set allowlistedApps = new ArraySet<>(mAppDataIsolationAllowlistedApps);
for (String pkg : targetPackagesList) {
allowlistedApps.remove(pkg);
}
allowlistedAppDataInfoMap = getPackageAppDataInfoMap(pmInt,
allowlistedApps.toArray(new String[0]), uid);
if (allowlistedAppDataInfoMap == null) {
// TODO(b/152760674): Handle inode == 0 case properly, now we just give it a
// tmp free pass.
bindMountAppsData = false;
}
int userId = UserHandle.getUserId(uid);
StorageManagerInternal storageManagerInternal = LocalServices.getService(
StorageManagerInternal.class);
if (needsStorageDataIsolation(storageManagerInternal, app)) {
// We will run prepareStorageDirs() after we trigger zygote fork, so it won't
// slow down app starting speed as those dirs might not be cached.
if (pkgDataInfoMap != null && storageManagerInternal.isFuseMounted(userId)) {
bindMountAppStorageDirs = true;
} else {
// Fuse is not mounted or inode == 0,
// so we won't mount it in zygote, but resume the mount after unlocking device.
app.setBindMountPending(true);
bindMountAppStorageDirs = false;
}
}
// If it's an isolated process, it should not even mount its own app data directories,
// since it has no access to them anyway.
if (app.isolated) {
pkgDataInfoMap = null;
allowlistedAppDataInfoMap = null;
}
final Process.ProcessStartResult startResult;
boolean regularZygote = false;
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()});
}
if (!regularZygote) {
// webview and app zygote don't have the permission to create the nodes
if (Process.createProcessGroup(uid, startResult.pid) < 0) {
Slog.e(ActivityManagerService.TAG, "Unable to create process group for "
+ app.processName + " (" + startResult.pid + ")");
}
}
// This runs after Process.start() as this method may block app process starting time
// if dir is not cached. Running this method after Process.start() can make it
// cache the dir asynchronously, so zygote can use it without waiting for it.
if (bindMountAppStorageDirs) {
storageManagerInternal.prepareStorageDirs(userId, pkgDataInfoMap.keySet(),
app.processName);
}
checkSlow(startTime, "startProcess: returned from zygote!");
return startResult;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
frameworks/base/core/java/android/os/Process.java
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>
pkgDataInfoMap,
@Nullable Map>
whitelistedDataInfoMap,
boolean bindMountAppsData,
boolean bindMountAppStorageDirs,
@Nullable String[] zygoteArgs) {
--------通过zygote创建进程
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);
}