Allow a small set of system apps to put their results into the promoted list before we have
enough data to decide which are highest ranking. Otherwise, only the top-ranked sources can
ever have their data in the promoted list.
diff --git a/src/com/android/globalsearch/SessionManager.java b/src/com/android/globalsearch/SessionManager.java
index b06d7d6..5faa58b 100644
--- a/src/com/android/globalsearch/SessionManager.java
+++ b/src/com/android/globalsearch/SessionManager.java
@@ -159,22 +159,33 @@
}
/**
- * Orders sources by source ranking. The ordering is as follows:
- * - the web source is first regardless
- * - the rest of the promoted sources are filled based on the ranking passed in
- * - any unranked sources
- * The above are put in mPromotableSources.
+ * Orders sources by source ranking, and into two groups: one that are candidates for the
+ * promoted list (mPromotableSources), and the other containing sources that should not be in
+ * the promoted list (mUnpromotableSources).
*
- * The rest of the ranked sources are put in mUnpromotableSources.
+ * The promotable list is as follows:
+ * - the web source
+ * - up to 'numPromoted' - 1 of the best ranked sources, among source for whom we have enough
+ * data (e.g are in the 'sourceRanking' list)
*
- * The idea is that unranked sources get a bump until they have enough data to be ranked like
- * the rest, and at the same time, no source can be in the promoted list unless it has a high
- * click through rate for a sustained amount of impressions.
+ * The unpromotoable list is as follows:
+ * - the sources lacking any impression / click data
+ * - the rest of the ranked sources
+ *
+ * The idea is to have the best ranked sources in the promoted list, and give newer sources the
+ * best slots under the "more results" positions to get a little extra attention until we have
+ * enough data to rank them as usual.
+ *
+ * Finally, to solve the empty room problem when there is no data about any sources, we allow
+ * a for a small whitelist of known system apps to be in the promoted list when there is no other
+ * ranked source available. This should only take effect for the first few usages of
+ * Quick search box.
*
* @param enabledSources The enabled sources.
* @param webSearchSource The name of the web search source, or <code>null</code> otherwise.
* @param sourceRanking The order the sources should be in.
* @param numPromoted The number of promoted sources.
+ * @return The order of the promotable and non-promotable sources.
*/
static Sources orderSources(
List<SuggestionSource> enabledSources,
@@ -247,7 +258,7 @@
}
public void add(SuggestionSource source, boolean forcePromotable) {
if (source == null) return;
- if (forcePromotable || shouldBePromotableWhenLowRanked(source)) {
+ if (forcePromotable || promotableWhenInsufficientRankingInfo(source)) {
if (DBG) Log.d(TAG, " Promotable: " + source);
mPromotableSources.add(source);
} else {
@@ -257,12 +268,14 @@
}
}
- private static boolean shouldBePromotableWhenLowRanked(SuggestionSource source) {
- // TODO: this is an ugly hack to make sure the Music source is unpromotable unless
- // it is ranked highly. (as long as there are at least
- // SuggestionSession.NUM_PROMOTED_SOURCES other sources)
- // Once the Music app returns better suggestions (i.e. token prefix matches, rather
- // than string infix matches) this should be removed.
- return !"com.android.music".equals(source.getComponentName().getPackageName());
+ /**
+ * To fix the empty room problem, we allow a small set of system apps to start putting their
+ * results in the promoted list before we have enough data to pick the high ranking ones.
+ */
+ private static boolean promotableWhenInsufficientRankingInfo(SuggestionSource source) {
+ final String packageName = source.getComponentName().getPackageName();
+ return "com.android.contacts".equals(packageName) ||
+ "com.android.browser".equals(packageName) ||
+ "com.android.providers.applications".equals(packageName);
}
}
diff --git a/src/com/android/globalsearch/SuggestionSession.java b/src/com/android/globalsearch/SuggestionSession.java
index a1db8b1..251be7a 100644
--- a/src/com/android/globalsearch/SuggestionSession.java
+++ b/src/com/android/globalsearch/SuggestionSession.java
@@ -133,8 +133,7 @@
* @param sourceLookup The sources to query for results
* @param promotableSources The promotable sources, in the order that they should be queried. If the
* web source is enabled, it will always be first.
- * @param unpromotableSources The unpromotable sources, in the order that they should be queried. If the
- * web source is enabled, it will always be first.
+ * @param unpromotableSources The unpromotable sources, in the order that they should be queried.
* @param queryExecutor Used to execute the asynchronous queries
* @param refreshExecutor Used to execute refresh tasks.
* @param delayedExecutor Used to post messages.
diff --git a/tests/src/com/android/globalsearch/SessionManagerTest.java b/tests/src/com/android/globalsearch/SessionManagerTest.java
index c736685..60ac249 100644
--- a/tests/src/com/android/globalsearch/SessionManagerTest.java
+++ b/tests/src/com/android/globalsearch/SessionManagerTest.java
@@ -28,6 +28,9 @@
/**
* Contains tests for logic in {@link SessionManager}
+ *
+ * TODO: refactor out hard coded 'promotableWhenInsufficientRankingInfo' list in session manager
+ * to make these tests less brittle.
*/
public class SessionManagerTest extends TestCase {
@@ -36,19 +39,19 @@
new ComponentName("com.example","com.example.WEB");
static final ComponentName B =
- new ComponentName("com.example","com.example.B");
+ new ComponentName("com.android.contacts","com.example.B");
static final ComponentName C =
- new ComponentName("com.example","com.example.C");
+ new ComponentName("com.android.contacts","com.example.C");
static final ComponentName D =
- new ComponentName("com.example","com.example.D");
+ new ComponentName("com.android.contacts","com.example.D");
static final ComponentName E =
- new ComponentName("com.example","com.example.E");
+ new ComponentName("com.android.contacts","com.example.E");
static final ComponentName F =
- new ComponentName("com.example","com.example.F");
+ new ComponentName("com.android.contacts","com.example.F");
private List<SuggestionSource> mAllSuggestionSources;