Fix ABC CollapsibleActionViews on ICS+

- Fix ActionBarCompat CollapsibleActionView callbacks
  not being propogated on ICS+.
- Moved support version of CollapsibleActionView from
  internal to public package.
- Fix IME not showing on SearchView when expanded

Bug: 9382915

Change-Id: I17851985c014f8c56e4adaa225354a023d3177fa
Signed-off-by: Chris Banes <chrisbanes@google.com>
diff --git a/v7/appcompat/src/android/support/v7/internal/view/menu/MenuItemWrapperICS.java b/v7/appcompat/src/android/support/v7/internal/view/menu/MenuItemWrapperICS.java
index 3c653b8..8711777 100644
--- a/v7/appcompat/src/android/support/v7/internal/view/menu/MenuItemWrapperICS.java
+++ b/v7/appcompat/src/android/support/v7/internal/view/menu/MenuItemWrapperICS.java
@@ -21,10 +21,12 @@
 import android.support.v4.internal.view.SupportMenuItem;
 import android.support.v4.view.ActionProvider;
 import android.support.v4.view.MenuItemCompat;
+import android.support.v7.view.CollapsibleActionView;
 import android.view.ContextMenu;
 import android.view.MenuItem;
 import android.view.SubMenu;
 import android.view.View;
+import android.widget.FrameLayout;
 
 class MenuItemWrapperICS extends BaseMenuWrapper<android.view.MenuItem> implements SupportMenuItem {
     private final boolean mEmulateProviderVisibilityOverride;
@@ -225,19 +227,33 @@
 
     @Override
     public MenuItem setActionView(View view) {
+        if (view instanceof CollapsibleActionView) {
+            view = new CollapsibleActionViewWrapper(view);
+        }
         mWrappedObject.setActionView(view);
         return this;
     }
 
     @Override
     public MenuItem setActionView(int resId) {
+        // Make framework menu item inflate the view
         mWrappedObject.setActionView(resId);
+
+        View actionView = mWrappedObject.getActionView();
+        if (actionView instanceof CollapsibleActionView) {
+            // If the inflated Action View is support-collapsible, wrap it
+            mWrappedObject.setActionView(new CollapsibleActionViewWrapper(actionView));
+        }
         return this;
     }
 
     @Override
     public View getActionView() {
-        return mWrappedObject.getActionView();
+        View actionView = mWrappedObject.getActionView();
+        if (actionView instanceof CollapsibleActionViewWrapper) {
+            return ((CollapsibleActionViewWrapper) actionView).getWrappedView();
+        }
+        return actionView;
     }
 
     @Override
@@ -394,4 +410,29 @@
             mInner.onPrepareSubMenu(getSubMenuWrapper(subMenu));
         }
     }
+
+    static class CollapsibleActionViewWrapper extends FrameLayout
+            implements android.view.CollapsibleActionView {
+        final CollapsibleActionView mWrappedView;
+
+        CollapsibleActionViewWrapper(View actionView) {
+            super(actionView.getContext());
+            mWrappedView = (CollapsibleActionView) actionView;
+            addView(actionView);
+        }
+
+        @Override
+        public void onActionViewExpanded() {
+            mWrappedView.onActionViewExpanded();
+        }
+
+        @Override
+        public void onActionViewCollapsed() {
+            mWrappedView.onActionViewCollapsed();
+        }
+
+        View getWrappedView() {
+            return (View) mWrappedView;
+        }
+    }
 }
diff --git a/v7/appcompat/src/android/support/v7/internal/widget/ActionBarView.java b/v7/appcompat/src/android/support/v7/internal/widget/ActionBarView.java
index 040aece..ff97e78 100644
--- a/v7/appcompat/src/android/support/v7/internal/widget/ActionBarView.java
+++ b/v7/appcompat/src/android/support/v7/internal/widget/ActionBarView.java
@@ -30,7 +30,7 @@
 import android.support.v7.app.ActionBar;
 import android.support.v7.app.ActionBar.OnNavigationListener;
 import android.support.v7.appcompat.R;
-import android.support.v7.internal.view.CollapsibleActionView;
+import android.support.v7.view.CollapsibleActionView;
 import android.support.v7.internal.view.menu.ActionMenuItem;
 import android.support.v7.internal.view.menu.ActionMenuPresenter;
 import android.support.v7.internal.view.menu.ActionMenuView;
diff --git a/v7/appcompat/src/android/support/v7/internal/view/CollapsibleActionView.java b/v7/appcompat/src/android/support/v7/view/CollapsibleActionView.java
similarity index 96%
rename from v7/appcompat/src/android/support/v7/internal/view/CollapsibleActionView.java
rename to v7/appcompat/src/android/support/v7/view/CollapsibleActionView.java
index dcc7a04..063b527 100644
--- a/v7/appcompat/src/android/support/v7/internal/view/CollapsibleActionView.java
+++ b/v7/appcompat/src/android/support/v7/view/CollapsibleActionView.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.support.v7.internal.view;
+package android.support.v7.view;
 
 import android.support.v4.view.MenuItemCompat.OnActionExpandListener;
 
