Fix AppCompatSpinner not overlaying the IME

Caused by ListPopupWindow using an internal version of
PopupWindow.getMaxAvailableHeight() which allows ignoring
of window decorations. We now use that method via reflection.

BUG: 23387567
Change-Id: I753090f58d7c74b588b15bea2a6fb09b8ed1c58d
diff --git a/v7/appcompat/src/android/support/v7/widget/ListPopupWindow.java b/v7/appcompat/src/android/support/v7/widget/ListPopupWindow.java
index 2b03774..e81bb59 100644
--- a/v7/appcompat/src/android/support/v7/widget/ListPopupWindow.java
+++ b/v7/appcompat/src/android/support/v7/widget/ListPopupWindow.java
@@ -76,6 +76,7 @@
     private static final int EXPAND_LIST_TIMEOUT = 250;
 
     private static Method sClipToWindowEnabledMethod;
+    private static Method sGetMaxAvailableHeightMethod;
 
     static {
         try {
@@ -84,6 +85,13 @@
         } catch (NoSuchMethodException e) {
             Log.i(TAG, "Could not find method setClipToScreenEnabled() on PopupWindow. Oh well.");
         }
+        try {
+            sGetMaxAvailableHeightMethod = PopupWindow.class.getDeclaredMethod(
+                    "getMaxAvailableHeight", View.class, int.class, boolean.class);
+        } catch (NoSuchMethodException e) {
+            Log.i(TAG, "Could not find method getMaxAvailableHeight(View, int, boolean)"
+                    + " on PopupWindow. Oh well.");
+        }
     }
 
     private Context mContext;
@@ -1198,11 +1206,10 @@
         }
 
         // Max height available on the screen for a popup.
-        boolean ignoreBottomDecorations =
+        final boolean ignoreBottomDecorations =
                 mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED;
-        final int maxHeight = mPopup.getMaxAvailableHeight(
-                getAnchorView(), mDropDownVerticalOffset /*, ignoreBottomDecorations*/);
-
+        final int maxHeight = getMaxAvailableHeight(getAnchorView(), mDropDownVerticalOffset,
+                ignoreBottomDecorations);
         if (mDropDownAlwaysVisible || mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) {
             return maxHeight + padding;
         }
@@ -1837,4 +1844,16 @@
         }
     }
 
+    private int getMaxAvailableHeight(View anchor, int yOffset, boolean ignoreBottomDecorations) {
+        if (sGetMaxAvailableHeightMethod != null) {
+            try {
+                return (int) sGetMaxAvailableHeightMethod.invoke(mPopup, anchor, yOffset,
+                        ignoreBottomDecorations);
+            } catch (Exception e) {
+                Log.i(TAG, "Could not call getMaxAvailableHeightMethod(View, int, boolean)"
+                        + " on PopupWindow. Using the public version.");
+            }
+        }
+        return mPopup.getMaxAvailableHeight(anchor, yOffset);
+    }
 }
\ No newline at end of file