Never promote 3rd party sources with < 3 clicks.

Fixes http://b/issue?id=2085102

Change-Id: I263b3b4d9c26efd778cb83ddbfb6f22cd9668d4f
diff --git a/src/com/android/globalsearch/ShortcutRepository.java b/src/com/android/globalsearch/ShortcutRepository.java
index 54719dc..cba63be 100644
--- a/src/com/android/globalsearch/ShortcutRepository.java
+++ b/src/com/android/globalsearch/ShortcutRepository.java
@@ -43,6 +43,11 @@
      */
     static final int MIN_IMPRESSIONS_FOR_SOURCE_RANKING = 5;
 
+    /**
+     * The mininum number of clicks to be considered for source ranking.
+     */
+    static final int MIN_CLICKS_FOR_SOURCE_RANKING = 3;
+
     static final int MAX_SHORTCUTS_RETURNED = 12;
 
     /**
diff --git a/src/com/android/globalsearch/ShortcutRepositoryImplLog.java b/src/com/android/globalsearch/ShortcutRepositoryImplLog.java
index 6e8c469..a473817 100644
--- a/src/com/android/globalsearch/ShortcutRepositoryImplLog.java
+++ b/src/com/android/globalsearch/ShortcutRepositoryImplLog.java
@@ -104,7 +104,8 @@
 
         final String tables = SourceStats.TABLE_NAME;
         final String[] columns = SourceStats.COLUMNS;
-        final String where = SourceStats.total_impressions + " >= $1";
+        final String where = SourceStats.total_impressions + " >= $1 AND "
+                + SourceStats.total_clicks + " >= $2";
         final String groupBy = null;
         final String having = null;
         final String orderBy = orderingExpr + " DESC";
@@ -167,7 +168,8 @@
 
     /** {@inheritDoc} */
     public ArrayList<ComponentName> getSourceRanking() {
-        return getSourceRanking(MIN_IMPRESSIONS_FOR_SOURCE_RANKING);
+        return getSourceRanking(MIN_IMPRESSIONS_FOR_SOURCE_RANKING,
+                MIN_CLICKS_FOR_SOURCE_RANKING);
     }
 
     /** {@inheritDoc} */
@@ -275,13 +277,14 @@
      * Returns the source ranking for sources with a minimum number of impressions.
      *
      * @param minImpressions The minimum number of impressions a source must have.
+     * @param minClicks The minimum number of clicks a source must have.
      * @return The list of sources, ranked by click through rate.
      */
-    ArrayList<ComponentName> getSourceRanking(int minImpressions) {
+    ArrayList<ComponentName> getSourceRanking(int minImpressions, int minClicks) {
         SQLiteDatabase db = mOpenHelper.getReadableDatabase();
         final Cursor cursor = db.rawQuery(
                 SOURCE_RANKING_SQL,
-                new String[] { String.valueOf(minImpressions) });
+                new String[] { String.valueOf(minImpressions), String.valueOf(minClicks) });
         try {
             final ArrayList<ComponentName> sources =
                     new ArrayList<ComponentName>(cursor.getCount());
diff --git a/tests/src/com/android/globalsearch/ShortcutRepositoryTest.java b/tests/src/com/android/globalsearch/ShortcutRepositoryTest.java
index 0d73484..b48c465 100644
--- a/tests/src/com/android/globalsearch/ShortcutRepositoryTest.java
+++ b/tests/src/com/android/globalsearch/ShortcutRepositoryTest.java
@@ -530,7 +530,7 @@
                         Lists.newArrayList(APP_COMPONENT, CONTACTS_COMPONENT)), NOW);
 
         assertContentsInOrder("expecting apps to rank ahead of contacts (more clicks)",
-                mRepo.getSourceRanking(0),
+                mRepo.getSourceRanking(0, 0),
                 APP_COMPONENT, CONTACTS_COMPONENT);
 
         // 2 clicks on a contact, impression for both apps and contacts
@@ -544,7 +544,7 @@
                         Lists.newArrayList(APP_COMPONENT, CONTACTS_COMPONENT)), NOW);
 
         assertContentsInOrder("expecting contacts to rank ahead of apps (more clicks)",
-                mRepo.getSourceRanking(0),
+                mRepo.getSourceRanking(0, 0),
                 CONTACTS_COMPONENT, APP_COMPONENT);
     }
 
@@ -563,7 +563,7 @@
 
         assertContentsInOrder(
                 "apps (1 click / 2 impressions) should beat contacts (2 clicks / 5 impressions)",
-                mRepo.getSourceRanking(0),
+                mRepo.getSourceRanking(0, 0),
                 APP_COMPONENT, CONTACTS_COMPONENT);
 
         // contacts: up to 4 clicks in 7 impressions
@@ -572,7 +572,7 @@
 
         assertContentsInOrder(
                 "contacts (4 click / 7 impressions) should beat apps (1 clicks / 2 impressions)",
-                mRepo.getSourceRanking(0),
+                mRepo.getSourceRanking(0, 0),
                 CONTACTS_COMPONENT, APP_COMPONENT);
     }
 
@@ -594,12 +594,12 @@
 
         assertContentsInOrder(
                 "old clicks for apps shouldn't count.",
-                mRepo.getSourceRanking(0),
+                mRepo.getSourceRanking(0, 0),
                 CONTACTS_COMPONENT, APP_COMPONENT);
     }
 
 
-    public void testSourceRanking_filterSourcesWithInsufficientImpressions() {
+    public void testSourceRanking_filterSourcesWithInsufficientData() {
         sourceImpressions(APP_COMPONENT, 1, 5);
         sourceImpressions(CONTACTS_COMPONENT, 1, 2);
         sourceImpressions(BOOKMARKS_COMPONENT, 9, 10);
@@ -609,8 +609,18 @@
         
         assertContentsInOrder(
                 "ordering should only include sources with at least 5 impressions.",
-                mRepo.getSourceRanking(5),
+                mRepo.getSourceRanking(5, 0),
                 BOOKMARKS_COMPONENT, MARKET_COMPONENT, APP_COMPONENT);
+
+        assertContentsInOrder(
+                "ordering should only include sources with at least 2 clicks.",
+                mRepo.getSourceRanking(0, 2),
+                HISTORY_COMPONENT, BOOKMARKS_COMPONENT, MARKET_COMPONENT);
+
+        assertContentsInOrder(
+                "ordering should only include sources with at least 5 impressions and 3 clicks.",
+                mRepo.getSourceRanking(5, 3),
+                BOOKMARKS_COMPONENT, MARKET_COMPONENT);
     }
 
     protected void sourceImpressions(ComponentName source, int clicks, int impressions) {