New View.dispatchDisplayHint() API.
Bug #2399147

This new API will be used by scrollable containers to tell children that they
are/are not displayed. This will allow lists to hide their filter popup window
for instance.
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a3d3521..31c9b08 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3789,7 +3789,8 @@
      * ViewGroups should override to route to their children.
      * @param changedView The view whose visibility changed. Could be 'this' or
      * an ancestor view.
-     * @param visibility The new visibility of changedView.
+     * @param visibility The new visibility of changedView: {@link #VISIBLE},
+     * {@link #INVISIBLE} or {@link #GONE}.
      */
     protected void dispatchVisibilityChanged(View changedView, int visibility) {
         onVisibilityChanged(changedView, visibility);
@@ -3799,12 +3800,38 @@
      * Called when the visibility of the view or an ancestor of the view is changed.
      * @param changedView The view whose visibility changed. Could be 'this' or
      * an ancestor view.
-     * @param visibility The new visibility of changedView.
+     * @param visibility The new visibility of changedView: {@link #VISIBLE},
+     * {@link #INVISIBLE} or {@link #GONE}.
      */
     protected void onVisibilityChanged(View changedView, int visibility) {
     }
 
     /**
+     * Dispatch a hint about whether this view is displayed. For instance, when
+     * a View moves out of the screen, it might receives a display hint indicating
+     * the view is not displayed. Applications should not <em>rely</em> on this hint
+     * as there is no guarantee that they will receive one.
+     * 
+     * @param hint A hint about whether or not this view is displayed:
+     * {@link #VISIBLE} or {@link #INVISIBLE}.
+     */
+    public void dispatchDisplayHint(int hint) {
+        onDisplayHint(hint);
+    }
+
+    /**
+     * Gives this view a hint about whether is displayed or not. For instance, when
+     * a View moves out of the screen, it might receives a display hint indicating
+     * the view is not displayed. Applications should not <em>rely</em> on this hint
+     * as there is no guarantee that they will receive one.
+     * 
+     * @param hint A hint about whether or not this view is displayed:
+     * {@link #VISIBLE} or {@link #INVISIBLE}.
+     */
+    protected void onDisplayHint(int hint) {
+    }
+
+    /**
      * Dispatch a window visibility change down the view hierarchy.
      * ViewGroups should override to route to their children.
      *
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 49c2d0e..cdf9eb0 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -679,6 +679,19 @@
             }
         }
     }
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void dispatchDisplayHint(int hint) {
+        super.dispatchDisplayHint(hint);
+        final int count = mChildrenCount;
+        final View[] children = mChildren;
+        for (int i = 0; i < count; i++) {
+            children[i].dispatchDisplayHint(hint);
+        }
+    }
 
     /**
      * {@inheritDoc}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index b795080..3a4b92d 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2852,6 +2852,23 @@
         checkSelectionChanged();
     }
 
+    @Override
+    protected void onDisplayHint(int hint) {
+        super.onDisplayHint(hint);
+        switch (hint) {
+            case INVISIBLE:
+                if (mPopup != null && mPopup.isShowing()) {
+                    dismissPopup();
+                }
+                break;
+            case VISIBLE:
+                if (mFiltered && mPopup != null && !mPopup.isShowing()) {
+                    showPopup();
+                }
+                break;
+        }
+    }
+
     /**
      * Removes the filter window
      */
@@ -3140,7 +3157,7 @@
             }
         } else {
             // Hide the popup when we are no longer visible
-            if (mPopup.isShowing()) {
+            if (mPopup != null && mPopup.isShowing()) {
                 dismissPopup();
             }
         }
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index d53a442..0f47b96 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -1033,6 +1033,18 @@
     }
 
     @Override
+    protected void onDisplayHint(int hint) {
+        super.onDisplayHint(hint);
+        switch (hint) {
+            case INVISIBLE:
+                if (!mDropDownAlwaysVisible) {
+                    dismissDropDown();
+                }
+                break;
+        }
+    }
+
+    @Override
     protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
         super.onFocusChanged(focused, direction, previouslyFocusedRect);
         // Perform validation if the view is losing focus.