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

news2025/2/23 10:51:58

系列文章

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

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

45.1 EnsureActivitiesVisibleHelper#makeVisibleAndRestartIfNeeded

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 */);
-----------后面会展开讲解
        }
    }

45.2 ActivityRecord#makeInvisible

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

46. ActivityTaskSupervisor#startSpecificActivity

紧接着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");
    }

47. ActivityTaskSupervisor#startProcessAsync

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

48. ActivityManagerService#startProcess

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

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

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

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.coloradmin.cn/o/1142628.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

17、简单记录一下两个流媒体工具和推流测试

基本思想:在开发流媒体服务过程中,使用了两个流媒体工具,这里做一下简单的记录,以后可以翻阅和查看 一:流媒体服务工具之一:https://github.com/bluenviron/mediamtx/releases 它支持rtsp/rtmp/hls推流测试 二、流媒体工具:Releases EasyDarwin/EasyDarwin GitHub 该…

华为认证H12-831考试新增题库

279、 以下哪些数列能被正则表达式[^100|200]$匹配? A、300 200 100 B、200 100 300 C、100 200 300 D、100 300 200 试题答案&#xff1a;BC 试题解析&#xff1a;[^ ]表示不包括字符&#xff0c;$表示以某字符结尾。题目的正则表达式表示不以100 200 结…

【CMake】windows10下入门课程

【CMake】windows10下入门课程 提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论 文章目录 【CMake】windows10下入门课程前言cmake安装初识cmake&#xff1a;新建helloworld项目cmake的入门使用法则总结 前言 CMake(Cross-Platform Make)是一个开源的跨平…

高效文件管理:自动生成文件夹及重命名的方法分享

在高效文件管理中&#xff0c;自动生成文件夹及重命名是一项非常实用的技巧。通过掌握这种方法&#xff0c;我们能够更轻松地整理和查找文件&#xff0c;提高工作效率。本文将分享云炫文件管理器自动生成文件夹及重命名的实用方法&#xff0c;帮助您实现高效的文件管理。现在跟…

OSPF NSSA区域配置

NSSA&#xff1a;Not-So-Stubby Area&#xff08;不太末节的区域&#xff09; 示例&#xff0c;拓朴如下&#xff1a; 思路&#xff1a; R1正常配置Area 0区域&#xff0c;R2的1口配置为区域0&#xff0c;2口配置为区域1&#xff0c;配置NSSA&#xff0c;R3配置为区域1…

如何在Windows和Linux系统上监听文件夹的变动?

文章目录 如何在Windows和Linux系统上监听文件夹的变动&#xff1f;读写文件文件系统的操作缓冲和流文件改变事件 如何在Windows和Linux系统上监听文件夹的变动&#xff1f; libuv库实现了监听整个文件夹的修改。本文详细介绍libuv库文件读写和监听的的实现方法。libuv库开发了…

【计算机网络笔记】Cookie技术

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…

Linux系统下安全控制策略SELinux解析

SELinux&#xff08;Security-Enhanced linux&#xff09;是增强版Linux&#xff0c;简称SELinux&#xff0c;它是一个Linux内核模块&#xff0c;也是Linux的一个安全子系统&#xff0c;主要以内核模块为支持&#xff0c;用户态程序进行权限策略管理。 背景 Linux系统下的roo…

镍氢充电管理芯片-IC AH2185

镍氢充电管理芯片AH2185&#xff1a;为便携式设备提供高效充电解决方案 随着科技的不断发展&#xff0c;便携式设备在人们的生活中扮演着越来越重要的角色。这些设备包括数码相机、电子词典、智能手机等&#xff0c;它们共同的特点是需要定期充电。为了满足这一需求&#xff0…

FFmpeg5.1.3编译动态库踩坑之旅(基于Linux虚拟机)

