Loading src/com/android/settings/search/AccessibilityServiceResultLoader.java +89 −82 Original line number Diff line number Diff line Loading @@ -30,24 +30,36 @@ import android.os.UserHandle; import android.support.annotation.VisibleForTesting; import android.support.v4.content.ContextCompat; import android.util.IconDrawableFactory; import android.util.Log; import android.view.accessibility.AccessibilityManager; import com.android.settings.R; import com.android.settings.accessibility.AccessibilitySettings; import com.android.settings.dashboard.SiteMapManager; import com.android.settings.utils.AsyncLoader; import java.util.HashSet; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; public class AccessibilityServiceResultLoader extends AsyncLoader<Set<? extends SearchResult>> { public class AccessibilityServiceResultLoader extends FutureTask<List<? extends SearchResult>> { private static final String TAG = "A11yResultFutureTask"; public AccessibilityServiceResultLoader(Context context, String query, SiteMapManager manager) { super(new AccessibilityServiceResultCallable(context, query, manager)); } static class AccessibilityServiceResultCallable implements Callable<List<? extends SearchResult>> { private static final int NAME_NO_MATCH = -1; private final Context mContext; private List<String> mBreadcrumb; private SiteMapManager mSiteMapManager; @VisibleForTesting Loading @@ -56,12 +68,10 @@ public class AccessibilityServiceResultLoader extends AsyncLoader<Set<? extends private final PackageManager mPackageManager; private final int mUserId; public AccessibilityServiceResultLoader(Context context, String query, public AccessibilityServiceResultCallable(Context context, String query, SiteMapManager mapManager) { super(context); mContext = context; mUserId = UserHandle.myUserId(); mContext = context; mSiteMapManager = mapManager; mPackageManager = context.getPackageManager(); mAccessibilityManager = Loading @@ -70,13 +80,13 @@ public class AccessibilityServiceResultLoader extends AsyncLoader<Set<? extends } @Override public Set<? extends SearchResult> loadInBackground() { final Set<SearchResult> results = new HashSet<>(); final Context context = getContext(); public List<? extends SearchResult> call() throws Exception { long startTime = System.currentTimeMillis(); final List<SearchResult> results = new ArrayList<>(); final List<AccessibilityServiceInfo> services = mAccessibilityManager .getInstalledAccessibilityServiceList(); final IconDrawableFactory iconFactory = IconDrawableFactory.newInstance(mContext); final String screenTitle = context.getString(R.string.accessibility_settings); final String screenTitle = mContext.getString(R.string.accessibility_settings); for (AccessibilityServiceInfo service : services) { if (service == null) { continue; Loading @@ -93,7 +103,7 @@ public class AccessibilityServiceResultLoader extends AsyncLoader<Set<? extends } final Drawable icon; if (resolveInfo.getIconResource() == 0) { icon = ContextCompat.getDrawable(context, R.mipmap.ic_accessibility_generic); icon = ContextCompat.getDrawable(mContext, R.mipmap.ic_accessibility_generic); } else { icon = iconFactory.getBadgedIcon( resolveInfo.serviceInfo, Loading @@ -102,7 +112,7 @@ public class AccessibilityServiceResultLoader extends AsyncLoader<Set<? extends } final String componentName = new ComponentName(serviceInfo.packageName, serviceInfo.name).flattenToString(); final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(context, final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(mContext, AccessibilitySettings.class.getName(), componentName, screenTitle); results.add(new SearchResult.Builder() Loading @@ -114,21 +124,18 @@ public class AccessibilityServiceResultLoader extends AsyncLoader<Set<? extends .setStableId(Objects.hash(screenTitle, componentName)) .build()); } Collections.sort(results); Log.i(TAG, "A11y search loading took:" + (System.currentTimeMillis() - startTime)); return results; } private List<String> getBreadCrumb() { if (mBreadcrumb == null || mBreadcrumb.isEmpty()) { final Context context = getContext(); mBreadcrumb = mSiteMapManager.buildBreadCrumb( context, AccessibilitySettings.class.getName(), context.getString(R.string.accessibility_settings)); mContext, AccessibilitySettings.class.getName(), mContext.getString(R.string.accessibility_settings)); } return mBreadcrumb; } @Override protected void onDiscardResult(Set<? extends SearchResult> result) { } } src/com/android/settings/search/CursorToSearchResultConverter.java +19 −10 Original line number Diff line number Diff line Loading @@ -36,16 +36,6 @@ import java.util.Map; import java.util.Set; import static com.android.settings.search.DatabaseResultLoader.BASE_RANKS; import static com.android.settings.search.DatabaseResultLoader.COLUMN_INDEX_CLASS_NAME; import static com.android.settings.search.DatabaseResultLoader.COLUMN_INDEX_ICON; 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.DatabaseResultLoader.COLUMN_INDEX_KEY; import static com.android.settings.search.DatabaseResultLoader.COLUMN_INDEX_PAYLOAD; import static com.android.settings.search.DatabaseResultLoader.COLUMN_INDEX_PAYLOAD_TYPE; import static com.android.settings.search.DatabaseResultLoader.COLUMN_INDEX_SCREEN_TITLE; import static com.android.settings.search.DatabaseResultLoader.COLUMN_INDEX_SUMMARY_ON; import static com.android.settings.search.DatabaseResultLoader.COLUMN_INDEX_TITLE; import static com.android.settings.search.SearchResult.TOP_RANK; /** Loading @@ -62,6 +52,25 @@ 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; Loading src/com/android/settings/search/DatabaseIndexingManager.java +5 −4 Original line number Diff line number Diff line Loading @@ -17,11 +17,13 @@ package com.android.settings.search; import static com.android.settings.search.DatabaseResultLoader.COLUMN_INDEX_ID; import static com.android.settings.search.DatabaseResultLoader import static com.android.settings.search.CursorToSearchResultConverter.COLUMN_INDEX_ID; import static com.android.settings.search.CursorToSearchResultConverter .COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE; import static com.android.settings.search.DatabaseResultLoader.COLUMN_INDEX_KEY; import static com.android.settings.search.CursorToSearchResultConverter.COLUMN_INDEX_KEY; import static com.android.settings.search.DatabaseResultLoader.SELECT_COLUMNS; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DOCID; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.CLASS_NAME; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_ENTRIES; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS; Loading @@ -31,7 +33,6 @@ import static com.android.settings.search.IndexDatabaseHelper.IndexColumns .DATA_SUMMARY_ON_NORMALIZED; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_TITLE; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_TITLE_NORMALIZED; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DOCID; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.ENABLED; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.ICON; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.INTENT_ACTION; Loading src/com/android/settings/search/DatabaseResultLoader.java +247 −178 Original line number Diff line number Diff line Loading @@ -24,35 +24,31 @@ import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.support.annotation.VisibleForTesting; import android.util.Log; import android.util.Pair; import com.android.settings.dashboard.SiteMapManager; import com.android.settings.utils.AsyncLoader; import com.android.settings.overlay.FeatureFactory; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.TreeSet; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** * AsyncTask to retrieve Settings, First party app and any intent based results. * AsyncTask to retrieve Settings, first party app and any intent based results. */ public class DatabaseResultLoader extends AsyncLoader<Set<? extends SearchResult>> { private static final String LOG = "DatabaseResultLoader"; /* 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; public class DatabaseResultLoader extends FutureTask<List<? extends SearchResult>> { private static final String TAG = "DatabaseResultLoader"; public static final String[] SELECT_COLUMNS = { IndexColumns.DOCID, Loading Loading @@ -82,62 +78,92 @@ public class DatabaseResultLoader extends AsyncLoader<Set<? extends SearchResult IndexColumns.DATA_SUMMARY_OFF_NORMALIZED, }; public static final String[] MATCH_COLUMNS_TERTIARY = { IndexColumns.DATA_KEYWORDS, IndexColumns.DATA_ENTRIES }; /** * 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 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 */ public static final int[] BASE_RANKS = {1, 3, 7, 9}; public DatabaseResultLoader(Context context, String query, SiteMapManager manager) { super(new StaticSearchResultCallable(context, query, manager)); } static class StaticSearchResultCallable implements Callable<List<? extends SearchResult>> { public final String[] MATCH_COLUMNS_TERTIARY = { IndexColumns.DATA_KEYWORDS, IndexColumns.DATA_ENTRIES }; @VisibleForTesting final String mQueryText; private final Context mContext; private final CursorToSearchResultConverter mConverter; private final SiteMapManager mSiteMapManager; private final SearchFeatureProvider mFeatureProvider; public DatabaseResultLoader(Context context, String queryText, SiteMapManager mapManager) { super(context); mSiteMapManager = mapManager; public StaticSearchResultCallable(Context context, String queryText, SiteMapManager mapManager) { mContext = context; mSiteMapManager = mapManager; mQueryText = queryText; mConverter = new CursorToSearchResultConverter(context); mFeatureProvider = FeatureFactory.getFactory(context).getSearchFeatureProvider(); } @Override protected void onDiscardResult(Set<? extends SearchResult> result) { // TODO Search } @Override public Set<? extends SearchResult> loadInBackground() { public List<? extends SearchResult> call() { if (mQueryText == null || mQueryText.isEmpty()) { return null; return new ArrayList<>(); } final Set<SearchResult> results = new HashSet<>(); // TODO (b/68656233) Consolidate timing metrics long startTime = System.currentTimeMillis(); // Start a Future to get search result scores. FutureTask<List<Pair<String, Float>>> rankerTask = mFeatureProvider.getRankerTask( mContext, mQueryText); results.addAll(firstWordQuery(MATCH_COLUMNS_PRIMARY, BASE_RANKS[0])); results.addAll(secondaryWordQuery(MATCH_COLUMNS_PRIMARY, BASE_RANKS[1])); results.addAll(anyWordQuery(MATCH_COLUMNS_SECONDARY, BASE_RANKS[2])); results.addAll(anyWordQuery(MATCH_COLUMNS_TERTIARY, BASE_RANKS[3])); return results; if (rankerTask != null) { ExecutorService executorService = mFeatureProvider.getExecutorService(); executorService.execute(rankerTask); } @Override protected boolean onCancelLoad() { // TODO return super.onCancelLoad(); final Set<SearchResult> resultSet = new HashSet<>(); resultSet.addAll(firstWordQuery(MATCH_COLUMNS_PRIMARY, BASE_RANKS[0])); resultSet.addAll(secondaryWordQuery(MATCH_COLUMNS_PRIMARY, BASE_RANKS[1])); resultSet.addAll(anyWordQuery(MATCH_COLUMNS_SECONDARY, BASE_RANKS[2])); resultSet.addAll(anyWordQuery(MATCH_COLUMNS_TERTIARY, BASE_RANKS[3])); // Try to retrieve the scores in time. Otherwise use static ranking. if (rankerTask != null) { try { final long timeoutMs = mFeatureProvider.smartSearchRankingTimeoutMs(mContext); List<Pair<String, Float>> searchRankScores = rankerTask.get(timeoutMs, TimeUnit.MILLISECONDS); return getDynamicRankedResults(resultSet, searchRankScores); } catch (TimeoutException | InterruptedException | ExecutionException e) { Log.d(TAG, "Error waiting for result scores: " + e); } } List<SearchResult> resultList = new ArrayList<>(resultSet); Collections.sort(resultList); Log.i(TAG, "Static search loading took:" + (System.currentTimeMillis() - startTime)); return resultList; } // TODO (b/33577327) Retrieve all search results with a single query. /** * Creates and executes the query which matches prefixes of the first word of the given columns. * Creates and executes the query which matches prefixes of the first word of the given * columns. * * @param matchColumns The columns to match on * @param baseRank The highest rank achievable by these results Loading Loading @@ -168,7 +194,8 @@ public class DatabaseResultLoader extends AsyncLoader<Set<? extends SearchResult } /** * Creates and executes the query which matches prefixes of the any word of the given columns. * Creates and executes the query which matches prefixes of the any word of the given * columns. * * @param matchColumns The columns to match on * @param baseRank The highest rank achievable by these results Loading @@ -192,7 +219,8 @@ public class DatabaseResultLoader extends AsyncLoader<Set<? extends SearchResult private Set<SearchResult> query(String whereClause, String[] selection, int baseRank) { final SQLiteDatabase database = IndexDatabaseHelper.getInstance(mContext).getReadableDatabase(); try (Cursor resultCursor = database.query(TABLE_PREFS_INDEX, SELECT_COLUMNS, whereClause, try (Cursor resultCursor = database.query(TABLE_PREFS_INDEX, SELECT_COLUMNS, whereClause, selection, null, null, null)) { return mConverter.convertCursor(mSiteMapManager, resultCursor, baseRank); } Loading Loading @@ -257,7 +285,8 @@ public class DatabaseResultLoader extends AsyncLoader<Set<? extends SearchResult /** * Fills out the selection array to match the query as the prefix of a word. * * @param size is twice the number of columns to be matched. The first match is for the prefix * @param size is twice the number of columns to be matched. The first match is for the * prefix * of the first word in the column. The second match is for any subsequent word * prefix match. */ Loading @@ -272,4 +301,44 @@ public class DatabaseResultLoader extends AsyncLoader<Set<? extends SearchResult } return selection; } private List<SearchResult> getDynamicRankedResults(Set<SearchResult> unsortedSet, List<Pair<String, Float>> searchRankScores) { TreeSet<SearchResult> dbResultsSortedByScores = new TreeSet<>( (o1, o2) -> { float score1 = getRankingScoreByStableId(searchRankScores, o1.stableId); float score2 = getRankingScoreByStableId(searchRankScores, o2.stableId); if (score1 > score2) { return -1; } else if (score1 == score2) { return 0; } else { return 1; } }); dbResultsSortedByScores.addAll(unsortedSet); return new ArrayList<>(dbResultsSortedByScores); } /** * Looks up ranking score for stableId * * @param stableId String of stableId * @return the ranking score corresponding to the given stableId. If there is no score * available for this stableId, -Float.MAX_VALUE is returned. */ @VisibleForTesting Float getRankingScoreByStableId(List<Pair<String, Float>> searchRankScores, int stableId) { for (Pair<String, Float> rankingScore : searchRankScores) { if (Integer.toString(stableId).compareTo(rankingScore.first) == 0) { return rankingScore.second; } } // If stableId not found in the list, we assign the minimum score so it will appear at // the end of the list. Log.w(TAG, "stableId " + stableId + " was not in the ranking scores."); return -Float.MAX_VALUE; } } } No newline at end of file src/com/android/settings/search/InputDeviceResultLoader.java +133 −122 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
src/com/android/settings/search/AccessibilityServiceResultLoader.java +89 −82 Original line number Diff line number Diff line Loading @@ -30,24 +30,36 @@ import android.os.UserHandle; import android.support.annotation.VisibleForTesting; import android.support.v4.content.ContextCompat; import android.util.IconDrawableFactory; import android.util.Log; import android.view.accessibility.AccessibilityManager; import com.android.settings.R; import com.android.settings.accessibility.AccessibilitySettings; import com.android.settings.dashboard.SiteMapManager; import com.android.settings.utils.AsyncLoader; import java.util.HashSet; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; public class AccessibilityServiceResultLoader extends AsyncLoader<Set<? extends SearchResult>> { public class AccessibilityServiceResultLoader extends FutureTask<List<? extends SearchResult>> { private static final String TAG = "A11yResultFutureTask"; public AccessibilityServiceResultLoader(Context context, String query, SiteMapManager manager) { super(new AccessibilityServiceResultCallable(context, query, manager)); } static class AccessibilityServiceResultCallable implements Callable<List<? extends SearchResult>> { private static final int NAME_NO_MATCH = -1; private final Context mContext; private List<String> mBreadcrumb; private SiteMapManager mSiteMapManager; @VisibleForTesting Loading @@ -56,12 +68,10 @@ public class AccessibilityServiceResultLoader extends AsyncLoader<Set<? extends private final PackageManager mPackageManager; private final int mUserId; public AccessibilityServiceResultLoader(Context context, String query, public AccessibilityServiceResultCallable(Context context, String query, SiteMapManager mapManager) { super(context); mContext = context; mUserId = UserHandle.myUserId(); mContext = context; mSiteMapManager = mapManager; mPackageManager = context.getPackageManager(); mAccessibilityManager = Loading @@ -70,13 +80,13 @@ public class AccessibilityServiceResultLoader extends AsyncLoader<Set<? extends } @Override public Set<? extends SearchResult> loadInBackground() { final Set<SearchResult> results = new HashSet<>(); final Context context = getContext(); public List<? extends SearchResult> call() throws Exception { long startTime = System.currentTimeMillis(); final List<SearchResult> results = new ArrayList<>(); final List<AccessibilityServiceInfo> services = mAccessibilityManager .getInstalledAccessibilityServiceList(); final IconDrawableFactory iconFactory = IconDrawableFactory.newInstance(mContext); final String screenTitle = context.getString(R.string.accessibility_settings); final String screenTitle = mContext.getString(R.string.accessibility_settings); for (AccessibilityServiceInfo service : services) { if (service == null) { continue; Loading @@ -93,7 +103,7 @@ public class AccessibilityServiceResultLoader extends AsyncLoader<Set<? extends } final Drawable icon; if (resolveInfo.getIconResource() == 0) { icon = ContextCompat.getDrawable(context, R.mipmap.ic_accessibility_generic); icon = ContextCompat.getDrawable(mContext, R.mipmap.ic_accessibility_generic); } else { icon = iconFactory.getBadgedIcon( resolveInfo.serviceInfo, Loading @@ -102,7 +112,7 @@ public class AccessibilityServiceResultLoader extends AsyncLoader<Set<? extends } final String componentName = new ComponentName(serviceInfo.packageName, serviceInfo.name).flattenToString(); final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(context, final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(mContext, AccessibilitySettings.class.getName(), componentName, screenTitle); results.add(new SearchResult.Builder() Loading @@ -114,21 +124,18 @@ public class AccessibilityServiceResultLoader extends AsyncLoader<Set<? extends .setStableId(Objects.hash(screenTitle, componentName)) .build()); } Collections.sort(results); Log.i(TAG, "A11y search loading took:" + (System.currentTimeMillis() - startTime)); return results; } private List<String> getBreadCrumb() { if (mBreadcrumb == null || mBreadcrumb.isEmpty()) { final Context context = getContext(); mBreadcrumb = mSiteMapManager.buildBreadCrumb( context, AccessibilitySettings.class.getName(), context.getString(R.string.accessibility_settings)); mContext, AccessibilitySettings.class.getName(), mContext.getString(R.string.accessibility_settings)); } return mBreadcrumb; } @Override protected void onDiscardResult(Set<? extends SearchResult> result) { } }
src/com/android/settings/search/CursorToSearchResultConverter.java +19 −10 Original line number Diff line number Diff line Loading @@ -36,16 +36,6 @@ import java.util.Map; import java.util.Set; import static com.android.settings.search.DatabaseResultLoader.BASE_RANKS; import static com.android.settings.search.DatabaseResultLoader.COLUMN_INDEX_CLASS_NAME; import static com.android.settings.search.DatabaseResultLoader.COLUMN_INDEX_ICON; 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.DatabaseResultLoader.COLUMN_INDEX_KEY; import static com.android.settings.search.DatabaseResultLoader.COLUMN_INDEX_PAYLOAD; import static com.android.settings.search.DatabaseResultLoader.COLUMN_INDEX_PAYLOAD_TYPE; import static com.android.settings.search.DatabaseResultLoader.COLUMN_INDEX_SCREEN_TITLE; import static com.android.settings.search.DatabaseResultLoader.COLUMN_INDEX_SUMMARY_ON; import static com.android.settings.search.DatabaseResultLoader.COLUMN_INDEX_TITLE; import static com.android.settings.search.SearchResult.TOP_RANK; /** Loading @@ -62,6 +52,25 @@ 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; Loading
src/com/android/settings/search/DatabaseIndexingManager.java +5 −4 Original line number Diff line number Diff line Loading @@ -17,11 +17,13 @@ package com.android.settings.search; import static com.android.settings.search.DatabaseResultLoader.COLUMN_INDEX_ID; import static com.android.settings.search.DatabaseResultLoader import static com.android.settings.search.CursorToSearchResultConverter.COLUMN_INDEX_ID; import static com.android.settings.search.CursorToSearchResultConverter .COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE; import static com.android.settings.search.DatabaseResultLoader.COLUMN_INDEX_KEY; import static com.android.settings.search.CursorToSearchResultConverter.COLUMN_INDEX_KEY; import static com.android.settings.search.DatabaseResultLoader.SELECT_COLUMNS; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DOCID; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.CLASS_NAME; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_ENTRIES; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS; Loading @@ -31,7 +33,6 @@ import static com.android.settings.search.IndexDatabaseHelper.IndexColumns .DATA_SUMMARY_ON_NORMALIZED; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_TITLE; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DATA_TITLE_NORMALIZED; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.DOCID; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.ENABLED; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.ICON; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.INTENT_ACTION; Loading
src/com/android/settings/search/DatabaseResultLoader.java +247 −178 Original line number Diff line number Diff line Loading @@ -24,35 +24,31 @@ import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.support.annotation.VisibleForTesting; import android.util.Log; import android.util.Pair; import com.android.settings.dashboard.SiteMapManager; import com.android.settings.utils.AsyncLoader; import com.android.settings.overlay.FeatureFactory; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.TreeSet; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** * AsyncTask to retrieve Settings, First party app and any intent based results. * AsyncTask to retrieve Settings, first party app and any intent based results. */ public class DatabaseResultLoader extends AsyncLoader<Set<? extends SearchResult>> { private static final String LOG = "DatabaseResultLoader"; /* 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; public class DatabaseResultLoader extends FutureTask<List<? extends SearchResult>> { private static final String TAG = "DatabaseResultLoader"; public static final String[] SELECT_COLUMNS = { IndexColumns.DOCID, Loading Loading @@ -82,62 +78,92 @@ public class DatabaseResultLoader extends AsyncLoader<Set<? extends SearchResult IndexColumns.DATA_SUMMARY_OFF_NORMALIZED, }; public static final String[] MATCH_COLUMNS_TERTIARY = { IndexColumns.DATA_KEYWORDS, IndexColumns.DATA_ENTRIES }; /** * 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 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 */ public static final int[] BASE_RANKS = {1, 3, 7, 9}; public DatabaseResultLoader(Context context, String query, SiteMapManager manager) { super(new StaticSearchResultCallable(context, query, manager)); } static class StaticSearchResultCallable implements Callable<List<? extends SearchResult>> { public final String[] MATCH_COLUMNS_TERTIARY = { IndexColumns.DATA_KEYWORDS, IndexColumns.DATA_ENTRIES }; @VisibleForTesting final String mQueryText; private final Context mContext; private final CursorToSearchResultConverter mConverter; private final SiteMapManager mSiteMapManager; private final SearchFeatureProvider mFeatureProvider; public DatabaseResultLoader(Context context, String queryText, SiteMapManager mapManager) { super(context); mSiteMapManager = mapManager; public StaticSearchResultCallable(Context context, String queryText, SiteMapManager mapManager) { mContext = context; mSiteMapManager = mapManager; mQueryText = queryText; mConverter = new CursorToSearchResultConverter(context); mFeatureProvider = FeatureFactory.getFactory(context).getSearchFeatureProvider(); } @Override protected void onDiscardResult(Set<? extends SearchResult> result) { // TODO Search } @Override public Set<? extends SearchResult> loadInBackground() { public List<? extends SearchResult> call() { if (mQueryText == null || mQueryText.isEmpty()) { return null; return new ArrayList<>(); } final Set<SearchResult> results = new HashSet<>(); // TODO (b/68656233) Consolidate timing metrics long startTime = System.currentTimeMillis(); // Start a Future to get search result scores. FutureTask<List<Pair<String, Float>>> rankerTask = mFeatureProvider.getRankerTask( mContext, mQueryText); results.addAll(firstWordQuery(MATCH_COLUMNS_PRIMARY, BASE_RANKS[0])); results.addAll(secondaryWordQuery(MATCH_COLUMNS_PRIMARY, BASE_RANKS[1])); results.addAll(anyWordQuery(MATCH_COLUMNS_SECONDARY, BASE_RANKS[2])); results.addAll(anyWordQuery(MATCH_COLUMNS_TERTIARY, BASE_RANKS[3])); return results; if (rankerTask != null) { ExecutorService executorService = mFeatureProvider.getExecutorService(); executorService.execute(rankerTask); } @Override protected boolean onCancelLoad() { // TODO return super.onCancelLoad(); final Set<SearchResult> resultSet = new HashSet<>(); resultSet.addAll(firstWordQuery(MATCH_COLUMNS_PRIMARY, BASE_RANKS[0])); resultSet.addAll(secondaryWordQuery(MATCH_COLUMNS_PRIMARY, BASE_RANKS[1])); resultSet.addAll(anyWordQuery(MATCH_COLUMNS_SECONDARY, BASE_RANKS[2])); resultSet.addAll(anyWordQuery(MATCH_COLUMNS_TERTIARY, BASE_RANKS[3])); // Try to retrieve the scores in time. Otherwise use static ranking. if (rankerTask != null) { try { final long timeoutMs = mFeatureProvider.smartSearchRankingTimeoutMs(mContext); List<Pair<String, Float>> searchRankScores = rankerTask.get(timeoutMs, TimeUnit.MILLISECONDS); return getDynamicRankedResults(resultSet, searchRankScores); } catch (TimeoutException | InterruptedException | ExecutionException e) { Log.d(TAG, "Error waiting for result scores: " + e); } } List<SearchResult> resultList = new ArrayList<>(resultSet); Collections.sort(resultList); Log.i(TAG, "Static search loading took:" + (System.currentTimeMillis() - startTime)); return resultList; } // TODO (b/33577327) Retrieve all search results with a single query. /** * Creates and executes the query which matches prefixes of the first word of the given columns. * Creates and executes the query which matches prefixes of the first word of the given * columns. * * @param matchColumns The columns to match on * @param baseRank The highest rank achievable by these results Loading Loading @@ -168,7 +194,8 @@ public class DatabaseResultLoader extends AsyncLoader<Set<? extends SearchResult } /** * Creates and executes the query which matches prefixes of the any word of the given columns. * Creates and executes the query which matches prefixes of the any word of the given * columns. * * @param matchColumns The columns to match on * @param baseRank The highest rank achievable by these results Loading @@ -192,7 +219,8 @@ public class DatabaseResultLoader extends AsyncLoader<Set<? extends SearchResult private Set<SearchResult> query(String whereClause, String[] selection, int baseRank) { final SQLiteDatabase database = IndexDatabaseHelper.getInstance(mContext).getReadableDatabase(); try (Cursor resultCursor = database.query(TABLE_PREFS_INDEX, SELECT_COLUMNS, whereClause, try (Cursor resultCursor = database.query(TABLE_PREFS_INDEX, SELECT_COLUMNS, whereClause, selection, null, null, null)) { return mConverter.convertCursor(mSiteMapManager, resultCursor, baseRank); } Loading Loading @@ -257,7 +285,8 @@ public class DatabaseResultLoader extends AsyncLoader<Set<? extends SearchResult /** * Fills out the selection array to match the query as the prefix of a word. * * @param size is twice the number of columns to be matched. The first match is for the prefix * @param size is twice the number of columns to be matched. The first match is for the * prefix * of the first word in the column. The second match is for any subsequent word * prefix match. */ Loading @@ -272,4 +301,44 @@ public class DatabaseResultLoader extends AsyncLoader<Set<? extends SearchResult } return selection; } private List<SearchResult> getDynamicRankedResults(Set<SearchResult> unsortedSet, List<Pair<String, Float>> searchRankScores) { TreeSet<SearchResult> dbResultsSortedByScores = new TreeSet<>( (o1, o2) -> { float score1 = getRankingScoreByStableId(searchRankScores, o1.stableId); float score2 = getRankingScoreByStableId(searchRankScores, o2.stableId); if (score1 > score2) { return -1; } else if (score1 == score2) { return 0; } else { return 1; } }); dbResultsSortedByScores.addAll(unsortedSet); return new ArrayList<>(dbResultsSortedByScores); } /** * Looks up ranking score for stableId * * @param stableId String of stableId * @return the ranking score corresponding to the given stableId. If there is no score * available for this stableId, -Float.MAX_VALUE is returned. */ @VisibleForTesting Float getRankingScoreByStableId(List<Pair<String, Float>> searchRankScores, int stableId) { for (Pair<String, Float> rankingScore : searchRankScores) { if (Integer.toString(stableId).compareTo(rankingScore.first) == 0) { return rankingScore.second; } } // If stableId not found in the list, we assign the minimum score so it will appear at // the end of the list. Log.w(TAG, "stableId " + stableId + " was not in the ranking scores."); return -Float.MAX_VALUE; } } } No newline at end of file
src/com/android/settings/search/InputDeviceResultLoader.java +133 −122 File changed.Preview size limit exceeded, changes collapsed. Show changes