Merge "Place black background only behind nav bar when letterboxed" into oc-dr1-dev
am: 3289a5a1e0

Change-Id: Id4069e1c1126d9658a18a448a4bd7566af938cbb
diff --git a/services/core/java/com/android/server/wm/SurfaceControlWithBackground.java b/services/core/java/com/android/server/wm/SurfaceControlWithBackground.java
index ac06c6d..3603f2f 100644
--- a/services/core/java/com/android/server/wm/SurfaceControlWithBackground.java
+++ b/services/core/java/com/android/server/wm/SurfaceControlWithBackground.java
@@ -29,12 +29,16 @@
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static android.view.WindowManagerPolicy.NAV_BAR_BOTTOM;
+import static android.view.WindowManagerPolicy.NAV_BAR_LEFT;
+import static android.view.WindowManagerPolicy.NAV_BAR_RIGHT;
 
 /**
- * SurfaceControl extension that has background sized to match its container.
+ * SurfaceControl extension that has black background behind navigation bar area for fullscreen
+ * letterboxed apps.
  */
 class SurfaceControlWithBackground extends SurfaceControl {
-    // SurfaceControl that holds the background behind opaque letterboxed app windows.
+    // SurfaceControl that holds the background.
     private SurfaceControl mBackgroundControl;
 
     // Flag that defines whether the background should be shown.
@@ -51,8 +55,10 @@
     private float mLastDsDx = 1, mLastDsDy = 1;
     private float mLastX, mLastY;
 
-    // Will skip alpha animation for background of starting window.
-    private boolean mIsStartingWindow;
+    // SurfaceFlinger doesn't support crop rectangles where width or height is non-positive.
+    // If we just set an empty crop it will behave as if there is no crop at all.
+    // To fix this we explicitly hide the surface and won't let it to be shown.
+    private boolean mHiddenForCrop = false;
 
     public SurfaceControlWithBackground(SurfaceControlWithBackground other) {
         super(other);
@@ -76,7 +82,6 @@
         mLastWidth = w;
         mLastHeight = h;
         mWindowSurfaceController.getContainerRect(mTmpContainerRect);
-        mIsStartingWindow = windowType == TYPE_APPLICATION_STARTING;
         mBackgroundControl = new SurfaceControl(s, "Background for - " + name,
                 mTmpContainerRect.width(), mTmpContainerRect.height(), PixelFormat.OPAQUE,
                 flags | SurfaceControl.FX_SURFACE_DIM);
@@ -89,10 +94,7 @@
         if (mBackgroundControl == null) {
             return;
         }
-        // We won't animate alpha for starting window because it will be visible as a flash for user
-        // when fading out to reveal real app window.
-        final float backgroundAlpha = mIsStartingWindow && alpha < 1.f ? 0 : alpha;
-        mBackgroundControl.setAlpha(backgroundAlpha);
+        mBackgroundControl.setAlpha(alpha);
     }
 
     @Override
@@ -146,15 +148,10 @@
         if (mBackgroundControl == null) {
             return;
         }
-        if (crop.width() < mLastWidth || crop.height() < mLastHeight) {
-            // We're animating and cropping window, compute the appropriate crop for background.
-            calculateBgCrop(crop);
-            mBackgroundControl.setWindowCrop(mTmpContainerRect);
-        } else {
-            // When not animating just set crop to container rect.
-            mWindowSurfaceController.getContainerRect(mTmpContainerRect);
-            mBackgroundControl.setWindowCrop(mTmpContainerRect);
-        }
+        calculateBgCrop(crop);
+        mBackgroundControl.setWindowCrop(mTmpContainerRect);
+        mHiddenForCrop = mTmpContainerRect.isEmpty();
+        updateBackgroundVisibility();
     }
 
     @Override
@@ -164,34 +161,24 @@
         if (mBackgroundControl == null) {
             return;
         }
-        if (crop.width() < mLastWidth || crop.height() < mLastHeight) {
-            // We're animating and cropping window, compute the appropriate crop for background.
-            calculateBgCrop(crop);
-            mBackgroundControl.setFinalCrop(mTmpContainerRect);
-        } else {
-            // When not animating just set crop to container rect.
-            mWindowSurfaceController.getContainerRect(mTmpContainerRect);
-            mBackgroundControl.setFinalCrop(mTmpContainerRect);
-        }
+        mWindowSurfaceController.getContainerRect(mTmpContainerRect);
+        mBackgroundControl.setFinalCrop(mTmpContainerRect);
     }
 
