The big keyguard transition refactor (1/n)

The heart of this change are two things:
1) Instead of using the force hide mechanism to hide windows behind
Keyguard, we actually make the activities invisible in activity manager.
2) When Keyguard is going away, we change the visibilities in activity
manager and run an app transition.

At the very core we move the responsibility of hiding activities to
ActivityStack, which checks whether Keyguard is showing, and then
hides all non-show-when-locked activities. For that, we need to check
whether any window of an activity has SHOW_WHEN_LOCKED set. We
introduce a callback from WM -> AM in case these Keyguard flags have
changed.

Furthermore, we decide whether to occlude Keyguard in KeyguardController,
which just checks whether the top activity has SHOW_WHEN_LOCKED set. When
this state changes, we prepare an occlude/unocclude app transition, and
in PWM we just inform the Keyguard about the animation so SysUI can play
along this animations in a mostly synchronized manner.

Since we now use an app transition when unlocking the phone, we get
lockscreen launch animations for free - window manager automatically
waits until the activity is drawn, or directly executes the transition
if there is nothing to animate. Thus, we can remove all the infrastructure
around "waitingForActivityDrawn".

The logic to show/hide non-app windows is moved to policy, and we add the
ability to run animations on non-app windows when executing an app
transition.

Test:
1) runtest frameworks-services -c com.android.server.wm.AppTransitionTests
2) Manually test unlocking Keyguard:
2a) Without security
2b) With security
2c) With security but trusted
2d) Portrait while activity behind is in landscape
3) Test launching things from Keyguard
3a) Without security
3b) With security
3c) Launch camera without security
3d) Launch camera with security
3e) Launch camera with securtiy and trusted
3f) Launch voice affordance
4) Set no notifications on lockscreen, drag down, make sure you get
the correct animation
5) Test clicking "emergency" on bouncer
5b) Test "Emergency info" on emergency dialer
5c) Test clicking edit button on emergency info, should show pattern on
Keyguard

Bug: 32057734
Change-Id: Icada03cca74d6a612c1f988845f4d4f601087558
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index cd46165..862c145 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -135,6 +135,21 @@
     public static final int TRANSIT_ACTIVITY_RELAUNCH = 18;
     /** A task is being docked from recents. */
     public static final int TRANSIT_DOCK_TASK_FROM_RECENTS = 19;
+    /** Keyguard is going away */
+    public static final int TRANSIT_KEYGUARD_GOING_AWAY = 20;
+    /** Keyguard is going away with showing an activity behind that requests wallpaper */
+    public static final int TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER = 21;
+    /** Keyguard is being occluded */
+    public static final int TRANSIT_KEYGUARD_OCCLUDE = 22;
+    /** Keyguard is being unoccluded */
+    public static final int TRANSIT_KEYGUARD_UNOCCLUDE = 23;
+
+    /** Transition flag: Keyguard is going away, but keeping the notification shade open */
+    public static final int TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE = 0x1;
+    /** Transition flag: Keyguard is going away, but doesn't want an animation for it */
+    public static final int TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION = 0x2;
+    /** Transition flag: Keyguard is going away while it was showing the system wallpaper. */
+    public static final int TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER = 0x4;
 
     /** Fraction of animation at which the recents thumbnail stays completely transparent */
     private static final float RECENTS_THUMBNAIL_FADEIN_FRACTION = 0.5f;
@@ -162,6 +177,7 @@
     private final WindowManagerService mService;
 
     private int mNextAppTransition = TRANSIT_UNSET;
+    private int mNextAppTransitionFlags = 0;
     private int mLastUsedAppTransition = TRANSIT_UNSET;
     private String mLastOpeningApp;
     private String mLastClosingApp;
@@ -286,8 +302,9 @@
         return mNextAppTransition;
      }
 
-    private void setAppTransition(int transit) {
+    private void setAppTransition(int transit, int flags) {
         mNextAppTransition = transit;
+        mNextAppTransitionFlags |= flags;
         setLastAppTransition(TRANSIT_UNSET, null, null);
     }
 
@@ -372,27 +389,33 @@
         return false;
     }
 
