Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e7ba3801 authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Consolidate handling occluded initializing activity

Since task fragment is introduced, forAllOccludedActivities may
not work as expected because individual task fragment has its
own occluding relationship. Without correcting that, it may
remove active starting window.

Though the method can be fixed by iterating task fragment with
bounds check, it increases the complexity to maintain another
partial logic of EnsureActivitiesVisibleHelper.

So it may be more efficient and simpler by reusing the core of
visibility update to call cancelInitializing. And because the
visibility update is common to be called when resuming, it can
provide the same effect. In this way, the long loop executed
every time (cancelInitializingActivities) when resuming any
activity is also eliminated.

Also
- Remove mStartingWindowState because the nullity of mStartingData
  has already indicated that.
- Move transferSplashScreenIfNeeded to removeStartingWindow because
  when calling removeStartingWindowAnimation, it should do the
  removal directly.

Bug: 189385912
Bug: 194193397
Test: ActivityRecordTests#testTransferStartingWindowFromFinishingActivity
      RootTaskTests#testClearUnknownAppVisibilityBehindFullscreenActivity
Change-Id: I4621c2215807e713d9142acc7814786de50d88c4
parent da634dae
Loading
Loading
Loading
Loading
+10 −31
Original line number Diff line number Diff line
@@ -543,11 +543,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
    final ActivityTaskSupervisor mTaskSupervisor;
    final RootWindowContainer mRootWindowContainer;

    static final int STARTING_WINDOW_NOT_SHOWN = 0;
    static final int STARTING_WINDOW_SHOWN = 1;
    static final int STARTING_WINDOW_REMOVED = 2;
    int mStartingWindowState = STARTING_WINDOW_NOT_SHOWN;

    // Tracking splash screen status from previous activity
    boolean mSplashScreenStyleEmpty = false;

@@ -885,19 +880,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        }
    };

    private static String startingWindowStateToString(int state) {
        switch (state) {
            case STARTING_WINDOW_NOT_SHOWN:
                return "STARTING_WINDOW_NOT_SHOWN";
            case STARTING_WINDOW_SHOWN:
                return "STARTING_WINDOW_SHOWN";
            case STARTING_WINDOW_REMOVED:
                return "STARTING_WINDOW_REMOVED";
            default:
                return "unknown state=" + state;
        }
    }

    @Override
    void dump(PrintWriter pw, String prefix, boolean dumpAll) {
        final long now = SystemClock.uptimeMillis();
@@ -1049,9 +1031,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                pw.print(" finishing="); pw.println(finishing);
        pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused);
                pw.print(" inHistory="); pw.print(inHistory);
                pw.print(" idle="); pw.print(idle);
                pw.print(" mStartingWindowState=");
                pw.println(startingWindowStateToString(mStartingWindowState));
                pw.print(" idle="); pw.println(idle);
        pw.print(prefix); pw.print("occludesParent="); pw.print(occludesParent());
                pw.print(" noDisplay="); pw.print(noDisplay);
                pw.print(" immersive="); pw.print(immersive);
