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

Commit a0ee8ad0 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Remove some dead code from search"

parents 682bb3e8 d75baf7e
Loading
Loading
Loading
Loading
+0 −213
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.android.settings.search;

import static com.android.settings.search.DatabaseResultLoader.BASE_RANKS;
import static com.android.settings.search.SearchResult.TOP_RANK;

import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.os.BadParcelableException;
import android.text.TextUtils;
import android.util.Log;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Controller to Build search results from {@link Cursor} Objects.
 *
 * Each converted {@link Cursor} has the following fields:
 * - String Title
 * - String Summary
 * - int rank
 * - {@link Drawable} icon
 * - {@link ResultPayload} payload
 */
public class CursorToSearchResultConverter {

    private static final String TAG = "CursorConverter";

    /**
     * These indices are used to match the columns of the this loader's SELECT statement.
     * These are not necessarily the same order nor similar coverage as the schema defined in
     * IndexDatabaseHelper
     */
    public static final int COLUMN_INDEX_ID = 0;
    public static final int COLUMN_INDEX_TITLE = 1;
    public static final int COLUMN_INDEX_SUMMARY_ON = 2;
    public static final int COLUMN_INDEX_SUMMARY_OFF = 3;
    public static final int COLUMN_INDEX_CLASS_NAME = 4;
    public static final int COLUMN_INDEX_SCREEN_TITLE = 5;
    public static final int COLUMN_INDEX_ICON = 6;
    public static final int COLUMN_INDEX_INTENT_ACTION = 7;
    public static final int COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE = 8;
    public static final int COLUMN_INDEX_INTENT_ACTION_TARGET_CLASS = 9;
    public static final int COLUMN_INDEX_KEY = 10;
    public static final int COLUMN_INDEX_PAYLOAD_TYPE = 11;
    public static final int COLUMN_INDEX_PAYLOAD = 12;

    private final Context mContext;

    private final int LONG_TITLE_LENGTH = 20;

    private static final String[] whiteList = {
            "main_toggle_wifi",
            "main_toggle_bluetooth",
            "main_toggle_bluetooth_obsolete",
            "toggle_airplane",
            "tether_settings",
            "battery_saver",
            "toggle_nfc",
            "restrict_background",
            "data_usage_enable",
            "button_roaming_key",
    };
    private static final Set<String> prioritySettings = new HashSet(Arrays.asList(whiteList));


    public CursorToSearchResultConverter(Context context) {
        mContext = context;
    }

    public Set<SearchResult> convertCursor(Cursor cursorResults, int baseRank) {
        if (cursorResults == null) {
            return null;
        }
        final Map<String, Context> contextMap = new HashMap<>();
        final Set<SearchResult> results = new HashSet<>();

        while (cursorResults.moveToNext()) {
            SearchResult result = buildSingleSearchResultFromCursor(contextMap, cursorResults,
                    baseRank);
            if (result != null) {
                results.add(result);
            }
        }
        return results;
    }

    public static ResultPayload getUnmarshalledPayload(byte[] marshalledPayload,
            int payloadType) {
        try {
            switch (payloadType) {
                case ResultPayload.PayloadType.INTENT:
                    return ResultPayloadUtils.unmarshall(marshalledPayload,
                            ResultPayload.CREATOR);
                case ResultPayload.PayloadType.INLINE_SWITCH:
                    return ResultPayloadUtils.unmarshall(marshalledPayload,
                            InlineSwitchPayload.CREATOR);
                case ResultPayload.PayloadType.INLINE_LIST:
                    return ResultPayloadUtils.unmarshall(marshalledPayload,
                            InlineListPayload.CREATOR);
            }
        } catch (BadParcelableException e) {
            Log.w(TAG, "Error creating parcelable: " + e);
        }
        return null;
    }

