SearchManagerService.java revision 8d17f3f24bbda9a9cd7ea08c5925508dc2c011be
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.server.search;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.ISearchManager;
208d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringertimport android.app.ISearchManagerCallback;
218d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringertimport android.app.SearchDialog;
228d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringertimport android.app.SearchManager;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.BroadcastReceiver;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ComponentName;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
268d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringertimport android.content.DialogInterface;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter;
298d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringertimport android.content.res.Configuration;
308d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringertimport android.os.Bundle;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
32f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampathimport android.os.RemoteException;
338d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringertimport android.util.Log;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
356d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringertimport java.util.List;
368d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringertimport java.util.concurrent.Callable;
378d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringertimport java.util.concurrent.ExecutionException;
388d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringertimport java.util.concurrent.FutureTask;
396d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is a simplified version of the Search Manager service.  It no longer handles
42f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * presentation (UI).  Its function is to maintain the map & list of "searchable"
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * items, which provides a mapping from individual activities (where a user might have
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * invoked search) to specific searchable activities (where the search will be dispatched).
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class SearchManagerService extends ISearchManager.Stub
478d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // general debugging support
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "SearchManagerService";
518d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    private static final boolean DBG = false;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // class maintenance and general shared data
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Context mContext;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Handler mHandler;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mSearchablesDirty;
578d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    private final Searchables mSearchables;
588d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
598d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    final SearchDialog mSearchDialog;
608d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    ISearchManagerCallback mCallback = null;
61f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
63875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * Initializes the Search Manager service in the provided system context.
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Only one instance of this object should be created!
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param context to use for accessing DB, window manager, etc.
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
68f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath    public SearchManagerService(Context context)  {
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHandler = new Handler();
71875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        mSearchablesDirty = true;
72875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        mSearchables = new Searchables(context);
738d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        mSearchDialog = new SearchDialog(context);
748d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        mSearchDialog.setOnCancelListener(this);
758d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        mSearchDialog.setOnDismissListener(this);
76f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Setup the infrastructure for updating and maintaining the list
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // of searchable activities.
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IntentFilter filter = new IntentFilter();
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        filter.addAction(Intent.ACTION_PACKAGE_ADDED);
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        filter.addDataScheme("package");
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
85f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // After startup settles down, preload the searchables list,
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // which will reduce the delay when the search UI is invoked.
88a48a5af931f2fb43c948416180b85dfe9ecdc9a1Bjorn Bringert        mHandler.post(mRunUpdateSearchable);
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
90f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Listens for intent broadcasts.
93f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     *
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The primary purpose here is to refresh the "searchables" list
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * if packages are added/removed.
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onReceive(Context context, Intent intent) {
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String action = intent.getAction();
101f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // First, test for intents that matter at any time
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (action.equals(Intent.ACTION_PACKAGE_ADDED) ||
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                action.equals(Intent.ACTION_PACKAGE_REMOVED) ||
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                action.equals(Intent.ACTION_PACKAGE_CHANGED)) {
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mSearchablesDirty = true;
107a48a5af931f2fb43c948416180b85dfe9ecdc9a1Bjorn Bringert                mHandler.post(mRunUpdateSearchable);
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
112f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This runnable (for the main handler / UI thread) will update the searchables list.
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Runnable mRunUpdateSearchable = new Runnable() {
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void run() {
118a48a5af931f2fb43c948416180b85dfe9ecdc9a1Bjorn Bringert            updateSearchablesIfDirty();
119f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath        }
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
123875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * Updates the list of searchables, either at startup or in response to
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a package add/remove broadcast message.
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updateSearchables() {
1278d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        if (DBG) debug("updateSearchables()");
128875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        mSearchables.buildSearchableList();
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSearchablesDirty = false;
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
133a48a5af931f2fb43c948416180b85dfe9ecdc9a1Bjorn Bringert     * Updates the list of searchables if needed.
134a48a5af931f2fb43c948416180b85dfe9ecdc9a1Bjorn Bringert     */
135a48a5af931f2fb43c948416180b85dfe9ecdc9a1Bjorn Bringert    private void updateSearchablesIfDirty() {
136a48a5af931f2fb43c948416180b85dfe9ecdc9a1Bjorn Bringert        if (mSearchablesDirty) {
137a48a5af931f2fb43c948416180b85dfe9ecdc9a1Bjorn Bringert            updateSearchables();
138a48a5af931f2fb43c948416180b85dfe9ecdc9a1Bjorn Bringert        }
139a48a5af931f2fb43c948416180b85dfe9ecdc9a1Bjorn Bringert    }
140a48a5af931f2fb43c948416180b85dfe9ecdc9a1Bjorn Bringert
141a48a5af931f2fb43c948416180b85dfe9ecdc9a1Bjorn Bringert    /**
142875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * Returns the SearchableInfo for a given activity
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param launchActivity The activity from which we're launching this search.
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param globalSearch If false, this will only launch the search that has been specifically
146f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     * defined by the application (which is usually defined as a local search).  If no default
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * search is defined in the current application or activity, no search will be launched.
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If true, this will always launch a platform-global (e.g. web-based) search instead.
149875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * @return Returns a SearchableInfo record describing the parameters of the search,
150875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * or null if no searchable metadata was available.
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SearchableInfo getSearchableInfo(ComponentName launchActivity, boolean globalSearch) {
153a48a5af931f2fb43c948416180b85dfe9ecdc9a1Bjorn Bringert        updateSearchablesIfDirty();
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SearchableInfo si = null;
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (globalSearch) {
156875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen            si = mSearchables.getDefaultSearchable();
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1588d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            if (launchActivity == null) {
1598d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                Log.e(TAG, "getSearchableInfo(), activity == null");
1608d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                return null;
1618d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            }
162875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen            si = mSearchables.getSearchableInfo(launchActivity);
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return si;
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
167f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath
1686d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert    /**
1696d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert     * Returns a list of the searchable activities that can be included in global search.
1706d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert     */
1716d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert    public List<SearchableInfo> getSearchablesInGlobalSearch() {
172a48a5af931f2fb43c948416180b85dfe9ecdc9a1Bjorn Bringert        updateSearchablesIfDirty();
1736d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert        return mSearchables.getSearchablesInGlobalSearchList();
1746d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert    }
1758d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    /**
1768d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     * Launches the search UI on the main thread of the service.
1778d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     *
1788d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     * @see SearchManager#startSearch(String, boolean, ComponentName, Bundle, boolean)
1798d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     */
1808d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    public void startSearch(final String initialQuery,
1818d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            final boolean selectInitialQuery,
1828d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            final ComponentName launchActivity,
1838d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            final Bundle appSearchData,
1848d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            final boolean globalSearch,
1858d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            final ISearchManagerCallback searchManagerCallback) {
1868d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        if (DBG) debug("startSearch()");
1878d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        Runnable task = new Runnable() {
1888d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            public void run() {
1898d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                performStartSearch(initialQuery,
1908d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                        selectInitialQuery,
1918d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                        launchActivity,
1928d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                        appSearchData,
1938d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                        globalSearch,
1948d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                        searchManagerCallback);
1958d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            }
1968d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        };
1978d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        mHandler.post(task);
1988d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    }
1998d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
2008d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    /**
2018d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     * Actually launches the search. This must be called on the service UI thread.
2028d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     */
2038d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    /*package*/ void performStartSearch(String initialQuery,
2048d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            boolean selectInitialQuery,
2058d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            ComponentName launchActivity,
2068d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            Bundle appSearchData,
2078d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            boolean globalSearch,
2088d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            ISearchManagerCallback searchManagerCallback) {
2098d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        if (DBG) debug("performStartSearch()");
2108d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        mSearchDialog.show(initialQuery, selectInitialQuery, launchActivity, appSearchData,
2118d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                globalSearch);
2128d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        if (searchManagerCallback != null) {
2138d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            mCallback = searchManagerCallback;
2148d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        }
2158d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    }
2168d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
2178d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    /**
2188d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     * Cancels the search dialog. Can be called from any thread.
2198d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     */
2208d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    public void stopSearch() {
2218d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        if (DBG) debug("stopSearch()");
2228d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        mHandler.post(new Runnable() {
2238d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            public void run() {
2248d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                performStopSearch();
2258d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            }
2268d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        });
2278d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    }
2288d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
2298d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    /**
2308d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     * Cancels the search dialog. Must be called from the service UI thread.
2318d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     */
2328d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    /*package*/ void performStopSearch() {
2338d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        if (DBG) debug("performStopSearch()");
2348d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        mSearchDialog.cancel();
2358d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    }
2368d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
2378d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    /**
2388d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     * Determines if the Search UI is currently displayed.
2398d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     *
2408d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     * @see SearchManager#isVisible()
2418d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     */
2428d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    public boolean isVisible() {
2438d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        return postAndWait(mIsShowing, false, "isShowing()");
2448d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    }
2458d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
2468d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    private final Callable<Boolean> mIsShowing = new Callable<Boolean>() {
2478d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        public Boolean call() {
2488d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            return mSearchDialog.isShowing();
2498d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        }
2508d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    };
2518d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
2528d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    public Bundle onSaveInstanceState() {
2538d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        return postAndWait(mOnSaveInstanceState, null, "onSaveInstanceState()");
2548d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    }
2558d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
2568d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    private final Callable<Bundle> mOnSaveInstanceState = new Callable<Bundle>() {
2578d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        public Bundle call() {
2588d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            if (mSearchDialog.isShowing()) {
2598d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                return mSearchDialog.onSaveInstanceState();
2608d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            } else {
2618d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                return null;
2628d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            }
2638d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        }
2648d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    };
2658d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
2668d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    public void onRestoreInstanceState(final Bundle searchDialogState) {
2678d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        if (searchDialogState != null) {
2688d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            mHandler.post(new Runnable() {
2698d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                public void run() {
2708d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                    mSearchDialog.onRestoreInstanceState(searchDialogState);
2718d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                }
2728d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            });
2738d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        }
2748d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    }
2758d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
2768d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    public void onConfigurationChanged(final Configuration newConfig) {
2778d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        mHandler.post(new Runnable() {
2788d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            public void run() {
2798d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                if (mSearchDialog.isShowing()) {
2808d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                    mSearchDialog.onConfigurationChanged(newConfig);
2818d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                }
2828d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            }
2838d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        });
2848d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    }
2858d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
2868d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    /**
2878d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     * Called by {@link SearchDialog} when it goes away.
2888d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     */
2898d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    public void onDismiss(DialogInterface dialog) {
2908d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        if (DBG) debug("onDismiss()");
2918d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        if (mCallback != null) {
2928d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            try {
2938d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                mCallback.onDismiss();
2948d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            } catch (RemoteException ex) {
2958d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                Log.e(TAG, "onDismiss() failed: " + ex);
2968d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            }
2978d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        }
2988d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    }
2998d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
3008d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    /**
3018d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     * Called by {@link SearchDialog} when the user or activity cancels search.
3028d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     * When this is called, {@link #onDismiss} is called too.
3038d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     */
3048d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    public void onCancel(DialogInterface dialog) {
3058d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        if (DBG) debug("onCancel()");
3068d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        if (mCallback != null) {
3078d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            try {
3088d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                mCallback.onCancel();
3098d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            } catch (RemoteException ex) {
3108d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                Log.e(TAG, "onCancel() failed: " + ex);
3118d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            }
3128d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        }
3138d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    }
314875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen
315f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath    /**
316f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     * Returns a list of the searchable activities that handle web searches.
317f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     */
318f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath    public List<SearchableInfo> getSearchablesForWebSearch() {
319f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath        updateSearchablesIfDirty();
320f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath        return mSearchables.getSearchablesForWebSearchList();
321f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath    }
322f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath
323f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath    /**
324f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     * Returns the default searchable activity for web searches.
325f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     */
326f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath    public SearchableInfo getDefaultSearchableForWebSearch() {
327f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath        updateSearchablesIfDirty();
328f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath        return mSearchables.getDefaultSearchableForWebSearch();
329f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath    }
330f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath
331f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath    /**
332f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     * Sets the default searchable activity for web searches.
333f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     */
334f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath    public void setDefaultWebSearch(ComponentName component) {
335f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath        mSearchables.setDefaultWebSearch(component);
336f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath    }
3378d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
3388d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    /**
3398d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     * Runs an operation on the handler for the service, blocks until it returns,
3408d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     * and returns the value returned by the operation.
3418d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     *
3428d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     * @param <V> Return value type.
3438d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     * @param callable Operation to run.
3448d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     * @param errorResult Value to return if the operations throws an exception.
3458d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     * @param name Operation name to include in error log messages.
3468d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     * @return The value returned by the operation.
3478d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     */
3488d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    private <V> V postAndWait(Callable<V> callable, V errorResult, String name) {
3498d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        FutureTask<V> task = new FutureTask<V>(callable);
3508d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        mHandler.post(task);
3518d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        try {
3528d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            return task.get();
3538d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        } catch (InterruptedException ex) {
3548d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            Log.e(TAG, "Error calling " + name + ": " + ex);
3558d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            return errorResult;
3568d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        } catch (ExecutionException ex) {
3578d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            Log.e(TAG, "Error calling " + name + ": " + ex);
3588d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            return errorResult;
3598d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        }
3608d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    }
3618d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
3628d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    private static void debug(String msg) {
3638d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        Thread thread = Thread.currentThread();
3648d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        Log.d(TAG, msg + " (" + thread.getName() + "-" + thread.getId() + ")");
3658d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    }
3668d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
368