@@ -25,8 +25,6 @@
  *
  * <p>See {@link android.support.v4.internal.view.SupportMenuItem} for more information about action views.
  * See {@link android.app.ActionBar} for more information about the action bar.
- *
- * @hide
  */
 public interface CollapsibleActionView {
 
diff --git a/v7/appcompat/src/android/support/v7/widget/SearchView.java b/v7/appcompat/src/android/support/v7/widget/SearchView.java
index 36411ad..1feec59 100644
--- a/v7/appcompat/src/android/support/v7/widget/SearchView.java
+++ b/v7/appcompat/src/android/support/v7/widget/SearchView.java
@@ -34,11 +34,12 @@
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.ResultReceiver;
 import android.speech.RecognizerIntent;
 import android.support.v4.view.KeyEventCompat;
 import android.support.v4.widget.CursorAdapter;
 import android.support.v7.appcompat.R;
-import android.support.v7.internal.view.CollapsibleActionView;
+import android.support.v7.view.CollapsibleActionView;
 import android.text.Editable;
 import android.text.InputType;
 import android.text.Spannable;
@@ -65,7 +66,6 @@
 import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
 
-import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.WeakHashMap;
 
@@ -148,7 +148,7 @@
                     getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
 
             if (imm != null) {
-                imm.showSoftInput(SearchView.this, 0);
+                HIDDEN_METHOD_INVOKER.showSoftInputUnchecked(imm, SearchView.this, 0);
             }
         }
     };
@@ -1550,17 +1550,6 @@
     }
 
     private void forceSuggestionQuery() {
-        try {
-            Method before = AutoCompleteTextView.class.getDeclaredMethod("doBeforeTextChanged");
-            Method after = AutoCompleteTextView.class.getDeclaredMethod("doAfterTextChanged");
-            before.setAccessible(true);
-            after.setAccessible(true);
-            before.invoke(mQueryTextView);
-            after.invoke(mQueryTextView);
-        } catch (Exception e) {
-            // Oh well...
-        }
-
         HIDDEN_METHOD_INVOKER.doBeforeTextChanged(mQueryTextView);
         HIDDEN_METHOD_INVOKER.doAfterTextChanged(mQueryTextView);
     }
@@ -1710,6 +1699,7 @@
     private static class AutoCompleteTextViewReflector {
         private Method doBeforeTextChanged, doAfterTextChanged;
         private Method ensureImeVisible;
+        private Method showSoftInputUnchecked;
 
         AutoCompleteTextViewReflector() {
             try {
@@ -1728,19 +1718,25 @@
             }
             try {
                 ensureImeVisible = AutoCompleteTextView.class
-                        .getMethod("ensureImeVisible", Boolean.TYPE);
+                        .getMethod("ensureImeVisible", boolean.class);
                 ensureImeVisible.setAccessible(true);
             } catch (NoSuchMethodException e) {
                 // Ah well.
             }
+            try {
+                showSoftInputUnchecked = InputMethodManager.class.getMethod(
+                        "showSoftInputUnchecked", int.class, ResultReceiver.class);
+                showSoftInputUnchecked.setAccessible(true);
+            } catch (NoSuchMethodException e) {
+                // Ah well.
+            }
         }
 
         void doBeforeTextChanged(AutoCompleteTextView view) {
             if (doBeforeTextChanged != null) {
                 try {
                     doBeforeTextChanged.invoke(view);
-                } catch (IllegalAccessException e) {
-                } catch (InvocationTargetException e) {
+                } catch (Exception e) {
                 }
             }
         }
@@ -1749,8 +1745,7 @@
             if (doAfterTextChanged != null) {
                 try {
                     doAfterTextChanged.invoke(view);
-                } catch (IllegalAccessException e) {
-                } catch (InvocationTargetException e) {
+                } catch (Exception e) {
                 }
             }
         }
@@ -1759,10 +1754,22 @@
             if (ensureImeVisible != null) {
                 try {
                     ensureImeVisible.invoke(view, visible);
-                } catch (IllegalAccessException e) {
-                } catch (InvocationTargetException e) {
+                } catch (Exception e) {
                 }
             }
         }
+
+        void showSoftInputUnchecked(InputMethodManager imm, View view, int flags) {
+            if (showSoftInputUnchecked != null) {
+                try {
+                    showSoftInputUnchecked.invoke(imm, flags, null);
+                    return;
+                } catch (Exception e) {
+                }
+            }
+
+            // Hidden method failed, call public version instead
+            imm.showSoftInput(view, flags);
+        }
     }
 }
\ No newline at end of file