-    /** Compute background crop based on current animation progress for main surface control. */
+    /**
+     * Compute background crop based on current animation progress for main surface control and
+     * update {@link #mTmpContainerRect} with new values.
+     */
     private void calculateBgCrop(Rect crop) {
         // Track overall progress of animation by computing cropped portion of status bar.
         final Rect contentInsets = mWindowSurfaceController.mAnimator.mWin.mContentInsets;
         float d = contentInsets.top == 0 ? 0 : (float) crop.top / contentInsets.top;
         if (d > 1.f) {
             // We're running expand animation from launcher, won't compute custom bg crop here.
-            mTmpContainerRect.set(crop);
+            mTmpContainerRect.setEmpty();
             return;
         }
 
-        // Compute additional offset for the background when app window is positioned not at (0,0).
-        // E.g. landscape with navigation bar on the left.
-        final Rect winFrame = mWindowSurfaceController.mAnimator.mWin.mFrame;
-        final int offsetX = (int) (winFrame.left * mLastDsDx * d + 0.5);
-        final int offsetY = (int) (winFrame.top * mLastDsDy * d + 0.5);
-
         // Compute new scaled width and height for background that will depend on current animation
         // progress. Those consist of current crop rect for the main surface + scaled areas outside
         // of letterboxed area.
@@ -201,17 +188,39 @@
         // computing correct frames for letterboxed windows in WindowState.
         d = d < 0.025f ? 0 : d;
         mWindowSurfaceController.getContainerRect(mTmpContainerRect);
-        final int backgroundWidth =
-                (int) (crop.width() + (mTmpContainerRect.width() - mLastWidth) * (1 - d) + 0.5);
-        final int backgroundHeight =
-                (int) (crop.height() + (mTmpContainerRect.height() - mLastHeight) * (1 - d) + 0.5);
+        int backgroundWidth = 0, backgroundHeight = 0;
+        // Compute additional offset for the background when app window is positioned not at (0,0).
+        // E.g. landscape with navigation bar on the left.
+        final Rect winFrame = mWindowSurfaceController.mAnimator.mWin.mFrame;
+        int offsetX = (int)((winFrame.left - mTmpContainerRect.left) * mLastDsDx),
+                offsetY = (int) ((winFrame.top - mTmpContainerRect.top) * mLastDsDy);
 
-        mTmpContainerRect.set(crop);
-        // Make sure that part of background to left/top is visible and scaled.
-        mTmpContainerRect.offset(offsetX, offsetY);
-        // Set correct width/height, so that area to right/bottom is cropped properly.
-        mTmpContainerRect.right = mTmpContainerRect.left + backgroundWidth;
-        mTmpContainerRect.bottom = mTmpContainerRect.top + backgroundHeight;
+        // Position and size background.
+        final int bgPosition = mWindowSurfaceController.mAnimator.mService.getNavBarPosition();
+
+        switch (bgPosition) {
+            case NAV_BAR_LEFT:
+                backgroundWidth = (int) ((mTmpContainerRect.width() - mLastWidth) * (1 - d) + 0.5);
+                backgroundHeight = crop.height();
+                offsetX += crop.left - backgroundWidth;
+                offsetY += crop.top;
+                break;
+            case NAV_BAR_RIGHT:
+                backgroundWidth = (int) ((mTmpContainerRect.width() - mLastWidth) * (1 - d) + 0.5);
+                backgroundHeight = crop.height();
+                offsetX += crop.right;
+                offsetY += crop.top;
+                break;
+            case NAV_BAR_BOTTOM:
+                backgroundWidth = crop.width();
+                backgroundHeight = (int) ((mTmpContainerRect.height() - mLastHeight) * (1 - d)
+                        + 0.5);
+                offsetX += crop.left;
+                offsetY += crop.bottom;
+                break;
+        }
+        mTmpContainerRect.set(offsetX, offsetY, offsetX + backgroundWidth,
+                offsetY + backgroundHeight);
     }
 
     @Override
@@ -317,7 +326,7 @@
             return;
         }
         final AppWindowToken appWindowToken = mWindowSurfaceController.mAnimator.mWin.mAppToken;
-        if (appWindowToken != null && appWindowToken.fillsParent() && mVisible) {
+        if (!mHiddenForCrop && mVisible && appWindowToken != null && appWindowToken.fillsParent()) {
             mBackgroundControl.show();
         } else {
             mBackgroundControl.hide();