    private SearchResult buildSingleSearchResultFromCursor(Map<String, Context> contextMap,
            Cursor cursor, int baseRank) {
        final int docId = cursor.getInt(COLUMN_INDEX_ID);
        final String pkgName = cursor.getString(COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE);
        final String title = cursor.getString(COLUMN_INDEX_TITLE);
        final String summaryOn = cursor.getString(COLUMN_INDEX_SUMMARY_ON);
        final String className = cursor.getString(COLUMN_INDEX_CLASS_NAME);
        final String key = cursor.getString(COLUMN_INDEX_KEY);
        final String iconResStr = cursor.getString(COLUMN_INDEX_ICON);
        final int payloadType = cursor.getInt(COLUMN_INDEX_PAYLOAD_TYPE);
        final byte[] marshalledPayload = cursor.getBlob(COLUMN_INDEX_PAYLOAD);
        final ResultPayload payload = getUnmarshalledPayload(marshalledPayload, payloadType);

        final int rank = getRank(title, baseRank, key);

        final SearchResult.Builder builder = new SearchResult.Builder()
                .setStableId(docId)
                .setTitle(title)
                .setSummary(summaryOn)
                .setRank(rank)
                .setIcon(getIconForPackage(contextMap, pkgName, className, iconResStr))
                .setPayload(payload);
        return builder.build();
    }

    private Drawable getIconForPackage(Map<String, Context> contextMap, String pkgName,
            String className, String iconResStr) {
        final int iconId = TextUtils.isEmpty(iconResStr)
                ? 0 : Integer.parseInt(iconResStr);
        Drawable icon;
        Context packageContext;
        if (iconId == 0) {
            icon = null;
        } else {
            if (TextUtils.isEmpty(className) && !TextUtils.isEmpty(pkgName)) {
                packageContext = contextMap.get(pkgName);
                if (packageContext == null) {
                    try {
                        packageContext = mContext.createPackageContext(pkgName, 0);
                    } catch (PackageManager.NameNotFoundException e) {
                        Log.e(TAG, "Cannot create Context for package: " + pkgName);
                        return null;
                    }
                    contextMap.put(pkgName, packageContext);
                }
            } else {
                packageContext = mContext;
            }
            try {
                icon = packageContext.getDrawable(iconId);
            } catch (Resources.NotFoundException nfe) {
                icon = null;
            }
        }
        return icon;
    }


    /** Uses the breadcrumbs to determine the offset to the base rank.
     *  There are three checks
     *  A) If the result is prioritized and the highest base level
     *  B) If the query matches the highest level menu title
     *  C) If the query is longer than 20
     *
     *  If the query matches A, set it to TOP_RANK
     *  If the query matches B, the offset is 0.
     *  If the query matches C, the offset is 1

     * @param title of the result.
     * @param baseRank of the result. Lower if it's a better result.
     * @return
     */
    private int getRank(String title, int baseRank, String key) {
        // The result can only be prioritized if it is a top ranked result.
        if (prioritySettings.contains(key) && baseRank < BASE_RANKS[1]) {
            return TOP_RANK;
        }
        if (title.length() > LONG_TITLE_LENGTH) {
            return baseRank + 1;
        }
        return baseRank;
    }
}
 No newline at end of file
+3 −3
Original line number Diff line number Diff line
@@ -18,10 +18,10 @@
package com.android.settings.search;


import static com.android.settings.search.CursorToSearchResultConverter.COLUMN_INDEX_ID;
import static com.android.settings.search.CursorToSearchResultConverter
import static com.android.settings.search.DatabaseResultLoader.COLUMN_INDEX_ID;
import static com.android.settings.search.DatabaseResultLoader
        .COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE;
import static com.android.settings.search.CursorToSearchResultConverter.COLUMN_INDEX_KEY;
import static com.android.settings.search.DatabaseResultLoader.COLUMN_INDEX_KEY;
import static com.android.settings.search.DatabaseResultLoader.SELECT_COLUMNS;
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.CLASS_NAME;
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_ENTRIES;
+6 −9
Original line number Diff line number Diff line
@@ -43,14 +43,11 @@ public class DatabaseResultLoader {
    };

    /**
     * Base ranks defines the best possible rank based on what the query matches.
     * If the query matches the prefix of the first word in the title, the best rank it can be
     * is 1
     * If the query matches the prefix of the other words in the title, the best rank it can be
     * is 3
     * If the query only matches the summary, the best rank it can be is 7
     * If the query only matches keywords or entries, the best rank it can be is 9
     * These indices are used to match the columns of the this loader's SELECT statement.
     * These are not necessarily the same order nor similar coverage as the schema defined in
     * IndexDatabaseHelper
     */
    public static final int[] BASE_RANKS = {1, 3, 7, 9};

    public static final int COLUMN_INDEX_ID = 0;
    public static final int COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE = 8;
    public static final int COLUMN_INDEX_KEY = 10;
}
 No newline at end of file
