Create whitelist for the most popular settings

As a temporary solution to getting the most popular
settings to be the top rank, we have created a white list.
If a prioritized setting shows up somewhere in the results
then it will be given an elevated rank to be at the top.

Bug: 35048659
Test: make RunSettingsRoboTests
Change-Id: I92b563a17b42d8f91d980dd1d8e5f8f29ca5aa9c
This commit is contained in:
Matthew Fritze
2017-02-14 13:57:08 -08:00
parent bdaf7572d9
commit b759516cbf
7 changed files with 322 additions and 14 deletions

View File

@@ -99,6 +99,8 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem
private final IntentFilter mIntentFilter; private final IntentFilter mIntentFilter;
// For Search
private static final String DATA_KEY_REFERENCE = "main_toggle_bluetooth";
// accessed from inner class (not private to avoid thunks) // accessed from inner class (not private to avoid thunks)
FooterPreference mMyDevicePreference; FooterPreference mMyDevicePreference;
@@ -567,6 +569,7 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem
SearchIndexableRaw data = new SearchIndexableRaw(context); SearchIndexableRaw data = new SearchIndexableRaw(context);
data.title = res.getString(R.string.bluetooth_settings); data.title = res.getString(R.string.bluetooth_settings);
data.screenTitle = res.getString(R.string.bluetooth_settings); data.screenTitle = res.getString(R.string.bluetooth_settings);
data.key = DATA_KEY_REFERENCE;
result.add(data); result.add(data);
// Add cached paired BT devices // Add cached paired BT devices

View File

@@ -35,6 +35,7 @@ import com.android.settings.Utils;
import com.android.settings.dashboard.SiteMapManager; import com.android.settings.dashboard.SiteMapManager;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@@ -77,6 +78,22 @@ class CursorToSearchResultConverter {
private final Set<String> mKeys; private final Set<String> mKeys;
private final int LONG_TITLE_LENGTH = 20;
private static final String[] whiteList = {
"main_toggle_wifi",
"main_toggle_bluetooth",
"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, String queryText) { public CursorToSearchResultConverter(Context context, String queryText) {
mContext = context; mContext = context;
mKeys = new HashSet<>(); mKeys = new HashSet<>();
@@ -135,7 +152,7 @@ class CursorToSearchResultConverter {
} }
final List<String> breadcrumbs = getBreadcrumbs(sitemapManager, cursor); final List<String> breadcrumbs = getBreadcrumbs(sitemapManager, cursor);
final int rank = getRank(breadcrumbs, baseRank); final int rank = getRank(title, breadcrumbs, baseRank, key);
final SearchResult.Builder builder = new SearchResult.Builder(); final SearchResult.Builder builder = new SearchResult.Builder();
builder.addTitle(title) builder.addTitle(title)
@@ -225,18 +242,32 @@ class CursorToSearchResultConverter {
} }
/** Uses the breadcrumbs to determine the offset to the base rank. /** Uses the breadcrumbs to determine the offset to the base rank.
* There are two checks * There are three checks
* A) If the query matches the highest level menu title * A) If the result is prioritized and the highest base level
* B) If the query matches a subsequent menu title * B) If the query matches the highest level menu title
* C) If the query matches a subsequent menu title
* D) Is the title longer than 20
* *
* If the query matches A and B, the offset is 0. * If the query matches A, set it to TOP_RANK
* If the query matches A only, the offset is 1. * If the query matches B and C, the offset is 0.
* If the query matches neither A nor B, the offset is 2. * If the query matches C only, the offset is 1.
* If the query matches neither B nor C, the offset is 2.
* If the query matches D, the offset is 2
* @param title of the result.
* @param crumbs from the Information Architecture * @param crumbs from the Information Architecture
* @param baseRank of the result. Lower if it's a better result. * @param baseRank of the result. Lower if it's a better result.
* @return * @return
*/ */
private int getRank(List<String> crumbs, int baseRank) { private int getRank(String title, List<String> crumbs, int baseRank, String key) {
// The result can only be prioritized if it is a top ranked result.
if (prioritySettings.contains(key) && baseRank < DatabaseResultLoader.BASE_RANKS[1]) {
return SearchResult.TOP_RANK;
}
if (title.length() > LONG_TITLE_LENGTH) {
return baseRank + 2;
}
return baseRank; return baseRank;
} }
} }

