diff options
-rw-r--r-- | api/current.xml | 36 | ||||
-rw-r--r-- | core/java/android/app/Activity.java | 21 | ||||
-rw-r--r-- | core/java/android/app/ISearchManager.aidl | 11 | ||||
-rw-r--r-- | core/java/android/app/SearchDialog.java | 2 | ||||
-rw-r--r-- | core/java/android/app/SearchManager.java | 62 | ||||
-rw-r--r-- | core/java/android/server/search/SearchDialogWrapper.java | 17 | ||||
-rw-r--r-- | core/java/android/server/search/SearchManagerService.java | 26 |
7 files changed, 166 insertions, 9 deletions
diff --git a/api/current.xml b/api/current.xml index ca8d81f..b704eb3 100644 --- a/api/current.xml +++ b/api/current.xml @@ -16991,6 +16991,23 @@ <parameter name="get" type="boolean"> </parameter> </method> +<method name="triggerSearch" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="query" type="java.lang.String"> +</parameter> +<parameter name="appSearchData" type="android.os.Bundle"> +</parameter> +<parameter name="globalSearch" type="boolean"> +</parameter> +</method> <method name="unregisterForContextMenu" return="void" abstract="false" @@ -23213,6 +23230,25 @@ visibility="public" > </method> +<method name="triggerSearch" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="query" type="java.lang.String"> +</parameter> +<parameter name="launchActivity" type="android.content.ComponentName"> +</parameter> +<parameter name="appSearchData" type="android.os.Bundle"> +</parameter> +<parameter name="globalSearch" type="boolean"> +</parameter> +</method> <field name="ACTION_KEY" type="java.lang.String" transient="false" diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 2f79fe9..c05e042 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -2536,6 +2536,25 @@ public class Activity extends ContextThemeWrapper } /** + * Similar to {@link #startSearch}, but actually fires off the search query after invoking + * the search dialog. Made available for testing purposes. + * + * @param query The query to trigger. If empty, the request will be ignored. + * @param appSearchData An application can insert application-specific + * context here, in order to improve quality or specificity of its own + * searches. This data will be returned with SEARCH intent(s). Null if + * no extra data is required. + * @param globalSearch If false, this will only launch the search that has been specifically + * defined by the application (which is usually defined as a local search). If no default + * search is defined in the current application or activity, no search will be launched. + * If true, this will always launch a platform-global (e.g. web-based) search instead. + */ + public void triggerSearch(String query, Bundle appSearchData, boolean globalSearch) { + ensureSearchManager(); + mSearchManager.triggerSearch(query, getComponentName(), appSearchData, globalSearch); + } + + /** * Request that key events come to this activity. Use this if your * activity has no views with focus, but the activity still wants * a chance to process key events. @@ -3256,7 +3275,7 @@ public class Activity extends ContextThemeWrapper throw new IllegalArgumentException("no ident"); } } - mSearchManager.setIdent(ident); + mSearchManager.setIdent(ident, getComponentName()); } @Override diff --git a/core/java/android/app/ISearchManager.aidl b/core/java/android/app/ISearchManager.aidl index bd72544..ed5dd3d 100644 --- a/core/java/android/app/ISearchManager.aidl +++ b/core/java/android/app/ISearchManager.aidl @@ -36,6 +36,17 @@ interface ISearchManager { boolean globalSearch, ISearchManagerCallback searchManagerCallback, int ident); + + void triggerSearch(in String query, + in ComponentName launchActivity, + in Bundle appSearchData, + ISearchManagerCallback searchManagerCallback, + boolean globalSearch, + int ident); + void stopSearch(); + + boolean isVisible(); + } diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java index b75bec2..8a9cca7 100644 --- a/core/java/android/app/SearchDialog.java +++ b/core/java/android/app/SearchDialog.java @@ -1120,7 +1120,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS /** * Launch a search for the text in the query text field. */ - protected void launchQuerySearch() { + public void launchQuerySearch() { launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null); } diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java index 97d46f8..15a277c 100644 --- a/core/java/android/app/SearchManager.java +++ b/core/java/android/app/SearchManager.java @@ -29,6 +29,7 @@ import android.os.ServiceManager; import android.server.search.SearchableInfo; import android.util.Log; import android.view.KeyEvent; +import android.text.TextUtils; import java.util.List; @@ -1622,7 +1623,17 @@ public class SearchManager private final Context mContext; + /** + * compact representation of the activity associated with this search manager so + * we can say who we are when starting search. the search managerservice, in turn, + * uses this to properly handle the back stack. + */ private int mIdent; + + /** + * The package associated with this seach manager. + */ + private String mAssociatedPackage; // package private since they are used by the inner class SearchManagerCallback /* package */ final Handler mHandler; @@ -1642,11 +1653,15 @@ public class SearchManager return mIdent != 0; } - /*package*/ void setIdent(int ident) { + /*package*/ void setIdent(int ident, ComponentName component) { if (mIdent != 0) { throw new IllegalStateException("mIdent already set"); } + if (component == null) { + throw new IllegalArgumentException("component must be non-null"); + } mIdent = ident; + mAssociatedPackage = component.getPackageName(); } /** @@ -1696,12 +1711,55 @@ public class SearchManager boolean globalSearch) { if (mIdent == 0) throw new IllegalArgumentException( "Called from outside of an Activity context"); + if (!globalSearch && !mAssociatedPackage.equals(launchActivity.getPackageName())) { + Log.w(TAG, "invoking app search on a different package " + + "not associated with this search manager"); + } try { // activate the search manager and start it up! mService.startSearch(initialQuery, selectInitialQuery, launchActivity, appSearchData, globalSearch, mSearchManagerCallback, mIdent); } catch (RemoteException ex) { - Log.e(TAG, "startSearch() failed: " + ex); + Log.e(TAG, "startSearch() failed.", ex); + } + } + + /** + * Similar to {@link #startSearch} but actually fires off the search query after invoking + * the search dialog. Made available for testing purposes. + * + * @param query The query to trigger. If empty, request will be ignored. + * @param launchActivity The ComponentName of the activity that has launched this search. + * @param appSearchData An application can insert application-specific + * context here, in order to improve quality or specificity of its own + * searches. This data will be returned with SEARCH intent(s). Null if + * no extra data is required. + * @param globalSearch If false, this will only launch the search that has been specifically + * defined by the application (which is usually defined as a local search). If no default + * search is defined in the current application or activity, no search will be launched. + * If true, this will always launch a platform-global (e.g. web-based) search instead. + * + * @see #startSearch + */ + public void triggerSearch(String query, + ComponentName launchActivity, + Bundle appSearchData, + boolean globalSearch) { + if (mIdent == 0) throw new IllegalArgumentException( + "Called from outside of an Activity context"); + if (!mAssociatedPackage.equals(launchActivity.getPackageName())) { + throw new IllegalArgumentException("invoking app search on a different package " + + "not associated with this search manager"); + } + if (query == null || TextUtils.getTrimmedLength(query) == 0) { + Log.w(TAG, "triggerSearch called with empty query, ignoring."); + return; + } + try { + mService.triggerSearch(query, launchActivity, appSearchData, mSearchManagerCallback, + globalSearch, mIdent); + } catch (RemoteException ex) { + Log.e(TAG, "triggerSearch() failed.", ex); } } diff --git a/core/java/android/server/search/SearchDialogWrapper.java b/core/java/android/server/search/SearchDialogWrapper.java index 49718cb..9ee64af 100644 --- a/core/java/android/server/search/SearchDialogWrapper.java +++ b/core/java/android/server/search/SearchDialogWrapper.java @@ -58,6 +58,7 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener { // data[KEY_INITIAL_QUERY]: initial query // data[KEY_LAUNCH_ACTIVITY]: launch activity // data[KEY_APP_SEARCH_DATA]: app search data + // data[KEY_TRIGGER]: 0 = false, 1 = true private static final int MSG_START_SEARCH = 1; // Takes no arguments private static final int MSG_STOP_SEARCH = 2; @@ -69,7 +70,8 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener { private static final String KEY_INITIAL_QUERY = "q"; private static final String KEY_LAUNCH_ACTIVITY = "a"; private static final String KEY_APP_SEARCH_DATA = "d"; - private static final String KEY_IDENT= "i"; + private static final String KEY_IDENT = "i"; + private static final String KEY_TRIGGER = "t"; // Context used for getting search UI resources private final Context mContext; @@ -173,7 +175,8 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener { final Bundle appSearchData, final boolean globalSearch, final ISearchManagerCallback searchManagerCallback, - int ident) { + int ident, + boolean trigger) { if (DBG) debug("startSearch()"); Message msg = Message.obtain(); msg.what = MSG_START_SEARCH; @@ -185,6 +188,7 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener { msgData.putParcelable(KEY_LAUNCH_ACTIVITY, launchActivity); msgData.putBundle(KEY_APP_SEARCH_DATA, appSearchData); msgData.putInt(KEY_IDENT, ident); + msgData.putInt(KEY_TRIGGER, trigger ? 1 : 0); mSearchUiThread.sendMessage(msg); // be a little more eager in setting this so isVisible will return the correct value if // called immediately after startSearch @@ -268,8 +272,9 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener { boolean globalSearch = msg.arg2 != 0; ISearchManagerCallback searchManagerCallback = (ISearchManagerCallback) msg.obj; int ident = msgData.getInt(KEY_IDENT); + boolean trigger = msgData.getInt(KEY_TRIGGER) != 0; performStartSearch(initialQuery, selectInitialQuery, launchActivity, - appSearchData, globalSearch, searchManagerCallback, ident); + appSearchData, globalSearch, searchManagerCallback, ident, trigger); } } @@ -284,7 +289,8 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener { Bundle appSearchData, boolean globalSearch, ISearchManagerCallback searchManagerCallback, - int ident) { + int ident, + boolean trigger) { if (DBG) debug("performStartSearch()"); registerBroadcastReceiver(); @@ -301,6 +307,9 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener { mSearchDialog.show(initialQuery, selectInitialQuery, launchActivity, appSearchData, globalSearch); mVisible = true; + if (trigger) { + mSearchDialog.launchQuerySearch(); + } } /** diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java index afed4a4..5e0b3d2 100644 --- a/core/java/android/server/search/SearchManagerService.java +++ b/core/java/android/server/search/SearchManagerService.java @@ -233,7 +233,31 @@ public class SearchManagerService extends ISearchManager.Stub { appSearchData, globalSearch, searchManagerCallback, - ident); + ident, + false); // don't trigger + } + + /** + * Launches the search UI and triggers the search, as if the user had clicked on the + * search button within the dialog. + * + * @see SearchManager#triggerSearch(String, android.content.ComponentName, android.os.Bundle) + */ + public void triggerSearch(String query, + ComponentName launchActivity, + Bundle appSearchData, + ISearchManagerCallback searchManagerCallback, + boolean globalSearch, + int ident) { + getSearchDialog().startSearch( + query, + false, + launchActivity, + appSearchData, + globalSearch, + searchManagerCallback, + ident, + true); // triger search after launching } /** |