Focus HUN with FPV instead of the FA

This allows us to use FAs for each notification card (so that rotation
stays within each card). The FPV will still focus a view in the HUN
window based on ViewUtils#adjustFocus, so we're able to focus the
appropriate view.

This approach also deals with the stray focus that we have when we see
the first HUN in rotary mode.

Bug: 172267951
Bug: 172268552
Test: manual
Change-Id: I8a3af5ec60749f8463d6655b232d9c67da083c6e
diff --git a/src/com/android/car/rotary/Navigator.java b/src/com/android/car/rotary/Navigator.java
index f1c10e9..32598f8 100644
--- a/src/com/android/car/rotary/Navigator.java
+++ b/src/com/android/car/rotary/Navigator.java
@@ -59,44 +59,6 @@
         mHunNudgeDirection = showHunOnBottom ? View.FOCUS_DOWN : View.FOCUS_UP;
     }
 
-    /**
-     * Returns a target node representing a HUN FocusArea for a nudge in {@code direction}. The
-     * caller is responsible for recycling the result.
-     *
-     * @param windows    a list of windows to search from
-     * @param sourceNode the current focus
-     * @param direction  nudge direction, must be {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
-     *                   {@link View#FOCUS_LEFT}, or {@link View#FOCUS_RIGHT}
-     * @return a node representing a HUN FocusArea, or null if the HUN isn't present, the nudge
-     *         isn't in the direction of the HUN, or the HUN contains no views that can take focus
-     */
-    @Nullable
-    AccessibilityNodeInfo findHunFocusArea(@NonNull List<AccessibilityWindowInfo> windows,
-            @NonNull AccessibilityNodeInfo sourceNode, int direction) {
-        if (direction != mHunNudgeDirection) {
-            return null;
-        }
-
-        // Find the HUN window, if any.
-        AccessibilityWindowInfo hunWindow = findHunWindow(windows);
-        if (hunWindow == null) {
-            return null;
-        }
-
-        // Find the target focus area within the HUN. The HUN may overlap the source node, in which
-        // case the geometric search will fail. The fallback is to use the first (typically only)
-        // focus area.
-        List<AccessibilityNodeInfo> hunFocusAreas = findFocusAreas(hunWindow);
-        removeEmptyFocusAreas(hunFocusAreas);
-        AccessibilityNodeInfo targetFocusArea =
-                chooseBestNudgeCandidate(sourceNode, hunFocusAreas, direction);
-        if (targetFocusArea == null && !hunFocusAreas.isEmpty()) {
-            targetFocusArea = copyNode(hunFocusAreas.get(0));
-        }
-        Utils.recycleNodes(hunFocusAreas);
-        return targetFocusArea;
-    }
-
     @Nullable
     AccessibilityWindowInfo findHunWindow(@NonNull List<AccessibilityWindowInfo> windows) {
         for (AccessibilityWindowInfo window : windows) {
diff --git a/src/com/android/car/rotary/RotaryService.java b/src/com/android/car/rotary/RotaryService.java
index dd0704d..daa27c5 100644
--- a/src/com/android/car/rotary/RotaryService.java
+++ b/src/com/android/car/rotary/RotaryService.java
@@ -1143,16 +1143,10 @@
 
     private boolean nudgeTo(@NonNull List<AccessibilityWindowInfo> windows, int direction) {
         // If the HUN is in the nudge direction, nudge to it.
-        AccessibilityNodeInfo hunFocusArea =
-                mNavigator.findHunFocusArea(windows, mFocusedNode, direction);
-        boolean success;
-        if (hunFocusArea != null) {
-            success = performFocusAction(hunFocusArea);
-            L.d(success ? "Nudge to HUN" : " Failed to nudge to HUN " + hunFocusArea);
-            hunFocusArea.recycle();
-            if (success) {
-                return true;
-            }
+        boolean hunFocusResult = focusHunsWindow(windows, direction);
+        if (hunFocusResult) {
+            L.d("Nudge to HUN successful");
+            return true;
         }
 
         // Try to move the focus to the shortcut node.
@@ -1197,7 +1191,7 @@
         if (Utils.isFocusArea(targetFocusArea)) {
             arguments.clear();
             arguments.putInt(NUDGE_DIRECTION, direction);
-            success = performFocusAction(targetFocusArea, arguments);
+            boolean success = performFocusAction(targetFocusArea, arguments);
             L.d("Nudging to the nearest FocusArea "
                     + (success ? "succeeded" : "failed: " + targetFocusArea));
             targetFocusArea.recycle();
@@ -1206,7 +1200,7 @@
 
         // targetFocusArea is an implicit FocusArea (i.e., the root node of a window without any
         // FocusAreas), so restore the focus in it.
-        success = restoreDefaultFocus(targetFocusArea);
+        boolean success = restoreDefaultFocus(targetFocusArea);
         L.d("Nudging to the nearest implicit focus area "
                 + (success ? "succeeded" : "failed: " + targetFocusArea));
         targetFocusArea.recycle();