+0 −186
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.android.settings.search;

import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.Log;

import java.util.List;

/**
 * Data class as an interface for all Search Results.
 */
public class SearchResult implements Comparable<SearchResult> {

    private static final String TAG = "SearchResult";

    /**
     * Defines the lowest rank for a search result to be considered as ranked. Results with ranks
     * higher than this have no guarantee for sorting order.
     */
    public static final int BOTTOM_RANK = 10;

    /**
     * Defines the highest rank for a search result. Used for special search results only.
     */
    public static final int TOP_RANK = 0;

    /**
     * The title of the result and main text displayed.
     * Intent Results: Displays as the primary
     */
    public final CharSequence title;

    /**
     * Summary / subtitle text
     * Intent Results: Displays the text underneath the title
     */
    final public CharSequence summary;

    /**
     * An ordered list of the information hierarchy.
     * Intent Results: Displayed a hierarchy of selections to reach the setting from the home screen
     */
    public final List<String> breadcrumbs;

    /**
     * A suggestion for the ranking of the result.
     * Based on Settings Rank:
     * 1 is a near perfect match
     * 9 is the weakest match
     * TODO subject to change
     */
    public final int rank;

    /**
     * Identifier for the recycler view adapter.
     */
    @ResultPayload.PayloadType
    public final int viewType;

    /**
     * Metadata for the specific result types.
     */
    public final ResultPayload payload;

    /**
     * Result's icon.
     */
    public final Drawable icon;

    /**
     * Stable id for this object.
     */
    public final int stableId;

    protected SearchResult(Builder builder) {
        stableId = builder.mStableId;
        title = builder.mTitle;
        summary = builder.mSummary;
        breadcrumbs = builder.mBreadcrumbs;
        rank = builder.mRank;
        icon = builder.mIcon;
        payload = builder.mResultPayload;
        viewType = payload.getType();
    }

    @Override
    public int compareTo(SearchResult searchResult) {
        if (searchResult == null) {
            return -1;
        }
        return this.rank - searchResult.rank;
    }

    @Override
    public boolean equals(Object that) {
        if (this == that) {
            return true;
        }
        if (!(that instanceof SearchResult)) {
            return false;
        }
        return this.stableId == ((SearchResult) that).stableId;
    }

    @Override
    public int hashCode() {
        return stableId;
    }

    public static class Builder {
        protected CharSequence mTitle;
        protected CharSequence mSummary;
        protected List<String> mBreadcrumbs;
        protected int mRank = 42;
        protected ResultPayload mResultPayload;
        protected Drawable mIcon;
        protected int mStableId;

        public Builder setTitle(CharSequence title) {
            mTitle = title;
            return this;
        }

        public Builder setSummary(CharSequence summary) {
            mSummary = summary;
            return this;
        }

        public Builder addBreadcrumbs(List<String> breadcrumbs) {
            mBreadcrumbs = breadcrumbs;
            return this;
        }

        public Builder setRank(int rank) {
            if (rank >= 0 && rank <= 9) {
                mRank = rank;
            }
            return this;
        }

        public Builder setIcon(Drawable icon) {
            mIcon = icon;
            return this;
        }

        public Builder setPayload(ResultPayload payload) {
            mResultPayload = payload;
            return this;
        }

        public Builder setStableId(int stableId) {
            mStableId = stableId;
            return this;
        }

        public SearchResult build() {
            // Check that all of the mandatory fields are set.
            if (TextUtils.isEmpty(mTitle)) {
                throw new IllegalStateException("SearchResult missing title argument");
            } else if (mStableId == 0) {
                Log.v(TAG, "No stable ID on SearchResult with title: " + mTitle);
                throw new IllegalStateException("SearchResult missing stableId argument");
            } else if (mResultPayload == null) {
                throw new IllegalStateException("SearchResult missing Payload argument");
            }
            return new SearchResult(this);
        }
    }
}
 No newline at end of file
+0 −347

File deleted.

Preview size limit exceeded, changes collapsed.

Loading