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/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index c9f1ffc..250d381 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -18,9 +18,12 @@
 
 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+
+import static com.android.server.wm.AppTransition.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
@@ -39,6 +42,7 @@
 import android.util.Slog;
 import android.view.DisplayInfo;
 import android.view.WindowManager;
+import android.view.animation.Animation;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -126,6 +130,16 @@
         return isWallpaperVisible(mWallpaperTarget);
     }
 
+    /**
+     * Starts {@param a} on all wallpaper windows.
+     */
+    void startWallpaperAnimation(Animation a) {
+        for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
+            final WindowToken token = mWallpaperTokens.get(curTokenNdx);
+            token.startAnimation(a);
+        }
+    }
+
     private boolean isWallpaperVisible(WindowState wallpaperTarget) {
         if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
                 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
@@ -383,6 +397,7 @@
         boolean inFreeformSpace = false;
         boolean replacing = false;
         boolean keyguardGoingAwayWithWallpaper = false;
+        boolean needsShowWhenLockedWallpaper = false;
 
         for (int i = windows.size() - 1; i >= 0; i--) {
             w = windows.get(i);
@@ -413,7 +428,19 @@
 
             replacing |= w.mWillReplaceWindow;
             keyguardGoingAwayWithWallpaper |= (w.mAppToken != null
-                    && w.mWinAnimator.mKeyguardGoingAwayWithWallpaper);
+                    && AppTransition.isKeyguardGoingAwayTransit(
+                            w.mAppToken.mAppAnimator.getTransit())
+                    && (w.mAppToken.mAppAnimator.getTransitFlags()
+                            & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0);
+
+            if ((w.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
+                    && mService.mPolicy.isKeyguardLocked()
+                    && mService.mPolicy.isKeyguardOccluded()) {
+                // The lowest show when locked window decides whether we need to put the wallpaper
+                // behind.
+                needsShowWhenLockedWallpaper = !isFullscreen(w.mAttrs)
+                        || (w.mAppToken != null && !w.mAppToken.fillsParent());
+            }
 
             final boolean hasWallpaper = (w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
             if (hasWallpaper && w.isOnScreen() && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
@@ -447,14 +474,19 @@
             // appear and can determine the visibility, to avoid flickering.
             result.setWallpaperTarget(result.topWallpaper, result.topWallpaperIndex);
 
-        } else if (keyguardGoingAwayWithWallpaper) {
-            // If the app is executing an animation because the keyguard is going away (and the
-            // keyguard was showing the wallpaper) keep the wallpaper during the animation so it
-            // doesn't flicker out by having it be its own target.
+        } else if (keyguardGoingAwayWithWallpaper || needsShowWhenLockedWallpaper) {
+            // Keep the wallpaper during Keyguard exit but also when it's needed for a
+            // non-fullscreen show when locked activity.
             result.setWallpaperTarget(result.topWallpaper, result.topWallpaperIndex);
         }
     }
 
+    private boolean isFullscreen(WindowManager.LayoutParams attrs) {
+        return attrs.x == 0 && attrs.y == 0
+                && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
+                && attrs.height == WindowManager.LayoutParams.MATCH_PARENT;
+    }
+
     /** Updates the target wallpaper if needed and returns true if an update happened. */
     private boolean updateWallpaperWindowsTarget(
             ReadOnlyWindowList windows, FindWallpaperTargetResult result) {