Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ea52d29b authored by Karl Rosaen's avatar Karl Rosaen
Browse files

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.
parent 5f6133a1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -37,4 +37,5 @@ interface ISearchManager {
            ISearchManagerCallback searchManagerCallback,
            int ident);
    void stopSearch();
    boolean isVisible();
}
+8 −8
Original line number Diff line number Diff line
@@ -354,7 +354,6 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
            }
            show();
        }

        updateUI();
        
        return true;
@@ -490,6 +489,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
     */
    private void updateUI() {
        if (mSearchable != null) {
            mDecor.setVisibility(View.VISIBLE);
            updateSearchAutoComplete();
            updateSearchButton();
            updateSearchAppIcon();
@@ -994,7 +994,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
    };

    @Override
    public void dismiss() {
    public void hide() {
        if (!isShowing()) return;

        // We made sure the IME was displayed, so also make sure it is closed
@@ -1006,7 +1006,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
                    getWindow().getDecorView().getWindowToken(), 0);
        }

        super.dismiss();
        super.hide();
    }

    /**
@@ -1234,8 +1234,8 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
    }

    /**
     * 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 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
        if (handleSpecialIntent(intent)){
            return;
        }
        dismiss();
        Log.d(LOG_TAG, "launching " + intent);
        getContext().startActivity(intent);
    }
    
+8 −14
Original line number Diff line number Diff line
@@ -1534,7 +1534,6 @@ public class SearchManager
    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 @@ public class SearchManager
                            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 @@ public class SearchManager
     * @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 @@ public class SearchManager
     * @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 @@ public class SearchManager
        private final Runnable mFireOnDismiss = new Runnable() {
            public void run() {
                if (DBG) debug("mFireOnDismiss");
                mIsShowing = false;
                if (mDismissListener != null) {
                    mDismissListener.onDismiss();
                }
@@ -1711,7 +1706,6 @@ public class SearchManager
        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();
                }
+58 −44
Original line number Diff line number Diff line
@@ -45,8 +45,6 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
    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;
@@ -89,12 +87,11 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
    // 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
     * be created some asynchronously on the search UI thread.
@@ -104,8 +101,6 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
    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 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
        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 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
                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 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
     * 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 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {

    }

    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 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
            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 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
        if (DBG) debug("performStopSearch()");
        if (DBG) Log.v(TAG, "******************* DIALOG: cancel");
        mSearchDialog.cancel();
        mVisible = false;
        mStartedIdent = 0;
    }

@@ -317,7 +306,21 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
        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 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
     */
    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);
            }
        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
+4 −0
Original line number Diff line number Diff line
@@ -238,4 +238,8 @@ public class SearchManagerService extends ISearchManager.Stub {
        getSearchDialog().stopSearch();
    }

    public boolean isVisible() {
        return mSearchDialog != null && mSearchDialog.isVisible();
    }

}