Cleanup of global search references in SearchDialog and SearchManager.
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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<ComponentName> 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 <code>true</code> 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<ComponentName> 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 <code>true</code> 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<ComponentName>();
|
||||
}
|
||||
mPreviousComponents.add(componentName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pops the previous component off the stack and returns it.
|
||||
*
|
||||
* @return The component name, or <code>null</code> 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 <code>true</code> 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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -350,7 +350,7 @@ import java.util.List;
|
||||
* <p><b>Configuring your Content Provider to Receive Suggestion Queries.</b> 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;
|
||||
*
|
||||
* <p>Every query includes a Uri, and the Search Manager will format the Uri as shown:
|
||||
* <p><pre class="prettyprint">
|
||||
* content:// your.suggest.authority / your.suggest.path / SearchManager.SUGGEST_URI_PATH_QUERY</pre>
|
||||
* content:// your.suggest.authority / your.suggest.path / SearchManager.SUGGEST_URI_PATH_QUERY
|
||||
* </pre>
|
||||
*
|
||||
* <p>Your Content Provider can receive the query text in one of two ways.
|
||||
* <ul>
|
||||
@@ -379,7 +380,7 @@ import java.util.List;
|
||||
* <p><b>Providing access to Content Providers that require permissions.</b> 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.
|
||||
* <ul>
|
||||
* <li><b>Action:</b> {@link android.content.Intent#ACTION_VIEW ACTION_VIEW}</li>
|
||||
* <li><b>Data:</b> a complete Uri, supplied by the cursor, that identifies the desired data.</li>
|
||||
* <li><b>Data:</b> a complete Uri, supplied by the cursor, that identifies the desired data.
|
||||
* </li>
|
||||
* <li><b>Query:</b> query text supplied with the suggestion (probably ignored)</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
@@ -570,7 +572,7 @@ import java.util.List;
|
||||
*
|
||||
* <p><b>Suggestion Rewriting.</b> 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. <i>Unused - can be null or column can be omitted.</i>
|
||||
*/
|
||||
@@ -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. <i>Optional.</i> 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<SearchableInfo> 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() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<String, Drawable.ConstantState> mOutsideDrawablesCache;
|
||||
private SparseArray<Drawable.ConstantState> 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<String, Drawable.ConstantState> outsideDrawablesCache,
|
||||
boolean globalSearchMode) {
|
||||
WeakHashMap<String, Drawable.ConstantState> 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<Drawable.ConstantState>();
|
||||
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) {
|
||||
|
||||
@@ -120,23 +120,6 @@ public class SearchManagerTest extends ActivityInstrumentationTestCase2<LocalAct
|
||||
assertSame(searchManager1, searchManager2 );
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testSearchables() {
|
||||
SearchManager searchManager = (SearchManager)
|
||||
mContext.getSystemService(Context.SEARCH_SERVICE);
|
||||
SearchableInfo si;
|
||||
|
||||
si = searchManager.getSearchableInfo(SEARCHABLE_ACTIVITY, false);
|
||||
assertNotNull(si);
|
||||
assertFalse(searchManager.isDefaultSearchable(si));
|
||||
si = searchManager.getSearchableInfo(SEARCHABLE_ACTIVITY, true);
|
||||
assertNotNull(si);
|
||||
assertTrue(searchManager.isDefaultSearchable(si));
|
||||
si = searchManager.getSearchableInfo(null, true);
|
||||
assertNotNull(si);
|
||||
assertTrue(searchManager.isDefaultSearchable(si));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that startSearch() can be called multiple times without stopSearch()
|
||||
* in between.
|
||||
|
||||
Reference in New Issue
Block a user