Android S从桌面点击图标启动APP流程 (五)

系列文章

Android S从桌面点击图标启动APP流程 (一)
Android S从桌面点击图标启动APP流程 (二)

Android S从桌面点击图标启动APP流程 (三)

Android S从桌面点击图标启动APP流程 (四)

Android S从桌面点击图标启动APP流程 (五)

Android S从桌面点击图标启动APP流程 (六)

Android 12的源码链接:

Android 12 AOSPicon-default.png?t=N7T8http://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=INITIALIZING

free住屏幕
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]

具体过程如下:

42. Task#ensureActivitiesVisible

    void ensureActivitiesVisible(@Nullable ActivityRecord starting, int configChanges,boolean preserveWindows) {ensureActivitiesVisible(starting, configChanges, preserveWindows, true /* notifyClients */);}

43. Task#ensureActivitiesVisible

通过更新可见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 changedforAllTasks(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();}}

44. EnsureActivitiesVisibleHelper#process

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();}}

45. EnsureActivitiesVisibleHelper#setActivityVisibilityState

frameworks/base/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.javaprivate 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 activitymakeVisibleAndRestartIfNeeded(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 flagmConfigChanges |= 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;}}

45.1 EnsureActivitiesVisibleHelper#makeVisibleAndRestartIfNeeded

frameworks/base/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.javaprivate 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可见性设为truer.setVisibility(true);}if (r != starting) {
-----------然后开始去启动将要resume的activitymTask.mTaskSupervisor.startSpecificActivity(r, andResume, true /* checkConfig */);
-----------后面会展开讲解}}

45.2 ActivityRecord#makeInvisible

frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.javavoid 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();}}

46. ActivityTaskSupervisor#startSpecificActivity

紧接着45.1,即将要去启动将要resume的APP,如果没有进程,则会创建进程。

frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.javavoid 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");}

47. ActivityTaskSupervisor#startProcessAsync

frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.javavoid 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);}}

48. ActivityManagerService#startProcess

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java@Overridepublic 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);}}

49. ActivityManagerService#startProcessLocked

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 */);}

50. ProcessList#startProcessLocked

frameworks/base/services/core/java/com/android/server/am/ProcessList.javaProcessRecord 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 killedSlog.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 为nullif (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 listapp.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;}

51. ProcessList#startProcessLocked

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;}}

52. ProcessList#startProcess

frameworks/base/services/core/java/com/android/server/am/ProcessList.javaprivate 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<String, Pair<String, Long>> pkgDataInfoMap;Map<String, Pair<String, Long>> 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<String> 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 nodesif (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);}}

53. Process#start

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<String, Pair<String, Long>>pkgDataInfoMap,@Nullable Map<String, Pair<String, Long>>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);}

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

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

相关文章

Unable to find GatewayFilterFactory with name TokenRelay

目录 问题分析解决方案参考文档开源项目微服务商城项目前后端分离项目 问题分析 Spring Cloud Gateway 网关作为代理资源服务器&#xff0c;需要将 JWT 传递给下游资源服务器&#xff0c;下面是网关的配置 spring:cloud:gateway:discovery:locator:enabled: true # 启用服务发…

应用案例|基于高精度三维机器视觉引导机器人自动分拣包裹的应用

Part.1 行业背景 近年来&#xff0c;电商高速发展&#xff0c;百万件日订单处理的超大型分拣中心模式日益普及&#xff0c;传统的人工供包模式效率低&#xff0c;难以满足高超大分拣中心对分拣包裹的需求。随着科技的进步&#xff0c;自动供包系统进入大众视野&#xff0c;成为…

Flutter extended_image库设置内存缓存区大小与缓存图片数

ExtendedImage ExtendedImage 是一个Flutter库&#xff0c;用于提供高级图片加载和显示功能。这个库使用了 image 包来进行图片的加载和缓存。如果你想修改缓存大小&#xff0c;你可以通过修改ImageCache的配置来实现。 1. 获取ImageCache实例: 你可以通过PaintingBinding…

Kafka - 3.x 副本不完全指北

文章目录 kafka 副本的基本信息Leader选举过程Kafka Controllerkafka 分区副本Leader的选举流程实际演示① 查看first的详细信息&#xff0c;注意观察副本分布情况② 停掉hadoop103上的kafka进程③ 再次查看first的相信信息&#xff0c;观察副本分布④ 处理分区leader分布不均匀…

mac电脑视频处理推荐:达芬奇DaVinci Resolve Studio 18 中文最新

DaVinci Resolve Studio 18是一款专业的视频编辑、调色和后期制作软件&#xff0c;由Blackmagic Design开发。它被广泛应用于电影、电视和广告等行业&#xff0c;提供了全面的工具和功能&#xff0c;使用户能够进行高质量的影片制作和后期处理。 以下是DaVinci Resolve Studio…

谷歌云的利润增长才刚刚开始

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 总结&#xff1a; &#xff08;1&#xff09;自从Google Cloud(谷歌云&#xff09;今年开始盈利以来&#xff0c;投资者都在怀疑这种盈利能力能否持续下去。 &#xff08;2&#xff09;虽然微软Azure目前在全球的人工智能竞…

工业自动化产品抗干扰笔记

工业自动化产品抗干扰笔记 名词解释&#xff1a; 耦合矢量控制寄生振荡热噪点闪变噪点尖峰噪点反电势集肤效应交流电阻感抗容抗寄生电容共模与差模电场和磁场漏电流浪涌电压电流传输与电压传输各种地线解析 一、干扰来源&#xff1a; 任何一个电磁干扰现象都具有电磁干扰源…