-    void goodToGo(AppWindowAnimator topOpeningAppAnimator, AppWindowAnimator topClosingAppAnimator,
-            ArraySet<AppWindowToken> openingApps, ArraySet<AppWindowToken> closingApps) {
-        int appTransition = mNextAppTransition;
+    /**
+     * @return bit-map of WindowManagerPolicy#FINISH_LAYOUT_REDO_* to indicate whether another
+     *         layout pass needs to be done
+     */
+    int goodToGo(int transit, AppWindowAnimator topOpeningAppAnimator,
+            AppWindowAnimator topClosingAppAnimator, ArraySet<AppWindowToken> openingApps,
+            ArraySet<AppWindowToken> closingApps) {
         mNextAppTransition = TRANSIT_UNSET;
+        mNextAppTransitionFlags = 0;
         mAppTransitionState = APP_STATE_RUNNING;
-        notifyAppTransitionStartingLocked(
+        int redoLayout = notifyAppTransitionStartingLocked(transit,
                 topOpeningAppAnimator != null ? topOpeningAppAnimator.mAppToken.token : null,
                 topClosingAppAnimator != null ? topClosingAppAnimator.mAppToken.token : null,
                 topOpeningAppAnimator != null ? topOpeningAppAnimator.animation : null,
                 topClosingAppAnimator != null ? topClosingAppAnimator.animation : null);
         mService.getDefaultDisplayContentLocked().getDockedDividerController()
-                .notifyAppTransitionStarting(openingApps, appTransition);
+                .notifyAppTransitionStarting(openingApps, transit);
 
         // Prolong the start for the transition when docking a task from recents, unless recents
         // ended it already then we don't need to wait.
-        if (mNextAppTransition == TRANSIT_DOCK_TASK_FROM_RECENTS && !mProlongedAnimationsEnded) {
+        if (transit == TRANSIT_DOCK_TASK_FROM_RECENTS && !mProlongedAnimationsEnded) {
             for (int i = openingApps.size() - 1; i >= 0; i--) {
                 final AppWindowAnimator appAnimator = openingApps.valueAt(i).mAppAnimator;
                 appAnimator.startProlongAnimation(PROLONG_ANIMATION_AT_START);
             }
         }
+        return redoLayout;
     }
 
     /**
@@ -413,10 +436,11 @@
     }
 
     void freeze() {
-        setAppTransition(AppTransition.TRANSIT_UNSET);
+        final int transit = mNextAppTransition;
+        setAppTransition(AppTransition.TRANSIT_UNSET, 0 /* flags */);
         clear();
         setReady();
-        notifyAppTransitionCancelledLocked();
+        notifyAppTransitionCancelledLocked(transit);
     }
 
     void registerListenerLocked(AppTransitionListener listener) {
@@ -435,18 +459,20 @@
         }
     }
 
