From 479ae0a28099eb77299fe0f44d4dfabce3115fb6 Mon Sep 17 00:00:00 2001 From: Amith Yamasani Date: Thu, 4 Feb 2010 14:52:32 -0800 Subject: [PATCH] Cleanup of global search references in SearchDialog and SearchManager. --- core/java/android/app/Dialog.java | 5 - core/java/android/app/SearchDialog.java | 566 ++---------------- core/java/android/app/SearchManager.java | 235 +------- core/java/android/app/SuggestionsAdapter.java | 154 +---- .../src/android/app/SearchManagerTest.java | 17 - 5 files changed, 78 insertions(+), 899 deletions(-) diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java index ed38240b92b31..4598bb562ff6b 100644 --- a/core/java/android/app/Dialog.java +++ b/core/java/android/app/Dialog.java @@ -822,11 +822,6 @@ public class Dialog implements DialogInterface, Window.Callback, final SearchManager searchManager = (SearchManager) mContext .getSystemService(Context.SEARCH_SERVICE); - // can't start search without an associated activity (e.g a system dialog) - if (!searchManager.hasIdent()) { - return false; - } - // associate search with owner activity if possible (otherwise it will default to // global search). final ComponentName appName = getAssociatedActivity(); diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java index e4c1ba6e851f1..581b436fb4076 100644 --- a/core/java/android/app/SearchDialog.java +++ b/core/java/android/app/SearchDialog.java @@ -16,6 +16,9 @@ package android.app; +import com.android.common.Patterns; +import com.android.common.speech.Recognition; + import static android.app.SuggestionsAdapter.getColumnString; import android.content.ActivityNotFoundException; @@ -67,9 +70,6 @@ import android.widget.TextView; import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemSelectedListener; -import com.android.common.Patterns; -import com.android.common.speech.Recognition; - import java.util.ArrayList; import java.util.WeakHashMap; import java.util.concurrent.atomic.AtomicLong; @@ -89,10 +89,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS private static final String INSTANCE_KEY_COMPONENT = "comp"; private static final String INSTANCE_KEY_APPDATA = "data"; - private static final String INSTANCE_KEY_GLOBALSEARCH = "glob"; - private static final String INSTANCE_KEY_STORED_COMPONENT = "sComp"; private static final String INSTANCE_KEY_STORED_APPDATA = "sData"; - private static final String INSTANCE_KEY_PREVIOUS_COMPONENTS = "sPrev"; private static final String INSTANCE_KEY_USER_QUERY = "uQry"; // The string used for privateImeOptions to identify to the IME that it should not show @@ -115,19 +112,8 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS private SearchableInfo mSearchable; private ComponentName mLaunchComponent; private Bundle mAppSearchData; - private boolean mGlobalSearchMode; private Context mActivityContext; private SearchManager mSearchManager; - - // Values we store to allow user to toggle between in-app search and global search. - private ComponentName mStoredComponentName; - private Bundle mStoredAppSearchData; - - // stack of previous searchables, to support the BACK key after - // SearchManager.INTENT_ACTION_CHANGE_SEARCH_SOURCE. - // The top of the stack (= previous searchable) is the last element of the list, - // since adding and removing is efficient at the end of an ArrayList. - private ArrayList mPreviousComponents; // For voice searching private final Intent mVoiceWebSearchIntent; @@ -158,7 +144,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS * @param context Application Context we can use for system acess */ public SearchDialog(Context context, SearchManager searchManager) { - super(context, com.android.internal.R.style.Theme_GlobalSearchBar); + super(context, com.android.internal.R.style.Theme_SearchBar); // Save voice intent for later queries/launching mVoiceWebSearchIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH); @@ -241,14 +227,8 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS * @return true if search dialog launched, false if not */ public boolean show(String initialQuery, boolean selectInitialQuery, - ComponentName componentName, Bundle appSearchData, boolean globalSearch) { - - // Reset any stored values from last time dialog was shown. - mStoredComponentName = null; - mStoredAppSearchData = null; - - boolean success = doShow(initialQuery, selectInitialQuery, componentName, appSearchData, - globalSearch); + ComponentName componentName, Bundle appSearchData) { + boolean success = doShow(initialQuery, selectInitialQuery, componentName, appSearchData); if (success) { // Display the drop down as soon as possible instead of waiting for the rest of the // pending UI stuff to get done, so that things appear faster to the user. @@ -257,67 +237,16 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS return success; } - private boolean isInRealAppSearch() { - return !mGlobalSearchMode - && (mPreviousComponents == null || mPreviousComponents.isEmpty()); - } - /** - * Called in response to a press of the hard search button in - * {@link #onKeyDown(int, KeyEvent)}, this method toggles between in-app - * search and global search when relevant. - * - * If pressed within an in-app search context, this switches the search dialog out to - * global search. If pressed within a global search context that was originally an in-app - * search context, this switches back to the in-app search context. If pressed within a - * global search context that has no original in-app search context (e.g., global search - * from Home), this does nothing. - * - * @return false if we wanted to toggle context but could not do so successfully, true - * in all other cases - */ - private boolean toggleGlobalSearch() { - String currentSearchText = mSearchAutoComplete.getText().toString(); - if (!mGlobalSearchMode) { - mStoredComponentName = mLaunchComponent; - mStoredAppSearchData = mAppSearchData; - - // If this is the browser, we have a special case to not show the icon to the left - // of the text field, for extra space for url entry (this should be reconciled in - // Eclair). So special case a second tap of the search button to remove any - // already-entered text so that we can be sure to show the "Quick Search Box" hint - // text to still make it clear to the user that we've jumped out to global search. - // - // TODO: When the browser icon issue is reconciled in Eclair, remove this special case. - if (isBrowserSearch()) currentSearchText = ""; - - cancel(); - mSearchManager.startGlobalSearch(currentSearchText, false, mStoredAppSearchData); - return true; - } else { - if (mStoredComponentName != null) { - // This means we should toggle *back* to an in-app search context from - // global search. - return doShow(currentSearchText, false, mStoredComponentName, - mStoredAppSearchData, false); - } else { - return true; - } - } - } - - /** - * Does the rest of the work required to show the search dialog. Called by both - * {@link #show(String, boolean, ComponentName, Bundle, boolean)} and - * {@link #toggleGlobalSearch()}. - * + * Does the rest of the work required to show the search dialog. Called by + * {@link #show(String, boolean, ComponentName, Bundle)} and + * * @return true if search dialog showed, false if not */ private boolean doShow(String initialQuery, boolean selectInitialQuery, - ComponentName componentName, Bundle appSearchData, - boolean globalSearch) { + ComponentName componentName, Bundle appSearchData) { // set up the searchable and show the dialog - if (!show(componentName, appSearchData, globalSearch)) { + if (!show(componentName, appSearchData)) { return false; } @@ -335,38 +264,24 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS * * @return true if search dialog launched */ - private boolean show(ComponentName componentName, Bundle appSearchData, - boolean globalSearch) { + private boolean show(ComponentName componentName, Bundle appSearchData) { if (DBG) { Log.d(LOG_TAG, "show(" + componentName + ", " - + appSearchData + ", " + globalSearch + ")"); + + appSearchData + ")"); } SearchManager searchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE); - // Try to get the searchable info for the provided component (or for global search, - // if globalSearch == true). - mSearchable = searchManager.getSearchableInfo(componentName, globalSearch); - - // If we got back nothing, and it wasn't a request for global search, then try again - // for global search, as we'll try to launch that in lieu of any component-specific search. - if (!globalSearch && mSearchable == null) { - globalSearch = true; - mSearchable = searchManager.getSearchableInfo(componentName, globalSearch); - } + // Try to get the searchable info for the provided component. + mSearchable = searchManager.getSearchableInfo(componentName, false); - // If there's not even a searchable info available for global search, then really give up. if (mSearchable == null) { - Log.w(LOG_TAG, "No global search provider."); return false; } mLaunchComponent = componentName; mAppSearchData = appSearchData; - // Using globalSearch here is just an optimization, just calling - // isDefaultSearchable() should always give the same result. - mGlobalSearchMode = globalSearch || searchManager.isDefaultSearchable(mSearchable); mActivityContext = mSearchable.getActivityContext(getContext()); // show the dialog. this will call onStart(). @@ -375,20 +290,6 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS // of any bad state in the AutoCompleteTextView etc createContentView(); - // The Dialog uses a ContextThemeWrapper for the context; use this to change the - // theme out from underneath us, between the global search theme and the in-app - // search theme. They are identical except that the global search theme does not - // dim the background of the window (because global search is full screen so it's - // not needed and this should save a little bit of time on global search invocation). - Object context = getContext(); - if (context instanceof ContextThemeWrapper) { - ContextThemeWrapper wrapper = (ContextThemeWrapper) context; - if (globalSearch) { - wrapper.setTheme(com.android.internal.R.style.Theme_GlobalSearchBar); - } else { - wrapper.setTheme(com.android.internal.R.style.Theme_SearchBar); - } - } show(); } updateUI(); @@ -414,7 +315,6 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS mSearchable = null; mActivityContext = null; mUserQuery = null; - mPreviousComponents = null; } /** @@ -428,7 +328,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS mWorkingSpinner.setVisible(working, false); mWorkingSpinner.invalidateSelf(); } - + /** * Closes and gets rid of the suggestions adapter. */ @@ -442,7 +342,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS } mSuggestionsAdapter = null; } - + /** * Save the minimal set of data necessary to recreate the search * @@ -458,10 +358,6 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS // setup info so I can recreate this particular search bundle.putParcelable(INSTANCE_KEY_COMPONENT, mLaunchComponent); bundle.putBundle(INSTANCE_KEY_APPDATA, mAppSearchData); - bundle.putBoolean(INSTANCE_KEY_GLOBALSEARCH, mGlobalSearchMode); - bundle.putParcelable(INSTANCE_KEY_STORED_COMPONENT, mStoredComponentName); - bundle.putBundle(INSTANCE_KEY_STORED_APPDATA, mStoredAppSearchData); - bundle.putParcelableArrayList(INSTANCE_KEY_PREVIOUS_COMPONENTS, mPreviousComponents); bundle.putString(INSTANCE_KEY_USER_QUERY, mUserQuery); return bundle; @@ -481,22 +377,10 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS ComponentName launchComponent = savedInstanceState.getParcelable(INSTANCE_KEY_COMPONENT); Bundle appSearchData = savedInstanceState.getBundle(INSTANCE_KEY_APPDATA); - boolean globalSearch = savedInstanceState.getBoolean(INSTANCE_KEY_GLOBALSEARCH); - ComponentName storedComponentName = - savedInstanceState.getParcelable(INSTANCE_KEY_STORED_COMPONENT); - Bundle storedAppSearchData = - savedInstanceState.getBundle(INSTANCE_KEY_STORED_APPDATA); - ArrayList previousComponents = - savedInstanceState.getParcelableArrayList(INSTANCE_KEY_PREVIOUS_COMPONENTS); String userQuery = savedInstanceState.getString(INSTANCE_KEY_USER_QUERY); - // Set stored state - mStoredComponentName = storedComponentName; - mStoredAppSearchData = storedAppSearchData; - mPreviousComponents = previousComponents; - // show the dialog. - if (!doShow(userQuery, false, launchComponent, appSearchData, globalSearch)) { + if (!doShow(userQuery, false, launchComponent, appSearchData)) { // for some reason, we couldn't re-instantiate return; } @@ -506,7 +390,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS * Called after resources have changed, e.g. after screen rotation or locale change. */ public void onConfigurationChanged() { - if (isShowing()) { + if (mSearchable != null && isShowing()) { // Redraw (resources may have changed) updateSearchButton(); updateSearchAppIcon(); @@ -571,19 +455,13 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS // we dismiss the entire dialog instead mSearchAutoComplete.setDropDownDismissedOnCompletion(false); - if (!isInRealAppSearch()) { - mSearchAutoComplete.setDropDownAlwaysVisible(true); // fill space until results come in - } else { - mSearchAutoComplete.setDropDownAlwaysVisible(false); - } - mSearchAutoComplete.setForceIgnoreOutsideTouch(true); // attach the suggestions adapter, if suggestions are available // The existence of a suggestions authority is the proxy for "suggestions available here" if (mSearchable.getSuggestAuthority() != null) { mSuggestionsAdapter = new SuggestionsAdapter(getContext(), this, mSearchable, - mOutsideDrawablesCache, mGlobalSearchMode); + mOutsideDrawablesCache); mSearchAutoComplete.setAdapter(mSuggestionsAdapter); } } @@ -611,7 +489,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS // global search, for extra space for url entry. // // TODO: Remove this special case once the issue has been reconciled in Eclair. - if (mGlobalSearchMode || isBrowserSearch()) { + if (isBrowserSearch()) { mAppIcon.setImageResource(0); mAppIcon.setVisibility(View.GONE); mSearchPlate.setPadding(SEARCH_PLATE_LEFT_PADDING_GLOBAL, @@ -705,15 +583,13 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS /** * Hack to determine whether this is the browser, so we can remove the browser icon - * to the left of the search field, as a special requirement for Donut. - * - * TODO: For Eclair, reconcile this with the rest of the global search UI. + * to the left of the search field. */ private boolean isBrowserSearch() { return mLaunchComponent.flattenToShortString().startsWith("com.android.browser/"); } - /** + /* * Listeners of various types */ @@ -769,7 +645,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS return super.onKeyDown(keyCode, event); } - + /** * Callback to watch the textedit field for empty/non-empty */ @@ -799,12 +675,8 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS if (mSearchable.autoUrlDetect() && !mSearchAutoComplete.isPerformingCompletion()) { // The user changed the query, check if it is a URL and if so change the search // button in the soft keyboard to the 'Go' button. - int options = (mSearchAutoComplete.getImeOptions() & (~EditorInfo.IME_MASK_ACTION)); - if (Patterns.WEB_URL.matcher(mUserQuery).matches()) { - options = options | EditorInfo.IME_ACTION_GO; - } else { - options = options | EditorInfo.IME_ACTION_SEARCH; - } + int options = (mSearchAutoComplete.getImeOptions() & (~EditorInfo.IME_MASK_ACTION)) + | EditorInfo.IME_ACTION_GO; if (options != mSearchAutoCompleteImeOptions) { mSearchAutoCompleteImeOptions = options; mSearchAutoComplete.setImeOptions(options); @@ -881,7 +753,8 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS if (searchable.getVoiceSearchLaunchWebSearch()) { getContext().startActivity(mVoiceWebSearchIntent); } else if (searchable.getVoiceSearchLaunchRecognizer()) { - Intent appSearchIntent = createVoiceAppSearchIntent(mVoiceAppSearchIntent); + Intent appSearchIntent = createVoiceAppSearchIntent(mVoiceAppSearchIntent, + searchable); getContext().startActivity(appSearchIntent); } } catch (ActivityNotFoundException e) { @@ -899,8 +772,8 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS * @param baseIntent The voice app search intent to start from * @return A completely-configured intent ready to send to the voice search activity */ - private Intent createVoiceAppSearchIntent(Intent baseIntent) { - ComponentName searchActivity = mSearchable.getSearchActivity(); + private Intent createVoiceAppSearchIntent(Intent baseIntent, SearchableInfo searchable) { + ComponentName searchActivity = searchable.getSearchActivity(); // create the necessary intent to set up a search-and-forward operation // in the voice search system. We have to keep the bundle separate, @@ -930,17 +803,17 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS String language = null; int maxResults = 1; Resources resources = mActivityContext.getResources(); - if (mSearchable.getVoiceLanguageModeId() != 0) { - languageModel = resources.getString(mSearchable.getVoiceLanguageModeId()); + if (searchable.getVoiceLanguageModeId() != 0) { + languageModel = resources.getString(searchable.getVoiceLanguageModeId()); } - if (mSearchable.getVoicePromptTextId() != 0) { - prompt = resources.getString(mSearchable.getVoicePromptTextId()); + if (searchable.getVoicePromptTextId() != 0) { + prompt = resources.getString(searchable.getVoicePromptTextId()); } - if (mSearchable.getVoiceLanguageId() != 0) { - language = resources.getString(mSearchable.getVoiceLanguageId()); + if (searchable.getVoiceLanguageId() != 0) { + language = resources.getString(searchable.getVoiceLanguageId()); } - if (mSearchable.getVoiceMaxResults() != 0) { - maxResults = mSearchable.getVoiceMaxResults(); + if (searchable.getVoiceMaxResults() != 0) { + maxResults = searchable.getVoiceMaxResults(); } voiceIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, languageModel); voiceIntent.putExtra(RecognizerIntent.EXTRA_PROMPT, prompt); @@ -1140,14 +1013,9 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS */ protected void launchQuerySearch(int actionKey, String actionMsg) { String query = mSearchAutoComplete.getText().toString(); - String action = mGlobalSearchMode ? Intent.ACTION_WEB_SEARCH : Intent.ACTION_SEARCH; + String action = Intent.ACTION_SEARCH; Intent intent = createIntent(action, null, null, query, null, - actionKey, actionMsg, null); - // Allow GlobalSearch to log and create shortcut for searches launched by - // the search button, enter key or an action key. - if (mGlobalSearchMode) { - mSuggestionsAdapter.reportSearch(query); - } + actionKey, actionMsg); launchIntent(intent); } @@ -1160,7 +1028,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS protected boolean launchSuggestion(int position) { return launchSuggestion(position, KeyEvent.KEYCODE_UNKNOWN, null); } - + /** * Launches an intent based on a suggestion. * @@ -1177,20 +1045,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS Intent intent = createIntentFromSuggestion(c, actionKey, actionMsg); - // report back about the click - if (mGlobalSearchMode) { - // in global search mode, do it via cursor - mSuggestionsAdapter.callCursorOnClick(c, position, actionKey, actionMsg); - } else if (intent != null - && mPreviousComponents != null - && !mPreviousComponents.isEmpty()) { - // in-app search (and we have pivoted in as told by mPreviousComponents, - // which is used for keeping track of what we pop back to when we are pivoting into - // in app search.) - reportInAppClickToGlobalSearch(c, intent); - } - - // launch the intent + // launch the intent launchIntent(intent); return true; @@ -1198,93 +1053,6 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS return false; } - /** - * Report a click from an in app search result back to global search for shortcutting porpoises. - * - * @param c The cursor that is pointing to the clicked position. - * @param intent The intent that will be launched for the click. - */ - private void reportInAppClickToGlobalSearch(Cursor c, Intent intent) { - // for in app search, still tell global search via content provider - Uri uri = getClickReportingUri(); - final ContentValues cv = new ContentValues(); - cv.put(SearchManager.SEARCH_CLICK_REPORT_COLUMN_QUERY, mUserQuery); - final ComponentName source = mSearchable.getSearchActivity(); - cv.put(SearchManager.SEARCH_CLICK_REPORT_COLUMN_COMPONENT, source.flattenToShortString()); - - // grab the intent columns from the intent we created since it has additional - // logic for falling back on the searchable default - cv.put(SearchManager.SUGGEST_COLUMN_INTENT_ACTION, intent.getAction()); - cv.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA, intent.getDataString()); - cv.put(SearchManager.SUGGEST_COLUMN_INTENT_COMPONENT_NAME, - intent.getComponent().flattenToShortString()); - - // ensure the icons will work for global search - cv.put(SearchManager.SUGGEST_COLUMN_ICON_1, - wrapIconForPackage( - mSearchable.getSuggestPackage(), - getColumnString(c, SearchManager.SUGGEST_COLUMN_ICON_1))); - cv.put(SearchManager.SUGGEST_COLUMN_ICON_2, - wrapIconForPackage( - mSearchable.getSuggestPackage(), - getColumnString(c, SearchManager.SUGGEST_COLUMN_ICON_2))); - - // the rest can be passed through directly - cv.put(SearchManager.SUGGEST_COLUMN_FORMAT, - getColumnString(c, SearchManager.SUGGEST_COLUMN_FORMAT)); - cv.put(SearchManager.SUGGEST_COLUMN_TEXT_1, - getColumnString(c, SearchManager.SUGGEST_COLUMN_TEXT_1)); - cv.put(SearchManager.SUGGEST_COLUMN_TEXT_2, - getColumnString(c, SearchManager.SUGGEST_COLUMN_TEXT_2)); - cv.put(SearchManager.SUGGEST_COLUMN_QUERY, - getColumnString(c, SearchManager.SUGGEST_COLUMN_QUERY)); - cv.put(SearchManager.SUGGEST_COLUMN_SHORTCUT_ID, - getColumnString(c, SearchManager.SUGGEST_COLUMN_SHORTCUT_ID)); - // note: deliberately omitting background color since it is only for global search - // "more results" entries - mContext.getContentResolver().insert(uri, cv); - } - - /** - * @return A URI appropriate for reporting a click. - */ - private Uri getClickReportingUri() { - Uri.Builder uriBuilder = new Uri.Builder() - .scheme(ContentResolver.SCHEME_CONTENT) - .authority(SearchManager.SEARCH_CLICK_REPORT_AUTHORITY); - - uriBuilder.appendPath(SearchManager.SEARCH_CLICK_REPORT_URI_PATH); - - return uriBuilder - .query("") // TODO: Remove, workaround for a bug in Uri.writeToParcel() - .fragment("") // TODO: Remove, workaround for a bug in Uri.writeToParcel() - .build(); - } - - /** - * Wraps an icon for a particular package. If the icon is a resource id, it is converted into - * an android.resource:// URI. - * - * @param packageName The source of the icon - * @param icon The icon retrieved from a suggestion column - * @return An icon string appropriate for the package. - */ - private String wrapIconForPackage(String packageName, String icon) { - if (icon == null || icon.length() == 0 || "0".equals(icon)) { - // SearchManager specifies that null or zero can be returned to indicate - // no icon. We also allow empty string. - return null; - } else if (!Character.isDigit(icon.charAt(0))){ - return icon; - } else { - return new Uri.Builder() - .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) - .authority(packageName) - .encodedPath(icon) - .toString(); - } - } - /** * Launches an intent, including any special intent handling. */ @@ -1292,70 +1060,22 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS if (intent == null) { return; } - if (handleSpecialIntent(intent)){ - return; - } Log.d(LOG_TAG, "launching " + intent); try { - // in global search mode, we send the activity straight to the original suggestion - // source. this is because GlobalSearch may not have permission to launch the - // intent, and to avoid the extra step of going through GlobalSearch. - if (mGlobalSearchMode) { - launchGlobalSearchIntent(intent); - if (mStoredComponentName != null) { - // If we're embedded in an application, dismiss the dialog. - // This ensures that if the intent is handled by the current - // activity, it's not obscured by the dialog. - dismiss(); - } - } else { - // If the intent was created from a suggestion, it will always have an explicit - // component here. - Log.i(LOG_TAG, "Starting (as ourselves) " + intent.toURI()); - getContext().startActivity(intent); - // If the search switches to a different activity, - // SearchDialogWrapper#performActivityResuming - // will handle hiding the dialog when the next activity starts, but for - // real in-app search, we still need to dismiss the dialog. - if (isInRealAppSearch()) { - dismiss(); - } - } + // If the intent was created from a suggestion, it will always have an explicit + // component here. + Log.i(LOG_TAG, "Starting (as ourselves) " + intent.toURI()); + getContext().startActivity(intent); + // If the search switches to a different activity, + // SearchDialogWrapper#performActivityResuming + // will handle hiding the dialog when the next activity starts, but for + // real in-app search, we still need to dismiss the dialog. + dismiss(); } catch (RuntimeException ex) { Log.e(LOG_TAG, "Failed launch activity: " + intent, ex); } } - private void launchGlobalSearchIntent(Intent intent) { - final String packageName; - // GlobalSearch puts the original source of the suggestion in the - // 'component name' column. If set, we send the intent to that activity. - // We trust GlobalSearch to always set this to the suggestion source. - String intentComponent = intent.getStringExtra(SearchManager.COMPONENT_NAME_KEY); - if (intentComponent != null) { - ComponentName componentName = ComponentName.unflattenFromString(intentComponent); - intent.setComponent(componentName); - intent.removeExtra(SearchManager.COMPONENT_NAME_KEY); - // Launch the intent as the suggestion source. - // This prevents sources from using the search dialog to launch - // intents that they don't have permission for themselves. - packageName = componentName.getPackageName(); - } else { - // If there is no component in the suggestion, it must be a built-in suggestion - // from GlobalSearch (e.g. "Search the web for") or the intent - // launched when pressing the search/go button in the search dialog. - // Launch the intent with the permissions of GlobalSearch. - packageName = mSearchable.getSearchActivity().getPackageName(); - } - - // Launch all global search suggestions as new tasks, since they don't relate - // to the current task. - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - setBrowserApplicationId(intent); - - startActivityInPackage(intent, packageName); - } - /** * If the intent is to open an HTTP or HTTPS URL, we set * {@link Browser#EXTRA_APPLICATION_ID} so that any existing browser window that @@ -1371,106 +1091,6 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS } } - /** - * Starts an activity as if it had been started by the given package. - * - * @param intent The description of the activity to start. - * @param packageName - * @throws ActivityNotFoundException If the intent could not be resolved to - * and existing activity. - * @throws SecurityException If the package does not have permission to start - * start the activity. - * @throws AndroidRuntimeException If some other error occurs. - */ - private void startActivityInPackage(Intent intent, String packageName) { - try { - int uid = ActivityThread.getPackageManager().getPackageUid(packageName); - if (uid < 0) { - throw new AndroidRuntimeException("Package UID not found " + packageName); - } - String resolvedType = intent.resolveTypeIfNeeded(getContext().getContentResolver()); - IBinder resultTo = null; - String resultWho = null; - int requestCode = -1; - boolean onlyIfNeeded = false; - Log.i(LOG_TAG, "Starting (uid " + uid + ", " + packageName + ") " + intent.toURI()); - int result = ActivityManagerNative.getDefault().startActivityInPackage( - uid, intent, resolvedType, resultTo, resultWho, requestCode, onlyIfNeeded); - checkStartActivityResult(result, intent); - } catch (RemoteException ex) { - throw new AndroidRuntimeException(ex); - } - } - - // Stolen from Instrumentation.checkStartActivityResult() - private static void checkStartActivityResult(int res, Intent intent) { - if (res >= IActivityManager.START_SUCCESS) { - return; - } - switch (res) { - case IActivityManager.START_INTENT_NOT_RESOLVED: - case IActivityManager.START_CLASS_NOT_FOUND: - if (intent.getComponent() != null) - throw new ActivityNotFoundException( - "Unable to find explicit activity class " - + intent.getComponent().toShortString() - + "; have you declared this activity in your AndroidManifest.xml?"); - throw new ActivityNotFoundException( - "No Activity found to handle " + intent); - case IActivityManager.START_PERMISSION_DENIED: - throw new SecurityException("Not allowed to start activity " - + intent); - case IActivityManager.START_FORWARD_AND_REQUEST_CONFLICT: - throw new AndroidRuntimeException( - "FORWARD_RESULT_FLAG used while also requesting a result"); - default: - throw new AndroidRuntimeException("Unknown error code " - + res + " when starting " + intent); - } - } - - /** - * Handles the special intent actions declared in {@link SearchManager}. - * - * @return true if the intent was handled. - */ - private boolean handleSpecialIntent(Intent intent) { - String action = intent.getAction(); - if (SearchManager.INTENT_ACTION_CHANGE_SEARCH_SOURCE.equals(action)) { - handleChangeSourceIntent(intent); - return true; - } - return false; - } - - /** - * Handles {@link SearchManager#INTENT_ACTION_CHANGE_SEARCH_SOURCE}. - */ - private void handleChangeSourceIntent(Intent intent) { - Uri dataUri = intent.getData(); - if (dataUri == null) { - Log.w(LOG_TAG, "SearchManager.INTENT_ACTION_CHANGE_SOURCE without intent data."); - return; - } - ComponentName componentName = ComponentName.unflattenFromString(dataUri.toString()); - if (componentName == null) { - Log.w(LOG_TAG, "Invalid ComponentName: " + dataUri); - return; - } - if (DBG) Log.d(LOG_TAG, "Switching to " + componentName); - - pushPreviousComponent(mLaunchComponent); - if (!show(componentName, mAppSearchData, false)) { - Log.w(LOG_TAG, "Failed to switch to source " + componentName); - popPreviousComponent(); - return; - } - - String query = intent.getStringExtra(SearchManager.QUERY); - setUserQuery(query); - mSearchAutoComplete.showDropDown(); - } - /** * Sets the list item selection in the AutoCompleteTextView's ListView. */ @@ -1478,61 +1098,6 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS mSearchAutoComplete.setListSelection(index); } - /** - * Checks if there are any previous searchable components in the history stack. - */ - private boolean hasPreviousComponent() { - return mPreviousComponents != null && !mPreviousComponents.isEmpty(); - } - - /** - * Saves the previous component that was searched, so that we can go - * back to it. - */ - private void pushPreviousComponent(ComponentName componentName) { - if (mPreviousComponents == null) { - mPreviousComponents = new ArrayList(); - } - mPreviousComponents.add(componentName); - } - - /** - * Pops the previous component off the stack and returns it. - * - * @return The component name, or null if there was - * no previous component. - */ - private ComponentName popPreviousComponent() { - if (!hasPreviousComponent()) { - return null; - } - return mPreviousComponents.remove(mPreviousComponents.size() - 1); - } - - /** - * Goes back to the previous component that was searched, if any. - * - * @return true if there was a previous component that we could go back to. - */ - private boolean backToPreviousComponent() { - ComponentName previous = popPreviousComponent(); - if (previous == null) { - return false; - } - - if (!show(previous, mAppSearchData, false)) { - Log.w(LOG_TAG, "Failed to switch to source " + previous); - return false; - } - - // must touch text to trigger suggestions - // TODO: should this be the text as it was when the user left - // the source that we are now going back to? - String query = mSearchAutoComplete.getText().toString(); - setUserQuery(query); - return true; - } - /** * When a particular suggestion has been selected, perform the various lookups required * to use the suggestion. This includes checking the cursor for suggestion-specific data, @@ -1582,10 +1147,9 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS String query = getColumnString(c, SearchManager.SUGGEST_COLUMN_QUERY); String extraData = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA); - String mode = mGlobalSearchMode ? SearchManager.MODE_GLOBAL_SEARCH_SUGGESTION : null; return createIntent(action, dataUri, extraData, query, componentName, actionKey, - actionMsg, mode); + actionMsg); } catch (RuntimeException e ) { int rowNum; try { // be really paranoid now @@ -1616,16 +1180,13 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS * @return The intent. */ private Intent createIntent(String action, Uri data, String extraData, String query, - String componentName, int actionKey, String actionMsg, String mode) { + String componentName, int actionKey, String actionMsg) { // Now build the Intent Intent intent = new Intent(action); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // We need CLEAR_TOP to avoid reusing an old task that has other activities // on top of the one we want. We don't want to do this in in-app search though, // as it can be destructive to the activity stack. - if (mGlobalSearchMode) { - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - } if (data != null) { intent.setData(data); } @@ -1636,9 +1197,6 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS if (extraData != null) { intent.putExtra(SearchManager.EXTRA_DATA_KEY, extraData); } - if (componentName != null) { - intent.putExtra(SearchManager.COMPONENT_NAME_KEY, componentName); - } if (mAppSearchData != null) { intent.putExtra(SearchManager.APP_DATA, mAppSearchData); } @@ -1646,16 +1204,10 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS intent.putExtra(SearchManager.ACTION_KEY, actionKey); intent.putExtra(SearchManager.ACTION_MSG, actionMsg); } - if (mode != null) { - intent.putExtra(SearchManager.SEARCH_MODE, mode); - } - // Only allow 3rd-party intents from GlobalSearch - if (!mGlobalSearchMode) { - intent.setComponent(mSearchable.getSearchActivity()); - } + intent.setComponent(mSearchable.getSearchActivity()); return intent; } - + /** * For a given suggestion and a given cursor row, get the action message. If not provided * by the specific row/column, also check for a single definition (for the action key). @@ -1812,12 +1364,8 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0)) { return; } - // Otherwise, go back to any previous source (e.g. back to QSB when - // pivoted into a source. - if (!backToPreviousComponent()) { - // If no previous source, close search dialog - cancel(); - } + // Close search dialog + cancel(); } /** diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java index 5a9a675f62e26..52cdc748a818a 100644 --- a/core/java/android/app/SearchManager.java +++ b/core/java/android/app/SearchManager.java @@ -350,7 +350,7 @@ import java.util.List; *

