Merge "Update handle menu coordinates properly on rotate." into main
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 03f0c7fb..7988983 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -345,7 +345,7 @@
         }
 
         if (isHandleMenuActive()) {
-            mHandleMenu.relayout(startT);
+            mHandleMenu.relayout(startT, mResult.mCaptionX);
         }
 
         updateRelayoutParams(mRelayoutParams, mContext, taskInfo, applyStartTransactionOnDraw,
@@ -871,7 +871,9 @@
                 splitScreenController,
                 DesktopModeStatus.canEnterDesktopMode(mContext),
                 browserLinkAvailable(),
-                mResult.mCaptionHeight
+                mResult.mCaptionWidth,
+                mResult.mCaptionHeight,
+                mResult.mCaptionX
         );
         mWindowDecorViewHolder.onHandleMenuOpened();
         mHandleMenu.show();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt
index b51b700..e174e83 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt
@@ -69,7 +69,9 @@
     private val splitScreenController: SplitScreenController,
     private val shouldShowWindowingPill: Boolean,
     private val shouldShowBrowserPill: Boolean,
-    private val captionHeight: Int
+    private val captionWidth: Int,
+    private val captionHeight: Int,
+    captionX: Int
 ) {
     private val context: Context = parentDecor.mDecorWindowContext
     private val taskInfo: ActivityManager.RunningTaskInfo = parentDecor.mTaskInfo
@@ -105,7 +107,7 @@
     private val globalMenuPosition: Point = Point()
 
     init {
-        updateHandleMenuPillPositions()
+        updateHandleMenuPillPositions(captionX)
     }
 
     fun show() {
@@ -262,11 +264,11 @@
     /**
      * Updates handle menu's position variables to reflect its next position.
      */
-    private fun updateHandleMenuPillPositions() {
+    private fun updateHandleMenuPillPositions(captionX: Int) {
         val menuX: Int
         val menuY: Int
         val taskBounds = taskInfo.getConfiguration().windowConfiguration.bounds
-        updateGlobalMenuPosition(taskBounds)
+        updateGlobalMenuPosition(taskBounds, captionX)
         if (layoutResId == R.layout.desktop_mode_app_header) {
             // Align the handle menu to the left side of the caption.
             menuX = marginMenuStart
@@ -287,7 +289,8 @@
         handleMenuPosition.set(menuX.toFloat(), menuY.toFloat())
     }
 
-    private fun updateGlobalMenuPosition(taskBounds: Rect) {
+    private fun updateGlobalMenuPosition(taskBounds: Rect, captionX: Int) {
+        val nonFreeformX = captionX + (captionWidth / 2) - (menuWidth / 2)
         when {
             taskInfo.isFreeform -> {
                 globalMenuPosition.set(
@@ -297,7 +300,7 @@
             }
             taskInfo.isFullscreen -> {
                 globalMenuPosition.set(
-                    /* x = */ taskBounds.width() / 2 - (menuWidth / 2),
+                    /* x = */ nonFreeformX,
                     /* y = */ marginMenuTop
                 )
             }
@@ -311,16 +314,13 @@
                 when (splitPosition) {
                     SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT -> {
                         globalMenuPosition.set(
-                            /* x = */ leftOrTopStageBounds.width()
-                                    + (rightOrBottomStageBounds.width() / 2)
-                                    - (menuWidth / 2),
+                            /* x = */ leftOrTopStageBounds.width() + nonFreeformX,
                             /* y = */ marginMenuTop
                         )
                     }
                     SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT -> {
                         globalMenuPosition.set(
-                            /* x = */ (leftOrTopStageBounds.width() / 2)
-                                    - (menuWidth / 2),
+                            /* x = */ nonFreeformX,
                             /* y = */ marginMenuTop
                         )
                     }
@@ -332,9 +332,12 @@
     /**
      * Update pill layout, in case task changes have caused positioning to change.
      */
-    fun relayout(t: SurfaceControl.Transaction) {
+    fun relayout(
+        t: SurfaceControl.Transaction,
+        captionX: Int
+    ) {
         handleMenuViewContainer?.let { container ->
-            updateHandleMenuPillPositions()
+            updateHandleMenuPillPositions(captionX)
             container.setPosition(t, handleMenuPosition.x, handleMenuPosition.y)
         }
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainer.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainer.kt
index 4897f76..03d2421 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainer.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainer.kt
@@ -38,6 +38,7 @@
     height: Int
 ) : AdditionalViewContainer() {
     override val view: View
+    val windowManager: WindowManager? = context.getSystemService(WindowManager::class.java)
 
     init {
         view = LayoutInflater.from(context).inflate(layoutId, null)
@@ -51,12 +52,11 @@
             gravity = Gravity.LEFT or Gravity.TOP
             setTrustedOverlay()
         }
-        val wm: WindowManager? = context.getSystemService(WindowManager::class.java)
-        wm?.addView(view, lp)
+        windowManager?.addView(view, lp)
     }
 
     override fun releaseView() {
-        context.getSystemService(WindowManager::class.java)?.removeViewImmediate(view)
+        windowManager?.removeViewImmediate(view)
     }
 
     override fun setPosition(t: SurfaceControl.Transaction, x: Float, y: Float) {
@@ -64,6 +64,6 @@
             this.x = x.toInt()
             this.y = y.toInt()
         }
-        view.layoutParams = lp
+        windowManager?.updateViewLayout(view, lp)
     }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt
index adda9a6..e548f8f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt
@@ -130,7 +130,7 @@
     @EnableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
     fun testFullscreenMenuUsesSystemViewContainer() {
         createTaskInfo(WINDOWING_MODE_FULLSCREEN, SPLIT_POSITION_UNDEFINED)
-        val handleMenu = createAndShowHandleMenu()
+        val handleMenu = createAndShowHandleMenu(SPLIT_POSITION_UNDEFINED)
         assertTrue(handleMenu.handleMenuViewContainer is AdditionalSystemViewContainer)
         // Verify menu is created at coordinates that, when added to WindowManager,
         // show at the top-center of display.
@@ -142,7 +142,7 @@
     @EnableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
     fun testFreeformMenu_usesViewHostViewContainer() {
         createTaskInfo(WINDOWING_MODE_FREEFORM, SPLIT_POSITION_UNDEFINED)
-        handleMenu = createAndShowHandleMenu()
+        handleMenu = createAndShowHandleMenu(SPLIT_POSITION_UNDEFINED)
         assertTrue(handleMenu.handleMenuViewContainer is AdditionalViewHostViewContainer)
         // Verify menu is created near top-left of task.
         val expected = Point(MENU_START_MARGIN, MENU_TOP_MARGIN)
@@ -153,7 +153,7 @@
     @EnableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
     fun testSplitLeftMenu_usesSystemViewContainer() {
         createTaskInfo(WINDOWING_MODE_MULTI_WINDOW, SPLIT_POSITION_TOP_OR_LEFT)
-        handleMenu = createAndShowHandleMenu()
+        handleMenu = createAndShowHandleMenu(SPLIT_POSITION_TOP_OR_LEFT)
         assertTrue(handleMenu.handleMenuViewContainer is AdditionalSystemViewContainer)
         // Verify menu is created at coordinates that, when added to WindowManager,
         // show at the top-center of split left task.
@@ -168,7 +168,7 @@
     @EnableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
     fun testSplitRightMenu_usesSystemViewContainer() {
         createTaskInfo(WINDOWING_MODE_MULTI_WINDOW, SPLIT_POSITION_BOTTOM_OR_RIGHT)
-        handleMenu = createAndShowHandleMenu()
+        handleMenu = createAndShowHandleMenu(SPLIT_POSITION_BOTTOM_OR_RIGHT)
         assertTrue(handleMenu.handleMenuViewContainer is AdditionalSystemViewContainer)
         // Verify menu is created at coordinates that, when added to WindowManager,
         // show at the top-center of split right task.
@@ -208,16 +208,30 @@
         }
     }
 
-    private fun createAndShowHandleMenu(): HandleMenu {
+    private fun createAndShowHandleMenu(splitPosition: Int): HandleMenu {
         val layoutId = if (mockDesktopWindowDecoration.mTaskInfo.isFreeform) {
             R.layout.desktop_mode_app_header
         } else {
             R.layout.desktop_mode_app_handle
         }
+        val captionX = when (mockDesktopWindowDecoration.mTaskInfo.windowingMode) {
+            WINDOWING_MODE_FULLSCREEN -> (DISPLAY_BOUNDS.width() / 2) - (HANDLE_WIDTH / 2)
+            WINDOWING_MODE_FREEFORM -> 0
+            WINDOWING_MODE_MULTI_WINDOW -> {
+                if (splitPosition == SPLIT_POSITION_TOP_OR_LEFT) {
+                    (SPLIT_LEFT_BOUNDS.width() / 2) - (HANDLE_WIDTH / 2)
+                } else {
+                    (SPLIT_RIGHT_BOUNDS.width() / 2) - (HANDLE_WIDTH / 2)
+                }
+            }
+            else -> error("Invalid windowing mode")
+        }
         val handleMenu = HandleMenu(mockDesktopWindowDecoration, layoutId,
                 onClickListener, onTouchListener, appIcon, appName, displayController,
-                splitScreenController, true /* shouldShowWindowingPill */,
-                true /* shouldShowBrowserPill */, 50 /* captionHeight */)
+                splitScreenController, shouldShowWindowingPill = true,
+                shouldShowBrowserPill = true, captionWidth = HANDLE_WIDTH, captionHeight = 50,
+                captionX = captionX
+        )
         handleMenu.show()
         return handleMenu
     }
@@ -233,5 +247,6 @@
         private const val MENU_START_MARGIN = 20
         private const val MENU_PILL_ELEVATION = 2
         private const val MENU_PILL_SPACING_MARGIN = 4
+        private const val HANDLE_WIDTH = 80
     }
 }