Search from root after nudge

When RotaryService performs an action to request a FocusArea to handle a
nudge event, if it succeeds, the focus will be in another focus area.
For RotaryService to find the new focus, it must search from the root of
the window rather than from the previous focus area.

Bug: 169886834
Test: nudge in CustomFocusAreas tab in RotaryPlayground, verify logs
Change-Id: Ia4aa1140ab966486855a9b302fc5dae9487beb11
diff --git a/src/com/android/car/rotary/RotaryService.java b/src/com/android/car/rotary/RotaryService.java
index d9624d5..5ae95b6 100644
--- a/src/com/android/car/rotary/RotaryService.java
+++ b/src/com/android/car/rotary/RotaryService.java
@@ -1164,7 +1164,11 @@
         arguments.putInt(NUDGE_DIRECTION, direction);
         if (mFocusArea.performAction(ACTION_NUDGE_SHORTCUT, arguments)) {
             L.d("Nudge to shortcut view");
-            findFocusedNode(mFocusArea);
+            AccessibilityNodeInfo root = Utils.getRoot(mFocusArea);
+            if (root != null) {
+                findFocusedNode(root);
+                root.recycle();
+            }
             return true;
         }
 
@@ -1174,7 +1178,11 @@
         arguments.putInt(NUDGE_DIRECTION, direction);
         if (mFocusArea.performAction(ACTION_NUDGE_TO_ANOTHER_FOCUS_AREA, arguments)) {
             L.d("Nudge to user specified FocusArea");
-            findFocusedNode(mFocusArea);
+            AccessibilityNodeInfo root = Utils.getRoot(mFocusArea);
+            if (root != null) {
+                findFocusedNode(root);
+                root.recycle();
+            }
             return true;
         }
 
@@ -1269,7 +1277,7 @@
                     mNavigator.findScrollableContainer(mFocusedNode);
             if (scrollableContainer != null) {
                 injectScrollEvent(scrollableContainer, clockwise, remainingRotationCount);
-                scrollableContainer.recycle();;
+                scrollableContainer.recycle();
             }
         }
     }
diff --git a/src/com/android/car/rotary/Utils.java b/src/com/android/car/rotary/Utils.java
index 5513361..23560ad 100644
--- a/src/com/android/car/rotary/Utils.java
+++ b/src/com/android/car/rotary/Utils.java
@@ -373,4 +373,19 @@
         }
         return null;
     }
+
+    /**
+     * Returns the root node in the tree containing {@code node}. Returns null if unable to get
+     * the root node for any reason. The caller is responsible for recycling the result.
+     */
+    @Nullable
+    static AccessibilityNodeInfo getRoot(@NonNull AccessibilityNodeInfo node) {
+        AccessibilityWindowInfo window = node.getWindow();
+        if (window == null) {
+            return null;
+        }
+        AccessibilityNodeInfo root = window.getRoot();
+        window.recycle();
+        return root;
+    }
 }