Configuring your Content Provider to Receive Suggestion Queries. The basic job of * a search suggestions {@link android.content.ContentProvider Content Provider} is to provide * "live" (while-you-type) conversion of the user's query text into a set of zero or more - * suggestions. Each application is free to define the conversion, and as described above there are + * suggestions. Each application is free to define the conversion, and as described above there are * many possible solutions. This section simply defines how to communicate with the suggestion * provider. * @@ -360,7 +360,8 @@ import java.util.List; * *

Every query includes a Uri, and the Search Manager will format the Uri as shown: *

- * content:// your.suggest.authority / your.suggest.path / SearchManager.SUGGEST_URI_PATH_QUERY
+ * content:// your.suggest.authority / your.suggest.path / SearchManager.SUGGEST_URI_PATH_QUERY + * * *

Your Content Provider can receive the query text in one of two ways. *

    @@ -379,7 +380,7 @@ import java.util.List; *

    Providing access to Content Providers that require permissions. If your content * provider declares an android:readPermission in your application's manifest, you must provide * access to the search infrastructure to the search suggestion path by including a path-permission - * that grants android:readPermission access to "android.permission.GLOBAL_SEARCH". Granting access + * that grants android:readPermission access to "android.permission.GLOBAL_SEARCH". Granting access * explicitly to the search infrastructure ensures it will be able to access the search suggestions * without needing to know ahead of time any other details of the permissions protecting your * provider. Content providers that require no permissions are already available to the search @@ -546,7 +547,8 @@ import java.util.List; * taken directly to a specific result. *

      *
    • Action: {@link android.content.Intent#ACTION_VIEW ACTION_VIEW}
    • - *
    • Data: a complete Uri, supplied by the cursor, that identifies the desired data.
    • + *
    • Data: a complete Uri, supplied by the cursor, that identifies the desired data. + *
    • *
    • Query: query text supplied with the suggestion (probably ignored)
    • *
    * @@ -570,7 +572,7 @@ import java.util.List; * *

    Suggestion Rewriting. If the user navigates through the suggestions list, the UI * may temporarily rewrite the user's query with a query that matches the currently selected - * suggestion. This enables the user to see what query is being suggested, and also allows the user + * suggestion. This enables the user to see what query is being suggested, and also allows the user * to click or touch in the entry EditText element and make further edits to the query before * dispatching it. In order to perform this correctly, the Search UI needs to know exactly what * text to rewrite the query with. @@ -1288,15 +1290,6 @@ public class SearchManager */ public final static String SEARCH_MODE = "search_mode"; - /** - * Value for the {@link #SEARCH_MODE} key. - * This is used if the intent was launched by clicking a suggestion in global search - * mode (Quick Search Box). - * - * @hide - */ - public static final String MODE_GLOBAL_SEARCH_SUGGESTION = "global_search_suggestion"; - /** * Intent extra data key: Use this key with Intent.ACTION_SEARCH and * {@link android.content.Intent#getIntExtra content.Intent.getIntExtra()} @@ -1307,14 +1300,6 @@ public class SearchManager */ public final static String ACTION_KEY = "action_key"; - /** - * Intent component name key: This key will be used for the extra populated by the - * {@link #SUGGEST_COLUMN_INTENT_COMPONENT_NAME} column. - * - * {@hide} - */ - public final static String COMPONENT_NAME_KEY = "intent_component_name_key"; - /** * Intent extra data key: This key will be used for the extra populated by the * {@link #SUGGEST_COLUMN_INTENT_EXTRA_DATA} column. @@ -1328,58 +1313,6 @@ public class SearchManager */ public final static String EXTRA_SELECT_QUERY = "select_query"; - /** - * Defines the constants used in the communication between {@link android.app.SearchDialog} and - * the global search provider via {@link Cursor#respond(android.os.Bundle)}. - * - * @hide - */ - public static class DialogCursorProtocol { - - /** - * The sent bundle will contain this integer key, with a value set to one of the events - * below. - */ - public final static String METHOD = "DialogCursorProtocol.method"; - - /** - * After data has been refreshed. - */ - public final static int POST_REFRESH = 0; - public final static String POST_REFRESH_RECEIVE_ISPENDING - = "DialogCursorProtocol.POST_REFRESH.isPending"; - public final static String POST_REFRESH_RECEIVE_DISPLAY_NOTIFY - = "DialogCursorProtocol.POST_REFRESH.displayNotify"; - - /** - * When a position has been clicked. - */ - public final static int CLICK = 2; - public final static String CLICK_SEND_POSITION - = "DialogCursorProtocol.CLICK.sendPosition"; - public final static String CLICK_SEND_MAX_DISPLAY_POS - = "DialogCursorProtocol.CLICK.sendDisplayPosition"; - public final static String CLICK_SEND_ACTION_KEY - = "DialogCursorProtocol.CLICK.sendActionKey"; - public final static String CLICK_SEND_ACTION_MSG - = "DialogCursorProtocol.CLICK.sendActionMsg"; - public final static String CLICK_RECEIVE_SELECTED_POS - = "DialogCursorProtocol.CLICK.receiveSelectedPosition"; - - /** - * When the threshold received in {@link #POST_REFRESH_RECEIVE_DISPLAY_NOTIFY} is displayed. - */ - public final static int THRESH_HIT = 3; - - /** - * When a search is started without using a suggestion. - */ - public final static int SEARCH = 4; - public final static String SEARCH_SEND_MAX_DISPLAY_POS - = "DialogCursorProtocol.SEARCH.sendDisplayPosition"; - public final static String SEARCH_SEND_QUERY = "DialogCursorProtocol.SEARCH.query"; - } - /** * Intent extra data key: Use this key with Intent.ACTION_SEARCH and * {@link android.content.Intent#getStringExtra content.Intent.getStringExtra()} @@ -1421,40 +1354,6 @@ public class SearchManager public final static String SHORTCUT_MIME_TYPE = "vnd.android.cursor.item/vnd.android.search.suggest"; - - /** - * The authority of the provider to report clicks to when a click is detected after pivoting - * into a specific app's search from global search. - * - * In addition to the columns below, the suggestion columns are used to pass along the full - * suggestion so it can be shortcutted. - * - * @hide - */ - public final static String SEARCH_CLICK_REPORT_AUTHORITY = - "com.android.globalsearch.stats"; - - /** - * The path the write goes to. - * - * @hide - */ - public final static String SEARCH_CLICK_REPORT_URI_PATH = "click"; - - /** - * The column storing the query for the click. - * - * @hide - */ - public final static String SEARCH_CLICK_REPORT_COLUMN_QUERY = "query"; - - /** - * The column storing the component name of the application that was pivoted into. - * - * @hide - */ - public final static String SEARCH_CLICK_REPORT_COLUMN_COMPONENT = "component"; - /** * Column name for suggestions cursor. Unused - can be null or column can be omitted. */ @@ -1531,10 +1430,7 @@ public class SearchManager */ public final static String SUGGEST_COLUMN_INTENT_EXTRA_DATA = "suggest_intent_extra_data"; /** - * Column name for suggestions cursor. Optional. This column allows suggestions - * to provide additional arbitrary data which will be included as an extra under the key - * {@link #COMPONENT_NAME_KEY}. For use by the global search system only - if other providers - * attempt to use this column, the value will be overwritten by global search. + * TODO: Remove * * @hide */ @@ -1593,27 +1489,6 @@ public class SearchManager */ public final static String SUGGEST_PARAMETER_LIMIT = "limit"; - /** - * If a suggestion has this value in {@link #SUGGEST_COLUMN_INTENT_ACTION}, - * the search dialog will switch to a different suggestion source when the - * suggestion is clicked. - * - * {@link #SUGGEST_COLUMN_INTENT_DATA} must contain - * the flattened {@link ComponentName} of the activity which is to be searched. - * - * TODO: Should {@link #SUGGEST_COLUMN_INTENT_DATA} instead contain a URI in the format - * used by {@link android.provider.Applications}? - * - * TODO: This intent should be protected by the same permission that we use - * for replacing the global search provider. - * - * The query text field will be set to the value of {@link #SUGGEST_COLUMN_QUERY}. - * - * @hide Pending API council approval. - */ - public final static String INTENT_ACTION_CHANGE_SEARCH_SOURCE - = "android.search.action.CHANGE_SEARCH_SOURCE"; - /** * Intent action for starting the global search activity. * The global search provider should handle this intent. @@ -1663,7 +1538,7 @@ public class SearchManager * @hide */ public final static String INTENT_ACTION_NONE = "android.search.action.ZILCH"; - + /** * Reference to the shared system search service. */ @@ -1671,13 +1546,6 @@ 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. */ @@ -1696,21 +1564,6 @@ public class SearchManager mService = ISearchManager.Stub.asInterface( ServiceManager.getService(Context.SEARCH_SERVICE)); } - - /*package*/ boolean hasIdent() { - return mIdent != 0; - } - - /*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(); - } /** * Launch search UI. @@ -1757,15 +1610,14 @@ public class SearchManager ComponentName launchActivity, Bundle appSearchData, boolean globalSearch) { - ensureSearchDialog(); - if (globalSearch) { startGlobalSearch(initialQuery, selectInitialQuery, appSearchData); return; } - mSearchDialog.show(initialQuery, selectInitialQuery, launchActivity, appSearchData, - globalSearch); + ensureSearchDialog(); + + mSearchDialog.show(initialQuery, selectInitialQuery, launchActivity, appSearchData); } private void ensureSearchDialog() { @@ -1994,17 +1846,6 @@ public class SearchManager return null; } } - - /** - * Checks whether the given searchable is the default searchable. - * - * @hide because SearchableInfo is not part of the API. - */ - public boolean isDefaultSearchable(SearchableInfo searchable) { - SearchableInfo defaultSearchable = getSearchableInfo(null, true); - return defaultSearchable != null - && defaultSearchable.getSearchActivity().equals(searchable.getSearchActivity()); - } /** * Gets a cursor with search suggestions. @@ -2091,56 +1932,4 @@ public class SearchManager } } - /** - * Returns a list of the searchable activities that handle web searches. - * - * @return a list of all searchable activities that handle - * {@link android.content.Intent#ACTION_WEB_SEARCH}. - * - * @hide because SearchableInfo is not part of the API. - */ - public List getSearchablesForWebSearch() { - try { - return mService.getSearchablesForWebSearch(); - } catch (RemoteException e) { - Log.e(TAG, "getSearchablesForWebSearch() failed: " + e); - return null; - } - } - - /** - * Returns the default searchable activity for web searches. - * - * @return searchable information for the activity handling web searches by default. - * - * @hide because SearchableInfo is not part of the API. - */ - public SearchableInfo getDefaultSearchableForWebSearch() { - try { - return mService.getDefaultSearchableForWebSearch(); - } catch (RemoteException e) { - Log.e(TAG, "getDefaultSearchableForWebSearch() failed: " + e); - return null; - } - } - - /** - * Sets the default searchable activity for web searches. - * - * @param component Name of the component to set as default activity for web searches. - * - * @hide - */ - public void setDefaultWebSearch(ComponentName component) { - try { - mService.setDefaultWebSearch(component); - } catch (RemoteException e) { - Log.e(TAG, "setDefaultWebSearch() failed: " + e); - } - } - - private static void debug(String msg) { - Thread thread = Thread.currentThread(); - Log.d(TAG, msg + " (" + thread.getName() + "-" + thread.getId() + ")"); - } } diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java index 173c3e1907a0a..57795d11b9123 100644 --- a/core/java/android/app/SuggestionsAdapter.java +++ b/core/java/android/app/SuggestionsAdapter.java @@ -16,7 +16,6 @@ package android.app; -import android.app.SearchManager.DialogCursorProtocol; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; @@ -30,12 +29,10 @@ import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.StateListDrawable; import android.net.Uri; -import android.os.Bundle; import android.text.Html; import android.text.TextUtils; import android.util.Log; import android.util.SparseArray; -import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; import android.widget.Filter; @@ -65,7 +62,6 @@ class SuggestionsAdapter extends ResourceCursorAdapter { private Context mProviderContext; private WeakHashMap mOutsideDrawablesCache; private SparseArray mBackgroundsCache; - private boolean mGlobalSearchMode; private boolean mClosed = false; // Cached column indexes, updated when the cursor changes. @@ -76,29 +72,8 @@ class SuggestionsAdapter extends ResourceCursorAdapter { private int mIconName2Col; private int mBackgroundColorCol; - // The extra used to tell a cursor to close itself. This is a hack, see the description by - // its use later in this file. - private static final String EXTRA_CURSOR_RESPOND_CLOSE_CURSOR = "cursor_respond_close_cursor"; - - // The bundle which contains {EXTRA_CURSOR_RESPOND_CLOSE_CURSOR=true}, just cached once - // so we don't bother recreating it a bunch. - private final Bundle mCursorRespondCloseCursorBundle; - - // This value is stored in SuggestionsAdapter by the SearchDialog to indicate whether - // a particular list item should be selected upon the next call to notifyDataSetChanged. - // This is used to indicate the index of the "More results..." list item so that when - // the data set changes after a click of "More results...", we can correctly tell the - // ListView to scroll to the right line item. It gets reset to NONE every time it - // is consumed. - private int mListItemToSelect = NONE; static final int NONE = -1; - // holds the maximum position that has been displayed to the user - int mMaxDisplayed = NONE; - - // holds the position that, when displayed, should result in notifying the cursor - int mDisplayNotifyPos = NONE; - private final Runnable mStartSpinnerRunnable; private final Runnable mStopSpinnerRunnable; @@ -110,8 +85,7 @@ class SuggestionsAdapter extends ResourceCursorAdapter { public SuggestionsAdapter(Context context, SearchDialog searchDialog, SearchableInfo searchable, - WeakHashMap outsideDrawablesCache, - boolean globalSearchMode) { + WeakHashMap outsideDrawablesCache) { super(context, com.android.internal.R.layout.search_dropdown_item_icons_2line, null, // no initial cursor @@ -126,7 +100,6 @@ class SuggestionsAdapter extends ResourceCursorAdapter { mOutsideDrawablesCache = outsideDrawablesCache; mBackgroundsCache = new SparseArray(); - mGlobalSearchMode = globalSearchMode; mStartSpinnerRunnable = new Runnable() { public void run() { @@ -140,10 +113,6 @@ class SuggestionsAdapter extends ResourceCursorAdapter { } }; - // Create this once because we'll reuse it a bunch. - mCursorRespondCloseCursorBundle = new Bundle(); - mCursorRespondCloseCursorBundle.putBoolean(EXTRA_CURSOR_RESPOND_CLOSE_CURSOR, true); - // delay 500ms when deleting getFilter().setDelayer(new Filter.Delayer() { @@ -177,27 +146,22 @@ class SuggestionsAdapter extends ResourceCursorAdapter { public Cursor runQueryOnBackgroundThread(CharSequence constraint) { if (DBG) Log.d(LOG_TAG, "runQueryOnBackgroundThread(" + constraint + ")"); String query = (constraint == null) ? "" : constraint.toString(); - if (!mGlobalSearchMode) { - /** - * for in app search we show the progress spinner until the cursor is returned with - * the results. for global search we manage the progress bar using - * {@link DialogCursorProtocol#POST_REFRESH_RECEIVE_ISPENDING}. - */ - mSearchDialog.getWindow().getDecorView().post(mStartSpinnerRunnable); - } + /** + * for in app search we show the progress spinner until the cursor is returned with + * the results. + */ + mSearchDialog.getWindow().getDecorView().post(mStartSpinnerRunnable); try { final Cursor cursor = mSearchManager.getSuggestions(mSearchable, query, QUERY_LIMIT); // trigger fill window so the spinner stays up until the results are copied over and // closer to being ready - if (!mGlobalSearchMode && cursor != null) cursor.getCount(); + if (cursor != null) cursor.getCount(); return cursor; } catch (RuntimeException e) { Log.w(LOG_TAG, "Search suggestions query threw an exception.", e); return null; } finally { - if (!mGlobalSearchMode) { - mSearchDialog.getWindow().getDecorView().post(mStopSpinnerRunnable); - } + mSearchDialog.getWindow().getDecorView().post(mStopSpinnerRunnable); } } @@ -221,21 +185,8 @@ class SuggestionsAdapter extends ResourceCursorAdapter { } try { - Cursor oldCursor = getCursor(); super.changeCursor(c); - - // We send a special respond to the cursor to tell it to close itself directly because - // it may not happen correctly for some cursors currently. This was originally - // included as a fix to http://b/2036290, in which the search dialog was holding - // on to references to the web search provider unnecessarily. This is being caused by - // the fact that the cursor is not being correctly closed in - // BulkCursorToCursorAdapter#close, which remains unfixed (see http://b/2015069). - // - // TODO: Remove this hack once http://b/2015069 is fixed. - if (oldCursor != null && oldCursor != c) { - oldCursor.respond(mCursorRespondCloseCursorBundle); - } - + if (c != null) { mFormatCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_FORMAT); mText1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1); @@ -249,79 +200,6 @@ class SuggestionsAdapter extends ResourceCursorAdapter { } } - @Override - public void notifyDataSetChanged() { - if (DBG) Log.d(LOG_TAG, "notifyDataSetChanged"); - super.notifyDataSetChanged(); - - callCursorPostRefresh(mCursor); - - // look out for the pending item we are supposed to scroll to - if (mListItemToSelect != NONE) { - mSearchDialog.setListSelection(mListItemToSelect); - mListItemToSelect = NONE; - } - } - - /** - * Handle sending and receiving information associated with - * {@link DialogCursorProtocol#POST_REFRESH}. - * - * @param cursor The cursor to call. - */ - private void callCursorPostRefresh(Cursor cursor) { - if (!mGlobalSearchMode) return; - final Bundle request = new Bundle(); - request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.POST_REFRESH); - final Bundle response = cursor.respond(request); - - mSearchDialog.setWorking( - response.getBoolean(DialogCursorProtocol.POST_REFRESH_RECEIVE_ISPENDING, false)); - - mDisplayNotifyPos = - response.getInt(DialogCursorProtocol.POST_REFRESH_RECEIVE_DISPLAY_NOTIFY, -1); - } - - /** - * Tell the cursor which position was clicked, handling sending and receiving information - * associated with {@link DialogCursorProtocol#CLICK}. - * - * @param cursor The cursor - * @param position The position that was clicked. - */ - void callCursorOnClick(Cursor cursor, int position, int actionKey, String actionMsg) { - if (!mGlobalSearchMode) return; - final Bundle request = new Bundle(5); - request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.CLICK); - request.putInt(DialogCursorProtocol.CLICK_SEND_POSITION, position); - request.putInt(DialogCursorProtocol.CLICK_SEND_MAX_DISPLAY_POS, mMaxDisplayed); - if (actionKey != KeyEvent.KEYCODE_UNKNOWN) { - request.putInt(DialogCursorProtocol.CLICK_SEND_ACTION_KEY, actionKey); - request.putString(DialogCursorProtocol.CLICK_SEND_ACTION_MSG, actionMsg); - } - final Bundle response = cursor.respond(request); - mMaxDisplayed = -1; - mListItemToSelect = response.getInt( - DialogCursorProtocol.CLICK_RECEIVE_SELECTED_POS, SuggestionsAdapter.NONE); - } - - /** - * Tell the cursor that a search was started without using a suggestion. - * - * @param query The search query. - */ - void reportSearch(String query) { - if (!mGlobalSearchMode) return; - Cursor cursor = getCursor(); - if (cursor == null) return; - final Bundle request = new Bundle(3); - request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.SEARCH); - request.putString(DialogCursorProtocol.SEARCH_SEND_QUERY, query); - request.putInt(DialogCursorProtocol.SEARCH_SEND_MAX_DISPLAY_POS, mMaxDisplayed); - // the response is always empty - cursor.respond(request); - } - /** * Tags the view with cached child view look-ups. */ @@ -353,20 +231,6 @@ class SuggestionsAdapter extends ResourceCursorAdapter { @Override public void bindView(View view, Context context, Cursor cursor) { ChildViewCache views = (ChildViewCache) view.getTag(); - final int pos = cursor.getPosition(); - - // update the maximum position displayed since last refresh - if (pos > mMaxDisplayed) { - mMaxDisplayed = pos; - } - - // if the cursor wishes to be notified about this position, send it - if (mGlobalSearchMode && mDisplayNotifyPos != NONE && pos == mDisplayNotifyPos) { - final Bundle request = new Bundle(); - request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.THRESH_HIT); - mCursor.respond(request); - mDisplayNotifyPos = NONE; // only notify the first time - } int backgroundColor = 0; if (mBackgroundColorCol != -1) { diff --git a/core/tests/coretests/src/android/app/SearchManagerTest.java b/core/tests/coretests/src/android/app/SearchManagerTest.java index fc7e78717788e..08b7f60c368f2 100644 --- a/core/tests/coretests/src/android/app/SearchManagerTest.java +++ b/core/tests/coretests/src/android/app/SearchManagerTest.java @@ -120,23 +120,6 @@ public class SearchManagerTest extends ActivityInstrumentationTestCase2