Merge "[wm]: Make the navigation bar in translucent mode when overlapping with freeform"
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index cf87203..61ba69f 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -284,6 +284,8 @@
     /** See {@link #getNavigationBarFrameHeight} */
     private int[] mNavigationBarFrameHeightForRotationDefault = new int[4];
 
+    private boolean mIsFreeformWindowOverlappingWithNavBar;
+
     /** Cached value of {@link ScreenShapeHelper#getWindowOutsetBottomPx} */
     @Px private int mWindowOutsetBottom;
 
@@ -2379,6 +2381,7 @@
         mAllowLockscreenWhenOn = false;
         mShowingDream = false;
         mWindowSleepTokenNeeded = false;
+        mIsFreeformWindowOverlappingWithNavBar = false;
     }
 
     /**
@@ -2478,6 +2481,13 @@
             }
         }
 
+        // Check if the freeform window overlaps with the navigation bar area.
+        final WindowState navBarWin = hasNavigationBar() ? mNavigationBar : null;
+        if (!mIsFreeformWindowOverlappingWithNavBar && win.inFreeformWindowingMode()
+                && isOverlappingWithNavBar(win, navBarWin)) {
+            mIsFreeformWindowOverlappingWithNavBar = true;
+        }
+
         // Also keep track of any windows that are dimming but not necessarily fullscreen in the
         // docked stack.
         if (mTopDockedOpaqueOrDimmingWindowState == null && affectsSystemUi && win.isDimming()
@@ -3458,7 +3468,11 @@
             }
         } else if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
             if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
-                visibility = setNavBarOpaqueFlag(visibility);
+                if (mIsFreeformWindowOverlappingWithNavBar) {
+                    visibility = setNavBarTranslucentFlag(visibility);
+                } else {
+                    visibility = setNavBarOpaqueFlag(visibility);
+                }
             } else if (fullscreenDrawsBackground) {
                 visibility = setNavBarTransparentFlag(visibility);
             }
@@ -3747,4 +3761,14 @@
         wm.removeView(mPointerLocationView);
         mPointerLocationView = null;
     }
+
+    @VisibleForTesting
+    static boolean isOverlappingWithNavBar(WindowState targetWindow, WindowState navBarWindow) {
+        if (navBarWindow == null || !navBarWindow.isVisibleLw()
+                || targetWindow.mAppToken == null || !targetWindow.isVisibleLw()) {
+            return false;
+        }
+
+        return Rect.intersects(targetWindow.getFrameLw(), navBarWindow.getFrameLw());
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index 1684f97..6a3c81a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -32,6 +32,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -49,10 +50,12 @@
 import static org.mockito.Mockito.when;
 
 import android.graphics.PixelFormat;
+import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.view.Surface;
 import android.view.WindowManager;
 
+import androidx.test.filters.FlakyTest;
 import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
@@ -273,4 +276,37 @@
         win.mHasSurface = true;
         return win;
     }
+
+    @Test
+    @FlakyTest(bugId = 131005232)
+    public void testOverlappingWithNavBar() {
+        final WindowState targetWin = createApplicationWindow();
+        final WindowFrames winFrame = targetWin.getWindowFrames();
+        winFrame.mFrame.set(new Rect(100, 100, 200, 200));
+
+        final WindowState navigationBar = createNavigationBarWindow();
+
+        navigationBar.getFrameLw().set(new Rect(100, 200, 200, 300));
+
+        assertFalse("Freeform is overlapping with navigation bar",
+                DisplayPolicy.isOverlappingWithNavBar(targetWin, navigationBar));
+
+        winFrame.mFrame.set(new Rect(100, 101, 200, 201));
+        assertTrue("Freeform should be overlapping with navigation bar (bottom)",
+                DisplayPolicy.isOverlappingWithNavBar(targetWin, navigationBar));
+
+        winFrame.mFrame.set(new Rect(99, 200, 199, 300));
+        assertTrue("Freeform should be overlapping with navigation bar (right)",
+                DisplayPolicy.isOverlappingWithNavBar(targetWin, navigationBar));
+
+        winFrame.mFrame.set(new Rect(199, 200, 299, 300));
+        assertTrue("Freeform should be overlapping with navigation bar (left)",
+                DisplayPolicy.isOverlappingWithNavBar(targetWin, navigationBar));
+    }
+
+    private WindowState createNavigationBarWindow() {
+        final WindowState win = createWindow(null, TYPE_NAVIGATION_BAR, "NavigationBar");
+        win.mHasSurface = true;
+        return win;
+    }
 }