Android 12 S ActivityManager解读之从dumpsys activity activities看activity

12 篇文章 1 订阅
6 篇文章 0 订阅

Display #0 (activities from top to bottom):
  * Task{45dbacd #1 //标志1type=home ?? U=0 //标志2visible=true visibleRequested=true   //标志3mode=fullscreen translucent=false sz=1}
    * Task{c41a1a1 #8 type=home I=com.android.launcher3/.uioverrides.QuickstepLauncher U=0 rootTaskId=1 visible=true visibleRequested=true mode=fullscreen translucent=false sz=1}
      mLastPausedActivity(上一次paused的activity): ActivityRecord{b9be218 u0 com.android.launcher3/.uioverrides.QuickstepLauncher t8}
      isSleeping=false
      topResumedActivity(top Resumed的activity)=ActivityRecord{b9be218 u0 com.android.launcher3/.uioverrides.QuickstepLauncher t8}
      * Hist  #0: ActivityRecord{b9be218 u0 com.android.launcher3/.uioverrides.QuickstepLauncher t8}
        (包名)packageName=com.android.launcher3 (进程名)processName=com.android.launcher3
        launchedFromUid=0 launchedFromPackage=null launchedFromFeature=null userId=0
        app=ProcessRecord{b1fce62 2666:com.android.launcher3/u0a107}
        Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.android.launcher3/.uioverrides.QuickstepLauncher (has extras) }
        (是否是根task)rootOfTask=true task=Task{c41a1a1 #8 type=home I=com.android.launcher3/.uioverrides.QuickstepLauncher U=0 rootTaskId=1 visible=true visibleRequested=true mode=fullscreen translucent=false sz=1}
        taskAffinity=null
        mActivityComponent=com.android.launcher3/.uioverrides.QuickstepLauncher
        (apk路径)baseDir=/system_ext/priv-app/Launcher3QuickStep/Launcher3QuickStep.apk
        (data数据路径)dataDir=/data/user/0/com.android.launcher3
        stateNotNeeded=true componentSpecified=false mActivityType=home
        compat={640dpi always-compat} labelRes=0x7f10007d icon=0x7f080250 theme=0x7f11000e
        mLastReportedConfigurations:
          (当前global config)mGlobalConfig={1.0 ?mcc?mnc [en_US] ldltr sw960dp w1776dp h876dp 640dpi xlrg long land vrheadset -touch -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 7104, 3840) mAppBounds=Rect(0, 0 - 7104, 3600) mMaxBounds=Rect(0, 0 - 7104, 3840) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_0} s.68 fontWeightAdjustment=0}
          (上一次的config)mOverrideConfig={1.0 ?mcc?mnc [en_US] ldltr sw960dp w1776dp h876dp 640dpi xlrg long land vrheadset -touch -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 7104, 3840) mAppBounds=Rect(0, 0 - 7104, 3600) mMaxBounds=Rect(0, 0 - 7104, 3840) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=home mAlwaysOnTop=undefined mRotation=ROTATION_0} s.3 fontWeightAdjustment=0}
        (当前Configuration)CurrentConfiguration={1.0 ?mcc?mnc [en_US] ldltr sw960dp w1776dp h876dp 640dpi xlrg long land vrheadset -touch -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 7104, 3840) mAppBounds=Rect(0, 0 - 7104, 3600) mMaxBounds=Rect(0, 0 - 7104, 3840) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=home mAlwaysOnTop=undefined mRotation=ROTATION_0} s.3 fontWeightAdjustment=0}
        RequestedOverrideConfiguration={0.0 ?mcc?mnc ?localeList ?layoutDir ?swdp ?wdp ?hdp ?density ?lsize ?long ?ldr ?wideColorGamut ?orien ?uimode ?night ?touch ?keyb/?/? ?nav/? winConfig={ mBounds=Rect(0, 0 - 0, 0) mAppBounds=null mMaxBounds=Rect(0, 0 - 0, 0) mWindowingMode=undefined mDisplayWindowingMode=undefined mActivityType=home mAlwaysOnTop=undefined mRotation=undefined} ?fontWeightAdjustment}
        taskDescription: label="null" icon=null iconResource=/0 iconFilename=null primaryColor=fff0f0f3
         (各布局颜色)backgroundColor=fff0f0f3 statusBarColor=0 navigationBarColor=0
         backgroundColorFloating=fff0f0f3
        launchFailed=false launchCount=0 lastLaunchTime=-2h20m41s36ms
        mHaveState=false mIcicle=null
        (当前activity状态)//标志4state=RESUMED stopped=false delayedResume=false finishing=false
        keysPaused=false inHistory=true idle=true
        occludesParent=true noDisplay=false immersive=false launchMode=2
        frozenBeforeDestroy=false forceNewConfig=false
        mActivityType=home
        mImeInsetsFrozenUntilStartInput=false
        windows=[Window{8097e4a u0 com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher}]
        windowType=2 hasVisible=true
        mOccludesParent=true
        mOrientation=SCREEN_ORIENTATION_UNSPECIFIED
        mVisibleRequested=true mVisible=true mClientVisible=true reportedDrawn=true reportedVisible=true
        mNumInterestingWindows=1 mNumDrawnWindows=1 allDrawn=true lastAllDrawn=true)
        startingData=null firstWindowDrawn=true mIsExiting=false
        nowVisible=true lastVisibleTime=-8s20ms
        connections={ConnectionRecord{7a9ad43 u0 com.android.launcher3/com.android.quickstep.TouchInteractionService:@3e082f2}}
        resizeMode=RESIZE_MODE_RESIZEABLE
        mLastReportedMultiWindowMode=false mLastReportedPictureInPictureMode=false
        supportsSizeChanges=SIZE_CHANGES_UNSUPPORTED_METADATA
        configChanges=0xdf3
        neverSandboxDisplayApis=false
        alwaysSandboxDisplayApis=false
        areBoundsLetterboxed=false

 ACTIVITY TYPE

 标志1代表当前Activity的类型,Activity共有以下几种类型:

ACTIVITY TYPEValue含义
ACTIVITY_TYPE_UNDEFINED0当前Activity type未定义
ACTIVITY_TYPE_STANDARD1标准的Activity type,这个Activity没有特别的地方
ACTIVITY_TYPE_HOME2Home/Launcher activity type
ACTIVITY_TYPE_RECENTS3Recents/Overview activity type,系统中只会存在一个这种类型的activity
ACTIVITY_TYPE_ASSISTANT4Assistant activity type。语音助手
ACTIVITY_TYPE_DREAM5Dream activity type。手机屏保

visible

标志2代表当前activity是否可见。流程如下:

/frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java

    boolean shouldBeVisible() {
        final Task rootTask = getRootTask();
        if (rootTask == null) {
            return false;
        }

        final boolean behindFullscreenActivity = !rootTask.shouldBeVisible(null /* starting */) || rootTask.getOccludingActivityAbove(this) != null;
        return shouldBeVisible(behindFullscreenActivity, false /* ignoringKeyguard */);
    }
    /** @return {@code true} if this activity should be made visible. */
    private boolean shouldBeVisible(boolean behindFullscreenActivity, boolean ignoringKeyguard) {
        updateVisibilityIgnoringKeyguard(behindFullscreenActivity);

        if (ignoringKeyguard) {
            return visibleIgnoringKeyguard;
        }

        return shouldBeVisibleUnchecked();
    }

WINDOWING MODE

标志3 处代表的是当前Activity的window mode.

 WINDOWING MODEValue含义
WINDOWING_MODE_UNDEFINED0未定义的window mode
WINDOWING_MODE_FULLSCREEN1占用整个屏幕或父容器的区域的window mode
WINDOWING_MODE_PINNED2始终在顶部(始终可见)。对父容器中其他兄弟容器的
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY3在分屏模式下的主容器
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY4在分屏模式下的第二容器
WINDOWING_MODE_FREEFORM5自由窗口,可以在父容器中自由调整大小
WINDOWING_MODE_MULTI_WINDOW6通用多窗口,没有来自窗口管理器的表示属性

ActivityState

标志4代表当前Activity的状态,enum ActivityState内容如下:

ActivityState含义
INITIALIZINGnew ActivityRecord后的第一个状态,
STARTED已经start
RESUMED已经resumed完成
PAUSING正在pausing
PAUSED已经pause完成
STOPPING正在stopping
STOPPED已经stop完成
FINISHING正在finishing
DESTROYING正在destroying
DESTROYED已经destroy
RESTARTING_PROCESS重新start

Activity State的状态转变是由setState方法进行设置的,后面跟有原因。

/frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java

    void setState(ActivityState state, String reason) {
        ProtoLog.v(WM_DEBUG_STATES, "State movement: %s from:%s to:%s reason:%s",
                this, getState(), state, reason);

        if (state == mState) {//这次和上次没变化
            // No need to do anything if state doesn't change.
            ProtoLog.v(WM_DEBUG_STATES, "State unchanged from:%s", state);
            return;
        }

        mState = state;

        if (task != null) {
            task.onActivityStateChanged(this, state, reason);
        }

        // The WindowManager interprets the app stopping signal as
        // an indication that the Surface will eventually be destroyed.
        // This however isn't necessarily true if we are going to sleep.
        if (state == STOPPING && !isSleeping()) {
            if (getParent() == null) {
                Slog.w(TAG_WM, "Attempted to notify stopping on non-existing app token: " + appToken);
                return;
            }
        }
        if (app != null) {
            mTaskSupervisor.onProcessActivityStateChanged(app, false /* forceBatch */);
        }

        switch (state) {
            case RESUMED:
                mAtmService.updateBatteryStats(this, true);
                mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_RESUMED);
                // Fall through.
            case STARTED:
// Update process info while making an activity from invisible to visible, to make sure the process state is updated to foreground.
                if (app != null) {
                    app.updateProcessInfo(false /* updateServiceConnectionActivities */, true /* activityChange */, true /* updateOomAdj */,true /* addPendingTopUid */);
                }
                final ContentCaptureManagerInternal contentCaptureService =
               LocalServices.getService(ContentCaptureManagerInternal.class);
                if (contentCaptureService != null) {
                    contentCaptureService.notifyActivityEvent(mUserId, mActivityComponent, ActivityEvent.TYPE_ACTIVITY_STARTED);
                }
                break;
            case PAUSED:
                mAtmService.updateBatteryStats(this, false);
                mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_PAUSED);
                break;
            case STOPPED:
               mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_STOPPED);
                break;
            case DESTROYED:
                mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_DESTROYED);
                // Fall through.
            case DESTROYING:
                if (app != null && !app.hasActivities()) {
// Update any services we are bound to that might care about whether their client may have activities. No longer have activities, so update LRU list and oom adj.
                    app.updateProcessInfo(true /* updateServiceConnectionActivities */,false /* activityChange */, true /* updateOomAdj */, false /* addPendingTopUid */);
                }
                break;
        }
    }

 1. setState STARTED

/frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java

    /**
     * Make activity resumed or paused if needed.
     * @param activeActivity an activity that is resumed or just completed pause action.
     *                       We won't change the state of this activity.
     */
    boolean makeActiveIfNeeded(ActivityRecord activeActivity) {
...
        } else if (shouldStartActivity()) {
            if (DEBUG_VISIBILITY) {
                Slog.v(TAG_VISIBILITY, "Start visible activity, " + this);
            }
            setState(STARTED, "makeActiveIfNeeded");
            try {
//执行动画
                mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken, StartActivityItem.obtain(takeOptions()));
            } catch (Exception e) {
                Slog.w(TAG, "Exception thrown sending start: " + intent.getComponent(), e);
            }
            // The activity may be waiting for stop, but that is no longer appropriate if we are starting the activity again
            mTaskSupervisor.mStoppingActivities.remove(this);
        }
        return false;
    }

2. setState STARTED

