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

Commit 71773c9f authored by wilsonshih's avatar wilsonshih Committed by Android Build Coastguard Worker
Browse files

Defer remove splash screen while device is locked

...and activity does not request showWhenLocked.
The splash screen won't contains secure information, so it's safe to
declared as showWhenLocked. But before remove starting window, if the
activity does not request showWhenLocked and device is locked, try to
trigger unoccluding animation, and keep app window hide until transition
animation finish.

Bug: 378088391
Bug: 383131643
Test: run simulate app repeatly, verify the app content won't be visible
during transition animation.
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:0cd03f0a39ec184dc9677281335461dc2c86f9f8)
Merged-In: Ia2ddece125521eefb15d67e22ea863dfae6af112
Change-Id: Ia2ddece125521eefb15d67e22ea863dfae6af112
parent da672983
Loading
Loading
Loading
Loading
+47 −8
Original line number Diff line number Diff line
@@ -225,6 +225,10 @@ import static com.android.server.wm.IdentifierProto.TITLE;
import static com.android.server.wm.IdentifierProto.USER_ID;
import static com.android.server.wm.LetterboxConfiguration.DEFAULT_LETTERBOX_ASPECT_RATIO_FOR_MULTI_WINDOW;
import static com.android.server.wm.LetterboxConfiguration.MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO;
import static com.android.server.wm.StartingData.AFTER_TRANSACTION_COPY_TO_CLIENT;
import static com.android.server.wm.StartingData.AFTER_TRANSACTION_IDLE;
import static com.android.server.wm.StartingData.AFTER_TRANSACTION_REMOVE_DIRECTLY;
import static com.android.server.wm.StartingData.AFTER_TRANSITION_FINISH;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
@@ -2682,6 +2686,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        if (isTransferringSplashScreen()) {
            return true;
        }
        // Only do transfer after transaction has done when starting window exist.
        if (mStartingData != null && mStartingData.mWaitForSyncTransactionCommit) {
            mStartingData.mRemoveAfterTransaction = AFTER_TRANSACTION_COPY_TO_CLIENT;
            return true;
        }
        requestCopySplashScreen();
        return isTransferringSplashScreen();
    }