关于亚马逊 CodeWhisperer 的测试反馈

CodeWhisperer 是亚马逊推出的实时 AI 编程助手&#xff0c;是一项基于机器学习的服务&#xff0c;它可以分析开发者在集成开发环境&#xff08;IDE&#xff09;中的注释和代码&#xff0c;并根据其内容生成多种代码建议。 亚马逊云科技开发者社区为开发者们提供全球的开发技术…

【QT】对象树

一、QT对象树的概念 先来看一下 QObject 的构造函数&#xff1a; 通过帮助文档我们可以看到&#xff0c;QObject 的构造函数中会传入一个 Parent 父对象指针&#xff0c;children() 函数返回 QObjectList。即每一个 QObject 对象有且仅有一个父对象&#xff0c;但可以有很多个…

如何集成验证码短信API到你的应用程序

引言 当你需要为你的应用程序增加安全性和用户验证功能时&#xff0c;集成验证码短信API是一个明智的选择。验证码短信API可以帮助你轻松实现用户验证、密码重置和账户恢复等功能&#xff0c;提高用户体验并增强应用程序的安全性。本文将介绍如何将验证码短信API集成到你的应用…

什么c++流行造轮子而不是调包侠?

什么c流行造轮子而不是调包侠&#xff1f; 因为在c&#xff08;和c&#xff09;中&#xff0c;你造的轮子是真的可以跟官方的轮子拼性能的&#xff0c;只要你的算法足够优秀&#xff0c;实现足够小心。 最近很多小伙伴找我&#xff0c;说想要一些c资料&#xff0c;然后我根据自…

在windows服务器上部署一个单机项目以及前后端分离项目

目录 一. 单机项目在windows服务器上的部署 1.1 在本机上测试项目无误 1.1.1 在数据库中测试sql文件没问题 1.1.2 在tomcat中测试war文件无误 1.1.3 测试完成后&#xff0c;进入浏览器运行单机项目确保无误 1.2 在windows服务器中运行项目 二. 前后端分离项目在服务器上…

【工具使用】使用Audition增加增益的方法

一&#xff0c;简介 本文主要介绍如何在Adobe Audition 2020中改变波形的幅值。供参考。 二&#xff0c;操作方法 这里使用1KHz&#xff0c;-120dB信号为例。 2.1 方法一&#xff1a;直接使用悬浮窗口 窗口中输入6&#xff0c;波形的幅值就变成了-114dB。 注意&#xff1a…

鸿蒙ArkUI-X跨端应用开发,一套代码构建多平台应用

文章目录 一、项目介绍二、技术架构三、Gitee仓库地址四、ArkUI-X开发者文档五、快速开始——环境准备1、下载DevEco Studio&#xff0c;版本V4.0 Beta2以上2、打开DevEco&#xff0c;下载相关环境配置3、配置开发环境3.1、OpenHarmony SDK3.2、安装ArkUI-X SDK3.2、Android SD…

IDEA 断点高阶

一、按钮介绍 1.1 补充 返回断点处&#xff1a; 设置debug配置&#xff1a; 二、增加/切换debugger视图 三、window快捷键 所在行处&#xff1a; CtrlF8断点属性编辑&#xff1a; CtrlShiftF8 四、一些常用的高级功能 4.1 查看对象内存-Attach memory agent 1.勾选Atta…

Redis(04)| 数据结构-压缩列表

压缩列表的最大特点&#xff0c;就是它被设计成一种内存紧凑型的数据结构&#xff0c;占用一块连续的内存空间&#xff0c;不仅可以利用 CPU 缓存&#xff0c;而且会针对不同长度的数据&#xff0c;进行相应编码&#xff0c;这种方法可以有效地节省内存开销。 但是&#xff0c;…

微信小程序如何使用地球半径计算两组经纬度点之间的距离(自身位置与接口返回位置)【上】

目录 1.配置位置权限 2.获取当前自身经纬度 3. 请求接口拿到返回经纬 4. 循环取每一项的经纬 5.如何判断是否打开了定位权限 6.进行距离计算操作 7.运行效果 8.完整代码 首先在使用小程序时&#xff0c;请求的接口一定要去配置合法域名&#xff0c;才能够进行接下来…

【httpd】 Apache http服务器目录显示不全解决

文章目录 1. 文件名过长问题1.1 在centos中文件所谓位置etc/httpd/conf.d/httpd-autoindex.conf1.2 在配置文件httpd-autoindex.conf中的修改&#xff1a;1.3 修改完成后重启Apache&#xff1a; 1. 文件名过长问题 1.1 在centos中文件所谓位置etc/httpd/conf.d/httpd-autoindex…

cola架构:cola源码中访问者模式应用浅析

目录 1.访问者模式简介 2.cola访问者模式应用 2.1 cola被访问者类图 2.2 cola访问者类图 我们知道&#xff0c;如果一个对象结构包含很多类型的对象&#xff0c;希望对这些对象实施一些依赖其具体类型的操作&#xff0c;但又避免让这些操作“污染”这些对象的类&#xff0c…

竞赛 深度学习卫星遥感图像检测与识别 -opencv python 目标检测

文章目录 0 前言1 课题背景2 实现效果3 Yolov5算法4 数据处理和训练5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **深度学习卫星遥感图像检测与识别 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐…