Find next focus id from inside-out.
Bug: 5165543

This change fixes some problems when the view hierarchy contains
duplicate ids, such as when ListViews contain nested custom views.
If the custom views contain next focused id hints, then the system
should prefer the other views within the ListView item over any
other views outside of the ListView item.

Change-Id: I5653ff6bac0bf9f08bd6ecbe5a3bb22ea47ab566
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 946f009..133f435 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -3545,16 +3545,16 @@
      * First look in our children, then in any header and footer views that may be scrolled off.
      */
     @Override
-    protected View findViewByPredicateTraversal(Predicate<View> predicate) {
+    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
         View v;
-        v = super.findViewByPredicateTraversal(predicate);
+        v = super.findViewByPredicateTraversal(predicate, childToSkip);
         if (v == null) {
-            v = findViewByPredicateInHeadersOrFooters(mHeaderViewInfos, predicate);
+            v = findViewByPredicateInHeadersOrFooters(mHeaderViewInfos, predicate, childToSkip);
             if (v != null) {
                 return v;
             }
 
-            v = findViewByPredicateInHeadersOrFooters(mFooterViewInfos, predicate);
+            v = findViewByPredicateInHeadersOrFooters(mFooterViewInfos, predicate, childToSkip);
             if (v != null) {
                 return v;
             }
@@ -3568,7 +3568,7 @@
      * the predicate.
      */
     View findViewByPredicateInHeadersOrFooters(ArrayList<FixedViewInfo> where,
-            Predicate<View> predicate) {
+            Predicate<View> predicate, View childToSkip) {
         if (where != null) {
             int len = where.size();
             View v;
@@ -3576,7 +3576,7 @@
             for (int i = 0; i < len; i++) {
                 v = where.get(i).view;
 
-                if (!v.isRootNamespace()) {
+                if (v != childToSkip && !v.isRootNamespace()) {
                     v = v.findViewByPredicate(predicate);
 
                     if (v != null) {