-    private void notifyAppTransitionCancelledLocked() {
+    private void notifyAppTransitionCancelledLocked(int transit) {
         for (int i = 0; i < mListeners.size(); i++) {
-            mListeners.get(i).onAppTransitionCancelledLocked();
+            mListeners.get(i).onAppTransitionCancelledLocked(transit);
         }
     }
 
-    private void notifyAppTransitionStartingLocked(IBinder openToken,
+    private int notifyAppTransitionStartingLocked(int transit, IBinder openToken,
             IBinder closeToken, Animation openAnimation, Animation closeAnimation) {
+        int redoLayout = 0;
         for (int i = 0; i < mListeners.size(); i++) {
-            mListeners.get(i).onAppTransitionStartingLocked(openToken, closeToken, openAnimation,
-                    closeAnimation);
+            redoLayout |= mListeners.get(i).onAppTransitionStartingLocked(transit, openToken,
+                    closeToken, openAnimation, closeAnimation);
         }
+        return redoLayout;
     }
 
     private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) {
@@ -1406,7 +1432,8 @@
     boolean canSkipFirstFrame() {
         return mNextAppTransitionType != NEXT_TRANSIT_TYPE_CUSTOM
                 && mNextAppTransitionType != NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE
-                && mNextAppTransitionType != NEXT_TRANSIT_TYPE_CLIP_REVEAL;
+                && mNextAppTransitionType != NEXT_TRANSIT_TYPE_CLIP_REVEAL
+                && mNextAppTransition != TRANSIT_KEYGUARD_GOING_AWAY;
     }
 
     /**
@@ -1435,7 +1462,13 @@
             @Nullable Rect surfaceInsets, boolean isVoiceInteraction, boolean freeform,
             int taskId) {
         Animation a;
-        if (isVoiceInteraction && (transit == TRANSIT_ACTIVITY_OPEN
+        if (isKeyguardGoingAwayTransit(transit) && enter) {
+            a = loadKeyguardExitAnimation(transit);
+        } else if (transit == TRANSIT_KEYGUARD_OCCLUDE) {
+            a = null;
+        } else if (transit == TRANSIT_KEYGUARD_UNOCCLUDE && !enter) {
+            a = loadAnimationRes(lp, com.android.internal.R.anim.wallpaper_open_exit);
+        } else if (isVoiceInteraction && (transit == TRANSIT_ACTIVITY_OPEN
                 || transit == TRANSIT_TASK_OPEN
                 || transit == TRANSIT_TASK_TO_FRONT)) {
             a = loadAnimationRes(lp, enter
@@ -1590,14 +1623,30 @@
         return a;
     }
 
+    private Animation loadKeyguardExitAnimation(int transit) {
+        if ((mNextAppTransitionFlags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION) != 0) {
+            return null;
+        }
+        final boolean toShade =
+                (mNextAppTransitionFlags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE) != 0;
+        return mService.mPolicy.createHiddenByKeyguardExit(
+                transit == TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER, toShade);
+    }
+
     int getAppStackClipMode() {
         return mNextAppTransition == TRANSIT_ACTIVITY_RELAUNCH
                 || mNextAppTransition == TRANSIT_DOCK_TASK_FROM_RECENTS
+                || mNextAppTransition == TRANSIT_KEYGUARD_GOING_AWAY
+                || mNextAppTransition == TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER
                 || mNextAppTransitionType == NEXT_TRANSIT_TYPE_CLIP_REVEAL
                 ? STACK_CLIP_NONE
                 : STACK_CLIP_AFTER_ANIM;
     }
 
+    public int getTransitFlags() {
+        return mNextAppTransitionFlags;
+    }
+
     void postAnimationCallback() {
         if (mNextAppTransitionCallback != null) {
             mService.mH.sendMessage(mService.mH.obtainMessage(H.DO_ANIMATION_CALLBACK,
@@ -1819,6 +1868,18 @@
             case TRANSIT_DOCK_TASK_FROM_RECENTS: {
                 return "TRANSIT_DOCK_TASK_FROM_RECENTS";
             }
+            case TRANSIT_KEYGUARD_GOING_AWAY: {
+                return "TRANSIT_KEYGUARD_GOING_AWAY";
+            }
+            case TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER: {
+                return "TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER";
+            }
+            case TRANSIT_KEYGUARD_OCCLUDE: {
+                return "TRANSIT_KEYGUARD_OCCLUDE";
+            }
+            case TRANSIT_KEYGUARD_UNOCCLUDE: {
+                return "TRANSIT_KEYGUARD_UNOCCLUDE";
+            }
             default: {
                 return "<UNKNOWN>";
             }
@@ -1933,22 +1994,24 @@
      * @return true if transition is not running and should not be skipped, false if transition is
      *         already running
      */
-    boolean prepareAppTransitionLocked(int transit, boolean alwaysKeepCurrent) {
+    boolean prepareAppTransitionLocked(int transit, boolean alwaysKeepCurrent, int flags,
+            boolean forceOverride) {
         if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Prepare app transition:"
                 + " transit=" + appTransitionToString(transit)
                 + " " + this
                 + " alwaysKeepCurrent=" + alwaysKeepCurrent
                 + " Callers=" + Debug.getCallers(3));
-        if (!isTransitionSet() || mNextAppTransition == TRANSIT_NONE) {
-            setAppTransition(transit);
+        if (forceOverride || isKeyguardTransit(transit) || !isTransitionSet()
+                || mNextAppTransition == TRANSIT_NONE) {
+            setAppTransition(transit, flags);
         } else if (!alwaysKeepCurrent) {
             if (transit == TRANSIT_TASK_OPEN && isTransitionEqual(TRANSIT_TASK_CLOSE)) {
                 // Opening a new task always supersedes a close for the anim.
-                setAppTransition(transit);
+                setAppTransition(transit, flags);
             } else if (transit == TRANSIT_ACTIVITY_OPEN
                     && isTransitionEqual(TRANSIT_ACTIVITY_CLOSE)) {
                 // Opening a new activity always supersedes a close for the anim.
-                setAppTransition(transit);
+                setAppTransition(transit, flags);
             }
         }
         boolean prepared = prepare();
@@ -1960,6 +2023,20 @@
     }
 
     /**
+     * @return true if {@param transit} is representing a transition in which Keyguard is going
+     *         away, false otherwise
+     */
+    public static boolean isKeyguardGoingAwayTransit(int transit) {
+        return transit == TRANSIT_KEYGUARD_GOING_AWAY
+                || transit == TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
+    }
+
+    private static boolean isKeyguardTransit(int transit) {
+        return isKeyguardGoingAwayTransit(transit) || transit == TRANSIT_KEYGUARD_OCCLUDE
+                || transit == TRANSIT_KEYGUARD_UNOCCLUDE;
+    }
+
+    /**
      * @return whether the specified {@param uiMode} is the TV mode.
      */
     private boolean isTvUiMode(int uiMode) {