准备工作 环境准备 1.Windows安装Oracle VM VirtualBox 7.0.10&#xff0c;安装ubuntu-22.04.3。 坑一&#xff1a;无法往虚拟机里拖放复制文件&#xff0c;解决办法&#xff1a;登录Ubuntu虚拟机时切换到xorg方式登录&#xff0c;参考地址&#xff1a;Ubuntu Desktop 22.04…

LLVM学习笔记(55)

4.1.3. 降级 在前面的章节里&#xff0c;我们展示了目标机器特定节点与目标机器无关节点共存的一个图。你可能会问&#xff0c;如果这是指令选择的一个输入&#xff0c;为什么在SelectionDAG类中已经有一些目标机器特定的节点&#xff1f;要理解这&#xff0c;我们首先在下图概…

Kafka - 3.x 图解Broker总体工作流程

文章目录 Zk中存储的kafka的信息Kafka Broker总体工作流程1. broker启动后向zk中注册2. Controller谁先启动注册&#xff0c;谁说了算3. 由选举出来的Controller监听brokers节点的变化4. Controller决定leader选举5. Controller将节点信息上传到Zk中6. 其他Controller从zk中同步…

numpy和字符串格式化,用*画田字形状

numpy的字符型元素矩阵&#xff0c;可以方便画&#xff1b;直接python字符串手撕&#xff0c;也可以轻巧完成。 (本笔记适合熟悉循环和列表的 coder 翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&#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…

科聪协作(复合)移动机器人整体解决方案

协作&#xff08;复合&#xff09;移动机器人&#xff08;AGV/AMR&#xff09;相较传统工业机器人具有更加安全和简单的工作优势&#xff0c;具备较强的发展潜力。协作&#xff08;复合&#xff09;移动机器人安全性和操作的简洁性、灵活性不断提高,优势得到了充分发挥,在越来越…

浏览器事件循环 (event loop)

进程与线程 进程 进程的概念 进程是操作系统中的一个程序或者一个程序的一次执行过程&#xff0c;是一个动态的概念&#xff0c;是程序在执行过程中分配和管理资源的基本单位&#xff0c;是操作系统结构的基础。 简单的来说&#xff0c;就是一个程序运行开辟的一块内存空间&a…

Windows-Oracle19c 安装详解-含Navicate远程连接配置 - 同时连接Oracle11g和Oracle19c

文章目录 0 说明1 下载链接2 安装&#xff1a;一定要以管理员身份运行&#xff0c;不然后面有可能会报错。3 启动监听4. 登录Oracle4 Navicate远程连接-配置监听4.1 修改监听文件4.2 网络配置助手-配置本地监听端口4.3 Navicate连接成功 5 Navicate同时连接两个Oracle数据库 0 …

读高性能MySQL(第4版)笔记21_读后总结与感想兼导读

1. 基本信息 高性能MySQL&#xff1a;经过大规模运维验证的策略&#xff08;第4版&#xff09; High Performance MySQL, Fourth Edition [美] Silvia Botros(西尔维亚博特罗斯)&#xff1b;Jeremy Tinley(杰里米廷利) 电子工业出版社,2022年10月出版 1.1. 读薄率 书籍总字…

窗帘布艺经营配送小程序商城的效果如何

窗帘布艺覆盖生活中多个使用场景&#xff0c;可以说是必需品&#xff0c;由于需要客户提供尺寸乃至上门安装等&#xff0c;因此传统客户购买此类产品&#xff0c;一般会选择线下亲自购买&#xff0c;包括质感、论价、挑选等。 但随着互联网电商深入&#xff0c;线上销售和客户…

Java NIO 高并发开发

Java NIO 高并发开发 前言 Java NIO&#xff08;New I/O&#xff09;相比于传统的Java I/O&#xff08;BIO&#xff09;在高并发开发方面具有以下优势&#xff1a; 非阻塞模式&#xff1a;Java NIO使用非阻塞的I/O操作&#xff0c;允许一个线程管理多个通道&#xff08;Channe…