@@ -2005,6 +1985,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        }
    }

    @VisibleForTesting
    boolean addStartingWindow(String pkg, int resolvedTheme, CompatibilityInfo compatInfo,
            CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
            IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
@@ -2340,13 +2321,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
    }

    void removeStartingWindow() {
        if (transferSplashScreenIfNeeded()) {
            return;
        }
        removeStartingWindowAnimation(true /* prepareAnimation */);
    }

    void removeStartingWindowAnimation(boolean prepareAnimation) {
        if (transferSplashScreenIfNeeded()) {
            return;
        }
        mTransferringSplashScreenState = TRANSFER_SPLASH_SCREEN_IDLE;
        if (mStartingWindow == null) {
            if (mStartingData != null) {
@@ -6479,13 +6460,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        final boolean newSingleActivity = !newTask && !activityCreated
                && task.getActivity((r) -> !r.finishing && r != this) == null;

        final boolean shown = addStartingWindow(packageName, resolvedTheme,
        final boolean scheduled = addStartingWindow(packageName, resolvedTheme,
                compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
                prev != null ? prev.appToken : null,
                newTask || newSingleActivity, taskSwitch, isProcessRunning(),
                allowTaskSnapshot(), activityCreated, mSplashScreenStyleEmpty);
        if (shown) {
            mStartingWindowState = STARTING_WINDOW_SHOWN;
        if (DEBUG_STARTING_WINDOW_VERBOSE && scheduled) {
            Slog.d(TAG, "Scheduled starting window for " + this);
        }
    }

@@ -6497,14 +6478,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
     * It should only be called if this activity is behind other fullscreen activity.
     */
    void cancelInitializing() {
        if (mStartingWindowState == STARTING_WINDOW_SHOWN) {
        if (mStartingData != null) {
            // Remove orphaned starting window.
            if (DEBUG_VISIBILITY) Slog.w(TAG_VISIBILITY, "Found orphaned starting window " + this);
            mStartingWindowState = STARTING_WINDOW_REMOVED;
            removeStartingWindowAnimation(false /* prepareAnimation */);
        }
        if (isState(INITIALIZING) && !shouldBeVisible(
                true /* behindFullscreenActivity */, true /* ignoringKeyguard */)) {
        if (!mDisplayContent.mUnknownAppVisibilityController.allResolved()) {
            // Remove the unknown visibility record because an invisible activity shouldn't block
            // the keyguard transition.
            mDisplayContent.mUnknownAppVisibilityController.appRemovedOrHidden(this);
+3 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.wm;

import static com.android.server.wm.ActivityRecord.State.INITIALIZING;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.Task.TAG_VISIBILITY;

@@ -141,6 +142,8 @@ class EnsureActivitiesVisibleHelper {
            } else {
                mBehindFullyOccludedContainer = false;
            }
        } else if (r.isState(INITIALIZING)) {
            r.cancelInitializing();
        }

        if (reallyVisible) {
+0 −8
Original line number Diff line number Diff line
@@ -3421,14 +3421,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
        }, true /* traverseTopToBottom */);
    }

    void cancelInitializingActivities() {
        forAllRootTasks(task -> {
            // We don't want to clear starting window for activities that aren't occluded
            // as we need to display their starting window until they are done initializing.
            task.forAllOccludedActivities(ActivityRecord::cancelInitializing);
        });
    }

    Task anyTaskForId(int id) {
        return anyTaskForId(id, MATCH_ATTACHED_TASK_OR_RECENT_TASKS_AND_RESTORE);
    }
+2 −31
Original line number Diff line number Diff line
@@ -76,7 +76,6 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_LOCKTASK;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS;
import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_SHOWN;
import static com.android.server.wm.ActivityRecord.State.INITIALIZING;
import static com.android.server.wm.ActivityRecord.State.PAUSED;
import static com.android.server.wm.ActivityRecord.State.PAUSING;
@@ -1429,14 +1428,6 @@ class Task extends TaskFragment {
                window.getBaseType() == TYPE_APPLICATION_STARTING) != null);
    }

    ActivityRecord topActivityWithStartingWindow() {
        if (getParent() == null) {
            return null;
        }
        return getActivity((r) -> r.mStartingWindowState == STARTING_WINDOW_SHOWN
                && r.okToShowLocked());
    }

    /**
     * Return the number of running activities, and the number of non-finishing/initializing
     * activities in the provided {@param reportOut} respectively.
@@ -2840,25 +2831,6 @@ class Task extends TaskFragment {
        return top != activity ? top : null;
    }

    /** Iterates through all occluded activities. */
    void forAllOccludedActivities(Consumer<ActivityRecord> handleOccludedActivity) {
        if (!shouldBeVisible(null /* starting */)) {
            // The root task is invisible so all activities are occluded.
            forAllActivities(handleOccludedActivity);
            return;
        }
        final ActivityRecord topOccluding = getOccludingActivityAbove(null);
        if (topOccluding == null) {
            // No activities are occluded.
            return;
        }
        // Invoke the callback on the activities behind the top occluding activity.
        forAllActivities(r -> {
            handleOccludedActivity.accept(r);
            return false;
        }, topOccluding, false /* includeBoundary */, true /* traverseTopToBottom */);
    }

    @Override
    public SurfaceControl.Builder makeAnimationLeash() {
        return super.makeAnimationLeash().setMetadata(METADATA_TASK_ID, mTaskId);
@@ -4897,8 +4869,6 @@ class Task extends TaskFragment {
            return false;
        }

        mRootWindowContainer.cancelInitializingActivities();

        final ActivityRecord topActivity = topRunningActivity(true /* focusableOnly */);
        if (topActivity == null) {
            // There are no activities left in this task, let's look somewhere else.
@@ -5056,7 +5026,8 @@ class Task extends TaskFragment {
                // window manager to keep the previous window it had previously
                // created, if it still had one.
                Task prevTask = r.getTask();
                ActivityRecord prev = prevTask.topActivityWithStartingWindow();
                ActivityRecord prev = prevTask.getActivity(
                        a -> a.mStartingData != null && a.okToShowLocked());
                if (prev != null) {
                    // We don't want to reuse the previous starting preview if:
                    // (1) The current activity is in a different task.
+0 −1
Original line number Diff line number Diff line
@@ -2590,7 +2590,6 @@ public class ActivityRecordTests extends WindowTestsBase {
                false /* activityCreate */, false /* suggestEmpty */);
        waitUntilHandlersIdle();
        assertHasStartingWindow(activity);
        activity.mStartingWindowState = ActivityRecord.STARTING_WINDOW_SHOWN;

        doCallRealMethod().when(task).startActivityLocked(
                any(), any(), anyBoolean(), anyBoolean(), any(), any());
Loading