Fix back key handling for search dialog.

Now that the search manager service handles hiding (not dismissing) and reshowing it
when the user hits back after launching a result, search manager can't cache
"mShowing".  Also noticed a few other minor problems that was hosing the handling
of pause / resume to reshow the dialog, like moving some logic to onHide instead
of onDismiss.
diff --git a/core/java/android/app/ISearchManager.aidl b/core/java/android/app/ISearchManager.aidl
index 84a6085..bd72544 100644
--- a/core/java/android/app/ISearchManager.aidl
+++ b/core/java/android/app/ISearchManager.aidl
@@ -37,4 +37,5 @@
             ISearchManagerCallback searchManagerCallback,
             int ident);
     void stopSearch();
+    boolean isVisible();
 }
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 906361c..54b6527 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -354,7 +354,6 @@
             }
             show();
         }
-
         updateUI();
         
         return true;
@@ -490,6 +489,7 @@
      */
     private void updateUI() {
         if (mSearchable != null) {
+            mDecor.setVisibility(View.VISIBLE);
             updateSearchAutoComplete();
             updateSearchButton();
             updateSearchAppIcon();
@@ -994,7 +994,7 @@
     };
 
     @Override
-    public void dismiss() {
+    public void hide() {
         if (!isShowing()) return;
 
         // We made sure the IME was displayed, so also make sure it is closed
@@ -1005,10 +1005,10 @@
             imm.hideSoftInputFromWindow(
                     getWindow().getDecorView().getWindowToken(), 0);
         }
-        
-        super.dismiss();
+
+        super.hide();
     }
-    
+
     /**
      * React to the user typing while in the suggestions list. First, check for action
      * keys. If not handled, try refocusing regular characters into the EditText. 
@@ -1234,8 +1234,8 @@
     }
 
     /**
-     * Launches an intent and dismisses the search dialog (unless the intent
-     * is one of the special intents that modifies the state of the search dialog).
+     * Launches an intent, including any special intent handling.  Doesn't dismiss the dialog
+     * since that will be handled in {@link SearchDialogWrapper#performActivityResuming}
      */
     private void launchIntent(Intent intent) {
         if (intent == null) {
@@ -1244,7 +1244,7 @@
         if (handleSpecialIntent(intent)){
             return;
         }
-        dismiss();
+        Log.d(LOG_TAG, "launching " + intent);
         getContext().startActivity(intent);
     }
     
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index b795a54..325c207 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -1534,7 +1534,6 @@
     private int mIdent;
     
     // package private since they are used by the inner class SearchManagerCallback
-    /* package */ boolean mIsShowing = false;
     /* package */ final Handler mHandler;
     /* package */ OnDismissListener mDismissListener = null;
     /* package */ OnCancelListener mCancelListener = null;
@@ -1600,12 +1599,9 @@
                             ComponentName launchActivity,
                             Bundle appSearchData,
                             boolean globalSearch) {
-        if (DBG) debug("startSearch(), mIsShowing=" + mIsShowing);
-        if (mIsShowing) return;
         if (mIdent == 0) throw new IllegalArgumentException(
                 "Called from outside of an Activity context");
         try {
-            mIsShowing = true;
             // activate the search manager and start it up!
             mService.startSearch(initialQuery, selectInitialQuery, launchActivity, appSearchData,
                     globalSearch, mSearchManagerCallback, mIdent);
@@ -1626,15 +1622,10 @@
      * @see #startSearch
      */
     public void stopSearch() {
-        if (DBG) debug("stopSearch(), mIsShowing=" + mIsShowing);
-        if (!mIsShowing) return;
+        if (DBG) debug("stopSearch()");
         try {
             mService.stopSearch();
-            // onDismiss will also clear this, but we do it here too since onDismiss() is
-            // called asynchronously.
-            mIsShowing = false;
         } catch (RemoteException ex) {
-            Log.e(TAG, "stopSearch() failed: " + ex);
         }
     }
 
@@ -1648,8 +1639,13 @@
      * @hide
      */
     public boolean isVisible() {
-        if (DBG) debug("isVisible(), mIsShowing=" + mIsShowing);
-        return mIsShowing;
+        if (DBG) debug("isVisible()");
+        try {
+            return mService.isVisible();
+        } catch (RemoteException e) {
+            Log.e(TAG, "isVisible() failed: " + e);
+            return false;
+        }
     }
 
     /**
@@ -1701,7 +1697,6 @@
         private final Runnable mFireOnDismiss = new Runnable() {
             public void run() {
                 if (DBG) debug("mFireOnDismiss");
-                mIsShowing = false;
                 if (mDismissListener != null) {
                     mDismissListener.onDismiss();
                 }
@@ -1711,7 +1706,6 @@
         private final Runnable mFireOnCancel = new Runnable() {
             public void run() {
                 if (DBG) debug("mFireOnCancel");
-                // doesn't need to clear mIsShowing since onDismiss() always gets called too
                 if (mCancelListener != null) {
                     mCancelListener.onCancel();
                 }
diff --git a/core/java/android/server/search/SearchDialogWrapper.java b/core/java/android/server/search/SearchDialogWrapper.java
index 70c7d73..d3ef5de 100644
--- a/core/java/android/server/search/SearchDialogWrapper.java
+++ b/core/java/android/server/search/SearchDialogWrapper.java
@@ -45,8 +45,6 @@
     private static final String TAG = "SearchManagerService";
     private static final boolean DBG = false;
 
-    private static final String DISABLE_SEARCH_PROPERTY = "dev.disablesearchdialog";
-
     private static final String SEARCH_UI_THREAD_NAME = "SearchDialog";
     private static final int SEARCH_UI_THREAD_PRIORITY =
         android.os.Process.THREAD_PRIORITY_DEFAULT;
@@ -88,12 +86,11 @@
     
     // Identity of currently resumed activity.
     private int mResumedIdent = 0;
-    
-    // Allows disabling of search dialog for stress testing runs
-    private final boolean mDisabledOnBoot;
 
     // True if we have registered our receivers.
     private boolean mReceiverRegistered;
+
+    private volatile boolean mVisible = false;
     
     /**
      * Creates a new search dialog wrapper and a search UI thread. The search dialog itself will
@@ -104,8 +101,6 @@
     public SearchDialogWrapper(Context context) {
         mContext = context;
 
-        mDisabledOnBoot = !TextUtils.isEmpty(SystemProperties.get(DISABLE_SEARCH_PROPERTY));
-
         // Create the search UI thread
         HandlerThread t = new HandlerThread(SEARCH_UI_THREAD_NAME, SEARCH_UI_THREAD_PRIORITY);
         t.start();
@@ -115,6 +110,10 @@
         mSearchUiThread.sendEmptyMessage(MSG_INIT);
     }
 
+    public boolean isVisible() {
+        return mVisible;
+    }
+
     /**
      * Initializes the search UI.
      * Must be called from the search UI thread.
@@ -151,8 +150,10 @@
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
             if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
-                if (DBG) debug(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
-                performStopSearch();
+                if (!"search".equals(intent.getStringExtra("reason"))) {
+                    if (DBG) debug(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+                    performStopSearch();
+                }
             } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
                 if (DBG) debug(Intent.ACTION_CONFIGURATION_CHANGED);
                 performOnConfigurationChanged();
@@ -205,7 +206,7 @@
      * Can be called from any thread.
      */
     public void activityResuming(int ident) {
-        if (DBG) debug("startSearch()");
+        if (DBG) debug("activityResuming(ident=" + ident + ")");
         Message msg = Message.obtain();
         msg.what = MSG_ACTIVITY_RESUMING;
         msg.arg1 = ident;
@@ -256,20 +257,6 @@
 
     }
 
-    void updateDialogVisibility() {
-        if (mStartedIdent != 0) {
-            // mResumedIdent == 0 means we have just booted and the user
-            // hasn't yet gone anywhere.
-            if (mResumedIdent == 0 || mStartedIdent == mResumedIdent) {
-                if (DBG) Log.v(TAG, "******************* DIALOG: show");
-                mSearchDialog.show();
-            } else {
-                if (DBG) Log.v(TAG, "******************* DIALOG: hide");
-                mSearchDialog.hide();
-            }
-        }
-    }
-    
     /**
      * Actually launches the search UI.
      * This must be called on the search UI thread.
@@ -283,19 +270,20 @@
             int ident) {
         if (DBG) debug("performStartSearch()");
 
-        if (mDisabledOnBoot) {
-            Log.d(TAG, "ignoring start search request because " + DISABLE_SEARCH_PROPERTY
-                    + " system property is set.");
-            return;
-        }
-
         registerBroadcastReceiver();
         mCallback = searchManagerCallback;
+
+        // clean up any hidden dialog that we were waiting to resume
+        if (mStartedIdent != 0) {
+            mSearchDialog.dismiss();
+        }
+
         mStartedIdent = ident;
         if (DBG) Log.v(TAG, "******************* DIALOG: start");
+
         mSearchDialog.show(initialQuery, selectInitialQuery, launchActivity, appSearchData,
                 globalSearch);
-        updateDialogVisibility();
+        mVisible = true;
     }
 
     /**
@@ -306,6 +294,7 @@
         if (DBG) debug("performStopSearch()");
         if (DBG) Log.v(TAG, "******************* DIALOG: cancel");
         mSearchDialog.cancel();
+        mVisible = false;
         mStartedIdent = 0;
     }
 
@@ -317,7 +306,21 @@
         if (DBG) debug("performResumingActivity(): mStartedIdent="
                 + mStartedIdent + ", resuming: " + ident);
         this.mResumedIdent = ident;
-        updateDialogVisibility();
+        if (mStartedIdent != 0) {
+            if (mStartedIdent == mResumedIdent) {
+                // we are resuming into the activity where we previously hid the dialog, bring it
+                // back
+                if (DBG) Log.v(TAG, "******************* DIALOG: show");
+                mSearchDialog.show();
+                mVisible = true;
+            } else {
+                // resuming into some other activity; hide ourselves in case we ever come back
+                // so we can show ourselves quickly again
+                if (DBG) Log.v(TAG, "******************* DIALOG: hide");
+                mSearchDialog.hide();
+                mVisible = false;
+            }
+        }
     }
 
     /**
@@ -333,27 +336,38 @@
      */
     public void onDismiss(DialogInterface dialog) {
         if (DBG) debug("onDismiss()");
-        if (mCallback != null) {
-            try {
-                // should be safe to do on the search UI thread, since it's a oneway interface
-                mCallback.onDismiss();
-            } catch (DeadObjectException ex) {
-                // The process that hosted the callback has died, do nothing
-            } catch (RemoteException ex) {
-                Log.e(TAG, "onDismiss() failed: " + ex);
-            }
-            // we don't need the callback anymore, release it
-            mCallback = null;
-        }
+        mStartedIdent = 0;
+        mVisible = false;
+        callOnDismiss();
+
+        // we don't need the callback anymore, release it
+        mCallback = null;
         unregisterBroadcastReceiver();
     }
 
+
     /**
      * Called by {@link SearchDialog} when the user or activity cancels search.
      * Whenever this method is called, {@link #onDismiss} is always called afterwards.
      */
     public void onCancel(DialogInterface dialog) {
         if (DBG) debug("onCancel()");
+        callOnCancel();
+    }
+
+    private void callOnDismiss() {
+        if (mCallback == null) return;
+        try {
+            // should be safe to do on the search UI thread, since it's a oneway interface
+            mCallback.onDismiss();
+        } catch (DeadObjectException ex) {
+            // The process that hosted the callback has died, do nothing
+        } catch (RemoteException ex) {
+            Log.e(TAG, "onDismiss() failed: " + ex);
+        }
+    }
+
+    private void callOnCancel() {
         if (mCallback != null) {
             try {
                 // should be safe to do on the search UI thread, since it's a oneway interface
diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java
index 7629912..fdeb8f9 100644
--- a/core/java/android/server/search/SearchManagerService.java
+++ b/core/java/android/server/search/SearchManagerService.java
@@ -238,4 +238,8 @@
         getSearchDialog().stopSearch();
     }
 
+    public boolean isVisible() {
+        return mSearchDialog != null && mSearchDialog.isVisible();
+    }
+
 }