Loading core/java/android/app/Dialog.java +0 −5 Original line number Diff line number Diff line Loading @@ -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(); Loading core/java/android/app/SearchDialog.java +57 −509 File changed.Preview size limit exceeded, changes collapsed. Show changes core/java/android/app/SearchManager.java +12 −223 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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> Loading Loading @@ -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()} Loading @@ -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. Loading @@ -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()} Loading Loading @@ -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> */ Loading Loading @@ -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 */ Loading Loading @@ -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. Loading Loading @@ -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. */ Loading @@ -1697,21 +1565,6 @@ public class SearchManager 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. * Loading Loading @@ -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() { Loading Loading @@ -1995,17 +1847,6 @@ public class SearchManager } } /** * 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. * Loading Loading @@ -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() + ")"); } } core/java/android/app/SuggestionsAdapter.java +9 −145 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package android.app; import android.app.SearchManager.DialogCursorProtocol; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; Loading @@ -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; Loading Loading @@ -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. Loading @@ -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; Loading @@ -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 Loading @@ -126,7 +100,6 @@ class SuggestionsAdapter extends ResourceCursorAdapter { mOutsideDrawablesCache = outsideDrawablesCache; mBackgroundsCache = new SparseArray<Drawable.ConstantState>(); mGlobalSearchMode = globalSearchMode; mStartSpinnerRunnable = new Runnable() { public void run() { Loading @@ -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() { Loading Loading @@ -177,29 +146,24 @@ 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}. * 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); } } } public void close() { if (DBG) Log.d(LOG_TAG, "close()"); Loading @@ -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); Loading @@ -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. */ Loading Loading @@ -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) { Loading core/tests/coretests/src/android/app/SearchManagerTest.java +0 −17 Original line number Diff line number Diff line Loading @@ -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. Loading Loading
core/java/android/app/Dialog.java +0 −5 Original line number Diff line number Diff line Loading @@ -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(); Loading
core/java/android/app/SearchDialog.java +57 −509 File changed.Preview size limit exceeded, changes collapsed. Show changes
core/java/android/app/SearchManager.java +12 −223 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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> Loading Loading @@ -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()} Loading @@ -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. Loading @@ -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()} Loading Loading @@ -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> */ Loading Loading @@ -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 */ Loading Loading @@ -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. Loading Loading @@ -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. */ Loading @@ -1697,21 +1565,6 @@ public class SearchManager 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. * Loading Loading @@ -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() { Loading Loading @@ -1995,17 +1847,6 @@ public class SearchManager } } /** * 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. * Loading Loading @@ -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() + ")"); } }
core/java/android/app/SuggestionsAdapter.java +9 −145 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package android.app; import android.app.SearchManager.DialogCursorProtocol; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; Loading @@ -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; Loading Loading @@ -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. Loading @@ -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; Loading @@ -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 Loading @@ -126,7 +100,6 @@ class SuggestionsAdapter extends ResourceCursorAdapter { mOutsideDrawablesCache = outsideDrawablesCache; mBackgroundsCache = new SparseArray<Drawable.ConstantState>(); mGlobalSearchMode = globalSearchMode; mStartSpinnerRunnable = new Runnable() { public void run() { Loading @@ -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() { Loading Loading @@ -177,29 +146,24 @@ 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}. * 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); } } } public void close() { if (DBG) Log.d(LOG_TAG, "close()"); Loading @@ -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); Loading @@ -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. */ Loading Loading @@ -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) { Loading
core/tests/coretests/src/android/app/SearchManagerTest.java +0 −17 Original line number Diff line number Diff line Loading @@ -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. Loading