Tailor the bounds of rotary container when finding nudge target

Bug: 171575056
Test: manual
Change-Id: Ic96ba7ef7d524061305458f57c49de86eba221b1
diff --git a/src/com/android/car/rotary/Utils.java b/src/com/android/car/rotary/Utils.java
index 9289ba1..7883205 100644
--- a/src/com/android/car/rotary/Utils.java
+++ b/src/com/android/car/rotary/Utils.java
@@ -317,7 +317,8 @@
             bounds.bottom -= bundle.getInt(FOCUS_AREA_BOTTOM_BOUND_OFFSET);
         } else if (Utils.isRotaryContainer(node)) {
             // For a rotary container, the bounds used for finding the nudge target are the
-            // minimum bounds containing its children.
+            // intersection of the two bounds: (1) minimum bounds containing its children, and
+            // (2) its ancestor FocusArea's bounds, if any.
             bounds.setEmpty();
             Rect childBounds = new Rect();
             for (int i = 0; i < node.getChildCount(); i++) {
@@ -328,7 +329,27 @@
                     bounds.union(childBounds);
                 }
             }
+            AccessibilityNodeInfo focusArea = getAncestorFocusArea(node);
+            if (focusArea != null) {
+                Rect focusAreaBounds = getBoundsInScreen(focusArea);
+                bounds.setIntersect(bounds, focusAreaBounds);
+                focusArea.recycle();
+            }
         }
         return bounds;
     }
+
+    @Nullable
+    private static AccessibilityNodeInfo getAncestorFocusArea(@NonNull AccessibilityNodeInfo node) {
+        AccessibilityNodeInfo ancestor = node.getParent();
+        while (ancestor != null) {
+            if (isFocusArea(ancestor)) {
+                return ancestor;
+            }
+            AccessibilityNodeInfo nextAncestor = ancestor.getParent();
+            ancestor.recycle();
+            ancestor = nextAncestor;
+        }
+        return null;
+    }
 }