frameworks/base/services/core/java/com/android/server/wm/Task.java

    void minimalResumeActivityLocked(ActivityRecord r) {
        ProtoLog.v(WM_DEBUG_STATES, "Moving to RESUMED: %s (starting new instance) " + "callers=%s", r, Debug.getCallers(5));
        r.setState(RESUMED, "minimalResumeActivityLocked");
        r.completeResumeLocked();
    }
    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options,
            boolean deferPause) {

......

        ActivityRecord next = topRunningActivity(true /* focusableOnly */);

......

        if (next.attachedToProcess()) {
            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next
                    + " stopped=" + next.stopped
                    + " visibleRequested=" + next.mVisibleRequested);
            final boolean lastActivityTranslucent = lastFocusedRootTask != null
                    && (lastFocusedRootTask.inMultiWindowMode()
                    || (lastFocusedRootTask.mLastPausedActivity != null
                    && !lastFocusedRootTask.mLastPausedActivity.occludesParent()));

            // This activity is now becoming visible.
            if (!next.mVisibleRequested || next.stopped || lastActivityTranslucent) {
                next.setVisibility(true);
            }

            // schedule launch ticks to collect information about slow apps.
            next.startLaunchTickingLocked();

            ActivityRecord lastResumedActivity =
                    lastFocusedRootTask == null ? null : lastFocusedRootTask.getResumedActivity();
            final ActivityState lastState = next.getState();

            mAtmService.updateCpuStats();

            ProtoLog.v(WM_DEBUG_STATES, "Moving to RESUMED: %s (in existing)", next);

            next.setState(RESUMED, "resumeTopActivityInnerLocked");

......

            try {
......
            } catch (Exception e) {
                // Whoops, need to restart this activity!
                ProtoLog.v(WM_DEBUG_STATES, "Resume failed; resetting state to %s: "
                        + "%s", lastState, next);
                next.setState(lastState, "resumeTopActivityInnerLocked");

                // lastResumedActivity being non-null implies there is a lastStack present.
                if (lastResumedActivity != null) {
                  lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked");
                }
......

3. setState PAUSING

    boolean makeActiveIfNeeded(ActivityRecord activeActivity) {
......
        } else if (shouldPauseActivity(activeActivity)) {
            if (DEBUG_VISIBILITY) {
                Slog.v(TAG_VISIBILITY, "Pause visible activity, " + this);
            }
            // An activity must be in the {@link PAUSING} state for the system to validate
            // the move to {@link PAUSED}.
            setState(PAUSING, "makeActiveIfNeeded");
            try {
                mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken, PauseActivityItem.obtain(finishing, false /* userLeaving */,configChangeFlags, false /* dontReport */));
            } catch (Exception e) {
                Slog.w(TAG, "Exception thrown sending pause: " + intent.getComponent(), e);
            }

    final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
            ActivityRecord resuming, String reason) {
......
        if (mPausingActivity != null) {
            Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity + " state=" + mPausingActivity.getState());
            if (!shouldSleepActivities()) {
                // Avoid recursion among check for sleep and complete pause during sleeping. Because activity will be paused immediately after resume, just let pause be completed by the order of activity paused from clients.
                completePauseLocked(false, resuming);
            }
        }
        ActivityRecord prev = mResumedActivity;

        if (prev == null) {
            if (resuming == null) {
                Slog.wtf(TAG, "Trying to pause when nothing is resumed");
                mRootWindowContainer.resumeFocusedTasksTopActivities();
            }
            return false;
        }

        if (prev == resuming) {
            Slog.wtf(TAG, "Trying to pause activity that is in process of being resumed");
            return false;
        }

        ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSING: %s", prev);
        mPausingActivity = prev;
        mLastPausedActivity = prev;
        if (prev.isNoHistory() && !mTaskSupervisor.mNoHistoryActivities.contains(prev)) {
            mTaskSupervisor.mNoHistoryActivities.add(prev);
        }
        prev.setState(PAUSING, "startPausingLocked");
        prev.getTask().touchActiveTime();

......

4. setState PAUSED

    void activityPaused(boolean timeout) {
        ProtoLog.v(WM_DEBUG_STATES, "Activity paused: token=%s, timeout=%b", appToken, timeout);

        if (task != null) {
            removePauseTimeout();

            final ActivityRecord pausingActivity = task.getPausingActivity();
            if (pausingActivity == this) {
                ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSED: %s %s", this,
                        (timeout ? "(due to timeout)" : " (pause complete)"));
                mAtmService.deferWindowLayout();
                try {
                    task.completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
                } finally {
                    mAtmService.continueWindowLayout();
                }
                return;
            } else {
                EventLogTags.writeWmFailedToPause(mUserId, System.identityHashCode(this), shortComponentName, pausingActivity != null ? pausingActivity.shortComponentName : "(none)");
                if (isState(PAUSING)) {
                    setState(PAUSED, "activityPausedLocked");
                    if (finishing) {
                        ProtoLog.v(WM_DEBUG_STATES,
                        "Executing finish of failed to pause activity: %s", this);
                        completeFinishing("activityPausedLocked");
                    }
                }
            }
        }

        mDisplayContent.handleActivitySizeCompatModeIfNeeded(this);
        mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
    }

    void relaunchActivityLocked(boolean preserveWindow) {
        if (mAtmService.mSuppressResizeConfigChanges && preserveWindow) {
            configChangeFlags = 0;
            return;
        }
        // Do not waiting for translucent activity if it is going to relaunch.
        final Task rootTask = getRootTask();
        if (rootTask != null && rootTask.mTranslucentActivityWaiting == this) {
            rootTask.checkTranslucentActivityWaiting(null);
        }
        final boolean andResume = shouldBeResumed(null /*activeActivity*/);
        List<ResultInfo> pendingResults = null;
        List<ReferrerIntent> pendingNewIntents = null;
        if (andResume) {
            pendingResults = results;
            pendingNewIntents = newIntents;
        }
        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
 "Relaunching: " + this + " with results=" + pendingResults   + " newIntents=" + pendingNewIntents + " andResume=" + andResume  + " preserveWindow=" + preserveWindow);
        if (andResume) {
            EventLogTags.writeWmRelaunchResumeActivity(mUserId, System.identityHashCode(this), task.mTaskId, shortComponentName);
        } else {
            EventLogTags.writeWmRelaunchActivity(mUserId, System.identityHashCode(this),  task.mTaskId, shortComponentName);
        }

        startFreezingScreenLocked(0);

        try {
            ProtoLog.i(WM_DEBUG_STATES, "Moving to %s Relaunching %s callers=%s" ,
             (andResume ? "RESUMED" : "PAUSED"), this, Debug.getCallers(6));
            forceNewConfig = false;
            startRelaunching();
            final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults, pendingNewIntents, configChangeFlags, new MergedConfiguration(getProcessGlobalConfiguration(), getMergedOverrideConfiguration()),  preserveWindow);
            final ActivityLifecycleItem lifecycleItem;
            if (andResume) {
                lifecycleItem = ResumeActivityItem.obtain(isTransitionForward());
            } else {
                lifecycleItem = PauseActivityItem.obtain();
            }
            final ClientTransaction transaction = ClientTransaction.obtain(app.getThread(), appToken);
            transaction.addCallback(callbackItem);
            transaction.setLifecycleStateRequest(lifecycleItem);
            mAtmService.getLifecycleManager().scheduleTransaction(transaction);
            // Note: don't need to call pauseIfSleepingLocked() here, because the caller will only request resume if this activity is currently resumed, which implies we aren't sleeping.
        } catch (RemoteException e) {
            ProtoLog.i(WM_DEBUG_STATES, "Relaunch failed %s", e);
        }

        if (andResume) {
            ProtoLog.d(WM_DEBUG_STATES, "Resumed after relaunch %s", this);
            results = null;
            newIntents = null;
            mAtmService.getAppWarningsLocked().onResumeActivity(this);
        } else {
            removePauseTimeout();
            setState(PAUSED, "relaunchActivityLocked");
        }

     // The activity may be waiting for stop, but that is no longer appropriate for it.
        mTaskSupervisor.mStoppingActivities.remove(this);

        configChangeFlags = 0;
        deferRelaunchUntilPaused = false;
        preserveWindowOnDeferredRelaunch = false;
    }

    void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
        // Complete the pausing process of a pausing activity, so it doesn't make sense to
        // operate on non-leaf tasks.
        warnForNonLeafTask("completePauseLocked");

        ActivityRecord prev = mPausingActivity;
        ProtoLog.v(WM_DEBUG_STATES, "Complete pause: %s", prev);

        if (prev != null) {
            prev.setWillCloseOrEnterPip(false);
            final boolean wasStopping = prev.isState(STOPPING);
            prev.setState(PAUSED, "completePausedLocked");
......

4. setState STOPPING

    ActivityRecord completeFinishing(boolean updateVisibility, String reason) {
        if (!finishing || isState(RESUMED)) {
            throw new IllegalArgumentException(
                "Activity must be finishing and not resumed to complete, r=" + this + ", finishing=" + finishing + ", state=" + mState);
        }

        if (isState(PAUSING)) {
// Activity is marked as finishing and will be processed once it completes.
            return this;
        }

        final boolean isCurrentVisible = mVisibleRequested || isState(PAUSED, STARTED);
        if (updateVisibility && isCurrentVisible) {
            boolean ensureVisibility = false;
            if (occludesParent(true /* includingFinishing */)) {
// If the current activity is not opaque, we need to make sure the visibilities of activities be updated, they may be seen by users.
                ensureVisibility = true;
            } else if (mTaskSupervisor.getKeyguardController().isKeyguardLocked()
                    && mTaskSupervisor.getKeyguardController().topActivityOccludesKeyguard(this)) {
// Ensure activity visibilities and update lockscreen occluded/dismiss state when finishing the top activity that occluded keyguard. So that, the ActivityStack#mTopActivityOccludesKeyguard can be updated and the activity below won't be resumed.
                ensureVisibility = true;
            }

            if (ensureVisibility) {
                mDisplayContent.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, false /* preserveWindows */, true /* notifyClients */);
            }
        }

        boolean activityRemoved = false;

// If this activity is currently visible, and the resumed activity is not yet visible, then hold off on finishing until the resumed one becomes visible. The activity that we are finishing may be over the lock screen. In this case, we do not want to consider activities that cannot be shown on the lock screen as running and should proceed with finishing the activity if there is no valid next top running activity. Note that if this finishing activity is floating task, we don't need to wait the next activity resume and can destroy it directly.
// TODO(b/137329632): find the next activity directly underneath this one, not just anywhere
        final ActivityRecord next = getDisplayArea().topRunningActivity( true /* considerKeyguardState */);
 // isNextNotYetVisible is to check if the next activity is invisible, or it has been requested to be invisible but its windows haven't reported as invisible.  If so, it implied that the current finishing activity should be added into stopping list rather than destroy immediately.
        final boolean isNextNotYetVisible = next != null
                && (!next.nowVisible || !next.mVisibleRequested);

// Clear last paused activity to ensure top activity can be resumed during sleeping.
        if (isNextNotYetVisible && mDisplayContent.isSleeping()
                && next == next.getRootTask().mLastPausedActivity) {
            next.getRootTask().mLastPausedActivity = null;
        }

        if (isCurrentVisible) {
            if (isNextNotYetVisible) {
// Add this activity to the list of stopping activities. It will be processed and destroyed when the next activity reports idle.
                addToStopping(false /* scheduleIdle */, false /* idleDelayed */,
                        "completeFinishing");
                setState(STOPPING, "completeFinishing");
            } else if (addToFinishingAndWaitForIdle()) {
// We added this activity to the finishing list and something else is becoming resumed. The activity will complete finishing when the next activity reports idle. No need to do anything else here.
            } else {
// Not waiting for the next one to become visible, and nothing else will be resumed in place of this activity - requesting destruction right away.
                activityRemoved = destroyIfPossible(reason);
            }
        } else {
// Just need to make sure the next activities can be resumed (if needed) and is free to destroy this activity since it is currently not visible.
            addToFinishingAndWaitForIdle();
            activityRemoved = destroyIfPossible(reason);
        }

        return activityRemoved ? null : this;
    }

    void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
        // Complete the pausing process of a pausing activity, so it doesn't make sense to operate on non-leaf tasks.
        warnForNonLeafTask("completePauseLocked");

        ActivityRecord prev = mPausingActivity;
        ProtoLog.v(WM_DEBUG_STATES, "Complete pause: %s", prev);

        if (prev != null) {
            prev.setWillCloseOrEnterPip(false);
            final boolean wasStopping = prev.isState(STOPPING);
            prev.setState(PAUSED, "completePausedLocked");
            if (prev.finishing) {
                // We will update the activity visibility later, no need to do in
                // completeFinishing(). Updating visibility here might also making the next activities to be resumed, and could result in wrong app transition due to lack of previous activity information.
                ProtoLog.v(WM_DEBUG_STATES, "Executing finish of activity: %s", prev);
                prev = prev.completeFinishing(false /* updateVisibility */,
                        "completePausedLocked");
            } else if (prev.hasProcess()) {
                ProtoLog.v(WM_DEBUG_STATES, "Enqueue pending stop if needed: %s "
                        + "wasStopping=%b visibleRequested=%b",  prev,  wasStopping,
                        prev.mVisibleRequested);
                if (prev.deferRelaunchUntilPaused) {
 // Complete the deferred relaunch that was waiting for pause to complete.
                    ProtoLog.v(WM_DEBUG_STATES, "Re-launching after pause: %s", prev);
                    prev.relaunchActivityLocked(prev.preserveWindowOnDeferredRelaunch);
                } else if (wasStopping) {
 // We are also stopping, the stop request must have gone soon after the pause. We can't clobber it, because the stop confirmation will not be handled.We don't need to schedule another stop, we only need to let it happen.
                    prev.setState(STOPPING, "completePausedLocked");
                } else if (!prev.mVisibleRequested || shouldSleepOrShutDownActivities()) {

    void stopIfPossible() {
        if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Stopping: " + this);
        final Task rootTask = getRootTask();
        if (isNoHistory()) {
            if (!finishing) {
                if (!rootTask.shouldSleepActivities()) {
                    ProtoLog.d(WM_DEBUG_STATES, "no-history finish of %s", this);
                    if (finishIfPossible("stop-no-history", false /* oomAdj */)
                            != FINISH_RESULT_CANCELLED) {
                        resumeKeyDispatchingLocked();
                        return;
                    }
                } else {
                    ProtoLog.d(WM_DEBUG_STATES, "Not finishing noHistory %s on stop "   + "because we're just sleeping", this);
                }
            }
        }

        if (!attachedToProcess()) {
            return;
        }
        resumeKeyDispatchingLocked();
        try {
            stopped = false;
            ProtoLog.v(WM_DEBUG_STATES, "Moving to STOPPING: %s (stop requested)", this);

            setState(STOPPING, "stopIfPossible");
            if (DEBUG_VISIBILITY) {
                Slog.v(TAG_VISIBILITY, "Stopping:" + this);
            }
            EventLogTags.writeWmStopActivity( mUserId, System.identityHashCode(this), shortComponentName);
            mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken, StopActivityItem.obtain(configChangeFlags));

            mAtmService.mH.postDelayed(mStopTimeoutRunnable, STOP_TIMEOUT);
        } catch (Exception e) {
            // Maybe just ignore exceptions here...  if the process has crashed, our death
            // notification will clean things up.
            Slog.w(TAG, "Exception thrown during pause", e);
            // Just in case, assume it to be stopped.
            stopped = true;
            ProtoLog.v(WM_DEBUG_STATES, "Stop failed; moving to STOPPED: %s", this);
            setState(STOPPED, "stopIfPossible");
            if (deferRelaunchUntilPaused) {
                destroyImmediately("stop-except");
            }
        }

 4. setState STOPPED

有一个见3中最后一个

    void activityStopped(Bundle newIcicle, PersistableBundle newPersistentState,
            CharSequence description) {
        final boolean isStopping = mState == STOPPING;
        if (!isStopping && mState != RESTARTING_PROCESS) {
            Slog.i(TAG, "Activity reported stop, but no longer stopping: " + this + " " + mState);
            removeStopTimeout();
            return;
        }
        if (newPersistentState != null) {
            mPersistentState = newPersistentState;
            mAtmService.notifyTaskPersisterLocked(task, false);
        }

        if (newIcicle != null) {
            // If icicle is null, this is happening due to a timeout, so we haven't really saved the state.
            setSavedState(newIcicle);
            launchCount = 0;
            updateTaskDescription(description);
        }
        ProtoLog.i(WM_DEBUG_STATES, "Saving icicle of %s: %s", this, mIcicle);
        if (!stopped) {
            ProtoLog.v(WM_DEBUG_STATES, "Moving to STOPPED: %s (stop complete)", this);
            removeStopTimeout();
            stopped = true;
            if (isStopping) {
                setState(STOPPED, "activityStoppedLocked");
            }

            notifyAppStopped();

            if (finishing) {
                abortAndClearOptionsAnimation();
            } else {
                if (deferRelaunchUntilPaused) {
                    destroyImmediately("stop-config");
                    mRootWindowContainer.resumeFocusedTasksTopActivities();
                } else {
                    mRootWindowContainer.updatePreviousProcess(this);
                }
            }
            mTaskSupervisor.checkReadyForSleepLocked(true /* allowDelay */);
        }
    }

    boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
            boolean andResume, boolean checkConfig) throws RemoteException {

 ......

        // TODO(lifecycler): Resume or pause requests are done as part of launch transaction, so updating the state should be done accordingly.
        if (andResume && readyToResume()) {
 // As part of the process of launching, ActivityThread also performs a resume.
            rootTask.minimalResumeActivityLocked(r);
        } else {
            // This activity is not starting in the resumed state... which should look like we asked it to pause+stop (but remain visible), and it has done so and reported back the current icicle and other state.
            ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSED: %s " + "(starting in paused state)", r);
            r.setState(PAUSED, "realStartActivityLocked");
            mRootWindowContainer.executeAppTransitionForAllDisplay();
        }

5. setState FINISHING

    boolean destroyIfPossible(String reason) {
        setState(FINISHING, "destroyIfPossible");
......
    boolean addToFinishingAndWaitForIdle() {
        ProtoLog.v(WM_DEBUG_STATES, "Enqueueing pending finish: %s", this);
        setState(FINISHING, "addToFinishingAndWaitForIdle"); 
......

6. setState DESTROYING DESTROYED

    boolean destroyImmediately(String reason) {
        if (DEBUG_SWITCH || DEBUG_CLEANUP) {
            Slog.v(TAG_SWITCH, "Removing activity from " + reason + ": token=" + this + ", app=" + (hasProcess() ? app.mName : "(null)"));
        }

        if (isState(DESTROYING, DESTROYED)) {
            ProtoLog.v(WM_DEBUG_STATES, "activity %s already destroying, skipping " + "request with reason:%s", this, reason);
            return false;
        }

        EventLogTags.writeWmDestroyActivity(mUserId, System.identityHashCode(this), task.mTaskId, shortComponentName, reason);

        boolean removedFromHistory = false;

        cleanUp(false /* cleanServices */, false /* setState */);

        if (hasProcess()) {
            app.removeActivity(this, true /* keepAssociation */);
            if (!app.hasActivities()) {
                mAtmService.clearHeavyWeightProcessIfEquals(app);
            }

            boolean skipDestroy = false;

            try {
                if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + this);
                mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken, DestroyActivityItem.obtain(finishing, configChangeFlags));
            } catch (Exception e) {
 // We can just ignore exceptions here...  if the process has crashed, our death notification will clean things up.
                if (finishing) {
                    removeFromHistory(reason + " exceptionInScheduleDestroy");
                    removedFromHistory = true;
                    skipDestroy = true;
                }
            }

            nowVisible = false;

 // If the activity is finishing, we need to wait on removing it from the list to give it a chance to do its cleanup.  During that time it may make calls back with its token so we need to be able to find it on the list and so we don't want to remove it from the list yet.  Otherwise, we can just immediately put it in the destroyed state since we are not removing it from the list.
            if (finishing && !skipDestroy) {
                ProtoLog.v(WM_DEBUG_STATES, "Moving to DESTROYING: %s (destroy requested)", this);
setState(DESTROYING, "destroyActivityLocked. finishing and not skipping destroy");
                mAtmService.mH.postDelayed(mDestroyTimeoutRunnable, DESTROY_TIMEOUT);
            } else {
                ProtoLog.v(WM_DEBUG_STATES, "Moving to DESTROYED: %s "
                        + "(destroy skipped)", this);
 setState(DESTROYED, "destroyActivityLocked. not finishing or skipping destroy");
                if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during destroy for activity " + this);
                detachFromProcess();
            }
        } else {
            // Remove this record from the history.
            if (finishing) {
                removeFromHistory(reason + " hadNoApp");
                removedFromHistory = true;
            } else {
                ProtoLog.v(WM_DEBUG_STATES, "Moving to DESTROYED: %s (no app)", this);
setState(DESTROYED, "destroyActivityLocked. not finishing and had no app");
            }
        }

        configChangeFlags = 0;

        return removedFromHistory;
    }

    /** Note: call {@link #cleanUp(boolean, boolean)} before this method. */
    void removeFromHistory(String reason) {
        finishActivityResults(Activity.RESULT_CANCELED,null /* resultData */, null /* resultGrants */);
        makeFinishingLocked();

        ProtoLog.i(WM_DEBUG_ADD_REMOVE, "Removing activity %s, reason= %s "
                        + "callers=%s", this, reason, Debug.getCallers(5));

        takeFromHistory();
        removeTimeouts();
        ProtoLog.v(WM_DEBUG_STATES, "Moving to DESTROYED: %s (removed from history)",this);
        setState(DESTROYED, "removeFromHistory");
        if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + this);
        detachFromProcess();
        removeAppTokenFromDisplay();

        cleanUpActivityServices();
        removeUriPermissionsLocked();
    }
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ActivityManagerAndroid系统中非常重要的一个组件,负责管理系统中所有Activity的生命周期、进程管理、任务管理等。在本篇文章中,我们将深入了解ActivityManager框架的实现原理。 ## Activity的启动过程 在Android系统中,Activity是应用程序中最基本的界面单元。当用户点击应用程序的图标时,ActivityManager会负责启动应用程序并启动相应的Activity。下面是Activity的启动过程: 1. 应用程序进程启动:ActivityManager会创建一个新的进程来运行应用程序。 2. 应用程序的Application对象创建:在应用程序进程启动之后,ActivityManager会负责创建应用程序的Application对象。 3. Activity对象创建:当用户点击应用程序的图标并选择启动Activity时,ActivityManager会负责创建相应的Activity对象。 4. Activity的onCreate方法调用:ActivityManager会调用Activity对象的onCreate方法,完成Activity的初始化工作。 5. Activity的onStart方法调用:ActivityManager会调用Activity对象的onStart方法,将Activity显示给用户。 6. Activity的onResume方法调用:ActivityManager会调用Activity对象的onResume方法,让Activity成为用户交互的焦点。 7. Activity的生命周期结束:当用户退出Activity时,ActivityManager会负责销毁Activity对象。 ## 进程管理 在Android系统中,每个应用程序都运行在一个独立的进程中。ActivityManager负责管理所有进程,以确保系统的稳定和性能。 当应用程序被启动时,ActivityManager会为其创建一个新的进程并分配一定的内存资源。如果此时系统内存不足,ActivityManager会根据一定的策略来回收一些进程内存,以确保系统正常运行。 ActivityManager还负责监控进程的CPU使用情况和内存使用情况。如果一个进程的CPU使用率过高或者内存使用量过大,ActivityManager会考虑回收该进程的资源,以避免系统崩溃。 ## 任务管理 在Android系统中,任务是指一组相关的Activity。当用户启动一个应用程序时,ActivityManager会创建一个新的任务,并将应用程序的第一个Activity加入到该任务中。 当用户从一个Activity切换到另一个Activity时,ActivityManager会将前一个Activity加入到任务的后台,并将新的Activity显示给用户。当用户点击返回键时,ActivityManager会将当前Activity从任务中移除,并将前一个Activity重新显示给用户。 需要注意的是,当应用程序中的所有Activity都被销毁时,该应用程序的任务也会被销毁。这是因为Android系统中的Activity都是基于任务的,一个应用程序的所有Activity都属于同一个任务。 ## 总结 ActivityManagerAndroid系统中非常重要的一个组件,它负责管理系统中所有Activity的生命周期、进程管理、任务管理等。在本篇文章中,我们深入了解了ActivityManager的实现原理。熟悉ActivityManager的工作原理对于开发高质量的Android应用程序非常重要。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值