@@ -2809,9 +2818,28 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        attachStartingSurfaceToAssociatedTask();
    }

    /**
     * If the device is locked and the app does not request showWhenLocked,
     * defer removing the starting window until the transition is complete.
     * This prevents briefly appearing the app context and causing secure concern.
     */
    void deferStartingWindowRemovalForKeyguardUnoccluding() {
        if (mStartingData != null
                && mStartingData.mRemoveAfterTransaction != AFTER_TRANSITION_FINISH
                && isKeyguardLocked() && !canShowWhenLockedInner(this) && !isVisibleRequested()
                && mTransitionController.inTransition(this)) {
            mStartingData.mRemoveAfterTransaction = AFTER_TRANSITION_FINISH;
        }
    }

    void removeStartingWindow() {
        boolean prevEligibleForLetterboxEducation = isEligibleForLetterboxEducation();

        if (mStartingData != null
                && mStartingData.mRemoveAfterTransaction == AFTER_TRANSITION_FINISH) {
            return;
        }

        if (transferSplashScreenIfNeeded()) {
            return;
        }
@@ -2839,10 +2867,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        if (mStartingData == null) {
            return;
        }
        mStartingData.mWaitForSyncTransactionCommit = false;
        if (mStartingData.mRemoveAfterTransaction) {
            mStartingData.mRemoveAfterTransaction = false;
            removeStartingWindowAnimation(mStartingData.mPrepareRemoveAnimation);
        final StartingData lastData = mStartingData;
        lastData.mWaitForSyncTransactionCommit = false;
        if (lastData.mRemoveAfterTransaction == AFTER_TRANSACTION_REMOVE_DIRECTLY) {
            removeStartingWindowAnimation(lastData.mPrepareRemoveAnimation);
        } else if (lastData.mRemoveAfterTransaction == AFTER_TRANSACTION_COPY_TO_CLIENT) {
            removeStartingWindow();
        }
    }

@@ -2870,7 +2900,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        if (mStartingData != null) {
            if (mStartingData.mWaitForSyncTransactionCommit
                    || mTransitionController.inCollectingTransition(startingWindow)) {
                mStartingData.mRemoveAfterTransaction = true;
                mStartingData.mRemoveAfterTransaction = AFTER_TRANSACTION_REMOVE_DIRECTLY;
                mStartingData.mPrepareRemoveAnimation = prepareAnimation;
                return;
            }
@@ -4477,6 +4507,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                tStartingWindow.mToken = this;
                tStartingWindow.mActivityRecord = this;

                if (mStartingData.mRemoveAfterTransaction == AFTER_TRANSITION_FINISH) {
                    mStartingData.mRemoveAfterTransaction = AFTER_TRANSACTION_IDLE;
                }

                ProtoLog.v(WM_DEBUG_ADD_REMOVE,
                        "Removing starting %s from %s", tStartingWindow, fromActivity);
                mTransitionController.collect(tStartingWindow);
@@ -4638,17 +4672,22 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        if (r == null || r.getTaskFragment() == null) {
            return false;
        }
        if (!r.inPinnedWindowingMode() && (r.mShowWhenLocked || r.containsShowWhenLockedWindow())) {
        if (canShowWhenLockedInner(r)) {
            return true;
        } else if (r.mInheritShownWhenLocked) {
            final ActivityRecord activity = r.getTaskFragment().getActivityBelow(r);
            return activity != null && !activity.inPinnedWindowingMode()
                    && (activity.mShowWhenLocked || activity.containsShowWhenLockedWindow());
            return activity != null && canShowWhenLockedInner(activity);
        } else {
            return false;
        }
    }

    /** @see #canShowWhenLocked(ActivityRecord) */
    private static boolean canShowWhenLockedInner(@NonNull ActivityRecord r) {
        return !r.inPinnedWindowingMode() &&
                (r.mShowWhenLocked || r.containsShowWhenLockedWindow());
    }

    /**
     *  Determines if the activity can show while lock-screen is displayed. System displays
     *  activities while lock-screen is displayed only if all activities
+24 −1
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.wm;

import android.annotation.IntDef;

import com.android.server.wm.StartingSurfaceController.StartingSurface;

/**
@@ -23,6 +25,27 @@ import com.android.server.wm.StartingSurfaceController.StartingSurface;
 */
public abstract class StartingData {

    /** Nothing need to do after transaction */
    static final int AFTER_TRANSACTION_IDLE = 0;
    /** Remove the starting window directly after transaction done. */
    static final int AFTER_TRANSACTION_REMOVE_DIRECTLY = 1;
    /** Do copy splash screen to client after transaction done. */
    static final int AFTER_TRANSACTION_COPY_TO_CLIENT = 2;
    /**
     * Remove the starting window after transition finish.
     * Used when activity doesn't request show when locked, so the app window should never show to
     * the user if device is locked.
     **/
    static final int AFTER_TRANSITION_FINISH = 3;

    @IntDef(prefix = { "AFTER_TRANSACTION" }, value = {
            AFTER_TRANSACTION_IDLE,
            AFTER_TRANSACTION_REMOVE_DIRECTLY,
            AFTER_TRANSACTION_COPY_TO_CLIENT,
            AFTER_TRANSITION_FINISH,
    })
    @interface AfterTransaction {}

    protected final WindowManagerService mService;
    protected final int mTypeParams;

@@ -56,7 +79,7 @@ public abstract class StartingData {
     * This starting window should be removed after applying the start transaction of transition,
     * which ensures the app window has shown.
     */
    boolean mRemoveAfterTransaction;
    @AfterTransaction int mRemoveAfterTransaction = AFTER_TRANSACTION_IDLE;

    /** Whether to prepare the removal animation. */
    boolean mPrepareRemoveAnimation;
+9 −0
Original line number Diff line number Diff line
@@ -63,6 +63,8 @@ import static com.android.server.wm.ActivityRecord.State.RESUMED;
import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_RECENTS_ANIM;
import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_SPLASH_SCREEN;
import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_WINDOWS_DRAWN;
import static com.android.server.wm.StartingData.AFTER_TRANSACTION_IDLE;
import static com.android.server.wm.StartingData.AFTER_TRANSITION_FINISH;

import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -1155,6 +1157,13 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
                        enterAutoPip = true;
                    }
                }

                if (ar.mStartingData != null && ar.mStartingData.mRemoveAfterTransaction
                        == AFTER_TRANSITION_FINISH
                        && (!ar.isVisible() || !ar.mTransitionController.inTransition(ar))) {
                    ar.mStartingData.mRemoveAfterTransaction = AFTER_TRANSACTION_IDLE;
                    ar.removeStartingWindow();
                }
                final ChangeInfo changeInfo = mChanges.get(ar);
                // Due to transient-hide, there may be some activities here which weren't in the
                // transition.
+15 −0
Original line number Diff line number Diff line
@@ -124,6 +124,7 @@ import static com.android.server.wm.IdentifierProto.USER_ID;
import static com.android.server.wm.MoveAnimationSpecProto.DURATION_MS;
import static com.android.server.wm.MoveAnimationSpecProto.FROM;
import static com.android.server.wm.MoveAnimationSpecProto.TO;
import static com.android.server.wm.StartingData.AFTER_TRANSITION_FINISH;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
@@ -1931,6 +1932,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        }
        final ActivityRecord atoken = mActivityRecord;
        if (atoken != null) {
            if (atoken.mStartingData != null && mAttrs.type != TYPE_APPLICATION_STARTING
                    && atoken.mStartingData.mRemoveAfterTransaction
                    == AFTER_TRANSITION_FINISH) {
                // Preventing app window from visible during un-occluding animation playing due to
                // alpha blending.
                return false;
            }
            return ((!isParentWindowHidden() && atoken.isVisible())
                    || isAnimationRunningSelfOrParent());
        }
@@ -2893,7 +2901,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
            final int mask = FLAG_SHOW_WHEN_LOCKED | FLAG_DISMISS_KEYGUARD
                    | FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
            WindowManager.LayoutParams sa = mActivityRecord.mStartingWindow.mAttrs;
            final boolean wasShowWhenLocked = (sa.flags & FLAG_SHOW_WHEN_LOCKED) != 0;
            final boolean removeShowWhenLocked = (mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) == 0;
            sa.flags = (sa.flags & ~mask) | (mAttrs.flags & mask);
            if (wasShowWhenLocked && removeShowWhenLocked) {
                // Trigger unoccluding animation if needed.
                mActivityRecord.checkKeyguardFlagsChanged();
                mActivityRecord.deferStartingWindowRemovalForKeyguardUnoccluding();
            }
        }
    }