diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 6714c393d64bb..a91781580ac4f 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -435,11 +435,15 @@ public interface WindowManager extends ViewManager { int TRANSIT_KEYGUARD_GOING_AWAY = 7; /** * A window is appearing above a locked keyguard. + * @deprecated use {@link #TRANSIT_TO_FRONT} + {@link #TRANSIT_FLAG_KEYGUARD_OCCLUDING} for + * keyguard occluding with Shell transition. * @hide */ int TRANSIT_KEYGUARD_OCCLUDE = 8; /** * A window is made invisible revealing a locked keyguard. + * @deprecated use {@link #TRANSIT_TO_BACK} + {@link #TRANSIT_FLAG_KEYGUARD_UNOCCLUDING} for + * keyguard occluding with Shell transition. * @hide */ int TRANSIT_KEYGUARD_UNOCCLUDE = 9; @@ -561,6 +565,25 @@ public interface WindowManager extends ViewManager { */ int TRANSIT_FLAG_INVISIBLE = (1 << 10); // 0x400 + /** + * Transition flag: Indicates that keyguard will be showing (locked) with this transition, + * which is the opposite of {@link #TRANSIT_FLAG_KEYGUARD_GOING_AWAY}. + * @hide + */ + int TRANSIT_FLAG_KEYGUARD_APPEARING = (1 << 11); // 0x800 + + /** + * Transition flag: Indicates that keyguard is becoming hidden by an app + * @hide + */ + int TRANSIT_FLAG_KEYGUARD_OCCLUDING = (1 << 12); // 0x1000 + + /** + * Transition flag: Indicates that keyguard is being revealed after an app was occluding it. + * @hide + */ + int TRANSIT_FLAG_KEYGUARD_UNOCCLUDING = (1 << 13); // 0x2000 + /** * @hide */ @@ -576,10 +599,27 @@ public interface WindowManager extends ViewManager { TRANSIT_FLAG_KEYGUARD_GOING_AWAY, TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_LAUNCHER_CLEAR_SNAPSHOT, TRANSIT_FLAG_INVISIBLE, + TRANSIT_FLAG_KEYGUARD_APPEARING, + TRANSIT_FLAG_KEYGUARD_OCCLUDING, + TRANSIT_FLAG_KEYGUARD_UNOCCLUDING }) @Retention(RetentionPolicy.SOURCE) @interface TransitionFlags {} + /** + * Transit flags used to signal keyguard visibility is changing for animations. + * + *

These roughly correspond to CLOSE, OPEN, TO_BACK, and TO_FRONT on a hypothetical Keyguard + * container. Since Keyguard isn't a container we can't include it in changes and need to send + * this information in its own channel. + * @hide + */ + int KEYGUARD_VISIBILITY_TRANSIT_FLAGS = + (TRANSIT_FLAG_KEYGUARD_GOING_AWAY + | TRANSIT_FLAG_KEYGUARD_APPEARING + | TRANSIT_FLAG_KEYGUARD_OCCLUDING + | TRANSIT_FLAG_KEYGUARD_UNOCCLUDING); + /** * Remove content mode: Indicates remove content mode is currently not defined. * @hide diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java index a92ca8a4d3f26..59238b40e0c8e 100644 --- a/core/java/android/window/TransitionInfo.java +++ b/core/java/android/window/TransitionInfo.java @@ -99,9 +99,6 @@ public final class TransitionInfo implements Parcelable { /** The container is the display. */ public static final int FLAG_IS_DISPLAY = 1 << 5; - /** The container can show on top of lock screen. */ - public static final int FLAG_OCCLUDES_KEYGUARD = 1 << 6; - /** * Only for IS_DISPLAY containers. Is set if the display has system alert windows. This is * used to prevent seamless rotation. @@ -175,7 +172,6 @@ public final class TransitionInfo implements Parcelable { FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT, FLAG_IS_VOICE_INTERACTION, FLAG_IS_DISPLAY, - FLAG_OCCLUDES_KEYGUARD, FLAG_DISPLAY_HAS_ALERT_WINDOWS, FLAG_IS_INPUT_METHOD, FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY, @@ -457,9 +453,6 @@ public final class TransitionInfo implements Parcelable { if ((flags & FLAG_IS_DISPLAY) != 0) { sb.append(sb.length() == 0 ? "" : "|").append("IS_DISPLAY"); } - if ((flags & FLAG_OCCLUDES_KEYGUARD) != 0) { - sb.append(sb.length() == 0 ? "" : "|").append("OCCLUDES_KEYGUARD"); - } if ((flags & FLAG_DISPLAY_HAS_ALERT_WINDOWS) != 0) { sb.append(sb.length() == 0 ? "" : "|").append("DISPLAY_HAS_ALERT_WINDOWS"); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java index 513638eeb9607..cef7e16663312 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java @@ -17,31 +17,25 @@ package com.android.wm.shell.keyguard; import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM; -import static android.view.WindowManager.TRANSIT_CLOSE; -import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE; -import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE; -import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE; -import static android.view.WindowManager.TRANSIT_NONE; -import static android.view.WindowManager.TRANSIT_OPEN; -import static android.view.WindowManager.TRANSIT_SLEEP; -import static android.view.WindowManager.TRANSIT_TO_BACK; -import static android.view.WindowManager.TRANSIT_TO_FRONT; -import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED; +import static android.view.WindowManager.KEYGUARD_VISIBILITY_TRANSIT_FLAGS; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY; -import static android.window.TransitionInfo.FLAG_OCCLUDES_KEYGUARD; +import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_APPEARING; +import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_OCCLUDING; +import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_UNOCCLUDING; +import static android.view.WindowManager.TRANSIT_SLEEP; import static com.android.wm.shell.util.TransitionUtil.isOpeningType; -import static com.android.wm.shell.util.TransitionUtil.isClosingType; import android.annotation.NonNull; import android.annotation.Nullable; -import android.os.RemoteException; import android.os.Binder; import android.os.Handler; import android.os.IBinder; +import android.os.RemoteException; import android.util.ArrayMap; import android.util.Log; import android.view.SurfaceControl; +import android.view.WindowManager; import android.window.IRemoteTransition; import android.window.IRemoteTransitionFinishedCallback; import android.window.TransitionInfo; @@ -56,8 +50,6 @@ import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.transition.Transitions.TransitionFinishCallback; -import java.util.Map; - /** * The handler for Keyguard enter/exit and occlude/unocclude animations. * @@ -70,7 +62,7 @@ public class KeyguardTransitionHandler implements Transitions.TransitionHandler private final Handler mMainHandler; private final ShellExecutor mMainExecutor; - private final Map mStartedTransitions = new ArrayMap<>(); + private final ArrayMap mStartedTransitions = new ArrayMap<>(); /** * Local IRemoteTransition implementations registered by the keyguard service. @@ -81,6 +73,18 @@ public class KeyguardTransitionHandler implements Transitions.TransitionHandler private IRemoteTransition mOccludeByDreamTransition = null; private IRemoteTransition mUnoccludeTransition = null; + private final class StartedTransition { + final TransitionInfo mInfo; + final SurfaceControl.Transaction mFinishT; + final IRemoteTransition mPlayer; + + public StartedTransition(TransitionInfo info, + SurfaceControl.Transaction finishT, IRemoteTransition player) { + mInfo = info; + mFinishT = finishT; + mPlayer = player; + } + } public KeyguardTransitionHandler( @NonNull ShellInit shellInit, @NonNull Transitions transitions, @@ -105,10 +109,7 @@ public class KeyguardTransitionHandler implements Transitions.TransitionHandler } public static boolean handles(TransitionInfo info) { - return (info.getFlags() & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0 - || (info.getFlags() & TRANSIT_FLAG_KEYGUARD_LOCKED) != 0 - || info.getType() == TRANSIT_KEYGUARD_OCCLUDE - || info.getType() == TRANSIT_KEYGUARD_UNOCCLUDE; + return (info.getFlags() & KEYGUARD_VISIBILITY_TRANSIT_FLAGS) != 0; } @Override @@ -120,39 +121,14 @@ public class KeyguardTransitionHandler implements Transitions.TransitionHandler return false; } - boolean hasOpeningOcclude = false; - boolean hasClosingOcclude = false; - boolean hasOpeningDream = false; - boolean hasClosingApp = false; - - // Check for occluding/dream/closing apps - for (int i = info.getChanges().size() - 1; i >= 0; i--) { - final TransitionInfo.Change change = info.getChanges().get(i); - if ((change.getFlags() & TransitionInfo.FLAG_IS_WALLPAPER) != 0) { - continue; - } else if (isOpeningType(change.getMode())) { - hasOpeningOcclude |= change.hasFlags(FLAG_OCCLUDES_KEYGUARD); - hasOpeningDream |= (change.getTaskInfo() != null - && change.getTaskInfo().getActivityType() == ACTIVITY_TYPE_DREAM); - } else if (isClosingType(change.getMode())) { - hasClosingOcclude |= change.hasFlags(FLAG_OCCLUDES_KEYGUARD); - hasClosingApp = true; - } - } - // Choose a transition applicable for the changes and keyguard state. if ((info.getFlags() & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0) { return startAnimation(mExitTransition, "going-away", transition, info, startTransaction, finishTransaction, finishCallback); } - if (hasOpeningOcclude || info.getType() == TRANSIT_KEYGUARD_OCCLUDE) { - if (hasClosingOcclude) { - // Transitions between apps on top of the keyguard can use the default handler. - // WM sends a final occlude status update after the transition is finished. - return false; - } - if (hasOpeningDream) { + if ((info.getFlags() & TRANSIT_FLAG_KEYGUARD_OCCLUDING) != 0) { + if (hasOpeningDream(info)) { return startAnimation(mOccludeByDreamTransition, "occlude-by-dream", transition, info, startTransaction, finishTransaction, finishCallback); @@ -161,12 +137,12 @@ public class KeyguardTransitionHandler implements Transitions.TransitionHandler "occlude", transition, info, startTransaction, finishTransaction, finishCallback); } - } else if (hasClosingApp || info.getType() == TRANSIT_KEYGUARD_UNOCCLUDE) { + } else if ((info.getFlags() & TRANSIT_FLAG_KEYGUARD_UNOCCLUDING) != 0) { return startAnimation(mUnoccludeTransition, "unocclude", transition, info, startTransaction, finishTransaction, finishCallback); } else { - Log.w(TAG, "Failed to play: " + info); + Log.i(TAG, "Refused to play keyguard transition: " + info); return false; } } @@ -194,7 +170,8 @@ public class KeyguardTransitionHandler implements Transitions.TransitionHandler }); } }); - mStartedTransitions.put(transition, remoteHandler); + mStartedTransitions.put(transition, + new StartedTransition(info, finishTransaction, remoteHandler)); } catch (RemoteException e) { Log.wtf(TAG, "RemoteException thrown from local IRemoteTransition", e); return false; @@ -207,20 +184,35 @@ public class KeyguardTransitionHandler implements Transitions.TransitionHandler public void mergeAnimation(@NonNull IBinder nextTransition, @NonNull TransitionInfo nextInfo, @NonNull SurfaceControl.Transaction nextT, @NonNull IBinder currentTransition, @NonNull TransitionFinishCallback nextFinishCallback) { - final IRemoteTransition playing = mStartedTransitions.get(currentTransition); - + final StartedTransition playing = mStartedTransitions.get(currentTransition); if (playing == null) { ProtoLog.e(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "unknown keyguard transition %s", currentTransition); return; } - - if (nextInfo.getType() == TRANSIT_SLEEP) { + if ((nextInfo.getFlags() & WindowManager.TRANSIT_FLAG_KEYGUARD_APPEARING) != 0 + && (playing.mInfo.getFlags() & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0) { + // Keyguard unlocking has been canceled. Merge the unlock and re-lock transitions to + // avoid a flicker where we flash one frame with the screen fully unlocked. + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, + "canceling keyguard exit transition %s", currentTransition); + playing.mFinishT.merge(nextT); + try { + playing.mPlayer.mergeAnimation(nextTransition, nextInfo, nextT, currentTransition, + new FakeFinishCallback()); + } catch (RemoteException e) { + // There is no good reason for this to happen because the player is a local object + // implementing an AIDL interface. + Log.wtf(TAG, "RemoteException thrown from KeyguardService transition", e); + } + nextFinishCallback.onTransitionFinished(null, null); + } else if (nextInfo.getType() == TRANSIT_SLEEP) { // An empty SLEEP transition comes in as a signal to abort transitions whenever a sleep // token is held. In cases where keyguard is showing, we are running the animation for // the device sleeping/waking, so it's best to ignore this and keep playing anyway. return; - } else { + } else if (handles(nextInfo)) { + // In all other cases, fast-forward to let the next queued transition start playing. finishAnimationImmediately(currentTransition, playing); } } @@ -228,7 +220,7 @@ public class KeyguardTransitionHandler implements Transitions.TransitionHandler @Override public void onTransitionConsumed(IBinder transition, boolean aborted, SurfaceControl.Transaction finishTransaction) { - final IRemoteTransition playing = mStartedTransitions.remove(transition); + final StartedTransition playing = mStartedTransitions.remove(transition); if (playing != null) { finishAnimationImmediately(transition, playing); } @@ -241,13 +233,26 @@ public class KeyguardTransitionHandler implements Transitions.TransitionHandler return null; } - private void finishAnimationImmediately(IBinder transition, IRemoteTransition playing) { + private static boolean hasOpeningDream(@NonNull TransitionInfo info) { + for (int i = info.getChanges().size() - 1; i >= 0; i--) { + final TransitionInfo.Change change = info.getChanges().get(i); + if (isOpeningType(change.getMode()) + && change.getTaskInfo() != null + && change.getTaskInfo().getActivityType() == ACTIVITY_TYPE_DREAM) { + return true; + } + } + return false; + } + + private void finishAnimationImmediately(IBinder transition, StartedTransition playing) { final IBinder fakeTransition = new Binder(); final TransitionInfo fakeInfo = new TransitionInfo(TRANSIT_SLEEP, 0x0); final SurfaceControl.Transaction fakeT = new SurfaceControl.Transaction(); final FakeFinishCallback fakeFinishCb = new FakeFinishCallback(); try { - playing.mergeAnimation(fakeTransition, fakeInfo, fakeT, transition, fakeFinishCb); + playing.mPlayer.mergeAnimation( + fakeTransition, fakeInfo, fakeT, transition, fakeFinishCb); } catch (RemoteException e) { // There is no good reason for this to happen because the player is a local object // implementing an AIDL interface. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java index 64571e067a832..3ec433e55da96 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java @@ -31,6 +31,7 @@ import static com.android.wm.shell.util.TransitionUtil.isOpeningType; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.IBinder; +import android.util.Log; import android.util.Pair; import android.view.SurfaceControl; import android.view.WindowManager; @@ -566,11 +567,18 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler, @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { - boolean consumed = mKeyguardHandler.startAnimation( - mixed.mTransition, info, startTransaction, finishTransaction, finishCallback); - if (!consumed) { + final Transitions.TransitionFinishCallback finishCB = (wct, wctCB) -> { + mixed.mInFlightSubAnimations--; + if (mixed.mInFlightSubAnimations == 0) { + mActiveTransitions.remove(mixed); + finishCallback.onTransitionFinished(wct, wctCB); + } + }; + if (!mKeyguardHandler.startAnimation( + mixed.mTransition, info, startTransaction, finishTransaction, finishCB)) { return false; } + mixed.mInFlightSubAnimations++; // Sync pip state. if (mPipHandler != null) { // We don't know when to apply `startTransaction` so use a separate transaction here. diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java index 10db9050caf50..94227bccfced5 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java @@ -19,6 +19,7 @@ package com.android.systemui.keyguard; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.view.RemoteAnimationTarget.MODE_CLOSING; import static android.view.RemoteAnimationTarget.MODE_OPENING; +import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_APPEARING; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY; import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY; import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE; @@ -182,8 +183,8 @@ public class KeyguardService extends Service { // Wrap Keyguard going away animation. // Note: Also used for wrapping occlude by Dream animation. It works (with some redundancy). - public static IRemoteTransition wrap(IRemoteAnimationRunner runner, - boolean lockscreenLiveWallpaperEnabled) { + public static IRemoteTransition wrap(final KeyguardViewMediator keyguardViewMediator, + final IRemoteAnimationRunner runner, final boolean lockscreenLiveWallpaperEnabled) { return new IRemoteTransition.Stub() { private final ArrayMap mLeashMap = new ArrayMap<>(); @@ -239,6 +240,12 @@ public class KeyguardService extends Service { SurfaceControl.Transaction candidateT, IBinder currentTransition, IRemoteTransitionFinishedCallback candidateFinishCallback) throws RemoteException { + if ((candidateInfo.getFlags() & TRANSIT_FLAG_KEYGUARD_APPEARING) != 0) { + keyguardViewMediator.setPendingLock(true); + keyguardViewMediator.cancelKeyguardExitAnimation(); + return; + } + try { synchronized (mLeashMap) { runner.onAnimationCancelled(); diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt index fe804661914dd..57c7b09759a5f 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt @@ -205,6 +205,12 @@ class KeyguardUnlockAnimationController @Inject constructor( */ var playingCannedUnlockAnimation = false + /** + * Whether we reached the swipe gesture threshold to dismiss keyguard, or restore it, once + * and should ignore any future changes to the dismiss amount before the animation finishes. + */ + var dismissAmountThresholdsReached = false + /** * Remote callback provided by Launcher that allows us to control the Launcher's unlock * animation and smartspace. @@ -649,6 +655,7 @@ class KeyguardUnlockAnimationController @Inject constructor( @VisibleForTesting fun unlockToLauncherWithInWindowAnimations() { + surfaceBehindAlpha = 1f setSurfaceBehindAppearAmount(1f, wallpapers = false) try { @@ -762,6 +769,10 @@ class KeyguardUnlockAnimationController @Inject constructor( return } + if (dismissAmountThresholdsReached) { + return + } + if (!keyguardStateController.isShowing) { return } @@ -793,6 +804,11 @@ class KeyguardUnlockAnimationController @Inject constructor( return } + // no-op if we alreaddy reached a threshold. + if (dismissAmountThresholdsReached) { + return + } + // no-op if animation is not requested yet. if (!keyguardViewMediator.get().requestedShowSurfaceBehindKeyguard() || !keyguardViewMediator.get().isAnimatingBetweenKeyguardAndSurfaceBehindOrWillBe) { @@ -807,6 +823,7 @@ class KeyguardUnlockAnimationController @Inject constructor( !keyguardStateController.isFlingingToDismissKeyguardDuringSwipeGesture && dismissAmount >= DISMISS_AMOUNT_EXIT_KEYGUARD_THRESHOLD)) { setSurfaceBehindAppearAmount(1f) + dismissAmountThresholdsReached = true keyguardViewMediator.get().exitKeyguardAndFinishSurfaceBehindRemoteAnimation( false /* cancelled */) } @@ -941,6 +958,7 @@ class KeyguardUnlockAnimationController @Inject constructor( wallpaperTargets = null playingCannedUnlockAnimation = false + dismissAmountThresholdsReached = false willUnlockWithInWindowLauncherAnimations = false willUnlockWithSmartspaceTransition = false diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 992add63e23ca..6680a431487e2 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -1352,12 +1352,12 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, setShowingLocked(false /* showing */, true /* forceCallbacks */); } - boolean isLockscreenLwpEnabled = getWallpaperManager().isLockscreenLiveWallpaperEnabled(); + boolean isLLwpEnabled = getWallpaperManager().isLockscreenLiveWallpaperEnabled(); mKeyguardTransitions.register( - KeyguardService.wrap(getExitAnimationRunner(), isLockscreenLwpEnabled), - KeyguardService.wrap(getOccludeAnimationRunner(), isLockscreenLwpEnabled), - KeyguardService.wrap(getOccludeByDreamAnimationRunner(), isLockscreenLwpEnabled), - KeyguardService.wrap(getUnoccludeAnimationRunner(), isLockscreenLwpEnabled)); + KeyguardService.wrap(this, getExitAnimationRunner(), isLLwpEnabled), + KeyguardService.wrap(this, getOccludeAnimationRunner(), isLLwpEnabled), + KeyguardService.wrap(this, getOccludeByDreamAnimationRunner(), isLLwpEnabled), + KeyguardService.wrap(this, getUnoccludeAnimationRunner(), isLLwpEnabled)); final ContentResolver cr = mContext.getContentResolver(); @@ -2906,6 +2906,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, // re-locking. We should just end the surface-behind animation without exiting the // keyguard. The pending lock will be handled by onFinishedGoingToSleep(). finishSurfaceBehindRemoteAnimation(true); + maybeHandlePendingLock(); } else { Log.d(TAG, "#handleCancelKeyguardExitAnimation: keyguard exit animation cancelled. " + "No pending lock, we should end up unlocked with the app/launcher visible."); @@ -3261,8 +3262,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, /** * Cancel the keyguard exit animation, usually because we were swiping to unlock but WM starts * a new remote animation before finishing the keyguard exit animation. - * - * This will dismiss the keyguard. */ public void cancelKeyguardExitAnimation() { Trace.beginSection("KeyguardViewMediator#cancelKeyguardExitAnimation"); @@ -3435,7 +3434,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, } } - private void setPendingLock(boolean hasPendingLock) { + public void setPendingLock(boolean hasPendingLock) { mPendingLock = hasPendingLock; Trace.traceCounter(Trace.TRACE_TAG_APP, "pendingLock", mPendingLock ? 1 : 0); } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 6aec96988a772..7fc86b0fdc016 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -5602,17 +5602,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp */ void requestTransitionAndLegacyPrepare(@WindowManager.TransitionType int transit, @WindowManager.TransitionFlags int flags) { - prepareAppTransition(transit, flags); - mTransitionController.requestTransitionIfNeeded(transit, flags, - null /* trigger */, this); + requestTransitionAndLegacyPrepare(transit, flags, null /* trigger */); } /** @see #requestTransitionAndLegacyPrepare(int, int) */ void requestTransitionAndLegacyPrepare(@WindowManager.TransitionType int transit, - @Nullable WindowContainer trigger) { - prepareAppTransition(transit); - mTransitionController.requestTransitionIfNeeded(transit, 0 /* flags */, - trigger, this); + @WindowManager.TransitionFlags int flags, @Nullable WindowContainer trigger) { + prepareAppTransition(transit, flags); + mTransitionController.requestTransitionIfNeeded(transit, flags, trigger, this); } void executeAppTransition() { diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java index 99878a3d0ffe5..ad9c3b2742673 100644 --- a/services/core/java/com/android/server/wm/KeyguardController.java +++ b/services/core/java/com/android/server/wm/KeyguardController.java @@ -19,17 +19,21 @@ package com.android.server.wm; import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.view.Display.DEFAULT_DISPLAY; +import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_APPEARING; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_LAUNCHER_CLEAR_SNAPSHOT; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER; +import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_OCCLUDING; +import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_UNOCCLUDING; import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY; import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE; import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE; import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_TO_BACK; +import static android.view.WindowManager.TRANSIT_TO_FRONT; import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS; import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_SUBTLE_WINDOW_ANIMATIONS; import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_LAUNCHER_CLEAR_SNAPSHOT; @@ -171,10 +175,11 @@ class KeyguardController { final KeyguardDisplayState state = getDisplayState(displayId); final boolean aodChanged = aodShowing != state.mAodShowing; final boolean aodRemoved = state.mAodShowing && !aodShowing; + final boolean goingAwayRemoved = state.mKeyguardGoingAway && keyguardShowing; // If keyguard is going away, but SystemUI aborted the transition, need to reset state. // Do not reset keyguardChanged status when only AOD is removed. final boolean keyguardChanged = (keyguardShowing != state.mKeyguardShowing) - || (state.mKeyguardGoingAway && keyguardShowing && !aodRemoved); + || (goingAwayRemoved && !aodRemoved); if (aodRemoved) { updateDeferTransitionForAod(false /* waiting */); } @@ -214,6 +219,15 @@ class KeyguardController { if (keyguardShowing) { state.mDismissalRequested = false; } + if (goingAwayRemoved) { + // Keyguard dismiss is canceled. Send a transition to undo the changes and clean up + // before holding the sleep token again. + final DisplayContent dc = mRootWindowContainer.getDefaultDisplay(); + dc.requestTransitionAndLegacyPrepare( + TRANSIT_TO_FRONT, TRANSIT_FLAG_KEYGUARD_APPEARING); + dc.mWallpaperController.showWallpaperInTransition(false /* showHome */); + mWindowManager.executeAppTransition(); + } } // Update the sleep token first such that ensureActivitiesVisible has correct sleep token @@ -269,7 +283,7 @@ class KeyguardController { updateKeyguardSleepToken(); // Make the home wallpaper visible - dc.mWallpaperController.showHomeWallpaperInTransition(); + dc.mWallpaperController.showWallpaperInTransition(true /* showHome */); // Some stack visibility might change (e.g. docked stack) mRootWindowContainer.resumeFocusedTasksTopActivities(); mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); @@ -413,10 +427,12 @@ class KeyguardController { if (isDisplayOccluded(DEFAULT_DISPLAY)) { mRootWindowContainer.getDefaultDisplay().requestTransitionAndLegacyPrepare( TRANSIT_KEYGUARD_OCCLUDE, + TRANSIT_FLAG_KEYGUARD_OCCLUDING, topActivity != null ? topActivity.getRootTask() : null); } else { mRootWindowContainer.getDefaultDisplay().requestTransitionAndLegacyPrepare( - TRANSIT_KEYGUARD_UNOCCLUDE, 0 /* flags */); + TRANSIT_KEYGUARD_UNOCCLUDE, + TRANSIT_FLAG_KEYGUARD_UNOCCLUDING); } updateKeyguardSleepToken(DEFAULT_DISPLAY); mWindowManager.executeAppTransition(); diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index b938b9e4ec51e..9a5f766989ca8 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -52,7 +52,6 @@ import static android.window.TransitionInfo.FLAG_IS_VOICE_INTERACTION; import static android.window.TransitionInfo.FLAG_IS_WALLPAPER; import static android.window.TransitionInfo.FLAG_MOVED_TO_TOP; import static android.window.TransitionInfo.FLAG_NO_ANIMATION; -import static android.window.TransitionInfo.FLAG_OCCLUDES_KEYGUARD; import static android.window.TransitionInfo.FLAG_SHOW_WALLPAPER; import static android.window.TransitionInfo.FLAG_TASK_LAUNCHING_BEHIND; import static android.window.TransitionInfo.FLAG_TRANSLUCENT; @@ -2820,9 +2819,6 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { } } } - if (occludesKeyguard(wc)) { - flags |= FLAG_OCCLUDES_KEYGUARD; - } if ((mFlags & FLAG_CHANGE_NO_ANIMATION) != 0 && (mFlags & FLAG_CHANGE_YES_ANIMATION) == 0) { flags |= FLAG_NO_ANIMATION; diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java index 1c6a412e54503..0cb6f14b38f2c 100644 --- a/services/core/java/com/android/server/wm/TransitionController.java +++ b/services/core/java/com/android/server/wm/TransitionController.java @@ -16,10 +16,10 @@ package com.android.server.wm; +import static android.view.WindowManager.KEYGUARD_VISIBILITY_TRANSIT_FLAGS; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_FLAG_IS_RECENTS; -import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY; import static android.view.WindowManager.TRANSIT_NONE; import static android.view.WindowManager.TRANSIT_OPEN; @@ -619,9 +619,9 @@ class TransitionController { } // Make the collecting transition wait until this request is ready. mCollectingTransition.setReady(readyGroupRef, false); - if ((flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0) { - // Add keyguard flag to dismiss keyguard - mCollectingTransition.addFlag(flags); + if ((flags & KEYGUARD_VISIBILITY_TRANSIT_FLAGS) != 0) { + // Add keyguard flags to affect keyguard visibility + mCollectingTransition.addFlag(flags & KEYGUARD_VISIBILITY_TRANSIT_FLAGS); } } else { newTransition = requestStartTransition(createTransition(type, flags), diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java index 4616e6b2a6800..7f41ff1a3d9b7 100644 --- a/services/core/java/com/android/server/wm/WallpaperController.java +++ b/services/core/java/com/android/server/wm/WallpaperController.java @@ -339,12 +339,12 @@ class WallpaperController { } /** - * Change the visibility if wallpaper is home screen only. + * Make one wallpaper visible, according to {@attr showHome}. * This is called during the keyguard unlocking transition - * (see {@link KeyguardController#keyguardGoingAway(int, int)}) and thus assumes that if the - * system wallpaper is shared with lock, then it needs no animation. + * (see {@link KeyguardController#keyguardGoingAway(int, int)}), + * or when a keyguard unlock is cancelled (see {@link KeyguardController}) */ - public void showHomeWallpaperInTransition() { + public void showWallpaperInTransition(boolean showHome) { updateWallpaperWindowsTarget(mFindResults); if (!mFindResults.hasTopShowWhenLockedWallpaper()) { @@ -357,9 +357,9 @@ class WallpaperController { // Shared wallpaper, ensure its visibility showWhenLocked.mToken.asWallpaperToken().updateWallpaperWindows(true); } else { - // Separate lock and home wallpapers: show home wallpaper and hide lock - hideWhenLocked.mToken.asWallpaperToken().updateWallpaperWindowsInTransition(true); - showWhenLocked.mToken.asWallpaperToken().updateWallpaperWindowsInTransition(false); + // Separate lock and home wallpapers: show the correct wallpaper in transition + hideWhenLocked.mToken.asWallpaperToken().updateWallpaperWindowsInTransition(showHome); + showWhenLocked.mToken.asWallpaperToken().updateWallpaperWindowsInTransition(!showHome); } }