Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9d19fdb2 authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change 3576 into donut

* changes:
  Track clicks that occur after pivoting into an app from global search.
parents 4ab3c009 d4c98c4c
Loading
Loading
Loading
Loading
+106 −3
Original line number Diff line number Diff line
@@ -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)) {

            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
            Intent intent = createIntentFromSuggestion(c, actionKey, actionMsg);
            launchIntent(intent);

            return true;
@@ -1213,6 +1228,94 @@ 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_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.
     */
@@ -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();
+35 −0
Original line number Diff line number Diff line
@@ -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>
     */