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

Commit 0f9dd1d1 authored by Wei Sheng Shih's avatar Wei Sheng Shih Committed by Android (Google) Code Review
Browse files

Merge "Submit visibility to the activities after the sleep state stable"

parents 7febf914 bba6bedf
Loading
Loading
Loading
Loading
+31 −21
Original line number Diff line number Diff line
@@ -4628,18 +4628,26 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(this);
    }

    /** @return {@code true} if this activity should be made visible. */
    boolean shouldBeVisible(boolean behindFullscreenActivity, boolean ignoringKeyguard) {
    private void updateVisibleIgnoringKeyguard(boolean behindFullscreenActivity) {
        // Check whether activity should be visible without Keyguard influence
        visibleIgnoringKeyguard = (!behindFullscreenActivity || mLaunchTaskBehind)
                && okToShowLocked();
    }

    /** @return {@code true} if this activity should be made visible. */
    private boolean shouldBeVisible(boolean behindFullscreenActivity, boolean ignoringKeyguard) {
        updateVisibleIgnoringKeyguard(behindFullscreenActivity);

        if (ignoringKeyguard) {
            return visibleIgnoringKeyguard;
        }

        return shouldBeVisibleUnchecked();
    }

    boolean shouldBeVisibleUnchecked() {
        final Task stack = getRootTask();
        if (stack == null) {
        if (stack == null || !visibleIgnoringKeyguard) {
            return false;
        }

@@ -4652,26 +4660,30 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
            return false;
        }

        // Check if the activity is on a sleeping display, and if it can turn it ON.
        if (mDisplayContent.isSleeping()) {
            final boolean canTurnScreenOn = !mSetToSleep || canTurnScreenOn()
                    || canShowWhenLocked() || containsDismissKeyguardWindow();
            if (!canTurnScreenOn) {
        // Check if the activity is on a sleeping display
        // TODO b/163993448 mSetToSleep is required when restarting an existing activity, try to
        // remove it if possible.
        if (mSetToSleep && mDisplayContent.isSleeping()) {
            return false;
        }

        return mStackSupervisor.getKeyguardController().checkKeyguardVisibility(this);
    }

    void updateVisibility(boolean behindFullscreenActivity) {
        updateVisibleIgnoringKeyguard(behindFullscreenActivity);
        final Task task = getRootTask();
        if (task == null || !visibleIgnoringKeyguard) {
            return;
        }
        // Now check whether it's really visible depending on Keyguard state, and update
        // {@link ActivityStack} internal states.
        // Inform the method if this activity is the top activity of this stack, but exclude the
        // case where this is the top activity in a pinned stack.
        final boolean isTop = this == stack.getTopNonFinishingActivity();
        final boolean isTopNotPinnedStack = stack.isAttached()
                && stack.getDisplayArea().isTopNotFinishNotPinnedStack(stack);
        final boolean visibleIgnoringDisplayStatus = stack.checkKeyguardVisibility(this,
                visibleIgnoringKeyguard, isTop && isTopNotPinnedStack);

        return visibleIgnoringDisplayStatus;
        final boolean isTop = this == task.getTopNonFinishingActivity();
        final boolean isTopNotPinnedStack = task.isAttached()
                && task.getDisplayArea().isTopNotFinishNotPinnedStack(task);
        task.updateKeyguardVisibility(this, isTop && isTopNotPinnedStack);
    }

    boolean shouldBeVisible() {
@@ -7537,10 +7549,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
            return false;
        }
        final Task stack = getRootTask();
        return stack != null
                && !stack.inMultiWindowMode()
                && stack.checkKeyguardVisibility(this, true /* shouldBeVisible */,
                        stack.topRunningActivity() == this /* isTop */);
        return stack != null && !stack.inMultiWindowMode()
                && mStackSupervisor.getKeyguardController().checkKeyguardVisibility(this);
    }

    void setTurnScreenOn(boolean turnScreenOn) {
+8 −5
Original line number Diff line number Diff line
@@ -759,8 +759,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
                        false /* markFrozenIfConfigChanged */, true /* deferResume */);
            }

            if (r.getRootTask().checkKeyguardVisibility(r, true /* shouldBeVisible */,
                    true /* isTop */) && r.allowMoveToFront()) {
            if (mKeyguardController.checkKeyguardVisibility(r) && r.allowMoveToFront()) {
                // We only set the visibility to true if the activity is not being launched in
                // background, and is allowed to be visible based on keyguard state. This avoids
                // setting this into motion in window manager that is later cancelled due to later
@@ -2298,11 +2297,15 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
    }

    /** Ends a batch of visibility updates. */
    void endActivityVisibilityUpdate() {
        mVisibilityTransactionDepth--;
        if (mVisibilityTransactionDepth == 0) {
    void endActivityVisibilityUpdate(ActivityRecord starting, int configChanges,
            boolean preserveWindows, boolean notifyClients) {
        if (mVisibilityTransactionDepth == 1) {
            getKeyguardController().visibilitiesUpdated();
            // commit visibility to activities
            mRootWindowContainer.commitActivitiesVisible(starting, configChanges, preserveWindows,
                    notifyClients);
        }
        mVisibilityTransactionDepth--;
    }

    /** Returns {@code true} if the caller is on the path to update visibility. */
+9 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import static android.os.Build.VERSION_CODES.N;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.util.DisplayMetrics.DENSITY_DEFAULT;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
import static android.view.Display.FLAG_PRIVATE;
import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
import static android.view.Display.INVALID_DISPLAY;
@@ -5271,6 +5272,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        mSingleTaskInstance = true;
    }

    /**
     * Check if the display has {@link Display#FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD} applied.
     */
    boolean canShowWithInsecureKeyguard() {
        final int flags = mDisplay.getFlags();
        return (flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0;
    }

    /** Returns true if the display can only contain one task */
    boolean isSingleTaskInstance() {
        return mSingleTaskInstance;
+78 −46
Original line number Diff line number Diff line
@@ -22,12 +22,9 @@ import static com.android.server.wm.Task.TAG_VISIBILITY;
import android.annotation.Nullable;
import android.util.Slog;

import com.android.internal.util.function.pooled.PooledConsumer;
import com.android.internal.util.function.pooled.PooledLambda;

/** Helper class to ensure activities are in the right visible state for a container. */
class EnsureActivitiesVisibleHelper {
    private final Task mContiner;
    private final Task mTask;
    private ActivityRecord mTop;
    private ActivityRecord mStarting;
    private boolean mAboveTop;
@@ -38,11 +35,11 @@ class EnsureActivitiesVisibleHelper {
    private boolean mNotifyClients;

    EnsureActivitiesVisibleHelper(Task container) {
        mContiner = container;
        mTask = container;
    }

    /**
     * Update all attributes except {@link mContiner} to use in subsequent calculations.
     * Update all attributes except {@link mTask} to use in subsequent calculations.
     *
     * @param starting The activity that is being started
     * @param configChanges Parts of the configuration that changed for this activity for evaluating
@@ -54,11 +51,11 @@ class EnsureActivitiesVisibleHelper {
    void reset(ActivityRecord starting, int configChanges, boolean preserveWindows,
            boolean notifyClients) {
        mStarting = starting;
        mTop = mContiner.topRunningActivity();
        mTop = mTask.topRunningActivity();
        // If the top activity is not fullscreen, then we need to make sure any activities under it
        // are now visible.
        mAboveTop = mTop != null;
        mContainerShouldBeVisible = mContiner.shouldBeVisible(mStarting);
        mContainerShouldBeVisible = mTask.shouldBeVisible(mStarting);
        mBehindFullscreenActivity = !mContainerShouldBeVisible;
        mConfigChanges = configChanges;
        mPreserveWindows = preserveWindows;
@@ -66,7 +63,26 @@ class EnsureActivitiesVisibleHelper {
    }

    /**
     * Ensure visibility with an option to also update the configuration of visible activities.
     * Update visibility to activities.
     * @see Task#ensureActivitiesVisible(ActivityRecord, int, boolean)
     * @see RootWindowContainer#ensureActivitiesVisible(ActivityRecord, int, boolean)
     * @param starting The top most activity in the task.
     *                 The activity is either starting or resuming.
     *                 Caller should ensure starting activity is visible.
     *
     */
    void processUpdate(@Nullable ActivityRecord starting) {
        reset(starting, 0 /* configChanges */, false /* preserveWindows */,
                false /* notifyClients */);
        if (DEBUG_VISIBILITY) {
            Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible processUpdate behind " + mTop);
        }

        mTask.forAllActivities(this::updateActivityVisibility);
    }

    /**
     * Commit visibility with an option to also update the configuration of visible activities.
     * @see Task#ensureActivitiesVisible(ActivityRecord, int, boolean)
     * @see RootWindowContainer#ensureActivitiesVisible(ActivityRecord, int, boolean)
     * @param starting The top most activity in the task.
@@ -79,54 +95,84 @@ class EnsureActivitiesVisibleHelper {
     * @param notifyClients Flag indicating whether the configuration and visibility changes shoulc
     *                      be sent to the clients.
     */
    void process(@Nullable ActivityRecord starting, int configChanges, boolean preserveWindows,
            boolean notifyClients) {
    void processCommit(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 (DEBUG_VISIBILITY) {
            Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible processCommit behind " + mTop);
        }
        if (mTop != null) {
            mContiner.checkTranslucentActivityWaiting(mTop);
            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).
        final boolean resumeTopActivity = mTop != null && !mTop.mLaunchTaskBehind
                && mContiner.isTopActivityFocusable()
                && (starting == null || !starting.isDescendantOf(mContiner));
                && mTask.isTopActivityFocusable()
                && (starting == null || !starting.isDescendantOf(mTask));

        final PooledConsumer f = PooledLambda.obtainConsumer(
                EnsureActivitiesVisibleHelper::setActivityVisibilityState, this,
                PooledLambda.__(ActivityRecord.class), starting, resumeTopActivity);
        mContiner.forAllActivities(f);
        f.recycle();
        mTask.forAllActivities(a -> {
            commitActivityVisibility(a, starting, resumeTopActivity);
        });
    }

    private void setActivityVisibilityState(ActivityRecord r, ActivityRecord starting,
            final boolean resumeTopActivity) {
        final boolean isTop = r == mTop;
    private boolean isAboveTop(boolean isTop) {
        if (mAboveTop && !isTop) {
            return;
            return true;
        }
        mAboveTop = false;
        return false;
    }

        final boolean reallyVisible = r.shouldBeVisible(
                mBehindFullscreenActivity, false /* ignoringKeyguard */);
    private void updateActivityVisibility(ActivityRecord r) {
        final boolean isTop = r == mTop;
        if (isAboveTop(isTop)) {
            return;
        }

        r.updateVisibility(mBehindFullscreenActivity);

        // Check whether activity should be visible without Keyguard influence
        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
                if (DEBUG_VISIBILITY) {
                    Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r
                            + " stackVisible=" + mContainerShouldBeVisible
                            + " behindFullscreen=" + mBehindFullscreenActivity);
                }
                mBehindFullscreenActivity = true;
            } else {
                mBehindFullscreenActivity = false;
            }
        }

        if (!mBehindFullscreenActivity && mTask.isActivityTypeHome() && r.isRootOfTask()) {
            if (DEBUG_VISIBILITY) {
                Slog.v(TAG_VISIBILITY, "Home task: at " + mTask
                        + " stackShouldBeVisible=" + mContainerShouldBeVisible
                        + " behindFullscreenActivity=" + mBehindFullscreenActivity);
            }
            // No other task in the home stack 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 stack behind them vs. another
            // task in the home stack like recents.
            mBehindFullscreenActivity = true;
        }
    }

    private void commitActivityVisibility(ActivityRecord r, ActivityRecord starting,
            final boolean resumeTopActivity) {
        final boolean isTop = r == mTop;
        if (isAboveTop(isTop)) {
            return;
        }

        final boolean reallyVisible = r.shouldBeVisibleUnchecked();

        if (reallyVisible) {
            if (r.finishing) {
                return;
@@ -170,20 +216,6 @@ class EnsureActivitiesVisibleHelper {
                    + " mLaunchTaskBehind=" + r.mLaunchTaskBehind);
            r.makeInvisible();
        }

        final int windowingMode = mContiner.getWindowingMode();
        if (!mBehindFullscreenActivity && mContiner.isActivityTypeHome()
                && r.isRootOfTask()) {
            if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + mContiner
                    + " stackShouldBeVisible=" + mContainerShouldBeVisible
                    + " behindFullscreenActivity=" + mBehindFullscreenActivity);
            // No other task in the home stack 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 stack behind them vs. another
            // task in the home stack like recents.
            mBehindFullscreenActivity = true;
        }
    }

    private void makeVisibleAndRestartIfNeeded(ActivityRecord starting, int configChanges,
@@ -207,7 +239,7 @@ class EnsureActivitiesVisibleHelper {
            r.setVisibility(true);
        }
        if (r != starting) {
            mContiner.mStackSupervisor.startSpecificActivity(r, andResume, true /* checkConfig */);
            mTask.mStackSupervisor.startSpecificActivity(r, andResume, true /* checkConfig */);
        }
    }
}
+48 −10
Original line number Diff line number Diff line
@@ -277,6 +277,27 @@ class KeyguardController {
                && !mWindowManager.isKeyguardSecure(mService.getCurrentUserId());
    }

    /**
     * Checks whether {@param r} should be visible depending on Keyguard state.
     *
     * @return true if {@param r} is visible taken Keyguard state into account, false otherwise
     */
    boolean checkKeyguardVisibility(ActivityRecord r) {
        if (r.mDisplayContent.canShowWithInsecureKeyguard() && canDismissKeyguard()) {
            return true;
        }

        if (isKeyguardOrAodShowing(r.mDisplayContent.getDisplayId())) {
            // If keyguard is showing, nothing is visible, except if we are able to dismiss Keyguard
            // right away and AOD isn't visible.
            return canShowActivityWhileKeyguardShowing(r, r.containsDismissKeyguardWindow());
        } else if (isKeyguardLocked()) {
            return canShowWhileOccluded(r.containsDismissKeyguardWindow(), r.canShowWhenLocked());
        } else {
            return true;
        }
    }

    /**
     * Makes sure to update lockscreen occluded/dismiss state if needed after completing all
     * visibility updates ({@link ActivityStackSupervisor#endActivityVisibilityUpdate}).
@@ -442,6 +463,7 @@ class KeyguardController {
        private final int mDisplayId;
        private boolean mOccluded;
        private ActivityRecord mDismissingKeyguardActivity;
        private ActivityRecord mTopTurnScreenOnActivity;
        private boolean mRequestDismissKeyguard;
        private final ActivityTaskManagerService mService;
        private final ActivityTaskManagerInternal.SleepTokenAcquirer mSleepTokenAcquirer;
@@ -455,30 +477,38 @@ class KeyguardController {

        void onRemoved() {
            mDismissingKeyguardActivity = null;
            mTopTurnScreenOnActivity = null;
            mSleepTokenAcquirer.release(mDisplayId);
        }

        void visibilitiesUpdated(KeyguardController controller, DisplayContent display) {
            final boolean lastOccluded = mOccluded;
            final ActivityRecord lastDismissActivity = mDismissingKeyguardActivity;
            final ActivityRecord lastTurnScreenOnActivity = mTopTurnScreenOnActivity;
            mRequestDismissKeyguard = false;
            mOccluded = false;
            mDismissingKeyguardActivity = null;
            mTopTurnScreenOnActivity = null;

            // only top + focusable + visible task can control occluding.
            final Task stack = getStackForControllingOccluding(display);
            if (stack != null) {
                final ActivityRecord topDismissing = stack.getTopDismissingKeyguardActivity();
                final ActivityRecord topTurnScreenOn = stack.getTopTurnScreenOnActivity();
                mOccluded = stack.topActivityOccludesKeyguard() || (topDismissing != null
                        && stack.topRunningActivity() == topDismissing
                        && controller.canShowWhileOccluded(
                                true /* dismissKeyguard */,
                                false /* showWhenLocked */));
                if (stack.getTopDismissingKeyguardActivity() != null) {
                    mDismissingKeyguardActivity = stack.getTopDismissingKeyguardActivity();
                if (topDismissing != null) {
                    mDismissingKeyguardActivity = topDismissing;
                }
                if (topTurnScreenOn != null) {
                    mTopTurnScreenOnActivity = topTurnScreenOn;
                }
                // FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD only apply for secondary display.
                if (mDisplayId != DEFAULT_DISPLAY) {
                    mOccluded |= stack.canShowWithInsecureKeyguard()
                if (mDisplayId != DEFAULT_DISPLAY && stack.mDisplayContent != null) {
                    mOccluded |= stack.mDisplayContent.canShowWithInsecureKeyguard()
                            && controller.canDismissKeyguard();
                }
            }
@@ -488,14 +518,20 @@ class KeyguardController {
                        .getDisplayPolicy().isShowingDreamLw();
            }

            if (lastOccluded != mOccluded) {
                controller.handleOccludedChanged(mDisplayId);
            }
            if (lastDismissActivity != mDismissingKeyguardActivity && !mOccluded
            mRequestDismissKeyguard = lastDismissActivity != mDismissingKeyguardActivity
                    && !mOccluded
                    && mDismissingKeyguardActivity != null
                    && controller.mWindowManager.isKeyguardSecure(
                            controller.mService.getCurrentUserId())) {
                mRequestDismissKeyguard = true;
                    controller.mService.getCurrentUserId());

            if (mTopTurnScreenOnActivity != null
                    && mTopTurnScreenOnActivity != lastTurnScreenOnActivity
                    && !mService.mWindowManager.mPowerManager.isInteractive()) {
                controller.mStackSupervisor.wakeUp("handleTurnScreenOn");
            }

            if (lastOccluded != mOccluded) {
                controller.handleOccludedChanged(mDisplayId);
            }
        }

@@ -525,6 +561,8 @@ class KeyguardController {
            sb.append("  Occluded=").append(mOccluded)
                    .append(" DismissingKeyguardActivity=")
                    .append(mDismissingKeyguardActivity)
                    .append(" TurnScreenOnActivity=")
                    .append(mTopTurnScreenOnActivity)
                    .append(" at display=")
                    .append(mDisplayId);
            pw.println(sb.toString());
Loading