diff options
| author | 2009-06-09 12:45:35 -0700 | |
|---|---|---|
| committer | 2009-06-09 12:45:35 -0700 | |
| commit | 9d19fdb231592904b6f8940355d89745719a1ea1 (patch) | |
| tree | 43ef362cf9f8d739e0dc9d95733f449a669bef24 | |
| parent | 4ab3c00993bd7932e5262d325e6d9943074844ed (diff) | |
| parent | d4c98c4c450a95b67fe9746675984333b7653713 (diff) | |
Merge change 3576 into donut
* changes:
Track clicks that occur after pivoting into an app from global search.
| -rw-r--r-- | core/java/android/app/SearchDialog.java | 109 | ||||
| -rw-r--r-- | core/java/android/app/SearchManager.java | 35 |
2 files changed, 141 insertions, 3 deletions
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java index 0bb483b40d8b..7de657238bcb 100644 --- a/core/java/android/app/SearchDialog.java +++ b/core/java/android/app/SearchDialog.java @@ -24,6 +24,8 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.ContentResolver; +import android.content.ContentValues; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; @@ -1202,10 +1204,23 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS protected boolean launchSuggestion(int position, int actionKey, String actionMsg) { Cursor c = mSuggestionsAdapter.getCursor(); if ((c != null) && c.moveToPosition(position)) { - mSuggestionsAdapter.callCursorOnClick(c, position); - // launch the intent 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); + } 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 launchIntent(intent); return true; @@ -1214,6 +1229,94 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS } /** + * 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_EXTRA_DATA, + intent.getStringExtra(SearchManager.EXTRA_DATA_KEY)); + + // ensure the icons will work for global search + cv.put(SearchManager.SUGGEST_COLUMN_ICON_1, + wrapIconForPackage( + source, + getColumnString(c, SearchManager.SUGGEST_COLUMN_ICON_1))); + cv.put(SearchManager.SUGGEST_COLUMN_ICON_2, + wrapIconForPackage( + source, + 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 source 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(ComponentName source, 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 { + String packageName = source.getPackageName(); + return new Uri.Builder() + .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) + .authority(packageName) + .encodedPath(icon) + .toString(); + } + } + + /** * Launches an intent. Also dismisses the search dialog if not in global search mode. */ private void launchIntent(Intent intent) { @@ -1244,7 +1347,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS } /** - * Handles SearchManager#INTENT_ACTION_CHANGE_SOURCE. + * Handles {@link SearchManager#INTENT_ACTION_CHANGE_SEARCH_SOURCE}. */ private void handleChangeSourceIntent(Intent intent) { Uri dataUri = intent.getData(); diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java index fc1481f2fa7f..3f0aa950e19c 100644 --- a/core/java/android/app/SearchManager.java +++ b/core/java/android/app/SearchManager.java @@ -1256,6 +1256,41 @@ 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> */ |