Introduce new constant for double tap gesture rotation hint.

As discussed in ag/1192965/ we have a special case for rotation
animation selection in launch from double tap. This was set to
ROTATION_ANIMATION_CROSSFADE as the goal was just to avoid
ROTATION_ANIMATION_ROTATE on the viewfinder surface and
seamless rotation in launch scenarios was initially descoped. Now we
are aiming at fixing this though, and ROTATION_ANIMATION_CROSSFADE
does not quality for seamless rotation. ROTATION_ANIMATION_JUMPCUT
also would not be a good choice because in the situation that the
rotation occurs before the app starting window appears, then we would
jump cut from unrotated wallpaper to rotated app, I think we want
a crossfade in this scenario. To this end introduce and use a new @hide constant
ROTATION_ANIMATION_SEAMLESS which qualifies for seamless but falls back
to CROSSFADE if seamless can't occur.

Bug: 30171992
Change-Id: If1945b17b5159be4cd5ba0b139d6bea9f7fcca33
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 1b37ed4..eb6b17e 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1581,6 +1581,15 @@
         public static final int ROTATION_ANIMATION_JUMPCUT = 2;
 
         /**
+         * Value for {@link #rotationAnimation} to specify seamless rotation mode.
+         * This works like JUMPCUT but will fall back to CROSSFADE if rotation
+         * can't be applied without pausing the screen.
+         *
+         * @hide
+         */
+        public static final int ROTATION_ANIMATION_SEAMLESS = 3;
+
+        /**
          * Define the exit and entry animations used on this window when the device is rotated.
          * This only has an affect if the incoming and outgoing topmost
          * opaque windows have the #FLAG_FULLSCREEN bit set and are not covered
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 048c4bd..8cabfb9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -461,7 +461,7 @@
                     // happens to occur during the launch.
                     ActivityOptions o = ActivityOptions.makeBasic();
                     o.setRotationAnimationHint(
-                            WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE);
+                            WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS);
                     try {
                         result = ActivityManagerNative.getDefault().startActivityAsUser(
                                 null, getContext().getBasePackageName(),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index b4368d6..447a343 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -3419,7 +3419,7 @@
                     // force the crossfade animation if an orientation change
                     // happens to occur during the launch.
                     options.setRotationAnimationHint(
-                            WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE);
+                            WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS);
                 }
                 try {
                     result = ActivityManagerNative.getDefault().startActivityAsUser(
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index f7454a3..0b07902 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2891,6 +2891,7 @@
             }
             switch (animationHint) {
                 case ROTATION_ANIMATION_CROSSFADE:
+                case ROTATION_ANIMATION_SEAMLESS: // Crossfade is fallback for seamless.
                     anim[0] = R.anim.rotation_animation_xfade_exit;
                     anim[1] = R.anim.rotation_animation_enter;
                     break;
@@ -7751,14 +7752,15 @@
             return false;
         }
 
+        final WindowState w = mTopFullscreenOpaqueWindowState;
+
         // We only enable seamless rotation if the top window has requested
         // it and is in the fullscreen opaque state. Seamless rotation
         // requires freezing various Surface states and won't work well
         // with animations, so we disable it in the animation case for now.
-        if (mTopFullscreenOpaqueWindowState != null && mTopIsFullscreen &&
-                !mTopFullscreenOpaqueWindowState.isAnimatingLw() &&
-                mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation ==
-                ROTATION_ANIMATION_JUMPCUT) {
+        if (w != null  && mTopIsFullscreen && !w.isAnimatingLw() &&
+                ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) ||
+                        (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) {
             return true;
         }
         return false;