View File

@@ -97,7 +97,7 @@ public class DatabaseResultLoader extends AsyncLoader<List<? extends SearchResul
* If the query only matches keywords or entries, the best rank it can be is 9 * If the query only matches keywords or entries, the best rank it can be is 9
* *
*/ */
private static final int[] BASE_RANKS = {1, 3, 7, 9}; public static final int[] BASE_RANKS = {1, 3, 7, 9};
private final String mQueryText; private final String mQueryText;
private final Context mContext; private final Context mContext;

View File

@@ -27,10 +27,15 @@ import java.util.Objects;
public class SearchResult implements Comparable<SearchResult> { public class SearchResult implements Comparable<SearchResult> {
/** /**
* Defines the max rank for a search result to be considered as ranked. Results with ranks * 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. * higher than this have no guarantee for sorting order.
*/ */
public static final int MAX_RANK = 10; 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. * The title of the result and main text displayed.

View File

@@ -32,7 +32,8 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static com.android.settings.search2.SearchResult.MAX_RANK; import static com.android.settings.search2.SearchResult.TOP_RANK;
import static com.android.settings.search2.SearchResult.BOTTOM_RANK;
public class SearchResultsAdapter extends Adapter<SearchViewHolder> { public class SearchResultsAdapter extends Adapter<SearchViewHolder> {
@@ -117,9 +118,9 @@ public class SearchResultsAdapter extends Adapter<SearchViewHolder> {
int dbIndex = 0; int dbIndex = 0;
int appIndex = 0; int appIndex = 0;
int rank = 1; int rank = TOP_RANK;
while (rank <= MAX_RANK) { while (rank <= BOTTOM_RANK) {
while ((dbIndex < dbSize) && (databaseResults.get(dbIndex).rank == rank)) { while ((dbIndex < dbSize) && (databaseResults.get(dbIndex).rank == rank)) {
results.add(databaseResults.get(dbIndex++)); results.add(databaseResults.get(dbIndex++));
} }

View File

@@ -168,6 +168,9 @@ public class WifiSettings extends RestrictedSettingsFragment
private MenuItem mScanMenuItem; private MenuItem mScanMenuItem;
// For Search
private static final String DATA_KEY_REFERENCE = "main_toggle_wifi";
/* End of "used in Wifi Setup context" */ /* End of "used in Wifi Setup context" */
public WifiSettings() { public WifiSettings() {
@@ -1028,6 +1031,7 @@ public class WifiSettings extends RestrictedSettingsFragment
data.title = res.getString(R.string.wifi_settings); data.title = res.getString(R.string.wifi_settings);
data.screenTitle = res.getString(R.string.wifi_settings); data.screenTitle = res.getString(R.string.wifi_settings);
data.keywords = res.getString(R.string.keywords_wifi); data.keywords = res.getString(R.string.keywords_wifi);
data.key = DATA_KEY_REFERENCE;
result.add(data); result.add(data);
// Add saved Wi-Fi access points // Add saved Wi-Fi access points

View File

@@ -24,6 +24,7 @@ import android.database.MatrixCursor;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.util.ArrayMap; import android.util.ArrayMap;
import com.android.settings.DisplaySettings;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.SubSettings; import com.android.settings.SubSettings;
@@ -32,6 +33,7 @@ import com.android.settings.dashboard.SiteMapManager;
import com.android.settings.gestures.SwipeToNotificationSettings; import com.android.settings.gestures.SwipeToNotificationSettings;
import com.android.settings.search2.ResultPayload.PayloadType; import com.android.settings.search2.ResultPayload.PayloadType;
import com.android.settings.wifi.WifiSettings;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@@ -146,6 +148,29 @@ public class CursorToSearchResultConverterTest {
} }
} }
@Test
public void testLongTitle_PenalizedInRank() {
MatrixCursor cursor = new MatrixCursor(DatabaseResultLoader.SELECT_COLUMNS);
final String BLANK = "";
cursor.addRow(new Object[]{
ID, // Doc ID
"Longer than 20 characters", // Title
SUMMARY, // Summary on
SUMMARY, // summary off
DisplaySettings.class.getName(),
BLANK, // screen title
null, // icon
BLANK, // action
null, // target package
BLANK, // target class
BLANK, // Key
0, // Payload Type
null // Payload
});
List<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor, BASE_RANK);
assertThat(results.get(0).rank).isEqualTo(BASE_RANK + 2);
}
@Test @Test
public void testParseCursor_MatchesIntentForSubSettings() { public void testParseCursor_MatchesIntentForSubSettings() {
MatrixCursor cursor = new MatrixCursor(DatabaseResultLoader.SELECT_COLUMNS); MatrixCursor cursor = new MatrixCursor(DatabaseResultLoader.SELECT_COLUMNS);
@@ -246,6 +271,245 @@ public class CursorToSearchResultConverterTest {
assertThat(newPayload.valueMap.get(0)).isFalse(); assertThat(newPayload.valueMap.get(0)).isFalse();
} }
// The following tests are temporary, and should be removed when we replace the Search
// White-list solution for elevating ranking.
@Test
public void testWifiKey_PrioritizedResult() {
MatrixCursor cursor = new MatrixCursor(DatabaseResultLoader.SELECT_COLUMNS);
final String BLANK = "";
final String key = "main_toggle_wifi";
cursor.addRow(new Object[]{
ID, // Doc ID
TITLES[0], // Title
SUMMARY, // Summary on
SUMMARY, // summary off
WifiSettings.class.getName(), // ClassName
BLANK, // screen title
null, // icon
BLANK, // action
null, // target package
BLANK, // target class
key, // Key
0, // Payload Type
null // Payload
});
List<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor, BASE_RANK);
assertThat(results.get(0).rank).isEqualTo(SearchResult.TOP_RANK);
}
@Test
public void testBluetoothKey_PrioritizedResult() {
MatrixCursor cursor = new MatrixCursor(DatabaseResultLoader.SELECT_COLUMNS);
final String BLANK = "";
final String key = "main_toggle_bluetooth";
cursor.addRow(new Object[]{
ID, // Doc ID
TITLES[0], // Title
SUMMARY, // Summary on
SUMMARY, // summary off
WifiSettings.class.getName(), // ClassName
BLANK, // screen title
null, // icon
BLANK, // action
null, // target package
BLANK, // target class
key, // Key
0, // Payload Type
null // Payload
});
List<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor, BASE_RANK);
assertThat(results.get(0).rank).isEqualTo(SearchResult.TOP_RANK);
}
@Test
public void testAirplaneKey_PrioritizedResult() {
MatrixCursor cursor = new MatrixCursor(DatabaseResultLoader.SELECT_COLUMNS);
final String BLANK = "";
final String key = "toggle_airplane";
cursor.addRow(new Object[]{
ID, // Doc ID
TITLES[0], // Title
SUMMARY, // Summary on
SUMMARY, // summary off
WifiSettings.class.getName(), // ClassName
BLANK, // screen title
null, // icon
BLANK, // action
null, // target package
BLANK, // target class
key, // Key
0, // Payload Type
null // Payload
});
List<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor, BASE_RANK);
assertThat(results.get(0).rank).isEqualTo(SearchResult.TOP_RANK);
}
@Test
public void testHotspotKey_PrioritizedResult() {
MatrixCursor cursor = new MatrixCursor(DatabaseResultLoader.SELECT_COLUMNS);
final String BLANK = "";
final String key = "tether_settings";
cursor.addRow(new Object[]{
ID, // Doc ID
TITLES[0], // Title
SUMMARY, // Summary on
SUMMARY, // summary off
WifiSettings.class.getName(), // ClassName
BLANK, // screen title
null, // icon
BLANK, // action
null, // target package
BLANK, // target class
key, // Key
0, // Payload Type
null // Payload
});
List<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor, BASE_RANK);
assertThat(results.get(0).rank).isEqualTo(SearchResult.TOP_RANK);
}
@Test
public void testBatterySaverKey_PrioritizedResult() {
MatrixCursor cursor = new MatrixCursor(DatabaseResultLoader.SELECT_COLUMNS);
final String BLANK = "";
final String key = "battery_saver";
cursor.addRow(new Object[]{
ID, // Doc ID
TITLES[0], // Title
SUMMARY, // Summary on
SUMMARY, // summary off
WifiSettings.class.getName(), // ClassName
BLANK, // screen title
null, // icon
BLANK, // action
null, // target package
BLANK, // target class
key, // Key
0, // Payload Type
null // Payload
});
List<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor, BASE_RANK);
assertThat(results.get(0).rank).isEqualTo(SearchResult.TOP_RANK);
}
@Test
public void testNFCKey_PrioritizedResult() {
MatrixCursor cursor = new MatrixCursor(DatabaseResultLoader.SELECT_COLUMNS);
final String BLANK = "";
final String key = "toggle_nfc";
cursor.addRow(new Object[]{
ID, // Doc ID
TITLES[0], // Title
SUMMARY, // Summary on
SUMMARY, // summary off
WifiSettings.class.getName(), // ClassName
BLANK, // screen title
null, // icon
BLANK, // action
null, // target package
BLANK, // target class
key, // Key
0, // Payload Type
null // Payload
});
List<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor, BASE_RANK);
assertThat(results.get(0).rank).isEqualTo(SearchResult.TOP_RANK);
}
@Test
public void testDataSaverKey_PrioritizedResult() {
MatrixCursor cursor = new MatrixCursor(DatabaseResultLoader.SELECT_COLUMNS);
final String BLANK = "";
final String key = "restrict_background";
cursor.addRow(new Object[]{
ID, // Doc ID
TITLES[0], // Title
SUMMARY, // Summary on
SUMMARY, // summary off
WifiSettings.class.getName(), // ClassName
BLANK, // screen title
null, // icon
BLANK, // action
null, // target package
BLANK, // target class
key, // Key
0, // Payload Type
null // Payload
});
List<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor, BASE_RANK);
assertThat(results.get(0).rank).isEqualTo(SearchResult.TOP_RANK);
}
@Test
public void testDataUsageKey_PrioritizedResult() {
MatrixCursor cursor = new MatrixCursor(DatabaseResultLoader.SELECT_COLUMNS);
final String BLANK = "";
final String key = "data_usage_enable";
cursor.addRow(new Object[]{
ID, // Doc ID
TITLES[0], // Title
SUMMARY, // Summary on
SUMMARY, // summary off
WifiSettings.class.getName(), // ClassName
BLANK, // screen title
null, // icon
BLANK, // action
null, // target package
BLANK, // target class
key, // Key
0, // Payload Type
null // Payload
});
List<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor, BASE_RANK);
assertThat(results.get(0).rank).isEqualTo(SearchResult.TOP_RANK);
}
@Test
public void testRoamingKey_PrioritizedResult() {
MatrixCursor cursor = new MatrixCursor(DatabaseResultLoader.SELECT_COLUMNS);
final String BLANK = "";
final String key = "button_roaming_key";
cursor.addRow(new Object[]{
ID, // Doc ID
TITLES[0], // Title
SUMMARY, // Summary on
SUMMARY, // summary off
WifiSettings.class.getName(), // ClassName
BLANK, // screen title
null, // icon
BLANK, // action
null, // target package
BLANK, // target class
key, // Key
0, // Payload Type
null // Payload
});
List<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor, BASE_RANK);
assertThat(results.get(0).rank).isEqualTo(SearchResult.TOP_RANK);
}
// End of temporary tests
private MatrixCursor getDummyCursor() { private MatrixCursor getDummyCursor() {
return getDummyCursor(true /* hasIcon */); return getDummyCursor(true /* hasIcon */);
} }