Remove content provider querying from the search app.

The global search API that is used for this is being deprecated, since it
has long been beset by performance problems. Remove all related code from
the search app.

Bug: 10487397

Change-Id: Ifa91b50d784cb469cb39d6008284aa44ff54e62b
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index e916545..505417e 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -56,58 +56,10 @@
             <intent-filter>
                 <action android:name="android.search.action.GLOBAL_SEARCH" />
                 <category android:name="android.intent.category.DEFAULT" />
-                <data android:scheme="qsb.corpus" />
             </intent-filter>
-            <!-- Intent sent by corpus indicator in search widget. Opens QSB with
-                 corpus drop-down on top. -->
-            <intent-filter>
-                <action android:name="com.android.quicksearchbox.action.QSB_AND_SELECT_CORPUS" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-            <intent-filter>
-                <action android:name="com.android.quicksearchbox.action.QSB_AND_SELECT_CORPUS" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:scheme="qsb.corpus" />
-            </intent-filter>
-            <meta-data android:name="android.app.search.shortcut.provider" android:value="content://com.android.quicksearchbox.shortcuts/shortcuts" />
             <meta-data android:name="com.android.launcher.toolbar_icon" android:resource="@drawable/ic_google_logo_normal" />
         </activity>
 
-        <provider android:name=".ShortcutsProvider"
-            android:authorities="com.android.quicksearchbox.shortcuts"
-            android:exported="true" />
-
-        <activity android:name=".preferences.SearchSettingsActivity"
-                android:label="@string/search_settings"
-                android:excludeFromRecents="true">
-            <intent-filter>
-                <action android:name="android.search.action.SEARCH_SETTINGS" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-            <intent-filter>
-                <action android:name="android.search.action.WEB_SEARCH_SETTINGS" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name=".preferences.SearchableItemsActivity"
-                android:label="@string/search_sources"
-                android:excludeFromRecents="true">
-            <intent-filter>
-                <action android:name="com.android.quicksearchbox.action.SEARCHABLE_ITEMS" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-        </activity>
-
-        <receiver android:name=".CorporaUpdateReceiver">
-            <intent-filter>
-                <action android:name="android.search.action.SEARCHABLES_CHANGED" />
-            </intent-filter>
-            <intent-filter>
-                <action android:name="android.search.action.SETTINGS_CHANGED" />
-            </intent-filter>
-        </receiver>
-
         <receiver android:name=".SearchWidgetProvider"
                   android:label="@string/app_name">
             <intent-filter>
diff --git a/res/layout-xlarge/search_activity.xml b/res/layout-xlarge/search_activity.xml
deleted file mode 100644
index e45768e..0000000
--- a/res/layout-xlarge/search_activity.xml
+++ /dev/null
@@ -1,245 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-
-<com.android.quicksearchbox.ui.SearchActivityViewTwoPane
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/search_activity_view"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
->
-
-    <!-- A background area that when touched dismisses the activity if the search box is empty.
-         The top and bottom margins are here to avoid accidental dismissal when
-         using the keyboard or the widgets along the top of the screen. -->
-    <FrameLayout
-            android:id="@+id/dismiss_bg"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_alignParentLeft="true"
-            android:layout_alignParentTop="true"
-            android:layout_marginTop="80dip"
-            android:layout_marginBottom="30dip"
-            />
-
-    <LinearLayout
-            android:id="@+id/panes"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_alignParentLeft="true"
-            android:layout_alignParentTop="true"
-            android:orientation="horizontal"
-            android:splitMotionEvents="true">
-
-        <!-- Begin left_pane for suggestions -->
-        <RelativeLayout
-                android:id="@+id/left_pane"
-                android:layout_width="@dimen/suggestions_width"
-                android:layout_height="match_parent"
-                android:layout_marginLeft="5dp"
-                android:layout_marginBottom="12dip"
-                >
-
-            <FrameLayout
-                android:id="@+id/suggestions_container"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:layout_alignParentLeft="true"
-                android:layout_alignParentRight="true"
-                android:layout_below="@+id/search_plate"
-                >
-
-                <view
-                    class="com.android.quicksearchbox.ui.SuggestionsView"
-                    android:id="@+id/suggestions"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:paddingBottom="12dip"
-                    android:cacheColorHint="@android:color/transparent"
-                    android:scrollbars="none"
-                    android:divider="@android:color/transparent"
-                    android:dividerHeight="0px"
-                    >
-                </view>
-
-            </FrameLayout>
-
-            <!-- The search plate is after the suggestions, to give it a higher
-                 z-index. -->
-            <LinearLayout
-                android:id="@+id/search_plate"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:paddingTop="11dp"
-                android:layout_alignParentLeft="true"
-                android:layout_alignParentTop="true"
-                android:layout_alignParentRight="true"
-                android:gravity="top|left"
-                android:orientation="horizontal"
-                android:clickable="true"
-                >
-
-                <LinearLayout
-                    android:id="@+id/search_edit_frame"
-                    android:layout_width="0dip"
-                    android:layout_height="36dp"
-                    android:layout_weight="1.0"
-                    android:orientation="horizontal"
-                    android:gravity="center_vertical"
-                    android:background="@drawable/textfield_start"
-                    >
-
-                    <ImageView
-                        android:id="@+id/search_app_icon"
-                        android:layout_height="wrap_content"
-                        android:layout_width="wrap_content"
-                        android:paddingLeft="8dp"
-                        android:layout_gravity="center"
-                        android:src="@drawable/ic_search"
-                    />
-
-                    <com.android.quicksearchbox.ui.QueryTextView
-                        android:id="@+id/search_src_text"
-                        android:layout_width="0dip"
-                        android:layout_height="match_parent"
-                        android:layout_weight="1.0"
-                        android:layout_marginBottom="1dip"
-                        android:layout_marginLeft="5dip"
-                        android:layout_marginRight="8dip"
-                        android:gravity="center_vertical|left"
-                        android:singleLine="true"
-                        android:ellipsize="end"
-                        android:inputType="text|textAutoComplete"
-                        android:background="@drawable/textfield_search_empty_google"
-                        android:textSize="18sp"
-                        android:textStyle="normal"
-                        android:textColor="@android:color/primary_text_dark"
-                        android:textColorHint="@color/search_hint"
-                        android:imeOptions="actionGo"
-                    />
-
-                    <ImageButton
-                        android:id="@+id/search_close_btn"
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:paddingLeft="12dp"
-                        android:paddingRight="12dp"
-                        android:layout_gravity="center"
-                        android:background="@drawable/button_bg"
-                        android:src="@drawable/ic_clear_disabled"
-                        />
-
-                </LinearLayout>
-
-                <LinearLayout
-                    android:layout_width="78dip"
-                    android:layout_height="36dp"
-                    android:orientation="horizontal"
-                    android:gravity="center"
-                    android:background="@drawable/textfield_end" >
-                    <!-- One of these two will be visible at a time -->
-                    <ImageButton
-                        android:id="@+id/search_go_btn"
-                        android:background="@drawable/button_bg"
-                        android:src="@drawable/ic_go"
-                        android:layout_width="match_parent"
-                        android:layout_height="match_parent"
-                        android:layout_gravity="center"
-                        android:scaleType="centerInside"
-                        />
-                    <ImageButton
-                        android:id="@+id/search_voice_btn"
-                        android:background="@drawable/button_bg"
-                        android:src="@drawable/ic_btn_speak_now"
-                        android:layout_width="match_parent"
-                        android:layout_height="match_parent"
-                        android:layout_gravity="center"
-                        android:visibility="gone"
-                        android:scaleType="centerInside"
-                    />
-                </LinearLayout>
-
-            </LinearLayout>
-
-        </RelativeLayout>
-        <!-- End left_pane -->
-
-        <!-- Begin right_pane -->
-        <RelativeLayout
-                android:id="@+id/right_pane"
-                android:layout_width="0dp"
-                android:layout_height="match_parent"
-                android:layout_weight="1"
-                android:layout_marginLeft="16dp"
-                android:layout_marginBottom="12dip"
-                >
-
-            <view
-                class="com.android.quicksearchbox.ui.ClusteredSuggestionsView"
-                android:id="@+id/shortcuts"
-                android:layout_width="@dimen/shortcuts_width"
-                android:layout_height="wrap_content"
-                android:layout_alignParentLeft="true"
-                android:layout_alignWithParentIfMissing="true"
-                android:layout_below="@+id/shortcut_title"
-                android:cacheColorHint="@android:color/transparent"
-                android:scrollbars="none"
-                android:groupIndicator="@null"
-                android:listSelector="@drawable/suggestion_highlight"
-                android:divider="@android:color/transparent"
-                android:dividerHeight="0px"
-                android:childDivider="@android:color/transparent"
-                android:fadingEdge="vertical"
-                android:fadingEdgeLength="20dip"
-                android:focusable="true"
-                >
-
-             </view>
-
-            <!-- The search plate is after the suggestions, to give it a higher
-                 z-index. -->
-            <RelativeLayout
-                android:id="@+id/shortcut_title"
-                android:layout_width="@dimen/shortcuts_width"
-                android:layout_height="48dp"
-                android:layout_alignParentLeft="true"
-                android:layout_alignParentTop="true"
-                android:background="@drawable/section_header"
-                android:clickable="true"
-                android:visibility="invisible"
-                >
-
-            </RelativeLayout>
-
-        </RelativeLayout>
-
-        <ImageButton
-            android:id="@+id/menu_button"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="right|top"
-            android:paddingTop="5dip"
-            android:paddingRight="10dip"
-            android:paddingLeft="10dip"
-            android:paddingBottom="10dip"
-            android:singleLine="true"
-            android:clickable="true"
-            android:focusable="true"
-            android:background="@drawable/button_bg"
-            android:src="@drawable/ic_menu_moreoverflow_normal_holo_dark"
-        />
-
-    </LinearLayout>
-</com.android.quicksearchbox.ui.SearchActivityViewTwoPane>
diff --git a/res/layout/contact_suggestion.xml b/res/layout/contact_suggestion.xml
deleted file mode 100644
index 1f52da3..0000000
--- a/res/layout/contact_suggestion.xml
+++ /dev/null
@@ -1,63 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 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.
--->
-
-<view
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    class="com.android.quicksearchbox.ui.ContactSuggestionView"
-    style="@style/Suggestion">
-
-    <!-- Icons come first in the layout, since their placement doesn't depend on
-         the placement of the text views. -->
-
-    <LinearLayout android:id="@+id/contact_container"
-        style="@style/SuggestionIcon1"
-        android:layout_alignParentLeft="true"
-        android:layout_alignParentTop="true"
-        android:layout_alignParentBottom="true"
-        android:gravity="center"
-    >
-        <com.android.quicksearchbox.ui.ContactBadge android:id="@+id/icon1"
-            style="?android:attr/quickContactBadgeStyleSmallWindowSmall"/>
-    </LinearLayout>
-
-    <ImageView android:id="@+id/icon2"
-        style="@style/SuggestionIcon2"
-        android:scaleType="centerInside"
-        android:layout_alignParentRight="true"
-        android:layout_alignParentTop="true"
-        android:layout_alignParentBottom="true"
-        android:visibility="gone" />
-
-    <!-- The subtitle comes before the title, since the height of the title depends on whether the
-         subtitle is visible or gone. -->
-    <TextView android:id="@+id/text2"
-        style="@style/SuggestionText2"
-        android:singleLine="true"
-        android:layout_toRightOf="@id/contact_container"
-        android:layout_toLeftOf="@id/icon2"
-        android:layout_alignWithParentIfMissing="true"
-        android:layout_alignParentBottom="true"
-        android:visibility="gone" />
-
-    <!-- The title is placed above the subtitle, if there is one. If there is no
-         subtitle, it fills the parent. -->
-    <TextView android:id="@+id/text1"
-        style="@style/SuggestionText1"
-        android:layout_toRightOf="@id/contact_container"
-        android:layout_toLeftOf="@id/icon2"
-        android:layout_above="@id/text2" />
-
-</view>
diff --git a/res/layout/corpus_indicator.xml b/res/layout/corpus_indicator.xml
deleted file mode 100644
index b519736..0000000
--- a/res/layout/corpus_indicator.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 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.
--->
-
-<ImageButton
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/corpus_indicator"
-    android:layout_width="48dip"
-    android:layout_height="match_parent"
-    android:scaleType="centerInside"
-    android:focusable="true"
-    android:clickable="true"
-    android:src="@mipmap/search_app_icon"
-    android:background="@drawable/corpus_indicator_bg"
-    />
diff --git a/res/layout/search_activity.xml b/res/layout/search_activity.xml
index 498cb5b..7d020e0 100644
--- a/res/layout/search_activity.xml
+++ b/res/layout/search_activity.xml
@@ -51,8 +51,6 @@
         android:layout_alignParentRight="true"
         >
 
-        <include layout="@layout/corpus_indicator" />
-
         <com.android.quicksearchbox.ui.QueryTextView
             android:id="@+id/search_src_text"
             android:layout_width="0dip"
@@ -97,4 +95,4 @@
         />
     </LinearLayout>
 
-</com.android.quicksearchbox.ui.SearchActivityViewSinglePane>
\ No newline at end of file
+</com.android.quicksearchbox.ui.SearchActivityViewSinglePane>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 847f6ed..a87e7d0 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -17,68 +17,23 @@
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_name">Search</string>
 
-    <!-- Search widget -->
-    <string name="search_widget">Search</string>
-
-    <!-- Text in the dialog for confirming whether to remove an item from the search
-         history. [CHAR_LIMIT=NONE] -->
-    <string name="remove_from_history">Do you want to remove this item from the search history?</string>
-
     <!-- Toast text shown when the app fails to remove an item from
          the search history. [CHAR_LIMIT=60] -->
     <string name="remove_from_history_failed">Couldn\'t remove item from history.</string>
 
     <!-- Source selector -->
     <string name="corpus_selection_heading">Search</string>
-    <string name="corpus_label_global">All</string>
-
-    <!-- Name of the combined Web source shown in QSB -->
-    <string name="corpus_label_web">Web</string>
-    <!-- Description of the combined Web source shown in QSB -->
-    <string name="corpus_description_web">Web search, bookmarks, and browser history</string>
-
-    <!-- Name of the Apps source shown in QSB -->
-    <string name="corpus_label_apps">Apps</string>
-    <!-- Settings description for the Apps source shown in QSB -->
-    <string name="corpus_description_apps">Names of installed applications</string>
-    <!-- Search hint for the Apps source shown in QSB -->
-    <string name="corpus_hint_apps">Search apps</string>
-
-    <!-- Search settings stuff -->
 
     <!-- Search settings menu item -->
     <string name="menu_settings">Search settings</string>
 
-    <!-- Search settings title -->
-    <string name="search_settings">Search settings</string>
-
-    <!-- Title for Google Account category of search settings.
-         [CHAR LIMIT=20] -->
-    <string name="google_settings_category_title">Google Search</string>
-
-    <!-- Title for 'device' category of search settings 
-        [CHAR LIMIT=20] -->
-    <string name="device_settings_category_title">Clear shortcuts</string>
-
     <!-- Title for 'system search' category of search settings -->
     <string name="system_search_category_title">Phone</string>
 
-    <!-- Title and summary for 'search sources' link for system search -->
-    <string name="search_sources">Searchable items</string>
-    <string name="search_sources_summary">Choose what to search on the phone</string>
-
     <!-- Title and summary used for the option to clear search shortcuts from the system
          search history -->
-    <string name="clear_shortcuts">Clear shortcuts</string>
     <string name="clear_shortcuts_summary">Clear shortcuts to recently chosen search suggestions</string>
 
-    <!--[CHAR LIMIT=200] Title used in the dialog shown after choosing the 'clear search shortcuts' setting. -->
-    <string name="clear_shortcuts_prompt">"Do you want to clear all shortcuts to recently chosen search suggestions?"\n\n"To clear your Browser history, use the Browser's settings."</string>
-    <!--[CHAR LIMIT=30] Text used on the button to clear shortcuts in the dialog shown after choosing the 'clear search shortcuts' setting. -->
-    <string name="clear_shortcuts_agree">Clear shortcuts</string>
-    <!--[CHAR LIMIT=30] Text used on the button to cancel in the dialog shown after choosing the 'clear search shortcuts' setting. -->
-    <string name="clear_shortcuts_disagree">"Don't clear shortcuts"</string>
-
     <!-- Help menu item. Opens a web page with information about how to use Quick Search Box.
          [CHAR LIMIT=20] -->
     <string name="menu_help">Help</string>
@@ -86,9 +41,6 @@
     <!-- Search source label for the Google search source. -->
     <string name="google_search_label">Google</string>
 
-    <!-- The search activity label. -->
-    <string name="google_app_label">Google Search</string>
-
     <!-- This is the hint text shown in the search widget, before text is entered. -->
     <!-- This translation MUST MATCH the string "search_hint" which is found in
          Home/res/values/strings.xml -->
@@ -99,9 +51,5 @@
 
     <!-- Title for Voice Search hints bubble -->
     <string name="voice_search_hint_title">Try saying:</string>
-    <!-- Starting quotation marks of the voice search hint -->
-    <string name="voice_search_hint_quotation_start">\"</string>
-    <!-- Ending quotation marks of the voice search hint -->
-    <string name="voice_search_hint_quotation_end">\"</string>
 
 </resources>
diff --git a/res/xml/device_search_preferences.xml b/res/xml/device_search_preferences.xml
deleted file mode 100644
index fe5e1db..0000000
--- a/res/xml/device_search_preferences.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-
-<PreferenceScreen
-        xmlns:android="http://schemas.android.com/apk/res/android">
-
-        <com.android.quicksearchbox.preferences.OkCancelPreference
-                android:key="clear_shortcuts"
-                android:persistent="false"
-                android:title="@string/clear_shortcuts"
-                android:summary="@string/clear_shortcuts_summary"
-                android:dialogTitle="@string/clear_shortcuts"
-                android:dialogMessage="@string/clear_shortcuts_prompt"
-                android:positiveButtonText="@string/clear_shortcuts_agree"
-                android:negativeButtonText="@string/clear_shortcuts_disagree"
-                />
-
-</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/legacy_preferences.xml b/res/xml/legacy_preferences.xml
deleted file mode 100644
index a7c5ee0..0000000
--- a/res/xml/legacy_preferences.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 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.
--->
-
-<PreferenceScreen
-        xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <PreferenceCategory
-            android:title="@string/system_search_category_title">
-
-        <PreferenceScreen
-                android:key="search_corpora"
-                android:title="@string/search_sources"
-                android:summary="@string/search_sources_summary"
-                />
-
-        <com.android.quicksearchbox.preferences.OkCancelPreference
-                android:key="clear_shortcuts"
-                android:persistent="false"
-                android:title="@string/clear_shortcuts"
-                android:summary="@string/clear_shortcuts_summary"
-                android:dialogTitle="@string/clear_shortcuts"
-                android:dialogMessage="@string/clear_shortcuts_prompt"
-                android:positiveButtonText="@string/clear_shortcuts_agree"
-                android:negativeButtonText="@string/clear_shortcuts_disagree"
-                />
-
-    </PreferenceCategory>
-
-</PreferenceScreen>
diff --git a/res/xml/preferences_headers.xml b/res/xml/preferences_headers.xml
deleted file mode 100644
index 62e06c2..0000000
--- a/res/xml/preferences_headers.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-
-<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <header android:fragment="com.android.quicksearchbox.preferences.SearchableItemsFragment"
-        android:title="@string/search_sources"
-    />
-
-    <header android:fragment="com.android.quicksearchbox.preferences.DeviceSearchFragment"
-        android:title="@string/device_settings_category_title"
-    />
-
-</preference-headers>
diff --git a/res/xml/preferences_searchable_items.xml b/res/xml/preferences_searchable_items.xml
deleted file mode 100644
index 4a20243..0000000
--- a/res/xml/preferences_searchable_items.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-
-<PreferenceScreen
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:title="@string/search_sources"
-        android:key="search_corpora"
-        android:summary="@string/search_sources_summary">
-
-    <!-- CheckBoxPreferences added here dynamically -->
-
-</PreferenceScreen>
diff --git a/src/com/android/quicksearchbox/AbstractCorpus.java b/src/com/android/quicksearchbox/AbstractCorpus.java
deleted file mode 100644
index f63295c..0000000
--- a/src/com/android/quicksearchbox/AbstractCorpus.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2009 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.quicksearchbox;
-
-import android.content.Context;
-
-
-/**
- * Base class for corpus implementations.
- */
-public abstract class AbstractCorpus implements Corpus {
-
-    private final Context mContext;
-
-    private final Config mConfig;
-
-    public AbstractCorpus(Context context, Config config) {
-        mContext = context;
-        mConfig = config;
-    }
-
-    protected Context getContext() {
-        return mContext;
-    }
-
-    public boolean isCorpusDefaultEnabled() {
-        return mConfig.isCorpusEnabledByDefault(this);
-    }
-
-    public boolean isCorpusHidden() {
-        return mConfig.isCorpusHidden(getName());
-    }
-
-    @Override
-    public String toString() {
-        return getName();
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (o != null && getClass().equals(o.getClass())) {
-            return getName().equals(((Corpus) o).getName());
-        } else {
-            return false;
-        }
-    }
-
-    @Override
-    public int hashCode() {
-        return getName().hashCode();
-    }
-
-}
diff --git a/src/com/android/quicksearchbox/AbstractInternalSource.java b/src/com/android/quicksearchbox/AbstractInternalSource.java
index 34359fa..5567452 100644
--- a/src/com/android/quicksearchbox/AbstractInternalSource.java
+++ b/src/com/android/quicksearchbox/AbstractInternalSource.java
@@ -31,14 +31,17 @@
         super(context, uiThread, iconLoader);
     }
 
+    @Override
     public String getSuggestUri() {
         return null;
     }
 
+    @Override
     public boolean canRead() {
         return true;
     }
 
+    @Override
     public String getDefaultIntentData() {
         return null;
     }
@@ -48,14 +51,17 @@
         return getContext().getPackageName();
     }
 
+    @Override
     public int getQueryThreshold() {
         return 0;
     }
 
+    @Override
     public Drawable getSourceIcon() {
         return getContext().getResources().getDrawable(getSourceIconResource());
     }
 
+    @Override
     public Uri getSourceIconUri() {
         return Uri.parse("android.resource://" + getContext().getPackageName()
                 + "/" +  getSourceIconResource());
@@ -63,20 +69,7 @@
 
     protected abstract int getSourceIconResource();
 
-    public int getVersionCode() {
-        return QsbApplication.get(getContext()).getVersionCode();
-    }
-
-    /**
-     * Shortcuts from previous version are compatible with shortcuts from this version, so we just
-     * return true. If shortcuts become incompatible during an upgrade, some examination of the
-     * version code should be added here.
-     */
     @Override
-    public boolean isVersionCodeCompatible(int version) {
-        return true;
-    }
-
     public boolean queryAfterZeroResults() {
         return true;
     }
diff --git a/src/com/android/quicksearchbox/AbstractPromoter.java b/src/com/android/quicksearchbox/AbstractPromoter.java
deleted file mode 100644
index d1430b6..0000000
--- a/src/com/android/quicksearchbox/AbstractPromoter.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-/**
- * Abstract {@link Promoter} that uses a {@link SuggestionFilter} to choose shortcuts.
- */
-public abstract class AbstractPromoter implements Promoter {
-
-    private final SuggestionFilter mFilter;
-    private final Promoter mNext;
-    private final Config mConfig;
-
-    protected AbstractPromoter(SuggestionFilter filter, Promoter next, Config config) {
-        mFilter = filter;
-        mNext = next;
-        mConfig = config;
-    }
-
-    public void pickPromoted(
-            Suggestions suggestions, int maxPromoted, ListSuggestionCursor promoted) {
-        doPickPromoted(suggestions, maxPromoted, promoted);
-        if (mNext != null) {
-            mNext.pickPromoted(suggestions, maxPromoted, promoted);
-        }
-    }
-
-    protected abstract void doPickPromoted(
-            Suggestions suggestions, int maxPromoted, ListSuggestionCursor promoted);
-
-    protected Config getConfig() {
-        return mConfig;
-    }
-
-    protected boolean accept(Suggestion s) {
-        if (mFilter != null) {
-            return mFilter.accept(s);
-        } else {
-            return true;
-        }
-    }
-
-}
diff --git a/src/com/android/quicksearchbox/AbstractSource.java b/src/com/android/quicksearchbox/AbstractSource.java
index 7ce322f..f8c6d0c 100644
--- a/src/com/android/quicksearchbox/AbstractSource.java
+++ b/src/com/android/quicksearchbox/AbstractSource.java
@@ -64,18 +64,17 @@
 
     protected abstract String getIconPackage();
 
-    public boolean isVersionCodeCompatible(int version) {
-        return getVersionCode() == version;
-    }
-
+    @Override
     public NowOrLater<Drawable> getIcon(String drawableId) {
         return getIconLoader().getIcon(drawableId);
     }
 
+    @Override
     public Uri getIconUri(String drawableId) {
         return getIconLoader().getIconUri(drawableId);
     }
 
+    @Override
     public Intent createSearchIntent(String query, Bundle appData) {
         return createSourceSearchIntent(getIntentComponent(), query, appData);
     }
@@ -105,6 +104,7 @@
                 .createVoiceWebSearchIntent(appData);
     }
 
+    @Override
     public Source getRoot() {
         return this;
     }
diff --git a/src/com/android/quicksearchbox/AppsCorpus.java b/src/com/android/quicksearchbox/AppsCorpus.java
deleted file mode 100644
index dd24ea3..0000000
--- a/src/com/android/quicksearchbox/AppsCorpus.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-
-import com.android.quicksearchbox.util.Util;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.util.Log;
-
-/**
- * The apps search source.
- */
-public class AppsCorpus extends SingleSourceCorpus {
-
-    private static final String TAG = "QSB.AppsCorpus";
-
-    private static final String APPS_CORPUS_NAME = "apps";
-
-    public AppsCorpus(Context context, Config config, Source appsSource) {
-        super(context, config, appsSource);
-    }
-
-    @Override
-    public CharSequence getLabel() {
-        return getContext().getText(R.string.corpus_label_apps);
-    }
-
-    @Override
-    public CharSequence getHint() {
-        return getContext().getText(R.string.corpus_hint_apps);
-    }
-
-    @Override
-    public Drawable getCorpusIcon() {
-        return getContext().getResources().getDrawable(R.drawable.corpus_icon_apps);
-    }
-
-    @Override
-    public Uri getCorpusIconUri() {
-        return Util.getResourceUri(getContext(), R.drawable.corpus_icon_apps);
-    }
-
-    @Override
-    public String getName() {
-        return APPS_CORPUS_NAME;
-    }
-
-    @Override
-    public CharSequence getSettingsDescription() {
-        return getContext().getText(R.string.corpus_description_apps);
-    }
-
-    @Override
-    public Intent createSearchIntent(String query, Bundle appData) {
-        Intent appSearchIntent = createAppSearchIntent(query, appData);
-        if (appSearchIntent != null) {
-            return appSearchIntent;
-        } else {
-            // Fall back to sending the intent to ApplicationsProvider
-            return super.createSearchIntent(query, appData);
-        }
-    }
-
-    /**
-     * Creates an intent that starts the search activity specified in
-     * R.string.apps_search_activity.
-     *
-     * @return An intent, or {@code null} if the search activity is not set or can't be found.
-     */
-    private Intent createAppSearchIntent(String query, Bundle appData) {
-        ComponentName name = getComponentName(getContext(), R.string.apps_search_activity);
-        if (name == null) return null;
-        Intent intent = AbstractSource.createSourceSearchIntent(name, query, appData);
-        if (intent == null) return null;
-        ActivityInfo ai = intent.resolveActivityInfo(getContext().getPackageManager(), 0);
-        if (ai != null) {
-            return intent;
-        } else {
-            Log.w(TAG, "Can't find app search activity " + name);
-            return null;
-        }
-    }
-
-    private static ComponentName getComponentName(Context context, int res) {
-        String nameStr = context.getString(res);
-        if (TextUtils.isEmpty(nameStr)) {
-            return null;
-        } else {
-            return ComponentName.unflattenFromString(nameStr);
-        }
-    }
-}
diff --git a/src/com/android/quicksearchbox/Config.java b/src/com/android/quicksearchbox/Config.java
index f71339c..678d411 100644
--- a/src/com/android/quicksearchbox/Config.java
+++ b/src/com/android/quicksearchbox/Config.java
@@ -99,53 +99,12 @@
     }
 
     private HashSet<String> loadResourceStringSet(int res) {
-        HashSet<String> defaultCorpora = new HashSet<String>();
-        String[] corpora = mContext.getResources().getStringArray(res);
-        for (String corpus : corpora) {
-            if (DBG) Log.d(TAG, "Default corpus: " + corpus);
-            defaultCorpora.add(corpus);
+        HashSet<String> set = new HashSet<String>();
+        String[] items = mContext.getResources().getStringArray(res);
+        for (String item : items) {
+            set.add(item);
         }
-        return defaultCorpora;
-    }
-
-    /**
-     * Checks if we trust the given source not to be spammy.
-     */
-    public synchronized boolean isCorpusEnabledByDefault(Corpus corpus) {
-        if (DBG) Log.d(TAG, "isCorpusEnabledByDefault(" + corpus.getName() + ")");
-        if (mDefaultCorpora == null) {
-            mDefaultCorpora = loadResourceStringSet(R.array.default_corpora);
-        }
-        if (mDefaultCorpora.contains(corpus.getName())) {
-            if (DBG) Log.d(TAG, "Corpus " + corpus.getName() + " IS default");
-            return true;
-        }
-
-        if (mDefaultCorporaSuggestUris == null) {
-            mDefaultCorporaSuggestUris = loadResourceStringSet(
-                    R.array.default_corpora_suggest_uris);
-        }
-
-        for (Source s : corpus.getSources()) {
-            String uri = s.getSuggestUri();
-            if (DBG) Log.d(TAG, "Suggest URI for " + corpus.getName() + ": " + uri);
-            if (mDefaultCorporaSuggestUris.contains(uri)) {
-                if (DBG) Log.d(TAG, "Corpus " + corpus.getName() + " IS default");
-                return true;
-            }
-        }
-        if (DBG) Log.d(TAG, "Corpus " + corpus.getName() + " is NOT default");
-        return false;
-    }
-
-    /**
-     * Checks if the given corpus should be hidden from the corpus selection dialog.
-     */
-    public synchronized boolean isCorpusHidden(String corpusName) {
-        if (mHiddenCorpora == null) {
-            mHiddenCorpora = loadResourceStringSet(R.array.hidden_corpora);
-        }
-        return mHiddenCorpora.contains(corpusName);
+        return set;
     }
 
     /**
@@ -254,14 +213,6 @@
         return TYPING_SUGGESTIONS_UPDATE_DELAY_MILLIS;
     }
 
-    /**
-     * The delay in milliseconds before corpus results are published.
-     * If a new result arrives before this timeout expires, the timeout is reset.
-     */
-    public long getPublishResultDelayMillis() {
-        return PUBLISH_RESULT_DELAY_MILLIS;
-    }
-
     public boolean allowVoiceSearchHints() {
         return true;
     }
diff --git a/src/com/android/quicksearchbox/ContactsSource.java b/src/com/android/quicksearchbox/ContactsSource.java
deleted file mode 100644
index 463462e..0000000
--- a/src/com/android/quicksearchbox/ContactsSource.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import com.android.quicksearchbox.util.NamedTaskExecutor;
-
-import android.app.SearchableInfo;
-import android.content.Context;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.os.Handler;
-
-/**
- * Special case SearchableSource for contacts to provide the custom contacts suggestion view.
- */
-public class ContactsSource extends SearchableSource {
-
-    public ContactsSource(Context context, SearchableInfo searchable, Handler uiThread,
-            NamedTaskExecutor iconLoader) throws NameNotFoundException {
-        super(context, searchable, uiThread, iconLoader);
-    }
-
-}
diff --git a/src/com/android/quicksearchbox/Corpora.java b/src/com/android/quicksearchbox/Corpora.java
deleted file mode 100644
index 8533e22..0000000
--- a/src/com/android/quicksearchbox/Corpora.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2009 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.quicksearchbox;
-
-import android.database.DataSetObserver;
-
-import java.util.Collection;
-import java.util.List;
-
-/**
- * Maintains the set of available and enabled corpora.
- */
-public interface Corpora {
-
-    /**
-     * Gets all corpora, including the web corpus.
-     *
-     * @return Callers must not modify the returned collection.
-     */
-    Collection<Corpus> getAllCorpora();
-
-    /**
-     * Gets all enabled corpora.
-     *
-     * @return Callers must not modify the returned list.
-     */
-    List<Corpus> getEnabledCorpora();
-
-    /**
-     * Gets all corpora that should be included in the blended All mode.
-     *
-     * @return Callers must not modify the returned list.
-     */
-    List<Corpus> getCorporaInAll();
-
-    /**
-     * Gets a corpus by name.
-     *
-     * @return A corpus, or null.
-     */
-    Corpus getCorpus(String name);
-
-    /**
-     * Gets the web search corpus.
-     *
-     * @return The web search corpus, or {@code null} if there is no web search corpus.
-     */
-    Corpus getWebCorpus();
-
-    /**
-     * Gets a source by name.
-     *
-     * @param name Source name.
-     * @return A source, or {@code null} if no source with the given name exists.
-     */
-    Source getSource(String name);
-
-    /**
-     * Gets the corpus that contains the given source.
-     */
-    Corpus getCorpusForSource(Source source);
-
-    /**
-     * Updates the corpora.
-     */
-    void update();
-
-    /**
-     * Registers an observer that is called when corpus set changes.
-     *
-     * @param observer gets notified when the data set changes.
-     */
-    void registerDataSetObserver(DataSetObserver observer);
-
-    /**
-     * Unregisters an observer that has previously been registered with
-     * {@link #registerDataSetObserver(DataSetObserver)}
-     *
-     * @param observer the observer to unregister.
-     */
-    void unregisterDataSetObserver(DataSetObserver observer);
-}
diff --git a/src/com/android/quicksearchbox/CorporaUpdateReceiver.java b/src/com/android/quicksearchbox/CorporaUpdateReceiver.java
deleted file mode 100644
index 20ac202..0000000
--- a/src/com/android/quicksearchbox/CorporaUpdateReceiver.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import android.app.SearchManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.util.Log;
-
-/**
- * Listens for broadcasts that require updates to the corpus set.
- */
-public class CorporaUpdateReceiver extends BroadcastReceiver {
-
-    private static final boolean DBG = false;
-    private static final String TAG = "QSB.CorporaUpdateReceiver";
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        String action = intent.getAction();
-        if (SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED.equals(action)
-                || SearchManager.INTENT_ACTION_SEARCH_SETTINGS_CHANGED.equals(action)) {
-            if (DBG) Log.d(TAG, "onReceive(" + intent + ")");
-            updateCorpora(context);
-            SearchWidgetProvider.updateSearchWidgets(context);
-        }
-    }
-
-    private void updateCorpora(Context context) {
-        QsbApplication.get(context).updateCorpora();
-    }
-
-}
diff --git a/src/com/android/quicksearchbox/Corpus.java b/src/com/android/quicksearchbox/Corpus.java
deleted file mode 100644
index e38cbbc..0000000
--- a/src/com/android/quicksearchbox/Corpus.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2009 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.quicksearchbox;
-
-import android.content.Intent;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-
-import java.util.Collection;
-
-/**
- * A corpus is a user-visible set of suggestions. A corpus gets suggestions from one
- * or more sources.
- *
- * Objects that implement this interface should override {@link Object#equals(Object)}
- * and {@link Object#hashCode()} so that they can be used as keys in hash maps.
- */
-public interface Corpus extends SuggestionCursorProvider<CorpusResult> {
-
-    /**
-     * Gets the localized, human-readable label for this corpus.
-     */
-    CharSequence getLabel();
-
-    /**
-     * Gets the icon for this corpus.
-     */
-    Drawable getCorpusIcon();
-
-    /**
-     * Gets the icon URI for this corpus.
-     */
-    Uri getCorpusIconUri();
-
-    /**
-     * Gets the description to use for this corpus in system search settings.
-     */
-    CharSequence getSettingsDescription();
-
-    /**
-     * Gets the search hint text for this corpus.
-     */
-    CharSequence getHint();
-
-    /**
-     * @return The minimum query length for which this corpus should be queried.
-     */
-    int getQueryThreshold();
-
-    boolean queryAfterZeroResults();
-
-    boolean voiceSearchEnabled();
-
-    Intent createSearchIntent(String query, Bundle appData);
-
-    Intent createVoiceSearchIntent(Bundle appData);
-
-    boolean isWebCorpus();
-
-    /**
-     * Gets the sources that this corpus uses.
-     */
-    Collection<Source> getSources();
-
-    /**
-     * Checks if this corpus is enabled by default.
-     */
-    boolean isCorpusDefaultEnabled();
-
-    /**
-     * Whether this corpus should be included in the blended All mode.
-     */
-    boolean includeInAll();
-
-    /**
-     * Checks if this corpus should be hidden from the corpus selector.
-     */
-    boolean isCorpusHidden();
-
-}
diff --git a/src/com/android/quicksearchbox/CorpusFactory.java b/src/com/android/quicksearchbox/CorpusFactory.java
deleted file mode 100644
index a9c327f..0000000
--- a/src/com/android/quicksearchbox/CorpusFactory.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import java.util.Collection;
-
-/**
- * Creates corpora.
- */
-public interface CorpusFactory {
-
-    Collection<Corpus> createCorpora(Sources sources);
-
-}
diff --git a/src/com/android/quicksearchbox/CorpusRanker.java b/src/com/android/quicksearchbox/CorpusRanker.java
deleted file mode 100644
index d96dbcd..0000000
--- a/src/com/android/quicksearchbox/CorpusRanker.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import com.android.quicksearchbox.util.Consumer;
-
-import java.util.List;
-
-/**
- * Orders corpora by importance.
- */
-public interface CorpusRanker {
-
-    /**
-     * Gets a an ordered list of corpora.
-     *
-     * @param consumer Consumer that will be given the list of ranked corpora.
-     *        The consumer is called on an unspecified thread.
-     *        The most important corpora come first in the list. Callers should not modify the
-     *        list.
-     */
-    void getCorporaInAll(Consumer<List<Corpus>> consumer);
-
-}
diff --git a/src/com/android/quicksearchbox/CorpusResult.java b/src/com/android/quicksearchbox/CorpusResult.java
deleted file mode 100644
index 948d4fa..0000000
--- a/src/com/android/quicksearchbox/CorpusResult.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2009 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.quicksearchbox;
-
-
-/**
- * A sequence of suggestions from a single corpus.
- */
-public interface CorpusResult extends SuggestionCursor {
-
-    /**
-     * Gets the corpus that produced these suggestions.
-     */
-    Corpus getCorpus();
-
-    /**
-     * The user query that returned these suggestions.
-     */
-    String getUserQuery();
-
-    /**
-     * Gets the latency of the suggestion query that produced this result.
-     *
-     * @return The latency in milliseconds.
-     */
-    int getLatency();
-}
diff --git a/src/com/android/quicksearchbox/CorpusSelectionDialog.java b/src/com/android/quicksearchbox/CorpusSelectionDialog.java
deleted file mode 100644
index d33e2b9..0000000
--- a/src/com/android/quicksearchbox/CorpusSelectionDialog.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (C) 2009 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.quicksearchbox;
-
-import com.android.quicksearchbox.ui.CorporaAdapter;
-
-import android.app.Dialog;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.Window;
-import android.view.WindowManager;
-import android.widget.AdapterView;
-import android.widget.GridView;
-import android.widget.ImageView;
-
-/**
- * Corpus selection dialog.
- */
-public class CorpusSelectionDialog extends Dialog {
-
-    private static final boolean DBG = false;
-    private static final String TAG = "QSB.SelectSearchSourceDialog";
-
-    private final SearchSettings mSettings;
-
-    private GridView mCorpusGrid;
-
-    private ImageView mEditItems;
-
-    private OnCorpusSelectedListener mListener;
-
-    private Corpus mCorpus;
-
-    private CorporaAdapter mAdapter;
-
-    public CorpusSelectionDialog(Context context, SearchSettings settings) {
-        super(context, R.style.Theme_SelectSearchSource);
-        mSettings = settings;
-    }
-
-    protected SearchSettings getSettings() {
-        return mSettings;
-    }
-
-    /**
-     * Shows the corpus selection dialog.
-     *
-     * @param corpus The currently selected corpus.
-     */
-    public void show(Corpus corpus) {
-        mCorpus = corpus;
-        show();
-    }
-
-    public void setOnCorpusSelectedListener(OnCorpusSelectedListener listener) {
-        mListener = listener;
-    }
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        setContentView(R.layout.corpus_selection_dialog);
-        mCorpusGrid = (GridView) findViewById(R.id.corpus_grid);
-        mCorpusGrid.setOnItemClickListener(new CorpusClickListener());
-        // TODO: for some reason, putting this in the XML layout instead makes
-        // the list items unclickable.
-        mCorpusGrid.setFocusable(true);
-
-        mEditItems = (ImageView) findViewById(R.id.corpus_edit_items);
-        mEditItems.setOnClickListener(new CorpusEditListener());
-
-        Window window = getWindow();
-        WindowManager.LayoutParams lp = window.getAttributes();
-        lp.width = WindowManager.LayoutParams.MATCH_PARENT;
-        lp.height = WindowManager.LayoutParams.MATCH_PARENT;
-        // Put window on top of input method
-        lp.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-        window.setAttributes(lp);
-        if (DBG) Log.d(TAG, "Window params: " + lp);
-    }
-
-    @Override
-    protected void onStart() {
-        super.onStart();
-        Corpora corpora = getQsbApplication().getCorpora();
-        CorporaAdapter adapter =
-                new CorporaAdapter(getContext(), corpora, R.layout.corpus_grid_item);
-        adapter.setCurrentCorpus(mCorpus);
-        setAdapter(adapter);
-        mCorpusGrid.setSelection(adapter.getCorpusPosition(mCorpus));
-    }
-
-    @Override
-    protected void onStop() {
-        setAdapter(null);
-        super.onStop();
-    }
-
-    @Override
-    public boolean onPrepareOptionsMenu(Menu menu) {
-        menu.clear();
-        getSettings().addMenuItems(menu, true);
-        return true;
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        if (event.getAction() == MotionEvent.ACTION_DOWN) {
-            // Cancel dialog on any touch down event which is not handled by the corpus grid
-            cancel();
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-        boolean handled = super.onKeyDown(keyCode, event);
-        if (handled) {
-            return handled;
-        }
-        // Dismiss dialog on up move when nothing, or an item on the top row, is selected.
-        if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
-            if (mEditItems.isFocused()) {
-                cancel();
-                return true;
-            }
-        }
-        // Dismiss dialog when typing on hard keyboard (soft keyboard is behind the dialog,
-        // so that can't be typed on)
-        if (event.isPrintingKey()) {
-            cancel();
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    public void onBackPressed() {
-        SearchActivity searchActivity = getSearchActivity();
-        if (searchActivity.startedIntoCorpusSelectionDialog()) {
-            searchActivity.onBackPressed();
-        }
-        cancel();
-    }
-
-    private SearchActivity getSearchActivity() {
-        return (SearchActivity) getOwnerActivity();
-    }
-
-    private void setAdapter(CorporaAdapter adapter) {
-        if (adapter == mAdapter) return;
-        if (mAdapter != null) mAdapter.close();
-        mAdapter = adapter;
-        mCorpusGrid.setAdapter(mAdapter);
-    }
-
-    private QsbApplication getQsbApplication() {
-        return QsbApplication.get(getContext());
-    }
-
-    protected void selectCorpus(Corpus corpus) {
-        dismiss();
-        if (mListener != null) {
-            String corpusName = corpus == null ? null : corpus.getName();
-            mListener.onCorpusSelected(corpusName);
-        }
-    }
-
-    private class CorpusClickListener implements AdapterView.OnItemClickListener {
-        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-            Corpus corpus = (Corpus) parent.getItemAtPosition(position);
-            if (DBG) Log.d(TAG, "Corpus selected: " + corpus);
-            selectCorpus(corpus);
-        }
-    }
-
-    private class CorpusEditListener implements View.OnClickListener {
-        public void onClick(View v) {
-            Intent intent = getSettings().getSearchableItemsIntent();
-            getContext().startActivity(intent);
-        }
-    }
-
-    public interface OnCorpusSelectedListener {
-        void onCorpusSelected(String corpusName);
-    }
-}
diff --git a/src/com/android/quicksearchbox/CursorBackedSourceResult.java b/src/com/android/quicksearchbox/CursorBackedSourceResult.java
index 75dbe77..7c2fe9f 100644
--- a/src/com/android/quicksearchbox/CursorBackedSourceResult.java
+++ b/src/com/android/quicksearchbox/CursorBackedSourceResult.java
@@ -18,28 +18,30 @@
 import android.content.ComponentName;
 import android.database.Cursor;
 
+import com.android.quicksearchbox.google.GoogleSource;
+
 import java.util.Collection;
 
 public class CursorBackedSourceResult extends CursorBackedSuggestionCursor
         implements SourceResult {
 
-    private final Source mSource;
+    private final GoogleSource mSource;
 
-    public CursorBackedSourceResult(Source source, String userQuery) {
+    public CursorBackedSourceResult(GoogleSource source, String userQuery) {
         this(source, userQuery, null);
     }
 
-    public CursorBackedSourceResult(Source source, String userQuery, Cursor cursor) {
+    public CursorBackedSourceResult(GoogleSource source, String userQuery, Cursor cursor) {
         super(userQuery, cursor);
         mSource = source;
     }
 
-    public Source getSource() {
+    public GoogleSource getSource() {
         return mSource;
     }
 
     @Override
-    public Source getSuggestionSource() {
+    public GoogleSource getSuggestionSource() {
         return mSource;
     }
 
diff --git a/src/com/android/quicksearchbox/DefaultCorpusRanker.java b/src/com/android/quicksearchbox/DefaultCorpusRanker.java
deleted file mode 100644
index 490f8ec..0000000
--- a/src/com/android/quicksearchbox/DefaultCorpusRanker.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import com.android.quicksearchbox.util.CachedLater;
-import com.android.quicksearchbox.util.Consumer;
-
-import android.database.DataSetObserver;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-
-/**
- * A corpus ranker that uses corpus scores from the shortcut repository to rank
- * corpora.
- */
-public class DefaultCorpusRanker implements CorpusRanker {
-
-    private static final boolean DBG = false;
-    private static final String TAG = "QSB.DefaultCorpusRanker";
-
-    private final ShortcutRepository mShortcuts;
-
-    private final Corpora mCorpora;
-
-    // Cached list of ranked corpora.
-    private final RankedCorporaCache mRankedCorpora;
-
-    /**
-     * Creates a new default corpus ranker.
-     *
-     * @param corpora Corpora to rank.
-     * @param shortcuts Shortcut repository for getting corpus scores.
-     */
-    public DefaultCorpusRanker(Corpora corpora, ShortcutRepository shortcuts) {
-        mCorpora = corpora;
-        mCorpora.registerDataSetObserver(new CorporaObserver());
-        mShortcuts = shortcuts;
-        mRankedCorpora = new RankedCorporaCache();
-    }
-
-    public void getCorporaInAll(Consumer<List<Corpus>> consumer) {
-        mRankedCorpora.getLater(consumer);
-    }
-
-    public void clear() {
-        mRankedCorpora.clear();
-    }
-
-    private class CorporaObserver extends DataSetObserver {
-        @Override
-        public void onChanged() {
-            clear();
-        }
-    }
-
-    private class RankedCorporaCache extends CachedLater<List<Corpus>> {
-
-        @Override
-        protected void create() {
-            mShortcuts.getCorpusScores(new Consumer<Map<String,Integer>>(){
-                public boolean consume(Map<String, Integer> clickScores) {
-                    Collection<Corpus> enabledCorpora = mCorpora.getCorporaInAll();
-                    if (DBG) Log.d(TAG, "Ranking: " + enabledCorpora);
-                    ArrayList<Corpus> ordered = new ArrayList<Corpus>(enabledCorpora);
-                    Collections.sort(ordered, new CorpusComparator(clickScores));
-
-                    if (DBG) Log.d(TAG, "Click scores: " + clickScores);
-                    if (DBG) Log.d(TAG, "Ordered: " + ordered);
-
-                    store(ordered);
-                    return true;
-                }
-            });
-        }
-
-    }
-
-    private static class CorpusComparator implements Comparator<Corpus> {
-        private final Map<String,Integer> mClickScores;
-
-        public CorpusComparator(Map<String,Integer> clickScores) {
-            mClickScores = clickScores;
-        }
-
-        public int compare(Corpus corpus1, Corpus corpus2) {
-            boolean corpus1IsDefault = corpus1.isCorpusDefaultEnabled();
-            boolean corpus2IsDefault = corpus2.isCorpusDefaultEnabled();
-
-            if (corpus1IsDefault != corpus2IsDefault) {
-                // Default corpora always come before non-default
-                return corpus1IsDefault ? -1 : 1;
-            }
-
-            // Then by descending score
-            int scoreDiff = getCorpusScore(corpus2) - getCorpusScore(corpus1);
-            if (scoreDiff != 0) {
-                return scoreDiff;
-            }
-
-            // Finally by name
-            return corpus1.getLabel().toString().compareTo(corpus2.getLabel().toString());
-        }
-
-        /**
-         * Scores a corpus. Higher score is better.
-         */
-        private int getCorpusScore(Corpus corpus) {
-            // Web corpus always comes first
-            if (corpus.isWebCorpus()) {
-                return Integer.MAX_VALUE;
-            }
-            // Then use click score
-            return getClickScore(corpus);
-        }
-
-        private int getClickScore(Corpus corpus) {
-            if (mClickScores == null) return 0;
-            Integer clickScore = mClickScores.get(corpus.getName());
-            return clickScore == null ? 0 : clickScore;
-        }
-    }
-
-}
diff --git a/src/com/android/quicksearchbox/EventLogLogger.java b/src/com/android/quicksearchbox/EventLogLogger.java
index 72cf583..17ec0d1 100644
--- a/src/com/android/quicksearchbox/EventLogLogger.java
+++ b/src/com/android/quicksearchbox/EventLogLogger.java
@@ -57,56 +57,40 @@
         return mConfig;
     }
 
-    public void logStart(int onCreateLatency, int latency, String intentSource, Corpus corpus,
-            List<Corpus> orderedCorpora) {
+    @Override
+    public void logStart(int onCreateLatency, int latency, String intentSource) {
         // TODO: Add more info to startMethod
         String startMethod = intentSource;
-        String currentCorpus = getCorpusLogName(corpus);
-        String enabledCorpora = getCorpusLogNames(orderedCorpora);
         EventLogTags.writeQsbStart(mPackageName, getVersionCode(), startMethod,
-                latency, currentCorpus, enabledCorpora, onCreateLatency);
+                latency, null, null, onCreateLatency);
     }
 
-    public void logSuggestionClick(long id, SuggestionCursor suggestionCursor,
-            Collection<Corpus> queriedCorpora, int clickType) {
+    @Override
+    public void logSuggestionClick(long id, SuggestionCursor suggestionCursor, int clickType) {
         String suggestions = getSuggestions(suggestionCursor);
-        String corpora = getCorpusLogNames(queriedCorpora);
         int numChars = suggestionCursor.getUserQuery().length();
-        EventLogTags.writeQsbClick(id, suggestions, corpora, numChars,
+        EventLogTags.writeQsbClick(id, suggestions, null, numChars,
                 clickType);
     }
 
-    public void logSearch(Corpus corpus, int startMethod, int numChars) {
-        String corpusName = getCorpusLogName(corpus);
-        EventLogTags.writeQsbSearch(corpusName, startMethod, numChars);
+    @Override
+    public void logSearch(int startMethod, int numChars) {
+        EventLogTags.writeQsbSearch(null, startMethod, numChars);
     }
 
-    public void logVoiceSearch(Corpus corpus) {
-        String corpusName = getCorpusLogName(corpus);
-        EventLogTags.writeQsbVoiceSearch(corpusName);
+    @Override
+    public void logVoiceSearch() {
+        EventLogTags.writeQsbVoiceSearch(null);
     }
 
+    @Override
     public void logExit(SuggestionCursor suggestionCursor, int numChars) {
         String suggestions = getSuggestions(suggestionCursor);
         EventLogTags.writeQsbExit(suggestions, numChars);
     }
 
-    public void logLatency(CorpusResult result) {
-        if (!shouldLogLatency()) return;
-        String corpusName = getCorpusLogName(result.getCorpus());
-        int latency = result.getLatency();
-        int numChars = result.getUserQuery().length();
-        EventLogTags.writeQsbLatency(corpusName, latency, numChars);
-    }
-
-    private boolean shouldLogLatency() {
-        int freq = mConfig.getLatencyLogFrequency();
-        return freq > mRandom.nextInt(1000);
-    }
-
-    private String getCorpusLogName(Corpus corpus) {
-        if (corpus == null) return null;
-        return corpus.getName();
+    @Override
+    public void logLatency(SourceResult result) {
     }
 
     private String getSuggestions(SuggestionCursor cursor) {
@@ -124,14 +108,4 @@
         return sb.toString();
     }
 
-    private String getCorpusLogNames(Collection<Corpus> corpora) {
-        if (corpora == null) return "";
-        StringBuilder sb = new StringBuilder();
-        for (Corpus corpus : corpora) {
-            if (sb.length() > 0) sb.append(LIST_SEPARATOR);
-            sb.append(getCorpusLogName(corpus));
-        }
-        return sb.toString();
-    }
-
 }
diff --git a/src/com/android/quicksearchbox/Logger.java b/src/com/android/quicksearchbox/Logger.java
index d6bdb1f..40ff606 100644
--- a/src/com/android/quicksearchbox/Logger.java
+++ b/src/com/android/quicksearchbox/Logger.java
@@ -16,8 +16,6 @@
 
 package com.android.quicksearchbox;
 
-import java.util.Collection;
-import java.util.List;
 
 
 /**
@@ -37,8 +35,7 @@
      *
      * @param latency User-visible start-up latency in milliseconds.
      */
-    void logStart(int onCreateLatency, int latency, String intentSource, Corpus corpus,
-            List<Corpus> orderedCorpora);
+    void logStart(int onCreateLatency, int latency, String intentSource);
 
     /**
      * Called when a suggestion is clicked.
@@ -46,12 +43,9 @@
      * @param suggestionId Suggestion ID; 0-based position of the suggestion in the UI if the list
      *      is flat.
      * @param suggestionCursor all the suggestions shown in the UI.
-     * @param queriedCorpora all corpora that were queried to produce the suggestions in
-     *        {@code suggestionCursor}, ordered by rank.
      * @param clickType One of the SUGGESTION_CLICK_TYPE constants.
      */
-    void logSuggestionClick(long suggestionId, SuggestionCursor suggestionCursor,
-            Collection<Corpus> queriedCorpora, int clickType);
+    void logSuggestionClick(long suggestionId, SuggestionCursor suggestionCursor,  int clickType);
 
     /**
      * The user launched a search.
@@ -59,12 +53,12 @@
      * @param startMethod One of {@link #SEARCH_METHOD_BUTTON} or {@link #SEARCH_METHOD_KEYBOARD}.
      * @param numChars The number of characters in the query.
      */
-    void logSearch(Corpus corpus, int startMethod, int numChars);
+    void logSearch(int startMethod, int numChars);
 
     /**
      * The user launched a voice search.
      */
-    void logVoiceSearch(Corpus corpus);
+    void logVoiceSearch();
 
     /**
      * The user left QSB without performing any action (click suggestions, search or voice search).
@@ -79,6 +73,6 @@
      *
      * @param result The result of the query.
      */
-    void logLatency(CorpusResult result);
+    void logLatency(SourceResult result);
 
 }
diff --git a/src/com/android/quicksearchbox/MultiSourceCorpus.java b/src/com/android/quicksearchbox/MultiSourceCorpus.java
deleted file mode 100644
index b42bc5e..0000000
--- a/src/com/android/quicksearchbox/MultiSourceCorpus.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-
-import com.android.quicksearchbox.util.BarrierConsumer;
-
-import android.content.Context;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.Executor;
-
-/**
- * Base class for corpora backed by multiple sources.
- */
-public abstract class MultiSourceCorpus extends AbstractCorpus {
-
-    private final Executor mExecutor;
-
-    private final ArrayList<Source> mSources;
-
-    // calculated values based on properties of sources:
-    private boolean mSourcePropertiesValid;
-    private int mQueryThreshold;
-    private boolean mQueryAfterZeroResults;
-    private boolean mVoiceSearchEnabled;
-    private boolean mIncludeInAll;
-
-    public MultiSourceCorpus(Context context, Config config,
-            Executor executor, Source... sources) {
-        super(context, config);
-        mExecutor = executor;
-
-        mSources = new ArrayList<Source>();
-        for (Source source : sources) {
-            addSource(source);
-        }
-
-    }
-
-    protected void addSource(Source source) {
-        if (source != null) {
-            mSources.add(source);
-            // invalidate calculated values:
-            mSourcePropertiesValid = false;
-        }
-    }
-
-    public Collection<Source> getSources() {
-        return mSources;
-    }
-
-    /**
-     * Creates a corpus result object for a set of source results.
-     * This method should not call {@link Result#fill}.
-     *
-     * @param query The query text.
-     * @param results The results of the queries.
-     * @param latency Latency in milliseconds of the suggestion queries.
-     * @return An instance of {@link Result} or a subclass of it.
-     */
-    protected Result createResult(String query, ArrayList<SourceResult> results, int latency) {
-        return new Result(query, results, latency);
-    }
-
-    /**
-     * Gets the sources to query for suggestions for the given input.
-     *
-     * @param query The current input.
-     * @param onlyCorpus If true, this is the only corpus being queried.
-     * @return The sources to query.
-     */
-    protected List<Source> getSourcesToQuery(String query, boolean onlyCorpus) {
-        List<Source> sources = new ArrayList<Source>();
-        for (Source candidate : getSources()) {
-            if (candidate.getQueryThreshold() <= query.length()) {
-                sources.add(candidate);
-            }
-        }
-        return sources;
-    }
-
-    private void updateSourceProperties() {
-        if (mSourcePropertiesValid) return;
-        mQueryThreshold = Integer.MAX_VALUE;
-        mQueryAfterZeroResults = false;
-        mVoiceSearchEnabled = false;
-        mIncludeInAll = false;
-        for (Source s : getSources()) {
-            mQueryThreshold = Math.min(mQueryThreshold, s.getQueryThreshold());
-            mQueryAfterZeroResults |= s.queryAfterZeroResults();
-            mVoiceSearchEnabled |= s.voiceSearchEnabled();
-            mIncludeInAll |= s.includeInAll();
-        }
-        if (mQueryThreshold == Integer.MAX_VALUE) {
-            mQueryThreshold = 0;
-        }
-        mSourcePropertiesValid = true;
-    }
-
-    public int getQueryThreshold() {
-        updateSourceProperties();
-        return mQueryThreshold;
-    }
-
-    public boolean queryAfterZeroResults() {
-        updateSourceProperties();
-        return mQueryAfterZeroResults;
-    }
-
-    public boolean voiceSearchEnabled() {
-        updateSourceProperties();
-        return mVoiceSearchEnabled;
-    }
-
-    public boolean includeInAll() {
-        updateSourceProperties();
-        return mIncludeInAll;
-    }
-
-    public CorpusResult getSuggestions(String query, int queryLimit, boolean onlyCorpus) {
-        LatencyTracker latencyTracker = new LatencyTracker();
-        List<Source> sources = getSourcesToQuery(query, onlyCorpus);
-        BarrierConsumer<SourceResult> consumer =
-                new BarrierConsumer<SourceResult>(sources.size());
-        boolean onlySource = sources.size() == 1;
-        for (Source source : sources) {
-            QueryTask<SourceResult> task = new QueryTask<SourceResult>(query, queryLimit,
-                    source, null, consumer, onlySource);
-            mExecutor.execute(task);
-        }
-        ArrayList<SourceResult> results = consumer.getValues();
-        int latency = latencyTracker.getLatency();
-        Result result = createResult(query, results, latency);
-        result.fill();
-        return result;
-    }
-
-    /**
-     * Base class for results returned by {@link MultiSourceCorpus#getSuggestions}.
-     * Subclasses of {@link MultiSourceCorpus} should override
-     * {@link MultiSourceCorpus#createResult} and return an instance of this class or a
-     * subclass.
-     */
-    protected class Result extends ListSuggestionCursor implements CorpusResult {
-
-        private final ArrayList<SourceResult> mResults;
-
-        private final int mLatency;
-
-        public Result(String userQuery, ArrayList<SourceResult> results, int latency) {
-            super(userQuery);
-            mResults = results;
-            mLatency = latency;
-        }
-
-        protected ArrayList<SourceResult> getResults() {
-            return mResults;
-        }
-
-        /**
-         * Fills the list of suggestions using the list of results.
-         * The default implementation concatenates the results.
-         */
-        public void fill() {
-            for (SourceResult result : getResults()) {
-                int count = result.getCount();
-                for (int i = 0; i < count; i++) {
-                    result.moveTo(i);
-                    add(new SuggestionPosition(result));
-                }
-            }
-        }
-
-        public Corpus getCorpus() {
-            return MultiSourceCorpus.this;
-        }
-
-        public int getLatency() {
-            return mLatency;
-        }
-
-        @Override
-        public void close() {
-            super.close();
-            for (SourceResult result : mResults) {
-                result.close();
-            }
-        }
-
-        @Override
-        public String toString() {
-            return "{" + getCorpus() + "[" + getUserQuery() + "]" + ";n=" + getCount() + "}";
-        }
-    }
-
-}
diff --git a/src/com/android/quicksearchbox/Promoter.java b/src/com/android/quicksearchbox/Promoter.java
deleted file mode 100644
index 494e85c..0000000
--- a/src/com/android/quicksearchbox/Promoter.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2009 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.quicksearchbox;
-
-
-/**
- * Promoters choose which suggestions to promote from all the available suggestions.
- *
- */
-public interface Promoter {
-
-    /**
-     * Gets the promoted suggestions.
-     *
-     * @param suggestions The suggestions to promote from.
-     * @param maxPromoted The maximum number of suggestions to promote.
-     * @param promoted List to add the promoted suggestions to.
-     */
-    void pickPromoted(Suggestions suggestions, int maxPromoted, ListSuggestionCursor promoted);
-
-}
diff --git a/src/com/android/quicksearchbox/QsbApplication.java b/src/com/android/quicksearchbox/QsbApplication.java
index 2eb450d..b3bccd3 100644
--- a/src/com/android/quicksearchbox/QsbApplication.java
+++ b/src/com/android/quicksearchbox/QsbApplication.java
@@ -16,10 +16,18 @@
 
 package com.android.quicksearchbox;
 
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Process;
+import android.view.ContextThemeWrapper;
+
 import com.android.quicksearchbox.google.GoogleSource;
 import com.android.quicksearchbox.google.GoogleSuggestClient;
 import com.android.quicksearchbox.google.SearchBaseUrlHelper;
-import com.android.quicksearchbox.preferences.PreferenceControllerFactory;
 import com.android.quicksearchbox.ui.DefaultSuggestionViewFactory;
 import com.android.quicksearchbox.ui.SuggestionViewFactory;
 import com.android.quicksearchbox.util.Factory;
@@ -31,16 +39,6 @@
 import com.android.quicksearchbox.util.SingleThreadNamedTaskExecutor;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
 
-import android.app.Activity;
-import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Process;
-import android.view.ContextThemeWrapper;
-
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ThreadFactory;
@@ -52,11 +50,6 @@
     private Handler mUiThreadHandler;
     private Config mConfig;
     private SearchSettings mSettings;
-    private Sources mSources;
-    private Corpora mCorpora;
-    private CorpusRanker mCorpusRanker;
-    private ShortcutRepository mShortcutRepository;
-    private ShortcutRefresher mShortcutRefresher;
     private NamedTaskExecutor mSourceTaskExecutor;
     private ThreadFactory mQueryThreadFactory;
     private SuggestionsProvider mSuggestionsProvider;
@@ -119,14 +112,6 @@
             mConfig.close();
             mConfig = null;
         }
-        if (mShortcutRepository != null) {
-            mShortcutRepository.close();
-            mShortcutRepository = null;
-        }
-        if (mSourceTaskExecutor != null) {
-            mSourceTaskExecutor.close();
-            mSourceTaskExecutor = null;
-        }
         if (mSuggestionsProvider != null) {
             mSuggestionsProvider.close();
             mSuggestionsProvider = null;
@@ -190,59 +175,10 @@
         return new SearchSettingsImpl(getContext(), getConfig());
     }
 
-    /**
-     * Gets all corpora.
-     *
-     * May only be called from the main thread.
-     */
-    public Corpora getCorpora() {
-        checkThread();
-        if (mCorpora == null) {
-            mCorpora = createCorpora(getSources());
-        }
-        return mCorpora;
-    }
-
-    protected Corpora createCorpora(Sources sources) {
-        SearchableCorpora corpora = new SearchableCorpora(getContext(), getSettings(), sources,
-                createCorpusFactory());
-        corpora.update();
-        return corpora;
-    }
-
-    /**
-     * Updates the corpora, if they are loaded.
-     * May only be called from the main thread.
-     */
-    public void updateCorpora() {
-        checkThread();
-        if (mCorpora != null) {
-            mCorpora.update();
-        }
-    }
-
-    protected Sources getSources() {
-        checkThread();
-        if (mSources == null) {
-            mSources = createSources();
-        }
-        return mSources;
-    }
-
-    protected Sources createSources() {
-        return new SearchableSources(getContext(), getMainThreadHandler(),
-                getIconLoaderExecutor(), getConfig());
-    }
-
-    protected CorpusFactory createCorpusFactory() {
-        int numWebCorpusThreads = getConfig().getNumWebCorpusThreads();
-        return new SearchableCorpusFactory(getContext(), getConfig(), getSettings(),
-                createExecutorFactory(numWebCorpusThreads));
-    }
-
     protected Factory<Executor> createExecutorFactory(final int numThreads) {
         final ThreadFactory threadFactory = getQueryThreadFactory();
         return new Factory<Executor>() {
+            @Override
             public Executor create() {
                 return Executors.newFixedThreadPool(numThreads, threadFactory);
             }
@@ -250,62 +186,6 @@
     }
 
     /**
-     * Gets the corpus ranker.
-     * May only be called from the main thread.
-     */
-    public CorpusRanker getCorpusRanker() {
-        checkThread();
-        if (mCorpusRanker == null) {
-            mCorpusRanker = createCorpusRanker();
-        }
-        return mCorpusRanker;
-    }
-
-    protected CorpusRanker createCorpusRanker() {
-        return new DefaultCorpusRanker(getCorpora(), getShortcutRepository());
-    }
-
-    /**
-     * Gets the shortcut repository.
-     * May only be called from the main thread.
-     */
-    public ShortcutRepository getShortcutRepository() {
-        checkThread();
-        if (mShortcutRepository == null) {
-            mShortcutRepository = createShortcutRepository();
-        }
-        return mShortcutRepository;
-    }
-
-    protected ShortcutRepository createShortcutRepository() {
-        ThreadFactory logThreadFactory =
-                new ThreadFactoryBuilder()
-                .setNameFormat("ShortcutRepository #%d")
-                .setThreadFactory(new PriorityThreadFactory(
-                        Process.THREAD_PRIORITY_BACKGROUND))
-                .build();
-        Executor logExecutor = Executors.newSingleThreadExecutor(logThreadFactory);
-        return ShortcutRepositoryImplLog.create(getContext(), getConfig(), getCorpora(),
-            getShortcutRefresher(), getMainThreadHandler(), logExecutor);
-    }
-
-    /**
-     * Gets the shortcut refresher.
-     * May only be called from the main thread.
-     */
-    public ShortcutRefresher getShortcutRefresher() {
-        checkThread();
-        if (mShortcutRefresher == null) {
-            mShortcutRefresher = createShortcutRefresher();
-        }
-        return mShortcutRefresher;
-    }
-
-    protected ShortcutRefresher createShortcutRefresher() {
-        // For now, ShortcutRefresher gets its own SourceTaskExecutor
-        return new SourceShortcutRefresher(createSourceTaskExecutor());
-    }
-
     /**
      * Gets the source task executor.
      * May only be called from the main thread.
@@ -380,28 +260,6 @@
         return new DefaultSuggestionViewFactory(getContext());
     }
 
-    public Promoter createBlendingPromoter() {
-        return new ShortcutPromoter(getConfig(),
-                new RankAwarePromoter(getConfig(), null, null), null);
-    }
-
-    public Promoter createSingleCorpusPromoter(Corpus corpus) {
-        return new SingleCorpusPromoter(corpus, Integer.MAX_VALUE);
-    }
-
-    public Promoter createSingleCorpusResultsPromoter(Corpus corpus) {
-        return new SingleCorpusResultsPromoter(corpus, Integer.MAX_VALUE);
-    }
-
-    public Promoter createWebPromoter() {
-        return new WebPromoter(getConfig().getMaxShortcutsPerWebSource());
-    }
-
-    public Promoter createResultsPromoter() {
-        SuggestionFilter resultFilter = new ResultFilter();
-        return new ShortcutPromoter(getConfig(), null, resultFilter);
-    }
-
     /**
      * Gets the Google source.
      * May only be called from the main thread.
@@ -472,10 +330,6 @@
         return new TextAppearanceFactory(getContext());
     }
 
-    public PreferenceControllerFactory createPreferenceControllerFactory(Activity activity) {
-        return new PreferenceControllerFactory(getSettings(), activity);
-    }
-
     public synchronized HttpHelper getHttpHelper() {
         if (mHttpHelper == null) {
             mHttpHelper = createHttpHelper();
diff --git a/src/com/android/quicksearchbox/QueryTask.java b/src/com/android/quicksearchbox/QueryTask.java
index a85731c..8ea5be9 100644
--- a/src/com/android/quicksearchbox/QueryTask.java
+++ b/src/com/android/quicksearchbox/QueryTask.java
@@ -36,7 +36,6 @@
     private final SuggestionCursorProvider<C> mProvider;
     private final Handler mHandler;
     private final Consumer<C> mConsumer;
-    private final boolean mTheOnlyOne;
 
     /**
      * Creates a new query task.
@@ -47,24 +46,24 @@
      * @param handler Handler that {@link Consumer#consume} will
      *        get called on. If null, the method is called on the query thread.
      * @param consumer Consumer to notify when the suggestions have been returned.
-     * @param onlyTask Indicates if this is the only task within a batch.
      */
     public QueryTask(String query, int queryLimit, SuggestionCursorProvider<C> provider,
-            Handler handler, Consumer<C> consumer, boolean onlyTask) {
+            Handler handler, Consumer<C> consumer) {
         mQuery = query;
         mQueryLimit = queryLimit;
         mProvider = provider;
         mHandler = handler;
         mConsumer = consumer;
-        mTheOnlyOne = onlyTask;
     }
 
+    @Override
     public String getName() {
         return mProvider.getName();
     }
 
+    @Override
     public void run() {
-        final C cursor = mProvider.getSuggestions(mQuery, mQueryLimit, mTheOnlyOne);
+        final C cursor = mProvider.getSuggestions(mQuery, mQueryLimit);
         if (DBG) Log.d(TAG, "Suggestions from " + mProvider + " = " + cursor);
         Consumers.consumeCloseableAsync(mHandler, mConsumer, cursor);
     }
@@ -74,26 +73,14 @@
         return mProvider + "[" + mQuery + "]";
     }
 
-    public static <C extends SuggestionCursor> void startQueries(String query,
-            int maxResultsPerProvider,
-            Iterable<? extends SuggestionCursorProvider<C>> providers,
-            NamedTaskExecutor executor, Handler handler,
-            Consumer<C> consumer, boolean onlyOneProvider) {
-
-        for (SuggestionCursorProvider<C> provider : providers) {
-            QueryTask.startQuery(query, maxResultsPerProvider, provider,
-                    executor, handler, consumer, onlyOneProvider);
-        }
-    }
-
     public static <C extends SuggestionCursor> void startQuery(String query,
-            int maxResultsPerProvider,
+            int maxResults,
             SuggestionCursorProvider<C> provider,
             NamedTaskExecutor executor, Handler handler,
-            Consumer<C> consumer, boolean onlyOneProvider) {
+            Consumer<C> consumer) {
 
-        QueryTask<C> task = new QueryTask<C>(query, maxResultsPerProvider, provider, handler,
-                consumer, onlyOneProvider);
+        QueryTask<C> task = new QueryTask<C>(query, maxResults, provider, handler,
+                consumer);
         executor.execute(task);
     }
 }
diff --git a/src/com/android/quicksearchbox/RankAwarePromoter.java b/src/com/android/quicksearchbox/RankAwarePromoter.java
deleted file mode 100644
index 75b2e2a..0000000
--- a/src/com/android/quicksearchbox/RankAwarePromoter.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import com.google.common.annotations.VisibleForTesting;
-
-import android.util.Log;
-
-import java.util.Iterator;
-import java.util.LinkedList;
-
-/**
- * A promoter that gives preference to suggestions from higher ranking corpora.
- */
-public class RankAwarePromoter extends AbstractPromoter {
-
-    private static final boolean DBG = false;
-    private static final String TAG = "QSB.RankAwarePromoter";
-
-    public RankAwarePromoter(Config config, SuggestionFilter filter, Promoter next) {
-        super(filter, next, config);
-    }
-
-    @Override
-    public void doPickPromoted(Suggestions suggestions,
-            int maxPromoted, ListSuggestionCursor promoted) {
-        promoteSuggestions(suggestions.getCorpusResults(), maxPromoted, promoted);
-    }
-
-    @VisibleForTesting
-    void promoteSuggestions(Iterable<CorpusResult> suggestions, int maxPromoted,
-            ListSuggestionCursor promoted) {
-        if (DBG) Log.d(TAG, "Available results: " + suggestions);
-
-        // Split non-empty results into important suggestions and not-so-important
-        // suggestions, each corpus's cursor positioned at the first suggestion.
-        LinkedList<CorpusResult> highRankingSuggestions = new LinkedList<CorpusResult>();
-        LinkedList<CorpusResult> lowRankingSuggestions = new LinkedList<CorpusResult>();
-        partitionSuggestionsByRank(suggestions, highRankingSuggestions, lowRankingSuggestions);
-
-        // Top results, evenly distributed between each high-ranking corpus.
-        promoteTopSuggestions(highRankingSuggestions, promoted, maxPromoted);
-
-        // Then try to fill promoted list with the remaining high-ranking suggestions,
-        // and then use the low-ranking suggestions if the list isn't full yet.
-        promoteEquallyFromEachCorpus(highRankingSuggestions, promoted, maxPromoted);
-        promoteEquallyFromEachCorpus(lowRankingSuggestions, promoted, maxPromoted);
-
-        if (DBG) Log.d(TAG, "Returning " + promoted.toString());
-    }
-
-    /**
-     * Shares the top slots evenly among each of the high-ranking (default) corpora.
-     *
-     * The corpora will appear in the promoted list in the order they are listed
-     * among the incoming suggestions (this method doesn't change their order).
-     */
-    private void promoteTopSuggestions(LinkedList<CorpusResult> highRankingSuggestions,
-            ListSuggestionCursor promoted, int maxPromoted) {
-
-        int slotsLeft = getSlotsLeft(promoted, maxPromoted);
-        if (slotsLeft > 0 && !highRankingSuggestions.isEmpty()) {
-            int slotsToFill = Math.min(getSlotsAboveKeyboard() - promoted.getCount(), slotsLeft);
-
-            if (slotsToFill > 0) {
-                int stripeSize = Math.max(1, slotsToFill / highRankingSuggestions.size());
-                roundRobin(highRankingSuggestions, slotsToFill, stripeSize, promoted);
-            }
-        }
-    }
-
-    /**
-     * Tries to promote the same number of elements from each corpus.
-     *
-     * The corpora will appear in the promoted list in the order they are listed
-     * among the incoming suggestions (this method doesn't change their order).
-     */
-    private void promoteEquallyFromEachCorpus(LinkedList<CorpusResult> suggestions,
-            ListSuggestionCursor promoted, int maxPromoted) {
-
-        int slotsLeft = getSlotsLeft(promoted, maxPromoted);
-        if (slotsLeft == 0) {
-            // No more items to add.
-            return;
-        }
-
-        if (suggestions.isEmpty()) {
-            return;
-        }
-
-        int stripeSize = Math.max(1, slotsLeft / suggestions.size());
-        roundRobin(suggestions, slotsLeft, stripeSize, promoted);
-
-        // We may still have a few slots left
-        slotsLeft = getSlotsLeft(promoted, maxPromoted);
-        roundRobin(suggestions, slotsLeft, slotsLeft, promoted);
-    }
-
-    /**
-     * Partitions the suggestions into "important" (high-ranking)
-     * and "not-so-important" (low-ranking) suggestions, dependent on the
-     * rank of the corpus the result is part of.
-     *
-     * @param suggestions
-     * @param highRankingSuggestions These should be displayed first to the
-     *     user.
-     * @param lowRankingSuggestions These should be displayed if the
-     *     high-ranking suggestions don't fill all the available space in the
-     *     result view.
-     */
-    private void partitionSuggestionsByRank(Iterable<CorpusResult> suggestions,
-            LinkedList<CorpusResult> highRankingSuggestions,
-            LinkedList<CorpusResult> lowRankingSuggestions) {
-
-        for (CorpusResult result : suggestions) {
-            if (result.getCount() > 0) {
-                result.moveTo(0);
-                Corpus corpus = result.getCorpus();
-                if (isCorpusHighlyRanked(corpus)) {
-                    highRankingSuggestions.add(result);
-                } else {
-                    lowRankingSuggestions.add(result);
-                }
-            }
-        }
-    }
-
-    private boolean isCorpusHighlyRanked(Corpus corpus) {
-        // The default corpora shipped with QSB (apps, etc.) are
-        // more important than ones that were registered later.
-        return corpus == null || corpus.isCorpusDefaultEnabled();
-    }
-
-    private int getSlotsLeft(ListSuggestionCursor promoted, int maxPromoted) {
-        // It's best to calculate this after each addition because duplicates
-        // may get filtered out automatically in the list of promoted items.
-        return Math.max(0, maxPromoted - promoted.getCount());
-    }
-
-    private int getSlotsAboveKeyboard() {
-        return getConfig().getNumSuggestionsAboveKeyboard();
-    }
-
-    /**
-     * Promotes "stripes" of suggestions from each corpus.
-     *
-     * @param results     the list of CorpusResults from which to promote.
-     *                    Exhausted CorpusResults are removed from the list.
-     * @param maxPromoted maximum number of suggestions to promote.
-     * @param stripeSize  number of suggestions to take from each corpus.
-     * @param promoted    the list to which promoted suggestions are added.
-     * @return the number of suggestions actually promoted.
-     */
-    private int roundRobin(LinkedList<CorpusResult> results, int maxPromoted, int stripeSize,
-            ListSuggestionCursor promoted) {
-        int count = 0;
-        if (maxPromoted > 0 && !results.isEmpty()) {
-            for (Iterator<CorpusResult> iter = results.iterator();
-                 count < maxPromoted && iter.hasNext();) {
-                CorpusResult result = iter.next();
-                count += promote(result, stripeSize, promoted);
-                if (result.getPosition() == result.getCount()) {
-                    iter.remove();
-                }
-            }
-        }
-        return count;
-    }
-
-    /**
-     * Copies suggestions from a SuggestionCursor to the list of promoted suggestions.
-     *
-     * @param cursor from which to copy the suggestions
-     * @param count maximum number of suggestions to copy
-     * @param promoted the list to which to add the suggestions
-     * @return the number of suggestions actually copied.
-     */
-    private int promote(SuggestionCursor cursor, int count, ListSuggestionCursor promoted) {
-        if (count < 1 || cursor.getPosition() >= cursor.getCount()) {
-            return 0;
-        }
-        int addedCount = 0;
-        do {
-            if (accept(cursor)) {
-                if (promoted.add(new SuggestionPosition(cursor))) {
-                    // Added successfully (wasn't already promoted).
-                    addedCount++;
-                }
-            }
-        } while (cursor.moveToNext() && addedCount < count);
-        return addedCount;
-    }
-
-}
diff --git a/src/com/android/quicksearchbox/SearchActivity.java b/src/com/android/quicksearchbox/SearchActivity.java
index a6a96e9..d17e436 100644
--- a/src/com/android/quicksearchbox/SearchActivity.java
+++ b/src/com/android/quicksearchbox/SearchActivity.java
@@ -16,21 +16,9 @@
 
 package com.android.quicksearchbox;
 
-import com.android.common.Search;
-import com.android.quicksearchbox.ui.SearchActivityView;
-import com.android.quicksearchbox.ui.SuggestionClickListener;
-import com.android.quicksearchbox.ui.SuggestionsAdapter;
-import com.android.quicksearchbox.util.Consumer;
-import com.android.quicksearchbox.util.Consumers;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.CharMatcher;
-
 import android.app.Activity;
-import android.app.AlertDialog;
 import android.app.SearchManager;
-import android.content.DialogInterface;
 import android.content.Intent;
-import android.database.DataSetObserver;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Debug;
@@ -39,13 +27,15 @@
 import android.util.Log;
 import android.view.Menu;
 import android.view.View;
-import android.widget.Toast;
+
+import com.android.common.Search;
+import com.android.quicksearchbox.ui.SearchActivityView;
+import com.android.quicksearchbox.ui.SuggestionClickListener;
+import com.android.quicksearchbox.ui.SuggestionsAdapter;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.CharMatcher;
 
 import java.io.File;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
 
 /**
  * The main activity for Quick Search Box. Shows the search UI.
@@ -58,13 +48,9 @@
 
     private static final String SCHEME_CORPUS = "qsb.corpus";
 
-    public static final String INTENT_ACTION_QSB_AND_SELECT_CORPUS
-            = "com.android.quicksearchbox.action.QSB_AND_SELECT_CORPUS";
-
     private static final String INTENT_EXTRA_TRACE_START_UP = "trace_start_up";
 
     // Keys for the saved instance state.
-    private static final String INSTANCE_KEY_CORPUS = "corpus";
     private static final String INSTANCE_KEY_QUERY = "query";
 
     private static final String ACTIVITY_HELP_CONTEXT = "search";
@@ -83,18 +69,20 @@
 
     private SearchActivityView mSearchActivityView;
 
-    private CorporaObserver mCorporaObserver;
+    private Source mSource;
 
     private Bundle mAppSearchData;
 
     private final Handler mHandler = new Handler();
     private final Runnable mUpdateSuggestionsTask = new Runnable() {
+        @Override
         public void run() {
             updateSuggestions();
         }
     };
 
     private final Runnable mShowInputMethodTask = new Runnable() {
+        @Override
         public void run() {
             mSearchActivityView.showInputMethodForQuery();
         }
@@ -119,13 +107,10 @@
         // sent as early as possible.
         QsbApplication.get(this).getSearchBaseUrlHelper();
 
+        mSource = QsbApplication.get(this).getGoogleSource();
+
         mSearchActivityView = setupContentView();
 
-        if (getConfig().showScrollingSuggestions()) {
-            mSearchActivityView.setMaxPromotedSuggestions(getConfig().getMaxPromotedSuggestions());
-        } else {
-            mSearchActivityView.limitSuggestionsToViewHeight();
-        }
         if (getConfig().showScrollingResults()) {
             mSearchActivityView.setMaxPromotedResults(getConfig().getMaxPromotedResults());
         } else {
@@ -133,12 +118,14 @@
         }
 
         mSearchActivityView.setSearchClickListener(new SearchActivityView.SearchClickListener() {
+            @Override
             public boolean onSearchClicked(int method) {
                 return SearchActivity.this.onSearchClicked(method);
             }
         });
 
         mSearchActivityView.setQueryListener(new SearchActivityView.QueryListener() {
+            @Override
             public void onQueryChanged() {
                 updateSuggestionsBuffered();
             }
@@ -147,12 +134,14 @@
         mSearchActivityView.setSuggestionClickListener(new ClickHandler());
 
         mSearchActivityView.setVoiceSearchButtonClickListener(new View.OnClickListener() {
+            @Override
             public void onClick(View view) {
                 onVoiceSearchClicked();
             }
         });
 
         View.OnClickListener finishOnClick = new View.OnClickListener() {
+            @Override
             public void onClick(View v) {
                 finish();
             }
@@ -169,8 +158,6 @@
         // is called.
         mSearchActivityView.start();
 
-        mCorporaObserver = new CorporaObserver();
-        getCorpora().registerDataSetObserver(mCorporaObserver);
         recordOnCreateDone();
     }
 
@@ -204,9 +191,7 @@
 
     protected void restoreInstanceState(Bundle savedInstanceState) {
         if (savedInstanceState == null) return;
-        String corpusName = savedInstanceState.getString(INSTANCE_KEY_CORPUS);
         String query = savedInstanceState.getString(INSTANCE_KEY_QUERY);
-        setCorpus(corpusName);
         setQuery(query, false);
     }
 
@@ -216,7 +201,6 @@
         // We don't save appSearchData, since we always get the value
         // from the intent and the user can't change it.
 
-        outState.putString(INSTANCE_KEY_CORPUS, getCorpusName());
         outState.putString(INSTANCE_KEY_QUERY, getQuery());
     }
 
@@ -227,38 +211,9 @@
         Bundle appSearchData = intent.getBundleExtra(SearchManager.APP_DATA);
         boolean selectAll = intent.getBooleanExtra(SearchManager.EXTRA_SELECT_QUERY, false);
 
-        setCorpus(corpusName);
         setQuery(query, selectAll);
         mAppSearchData = appSearchData;
 
-        if (startedIntoCorpusSelectionDialog()) {
-            mSearchActivityView.showCorpusSelectionDialog();
-        }
-    }
-
-    public boolean startedIntoCorpusSelectionDialog() {
-        return INTENT_ACTION_QSB_AND_SELECT_CORPUS.equals(getIntent().getAction());
-    }
-
-    /**
-     * Removes corpus selector intent action, so that BACK works normally after
-     * dismissing and reopening the corpus selector.
-     */
-    public void clearStartedIntoCorpusSelectionDialog() {
-        Intent oldIntent = getIntent();
-        if (SearchActivity.INTENT_ACTION_QSB_AND_SELECT_CORPUS.equals(oldIntent.getAction())) {
-            Intent newIntent = new Intent(oldIntent);
-            newIntent.setAction(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
-            setIntent(newIntent);
-        }
-    }
-
-    public static Uri getCorpusUri(Corpus corpus) {
-        if (corpus == null) return null;
-        return new Uri.Builder()
-                .scheme(SCHEME_CORPUS)
-                .authority(corpus.getName())
-                .build();
     }
 
     private String getCorpusNameFromUri(Uri uri) {
@@ -267,18 +222,6 @@
         return uri.getAuthority();
     }
 
-    private Corpus getCorpus() {
-        return mSearchActivityView.getCorpus();
-    }
-
-    private String getCorpusName() {
-        return mSearchActivityView.getCorpusName();
-    }
-
-    private void setCorpus(String name) {
-        mSearchActivityView.setCorpus(name);
-    }
-
     private QsbApplication getQsbApplication() {
         return QsbApplication.get(this);
     }
@@ -291,18 +234,6 @@
         return getQsbApplication().getSettings();
     }
 
-    private Corpora getCorpora() {
-        return getQsbApplication().getCorpora();
-    }
-
-    private CorpusRanker getCorpusRanker() {
-        return getQsbApplication().getCorpusRanker();
-    }
-
-    private ShortcutRepository getShortcutRepository() {
-        return getQsbApplication().getShortcutRepository();
-    }
-
     private SuggestionsProvider getSuggestionsProvider() {
         return getQsbApplication().getSuggestionsProvider();
     }
@@ -319,7 +250,6 @@
     @Override
     protected void onDestroy() {
         if (DBG) Log.d(TAG, "onDestroy()");
-        getCorpora().unregisterDataSetObserver(mCorporaObserver);
         mSearchActivityView.destroy();
         super.onDestroy();
         if (mDestroyListener != null) {
@@ -339,7 +269,6 @@
         // Close all open suggestion cursors. The query will be redone in onResume()
         // if we come back to this activity.
         mSearchActivityView.clearSuggestions();
-        getQsbApplication().getShortcutRefresher().reset();
         mSearchActivityView.onStop();
         super.onStop();
     }
@@ -375,7 +304,6 @@
     }
 
     public void createMenuItems(Menu menu, boolean showDisabled) {
-        getSettings().addMenuItems(menu, showDisabled);
         getQsbApplication().getHelp().addHelpMenuItem(menu, ACTIVITY_HELP_CONTEXT);
     }
 
@@ -396,17 +324,6 @@
         mSearchActivityView.setQuery(query, selectAll);
     }
 
-    public CorpusSelectionDialog getCorpusSelectionDialog() {
-        CorpusSelectionDialog dialog = createCorpusSelectionDialog();
-        dialog.setOwnerActivity(this);
-        dialog.setOnDismissListener(new CorpusSelectorDismissListener());
-        return dialog;
-    }
-
-    protected CorpusSelectionDialog createCorpusSelectionDialog() {
-        return new CorpusSelectionDialog(this, getSettings());
-    }
-
     /**
      * @return true if a search was performed as a result of this click, false otherwise.
      */
@@ -417,45 +334,40 @@
         // Don't do empty queries
         if (TextUtils.getTrimmedLength(query) == 0) return false;
 
-        Corpus searchCorpus = getSearchCorpus();
-        if (searchCorpus == null) return false;
-
         mTookAction = true;
 
         // Log search start
-        getLogger().logSearch(getCorpus(), method, query.length());
+        getLogger().logSearch(method, query.length());
 
         // Start search
-        startSearch(searchCorpus, query);
+        startSearch(mSource, query);
         return true;
     }
 
-    protected void startSearch(Corpus searchCorpus, String query) {
-        Intent intent = searchCorpus.createSearchIntent(query, mAppSearchData);
+    protected void startSearch(Source searchSource, String query) {
+        Intent intent = searchSource.createSearchIntent(query, mAppSearchData);
         launchIntent(intent);
     }
 
     protected void onVoiceSearchClicked() {
         if (DBG) Log.d(TAG, "Voice Search clicked");
-        Corpus searchCorpus = getSearchCorpus();
-        if (searchCorpus == null) return;
 
         mTookAction = true;
 
         // Log voice search start
-        getLogger().logVoiceSearch(searchCorpus);
+        getLogger().logVoiceSearch();
 
         // Start voice search
-        Intent intent = searchCorpus.createVoiceSearchIntent(mAppSearchData);
+        Intent intent = mSource.createVoiceSearchIntent(mAppSearchData);
         launchIntent(intent);
     }
 
-    protected Corpus getSearchCorpus() {
-        return mSearchActivityView.getSearchCorpus();
+    protected Source getSearchSource() {
+        return mSource;
     }
 
     protected SuggestionCursor getCurrentSuggestions() {
-        return mSearchActivityView.getCurrentPromotedSuggestions();
+        return mSearchActivityView.getSuggestions().getResult();
     }
 
     protected SuggestionPosition getCurrentSuggestions(SuggestionsAdapter<?> adapter, long id) {
@@ -477,11 +389,6 @@
         return pos;
     }
 
-    protected Set<Corpus> getCurrentIncludedCorpora() {
-        Suggestions suggestions = mSearchActivityView.getSuggestions();
-        return suggestions == null  ? null : suggestions.getIncludedCorpora();
-    }
-
     protected void launchIntent(Intent intent) {
         if (DBG) Log.d(TAG, "launchIntent " + intent);
         if (intent == null) {
@@ -504,12 +411,9 @@
         mTookAction = true;
 
         // Log suggestion click
-        getLogger().logSuggestionClick(id, suggestion.getCursor(), getCurrentIncludedCorpora(),
+        getLogger().logSuggestionClick(id, suggestion.getCursor(),
                 Logger.SUGGESTION_CLICK_TYPE_LAUNCH);
 
-        // Create shortcut
-        getShortcutRepository().reportClick(suggestion.getCursor(), suggestion.getPosition());
-
         // Launch intent
         launchSuggestion(suggestion.getCursor(), suggestion.getPosition());
 
@@ -522,68 +426,6 @@
         launchIntent(intent);
     }
 
-    protected void removeFromHistoryClicked(final SuggestionsAdapter<?> adapter,
-            final long id) {
-        SuggestionPosition suggestion = getCurrentSuggestions(adapter, id);
-        if (suggestion == null) return;
-        CharSequence title = suggestion.getSuggestionText1();
-        AlertDialog dialog = new AlertDialog.Builder(this)
-                .setTitle(title)
-                .setMessage(R.string.remove_from_history)
-                .setPositiveButton(android.R.string.ok,
-                        new DialogInterface.OnClickListener() {
-                            public void onClick(DialogInterface dialog, int which) {
-                                // TODO: what if the suggestions have changed?
-                                removeFromHistory(adapter, id);
-                            }
-                        })
-                .setNegativeButton(android.R.string.cancel, null)
-                .create();
-        dialog.show();
-    }
-
-    protected void removeFromHistory(SuggestionsAdapter<?> adapter, long id) {
-        SuggestionPosition suggestion = getCurrentSuggestions(adapter, id);
-        if (suggestion == null) return;
-        removeFromHistory(suggestion.getCursor(), suggestion.getPosition());
-        // TODO: Log to event log?
-    }
-
-    protected void removeFromHistory(SuggestionCursor suggestions, int position) {
-        removeShortcut(suggestions, position);
-        removeFromHistoryDone(true);
-    }
-
-    protected void removeFromHistoryDone(boolean ok) {
-        Log.i(TAG, "Removed query from history, success=" + ok);
-        updateSuggestionsBuffered();
-        if (!ok) {
-            Toast.makeText(this, R.string.remove_from_history_failed, Toast.LENGTH_SHORT).show();
-        }
-    }
-
-    protected void removeShortcut(SuggestionCursor suggestions, int position) {
-        if (suggestions.isSuggestionShortcut()) {
-            if (DBG) Log.d(TAG, "Removing suggestion " + position + " from shortcuts");
-            getShortcutRepository().removeFromHistory(suggestions, position);
-        }
-    }
-
-    protected void clickedQuickContact(SuggestionsAdapter<?> adapter, long id) {
-        SuggestionPosition suggestion = getCurrentSuggestions(adapter, id);
-        if (suggestion == null) return;
-
-        if (DBG) Log.d(TAG, "Used suggestion " + suggestion.getPosition());
-        mTookAction = true;
-
-        // Log suggestion click
-        getLogger().logSuggestionClick(id, suggestion.getCursor(), getCurrentIncludedCorpora(),
-                Logger.SUGGESTION_CLICK_TYPE_QUICK_CONTACT);
-
-        // Create shortcut
-        getShortcutRepository().reportClick(suggestion.getCursor(), suggestion.getPosition());
-    }
-
     protected void refineSuggestion(SuggestionsAdapter<?> adapter, long id) {
         if (DBG) Log.d(TAG, "query refine clicked, pos " + id);
         SuggestionPosition suggestion = getCurrentSuggestions(adapter, id);
@@ -596,7 +438,7 @@
         }
 
         // Log refine click
-        getLogger().logSuggestionClick(id, suggestion.getCursor(), getCurrentIncludedCorpora(),
+        getLogger().logSuggestionClick(id, suggestion.getCursor(),
                 Logger.SUGGESTION_CLICK_TYPE_REFINE);
 
         // Put query + space in query text view
@@ -618,60 +460,21 @@
             mStarting = false;
             String source = getIntent().getStringExtra(Search.SOURCE);
             int latency = mStartLatencyTracker.getLatency();
-            getLogger().logStart(mOnCreateLatency, latency, source, getCorpus(),
-                    suggestions == null ? null : suggestions.getExpectedCorpora());
+            getLogger().logStart(mOnCreateLatency, latency, source);
             getQsbApplication().onStartupComplete();
         }
     }
 
-    private void getCorporaToQuery(Consumer<List<Corpus>> consumer) {
-        Corpus corpus = getCorpus();
-        if (corpus == null) {
-            getCorpusRanker().getCorporaInAll(Consumers.createAsyncConsumer(mHandler, consumer));
-        } else {
-            List<Corpus> corpora = new ArrayList<Corpus>();
-            Corpus searchCorpus = getSearchCorpus();
-            if (searchCorpus != null) corpora.add(searchCorpus);
-            consumer.consume(corpora);
-        }
-    }
-
-    protected void getShortcutsForQuery(String query, Collection<Corpus> corporaToQuery,
-            final Suggestions suggestions) {
-        ShortcutRepository shortcutRepo = getShortcutRepository();
-        if (shortcutRepo == null) return;
-        if (query.length() == 0 && !getConfig().showShortcutsForZeroQuery()) {
-            return;
-        }
-        Consumer<ShortcutCursor> consumer = Consumers.createAsyncCloseableConsumer(mHandler,
-                new Consumer<ShortcutCursor>() {
-            public boolean consume(ShortcutCursor shortcuts) {
-                suggestions.setShortcuts(shortcuts);
-                return true;
-            }
-        });
-        shortcutRepo.getShortcutsForQuery(query, corporaToQuery,
-                getSettings().allowWebSearchShortcuts(), consumer);
-    }
-
     public void updateSuggestions() {
         if (DBG) Log.d(TAG, "updateSuggestions()");
         final String query = CharMatcher.WHITESPACE.trimLeadingFrom(getQuery());
-        getQsbApplication().getSourceTaskExecutor().cancelPendingTasks();
-        getCorporaToQuery(new Consumer<List<Corpus>>(){
-            @Override
-            public boolean consume(List<Corpus> corporaToQuery) {
-                updateSuggestions(query, corporaToQuery);
-                return true;
-            }
-        });
+        updateSuggestions(query, mSource);
     }
 
-    protected void updateSuggestions(String query, List<Corpus> corporaToQuery) {
-        if (DBG) Log.d(TAG, "updateSuggestions(\"" + query+"\"," + corporaToQuery + ")");
+    protected void updateSuggestions(String query, Source source) {
+        if (DBG) Log.d(TAG, "updateSuggestions(\"" + query+"\"," + source + ")");
         Suggestions suggestions = getSuggestionsProvider().getSuggestions(
-                query, corporaToQuery);
-        getShortcutsForQuery(query, corporaToQuery, suggestions);
+                query, source);
 
         // Log start latency if this is the first suggestions update
         gotSuggestions(suggestions);
@@ -685,38 +488,17 @@
 
     private class ClickHandler implements SuggestionClickListener {
 
-        public void onSuggestionQuickContactClicked(SuggestionsAdapter<?> adapter, long id) {
-            clickedQuickContact(adapter, id);
-        }
-
+        @Override
         public void onSuggestionClicked(SuggestionsAdapter<?> adapter, long id) {
             launchSuggestion(adapter, id);
         }
 
-        public void onSuggestionRemoveFromHistoryClicked(SuggestionsAdapter<?> adapter, long id) {
-            removeFromHistoryClicked(adapter, id);
-        }
-
+        @Override
         public void onSuggestionQueryRefineClicked(SuggestionsAdapter<?> adapter, long id) {
             refineSuggestion(adapter, id);
         }
     }
 
-    private class CorpusSelectorDismissListener implements DialogInterface.OnDismissListener {
-        public void onDismiss(DialogInterface dialog) {
-            if (DBG) Log.d(TAG, "Corpus selector dismissed");
-            clearStartedIntoCorpusSelectionDialog();
-        }
-    }
-
-    private class CorporaObserver extends DataSetObserver {
-        @Override
-        public void onChanged() {
-            setCorpus(getCorpusName());
-            updateSuggestions();
-        }
-    }
-
     public interface OnDestroyListener {
         void onDestroyed();
     }
diff --git a/src/com/android/quicksearchbox/SearchSettings.java b/src/com/android/quicksearchbox/SearchSettings.java
index 68bca43..7b1a8a9 100644
--- a/src/com/android/quicksearchbox/SearchSettings.java
+++ b/src/com/android/quicksearchbox/SearchSettings.java
@@ -16,8 +16,6 @@
 
 package com.android.quicksearchbox;
 
-import android.content.Intent;
-import android.view.Menu;
 
 /**
  * Interface for search settings.
@@ -30,27 +28,17 @@
 
     public void upgradeSettingsIfNeeded();
 
-    public Intent getSearchableItemsIntent();
-
-    public boolean isCorpusEnabled(Corpus corpus);
-
     /**
      * Informs our listeners about the updated settings data.
      */
     public void broadcastSettingsChanged();
 
-    public void addMenuItems(Menu menu, boolean showDisabled);
-
     public int getNextVoiceSearchHintIndex(int size);
 
     public void resetVoiceSearchHintFirstSeenTime();
 
     public boolean haveVoiceSearchHintsExpired(int currentVoiceSearchVersion);
 
-    public Intent getSearchSettingsIntent();
-
-    public boolean allowWebSearchShortcuts();
-
     /**
      * Determines whether google.com should be used as the base path
      * for all searches (as opposed to using its country specific variants).
diff --git a/src/com/android/quicksearchbox/SearchSettingsImpl.java b/src/com/android/quicksearchbox/SearchSettingsImpl.java
index 4e3232b..1fc74ea 100644
--- a/src/com/android/quicksearchbox/SearchSettingsImpl.java
+++ b/src/com/android/quicksearchbox/SearchSettingsImpl.java
@@ -16,17 +16,14 @@
 
 package com.android.quicksearchbox;
 
-import com.android.common.SharedPreferencesCompat;
-
 import android.app.SearchManager;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.SharedPreferences.Editor;
 import android.util.Log;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
+
+import com.android.common.SharedPreferencesCompat;
 
 /**
  * Manages user settings.
@@ -39,10 +36,6 @@
     // Name of the preferences file used to store search preference
     public static final String PREFERENCES_NAME = "SearchSettings";
 
-    // Intent action that opens the "Searchable Items" preference
-    private static final String ACTION_SEARCHABLE_ITEMS =
-            "com.android.quicksearchbox.action.SEARCHABLE_ITEMS";
-
     /**
      * Preference key used for storing the index of the next voice search hint to show.
      */
@@ -77,11 +70,6 @@
      */
     private static final String SEARCH_BASE_DOMAIN_APPLY_TIME = "search_base_domain_apply_time";
 
-    /**
-     * Prefix of per-corpus enable preference
-     */
-    private static final String CORPUS_ENABLED_PREF_PREFIX = "enable_corpus_";
-
     private final Context mContext;
 
     private final Config mConfig;
@@ -99,30 +87,10 @@
         return mConfig;
     }
 
+    @Override
     public void upgradeSettingsIfNeeded() {
     }
 
-    public Intent getSearchableItemsIntent() {
-        Intent intent = new Intent(ACTION_SEARCHABLE_ITEMS);
-        intent.setPackage(getContext().getPackageName());
-        return intent;
-    }
-
-    /**
-     * Gets the preference key of the preference for whether the given corpus
-     * is enabled. The preference is stored in the {@link #PREFERENCES_NAME}
-     * preferences file.
-     */
-    public static String getCorpusEnabledPreference(Corpus corpus) {
-        return CORPUS_ENABLED_PREF_PREFIX + corpus.getName();
-    }
-
-    public boolean isCorpusEnabled(Corpus corpus) {
-        boolean defaultEnabled = corpus.isCorpusDefaultEnabled();
-        String sourceEnabledPref = getCorpusEnabledPreference(corpus);
-        return getSearchPreferences().getBoolean(sourceEnabledPref, defaultEnabled);
-    }
-
     public SharedPreferences getSearchPreferences() {
         return getContext().getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE);
     }
@@ -150,6 +118,7 @@
     /**
      * Informs our listeners about the updated settings data.
      */
+    @Override
     public void broadcastSettingsChanged() {
         // We use a message broadcast since the listeners could be in multiple processes.
         Intent intent = new Intent(SearchManager.INTENT_ACTION_SEARCH_SETTINGS_CHANGED);
@@ -157,20 +126,7 @@
         getContext().sendBroadcast(intent);
     }
 
-    public void addMenuItems(Menu menu, boolean showDisabled) {
-        MenuInflater inflater = new MenuInflater(getContext());
-        inflater.inflate(R.menu.settings, menu);
-        MenuItem item = menu.findItem(R.id.menu_settings);
-        item.setIntent(getSearchSettingsIntent());
-    }
-
-    public Intent getSearchSettingsIntent() {
-        Intent settings = new Intent(SearchManager.INTENT_ACTION_SEARCH_SETTINGS);
-        settings.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
-        settings.setPackage(getContext().getPackageName());
-        return settings;
-    }
-
+    @Override
     public int getNextVoiceSearchHintIndex(int size) {
             int i = getAndIncrementIntPreference(getSearchPreferences(),
                     NEXT_VOICE_SEARCH_HINT_INDEX_PREF);
@@ -184,10 +140,12 @@
         return i;
     }
 
+    @Override
     public void resetVoiceSearchHintFirstSeenTime() {
         storeLong(FIRST_VOICE_HINT_DISPLAY_TIME, System.currentTimeMillis());
     }
 
+    @Override
     public boolean haveVoiceSearchHintsExpired(int currentVoiceSearchVersion) {
         SharedPreferences prefs = getSearchPreferences();
 
@@ -213,10 +171,6 @@
         }
     }
 
-    public boolean allowWebSearchShortcuts() {
-        return true;
-    }
-
     /**
      * @return true if user searches should always be based at google.com, false
      *     otherwise.
diff --git a/src/com/android/quicksearchbox/SearchableCorpora.java b/src/com/android/quicksearchbox/SearchableCorpora.java
deleted file mode 100644
index d50bf89..0000000
--- a/src/com/android/quicksearchbox/SearchableCorpora.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (C) 2009 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.quicksearchbox;
-
-import android.content.Context;
-import android.database.DataSetObservable;
-import android.database.DataSetObserver;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * Maintains the list of all corpora.
- */
-public class SearchableCorpora implements Corpora {
-
-    // set to true to enable the more verbose debug logging for this file
-    private static final boolean DBG = false;
-    private static final String TAG = "QSB.DefaultCorpora";
-
-    private final DataSetObservable mDataSetObservable = new DataSetObservable();
-
-    private final Context mContext;
-    private final SearchSettings mSettings;
-    private final CorpusFactory mCorpusFactory;
-
-    private Sources mSources;
-    // Maps corpus names to corpora
-    private HashMap<String,Corpus> mCorporaByName;
-    // Maps sources to the corpus that contains them
-    private HashMap<Source,Corpus> mCorporaBySource;
-    // Enabled corpora
-    private List<Corpus> mEnabledCorpora;
-    // Web corpus
-    private Corpus mWebCorpus;
-
-    /**
-     *
-     * @param context Used for looking up source information etc.
-     */
-    public SearchableCorpora(Context context, SearchSettings settings, Sources sources,
-            CorpusFactory corpusFactory) {
-        mContext = context;
-        mSettings = settings;
-        mCorpusFactory = corpusFactory;
-        mSources = sources;
-    }
-
-    protected Context getContext() {
-        return mContext;
-    }
-
-    public Collection<Corpus> getAllCorpora() {
-        return Collections.unmodifiableCollection(mCorporaByName.values());
-    }
-
-    public List<Corpus> getEnabledCorpora() {
-        return mEnabledCorpora;
-    }
-
-    public List<Corpus> getCorporaInAll() {
-        ArrayList<Corpus> corpora = new ArrayList<Corpus>(mEnabledCorpora.size());
-        for (Corpus corpus : mEnabledCorpora) {
-            if (corpus.includeInAll()) {
-                corpora.add(corpus);
-            }
-        }
-        return corpora;
-    }
-
-    public Corpus getCorpus(String name) {
-        return mCorporaByName.get(name);
-    }
-
-    public Corpus getWebCorpus() {
-        return mWebCorpus;
-    }
-
-    public Corpus getCorpusForSource(Source source) {
-        return mCorporaBySource.get(source);
-    }
-
-    public Source getSource(String name) {
-        if (TextUtils.isEmpty(name)) {
-            Log.w(TAG, "Empty source name");
-            return null;
-        }
-        return mSources.getSource(name);
-    }
-
-    public void update() {
-        mSources.update();
-
-        Collection<Corpus> corpora = mCorpusFactory.createCorpora(mSources);
-
-        mCorporaByName = new HashMap<String,Corpus>(corpora.size());
-        mCorporaBySource = new HashMap<Source,Corpus>(corpora.size());
-        mEnabledCorpora = new ArrayList<Corpus>(corpora.size());
-        mWebCorpus = null;
-
-        for (Corpus corpus : corpora) {
-            mCorporaByName.put(corpus.getName(), corpus);
-            for (Source source : corpus.getSources()) {
-                mCorporaBySource.put(source, corpus);
-            }
-            if (mSettings.isCorpusEnabled(corpus)) {
-                mEnabledCorpora.add(corpus);
-            }
-            if (corpus.isWebCorpus()) {
-                if (mWebCorpus != null) {
-                    Log.w(TAG, "Multiple web corpora: " + mWebCorpus + ", " + corpus);
-                }
-                mWebCorpus = corpus;
-            }
-        }
-
-        if (DBG) Log.d(TAG, "Updated corpora: " + mCorporaBySource.values());
-
-        mEnabledCorpora = Collections.unmodifiableList(mEnabledCorpora);
-
-        notifyDataSetChanged();
-    }
-
-    public void registerDataSetObserver(DataSetObserver observer) {
-        mDataSetObservable.registerObserver(observer);
-    }
-
-    public void unregisterDataSetObserver(DataSetObserver observer) {
-        mDataSetObservable.unregisterObserver(observer);
-    }
-
-    protected void notifyDataSetChanged() {
-        mDataSetObservable.notifyChanged();
-    }
-}
diff --git a/src/com/android/quicksearchbox/SearchableCorpusFactory.java b/src/com/android/quicksearchbox/SearchableCorpusFactory.java
deleted file mode 100644
index 8acad04..0000000
--- a/src/com/android/quicksearchbox/SearchableCorpusFactory.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import com.android.quicksearchbox.util.Factory;
-
-import android.content.Context;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.concurrent.Executor;
-
-/**
- * Creates corpora.
- */
-public class SearchableCorpusFactory implements CorpusFactory {
-
-    private static final String TAG = "QSB.SearchableCorpusFactory";
-
-    private final Context mContext;
-
-    private final Config mConfig;
-
-    private final SearchSettings mSettings;
-
-    private final Factory<Executor> mWebCorpusExecutorFactory;
-
-    public SearchableCorpusFactory(Context context, Config config, SearchSettings settings,
-            Factory<Executor> webCorpusExecutorFactory) {
-        mContext = context;
-        mConfig = config;
-        mSettings = settings;
-        mWebCorpusExecutorFactory = webCorpusExecutorFactory;
-    }
-
-    public Collection<Corpus> createCorpora(Sources sources) {
-        ArrayList<Corpus> corpora = new ArrayList<Corpus>();
-        addSpecialCorpora(corpora, sources);
-        addSingleSourceCorpora(corpora, sources);
-        return corpora;
-    }
-
-    protected Context getContext() {
-        return mContext;
-    }
-
-    protected Config getConfig() {
-        return mConfig;
-    }
-
-    protected Executor createWebCorpusExecutor() {
-        return mWebCorpusExecutorFactory.create();
-    }
-
-    /**
-     * Adds any corpora that are not simple single source corpora.
-     *
-     * @param corpora List to add corpora to.
-     * @param sources All available sources.
-     */
-    protected void addSpecialCorpora(ArrayList<Corpus> corpora, Sources sources) {
-        addCorpus(corpora, createWebCorpus(sources));
-        addCorpus(corpora, createAppsCorpus(sources));
-    }
-
-    /**
-     * Adds corpora for all sources that are not already used by a corpus.
-     *
-     * @param corpora List to add the new corpora to. Corpora will not be created for the sources
-     *        used by corpora already in this list.
-     * @param sources Sources to create corpora for.
-     */
-    protected void addSingleSourceCorpora(ArrayList<Corpus> corpora, Sources sources) {
-        // Set of all sources that are already used
-        HashSet<Source> claimedSources = new HashSet<Source>();
-        for (Corpus specialCorpus : corpora) {
-            claimedSources.addAll(specialCorpus.getSources());
-        }
-
-        // Creates corpora for all unclaimed sources
-        for (Source source : sources.getSources()) {
-            if (!claimedSources.contains(source)) {
-                addCorpus(corpora, createSingleSourceCorpus(source));
-            }
-        }
-    }
-
-    private void addCorpus(ArrayList<Corpus> corpora, Corpus corpus) {
-        if (corpus != null) corpora.add(corpus);
-    }
-
-    protected Corpus createWebCorpus(Sources sources) {
-        Source webSource = getWebSource(sources);
-        if (webSource != null && !webSource.canRead()) {
-            Log.w(TAG, "Can't read web source " + webSource.getName());
-            webSource = null;
-        }
-        Source browserSource = getBrowserSource(sources);
-        if (browserSource != null && !browserSource.canRead()) {
-            Log.w(TAG, "Can't read browser source " + browserSource.getName());
-            browserSource = null;
-        }
-        Executor executor = createWebCorpusExecutor();
-        return new WebCorpus(mContext, mConfig, mSettings, executor, webSource, browserSource);
-    }
-
-    protected Corpus createAppsCorpus(Sources sources) {
-        Source appsSource = getAppsSource(sources);
-        if (appsSource == null) {
-            return null;
-        } else {
-            return new AppsCorpus(mContext, mConfig, appsSource);
-        }
-    }
-
-    protected Corpus createSingleSourceCorpus(Source source) {
-        if (!source.canRead()) return null;
-        return new SingleSourceCorpus(mContext, mConfig, source);
-    }
-
-    protected Source getWebSource(Sources sources) {
-        return sources.getWebSearchSource();
-    }
-
-    protected Source getBrowserSource(Sources sources) {
-        String name = getContext().getString(R.string.browser_search_component);
-        return sources.getSource(name);
-    }
-
-    protected Source getAppsSource(Sources sources) {
-        String name = getContext().getString(R.string.installed_apps_component);
-        return sources.getSource(name);
-    }
-
-}
diff --git a/src/com/android/quicksearchbox/SearchableSource.java b/src/com/android/quicksearchbox/SearchableSource.java
deleted file mode 100644
index f121d8d..0000000
--- a/src/com/android/quicksearchbox/SearchableSource.java
+++ /dev/null
@@ -1,472 +0,0 @@
-/*
- * Copyright (C) 2009 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.quicksearchbox;
-
-import com.android.quicksearchbox.util.NamedTaskExecutor;
-import com.android.quicksearchbox.util.Util;
-
-import android.app.PendingIntent;
-import android.app.SearchManager;
-import android.app.SearchableInfo;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.PathPermission;
-import android.content.pm.ProviderInfo;
-import android.database.Cursor;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.speech.RecognizerIntent;
-import android.util.Log;
-
-import java.util.Arrays;
-
-/**
- * Represents a single suggestion source, e.g. Contacts.
- */
-public class SearchableSource extends AbstractSource {
-
-    private static final boolean DBG = false;
-    private static final String TAG = "QSB.SearchableSource";
-
-    // TODO: This should be exposed or moved to android-common, see http://b/issue?id=2440614
-    // The extra key used in an intent to the speech recognizer for in-app voice search.
-    private static final String EXTRA_CALLING_PACKAGE = "calling_package";
-
-    private final SearchableInfo mSearchable;
-
-    private final String mName;
-
-    private final ActivityInfo mActivityInfo;
-
-    private final int mVersionCode;
-
-    // Cached label for the activity
-    private CharSequence mLabel = null;
-
-    // Cached icon for the activity
-    private Drawable.ConstantState mSourceIcon = null;
-
-    private Uri mSuggestUriBase;
-
-    public SearchableSource(Context context, SearchableInfo searchable, Handler uiThread,
-            NamedTaskExecutor iconLoader) throws NameNotFoundException {
-        super(context, uiThread, iconLoader);
-        ComponentName componentName = searchable.getSearchActivity();
-        if (DBG) Log.d(TAG, "created Searchable for " + componentName);
-        mSearchable = searchable;
-        mName = componentName.flattenToShortString();
-        PackageManager pm = context.getPackageManager();
-        mActivityInfo = pm.getActivityInfo(componentName, 0);
-        PackageInfo pkgInfo = pm.getPackageInfo(componentName.getPackageName(), 0);
-        mVersionCode = pkgInfo.versionCode;
-    }
-
-    public SearchableInfo getSearchableInfo() {
-        return mSearchable;
-    }
-
-    /**
-     * Checks if the current process can read the suggestion provider in this source.
-     */
-    public boolean canRead() {
-        String authority = mSearchable.getSuggestAuthority();
-        if (authority == null) {
-            // TODO: maybe we should have a way to distinguish between having suggestions
-            // and being readable.
-            return true;
-        }
-
-        Uri.Builder uriBuilder = new Uri.Builder()
-                .scheme(ContentResolver.SCHEME_CONTENT)
-                .authority(authority);
-        // if content path provided, insert it now
-        String contentPath = mSearchable.getSuggestPath();
-        if (contentPath != null) {
-            uriBuilder.appendEncodedPath(contentPath);
-        }
-        // append standard suggestion query path
-        uriBuilder.appendEncodedPath(SearchManager.SUGGEST_URI_PATH_QUERY);
-        Uri uri = uriBuilder.build();
-        return canRead(uri);
-    }
-
-    /**
-     * Checks if the current process can read the given content URI.
-     *
-     * TODO: Shouldn't this be a PackageManager / Context / ContentResolver method?
-     */
-    private boolean canRead(Uri uri) {
-        ProviderInfo provider = getContext().getPackageManager().resolveContentProvider(
-                uri.getAuthority(), 0);
-        if (provider == null) {
-            Log.w(TAG, getName() + " has bad suggestion authority " + uri.getAuthority());
-            return false;
-        }
-        String readPermission = provider.readPermission;
-        if (readPermission == null) {
-            // No permission required to read anything in the content provider
-            return true;
-        }
-        int pid = android.os.Process.myPid();
-        int uid = android.os.Process.myUid();
-        if (getContext().checkPermission(readPermission, pid, uid)
-                == PackageManager.PERMISSION_GRANTED) {
-            // We have permission to read everything in the content provider
-            return true;
-        }
-        PathPermission[] pathPermissions = provider.pathPermissions;
-        if (pathPermissions == null || pathPermissions.length == 0) {
-            // We don't have the readPermission, and there are no pathPermissions
-            if (DBG) Log.d(TAG, "Missing " + readPermission);
-            return false;
-        }
-        String path = uri.getPath();
-        for (PathPermission perm : pathPermissions) {
-            String pathReadPermission = perm.getReadPermission();
-            if (pathReadPermission != null
-                    && perm.match(path)
-                    && getContext().checkPermission(pathReadPermission, pid, uid)
-                            == PackageManager.PERMISSION_GRANTED) {
-                // We have the path permission
-                return true;
-            }
-        }
-        if (DBG) Log.d(TAG, "Missing " + readPermission + " and no path permission applies");
-        return false;
-    }
-
-    public ComponentName getIntentComponent() {
-        return mSearchable.getSearchActivity();
-    }
-
-    public int getVersionCode() {
-        return mVersionCode;
-    }
-
-    public String getName() {
-        return mName;
-    }
-
-    @Override
-    protected String getIconPackage() {
-        // Get icons from the package containing the suggestion provider, if any
-        String iconPackage = mSearchable.getSuggestPackage();
-        if (iconPackage != null) {
-            return iconPackage;
-        } else {
-            // Fall back to the package containing the searchable activity
-            return mSearchable.getSearchActivity().getPackageName();
-        }
-    }
-
-    public CharSequence getLabel() {
-        if (mLabel == null) {
-            // Load label lazily
-            mLabel = mActivityInfo.loadLabel(getContext().getPackageManager());
-        }
-        return mLabel;
-    }
-
-    public CharSequence getHint() {
-        return getText(mSearchable.getHintId());
-    }
-
-    public int getQueryThreshold() {
-        return mSearchable.getSuggestThreshold();
-    }
-
-    public CharSequence getSettingsDescription() {
-        return getText(mSearchable.getSettingsDescriptionId());
-    }
-
-    public Drawable getSourceIcon() {
-        if (mSourceIcon == null) {
-            Drawable icon = loadSourceIcon();
-            if (icon == null) {
-                icon = getContext().getResources().getDrawable(R.drawable.corpus_icon_default);
-            }
-            // Can't share Drawable instances, save constant state instead.
-            mSourceIcon = (icon != null) ? icon.getConstantState() : null;
-            // Optimization, return the Drawable the first time
-            return icon;
-        }
-        return (mSourceIcon != null) ? mSourceIcon.newDrawable() : null;
-    }
-
-    private Drawable loadSourceIcon() {
-        int iconRes = getSourceIconResource();
-        if (iconRes == 0) return null;
-        PackageManager pm = getContext().getPackageManager();
-        return pm.getDrawable(mActivityInfo.packageName, iconRes,
-                mActivityInfo.applicationInfo);
-    }
-
-    public Uri getSourceIconUri() {
-        int resourceId = getSourceIconResource();
-        if (resourceId == 0) {
-            return Util.getResourceUri(getContext(), R.drawable.corpus_icon_default);
-        } else {
-            return Util.getResourceUri(getContext(), mActivityInfo.applicationInfo, resourceId);
-        }
-    }
-
-    private int getSourceIconResource() {
-        return mActivityInfo.getIconResource();
-    }
-
-    public boolean voiceSearchEnabled() {
-        return mSearchable.getVoiceSearchEnabled();
-    }
-
-    public Intent createVoiceSearchIntent(Bundle appData) {
-        if (mSearchable.getVoiceSearchLaunchWebSearch()) {
-            return createVoiceWebSearchIntent(appData);
-        } else if (mSearchable.getVoiceSearchLaunchRecognizer()) {
-            return createVoiceAppSearchIntent(appData);
-        }
-        return null;
-    }
-
-    /**
-     * Create and return an Intent that can launch the voice search activity, perform a specific
-     * voice transcription, and forward the results to the searchable activity.
-     *
-     * This code is copied from SearchDialog
-     *
-     * @return A completely-configured intent ready to send to the voice search activity
-     */
-    private Intent createVoiceAppSearchIntent(Bundle appData) {
-        ComponentName searchActivity = mSearchable.getSearchActivity();
-
-        // create the necessary intent to set up a search-and-forward operation
-        // in the voice search system.   We have to keep the bundle separate,
-        // because it becomes immutable once it enters the PendingIntent
-        Intent queryIntent = new Intent(Intent.ACTION_SEARCH);
-        queryIntent.setComponent(searchActivity);
-        PendingIntent pending = PendingIntent.getActivity(
-                getContext(), 0, queryIntent, PendingIntent.FLAG_ONE_SHOT);
-
-        // Now set up the bundle that will be inserted into the pending intent
-        // when it's time to do the search.  We always build it here (even if empty)
-        // because the voice search activity will always need to insert "QUERY" into
-        // it anyway.
-        Bundle queryExtras = new Bundle();
-        if (appData != null) {
-            queryExtras.putBundle(SearchManager.APP_DATA, appData);
-        }
-
-        // Now build the intent to launch the voice search.  Add all necessary
-        // extras to launch the voice recognizer, and then all the necessary extras
-        // to forward the results to the searchable activity
-        Intent voiceIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
-        voiceIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
-        // Add all of the configuration options supplied by the searchable's metadata
-        String languageModel = getString(mSearchable.getVoiceLanguageModeId());
-        if (languageModel == null) {
-            languageModel = RecognizerIntent.LANGUAGE_MODEL_FREE_FORM;
-        }
-        String prompt = getString(mSearchable.getVoicePromptTextId());
-        String language = getString(mSearchable.getVoiceLanguageId());
-        int maxResults = mSearchable.getVoiceMaxResults();
-        if (maxResults <= 0) {
-            maxResults = 1;
-        }
-
-        voiceIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, languageModel);
-        voiceIntent.putExtra(RecognizerIntent.EXTRA_PROMPT, prompt);
-        voiceIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
-        voiceIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, maxResults);
-        voiceIntent.putExtra(EXTRA_CALLING_PACKAGE,
-                searchActivity == null ? null : searchActivity.toShortString());
-
-        // Add the values that configure forwarding the results
-        voiceIntent.putExtra(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT, pending);
-        voiceIntent.putExtra(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT_BUNDLE, queryExtras);
-
-        return voiceIntent;
-    }
-
-    public SourceResult getSuggestions(String query, int queryLimit, boolean onlySource) {
-        try {
-            Cursor cursor = getSuggestions(getContext(), mSearchable, query, queryLimit);
-            if (DBG) Log.d(TAG, toString() + "[" + query + "] returned.");
-            return new CursorBackedSourceResult(this, query, cursor);
-        } catch (RuntimeException ex) {
-            Log.e(TAG, toString() + "[" + query + "] failed", ex);
-            return new CursorBackedSourceResult(this, query);
-        }
-    }
-
-    public SuggestionCursor refreshShortcut(String shortcutId, String extraData) {
-        Cursor cursor = null;
-        try {
-            cursor = getValidationCursor(getContext(), mSearchable, shortcutId, extraData);
-            if (DBG) Log.d(TAG, toString() + "[" + shortcutId + "] returned.");
-            if (cursor != null && cursor.getCount() > 0) {
-                cursor.moveToFirst();
-            }
-            return new CursorBackedSourceResult(this, null, cursor);
-        } catch (RuntimeException ex) {
-            Log.e(TAG, toString() + "[" + shortcutId + "] failed", ex);
-            if (cursor != null) {
-                cursor.close();
-            }
-            // TODO: Should we delete the shortcut even if the failure is temporary?
-            return null;
-        }
-    }
-
-    public String getSuggestUri() {
-        Uri uri = getSuggestUriBase(mSearchable);
-        if (uri == null) return null;
-        return uri.toString();
-    }
-
-    private synchronized Uri getSuggestUriBase(SearchableInfo searchable) {
-        if (searchable == null) {
-            return null;
-        }
-        if (mSuggestUriBase == null) {
-
-            String authority = searchable.getSuggestAuthority();
-            if (authority == null) {
-                return null;
-            }
-
-            Uri.Builder uriBuilder = new Uri.Builder()
-                    .scheme(ContentResolver.SCHEME_CONTENT)
-                    .authority(authority);
-
-            // if content path provided, insert it now
-            final String contentPath = searchable.getSuggestPath();
-            if (contentPath != null) {
-                uriBuilder.appendEncodedPath(contentPath);
-            }
-
-            // append standard suggestion query path
-            uriBuilder.appendPath(SearchManager.SUGGEST_URI_PATH_QUERY);
-            mSuggestUriBase = uriBuilder.build();
-        }
-        return mSuggestUriBase;
-    }
-
-    /**
-     * This is a copy of {@link SearchManager#getSuggestions(SearchableInfo, String)}.
-     */
-    private Cursor getSuggestions(Context context, SearchableInfo searchable, String query,
-            int queryLimit) {
-
-        Uri base = getSuggestUriBase(searchable);
-        if (base == null) return null;
-        Uri.Builder uriBuilder = base.buildUpon();
-
-        // get the query selection, may be null
-        String selection = searchable.getSuggestSelection();
-        // inject query, either as selection args or inline
-        String[] selArgs = null;
-        if (selection != null) {    // use selection if provided
-            selArgs = new String[] { query };
-        } else {                    // no selection, use REST pattern
-            uriBuilder.appendPath(query);
-        }
-
-        uriBuilder.appendQueryParameter("limit", String.valueOf(queryLimit));
-
-        Uri uri = uriBuilder.build();
-
-        // finally, make the query
-        if (DBG) {
-            Log.d(TAG, "query(" + uri + ",null," + selection + ","
-                    + Arrays.toString(selArgs) + ",null)");
-        }
-        Cursor c = context.getContentResolver().query(uri, null, selection, selArgs, null);
-        if (DBG) Log.d(TAG, "Got cursor from " + mName + ": " + c);
-        return c;
-    }
-
-    private static Cursor getValidationCursor(Context context, SearchableInfo searchable,
-            String shortcutId, String extraData) {
-        String authority = searchable.getSuggestAuthority();
-        if (authority == null) {
-            return null;
-        }
-
-        Uri.Builder uriBuilder = new Uri.Builder()
-                .scheme(ContentResolver.SCHEME_CONTENT)
-                .authority(authority);
-
-        // if content path provided, insert it now
-        final String contentPath = searchable.getSuggestPath();
-        if (contentPath != null) {
-            uriBuilder.appendEncodedPath(contentPath);
-        }
-
-        // append the shortcut path and id
-        uriBuilder.appendPath(SearchManager.SUGGEST_URI_PATH_SHORTCUT);
-        uriBuilder.appendPath(shortcutId);
-
-        Uri uri = uriBuilder
-                .appendQueryParameter(SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA, extraData)
-                .build();
-
-        if (DBG) Log.d(TAG, "Requesting refresh " + uri);
-        // finally, make the query
-        return context.getContentResolver().query(uri, null, null, null, null);
-    }
-
-    public int getMaxShortcuts(Config config) {
-        return config.getMaxShortcuts(getName());
-    }
-
-    public boolean includeInAll() {
-        return true;
-    }
-
-    public boolean queryAfterZeroResults() {
-        return mSearchable.queryAfterZeroResults();
-    }
-
-    public String getDefaultIntentAction() {
-        String action = mSearchable.getSuggestIntentAction();
-        if (action != null) return action;
-        return Intent.ACTION_SEARCH;
-    }
-
-    public String getDefaultIntentData() {
-        return mSearchable.getSuggestIntentData();
-    }
-
-    private CharSequence getText(int id) {
-        if (id == 0) return null;
-        return getContext().getPackageManager().getText(mActivityInfo.packageName, id,
-                mActivityInfo.applicationInfo);
-    }
-
-    private String getString(int id) {
-        CharSequence text = getText(id);
-        return text == null ? null : text.toString();
-    }
-}
diff --git a/src/com/android/quicksearchbox/SearchableSources.java b/src/com/android/quicksearchbox/SearchableSources.java
deleted file mode 100644
index 32f2034..0000000
--- a/src/com/android/quicksearchbox/SearchableSources.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 2009 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.quicksearchbox;
-
-import com.android.quicksearchbox.util.NamedTaskExecutor;
-
-import android.app.SearchManager;
-import android.app.SearchableInfo;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.os.Handler;
-import android.util.Log;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * Maintains a list of search sources.
- */
-public class SearchableSources implements Sources {
-
-    // set to true to enable the more verbose debug logging for this file
-    private static final boolean DBG = false;
-    private static final String TAG = "QSB.SearchableSources";
-
-    private final Context mContext;
-    private final SearchManager mSearchManager;
-    private final Handler mUiThread;
-    private final Config mConfig;
-
-    // All suggestion sources, by name.
-    private HashMap<String, Source> mSources;
-
-    // The web search source to use.
-    private Source mWebSearchSource;
-
-    private final NamedTaskExecutor mIconLoaderExecutor;
-
-    /**
-     *
-     * @param context Used for looking up source information etc.
-     */
-    public SearchableSources(Context context, Handler uiThread,
-            NamedTaskExecutor iconLoader, Config config) {
-        mContext = context;
-        mSearchManager = (SearchManager) context.getSystemService(Context.SEARCH_SERVICE);
-        mUiThread = uiThread;
-        mIconLoaderExecutor = iconLoader;
-        mConfig = config;
-    }
-
-    protected Context getContext() {
-        return mContext;
-    }
-
-    protected Handler getUiThreadHandler() {
-        return mUiThread;
-    }
-
-    protected SearchManager getSearchManager() {
-        return mSearchManager;
-    }
-
-    protected NamedTaskExecutor getIconLoaderExecutor() {
-        return mIconLoaderExecutor;
-    }
-
-    protected Config getConfig() {
-        return mConfig;
-    }
-
-    public Collection<Source> getSources() {
-        return mSources.values();
-    }
-
-    public Source getSource(String name) {
-        return mSources.get(name);
-    }
-
-    public Source getWebSearchSource() {
-        return mWebSearchSource;
-    }
-
-    /**
-     * Updates the list of suggestion sources.
-     */
-    public void update() {
-        if (DBG) Log.d(TAG, "update()");
-        mSources = new HashMap<String,Source>();
-
-        addSearchableSources();
-
-        addInternalSources();
-
-        mWebSearchSource = createWebSearchSource();
-        if (mWebSearchSource != null) {
-            addSource(mWebSearchSource);
-        }
-    }
-
-    protected void addInternalSources() {
-    }
-
-    private void addSearchableSources() {
-        List<SearchableInfo> searchables = mSearchManager.getSearchablesInGlobalSearch();
-        if (searchables == null) {
-            Log.e(TAG, "getSearchablesInGlobalSearch() returned null");
-            return;
-        }
-        for (SearchableInfo searchable : searchables) {
-            SearchableSource source = createSearchableSource(searchable);
-            if (source != null) {
-                if (DBG) Log.d(TAG, "Created source " + source);
-                addSource(source);
-            }
-        }
-    }
-
-    protected void addSource(Source source) {
-        mSources.put(source.getName(), source);
-    }
-
-    protected Source createWebSearchSource() {
-        return QsbApplication.get(getContext()).getGoogleSource();
-    }
-
-    protected SearchableSource createSearchableSource(SearchableInfo searchable) {
-        if (searchable == null) return null;
-        try {
-            return new SearchableSource(mContext, searchable, getUiThreadHandler(),
-                    getIconLoaderExecutor());
-        } catch (NameNotFoundException ex) {
-            Log.e(TAG, "Source not found: " + ex);
-            return null;
-        }
-    }
-
-    public Source createSourceFor(ComponentName component) {
-        SearchableInfo info = mSearchManager.getSearchableInfo(component);
-        SearchableSource source = createSearchableSource(info);
-        if (DBG) Log.d(TAG, "SearchableSource for " + component + ": " + source);
-        return source;
-    }
-}
diff --git a/src/com/android/quicksearchbox/ShortcutCursor.java b/src/com/android/quicksearchbox/ShortcutCursor.java
deleted file mode 100644
index 1f2f80e..0000000
--- a/src/com/android/quicksearchbox/ShortcutCursor.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import com.google.common.annotations.VisibleForTesting;
-
-import android.os.Handler;
-import android.util.Log;
-
-import java.util.HashSet;
-
-/**
- * A SuggestionCursor that allows shortcuts to be updated by overlaying
- * with results from another cursor.
- */
-public class ShortcutCursor extends ListSuggestionCursor {
-
-    private static final boolean DBG = false;
-    private static final String TAG = "QSB.ShortcutCursor";
-
-    // mShortcuts is used to close the underlying cursor when we're closed.
-    private final SuggestionCursor mShortcuts;
-    // mRefreshed contains all the cursors that have been refreshed, so that
-    // they can be closed when ShortcutCursor is closed.
-    private final HashSet<SuggestionCursor> mRefreshed;
-
-    private boolean mClosed = false;
-
-    private final ShortcutRefresher mRefresher;
-    private final ShortcutRepository mShortcutRepo;
-    private final Handler mUiThread;
-
-    private ShortcutCursor(String query, SuggestionCursor shortcuts, Handler uiThread,
-            ShortcutRefresher refresher, ShortcutRepository repository) {
-        super(query);
-        mShortcuts = shortcuts;
-        mUiThread = uiThread;
-        mRefresher = refresher;
-        mShortcutRepo = repository;
-        mRefreshed = new HashSet<SuggestionCursor>();
-    }
-
-    @VisibleForTesting
-    ShortcutCursor(String query, Handler uiThread,
-            ShortcutRefresher refresher, ShortcutRepository repository) {
-        this(query, null, uiThread, refresher, repository);
-    }
-
-    @VisibleForTesting
-    ShortcutCursor(SuggestionCursor suggestions) {
-        this(suggestions, true, null, null, null);
-    }
-
-    public ShortcutCursor(SuggestionCursor suggestions, boolean allowWebSearchShortcuts,
-            Handler uiThread, ShortcutRefresher refresher, ShortcutRepository repository) {
-        this(suggestions.getUserQuery(), suggestions, uiThread, refresher, repository);
-        int count = suggestions.getCount();
-        if (DBG) Log.d(TAG, "Total shortcuts: " + count);
-        for (int i = 0; i < count; i++) {
-            suggestions.moveTo(i);
-            if (suggestions.getSuggestionSource() != null
-                    && (allowWebSearchShortcuts || !suggestions.isWebSearchSuggestion())) {
-                add(new SuggestionPosition(suggestions));
-            } else {
-                if (DBG) Log.d(TAG, "Skipping shortcut " + i);
-            }
-        }
-    }
-
-    @Override
-    public boolean isSuggestionShortcut() {
-        // Needed to make refreshed shortcuts be treated as shortcuts
-        return true;
-    }
-
-    /**
-     * Refresh a shortcut from this cursor.
-     *
-     * @param shortcut The shortcut to refresh. Should be a shortcut taken from this cursor.
-     */
-    public void refresh(Suggestion shortcut) {
-        mRefresher.refresh(shortcut, new ShortcutRefresher.Listener() {
-            public void onShortcutRefreshed(final Source source,
-                    final String shortcutId, final SuggestionCursor refreshed) {
-                if (DBG) Log.d(TAG, "Shortcut refreshed: " + shortcutId);
-                mShortcutRepo.updateShortcut(source, shortcutId, refreshed);
-                mUiThread.post(new Runnable() {
-                    public void run() {
-                        refresh(source, shortcutId, refreshed);
-                    }
-                });
-            }
-        });
-    }
-
-    /**
-     * Updates this SuggestionCursor with a refreshed result from another.
-     * Since this modifies the cursor, it should be called on the UI thread.
-     * This class assumes responsibility for closing refreshed.
-     */
-    private void refresh(Source source, String shortcutId, SuggestionCursor refreshed) {
-        if (DBG) Log.d(TAG, "refresh " + shortcutId);
-        if (mClosed) {
-            if (refreshed != null) {
-                refreshed.close();
-            }
-            return;
-        }
-        if (refreshed != null) {
-            mRefreshed.add(refreshed);
-        }
-        for (int i = 0; i < getCount(); i++) {
-            moveTo(i);
-            if (shortcutId.equals(getShortcutId()) && source.equals(getSuggestionSource())) {
-                if (refreshed != null && refreshed.getCount() > 0) {
-                    if (DBG) Log.d(TAG, "replacing row " + i);
-                    replaceRow(new SuggestionPosition(refreshed));
-                } else {
-                    if (DBG) Log.d(TAG, "removing row " + i);
-                    removeRow();
-                }
-                notifyDataSetChanged();
-                break;
-            }
-        }
-    }
-
-    @Override
-    public void close() {
-        if (DBG) Log.d(TAG, "close()");
-        if (mClosed) {
-            throw new IllegalStateException("double close");
-        }
-        mClosed = true;
-        if (mShortcuts != null) {
-            mShortcuts.close();
-        }
-        for (SuggestionCursor cursor : mRefreshed) {
-            cursor.close();
-        }
-        super.close();
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/quicksearchbox/ShortcutPromoter.java b/src/com/android/quicksearchbox/ShortcutPromoter.java
deleted file mode 100644
index a27c0a6..0000000
--- a/src/com/android/quicksearchbox/ShortcutPromoter.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.HashMultiset;
-
-/**
- * A promoter limits the maximum number of shortcuts per source
- * (from non-web sources) and blends results
- * from multiple sources.
- */
-public class ShortcutPromoter extends AbstractPromoter {
-
-    public ShortcutPromoter(Config config, Promoter next, SuggestionFilter filter) {
-        super(filter, next, config);
-    }
-
-    @Override
-    public void doPickPromoted(Suggestions suggestions, int maxPromoted,
-            ListSuggestionCursor promoted) {
-        promoteShortcuts(suggestions.getShortcuts(), maxPromoted, promoted);
-    }
-
-    @VisibleForTesting
-    void promoteShortcuts(SuggestionCursor shortcuts, int maxPromoted,
-            ListSuggestionCursor promoted) {
-        int shortcutCount = shortcuts == null ? 0 : shortcuts.getCount();
-        if (shortcutCount == 0) return;
-        HashMultiset<Source> sourceShortcutCounts = HashMultiset.create(shortcutCount);
-        for (int i = 0; i < shortcutCount && promoted.getCount() < maxPromoted; i++) {
-            shortcuts.moveTo(i);
-            Source source = shortcuts.getSuggestionSource();
-            if (source != null && accept(shortcuts)) {
-                int prevCount = sourceShortcutCounts.add(source, 1);
-                int maxShortcuts = source.getMaxShortcuts(getConfig());
-                if (prevCount < maxShortcuts) {
-                    promoted.add(new SuggestionPosition(shortcuts));
-                }
-            }
-        }
-    }
-
-}
diff --git a/src/com/android/quicksearchbox/ShortcutRefresher.java b/src/com/android/quicksearchbox/ShortcutRefresher.java
deleted file mode 100644
index 34af810..0000000
--- a/src/com/android/quicksearchbox/ShortcutRefresher.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-/**
- * Fires off tasks to validate shortcuts, and reports the results back to a
- * {@link Listener}.
- */
-public interface ShortcutRefresher {
-
-    public interface Listener {
-        /**
-         * Called by the ShortcutRefresher when a shortcut has been refreshed.
-         *
-         * @param source source of this shortcut.
-         * @param shortcutId the id of the shortcut.
-         * @param refreshed the updated shortcut, or {@code null} if the shortcut
-         *        is no longer valid and should be deleted.
-         */
-        void onShortcutRefreshed(Source source, String shortcutId,
-                SuggestionCursor refreshed);
-    }
-
-    /**
-     * Starts a task to refresh a single shortcut.
-     *
-     * @param shortcut The shortcut to be refreshed.
-     * @param listener Who to report back to.
-     */
-    void refresh(Suggestion shortcut, Listener listener);
-
-    /**
-     * Returns true if the given shortcut requires refreshing.
-     */
-    boolean shouldRefresh(Source source, String shortcutId);
-
-    /**
-     * Indicates that the shortcut no longer requires refreshing.
-     */
-    public void markShortcutRefreshed(Source source, String shortcutId);
-
-    /**
-     * Resets internal state. This results in all shortcuts requiring refreshing.
-     */
-    public void reset();
-
-}
diff --git a/src/com/android/quicksearchbox/ShortcutRepository.java b/src/com/android/quicksearchbox/ShortcutRepository.java
deleted file mode 100644
index fc2f078..0000000
--- a/src/com/android/quicksearchbox/ShortcutRepository.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2009 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.quicksearchbox;
-
-import com.android.quicksearchbox.util.Consumer;
-
-import java.util.Collection;
-import java.util.Map;
-
-/**
- * Holds information about shortcuts (results the user has clicked on before), and returns
- * appropriate shortcuts for a given query.
- */
-public interface ShortcutRepository {
-
-    /**
-     * Checks whether there is any stored history.
-     *
-     * @param consumer Consumer that the result will be passed to.
-     *        The value passed to the consumer will always be non-null.
-     *        The consumer will be called on an unspecified thread, and will always
-     *        get called eventually.
-     */
-    void hasHistory(Consumer<Boolean> consumer);
-
-    /**
-     * Removes a single suggestion from the stored history.
-     */
-    void removeFromHistory(SuggestionCursor suggestions, int position);
-
-    /**
-     * Clears all shortcut history.
-     */
-    void clearHistory();
-
-    /**
-     * Closes any database connections etc held by this object.
-     */
-    void close();
-
-    /**
-     * Reports a click on a suggestion.
-     * Must be called on the UI thread.
-     */
-    void reportClick(SuggestionCursor suggestions, int position);
-
-    /**
-     * Gets shortcuts for a query.
-     *
-     * @param query The query. May be empty.
-     * @param allowedCorpora The corpora to get shortcuts for.
-     * @param allowWebSearchShortcuts Whether to include web search shortcuts.
-     * @param consumer Consumer that the shortcuts cursor will be passed to.
-     *        The shortcut cursor passed to the consumer may be null if there are no shortcuts.
-     *        If non-null, and the consumer returns {@code true}, the consumer must ensure that
-     *        the shortcut cursor will get closed eventually.
-     *        The consumer will be called on an unspecified thread, and will always
-     *        get called eventually.
-     */
-    void getShortcutsForQuery(String query, Collection<Corpus> allowedCorpora,
-            boolean allowWebSearchShortcuts,
-            Consumer<ShortcutCursor> consumer);
-
-    /**
-     * Updates a shortcut in the repository after it's been refreshed.
-     *
-     * @param source The source of the shortcut that's been refreshed
-     * @param shortcutId The ID of the shortcut that's been refershed
-     * @param refreshed The refreshed shortcut suggestion.
-     */
-    void updateShortcut(Source source, String shortcutId, SuggestionCursor refreshed);
-
-    /**
-     * Gets scores for all corpora in the click log.
-     *
-     * @param consumer Consumer that the result will be passed to.
-     *        The result is a map of corpus name to score. A higher score means that the corpus
-     *        is more important.
-     *        The value passed to the consumer may be non-null.
-     *        The consumer will be called on an unspecified thread, and will always
-     *        get called eventually.
-     */
-    void getCorpusScores(Consumer<Map<String,Integer>> consumer);
-}
diff --git a/src/com/android/quicksearchbox/ShortcutRepositoryImplLog.java b/src/com/android/quicksearchbox/ShortcutRepositoryImplLog.java
deleted file mode 100644
index 3c5bab2..0000000
--- a/src/com/android/quicksearchbox/ShortcutRepositoryImplLog.java
+++ /dev/null
@@ -1,937 +0,0 @@
-/*
- * Copyright (C) 2009 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.quicksearchbox;
-
-import com.android.quicksearchbox.util.Consumer;
-import com.android.quicksearchbox.util.Consumers;
-import com.android.quicksearchbox.util.SQLiteAsyncQuery;
-import com.android.quicksearchbox.util.SQLiteTransaction;
-import com.android.quicksearchbox.util.Util;
-import com.google.common.annotations.VisibleForTesting;
-
-import org.json.JSONException;
-
-import android.app.SearchManager;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.database.sqlite.SQLiteQueryBuilder;
-import android.net.Uri;
-import android.os.Handler;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.io.File;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.Executor;
-
-/**
- * A shortcut repository implementation that uses a log of every click.
- *
- * To inspect DB:
- * # sqlite3 /data/data/com.android.quicksearchbox/databases/qsb-log.db
- *
- * TODO: Refactor this class.
- */
-public class ShortcutRepositoryImplLog implements ShortcutRepository {
-
-    private static final boolean DBG = false;
-    private static final String TAG = "QSB.ShortcutRepositoryImplLog";
-
-    private static final String DB_NAME = "qsb-log.db";
-    private static final int DB_VERSION = 32;
-
-    private static final String HAS_HISTORY_QUERY =
-        "SELECT " + Shortcuts.intent_key.fullName + " FROM " + Shortcuts.TABLE_NAME;
-    private String mEmptyQueryShortcutQuery ;
-    private String mShortcutQuery;
-
-    private static final String SHORTCUT_BY_ID_WHERE =
-            Shortcuts.shortcut_id.name() + "=? AND " + Shortcuts.source.name() + "=?";
-
-    private static final String SOURCE_RANKING_SQL = buildSourceRankingSql();
-
-    private final Context mContext;
-    private final Config mConfig;
-    private final Corpora mCorpora;
-    private final ShortcutRefresher mRefresher;
-    private final Handler mUiThread;
-    // Used to perform log write operations asynchronously
-    private final Executor mLogExecutor;
-    private final DbOpenHelper mOpenHelper;
-    private final String mSearchSpinner;
-
-    /**
-     * Create an instance to the repo.
-     */
-    public static ShortcutRepository create(Context context, Config config,
-            Corpora sources, ShortcutRefresher refresher, Handler uiThread,
-            Executor logExecutor) {
-        return new ShortcutRepositoryImplLog(context, config, sources, refresher,
-                uiThread, logExecutor, DB_NAME);
-    }
-
-    /**
-     * @param context Used to create / open db
-     * @param name The name of the database to create.
-     */
-    @VisibleForTesting
-    ShortcutRepositoryImplLog(Context context, Config config, Corpora corpora,
-            ShortcutRefresher refresher, Handler uiThread, Executor logExecutor, String name) {
-        mContext = context;
-        mConfig = config;
-        mCorpora = corpora;
-        mRefresher = refresher;
-        mUiThread = uiThread;
-        mLogExecutor = logExecutor;
-        mOpenHelper = new DbOpenHelper(context, name, DB_VERSION, config);
-        buildShortcutQueries();
-
-        mSearchSpinner = Util.getResourceUri(mContext, R.drawable.search_spinner).toString();
-    }
-
-    // clicklog first, since that's where restrict the result set
-    private static final String TABLES = ClickLog.TABLE_NAME + " INNER JOIN " +
-            Shortcuts.TABLE_NAME + " ON " + ClickLog.intent_key.fullName + " = " +
-            Shortcuts.intent_key.fullName;
-
-    private static final String AS = " AS ";
-
-    private static final String[] SHORTCUT_QUERY_COLUMNS = {
-            Shortcuts.intent_key.fullName,
-            Shortcuts.source.fullName,
-            Shortcuts.source_version_code.fullName,
-            Shortcuts.format.fullName + AS + SearchManager.SUGGEST_COLUMN_FORMAT,
-            Shortcuts.title + AS + SearchManager.SUGGEST_COLUMN_TEXT_1,
-            Shortcuts.description + AS + SearchManager.SUGGEST_COLUMN_TEXT_2,
-            Shortcuts.description_url + AS + SearchManager.SUGGEST_COLUMN_TEXT_2_URL,
-            Shortcuts.icon1 + AS + SearchManager.SUGGEST_COLUMN_ICON_1,
-            Shortcuts.icon2 + AS + SearchManager.SUGGEST_COLUMN_ICON_2,
-            Shortcuts.intent_action + AS + SearchManager.SUGGEST_COLUMN_INTENT_ACTION,
-            Shortcuts.intent_component.fullName,
-            Shortcuts.intent_data + AS + SearchManager.SUGGEST_COLUMN_INTENT_DATA,
-            Shortcuts.intent_query + AS + SearchManager.SUGGEST_COLUMN_QUERY,
-            Shortcuts.intent_extradata + AS + SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA,
-            Shortcuts.shortcut_id + AS + SearchManager.SUGGEST_COLUMN_SHORTCUT_ID,
-            Shortcuts.spinner_while_refreshing + AS +
-                    SearchManager.SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING,
-            Shortcuts.log_type + AS + CursorBackedSuggestionCursor.SUGGEST_COLUMN_LOG_TYPE,
-            Shortcuts.custom_columns.fullName,
-        };
-
-    // Avoid GLOB by using >= AND <, with some manipulation (see nextString(String)).
-    // to figure out the upper bound (e.g. >= "abc" AND < "abd"
-    // This allows us to use parameter binding and still take advantage of the
-    // index on the query column.
-    private static final String PREFIX_RESTRICTION =
-            ClickLog.query.fullName + " >= ?1 AND " + ClickLog.query.fullName + " < ?2";
-
-    private static final String LAST_HIT_TIME_EXPR = "MAX(" + ClickLog.hit_time.fullName + ")";
-    private static final String GROUP_BY = ClickLog.intent_key.fullName;
-    private static final String PREFER_LATEST_PREFIX =
-        "(" + LAST_HIT_TIME_EXPR + " = (SELECT " + LAST_HIT_TIME_EXPR + " FROM " +
-        ClickLog.TABLE_NAME + " WHERE ";
-    private static final String PREFER_LATEST_SUFFIX = "))";
-
-    private void buildShortcutQueries() {
-        // SQL expression for the time before which no clicks should be counted.
-        String cutOffTime_expr = "(?3 - " + mConfig.getMaxStatAgeMillis() + ")";
-        // Filter out clicks that are too old
-        String ageRestriction = ClickLog.hit_time.fullName + " >= " + cutOffTime_expr;
-        String having = null;
-        // Order by sum of hit times (seconds since cutoff) for the clicks for each shortcut.
-        // This has the effect of multiplying the average hit time with the click count
-        String ordering_expr =
-                "SUM((" + ClickLog.hit_time.fullName + " - " + cutOffTime_expr + ") / 1000)";
-
-        String where = ageRestriction;
-        String preferLatest = PREFER_LATEST_PREFIX + where + PREFER_LATEST_SUFFIX;
-        String orderBy = preferLatest + " DESC, " + ordering_expr + " DESC";
-        mEmptyQueryShortcutQuery = SQLiteQueryBuilder.buildQueryString(
-                false, TABLES, SHORTCUT_QUERY_COLUMNS, where, GROUP_BY, having, orderBy, null);
-        if (DBG) Log.d(TAG, "Empty shortcut query:\n" + mEmptyQueryShortcutQuery);
-
-        where = PREFIX_RESTRICTION + " AND " + ageRestriction;
-        preferLatest = PREFER_LATEST_PREFIX + where + PREFER_LATEST_SUFFIX;
-        orderBy = preferLatest + " DESC, " + ordering_expr + " DESC";
-        mShortcutQuery = SQLiteQueryBuilder.buildQueryString(
-                false, TABLES, SHORTCUT_QUERY_COLUMNS, where, GROUP_BY, having, orderBy, null);
-        if (DBG) Log.d(TAG, "Empty shortcut:\n" + mShortcutQuery);
-    }
-
-    /**
-     * @return sql that ranks sources by total clicks, filtering out sources
-     *         without enough clicks.
-     */
-    private static String buildSourceRankingSql() {
-        final String orderingExpr = SourceStats.total_clicks.name();
-        final String tables = SourceStats.TABLE_NAME;
-        final String[] columns = SourceStats.COLUMNS;
-        final String where = SourceStats.total_clicks + " >= $1";
-        final String groupBy = null;
-        final String having = null;
-        final String orderBy = orderingExpr + " DESC";
-        final String limit = null;
-        return SQLiteQueryBuilder.buildQueryString(
-                false, tables, columns, where, groupBy, having, orderBy, limit);
-    }
-
-    protected DbOpenHelper getOpenHelper() {
-        return mOpenHelper;
-    }
-
-    private void runTransactionAsync(final SQLiteTransaction transaction) {
-        mLogExecutor.execute(new Runnable() {
-            public void run() {
-                transaction.run(mOpenHelper.getWritableDatabase());
-            }
-        });
-    }
-
-    private <A> void runQueryAsync(final SQLiteAsyncQuery<A> query, final Consumer<A> consumer) {
-        mLogExecutor.execute(new Runnable() {
-            public void run() {
-                query.run(mOpenHelper.getReadableDatabase(), consumer);
-            }
-        });
-    }
-
-// --------------------- Interface ShortcutRepository ---------------------
-
-    public void hasHistory(Consumer<Boolean> consumer) {
-        runQueryAsync(new SQLiteAsyncQuery<Boolean>() {
-            @Override
-            protected Boolean performQuery(SQLiteDatabase db) {
-                return hasHistory(db);
-            }
-        }, consumer);
-    }
-
-    public void removeFromHistory(SuggestionCursor suggestions, int position) {
-        suggestions.moveTo(position);
-        final String intentKey = makeIntentKey(suggestions);
-        runTransactionAsync(new SQLiteTransaction() {
-            @Override
-            public boolean performTransaction(SQLiteDatabase db) {
-                db.delete(Shortcuts.TABLE_NAME, Shortcuts.intent_key.fullName + " = ?",
-                        new String[]{ intentKey });
-                return true;
-            }
-        });
-    }
-
-    public void clearHistory() {
-        runTransactionAsync(new SQLiteTransaction() {
-            @Override
-            public boolean performTransaction(SQLiteDatabase db) {
-                db.delete(ClickLog.TABLE_NAME, null, null);
-                db.delete(Shortcuts.TABLE_NAME, null, null);
-                db.delete(SourceStats.TABLE_NAME, null, null);
-                return true;
-            }
-        });
-    }
-
-    @VisibleForTesting
-    public void deleteRepository() {
-        getOpenHelper().deleteDatabase();
-    }
-
-    public void close() {
-        getOpenHelper().close();
-    }
-
-    public void reportClick(final SuggestionCursor suggestions, final int position) {
-        final long now = System.currentTimeMillis();
-        reportClickAtTime(suggestions, position, now);
-    }
-
-    public void getShortcutsForQuery(final String query, final Collection<Corpus> allowedCorpora,
-            final boolean allowWebSearchShortcuts, final Consumer<ShortcutCursor> consumer) {
-        final long now = System.currentTimeMillis();
-        mLogExecutor.execute(new Runnable() {
-            public void run() {
-                ShortcutCursor shortcuts = getShortcutsForQuery(query, allowedCorpora,
-                        allowWebSearchShortcuts, now);
-                Consumers.consumeCloseable(consumer, shortcuts);
-            }
-        });
-    }
-
-    public void updateShortcut(Source source, String shortcutId, SuggestionCursor refreshed) {
-        refreshShortcut(source, shortcutId, refreshed);
-    }
-
-    public void getCorpusScores(final Consumer<Map<String, Integer>> consumer) {
-        runQueryAsync(new SQLiteAsyncQuery<Map<String, Integer>>() {
-            @Override
-            protected Map<String, Integer> performQuery(SQLiteDatabase db) {
-                return getCorpusScores();
-            }
-        }, consumer);
-    }
-
-// -------------------------- end ShortcutRepository --------------------------
-
-    private boolean hasHistory(SQLiteDatabase db) {
-        Cursor cursor = db.rawQuery(HAS_HISTORY_QUERY, null);
-        try {
-            if (DBG) Log.d(TAG, "hasHistory(): cursor=" + cursor);
-            return cursor != null && cursor.getCount() > 0;
-        } finally {
-            if (cursor != null) cursor.close();
-        }
-    }
-
-    private Map<String,Integer> getCorpusScores() {
-        return getCorpusScores(mConfig.getMinClicksForSourceRanking());
-    }
-
-    private boolean shouldRefresh(Suggestion suggestion) {
-        return mRefresher.shouldRefresh(suggestion.getSuggestionSource(),
-                suggestion.getShortcutId());
-    }
-
-    @VisibleForTesting
-    ShortcutCursor getShortcutsForQuery(String query, Collection<Corpus> allowedCorpora,
-            boolean allowWebSearchShortcuts, long now) {
-        if (DBG) Log.d(TAG, "getShortcutsForQuery(" + query + "," + allowedCorpora + ")");
-        String sql = query.length() == 0 ? mEmptyQueryShortcutQuery : mShortcutQuery;
-        String[] params = buildShortcutQueryParams(query, now);
-
-        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
-        Cursor cursor = db.rawQuery(sql, params);
-        if (cursor.getCount() == 0) {
-            cursor.close();
-            return null;
-        }
-
-        if (DBG) Log.d(TAG, "Allowed sources: ");
-        HashMap<String,Source> allowedSources = new HashMap<String,Source>();
-        for (Corpus corpus : allowedCorpora) {
-            for (Source source : corpus.getSources()) {
-                if (DBG) Log.d(TAG, "\t" + source.getName());
-                allowedSources.put(source.getName(), source);
-            }
-        }
-
-        return new ShortcutCursor(new SuggestionCursorImpl(allowedSources, query, cursor),
-                allowWebSearchShortcuts, mUiThread, mRefresher, this);
-    }
-
-    @VisibleForTesting
-    void refreshShortcut(Source source, final String shortcutId,
-            SuggestionCursor refreshed) {
-        if (source == null) throw new NullPointerException("source");
-        if (shortcutId == null) throw new NullPointerException("shortcutId");
-
-        final String[] whereArgs = { shortcutId, source.getName() };
-        final ContentValues shortcut;
-        if (refreshed == null || refreshed.getCount() == 0) {
-            shortcut = null;
-        } else {
-            refreshed.moveTo(0);
-            shortcut = makeShortcutRow(refreshed);
-        }
-
-        runTransactionAsync(new SQLiteTransaction() {
-            @Override
-            protected boolean performTransaction(SQLiteDatabase db) {
-                if (shortcut == null) {
-                    if (DBG) Log.d(TAG, "Deleting shortcut: " + shortcutId);
-                    db.delete(Shortcuts.TABLE_NAME, SHORTCUT_BY_ID_WHERE, whereArgs);
-                } else {
-                    if (DBG) Log.d(TAG, "Updating shortcut: " + shortcut);
-                    db.updateWithOnConflict(Shortcuts.TABLE_NAME, shortcut,
-                            SHORTCUT_BY_ID_WHERE, whereArgs, SQLiteDatabase.CONFLICT_REPLACE);
-                }
-                return true;
-            }
-        });
-    }
-
-    private class SuggestionCursorImpl extends CursorBackedSuggestionCursor {
-
-        private final HashMap<String, Source> mAllowedSources;
-        private final int mExtrasColumn;
-
-        public SuggestionCursorImpl(HashMap<String,Source> allowedSources,
-                String userQuery, Cursor cursor) {
-            super(userQuery, cursor);
-            mAllowedSources = allowedSources;
-            mExtrasColumn = cursor.getColumnIndex(Shortcuts.custom_columns.name());
-        }
-
-        @Override
-        public Source getSuggestionSource() {
-            int srcCol = mCursor.getColumnIndex(Shortcuts.source.name());
-            String srcStr = mCursor.getString(srcCol);
-            if (srcStr == null) {
-                throw new NullPointerException("Missing source for shortcut.");
-            }
-            Source source = mAllowedSources.get(srcStr);
-            if (source == null) {
-                if (DBG) {
-                    Log.d(TAG, "Source " + srcStr + " (position " + mCursor.getPosition() +
-                            ") not allowed");
-                }
-                return null;
-            }
-            int versionCode = mCursor.getInt(Shortcuts.source_version_code.ordinal());
-            if (!source.isVersionCodeCompatible(versionCode)) {
-                if (DBG) {
-                    Log.d(TAG, "Version " + versionCode + " not compatible with " +
-                            source.getVersionCode() + " for source " + srcStr);
-                }
-                return null;
-            }
-            return source;
-        }
-
-        @Override
-        public ComponentName getSuggestionIntentComponent() {
-            int componentCol = mCursor.getColumnIndex(Shortcuts.intent_component.name());
-            // We don't fall back to getSuggestionSource().getIntentComponent() because
-            // we want to return the same value that getSuggestionIntentComponent() did for the
-            // original suggestion.
-            return stringToComponentName(mCursor.getString(componentCol));
-        }
-
-        @Override
-        public String getSuggestionIcon2() {
-            if (isSpinnerWhileRefreshing() && shouldRefresh(this)) {
-                if (DBG) Log.d(TAG, "shortcut " + getShortcutId() + " refreshing");
-                return mSearchSpinner;
-            }
-            if (DBG) Log.d(TAG, "shortcut " + getShortcutId() + " NOT refreshing");
-            return super.getSuggestionIcon2();
-        }
-
-        public boolean isSuggestionShortcut() {
-            return true;
-        }
-
-        public boolean isHistorySuggestion() {
-            // This always returns false, even for suggestions that originally came
-            // from server-side history, since we'd otherwise have to parse the Genie
-            // extra data. This is ok, since this method is only used for the
-            // "Remove from history" UI, which is also shown for all shortcuts.
-            return false;
-        }
-
-        @Override
-        public SuggestionExtras getExtras() {
-            String json = mCursor.getString(mExtrasColumn);
-            if (!TextUtils.isEmpty(json)) {
-                try {
-                    return new JsonBackedSuggestionExtras(json);
-                } catch (JSONException e) {
-                    Log.e(TAG, "Could not parse JSON extras from DB: " + json);
-                }
-            }
-            return null;
-        }
-
-        public Collection<String> getExtraColumns() {
-            /*
-             * We always return null here because:
-             * - to return an accurate value, we'd have to aggregate all the extra columns in all
-             *   shortcuts in the shortcuts table, which would mean parsing ALL the JSON contained
-             *   therein
-             * - ListSuggestionCursor does this aggregation, and does it lazily
-             * - All shortcuts are put into a ListSuggestionCursor during the promotion process, so
-             *   relying on ListSuggestionCursor to do the aggregation means that we only parse the
-             *   JSON for shortcuts that are actually displayed.
-             */
-            return null;
-        }
-    }
-
-    /**
-     * Builds a parameter list for the queries built by {@link #buildShortcutQueries}.
-     */
-    private static String[] buildShortcutQueryParams(String query, long now) {
-        return new String[]{ query, nextString(query), String.valueOf(now) };
-    }
-
-    /**
-     * Given a string x, this method returns the least string y such that x is not a prefix of y.
-     * This is useful to implement prefix filtering by comparison, since the only strings z that
-     * have x as a prefix are such that z is greater than or equal to x and z is less than y.
-     *
-     * @param str A non-empty string. The contract above is not honored for an empty input string,
-     *        since all strings have the empty string as a prefix.
-     */
-    private static String nextString(String str) {
-        int len = str.length();
-        if (len == 0) {
-            return str;
-        }
-        // The last code point in the string. Within the Basic Multilingual Plane,
-        // this is the same as str.charAt(len-1)
-        int codePoint = str.codePointBefore(len);
-        // This should be safe from overflow, since the largest code point
-        // representable in UTF-16 is U+10FFFF.
-        int nextCodePoint = codePoint + 1;
-        // The index of the start of the last code point.
-        // Character.charCount(codePoint) is always 1 (in the BMP) or 2
-        int lastIndex = len - Character.charCount(codePoint);
-        return new StringBuilder(len)
-                .append(str, 0, lastIndex)  // append everything but the last code point
-                .appendCodePoint(nextCodePoint)  // instead of the last code point, use successor
-                .toString();
-    }
-
-    /**
-     * Returns the source ranking for sources with a minimum number of clicks.
-     *
-     * @param minClicks The minimum number of clicks a source must have.
-     * @return The list of sources, ranked by total clicks.
-     */
-    Map<String,Integer> getCorpusScores(int minClicks) {
-        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
-        final Cursor cursor = db.rawQuery(
-                SOURCE_RANKING_SQL, new String[] { String.valueOf(minClicks) });
-        try {
-            Map<String,Integer> corpora = new HashMap<String,Integer>(cursor.getCount());
-            while (cursor.moveToNext()) {
-                String name = cursor.getString(SourceStats.corpus.ordinal());
-                int clicks = cursor.getInt(SourceStats.total_clicks.ordinal());
-                corpora.put(name, clicks);
-            }
-            return corpora;
-        } finally {
-            cursor.close();
-        }
-    }
-
-    private ContentValues makeShortcutRow(Suggestion suggestion) {
-        String intentAction = suggestion.getSuggestionIntentAction();
-        String intentComponent = componentNameToString(suggestion.getSuggestionIntentComponent());
-        String intentData = suggestion.getSuggestionIntentDataString();
-        String intentQuery = suggestion.getSuggestionQuery();
-        String intentExtraData = suggestion.getSuggestionIntentExtraData();
-
-        Source source = suggestion.getSuggestionSource();
-        String sourceName = source.getName();
-
-        String intentKey = makeIntentKey(suggestion);
-
-        // Get URIs for all icons, to make sure that they are stable
-        String icon1Uri = getIconUriString(source, suggestion.getSuggestionIcon1());
-        String icon2Uri = getIconUriString(source, suggestion.getSuggestionIcon2());
-
-        String extrasJson = null;
-        SuggestionExtras extras = suggestion.getExtras();
-        if (extras != null) {
-            // flatten any custom columns to JSON. We need to keep any custom columns so that
-            // shortcuts for custom suggestion views work properly.
-            try {
-                extrasJson = extras.toJsonString();
-            } catch (JSONException e) {
-                Log.e(TAG, "Could not flatten extras to JSON from " + suggestion, e);
-            }
-        }
-
-        ContentValues cv = new ContentValues();
-        cv.put(Shortcuts.intent_key.name(), intentKey);
-        cv.put(Shortcuts.source.name(), sourceName);
-        cv.put(Shortcuts.source_version_code.name(), source.getVersionCode());
-        cv.put(Shortcuts.format.name(), suggestion.getSuggestionFormat());
-        cv.put(Shortcuts.title.name(), suggestion.getSuggestionText1());
-        cv.put(Shortcuts.description.name(), suggestion.getSuggestionText2());
-        cv.put(Shortcuts.description_url.name(), suggestion.getSuggestionText2Url());
-        cv.put(Shortcuts.icon1.name(), icon1Uri);
-        cv.put(Shortcuts.icon2.name(), icon2Uri);
-        cv.put(Shortcuts.intent_action.name(), intentAction);
-        cv.put(Shortcuts.intent_component.name(), intentComponent);
-        cv.put(Shortcuts.intent_data.name(), intentData);
-        cv.put(Shortcuts.intent_query.name(), intentQuery);
-        cv.put(Shortcuts.intent_extradata.name(), intentExtraData);
-        cv.put(Shortcuts.shortcut_id.name(), suggestion.getShortcutId());
-        if (suggestion.isSpinnerWhileRefreshing()) {
-            cv.put(Shortcuts.spinner_while_refreshing.name(), "true");
-        }
-        cv.put(Shortcuts.log_type.name(), suggestion.getSuggestionLogType());
-        cv.put(Shortcuts.custom_columns.name(), extrasJson);
-
-        return cv;
-    }
-
-    /**
-     * Makes a string of the form source#intentData#intentAction#intentQuery
-     * for use as a unique identifier of a suggestion.
-     * */
-    private String makeIntentKey(Suggestion suggestion) {
-        String intentAction = suggestion.getSuggestionIntentAction();
-        String intentComponent = componentNameToString(suggestion.getSuggestionIntentComponent());
-        String intentData = suggestion.getSuggestionIntentDataString();
-        String intentQuery = suggestion.getSuggestionQuery();
-
-        Source source = suggestion.getSuggestionSource();
-        String sourceName = source.getName();
-        StringBuilder key = new StringBuilder(sourceName);
-        key.append("#");
-        if (intentData != null) {
-            key.append(intentData);
-        }
-        key.append("#");
-        if (intentAction != null) {
-            key.append(intentAction);
-        }
-        key.append("#");
-        if (intentComponent != null) {
-            key.append(intentComponent);
-        }
-        key.append("#");
-        if (intentQuery != null) {
-            key.append(intentQuery);
-        }
-
-        return key.toString();
-    }
-
-    private String componentNameToString(ComponentName component) {
-        return component == null ? null : component.flattenToShortString();
-    }
-
-    private ComponentName stringToComponentName(String str) {
-        return str == null ? null : ComponentName.unflattenFromString(str);
-    }
-
-    private String getIconUriString(Source source, String drawableId) {
-        // Fast path for empty icons
-        if (TextUtils.isEmpty(drawableId) || "0".equals(drawableId)) {
-            return null;
-        }
-        // Fast path for icon URIs
-        if (drawableId.startsWith(ContentResolver.SCHEME_ANDROID_RESOURCE)
-                || drawableId.startsWith(ContentResolver.SCHEME_CONTENT)
-                || drawableId.startsWith(ContentResolver.SCHEME_FILE)) {
-            return drawableId;
-        }
-        Uri uri = source.getIconUri(drawableId);
-        return uri == null ? null : uri.toString();
-    }
-
-    @VisibleForTesting
-    void reportClickAtTime(SuggestionCursor suggestion,
-            int position, long now) {
-        suggestion.moveTo(position);
-        if (DBG) {
-            Log.d(TAG, "logClicked(" + suggestion + ")");
-        }
-
-        if (SearchManager.SUGGEST_NEVER_MAKE_SHORTCUT.equals(suggestion.getShortcutId())) {
-            if (DBG) Log.d(TAG, "clicked suggestion requested not to be shortcuted");
-            return;
-        }
-
-        Corpus corpus = mCorpora.getCorpusForSource(suggestion.getSuggestionSource());
-        if (corpus == null) {
-            Log.w(TAG, "no corpus for clicked suggestion");
-            return;
-        }
-
-        // Once the user has clicked on a shortcut, don't bother refreshing
-        // (especially if this is a new shortcut)
-        mRefresher.markShortcutRefreshed(suggestion.getSuggestionSource(),
-                suggestion.getShortcutId());
-
-        // Add or update suggestion info
-        // Since intent_key is the primary key, any existing
-        // suggestion with the same source+data+action will be replaced
-        final ContentValues shortcut = makeShortcutRow(suggestion);
-        String intentKey = shortcut.getAsString(Shortcuts.intent_key.name());
-
-        // Log click for shortcut
-        final ContentValues click = new ContentValues();
-        click.put(ClickLog.intent_key.name(), intentKey);
-        click.put(ClickLog.query.name(), suggestion.getUserQuery());
-        click.put(ClickLog.hit_time.name(), now);
-        click.put(ClickLog.corpus.name(), corpus.getName());
-
-        runTransactionAsync(new SQLiteTransaction() {
-            @Override
-            protected boolean performTransaction(SQLiteDatabase db) {
-                if (DBG) Log.d(TAG, "Adding shortcut: " + shortcut);
-                db.replaceOrThrow(Shortcuts.TABLE_NAME, null, shortcut);
-                db.insertOrThrow(ClickLog.TABLE_NAME, null, click);
-                return true;
-            }
-        });
-    }
-
-// -------------------------- TABLES --------------------------
-
-    /**
-     * shortcuts table
-     */
-    enum Shortcuts {
-        intent_key,
-        source,
-        source_version_code,
-        format,
-        title,
-        description,
-        description_url,
-        icon1,
-        icon2,
-        intent_action,
-        intent_component,
-        intent_data,
-        intent_query,
-        intent_extradata,
-        shortcut_id,
-        spinner_while_refreshing,
-        log_type,
-        custom_columns;
-
-        static final String TABLE_NAME = "shortcuts";
-
-        public final String fullName;
-
-        Shortcuts() {
-            fullName = TABLE_NAME + "." + name();
-        }
-    }
-
-    /**
-     * clicklog table. Has one record for each click.
-     */
-    enum ClickLog {
-        _id,
-        intent_key,
-        query,
-        hit_time,
-        corpus;
-
-        static final String[] COLUMNS = initColumns();
-
-        static final String TABLE_NAME = "clicklog";
-
-        private static String[] initColumns() {
-            ClickLog[] vals = ClickLog.values();
-            String[] columns = new String[vals.length];
-            for (int i = 0; i < vals.length; i++) {
-                columns[i] = vals[i].fullName;
-            }
-            return columns;
-        }
-
-        public final String fullName;
-
-        ClickLog() {
-            fullName = TABLE_NAME + "." + name();
-        }
-    }
-
-    /**
-     * This is an aggregate table of {@link ClickLog} that stays up to date with the total
-     * clicks for each corpus. This makes computing the corpus ranking more
-     * more efficient, at the expense of some extra work when the clicks are reported.
-     */
-    enum SourceStats {
-        corpus,
-        total_clicks;
-
-        static final String TABLE_NAME = "sourcetotals";
-
-        static final String[] COLUMNS = initColumns();
-
-        private static String[] initColumns() {
-            SourceStats[] vals = SourceStats.values();
-            String[] columns = new String[vals.length];
-            for (int i = 0; i < vals.length; i++) {
-                columns[i] = vals[i].fullName;
-            }
-            return columns;
-        }
-
-        public final String fullName;
-
-        SourceStats() {
-            fullName = TABLE_NAME + "." + name();
-        }
-    }
-
-// -------------------------- END TABLES --------------------------
-
-    // contains creation and update logic
-    private static class DbOpenHelper extends SQLiteOpenHelper {
-        private final Config mConfig;
-        private String mPath;
-        private static final String SHORTCUT_ID_INDEX
-                = Shortcuts.TABLE_NAME + "_" + Shortcuts.shortcut_id.name();
-        private static final String CLICKLOG_QUERY_INDEX
-                = ClickLog.TABLE_NAME + "_" + ClickLog.query.name();
-        private static final String CLICKLOG_HIT_TIME_INDEX
-                = ClickLog.TABLE_NAME + "_" + ClickLog.hit_time.name();
-        private static final String CLICKLOG_INSERT_TRIGGER
-                = ClickLog.TABLE_NAME + "_insert";
-        private static final String SHORTCUTS_DELETE_TRIGGER
-                = Shortcuts.TABLE_NAME + "_delete";
-        private static final String SHORTCUTS_UPDATE_INTENT_KEY_TRIGGER
-                = Shortcuts.TABLE_NAME + "_update_intent_key";
-
-        public DbOpenHelper(Context context, String name, int version, Config config) {
-            super(context, name, null, version);
-            mConfig = config;
-        }
-
-        @Override
-        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
-            // The shortcuts info is not all that important, so we just drop the tables
-            // and re-create empty ones.
-            Log.i(TAG, "Upgrading shortcuts DB from version " +
-                    + oldVersion + " to " + newVersion + ". This deletes all shortcuts.");
-            dropTables(db);
-            onCreate(db);
-        }
-
-        private void dropTables(SQLiteDatabase db) {
-            db.execSQL("DROP TRIGGER IF EXISTS " + CLICKLOG_INSERT_TRIGGER);
-            db.execSQL("DROP TRIGGER IF EXISTS " + SHORTCUTS_DELETE_TRIGGER);
-            db.execSQL("DROP TRIGGER IF EXISTS " + SHORTCUTS_UPDATE_INTENT_KEY_TRIGGER);
-            db.execSQL("DROP INDEX IF EXISTS " + CLICKLOG_HIT_TIME_INDEX);
-            db.execSQL("DROP INDEX IF EXISTS " + CLICKLOG_QUERY_INDEX);
-            db.execSQL("DROP INDEX IF EXISTS " + SHORTCUT_ID_INDEX);
-            db.execSQL("DROP TABLE IF EXISTS " + ClickLog.TABLE_NAME);
-            db.execSQL("DROP TABLE IF EXISTS " + Shortcuts.TABLE_NAME);
-            db.execSQL("DROP TABLE IF EXISTS " + SourceStats.TABLE_NAME);
-        }
-
-        /**
-         * Deletes the database file.
-         */
-        public void deleteDatabase() {
-            close();
-            if (mPath == null) return;
-            try {
-                new File(mPath).delete();
-                if (DBG) Log.d(TAG, "deleted " + mPath);
-            } catch (Exception e) {
-                Log.w(TAG, "couldn't delete " + mPath, e);
-            }
-        }
-
-        @Override
-        public void onOpen(SQLiteDatabase db) {
-            super.onOpen(db);
-            mPath = db.getPath();
-        }
-
-        @Override
-        public void onCreate(SQLiteDatabase db) {
-            db.execSQL("CREATE TABLE " + Shortcuts.TABLE_NAME + " (" +
-                    // COLLATE UNICODE is needed to make it possible to use nextString()
-                    // to implement fast prefix filtering.
-                    Shortcuts.intent_key.name() + " TEXT NOT NULL COLLATE UNICODE PRIMARY KEY, " +
-                    Shortcuts.source.name() + " TEXT NOT NULL, " +
-                    Shortcuts.source_version_code.name() + " INTEGER NOT NULL, " +
-                    Shortcuts.format.name() + " TEXT, " +
-                    Shortcuts.title.name() + " TEXT, " +
-                    Shortcuts.description.name() + " TEXT, " +
-                    Shortcuts.description_url.name() + " TEXT, " +
-                    Shortcuts.icon1.name() + " TEXT, " +
-                    Shortcuts.icon2.name() + " TEXT, " +
-                    Shortcuts.intent_action.name() + " TEXT, " +
-                    Shortcuts.intent_component.name() + " TEXT, " +
-                    Shortcuts.intent_data.name() + " TEXT, " +
-                    Shortcuts.intent_query.name() + " TEXT, " +
-                    Shortcuts.intent_extradata.name() + " TEXT, " +
-                    Shortcuts.shortcut_id.name() + " TEXT, " +
-                    Shortcuts.spinner_while_refreshing.name() + " TEXT, " +
-                    Shortcuts.log_type.name() + " TEXT, " +
-                    Shortcuts.custom_columns.name() + " TEXT" +
-                    ");");
-
-            // index for fast lookup of shortcuts by shortcut_id
-            db.execSQL("CREATE INDEX " + SHORTCUT_ID_INDEX
-                    + " ON " + Shortcuts.TABLE_NAME
-                    + "(" + Shortcuts.shortcut_id.name() + ", " + Shortcuts.source.name() + ")");
-
-            db.execSQL("CREATE TABLE " + ClickLog.TABLE_NAME + " ( " +
-                    ClickLog._id.name() + " INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, " +
-                    // type must match Shortcuts.intent_key
-                    ClickLog.intent_key.name() + " TEXT NOT NULL COLLATE UNICODE REFERENCES "
-                        + Shortcuts.TABLE_NAME + "(" + Shortcuts.intent_key + "), " +
-                    ClickLog.query.name() + " TEXT, " +
-                    ClickLog.hit_time.name() + " INTEGER," +
-                    ClickLog.corpus.name() + " TEXT" +
-                    ");");
-
-            // index for fast lookup of clicks by query
-            db.execSQL("CREATE INDEX " + CLICKLOG_QUERY_INDEX
-                    + " ON " + ClickLog.TABLE_NAME + "(" + ClickLog.query.name() + ")");
-
-            // index for finding old clicks quickly
-            db.execSQL("CREATE INDEX " + CLICKLOG_HIT_TIME_INDEX
-                    + " ON " + ClickLog.TABLE_NAME + "(" + ClickLog.hit_time.name() + ")");
-
-            // trigger for purging old clicks, i.e. those such that
-            // hit_time < now - MAX_MAX_STAT_AGE_MILLIS, where now is the
-            // hit_time of the inserted record, and for updating the SourceStats table
-            db.execSQL("CREATE TRIGGER " + CLICKLOG_INSERT_TRIGGER + " AFTER INSERT ON "
-                    + ClickLog.TABLE_NAME
-                    + " BEGIN"
-                    + " DELETE FROM " + ClickLog.TABLE_NAME + " WHERE "
-                            + ClickLog.hit_time.name() + " <"
-                            + " NEW." + ClickLog.hit_time.name()
-                                    + " - " + mConfig.getMaxStatAgeMillis() + ";"
-                    + " DELETE FROM " + SourceStats.TABLE_NAME + ";"
-                    + " INSERT INTO " + SourceStats.TABLE_NAME  + " "
-                            + "SELECT " + ClickLog.corpus + "," + "COUNT(*) FROM "
-                            + ClickLog.TABLE_NAME + " GROUP BY " + ClickLog.corpus.name() + ";"
-                    + " END");
-
-            // trigger for deleting clicks about a shortcut once that shortcut has been
-            // deleted
-            db.execSQL("CREATE TRIGGER " + SHORTCUTS_DELETE_TRIGGER + " AFTER DELETE ON "
-                    + Shortcuts.TABLE_NAME
-                    + " BEGIN"
-                    + " DELETE FROM " + ClickLog.TABLE_NAME + " WHERE "
-                            + ClickLog.intent_key.name()
-                            + " = OLD." + Shortcuts.intent_key.name() + ";"
-                    + " END");
-
-            // trigger for updating click log entries when a shortcut changes its intent_key
-            db.execSQL("CREATE TRIGGER " + SHORTCUTS_UPDATE_INTENT_KEY_TRIGGER
-                    + " AFTER UPDATE ON " + Shortcuts.TABLE_NAME
-                    + " WHEN NEW." + Shortcuts.intent_key.name()
-                            + " != OLD." + Shortcuts.intent_key.name()
-                    + " BEGIN"
-                    + " UPDATE " + ClickLog.TABLE_NAME + " SET "
-                            + ClickLog.intent_key.name() + " = NEW." + Shortcuts.intent_key.name()
-                            + " WHERE "
-                            + ClickLog.intent_key.name() + " = OLD." + Shortcuts.intent_key.name()
-                            + ";"
-                    + " END");
-
-            db.execSQL("CREATE TABLE " + SourceStats.TABLE_NAME + " ( " +
-                    SourceStats.corpus.name() + " TEXT NOT NULL COLLATE UNICODE PRIMARY KEY, " +
-                    SourceStats.total_clicks + " INTEGER);"
-                    );
-        }
-    }
-}
diff --git a/src/com/android/quicksearchbox/ShortcutsProvider.java b/src/com/android/quicksearchbox/ShortcutsProvider.java
deleted file mode 100644
index 688d3f1..0000000
--- a/src/com/android/quicksearchbox/ShortcutsProvider.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import android.app.SearchManager;
-import android.content.ComponentName;
-import android.content.ContentProvider;
-import android.content.ContentValues;
-import android.content.Intent;
-import android.content.UriMatcher;
-import android.content.pm.PackageManager;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Binder;
-import android.text.TextUtils;
-import android.util.Log;
-
-/**
- * Handles broadcast intents for adding shortcuts to QSB.
- */
-public class ShortcutsProvider extends ContentProvider {
-
-    private static final boolean DBG = false;
-    private static final String TAG = "QSB.ExternalShortcutReceiver";
-
-    public static final String EXTRA_SHORTCUT_SOURCE = "shortcut_source";
-
-    private static final int URI_CODE_SHORTCUTS = 0;
-
-    private UriMatcher mUriMatcher;
-
-    @Override
-    public boolean onCreate() {
-        mUriMatcher = buildUriMatcher();
-        return true;
-    }
-
-    private UriMatcher buildUriMatcher() {
-        String authority = getAuthority();
-        UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
-        matcher.addURI(authority, "shortcuts", URI_CODE_SHORTCUTS);
-        return matcher;
-    }
-
-    private String getAuthority() {
-        return getContext().getPackageName() + ".shortcuts";
-    }
-
-    @Override
-    public String getType(Uri uri) {
-        switch (mUriMatcher.match(uri)) {
-            case URI_CODE_SHORTCUTS:
-                return SearchManager.SUGGEST_MIME_TYPE;
-            default:
-                throw new IllegalArgumentException("Unknown URI: " + uri);
-        }
-    }
-
-    @Override
-    public Uri insert(Uri uri, ContentValues values) {
-        switch (mUriMatcher.match(uri)) {
-            case URI_CODE_SHORTCUTS:
-                addShortcut(values);
-                return null;
-            default:
-                throw new IllegalArgumentException("Unknown URI: " + uri);
-        }
-    }
-
-    @Override
-    public int delete(Uri uri, String selection, String[] selectionArgs) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
-            String sortOrder) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
-        throw new UnsupportedOperationException();
-    }
-
-    private void addShortcut(final ContentValues shortcut) {
-        String sourceName = shortcut.getAsString(EXTRA_SHORTCUT_SOURCE);
-        if (TextUtils.isEmpty(sourceName)) {
-            Log.e(TAG, "Missing " + EXTRA_SHORTCUT_SOURCE);
-            return;
-        }
-
-        String sourceAction = shortcut.getAsString(SearchManager.SUGGEST_COLUMN_INTENT_ACTION);
-        if (Intent.ACTION_WEB_SEARCH.equals(sourceAction)) {
-            if (DBG) {
-                Log.d(TAG, "Ignoring shortcut from " + sourceName +
-                        "because its intent action was ACTION_WEB_SEARCH.");
-            }
-            return;
-        }
-
-        final ComponentName sourceComponent = ComponentName.unflattenFromString(sourceName);
-        if (!checkCallingPackage(sourceComponent.getPackageName())) {
-            Log.w(TAG, "Got shortcut for " + sourceComponent + " from a different process");
-            return;
-        }
-
-        getQsbApplication().runOnUiThread(new Runnable() {
-            public void run() {
-                storeShortcut(sourceComponent, shortcut);
-            }
-        });
-    }
-
-    // Called on the main thread
-    private void storeShortcut(ComponentName sourceComponent, ContentValues shortcut) {
-        if (DBG) Log.d(TAG, "Adding (PID: " + Binder.getCallingPid() + "): " + shortcut);
-
-        Source source = getCorpora().getSource(sourceComponent.flattenToShortString());
-        if (source == null) {
-            Log.w(TAG, "Unknown shortcut source " + sourceComponent);
-            return;
-        }
-
-        String userQuery = shortcut.getAsString(SearchManager.USER_QUERY);
-        if (userQuery == null) userQuery = "";
-
-        ListSuggestionCursor cursor = new ListSuggestionCursor(userQuery);
-        cursor.add(makeSuggestion(source, shortcut));
-        getShortcutRepository().reportClick(cursor, 0);
-    }
-
-    private boolean checkCallingPackage(String packageName) {
-        int callingUid = Binder.getCallingUid();
-        PackageManager pm = getContext().getPackageManager();
-        String[] uidPkgs = pm.getPackagesForUid(callingUid);
-        if (uidPkgs == null) return false;
-        for (String uidPkg : uidPkgs) {
-            if (packageName.equals(uidPkg)) return true;
-        }
-        return false;
-    }
-
-    private SuggestionData makeSuggestion(Source source, ContentValues shortcut) {
-        String format = shortcut.getAsString(SearchManager.SUGGEST_COLUMN_FORMAT);
-        String text1 = shortcut.getAsString(SearchManager.SUGGEST_COLUMN_TEXT_1);
-        String text2 = shortcut.getAsString(SearchManager.SUGGEST_COLUMN_TEXT_2);
-        String text2Url = shortcut.getAsString(SearchManager.SUGGEST_COLUMN_TEXT_2_URL);
-        String icon1 = shortcut.getAsString(SearchManager.SUGGEST_COLUMN_ICON_1);
-        String icon2 = shortcut.getAsString(SearchManager.SUGGEST_COLUMN_ICON_2);
-        String shortcutId = shortcut.getAsString(SearchManager.SUGGEST_COLUMN_SHORTCUT_ID);
-        boolean spinnerWhileRefreshing = unboxBoolean(
-                shortcut.getAsBoolean(SearchManager.SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING),
-                false);
-        String intentAction = shortcut.getAsString(SearchManager.SUGGEST_COLUMN_INTENT_ACTION);
-        String intentData = shortcut.getAsString(SearchManager.SUGGEST_COLUMN_INTENT_DATA);
-        String intentExtraData =
-                shortcut.getAsString(SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA);
-        String query = shortcut.getAsString(SearchManager.SUGGEST_COLUMN_QUERY);
-
-        SuggestionData suggestion = new SuggestionData(source);
-        suggestion.setFormat(format);
-        suggestion.setText1(text1);
-        suggestion.setText2(text2);
-        suggestion.setText2Url(text2Url);
-        suggestion.setIcon1(icon1);
-        suggestion.setIcon2(icon2);
-        suggestion.setShortcutId(shortcutId);
-        suggestion.setSpinnerWhileRefreshing(spinnerWhileRefreshing);
-        suggestion.setIntentAction(intentAction);
-        suggestion.setIntentData(intentData);
-        suggestion.setIntentExtraData(intentExtraData);
-        suggestion.setSuggestionQuery(query);
-        return suggestion;
-    }
-
-    private static boolean unboxBoolean(Boolean value, boolean defValue) {
-        return value == null ? defValue : value;
-    }
-
-    private QsbApplication getQsbApplication() {
-        return QsbApplication.get(getContext());
-    }
-
-    private ShortcutRepository getShortcutRepository() {
-        return getQsbApplication().getShortcutRepository();
-    }
-
-    private Corpora getCorpora() {
-        return getQsbApplication().getCorpora();
-    }
-
-}
diff --git a/src/com/android/quicksearchbox/ShouldQueryStrategy.java b/src/com/android/quicksearchbox/ShouldQueryStrategy.java
deleted file mode 100644
index 0725dc5..0000000
--- a/src/com/android/quicksearchbox/ShouldQueryStrategy.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
-/**
- * Decides whether a given source should be queried for a given query, taking
- * into account the source's query threshold and query after zero results flag.
- *
- * This class is thread safe.
- */
-class ShouldQueryStrategy {
-
-    private static final boolean DBG = false;
-    private static final String TAG = "QSB.ShouldQueryStrategy";
-
-    // The last query we've seen
-    private String mLastQuery = "";
-
-    private final Config mConfig;
-
-    // The current implementation keeps a record of those corpora that have
-    // returned zero results for some prefix of the current query. mEmptyCorpora
-    // maps from corpus to the length of the query which returned
-    // zero results.  When a query is shortened (e.g., by deleting characters)
-    // or changed entirely, mEmptyCorpora is pruned (in updateQuery)
-    private final HashMap<Corpus, Integer> mEmptyCorpora
-            = new HashMap<Corpus, Integer>();
-
-    public ShouldQueryStrategy(Config config) {
-        mConfig = config;
-    }
-
-    /**
-     * Returns whether we should query the given source for the given query.
-     */
-    public boolean shouldQueryCorpus(Corpus corpus, String query) {
-        updateQuery(query);
-        if (query.length() == 0
-                && !corpus.isWebCorpus() // always query web, to warm up connection
-                && !mConfig.showSuggestionsForZeroQuery()) {
-                return false;
-        }
-        if (query.length() >= corpus.getQueryThreshold()) {
-            if (!corpus.queryAfterZeroResults() && mEmptyCorpora.containsKey(corpus)) {
-                if (DBG) Log.i(TAG, "Not querying " + corpus + ", returned 0 after "
-                        + mEmptyCorpora.get(corpus));
-                return false;
-            }
-            return true;
-        }
-        if (DBG) Log.d(TAG, "Query too short for corpus " + corpus);
-        return false;
-    }
-
-    /**
-     * Called to notify ShouldQueryStrategy when a source reports no results for a query.
-     */
-    public void onZeroResults(Corpus corpus, String query) {
-        // Make sure this result is actually for a prefix of the current query.
-        if (mLastQuery.startsWith(query) && !corpus.queryAfterZeroResults()
-                && !TextUtils.isEmpty(query)) {
-            if (DBG) Log.d(TAG, corpus + " returned 0 results for '" + query + "'");
-            mEmptyCorpora.put(corpus, query.length());
-        }
-    }
-
-    private void updateQuery(String query) {
-        if (query.startsWith(mLastQuery)) {
-            // This is a refinement of the last query, no changes to mEmptyCorpora needed
-        } else if (mLastQuery.startsWith(query)) {
-            // This is a widening of the last query: clear out any sources
-            // that reported zero results after this query.
-            Iterator<Map.Entry<Corpus, Integer>> iter = mEmptyCorpora.entrySet().iterator();
-            while (iter.hasNext()) {
-                if (iter.next().getValue() > query.length()) {
-                    iter.remove();
-                }
-            }
-        } else {
-            // This is a completely different query, clear everything.
-            mEmptyCorpora.clear();
-        }
-        mLastQuery = query;
-    }
-}
diff --git a/src/com/android/quicksearchbox/SingleCorpusPromoter.java b/src/com/android/quicksearchbox/SingleCorpusPromoter.java
deleted file mode 100644
index f63246a..0000000
--- a/src/com/android/quicksearchbox/SingleCorpusPromoter.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Promotes shortcuts and suggestions from a single corpus.
- */
-public class SingleCorpusPromoter implements Promoter {
-
-    private final Corpus mCorpus;
-
-    private final int mMaxShortcuts;
-
-    private final Set<String> mAllowedSources;
-
-    public SingleCorpusPromoter(Corpus corpus, int maxShortcuts) {
-        mCorpus = corpus;
-        mMaxShortcuts = maxShortcuts;
-        mAllowedSources = new HashSet<String>();
-        for (Source source : corpus.getSources()) {
-            mAllowedSources.add(source.getName());
-        }
-    }
-
-    public void pickPromoted(Suggestions suggestions, int maxPromoted,
-            ListSuggestionCursor promoted) {
-        // Add shortcuts
-        SuggestionCursor shortcuts = suggestions.getShortcuts();
-        promoteUntilFull(shortcuts, mMaxShortcuts, promoted);
-        // Add suggestions
-        CorpusResult corpusResult = suggestions.getCorpusResult(mCorpus);
-        promoteUntilFull(corpusResult, maxPromoted, promoted);
-    }
-
-    private void promoteUntilFull(SuggestionCursor c, int maxSize, ListSuggestionCursor promoted) {
-        if (c == null) return;
-        int count = c.getCount();
-        for (int i = 0; i < count && promoted.getCount() < maxSize; i++) {
-            c.moveTo(i);
-            if (accept(c)) {
-                promoted.add(new SuggestionPosition(c, i));
-            }
-        }
-    }
-
-    protected boolean accept(Suggestion s) {
-        return mAllowedSources.contains(s.getSuggestionSource().getName());
-    }
-
-}
diff --git a/src/com/android/quicksearchbox/SingleCorpusResultsPromoter.java b/src/com/android/quicksearchbox/SingleCorpusResultsPromoter.java
deleted file mode 100644
index 1e1b59d..0000000
--- a/src/com/android/quicksearchbox/SingleCorpusResultsPromoter.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-/**
- * Promotes non-web-search shortcuts and suggestions from a single corpus.
- */
-public class SingleCorpusResultsPromoter extends SingleCorpusPromoter {
-
-    public SingleCorpusResultsPromoter(Corpus corpus, int maxShortcuts) {
-        super(corpus, maxShortcuts);
-    }
-
-    protected boolean accept(Suggestion s) {
-        return !s.isWebSearchSuggestion() && super.accept(s);
-    }
-
-}
diff --git a/src/com/android/quicksearchbox/SingleSourceCorpus.java b/src/com/android/quicksearchbox/SingleSourceCorpus.java
deleted file mode 100644
index 7cc1e80..0000000
--- a/src/com/android/quicksearchbox/SingleSourceCorpus.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2009 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.quicksearchbox;
-
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-
-import java.util.Collection;
-import java.util.Collections;
-
-/**
- * A corpus that uses a single source.
- */
-public class SingleSourceCorpus extends AbstractCorpus {
-
-    private final Source mSource;
-
-    public SingleSourceCorpus(Context context, Config config, Source source) {
-        super(context, config);
-        mSource = source;
-    }
-
-    public Drawable getCorpusIcon() {
-        return mSource.getSourceIcon();
-    }
-
-    public Uri getCorpusIconUri() {
-        return mSource.getSourceIconUri();
-    }
-
-    public CharSequence getLabel() {
-        return mSource.getLabel();
-    }
-
-    public CharSequence getHint() {
-        return mSource.getHint();
-    }
-
-    public CharSequence getSettingsDescription() {
-        return mSource.getSettingsDescription();
-    }
-
-    public CorpusResult getSuggestions(String query, int queryLimit, boolean onlyCorpus) {
-        LatencyTracker latencyTracker = new LatencyTracker();
-        SourceResult sourceResult = mSource.getSuggestions(query, queryLimit, true);
-        int latency = latencyTracker.getLatency();
-        return new SingleSourceCorpusResult(this, query, sourceResult, latency);
-    }
-
-    public String getName() {
-        return mSource.getName();
-    }
-
-    public boolean queryAfterZeroResults() {
-        return mSource.queryAfterZeroResults();
-    }
-
-    public int getQueryThreshold() {
-        return mSource.getQueryThreshold();
-    }
-
-    public boolean voiceSearchEnabled() {
-        return mSource.voiceSearchEnabled();
-    }
-
-    public Intent createSearchIntent(String query, Bundle appData) {
-        return mSource.createSearchIntent(query, appData);
-    }
-
-    public Intent createVoiceSearchIntent(Bundle appData) {
-        return mSource.createVoiceSearchIntent(appData);
-    }
-
-    public boolean includeInAll() {
-        return mSource.includeInAll();
-    }
-
-    public boolean isWebCorpus() {
-        return false;
-    }
-
-    public Collection<Source> getSources() {
-        return Collections.singletonList(mSource);
-    }
-
-}
diff --git a/src/com/android/quicksearchbox/SingleSourceCorpusResult.java b/src/com/android/quicksearchbox/SingleSourceCorpusResult.java
deleted file mode 100644
index 17a33f8..0000000
--- a/src/com/android/quicksearchbox/SingleSourceCorpusResult.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2009 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.quicksearchbox;
-
-
-/**
- * A CorpusResult backed by a single SourceResult.
- */
-public class SingleSourceCorpusResult extends SuggestionCursorWrapper implements CorpusResult {
-
-    private final Corpus mCorpus;
-
-    private final int mLatency;
-
-    public SingleSourceCorpusResult(Corpus corpus, String userQuery, SuggestionCursor cursor,
-            int latency) {
-        super(userQuery, cursor);
-        mCorpus = corpus;
-        mLatency = latency;
-    }
-
-    public Corpus getCorpus() {
-        return mCorpus;
-    }
-
-    public int getLatency() {
-        return mLatency;
-    }
-
-    @Override
-    public String toString() {
-        return getCorpus() + "[" + getUserQuery() + "]";
-    }
-
-}
diff --git a/src/com/android/quicksearchbox/Source.java b/src/com/android/quicksearchbox/Source.java
index d5e366d..680f415 100644
--- a/src/com/android/quicksearchbox/Source.java
+++ b/src/com/android/quicksearchbox/Source.java
@@ -41,22 +41,6 @@
     String getSuggestUri();
 
     /**
-     * Gets the version code of the source. This is expected to change when the app that
-     * this source is for is upgraded.
-     */
-    int getVersionCode();
-
-    /**
-     * Indicates if shortcuts from the given version of this source are compatible with the
-     * currently installed version. The version code given will only differ from the currently
-     * installed version after the source has been upgraded.
-     *
-     * @param version version of the source (as returned by {@link #getVersionCode} which originally
-     *      created the shortcut.
-     */
-    boolean isVersionCodeCompatible(int version);
-
-    /**
      * Gets the localized, human-readable label for this source.
      */
     CharSequence getLabel();
@@ -124,11 +108,6 @@
      */
     boolean includeInAll();
 
-    /**
-     * Gets the maximum number of shortcuts that will be shown from this source.
-     */
-    int getMaxShortcuts(Config config);
-
     Intent createSearchIntent(String query, Bundle appData);
 
     Intent createVoiceSearchIntent(Bundle appData);
@@ -142,20 +121,10 @@
      * Gets suggestions from this source.
      *
      * @param query The user query.
-     * @param onlySource Indicates if this is the only source being queried.
      * @return The suggestion results.
      */
-    SourceResult getSuggestions(String query, int queryLimit, boolean onlySource);
-
-    /**
-     * Updates a shortcut.
-     *
-     * @param shortcutId The id of the shortcut to update.
-     * @param extraData associated with this shortcut.
-     * @return A SuggestionCursor positioned at the updated shortcut.  If the
-     *         cursor is empty or <code>null</code>, the shortcut will be removed.
-     */
-    SuggestionCursor refreshShortcut(String shortcutId, String extraData);
+    @Override
+    SourceResult getSuggestions(String query, int queryLimit);
 
     /**
      * Gets the default intent action for suggestions from this source.
diff --git a/src/com/android/quicksearchbox/SourceShortcutRefresher.java b/src/com/android/quicksearchbox/SourceShortcutRefresher.java
deleted file mode 100644
index a27723e..0000000
--- a/src/com/android/quicksearchbox/SourceShortcutRefresher.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import com.android.quicksearchbox.util.NamedTask;
-import com.android.quicksearchbox.util.NamedTaskExecutor;
-
-import android.util.Log;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Refreshes shortcuts from their source.
- */
-class SourceShortcutRefresher implements ShortcutRefresher {
-    private static final String TAG = "QSB.SourceShortcutRefresher";
-    private static final boolean DBG = false;
-
-    private final NamedTaskExecutor mExecutor;
-
-    private final Set<String> mRefreshed = Collections.synchronizedSet(new HashSet<String>());
-    private final Set<String> mRefreshing = Collections.synchronizedSet(new HashSet<String>());
-
-    /**
-     * Create a ShortcutRefresher that will refresh shortcuts using the given executor.
-     *
-     * @param executor Used to execute the tasks.
-     */
-    public SourceShortcutRefresher(NamedTaskExecutor executor) {
-        mExecutor = executor;
-    }
-
-    public void refresh(Suggestion shortcut, Listener listener) {
-        Source source = shortcut.getSuggestionSource();
-        if (source == null) {
-            throw new NullPointerException("source");
-        }
-        String shortcutId = shortcut.getShortcutId();
-        if (shouldRefresh(source, shortcutId) && !isRefreshing(source, shortcutId)) {
-            if (DBG) {
-                Log.d(TAG, "Refreshing shortcut  " + shortcutId + " '" +
-                        shortcut.getSuggestionText1() + "'");
-            }
-            markShortcutRefreshing(source, shortcutId);
-            String extraData = shortcut.getSuggestionIntentExtraData();
-            ShortcutRefreshTask refreshTask = new ShortcutRefreshTask(
-                    source, shortcutId, extraData, listener);
-            mExecutor.execute(refreshTask);
-        }
-    }
-
-    /**
-     * Returns true if the given shortcut requires refreshing.
-     */
-    public boolean shouldRefresh(Source source, String shortcutId) {
-        return source != null && shortcutId != null
-                && !mRefreshed.contains(makeKey(source, shortcutId));
-    }
-
-    public boolean isRefreshing(Source source, String shortcutId) {
-        return source != null && shortcutId != null
-                && mRefreshing.contains(makeKey(source, shortcutId));
-    }
-
-    private void markShortcutRefreshing(Source source, String shortcutId) {
-        mRefreshing.add(makeKey(source, shortcutId));
-    }
-
-    /**
-     * Indicate that the shortcut no longer requires refreshing.
-     */
-    public void markShortcutRefreshed(Source source, String shortcutId) {
-        String key = makeKey(source, shortcutId);
-        mRefreshed.add(key);
-        mRefreshing.remove(key);
-    }
-
-    /**
-     * Reset internal state.  This results in all shortcuts requiring refreshing.
-     */
-    public void reset() {
-        mRefreshed.clear();
-    }
-
-    private static String makeKey(Source source, String shortcutId) {
-        return source.getName() + "#" + shortcutId;
-    }
-
-    /**
-     * Refreshes a shortcut with a source and reports the result to a
-     * {@link ShortcutRefresher.Listener}.
-     */
-    private class ShortcutRefreshTask implements NamedTask {
-        private final Source mSource;
-        private final String mShortcutId;
-        private final String mExtraData;
-        private final Listener mListener;
-
-        /**
-         * @param source The source that should validate the shortcut.
-         * @param shortcutId The shortcut to be refreshed.
-         * @param listener Who to report back to when the result is in.
-         */
-        ShortcutRefreshTask(Source source, String shortcutId, String extraData,
-                Listener listener) {
-            mSource = source;
-            mShortcutId = shortcutId;
-            mExtraData = extraData;
-            mListener = listener;
-        }
-
-        public String getName() {
-            return mSource.getName();
-        }
-
-        public void run() {
-            // TODO: Add latency tracking and logging.
-            SuggestionCursor refreshed = mSource.refreshShortcut(mShortcutId, mExtraData);
-            // Close cursor if empty and pass null as the refreshed cursor
-            if (refreshed != null && refreshed.getCount() == 0) {
-                refreshed.close();
-                refreshed = null;
-            }
-            markShortcutRefreshed(mSource, mShortcutId);
-            mListener.onShortcutRefreshed(mSource, mShortcutId, refreshed);
-        }
-
-    }
-}
diff --git a/src/com/android/quicksearchbox/Sources.java b/src/com/android/quicksearchbox/Sources.java
deleted file mode 100644
index 08c4fb8..0000000
--- a/src/com/android/quicksearchbox/Sources.java
+++ /dev/null
@@ -1,42 +0,0 @@
-
-package com.android.quicksearchbox;
-
-import android.content.ComponentName;
-
-import java.util.Collection;
-
-/**
- * Search source set.
- */
-public interface Sources {
-
-    /**
-     * Gets all sources.
-     */
-    Collection<Source> getSources();
-
-    /**
-     * Gets a source by name.
-     *
-     * @return A source, or {@code null} if no source with the given name exists.
-     */
-    Source getSource(String name);
-
-    /**
-     * Gets the web search source.
-     */
-    Source getWebSearchSource();
-
-    /**
-     * Creates a new source for a specific component.
-     * @param component Name of the component to search
-     * @return a new {@code Source} corresponding to {@code component}.
-     */
-    Source createSourceFor(ComponentName component);
-
-    /**
-     * Updates the list of sources.
-     */
-    void update();
-
-}
diff --git a/src/com/android/quicksearchbox/SuggestionCursor.java b/src/com/android/quicksearchbox/SuggestionCursor.java
index e848a8d..04d53c8 100644
--- a/src/com/android/quicksearchbox/SuggestionCursor.java
+++ b/src/com/android/quicksearchbox/SuggestionCursor.java
@@ -61,6 +61,7 @@
     /**
      * Frees any resources used by this cursor.
      */
+    @Override
     void close();
 
     /**
diff --git a/src/com/android/quicksearchbox/SuggestionCursorProvider.java b/src/com/android/quicksearchbox/SuggestionCursorProvider.java
index 12e611a..23109cd 100644
--- a/src/com/android/quicksearchbox/SuggestionCursorProvider.java
+++ b/src/com/android/quicksearchbox/SuggestionCursorProvider.java
@@ -33,8 +33,7 @@
      *
      * @param query The user query.
      * @param queryLimit An advisory maximum number of results that the source should return.
-     * @param onlyOne Indicates if this provider is the only one being used for the query.
      * @return The suggestion results. Must not be {@code null}.
      */
-    C getSuggestions(String query, int queryLimit, boolean onlyOne);
+    C getSuggestions(String query, int queryLimit);
 }
diff --git a/src/com/android/quicksearchbox/Suggestions.java b/src/com/android/quicksearchbox/Suggestions.java
index ad57eb9..aca2a67 100644
--- a/src/com/android/quicksearchbox/Suggestions.java
+++ b/src/com/android/quicksearchbox/Suggestions.java
@@ -16,19 +16,10 @@
 
 package com.android.quicksearchbox;
 
-import com.google.common.annotations.VisibleForTesting;
-
 import android.database.DataSetObservable;
 import android.database.DataSetObserver;
 import android.util.Log;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
 /**
  * Collects all corpus results for a single query.
  */
@@ -40,48 +31,23 @@
     private boolean mClosed = false;
     protected final String mQuery;
 
-    private ShortcutCursor mShortcuts;
-
-    private final MyShortcutsObserver mShortcutsObserver = new MyShortcutsObserver();
-
     /**
      * The observers that want notifications of changes to the published suggestions.
      * This object may be accessed on any thread.
      */
     private final DataSetObservable mDataSetObservable = new DataSetObservable();
 
-    /** The sources that are expected to report. */
-    private final List<Corpus> mExpectedCorpora;
-    private final HashMap<String, Integer> mCorpusPositions;
+    private Source mSource;
 
-    /**
-     * All {@link SuggestionCursor} objects that have been published so far,
-     * in the same order as {@link #mExpectedCorpora}. There may be {@code null} items
-     * in the array, if not all corpora have published yet.
-     * This object may only be accessed on the UI thread.
-     * */
-    private final CorpusResult[] mCorpusResults;
-
-    private CorpusResult mWebResult;
+    private SourceResult mResult;
 
     private int mRefCount = 0;
 
     private boolean mDone = false;
 
-    public Suggestions(String query, List<Corpus> expectedCorpora) {
+    public Suggestions(String query, Source source) {
         mQuery = query;
-        mExpectedCorpora = expectedCorpora;
-        mCorpusResults = new CorpusResult[mExpectedCorpora.size()];
-        // create a map of corpus name -> position in mExpectedCorpora for sorting later
-        // (we want to keep the ordering of corpora in mCorpusResults).
-        mCorpusPositions = new HashMap<String, Integer>();
-        for (int i = 0; i < mExpectedCorpora.size(); ++i) {
-            mCorpusPositions.put(mExpectedCorpora.get(i).getName(), i);
-        }
-        if (DBG) {
-            Log.d(TAG, "new Suggestions [" + hashCode() + "] query \"" + query
-                    + "\" expected corpora: " + mExpectedCorpora);
-        }
+        mSource = source;
     }
 
     public void acquire() {
@@ -95,66 +61,8 @@
         }
     }
 
-    public List<Corpus> getExpectedCorpora() {
-        return mExpectedCorpora;
-    }
-
-    /**
-     * Gets the number of corpora that are expected to report.
-     */
-    @VisibleForTesting
-    public int getExpectedResultCount() {
-        return mExpectedCorpora.size();
-    }
-
-    public boolean expectsCorpus(Corpus corpus) {
-        for (Corpus expectedCorpus : mExpectedCorpora) {
-            if (expectedCorpus.equals(corpus)) return true;
-        }
-        return false;
-    }
-
-    /**
-     * Gets the set of corpora that have reported results to this suggestions set.
-     *
-     * @return A collection of corpora.
-     */
-    public Set<Corpus> getIncludedCorpora() {
-        HashSet<Corpus> corpora = new HashSet<Corpus>();
-        for (CorpusResult result : mCorpusResults) {
-            if (result != null) {
-                corpora.add(result.getCorpus());
-            }
-        }
-        return corpora;
-    }
-
-    /**
-     * Sets the shortcut suggestions.
-     * Must be called on the UI thread, or before this object is seen by the UI thread.
-     *
-     * @param shortcuts The shortcuts.
-     */
-    public void setShortcuts(ShortcutCursor shortcuts) {
-        if (DBG) Log.d(TAG, "setShortcuts(" + shortcuts + ")");
-        if (mShortcuts != null) {
-            throw new IllegalStateException("Got duplicate shortcuts: old: " + mShortcuts
-                    + ", new: " + shortcuts);
-        }
-        if (shortcuts == null) return;
-        if (isClosed()) {
-            shortcuts.close();
-            return;
-        }
-        if (!mQuery.equals(shortcuts.getUserQuery())) {
-            throw new IllegalArgumentException("Got shortcuts for wrong query: "
-                    + mQuery + " != " + shortcuts.getUserQuery());
-        }
-        mShortcuts = shortcuts;
-        if (shortcuts != null) {
-            mShortcuts.registerDataSetObserver(mShortcutsObserver);
-        }
-        notifyDataSetChanged();
+    public Source getSource() {
+        return mSource;
     }
 
     /**
@@ -170,53 +78,28 @@
      * Must be called on the UI thread, or before this object is seen by the UI thread.
      */
     public boolean isDone() {
-        // TODO: Handle early completion because we have all the results we want.
-        return mDone || countCorpusResults() >= mExpectedCorpora.size();
-    }
-
-    private int countCorpusResults() {
-        int count = 0;
-        for (int i = 0; i < mCorpusResults.length; ++i) {
-            if (mCorpusResults[i] != null) {
-                count++;
-            }
-        }
-        return count;
+        return mDone || mResult != null;
     }
 
     /**
      * Adds a list of corpus results. Must be called on the UI thread, or before this
      * object is seen by the UI thread.
      */
-    public void addCorpusResults(List<CorpusResult> corpusResults) {
+    public void addResults(SourceResult result) {
         if (isClosed()) {
-            for (CorpusResult corpusResult : corpusResults) {
-                corpusResult.close();
-            }
+            result.close();
             return;
         }
 
-        for (CorpusResult corpusResult : corpusResults) {
-            if (DBG) {
-                Log.d(TAG, "addCorpusResult["+ hashCode() + "] corpus:" +
-                        corpusResult.getCorpus().getName() + " results:" + corpusResult.getCount());
-            }
-            if (!mQuery.equals(corpusResult.getUserQuery())) {
-              throw new IllegalArgumentException("Got result for wrong query: "
-                    + mQuery + " != " + corpusResult.getUserQuery());
-            }
-            Integer pos = mCorpusPositions.get(corpusResult.getCorpus().getName());
-            if (pos == null) {
-                Log.w(TAG, "Got unexpected CorpusResult from corpus " +
-                        corpusResult.getCorpus().getName());
-                corpusResult.close();
-            } else {
-                mCorpusResults[pos] = corpusResult;
-                if (corpusResult.getCorpus().isWebCorpus()) {
-                    mWebResult = corpusResult;
-                }
-            }
+        if (DBG) {
+            Log.d(TAG, "addResults["+ hashCode() + "] source:" +
+                    result.getSource().getName() + " results:" + result.getCount());
         }
+        if (!mQuery.equals(result.getUserQuery())) {
+          throw new IllegalArgumentException("Got result for wrong query: "
+                + mQuery + " != " + result.getUserQuery());
+        }
+        mResult = result;
         notifyDataSetChanged();
     }
 
@@ -257,37 +140,16 @@
         }
         mClosed = true;
         mDataSetObservable.unregisterAll();
-        if (mShortcuts != null) {
-            mShortcuts.close();
-            mShortcuts = null;
+        if (mResult != null) {
+            mResult.close();
         }
-
-        for (CorpusResult result : mCorpusResults) {
-            if (result != null) {
-                result.close();
-            }
-        }
-        Arrays.fill(mCorpusResults, null);
+        mResult = null;
     }
 
     public boolean isClosed() {
         return mClosed;
     }
 
-    public ShortcutCursor getShortcuts() {
-        return mShortcuts;
-    }
-
-    private void refreshShortcuts(SuggestionCursor promoted) {
-        if (DBG) Log.d(TAG, "refreshShortcuts(" + promoted + ")");
-        for (int i = 0; i < promoted.getCount(); ++i) {
-            promoted.moveTo(i);
-            if (promoted.isSuggestionShortcut()) {
-                getShortcuts().refresh(promoted);
-            }
-        }
-    }
-
     @Override
     protected void finalize() {
         if (!mClosed) {
@@ -299,50 +161,16 @@
         return mQuery;
     }
 
-    public SuggestionCursor getPromoted(Promoter promoter, int maxPromoted) {
-        SuggestionCursor promoted = buildPromoted(promoter, maxPromoted);
-        refreshShortcuts(promoted);
-        return promoted;
-    }
-
-    protected SuggestionCursor buildPromoted(Promoter promoter, int maxPromoted) {
-        ListSuggestionCursor promoted = new ListSuggestionCursorNoDuplicates(mQuery);
-        if (promoter == null) {
-            return promoted;
-        }
-        promoter.pickPromoted(this, maxPromoted, promoted);
-        if (DBG) {
-            Log.d(TAG, "pickPromoted(" + getShortcuts() + "," + mCorpusResults + ","
-                    + maxPromoted + ") = " + promoted);
-        }
-        return promoted;
-    }
-
     /**
      * Gets the list of corpus results reported so far. Do not modify or hang on to
      * the returned iterator.
      */
-    public Iterable<CorpusResult> getCorpusResults() {
-        ArrayList<CorpusResult> results = new ArrayList<CorpusResult>(mCorpusResults.length);
-        for (int i = 0; i < mCorpusResults.length; ++i) {
-            if (mCorpusResults[i] != null) {
-                results.add(mCorpusResults[i]);
-            }
-        }
-        return results;
+    public SourceResult getResult() {
+        return mResult;
     }
 
-    public CorpusResult getCorpusResult(Corpus corpus) {
-        for (CorpusResult result : mCorpusResults) {
-            if (result != null && corpus.equals(result.getCorpus())) {
-                return result;
-            }
-        }
-        return null;
-    }
-
-    public CorpusResult getWebResult() {
-        return mWebResult;
+    public SourceResult getWebResult() {
+        return mResult;
     }
 
     /**
@@ -353,20 +181,13 @@
         if (isClosed()) {
             throw new IllegalStateException("Called getSourceCount() when closed.");
         }
-        return countCorpusResults();
+        return mResult == null ? 0 : mResult.getCount();
     }
 
     @Override
     public String toString() {
-        return "Suggestions@" + hashCode() + "{expectedCorpora=" + mExpectedCorpora
-                + ",countCorpusResults()=" + countCorpusResults() + "}";
-    }
-
-    private class MyShortcutsObserver extends DataSetObserver {
-        @Override
-        public void onChanged() {
-            notifyDataSetChanged();
-        }
+        return "Suggestions@" + hashCode() + "{source=" + mSource
+                + ",getResultCount()=" + getResultCount() + "}";
     }
 
 }
diff --git a/src/com/android/quicksearchbox/SuggestionsProvider.java b/src/com/android/quicksearchbox/SuggestionsProvider.java
index c2bc1a8..9196018 100644
--- a/src/com/android/quicksearchbox/SuggestionsProvider.java
+++ b/src/com/android/quicksearchbox/SuggestionsProvider.java
@@ -16,9 +16,6 @@
 
 package com.android.quicksearchbox;
 
-import java.util.List;
-
-
 /**
  * Provides a set of suggestion results for a query..
  *
@@ -29,9 +26,9 @@
      * Gets suggestions for a query.
      *
      * @param query The query.
-     * @param corporaToQuery The corpora to query. Must be non-null.
+     * @param source The source to query. Must be non-null.
      */
-    Suggestions getSuggestions(String query, List<Corpus> corporaToQuery);
+    Suggestions getSuggestions(String query, Source source);
 
     void close();
 }
diff --git a/src/com/android/quicksearchbox/SuggestionsProviderImpl.java b/src/com/android/quicksearchbox/SuggestionsProviderImpl.java
index d0e96a0..76a9071 100644
--- a/src/com/android/quicksearchbox/SuggestionsProviderImpl.java
+++ b/src/com/android/quicksearchbox/SuggestionsProviderImpl.java
@@ -16,17 +16,14 @@
 
 package com.android.quicksearchbox;
 
+import android.os.Handler;
+import android.util.Log;
+
 import com.android.quicksearchbox.util.BatchingNamedTaskExecutor;
 import com.android.quicksearchbox.util.Consumer;
 import com.android.quicksearchbox.util.NamedTaskExecutor;
 import com.android.quicksearchbox.util.NoOpConsumer;
 
-import android.os.Handler;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.List;
-
 /**
  * Suggestions provider implementation.
  *
@@ -44,12 +41,8 @@
 
     private final Handler mPublishThread;
 
-    private final ShouldQueryStrategy mShouldQueryStrategy;
-
     private final Logger mLogger;
 
-    private BatchingNamedTaskExecutor mBatchingExecutor;
-
     public SuggestionsProviderImpl(Config config,
             NamedTaskExecutor queryExecutor,
             Handler publishThread,
@@ -58,101 +51,33 @@
         mQueryExecutor = queryExecutor;
         mPublishThread = publishThread;
         mLogger = logger;
-        mShouldQueryStrategy = new ShouldQueryStrategy(mConfig);
     }
 
+    @Override
     public void close() {
-        cancelPendingTasks();
     }
 
-    /**
-     * Cancels all pending query tasks.
-     */
-    private void cancelPendingTasks() {
-        if (mBatchingExecutor != null) {
-            mBatchingExecutor.cancelPendingTasks();
-            mBatchingExecutor = null;
-        }
-    }
-
-    /**
-     * Gets the sources that should be queried for the given query.
-     */
-    private List<Corpus> filterCorpora(String query, List<Corpus> corpora) {
-        // If there is only one corpus, always query it
-        if (corpora.size() <= 1) return corpora;
-        ArrayList<Corpus> corporaToQuery = new ArrayList<Corpus>(corpora.size());
-        for (Corpus corpus : corpora) {
-            if (shouldQueryCorpus(corpus, query)) {
-                if (DBG) Log.d(TAG, "should query corpus " + corpus);
-                corporaToQuery.add(corpus);
-            } else {
-                if (DBG) Log.d(TAG, "should NOT query corpus " + corpus);
-            }
-        }
-        if (DBG) Log.d(TAG, "getCorporaToQuery corporaToQuery=" + corporaToQuery);
-        return corporaToQuery;
-    }
-
-    protected boolean shouldQueryCorpus(Corpus corpus, String query) {
-        return mShouldQueryStrategy.shouldQueryCorpus(corpus, query);
-    }
-
-    private void updateShouldQueryStrategy(CorpusResult cursor) {
-        if (cursor.getCount() == 0) {
-            mShouldQueryStrategy.onZeroResults(cursor.getCorpus(),
-                    cursor.getUserQuery());
-        }
-    }
-
-    public Suggestions getSuggestions(String query, List<Corpus> corporaToQuery) {
+    @Override
+    public Suggestions getSuggestions(String query, Source sourceToQuery) {
         if (DBG) Log.d(TAG, "getSuggestions(" + query + ")");
-        corporaToQuery = filterCorpora(query, corporaToQuery);
-        final Suggestions suggestions = new Suggestions(query, corporaToQuery);
-        Log.i(TAG, "chars:" + query.length() + ",corpora:" + corporaToQuery);
+        final Suggestions suggestions = new Suggestions(query, sourceToQuery);
+        Log.i(TAG, "chars:" + query.length() + ",source:" + sourceToQuery);
 
-        // Fast path for the zero sources case
-        if (corporaToQuery.size() == 0) {
-            return suggestions;
-        }
-
-        int initialBatchSize = countDefaultCorpora(corporaToQuery);
-        if (initialBatchSize == 0) {
-            initialBatchSize = mConfig.getNumPromotedSources();
-        }
-
-        mBatchingExecutor = new BatchingNamedTaskExecutor(mQueryExecutor);
-
-        long publishResultDelayMillis = mConfig.getPublishResultDelayMillis();
-
-        Consumer<CorpusResult> receiver;
+        Consumer<SourceResult> receiver;
         if (shouldDisplayResults(query)) {
-            receiver = new SuggestionCursorReceiver(
-                    mBatchingExecutor, suggestions, initialBatchSize,
-                    publishResultDelayMillis);
+            receiver = new SuggestionCursorReceiver(suggestions);
         } else {
-            receiver = new NoOpConsumer<CorpusResult>();
+            receiver = new NoOpConsumer<SourceResult>();
             suggestions.done();
         }
 
-        int maxResultsPerSource = mConfig.getMaxResultsPerSource();
-        QueryTask.startQueries(query, maxResultsPerSource, corporaToQuery, mBatchingExecutor,
-                mPublishThread, receiver, corporaToQuery.size() == 1);
-        mBatchingExecutor.executeNextBatch(initialBatchSize);
+        int maxResults = mConfig.getMaxResultsPerSource();
+        QueryTask.startQuery(query, maxResults, sourceToQuery, mQueryExecutor,
+                mPublishThread, receiver);
 
         return suggestions;
     }
 
-    private int countDefaultCorpora(List<Corpus> corpora) {
-        int count = 0;
-        for (Corpus corpus : corpora) {
-            if (corpus.isCorpusDefaultEnabled()) {
-                count++;
-            }
-        }
-        return count;
-    }
-
     private boolean shouldDisplayResults(String query) {
         if (query.length() == 0 && !mConfig.showSuggestionsForZeroQuery()) {
             // Note that even though we don't display such results, it's
@@ -164,72 +89,27 @@
     }
 
 
-    private class SuggestionCursorReceiver implements Consumer<CorpusResult> {
-        private final BatchingNamedTaskExecutor mExecutor;
+    private class SuggestionCursorReceiver implements Consumer<SourceResult> {
         private final Suggestions mSuggestions;
-        private final long mResultPublishDelayMillis;
-        private final ArrayList<CorpusResult> mPendingResults;
-        private final Runnable mResultPublishTask = new Runnable () {
-            public void run() {
-                if (DBG) Log.d(TAG, "Publishing delayed results");
-                publishPendingResults();
-            }
-        };
 
-        private int mCountAtWhichToExecuteNextBatch;
-
-        public SuggestionCursorReceiver(BatchingNamedTaskExecutor executor,
-                Suggestions suggestions, int initialBatchSize,
-                long publishResultDelayMillis) {
-            mExecutor = executor;
+        public SuggestionCursorReceiver(Suggestions suggestions) {
             mSuggestions = suggestions;
-            mCountAtWhichToExecuteNextBatch = initialBatchSize;
-            mResultPublishDelayMillis = publishResultDelayMillis;
-            mPendingResults = new ArrayList<CorpusResult>();
         }
 
-        public boolean consume(CorpusResult cursor) {
+        @Override
+        public boolean consume(SourceResult cursor) {
             if (DBG) {
                 Log.d(TAG, "SuggestionCursorReceiver.consume(" + cursor + ") corpus=" +
-                        cursor.getCorpus() + " count = " + cursor.getCount());
+                        cursor.getSource() + " count = " + cursor.getCount());
             }
-            updateShouldQueryStrategy(cursor);
-            mPendingResults.add(cursor);
-            if (mResultPublishDelayMillis > 0
-                    && !mSuggestions.isClosed()
-                    && mSuggestions.getResultCount() + mPendingResults.size()
-                            < mCountAtWhichToExecuteNextBatch) {
-                // This is not the last result of the batch, delay publishing
-                if (DBG) Log.d(TAG, "Delaying result by " + mResultPublishDelayMillis + " ms");
-                mPublishThread.removeCallbacks(mResultPublishTask);
-                mPublishThread.postDelayed(mResultPublishTask, mResultPublishDelayMillis);
-            } else {
-                // This is the last result, publish immediately
-                if (DBG) Log.d(TAG, "Publishing result immediately");
-                mPublishThread.removeCallbacks(mResultPublishTask);
-                publishPendingResults();
-            }
-            if (!mSuggestions.isClosed()) {
-                executeNextBatchIfNeeded();
-            }
+            // publish immediately
+            if (DBG) Log.d(TAG, "Publishing results");
+            mSuggestions.addResults(cursor);
             if (cursor != null && mLogger != null) {
                 mLogger.logLatency(cursor);
             }
             return true;
         }
 
-        private void publishPendingResults() {
-            mSuggestions.addCorpusResults(mPendingResults);
-            mPendingResults.clear();
-        }
-
-        private void executeNextBatchIfNeeded() {
-            if (mSuggestions.getResultCount() == mCountAtWhichToExecuteNextBatch) {
-                // We've just finished one batch, ask for more
-                int nextBatchSize = mConfig.getNumPromotedSources();
-                mCountAtWhichToExecuteNextBatch += nextBatchSize;
-                mExecutor.executeNextBatch(nextBatchSize);
-            }
-        }
     }
 }
diff --git a/src/com/android/quicksearchbox/VoiceSearch.java b/src/com/android/quicksearchbox/VoiceSearch.java
index b407eb5..674db96 100644
--- a/src/com/android/quicksearchbox/VoiceSearch.java
+++ b/src/com/android/quicksearchbox/VoiceSearch.java
@@ -44,12 +44,8 @@
         return mContext;
     }
 
-    public boolean shouldShowVoiceSearch(Corpus corpus) {
-        return corpusSupportsVoiceSearch(corpus) && isVoiceSearchAvailable();
-    }
-
-    protected boolean corpusSupportsVoiceSearch(Corpus corpus) {
-        return (corpus == null || corpus.voiceSearchEnabled());
+    public boolean shouldShowVoiceSearch() {
+        return isVoiceSearchAvailable();
     }
 
     protected Intent createVoiceSearchIntent() {
diff --git a/src/com/android/quicksearchbox/WebCorpus.java b/src/com/android/quicksearchbox/WebCorpus.java
deleted file mode 100644
index dfd6fb0..0000000
--- a/src/com/android/quicksearchbox/WebCorpus.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-
-import com.android.quicksearchbox.util.Util;
-
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.util.Log;
-import android.util.Patterns;
-import android.webkit.URLUtil;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Executor;
-
-/**
- * The web search source.
- */
-public class WebCorpus extends MultiSourceCorpus {
-    private static final String TAG = "QSB.WebCorpus";
-    private static final boolean DBG = false;
-
-    private static final String WEB_CORPUS_NAME = "web";
-
-    private final SearchSettings mSettings;
-
-    private Source mWebSearchSource;
-
-    private final Source mBrowserSource;
-
-    public WebCorpus(Context context, Config config, SearchSettings settings, Executor executor,
-            Source webSearchSource, Source browserSource) {
-        super(context, config, executor, webSearchSource, browserSource);
-        if (DBG) {
-            Log.d(TAG, "init webSource=" + webSearchSource + "; browser source = " + browserSource);
-        }
-        mSettings = settings;
-        mWebSearchSource = webSearchSource;
-        mBrowserSource = browserSource;
-    }
-
-    protected SearchSettings getSettings() {
-        return mSettings;
-    }
-
-    public void setWebSource(Source web) {
-        if (DBG) Log.d(TAG, "setWebSource(" + web + ")");
-        mWebSearchSource = web;
-    }
-
-    public CharSequence getLabel() {
-        return getContext().getText(R.string.corpus_label_web);
-    }
-
-    public CharSequence getHint() {
-        // The web corpus uses a drawable hint instead
-        return null;
-    }
-
-    private boolean isUrl(String query) {
-       return Patterns.WEB_URL.matcher(query).matches();
-    }
-
-    public Intent createSearchIntent(String query, Bundle appData) {
-        if (isUrl(query)) {
-            return createBrowseIntent(query);
-        } else if (mWebSearchSource != null){
-            return mWebSearchSource.createSearchIntent(query, appData);
-        } else {
-            return null;
-        }
-    }
-
-    private Intent createBrowseIntent(String query) {
-        Intent intent = new Intent(Intent.ACTION_VIEW);
-        intent.addCategory(Intent.CATEGORY_BROWSABLE);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-        String url = URLUtil.guessUrl(query);
-        intent.setData(Uri.parse(url));
-        return intent;
-    }
-
-    public Intent createVoiceSearchIntent(Bundle appData) {
-        // TODO in 2-pane mode, mWebSearchSource may be NULL
-        // this functionality should be moved elsewhere.
-        if (mWebSearchSource != null){
-            return mWebSearchSource.createVoiceSearchIntent(appData);
-        } else {
-            return null;
-        }
-    }
-
-    private int getCorpusIconResource() {
-        return R.drawable.corpus_icon_web;
-    }
-
-    public Drawable getCorpusIcon() {
-        return getContext().getResources().getDrawable(getCorpusIconResource());
-    }
-
-    public Uri getCorpusIconUri() {
-        return Util.getResourceUri(getContext(), getCorpusIconResource());
-    }
-
-    public String getName() {
-        return WEB_CORPUS_NAME;
-    }
-
-    @Override
-    public int getQueryThreshold() {
-        return 0;
-    }
-
-    @Override
-    public boolean queryAfterZeroResults() {
-        return true;
-    }
-
-    @Override
-    public boolean voiceSearchEnabled() {
-        return true;
-    }
-
-    public boolean isWebCorpus() {
-        return true;
-    }
-
-    public CharSequence getSettingsDescription() {
-        return getContext().getText(R.string.corpus_description_web);
-    }
-
-    @Override
-    protected List<Source> getSourcesToQuery(String query, boolean onlyCorpus) {
-        ArrayList<Source> sourcesToQuery = new ArrayList<Source>(2);
-        if (mWebSearchSource != null) sourcesToQuery.add(mWebSearchSource);
-        if (mBrowserSource != null && query.length() > 0) {
-            sourcesToQuery.add(mBrowserSource);
-        }
-        if (DBG) Log.d(TAG, "getSourcesToQuery sourcesToQuery=" + sourcesToQuery);
-        return sourcesToQuery;
-    }
-
-    @Override
-    protected Result createResult(String query, ArrayList<SourceResult> results, int latency) {
-        return new WebResult(query, results, latency);
-    }
-
-    protected class WebResult extends Result {
-
-        public WebResult(String query, ArrayList<SourceResult> results, int latency) {
-            super(query, results, latency);
-        }
-
-        @Override
-        public void fill() {
-            SourceResult webSearchResult = null;
-            SourceResult browserResult = null;
-            for (SourceResult result : getResults()) {
-                if (result.getSource().equals(mWebSearchSource)) {
-                    webSearchResult = result;
-                } else {
-                    browserResult = result;
-                }
-            }
-            if (browserResult != null && browserResult.getCount() > 0) {
-                add(new SuggestionPosition(browserResult, 0));
-            }
-            if (webSearchResult != null) {
-                int count = webSearchResult.getCount();
-                for (int i = 0; i < count; i++) {
-                    add(new SuggestionPosition(webSearchResult, i));
-                }
-            }
-        }
-
-    }
-}
diff --git a/src/com/android/quicksearchbox/WebPromoter.java b/src/com/android/quicksearchbox/WebPromoter.java
deleted file mode 100644
index a0b77a1..0000000
--- a/src/com/android/quicksearchbox/WebPromoter.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import android.util.Log;
-
-
-public class WebPromoter implements Promoter {
-
-    private static final String TAG = "QSB.WebPromoter";
-    private static final boolean DBG = false;
-
-    private final int mMaxShortcuts;
-
-    public WebPromoter(int maxShortcuts) {
-        mMaxShortcuts = maxShortcuts;
-    }
-
-    public void pickPromoted(Suggestions suggestions, int maxPromoted,
-            ListSuggestionCursor promoted) {
-        // Add web shortcuts
-        SuggestionCursor shortcuts = suggestions.getShortcuts();
-        int shortcutCount = shortcuts == null ? 0 : shortcuts.getCount();
-        if (DBG) Log.d(TAG, "Shortcut count: " + shortcutCount);
-        int maxShortcutCount = Math.min(mMaxShortcuts, maxPromoted);
-        for (int i = 0; i < shortcutCount && promoted.getCount() < maxShortcutCount; i++) {
-            shortcuts.moveTo(i);
-            if (shortcuts.isWebSearchSuggestion()) {
-                if (DBG) Log.d(TAG, "Including shortcut " + i);
-                promoted.add(new SuggestionPosition(shortcuts, i));
-            } else {
-                if (DBG) Log.d(TAG, "Skipping shortcut " + i);
-            }
-        }
-
-        // Add web suggestion
-        CorpusResult webResult = suggestions.getWebResult();
-        int webCount = webResult == null ? 0 : webResult.getCount();
-        if (DBG) Log.d(TAG, "Web suggestion count: " + webCount);
-        for (int i = 0; i < webCount && promoted.getCount() < maxPromoted; i++) {
-            webResult.moveTo(i);
-            if (webResult.isWebSearchSuggestion()) {
-                if (DBG) Log.d(TAG, "Including suggestion " + i);
-                promoted.add(new SuggestionPosition(webResult, i));
-            } else {
-                if (DBG) Log.d(TAG, "Skipping suggestion " + i);
-            }
-        }
-    }
-
-}
\ No newline at end of file
diff --git a/src/com/android/quicksearchbox/google/AbstractGoogleSource.java b/src/com/android/quicksearchbox/google/AbstractGoogleSource.java
index 9de1dbb..2077777 100644
--- a/src/com/android/quicksearchbox/google/AbstractGoogleSource.java
+++ b/src/com/android/quicksearchbox/google/AbstractGoogleSource.java
@@ -15,20 +15,19 @@
  */
 package com.android.quicksearchbox.google;
 
-import com.android.quicksearchbox.AbstractInternalSource;
-import com.android.quicksearchbox.Config;
-import com.android.quicksearchbox.CursorBackedSourceResult;
-import com.android.quicksearchbox.R;
-import com.android.quicksearchbox.SourceResult;
-import com.android.quicksearchbox.SuggestionCursor;
-import com.android.quicksearchbox.util.NamedTaskExecutor;
-
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.Handler;
 
+import com.android.quicksearchbox.AbstractInternalSource;
+import com.android.quicksearchbox.CursorBackedSourceResult;
+import com.android.quicksearchbox.R;
+import com.android.quicksearchbox.SourceResult;
+import com.android.quicksearchbox.SuggestionCursor;
+import com.android.quicksearchbox.util.NamedTaskExecutor;
+
 /**
  * Special source implementation for Google suggestions.
  */
@@ -46,40 +45,50 @@
         super(context, uiThread, iconLoader);
     }
 
+    @Override
     public abstract ComponentName getIntentComponent();
 
+    @Override
     public abstract SuggestionCursor refreshShortcut(String shortcutId, String extraData);
 
     /**
      * Called by QSB to get web suggestions for a query.
      */
+    @Override
     public abstract SourceResult queryInternal(String query);
 
     /**
      * Called by external apps to get web suggestions for a query.
      */
+    @Override
     public abstract SourceResult queryExternal(String query);
 
+    @Override
     public Intent createVoiceSearchIntent(Bundle appData) {
         return createVoiceWebSearchIntent(appData);
     }
 
+    @Override
     public String getDefaultIntentAction() {
         return Intent.ACTION_WEB_SEARCH;
     }
 
+    @Override
     public CharSequence getHint() {
         return getContext().getString(R.string.google_search_hint);
     }
 
+    @Override
     public CharSequence getLabel() {
         return getContext().getString(R.string.google_search_label);
     }
 
+    @Override
     public String getName() {
         return GOOGLE_SOURCE_NAME;
     }
 
+    @Override
     public CharSequence getSettingsDescription() {
         return getContext().getString(R.string.google_search_description);
     }
@@ -89,7 +98,8 @@
         return R.mipmap.google_icon;
     }
 
-    public SourceResult getSuggestions(String query, int queryLimit, boolean onlySource) {
+    @Override
+    public SourceResult getSuggestions(String query, int queryLimit) {
         return emptyIfNull(queryInternal(query), query);
     }
 
@@ -101,14 +111,12 @@
         return result == null ? new CursorBackedSourceResult(this, query) : result;
     }
 
+    @Override
     public boolean voiceSearchEnabled() {
         return true;
     }
 
-    public int getMaxShortcuts(Config config) {
-        return config.getMaxShortcutsPerWebSource();
-    }
-
+    @Override
     public boolean includeInAll() {
         return true;
     }
diff --git a/src/com/android/quicksearchbox/google/GoogleSuggestClient.java b/src/com/android/quicksearchbox/google/GoogleSuggestClient.java
index 79d534c..5381acb 100644
--- a/src/com/android/quicksearchbox/google/GoogleSuggestClient.java
+++ b/src/com/android/quicksearchbox/google/GoogleSuggestClient.java
@@ -16,6 +16,16 @@
 
 package com.android.quicksearchbox.google;
 
+import android.content.ComponentName;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.http.AndroidHttpClient;
+import android.os.Build;
+import android.os.Handler;
+import android.text.TextUtils;
+import android.util.Log;
+
 import com.android.quicksearchbox.Config;
 import com.android.quicksearchbox.R;
 import com.android.quicksearchbox.Source;
@@ -27,21 +37,10 @@
 import org.apache.http.client.HttpClient;
 import org.apache.http.client.methods.HttpGet;
 import org.apache.http.params.HttpParams;
-import org.apache.http.params.HttpProtocolParams;
 import org.apache.http.util.EntityUtils;
 import org.json.JSONArray;
 import org.json.JSONException;
 
-import android.content.ComponentName;
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.http.AndroidHttpClient;
-import android.net.NetworkInfo;
-import android.os.Build;
-import android.os.Handler;
-import android.text.TextUtils;
-import android.util.Log;
-
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
@@ -103,7 +102,7 @@
             return null;
         }
         try {
-            query = URLEncoder.encode(query, "UTF-8");
+            String encodedQuery = URLEncoder.encode(query, "UTF-8");
             if (mSuggestUri == null) {
                 Locale l = Locale.getDefault();
                 String language = GoogleSearch.getLanguage(l);
@@ -111,7 +110,7 @@
                                                                     language);
             }
 
-            String suggestUri = mSuggestUri + query;
+            String suggestUri = mSuggestUri + encodedQuery;
             if (DBG) Log.d(LOG_TAG, "Sending request: " + suggestUri);
             HttpGet method = new HttpGet(suggestUri);
             HttpResponse response = mHttpClient.execute(method);
diff --git a/src/com/android/quicksearchbox/google/GoogleSuggestionProvider.java b/src/com/android/quicksearchbox/google/GoogleSuggestionProvider.java
index 61fc77b..02f9d38 100644
--- a/src/com/android/quicksearchbox/google/GoogleSuggestionProvider.java
+++ b/src/com/android/quicksearchbox/google/GoogleSuggestionProvider.java
@@ -63,7 +63,7 @@
         return SearchManager.SUGGEST_MIME_TYPE;
     }
 
-    private SourceResult emptyIfNull(SourceResult result, Source source, String query) {
+    private SourceResult emptyIfNull(SourceResult result, GoogleSource source, String query) {
         return result == null ? new CursorBackedSourceResult(source, query) : result;
     }
 
diff --git a/src/com/android/quicksearchbox/preferences/ClearShortcutsController.java b/src/com/android/quicksearchbox/preferences/ClearShortcutsController.java
deleted file mode 100644
index fe5d039..0000000
--- a/src/com/android/quicksearchbox/preferences/ClearShortcutsController.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox.preferences;
-
-import com.android.quicksearchbox.ShortcutRepository;
-import com.android.quicksearchbox.util.Consumer;
-import com.android.quicksearchbox.util.Consumers;
-
-import android.os.Handler;
-import android.preference.Preference;
-import android.util.Log;
-
-/**
- * Logic behind the 'clear shortcuts' preference.
- */
-public class ClearShortcutsController implements PreferenceController {
-
-    public static final String CLEAR_SHORTCUTS_PREF = "clear_shortcuts";
-
-    private static final boolean DBG = false;
-    private static final String TAG = "QSB.ClearShortcutsController";
-
-    private final ShortcutRepository mShortcuts;
-    private final Handler mHandler = new Handler();
-
-    private OkCancelPreference mClearShortcutsPreference;
-
-
-    public ClearShortcutsController(ShortcutRepository shortcuts) {
-        mShortcuts = shortcuts;
-    }
-
-    @Override
-    public void handlePreference(Preference p) {
-        mClearShortcutsPreference = (OkCancelPreference) p;
-        mClearShortcutsPreference.setListener(new OkCancelPreference.Listener() {
-            @Override
-            public void onDialogClosed(boolean okClicked) {
-                if (okClicked) {
-                    clearShortcuts();
-                }
-            }
-        });
-    }
-
-    public void onCreateComplete() {
-    }
-
-    public void onStop() {
-    }
-
-    public void onDestroy() {
-    }
-
-    @Override
-    public void onResume() {
-        updateClearShortcutsPreference();
-    }
-
-    /**
-     * Enables/disables the "Clear search shortcuts" preference depending
-     * on whether there is any search history.
-     */
-    private void updateClearShortcutsPreference() {
-        mShortcuts.hasHistory(Consumers.createAsyncConsumer(mHandler, new Consumer<Boolean>() {
-            @Override
-            public boolean consume(Boolean hasHistory) {
-                if (DBG) Log.d(TAG, "hasHistory()=" + hasHistory);
-                mClearShortcutsPreference.setEnabled(hasHistory);
-                return true;
-            }
-        }));
-    }
-
-    private void clearShortcuts() {
-        Log.i(TAG, "Clearing shortcuts...");
-        mShortcuts.clearHistory();
-        mClearShortcutsPreference.setEnabled(false);
-    }
-}
diff --git a/src/com/android/quicksearchbox/preferences/DeviceSearchFragment.java b/src/com/android/quicksearchbox/preferences/DeviceSearchFragment.java
deleted file mode 100644
index e259945..0000000
--- a/src/com/android/quicksearchbox/preferences/DeviceSearchFragment.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox.preferences;
-
-import com.android.quicksearchbox.R;
-
-/**
- * 'Device' preferences.
- */
-public class DeviceSearchFragment extends SettingsFragmentBase {
-
-    @Override
-    protected int getPreferencesResourceId() {
-        return R.xml.device_search_preferences;
-    }
-
-}
diff --git a/src/com/android/quicksearchbox/preferences/OkCancelPreference.java b/src/com/android/quicksearchbox/preferences/OkCancelPreference.java
deleted file mode 100644
index 33ccdf1..0000000
--- a/src/com/android/quicksearchbox/preferences/OkCancelPreference.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox.preferences;
-
-import android.content.Context;
-import android.preference.DialogPreference;
-import android.util.AttributeSet;
-
-/**
- * Dialog preference that allows registering a listener for the result.
- */
-public class OkCancelPreference extends DialogPreference {
-
-    private Listener mListener;
-
-    public OkCancelPreference(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    @Override
-    protected void onDialogClosed(boolean positiveResult) {
-        super.onDialogClosed(positiveResult);
-
-        if (mListener != null) {
-            mListener.onDialogClosed(positiveResult);
-        }
-    }
-
-    public void setListener(Listener listener) {
-        mListener = listener;
-    }
-
-    public interface Listener {
-        void onDialogClosed(boolean okClicked);
-    }
-
-}
diff --git a/src/com/android/quicksearchbox/preferences/PreferenceController.java b/src/com/android/quicksearchbox/preferences/PreferenceController.java
deleted file mode 100644
index de6afcb..0000000
--- a/src/com/android/quicksearchbox/preferences/PreferenceController.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox.preferences;
-
-import android.app.Activity;
-import android.preference.Preference;
-
-/**
- * Interfaces for classes that handle logic behind a settings preference.
- */
-public interface PreferenceController {
-
-    /**
-     * Handle a preference. This should take any action necessary to implement the logic behind the
-     * given preference. It will be called from {@link Activity#onCreate}.
-     * @param p
-     */
-    void handlePreference(Preference p);
-
-    /**
-     * Called when {@link Activity#onCreate} has completed and is just about to return.
-     */
-    void onCreateComplete();
-
-    /**
-     * Called from {@link Activity#onResume}.
-     */
-    void onResume();
-
-    /**
-     * Called from {@link Activity#onStop}.
-     */
-    void onStop();
-
-    /**
-     * called from {@link Activity#onDestroy}
-     */
-    void onDestroy();
-
-}
diff --git a/src/com/android/quicksearchbox/preferences/PreferenceControllerFactory.java b/src/com/android/quicksearchbox/preferences/PreferenceControllerFactory.java
deleted file mode 100644
index d95ffe6..0000000
--- a/src/com/android/quicksearchbox/preferences/PreferenceControllerFactory.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox.preferences;
-
-import com.android.quicksearchbox.Corpora;
-import com.android.quicksearchbox.QsbApplication;
-import com.android.quicksearchbox.SearchSettings;
-import com.android.quicksearchbox.ShortcutRepository;
-
-import android.content.Context;
-import android.preference.Preference;
-
-import java.util.ArrayList;
-
-/**
- * Class to handle logic behind the preferences in settings.
- */
-public class PreferenceControllerFactory implements PreferenceController {
-
-    private final SearchSettings mSettings;
-    private final Context mContext;
-    private final ArrayList<PreferenceController> mControllers;
-
-    public PreferenceControllerFactory(SearchSettings settings, Context context) {
-        mSettings = settings;
-        mContext = context;
-        mControllers = new ArrayList<PreferenceController>();
-    }
-
-    protected Context getContext() {
-        return mContext;
-    }
-
-    public void handlePreference(Preference p) {
-        String key = p.getKey();
-        if (key == null) return;
-        if (SearchableItemsController.SEARCH_CORPORA_PREF.equals(key)) {
-            Corpora corpora = QsbApplication.get(mContext).getCorpora();
-            addController(new SearchableItemsController(mSettings, corpora, getContext()), p);
-        } else if (ClearShortcutsController.CLEAR_SHORTCUTS_PREF.equals(key)) {
-            ShortcutRepository shortcuts = QsbApplication.get(getContext()).getShortcutRepository();
-            addController(new ClearShortcutsController(shortcuts), p);
-        } else {
-            throw new UnknownPreferenceException(p);
-        }
-    }
-
-    public void onCreateComplete() {
-        for (PreferenceController controller : mControllers) {
-            controller.onCreateComplete();
-        }
-    }
-
-    public void onResume() {
-        for (PreferenceController controller : mControllers) {
-            controller.onResume();
-        }
-    }
-
-    public void onStop() {
-        for (PreferenceController controller : mControllers) {
-            controller.onStop();
-        }
-    }
-
-    public void onDestroy() {
-        for (PreferenceController controller : mControllers) {
-            controller.onDestroy();
-        }
-    }
-
-    protected void addController(PreferenceController controller, Preference forPreference) {
-        mControllers.add(controller);
-        controller.handlePreference(forPreference);
-    }
-
-    private static class UnknownPreferenceException extends RuntimeException {
-        public UnknownPreferenceException(Preference p) {
-            super("Preference key " + p.getKey() + "; class: " + p.getClass().toString());
-        }
-    }
-}
diff --git a/src/com/android/quicksearchbox/preferences/SearchSettingsActivity.java b/src/com/android/quicksearchbox/preferences/SearchSettingsActivity.java
deleted file mode 100644
index f742034..0000000
--- a/src/com/android/quicksearchbox/preferences/SearchSettingsActivity.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox.preferences;
-
-import com.android.quicksearchbox.QsbApplication;
-import com.android.quicksearchbox.R;
-
-import android.preference.PreferenceActivity;
-import android.util.Log;
-import android.view.Menu;
-
-import java.util.List;
-
-/**
- * Activity for setting global search preferences.
- */
-public class SearchSettingsActivity extends PreferenceActivity {
-    private static final String TAG = "QSB.SearchSettingsActivity";
-    private static final boolean DBG = false;
-
-    private static final String CLEAR_SHORTCUTS_FRAGMENT = DeviceSearchFragment.class.getName();
-
-    private static final String ACTIVITY_HELP_CONTEXT = "settings";
-
-    /**
-     * Populate the activity with the top-level headers.
-     */
-    @Override
-    public void onBuildHeaders(List<Header> target) {
-        loadHeadersFromResource(R.xml.preferences_headers, target);
-        onHeadersBuilt(target);
-    }
-
-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        super.onCreateOptionsMenu(menu);
-        getQsbApplication().getHelp().addHelpMenuItem(menu, ACTIVITY_HELP_CONTEXT, true);
-        return true;
-    }
-
-    protected QsbApplication getQsbApplication() {
-        return QsbApplication.get(this);
-    }
-
-    /**
-     * Get the name of the fragment that contains only a 'clear shortcuts' preference, and hence
-     * can be removed if zero-query shortcuts are disabled. Returns null if no such fragment exists.
-     */
-    protected String getShortcutsOnlyFragment() {
-        return CLEAR_SHORTCUTS_FRAGMENT;
-    }
-
-    protected void onHeadersBuilt(List<Header> target) {
-        String shortcutsFragment = getShortcutsOnlyFragment();
-        if (shortcutsFragment == null) return;
-        if (DBG) Log.d(TAG, "onHeadersBuilt shortcutsFragment=" + shortcutsFragment);
-        if (!QsbApplication.get(this).getConfig().showShortcutsForZeroQuery()) {
-            // remove 'clear shortcuts'
-            for (int i = 0; i < target.size(); ++i) {
-                String fragment = target.get(i).fragment;
-                if (DBG) Log.d(TAG, "fragment " + i + ": " + fragment);
-                if (shortcutsFragment.equals(fragment)) {
-                    target.remove(i);
-                    break;
-                }
-            }
-        }
-    }
-
-}
diff --git a/src/com/android/quicksearchbox/preferences/SearchableItemPreference.java b/src/com/android/quicksearchbox/preferences/SearchableItemPreference.java
deleted file mode 100644
index 9926f18..0000000
--- a/src/com/android/quicksearchbox/preferences/SearchableItemPreference.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox.preferences;
-
-import com.android.quicksearchbox.R;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.preference.CheckBoxPreference;
-import android.view.View;
-import android.widget.ImageView;
-
-/**
- * A CheckBoxPreference with an icon added.
- */
-public class SearchableItemPreference extends CheckBoxPreference {
-
-    private Drawable mIcon;
-
-    SearchableItemPreference(Context context) {
-        super(context);
-        setLayoutResource(R.layout.searchable_item_preference);
-    }
-
-    public void setIcon(Drawable icon) {
-        mIcon = icon;
-    }
-
-     @Override
-    protected void onBindView(View view) {
-        super.onBindView(view);
-        ImageView icon = (ImageView) view.findViewById(R.id.icon);
-        icon.setImageDrawable(mIcon);
-    }
-
-}
diff --git a/src/com/android/quicksearchbox/preferences/SearchableItemsController.java b/src/com/android/quicksearchbox/preferences/SearchableItemsController.java
deleted file mode 100644
index c6a8b3a..0000000
--- a/src/com/android/quicksearchbox/preferences/SearchableItemsController.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox.preferences;
-
-import com.android.quicksearchbox.Corpora;
-import com.android.quicksearchbox.Corpus;
-import com.android.quicksearchbox.R;
-import com.android.quicksearchbox.SearchSettings;
-import com.android.quicksearchbox.SearchSettingsImpl;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.preference.Preference;
-import android.preference.Preference.OnPreferenceChangeListener;
-import android.preference.PreferenceGroup;
-import android.util.Log;
-
-/**
- * Logic backing the searchable items activity or fragment.
- */
-public class SearchableItemsController implements PreferenceController, OnPreferenceChangeListener {
-
-    private static final boolean DBG = false;
-    private static final String TAG = "QSB.SearchableItemsSettings";
-
-    public static final String SEARCH_CORPORA_PREF = "search_corpora";
-
-    private final SearchSettings mSearchSettings;
-    private final Corpora mCorpora;
-    private final Context mContext;
-
-    // References to the top-level preference objects
-    private PreferenceGroup mCorporaPreferences;
-
-    public SearchableItemsController(SearchSettings searchSettings, Corpora corpora,
-            Context context) {
-        mSearchSettings = searchSettings;
-        mCorpora = corpora;
-        mContext = context;
-    }
-
-    public void handlePreference(Preference corporaPreferences) {
-        mCorporaPreferences = (PreferenceGroup) corporaPreferences;
-        populateSourcePreference();
-    }
-
-    public String getCorporaPreferenceKey() {
-        return SEARCH_CORPORA_PREF;
-    }
-
-    private SearchSettings getSettings() {
-        return mSearchSettings;
-    }
-
-    private Corpora getCorpora() {
-        return mCorpora;
-    }
-
-    private Context getContext() {
-        return mContext;
-    }
-
-    private Resources getResources() {
-        return getContext().getResources();
-    }
-
-
-    /**
-     * Fills the suggestion source list.
-     */
-    private void populateSourcePreference() {
-        boolean includeNonAllCorpora =
-                getResources().getBoolean(R.bool.show_non_all_corpora_in_settings);
-        mCorporaPreferences.setOrderingAsAdded(false);
-        for (Corpus corpus : getCorpora().getAllCorpora()) {
-            if (includeNonAllCorpora || corpus.includeInAll()) {
-                Preference pref = createCorpusPreference(corpus);
-                if (pref != null) {
-                    if (DBG) Log.d(TAG, "Adding corpus: " + corpus);
-                    mCorporaPreferences.addPreference(pref);
-                }
-            }
-        }
-    }
-
-    /**
-     * Adds a suggestion source to the list of suggestion source checkbox preferences.
-     */
-    private Preference createCorpusPreference(Corpus corpus) {
-        SearchableItemPreference sourcePref = new SearchableItemPreference(getContext());
-        sourcePref.setKey(SearchSettingsImpl.getCorpusEnabledPreference(corpus));
-        // Put web corpus first. The rest are alphabetical.
-        if (corpus.isWebCorpus()) {
-            sourcePref.setOrder(0);
-        }
-        sourcePref.setDefaultValue(corpus.isCorpusDefaultEnabled());
-        sourcePref.setOnPreferenceChangeListener(this);
-        CharSequence label = corpus.getLabel();
-        sourcePref.setTitle(label);
-        CharSequence description = corpus.getSettingsDescription();
-        sourcePref.setSummaryOn(description);
-        sourcePref.setSummaryOff(description);
-        sourcePref.setIcon(corpus.getCorpusIcon());
-        return sourcePref;
-    }
-
-    public boolean onPreferenceChange(Preference preference, Object newValue) {
-        getSettings().broadcastSettingsChanged();
-        return true;
-    }
-
-    public void onCreateComplete() {
-    }
-
-    public void onStop() {
-    }
-
-    public void onDestroy() {
-    }
-
-    public void onResume() {
-    }
-
-}
diff --git a/src/com/android/quicksearchbox/preferences/SearchableItemsFragment.java b/src/com/android/quicksearchbox/preferences/SearchableItemsFragment.java
deleted file mode 100644
index c077d79..0000000
--- a/src/com/android/quicksearchbox/preferences/SearchableItemsFragment.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox.preferences;
-
-import com.android.quicksearchbox.R;
-
-import android.preference.PreferenceGroup;
-
-/**
- * Fragment for selecting searchable items
- */
-public class SearchableItemsFragment extends SettingsFragmentBase {
-
-    @Override
-    protected int getPreferencesResourceId() {
-        return R.xml.preferences_searchable_items;
-    }
-
-    @Override
-    protected void handlePreferenceGroup(PreferenceGroup screen) {
-        getController().handlePreference(screen);
-    }
-}
diff --git a/src/com/android/quicksearchbox/preferences/SettingsFragmentBase.java b/src/com/android/quicksearchbox/preferences/SettingsFragmentBase.java
deleted file mode 100644
index 74af931..0000000
--- a/src/com/android/quicksearchbox/preferences/SettingsFragmentBase.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox.preferences;
-
-import com.android.quicksearchbox.QsbApplication;
-
-import android.os.Bundle;
-import android.preference.Preference;
-import android.preference.PreferenceCategory;
-import android.preference.PreferenceFragment;
-import android.preference.PreferenceGroup;
-
-/**
- * System search settings fragment.
- */
-public abstract class SettingsFragmentBase extends PreferenceFragment {
-
-    // Name of the preferences file used to store search preference
-    public static final String PREFERENCES_NAME = "SearchSettings";
-
-    private PreferenceController mController;
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        mController = createController();
-
-        getPreferenceManager().setSharedPreferencesName(getPreferencesName());
-
-        addPreferencesFromResource(getPreferencesResourceId());
-
-        handlePreferenceGroup(getPreferenceScreen());
-
-        mController.onCreateComplete();
-    }
-
-    protected PreferenceController getController() {
-        return mController;
-    }
-
-    protected PreferenceControllerFactory createController() {
-        QsbApplication app = QsbApplication.get(getActivity());
-        return app.createPreferenceControllerFactory(getActivity());
-    }
-
-    protected String getPreferencesName() {
-        return PREFERENCES_NAME;
-    }
-
-    protected abstract int getPreferencesResourceId();
-
-    protected void handlePreferenceGroup(PreferenceGroup group) {
-        for (int i = 0; i < group.getPreferenceCount(); ++i) {
-            Preference p = group.getPreference(i);
-            if (p instanceof PreferenceCategory) {
-                handlePreferenceGroup((PreferenceCategory) p);
-            } else {
-                mController.handlePreference(group.getPreference(i));
-            }
-        }
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        mController.onResume();
-    }
-
-    @Override
-    public void onStop() {
-        mController.onStop();
-        super.onStop();
-    }
-
-    @Override
-    public void onDestroy() {
-        mController.onDestroy();
-        super.onDestroy();
-    }
-}
diff --git a/src/com/android/quicksearchbox/ui/BaseSuggestionView.java b/src/com/android/quicksearchbox/ui/BaseSuggestionView.java
index c891a8d..ed7f74b 100644
--- a/src/com/android/quicksearchbox/ui/BaseSuggestionView.java
+++ b/src/com/android/quicksearchbox/ui/BaseSuggestionView.java
@@ -60,17 +60,12 @@
         mIcon2 = (ImageView) findViewById(R.id.icon2);
     }
 
+    @Override
     public void bindAsSuggestion(Suggestion suggestion, String userQuery) {
         setOnClickListener(new ClickListener());
-        if (isFromHistory(suggestion)) {
-            setLongClickable(true);
-            setOnLongClickListener(new LongClickListener());
-        } else {
-            setLongClickable(false);
-            setOnLongClickListener(null);
-        }
     }
 
+    @Override
     public void bindAdapter(SuggestionsAdapter<?> adapter, long suggestionId) {
         mAdapter = adapter;
         mSuggestionId = suggestionId;
@@ -105,18 +100,6 @@
         }
     }
 
-    protected void onSuggestionQuickContactClicked() {
-        if (mAdapter != null) {
-            mAdapter.onSuggestionQuickContactClicked(mSuggestionId);
-        }
-    }
-
-    protected void onRemoveFromHistoryClicked() {
-        if (mAdapter != null) {
-            mAdapter.onSuggestionRemoveFromHistoryClicked(mSuggestionId);
-        }
-    }
-
     protected void onSuggestionQueryRefineClicked() {
         if (mAdapter != null) {
             mAdapter.onSuggestionQueryRefineClicked(mSuggestionId);
@@ -124,16 +107,10 @@
     }
 
     private class ClickListener implements OnClickListener {
+        @Override
         public void onClick(View v) {
             onSuggestionClicked();
         }
     }
 
-    private class LongClickListener implements View.OnLongClickListener {
-        public boolean onLongClick(View v) {
-            onRemoveFromHistoryClicked();
-            return true;
-        }
-    }
-
 }
diff --git a/src/com/android/quicksearchbox/ui/ClusteredSuggestionsAdapter.java b/src/com/android/quicksearchbox/ui/ClusteredSuggestionsAdapter.java
deleted file mode 100644
index eef4f1f..0000000
--- a/src/com/android/quicksearchbox/ui/ClusteredSuggestionsAdapter.java
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox.ui;
-
-import com.android.quicksearchbox.CorpusResult;
-import com.android.quicksearchbox.ListSuggestionCursor;
-import com.android.quicksearchbox.R;
-import com.android.quicksearchbox.Suggestion;
-import com.android.quicksearchbox.SuggestionCursor;
-import com.android.quicksearchbox.SuggestionPosition;
-import com.android.quicksearchbox.SuggestionUtils;
-import com.android.quicksearchbox.Suggestions;
-
-import android.content.Context;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseExpandableListAdapter;
-import android.widget.ExpandableListAdapter;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-
-/**
- * Adapter for suggestions list where suggestions are clustered by corpus.
- */
-public class ClusteredSuggestionsAdapter extends SuggestionsAdapterBase<ExpandableListAdapter> {
-
-    private static final String TAG = "QSB.ClusteredSuggestionsAdapter";
-
-    private final static int GROUP_SHIFT = 32;
-    private final static long CHILD_MASK = 0xffffffff;
-
-    private final Adapter mAdapter;
-    private final Context mContext;
-    private final LayoutInflater mInflater;
-
-    public ClusteredSuggestionsAdapter(SuggestionViewFactory viewFactory, Context context) {
-        super(viewFactory);
-        mAdapter = new Adapter();
-        mContext = context;
-        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-    }
-
-    @Override
-    public boolean isEmpty() {
-        return mAdapter.getGroupCount() == 0;
-    }
-
-    @Override
-    public boolean willPublishNonPromotedSuggestions() {
-        return true;
-    }
-
-    @Override
-    public SuggestionPosition getSuggestion(long suggestionId) {
-        return mAdapter.getChildById(suggestionId);
-    }
-
-    @Override
-    public ExpandableListAdapter getListAdapter() {
-        return mAdapter;
-    }
-
-    @Override
-    protected void notifyDataSetChanged() {
-        mAdapter.buildCorpusGroups();
-        mAdapter.notifyDataSetChanged();
-    }
-
-    @Override
-    protected void notifyDataSetInvalidated() {
-        mAdapter.buildCorpusGroups();
-        mAdapter.notifyDataSetInvalidated();
-    }
-
-    private class Adapter extends BaseExpandableListAdapter {
-
-        private ArrayList<SuggestionCursor> mCorpusGroups;
-
-        public void buildCorpusGroups() {
-            Suggestions suggestions = getSuggestions();
-            SuggestionCursor promoted = getCurrentPromotedSuggestions();
-            HashSet<String> promotedSuggestions = new HashSet<String>();
-            if (promoted != null && promoted.getCount() > 0) {
-                promoted.moveTo(0);
-                do {
-                    promotedSuggestions.add(SuggestionUtils.getSuggestionKey(promoted));
-                } while (promoted.moveToNext());
-            }
-            if (suggestions == null) {
-                mCorpusGroups = null;
-            } else {
-                if (mCorpusGroups == null) {
-                    mCorpusGroups = new ArrayList<SuggestionCursor>();
-                } else {
-                    mCorpusGroups.clear();
-                }
-                for (CorpusResult result : suggestions.getCorpusResults()) {
-                    ListSuggestionCursor corpusSuggestions = new ListSuggestionCursor(
-                            result.getUserQuery());
-                    for (int i = 0; i < result.getCount(); ++i) {
-                        result.moveTo(i);
-                        if (!result.isWebSearchSuggestion()) {
-                            if (!promotedSuggestions.contains(
-                                    SuggestionUtils.getSuggestionKey(result))) {
-                                corpusSuggestions.add(new SuggestionPosition(result, i));
-                            }
-                        }
-                    }
-                    if (corpusSuggestions.getCount() > 0) {
-                        mCorpusGroups.add(corpusSuggestions);
-                    }
-                }
-            }
-        }
-
-        @Override
-        public long getCombinedChildId(long groupId, long childId) {
-            // add one to the child ID to ensure that the group elements do not have the same ID
-            // as the first child within the group.
-            return (groupId << GROUP_SHIFT) | ((childId + 1) & CHILD_MASK);
-        }
-
-        @Override
-        public long getCombinedGroupId(long groupId) {
-            return groupId << GROUP_SHIFT;
-        }
-
-        public int getChildPosition(long childId) {
-            return (int) (childId & CHILD_MASK) - 1;
-        }
-
-        public int getGroupPosition(long childId) {
-            return (int) ((childId >> GROUP_SHIFT) & CHILD_MASK);
-        }
-
-        @Override
-        public Suggestion getChild(int groupPosition, int childPosition) {
-            SuggestionCursor c = getGroup(groupPosition);
-            if (c != null) {
-                c.moveTo(childPosition);
-                return new SuggestionPosition(c, childPosition);
-            }
-            return null;
-        }
-
-        public SuggestionPosition getChildById(long childId) {
-            SuggestionCursor groupCursor = getGroup(getGroupPosition(childId));
-            if (groupCursor != null) {
-                return new SuggestionPosition(groupCursor, getChildPosition(childId));
-            } else {
-                Log.w(TAG, "Invalid childId " + Long.toHexString(childId) + " (invalid group)");
-                return null;
-            }
-        }
-
-        @Override
-        public long getChildId(int groupPosition, int childPosition) {
-            return childPosition;
-        }
-
-        @Override
-        public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
-                View convertView, ViewGroup parent) {
-            SuggestionCursor cursor = getGroup(groupPosition);
-            if (cursor == null) return null;
-            return getView(cursor, childPosition, getCombinedChildId(groupPosition, childPosition),
-                    convertView, parent);
-        }
-
-        @Override
-        public int getChildrenCount(int groupPosition) {
-            SuggestionCursor group = getGroup(groupPosition);
-            return group == null ? 0 : group.getCount();
-        }
-
-        @Override
-        public SuggestionCursor getGroup(int groupPosition) {
-            if (groupPosition < promotedGroupCount()) {
-                return getCurrentPromotedSuggestions();
-            } else {
-                int pos = groupPosition - promotedGroupCount();
-                if ((pos < 0 ) || (pos >= mCorpusGroups.size())) return null;
-                return mCorpusGroups.get(pos);
-            }
-        }
-
-        private int promotedCount() {
-            SuggestionCursor promoted = getCurrentPromotedSuggestions();
-            return (promoted == null ? 0 : promoted.getCount());
-        }
-
-        private int promotedGroupCount() {
-            return (promotedCount() == 0) ? 0 : 1;
-        }
-
-        private int corpusGroupCount() {
-            return mCorpusGroups == null ? 0 : mCorpusGroups.size();
-        }
-
-        @Override
-        public int getGroupCount() {
-            return promotedGroupCount() + corpusGroupCount();
-        }
-
-        @Override
-        public long getGroupId(int groupPosition) {
-            return groupPosition;
-        }
-
-        @Override
-        public View getGroupView(
-                int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
-            if (convertView == null) {
-                convertView = mInflater.inflate(R.layout.suggestion_group, parent, false);
-            }
-            if (groupPosition == 0) {
-                // don't show the group separator for the first group, to avoid seeing an empty
-                // gap at the top of the list.
-                convertView.getLayoutParams().height = 0;
-            } else {
-                convertView.getLayoutParams().height = mContext.getResources().
-                        getDimensionPixelSize(R.dimen.suggestion_group_spacing);
-            }
-            // since we've fiddled with the layout params:
-            convertView.requestLayout();
-            return convertView;
-        }
-
-        @Override
-        public boolean hasStableIds() {
-            return false;
-        }
-
-        @Override
-        public boolean isChildSelectable(int groupPosition, int childPosition) {
-            return true;
-        }
-
-        @Override
-        public int getChildType(int groupPosition, int childPosition) {
-            return getSuggestionViewType(getGroup(groupPosition), childPosition);
-        }
-
-        @Override
-        public int getChildTypeCount() {
-            return getSuggestionViewTypeCount();
-        }
-    }
-
-}
diff --git a/src/com/android/quicksearchbox/ui/ContactSuggestionView.java b/src/com/android/quicksearchbox/ui/ContactSuggestionView.java
deleted file mode 100644
index 7290e6b..0000000
--- a/src/com/android/quicksearchbox/ui/ContactSuggestionView.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2009 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.quicksearchbox.ui;
-
-import com.android.quicksearchbox.R;
-import com.android.quicksearchbox.SearchableSource;
-import com.android.quicksearchbox.Source;
-import com.android.quicksearchbox.Suggestion;
-
-import android.app.SearchableInfo;
-import android.content.Context;
-import android.net.Uri;
-import android.provider.ContactsContract;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.view.View;
-
-/**
- * View for contacts appearing in the suggestions list.
- */
-public class ContactSuggestionView extends DefaultSuggestionView {
-
-    private static final String VIEW_ID = "contact";
-
-    private ContactBadge mQuickContact;
-
-    public ContactSuggestionView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-    }
-
-    public ContactSuggestionView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public ContactSuggestionView(Context context) {
-        super(context);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mQuickContact = (ContactBadge) findViewById(R.id.icon1);
-    }
-
-    @Override
-    public void bindAsSuggestion(Suggestion suggestion, String userQuery) {
-        super.bindAsSuggestion(suggestion, userQuery);
-        mQuickContact.assignContactUri(Uri.parse(suggestion.getSuggestionIntentDataString()));
-        mQuickContact.setExtraOnClickListener(new ContactBadgeClickListener());
-    }
-
-    private class ContactBadgeClickListener implements View.OnClickListener {
-        public void onClick(View v) {
-            onSuggestionQuickContactClicked();
-        }
-    }
-
-    public static class Factory extends SuggestionViewInflater {
-        public Factory(Context context) {
-            super(VIEW_ID, ContactSuggestionView.class, R.layout.contact_suggestion, context);
-        }
-
-        @Override
-        public boolean canCreateView(Suggestion suggestion) {
-            Source source = suggestion.getSuggestionSource();
-            if (source instanceof SearchableSource) {
-                SearchableSource searchableSource = (SearchableSource) source;
-                return isSearchableContacts(searchableSource.getSearchableInfo());
-            }
-            return false;
-        }
-
-        protected boolean isSearchableContacts(SearchableInfo searchable) {
-            return TextUtils.equals(ContactsContract.AUTHORITY, searchable.getSuggestAuthority());
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/quicksearchbox/ui/CorporaAdapter.java b/src/com/android/quicksearchbox/ui/CorporaAdapter.java
deleted file mode 100644
index f7612c1..0000000
--- a/src/com/android/quicksearchbox/ui/CorporaAdapter.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2009 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.quicksearchbox.ui;
-
-import com.android.quicksearchbox.Corpora;
-import com.android.quicksearchbox.Corpus;
-import com.android.quicksearchbox.R;
-
-import android.content.Context;
-import android.database.DataSetObserver;
-import android.graphics.drawable.Drawable;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-/**
- * Adapter for showing a list of sources in the source selection activity.
- */
-public class CorporaAdapter extends BaseAdapter {
-
-    private static final String TAG = "CorporaAdapter";
-    private static final boolean DBG = false;
-
-    private final Context mContext;
-
-    private final Corpora mCorpora;
-
-    private final int mCorpusViewRes;
-
-    private final DataSetObserver mCorporaObserver = new CorporaObserver();
-
-    private List<Corpus> mSortedCorpora;
-
-    private String mCurrentCorpusName;
-
-    public CorporaAdapter(Context context, Corpora corpora, int corpusViewRes) {
-        mContext = context;
-        mCorpora = corpora;
-        mCorpusViewRes = corpusViewRes;
-        mCorpora.registerDataSetObserver(mCorporaObserver);
-        updateCorpora();
-    }
-
-    public void setCurrentCorpus(Corpus corpus) {
-        mCurrentCorpusName = corpus == null ? null : corpus.getName();
-        notifyDataSetChanged();
-    }
-
-    private void updateCorpora() {
-        List<Corpus> enabledCorpora = mCorpora.getEnabledCorpora();
-        ArrayList<Corpus> sorted = new ArrayList<Corpus>(enabledCorpora.size());
-        for (Corpus corpus : enabledCorpora) {
-            if (!corpus.isCorpusHidden()) {
-                sorted.add(corpus);
-            }
-        }
-        Collections.sort(sorted, new CorpusComparator());
-        mSortedCorpora = sorted;
-        notifyDataSetChanged();
-    }
-
-    private static class CorpusComparator implements Comparator<Corpus> {
-        public int compare(Corpus corpus1, Corpus corpus2) {
-            // Comparing a corpus against itself
-            if (corpus1 == corpus2) return 0;
-            // Web always comes first
-            if (corpus1.isWebCorpus()) return -1;
-            if (corpus2.isWebCorpus()) return 1;
-            // Alphabetically by name
-            return corpus1.getLabel().toString().compareTo(corpus2.getLabel().toString());
-        }
-    }
-
-    public void close() {
-        mCorpora.unregisterDataSetObserver(mCorporaObserver);
-    }
-
-    public int getCount() {
-        return 1 + (mSortedCorpora == null ? 0 : mSortedCorpora.size());
-    }
-
-    public Corpus getItem(int position) {
-        if (position == 0) {
-            return null;
-        } else {
-            return mSortedCorpora.get(position - 1);
-        }
-    }
-
-    public long getItemId(int position) {
-        return position;
-    }
-
-    /**
-     * Gets the position of the given corpus.
-     */
-    public int getCorpusPosition(Corpus corpus) {
-        if (corpus == null) {
-            return 0;
-        }
-        int count = getCount();
-        for (int i = 0; i < count; i++) {
-            if (corpus.equals(getItem(i))) {
-                return i;
-            }
-        }
-        Log.w(TAG, "Corpus not in adapter: " + corpus);
-        return 0;
-    }
-
-    public View getView(int position, View convertView, ViewGroup parent) {
-        CorpusView view = (CorpusView) convertView;
-        if (view == null) {
-            view = createView(parent);
-        }
-        Corpus corpus = getItem(position);
-        if (DBG) Log.d(TAG, "Binding " + position + ", corpus=" + corpus);
-        bindView(view, corpus);
-        return view;
-    }
-
-    protected void bindView(CorpusView view, Corpus corpus) {
-        Drawable icon = getCorpusIcon(corpus);
-        CharSequence label = getCorpusLabel(corpus);
-        boolean isCurrent = isCurrentCorpus(corpus);
-        if (DBG) Log.d(TAG, "bind:name=" + corpus + ",label=" + label + ",current=" + isCurrent);
-        view.setIcon(icon);
-        view.setLabel(label);
-        view.setChecked(isCurrent);
-    }
-
-    protected Drawable getCorpusIcon(Corpus corpus) {
-        if (corpus == null) {
-            return mContext.getResources().getDrawable(R.mipmap.search_app_icon);
-        } else {
-            return corpus.getCorpusIcon();
-        }
-    }
-
-    protected CharSequence getCorpusLabel(Corpus corpus) {
-        if (corpus == null) {
-            return mContext.getText(R.string.corpus_label_global);
-        } else {
-            return corpus.getLabel();
-        }
-    }
-
-    protected boolean isCurrentCorpus(Corpus corpus) {
-        if (corpus == null) {
-            return mCurrentCorpusName == null;
-        } else {
-            return corpus.getName().equals(mCurrentCorpusName);
-        }
-    }
-
-    protected CorpusView createView(ViewGroup parent) {
-        return (CorpusView) LayoutInflater.from(mContext).inflate(mCorpusViewRes, parent, false);
-    }
-
-    protected LayoutInflater getInflater() {
-        return (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-    }
-
-    private class CorporaObserver extends DataSetObserver {
-        @Override
-        public void onChanged() {
-            updateCorpora();
-        }
-
-        @Override
-        public void onInvalidated() {
-            updateCorpora();
-        }
-    }
-
-}
diff --git a/src/com/android/quicksearchbox/ui/CorpusView.java b/src/com/android/quicksearchbox/ui/CorpusView.java
index 9c731aa..23982d1 100644
--- a/src/com/android/quicksearchbox/ui/CorpusView.java
+++ b/src/com/android/quicksearchbox/ui/CorpusView.java
@@ -64,11 +64,13 @@
         mIcon.setImageDrawable(icon);
     }
 
+    @Override
     @ViewDebug.ExportedProperty
     public boolean isChecked() {
         return mChecked;
     }
 
+    @Override
     public void setChecked(boolean checked) {
         if (mChecked != checked) {
             mChecked = checked;
@@ -76,6 +78,7 @@
         }
     }
 
+    @Override
     public void toggle() {
         setChecked(!mChecked);
     }
diff --git a/src/com/android/quicksearchbox/ui/DefaultSuggestionView.java b/src/com/android/quicksearchbox/ui/DefaultSuggestionView.java
index ec0ba53..c946568 100644
--- a/src/com/android/quicksearchbox/ui/DefaultSuggestionView.java
+++ b/src/com/android/quicksearchbox/ui/DefaultSuggestionView.java
@@ -193,6 +193,7 @@
                         if (DBG) Log.d(TAG , "getIcon getting later");
                         clearDrawable();
                         icon.getLater(new Consumer<Drawable>(){
+                            @Override
                             public boolean consume(Drawable icon) {
                                 if (DBG) {
                                     Log.d(TAG, "IconConsumer.consume got id " + uniqueIconId +
diff --git a/src/com/android/quicksearchbox/ui/DefaultSuggestionViewFactory.java b/src/com/android/quicksearchbox/ui/DefaultSuggestionViewFactory.java
index 89d7b0d..ed4625f 100644
--- a/src/com/android/quicksearchbox/ui/DefaultSuggestionViewFactory.java
+++ b/src/com/android/quicksearchbox/ui/DefaultSuggestionViewFactory.java
@@ -15,13 +15,13 @@
  */
 package com.android.quicksearchbox.ui;
 
-import com.android.quicksearchbox.Suggestion;
-import com.android.quicksearchbox.SuggestionCursor;
-
 import android.content.Context;
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.quicksearchbox.Suggestion;
+import com.android.quicksearchbox.SuggestionCursor;
+
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.LinkedList;
@@ -39,7 +39,6 @@
     public DefaultSuggestionViewFactory(Context context) {
         mDefaultFactory = new DefaultSuggestionView.Factory(context);
         addFactory(new WebSearchSuggestionView.Factory(context));
-        addFactory(new ContactSuggestionView.Factory(context));
     }
 
     /**
@@ -49,6 +48,7 @@
         mFactories.addFirst(factory);
     }
 
+    @Override
     public Collection<String> getSuggestionViewTypes() {
         if (mViewTypes == null) {
             mViewTypes = new HashSet<String>();
@@ -60,6 +60,7 @@
         return mViewTypes;
     }
 
+    @Override
     public View getView(SuggestionCursor suggestion, String userQuery,
             View convertView, ViewGroup parent) {
         for (SuggestionViewFactory factory : mFactories) {
@@ -70,6 +71,7 @@
         return mDefaultFactory.getView(suggestion, userQuery, convertView, parent);
     }
 
+    @Override
     public String getViewType(Suggestion suggestion) {
         for (SuggestionViewFactory factory : mFactories) {
             if (factory.canCreateView(suggestion)) {
diff --git a/src/com/android/quicksearchbox/ui/DelayingSuggestionsAdapter.java b/src/com/android/quicksearchbox/ui/DelayingSuggestionsAdapter.java
index 365520c..6b7d47e 100644
--- a/src/com/android/quicksearchbox/ui/DelayingSuggestionsAdapter.java
+++ b/src/com/android/quicksearchbox/ui/DelayingSuggestionsAdapter.java
@@ -16,8 +16,6 @@
 
 package com.android.quicksearchbox.ui;
 
-import com.android.quicksearchbox.CorpusResult;
-import com.android.quicksearchbox.Promoter;
 import com.android.quicksearchbox.SuggestionCursor;
 import com.android.quicksearchbox.SuggestionPosition;
 import com.android.quicksearchbox.Suggestions;
@@ -73,16 +71,9 @@
      */
     private boolean shouldPublish(Suggestions suggestions) {
         if (suggestions.isDone()) return true;
-        SuggestionCursor cursor = mDelayedAdapter.getPromoted(suggestions);
+        SuggestionCursor cursor = suggestions.getResult();
         if (cursor != null && cursor.getCount() > 0) {
             return true;
-        } else if (mDelayedAdapter.willPublishNonPromotedSuggestions()) {
-            Iterable<CorpusResult> results = suggestions.getCorpusResults();
-            for (CorpusResult result : results) {
-                if (result.getCount() > 0) {
-                    return true;
-                }
-            }
         }
         return false;
     }
@@ -134,51 +125,41 @@
         }
     }
 
+    @Override
     public A getListAdapter() {
         return mDelayedAdapter.getListAdapter();
     }
 
     public SuggestionCursor getCurrentPromotedSuggestions() {
-        return mDelayedAdapter.getCurrentPromotedSuggestions();
+        return mDelayedAdapter.getCurrentSuggestions();
     }
 
+    @Override
     public Suggestions getSuggestions() {
         return mDelayedAdapter.getSuggestions();
     }
 
+    @Override
     public SuggestionPosition getSuggestion(long suggestionId) {
         return mDelayedAdapter.getSuggestion(suggestionId);
     }
 
+    @Override
     public void onSuggestionClicked(long suggestionId) {
         mDelayedAdapter.onSuggestionClicked(suggestionId);
     }
 
+    @Override
     public void onSuggestionQueryRefineClicked(long suggestionId) {
         mDelayedAdapter.onSuggestionQueryRefineClicked(suggestionId);
     }
 
-    public void onSuggestionQuickContactClicked(long suggestionId) {
-        mDelayedAdapter.onSuggestionQuickContactClicked(suggestionId);
-    }
-
-    public void onSuggestionRemoveFromHistoryClicked(long suggestionId) {
-        mDelayedAdapter.onSuggestionRemoveFromHistoryClicked(suggestionId);
-    }
-
-    public void setMaxPromoted(int maxPromoted) {
-        mDelayedAdapter.setMaxPromoted(maxPromoted);
-    }
-
+    @Override
     public void setOnFocusChangeListener(OnFocusChangeListener l) {
         mDelayedAdapter.setOnFocusChangeListener(l);
     }
 
     @Override
-    public void setPromoter(Promoter promoter) {
-        mDelayedAdapter.setPromoter(promoter);
-    }
-
     public void setSuggestionClickListener(SuggestionClickListener listener) {
         mDelayedAdapter.setSuggestionClickListener(listener);
     }
diff --git a/src/com/android/quicksearchbox/ui/SearchActivityView.java b/src/com/android/quicksearchbox/ui/SearchActivityView.java
index f93716e..6060e4f 100644
--- a/src/com/android/quicksearchbox/ui/SearchActivityView.java
+++ b/src/com/android/quicksearchbox/ui/SearchActivityView.java
@@ -16,18 +16,6 @@
 
 package com.android.quicksearchbox.ui;
 
-import com.android.quicksearchbox.Corpora;
-import com.android.quicksearchbox.Corpus;
-import com.android.quicksearchbox.CorpusResult;
-import com.android.quicksearchbox.Logger;
-import com.android.quicksearchbox.Promoter;
-import com.android.quicksearchbox.QsbApplication;
-import com.android.quicksearchbox.R;
-import com.android.quicksearchbox.SearchActivity;
-import com.android.quicksearchbox.SuggestionCursor;
-import com.android.quicksearchbox.Suggestions;
-import com.android.quicksearchbox.VoiceSearch;
-
 import android.content.Context;
 import android.database.DataSetObserver;
 import android.graphics.drawable.Drawable;
@@ -47,6 +35,15 @@
 import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
 
+import com.android.quicksearchbox.Logger;
+import com.android.quicksearchbox.QsbApplication;
+import com.android.quicksearchbox.R;
+import com.android.quicksearchbox.SearchActivity;
+import com.android.quicksearchbox.SourceResult;
+import com.android.quicksearchbox.SuggestionCursor;
+import com.android.quicksearchbox.Suggestions;
+import com.android.quicksearchbox.VoiceSearch;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 
@@ -59,8 +56,6 @@
     // TODO: This should move to android-common or something.
     private static final String IME_OPTION_NO_MICROPHONE = "nm";
 
-    private Corpus mCorpus;
-
     protected QueryTextView mQueryTextView;
     // True if the query was empty on the previous call to updateQuery()
     protected boolean mQueryWasEmpty = true;
@@ -70,7 +65,6 @@
     protected SuggestionsListView<ListAdapter> mSuggestionsView;
     protected SuggestionsAdapter<ListAdapter> mSuggestionsAdapter;
 
-    protected ImageButton mSearchCloseButton;
     protected ImageButton mSearchGoButton;
     protected ImageButton mVoiceSearchButton;
 
@@ -108,7 +102,6 @@
         // suggestions?
         mSuggestionsAdapter.setOnFocusChangeListener(new SuggestListFocusListener());
 
-        mSearchCloseButton = (ImageButton) findViewById(R.id.search_close_btn);
         mSearchGoButton = (ImageButton) findViewById(R.id.search_go_btn);
         mVoiceSearchButton = (ImageButton) findViewById(R.id.search_voice_btn);
         mVoiceSearchButton.setImageDrawable(getVoiceSearchIcon());
@@ -123,10 +116,6 @@
         mButtonsKeyListener = new ButtonsKeyListener();
         mSearchGoButton.setOnKeyListener(mButtonsKeyListener);
         mVoiceSearchButton.setOnKeyListener(mButtonsKeyListener);
-        if (mSearchCloseButton != null) {
-            mSearchCloseButton.setOnKeyListener(mButtonsKeyListener);
-            mSearchCloseButton.setOnClickListener(new CloseClickListener());
-        }
 
         mUpdateSuggestions = true;
     }
@@ -167,72 +156,6 @@
                 getQsbApplication().getSuggestionViewFactory()));
     }
 
-    protected Corpora getCorpora() {
-        return getQsbApplication().getCorpora();
-    }
-
-    public Corpus getCorpus() {
-        return mCorpus;
-    }
-
-    protected abstract Promoter createSuggestionsPromoter();
-
-    protected Corpus getCorpus(String sourceName) {
-        if (sourceName == null) return null;
-        Corpus corpus = getCorpora().getCorpus(sourceName);
-        if (corpus == null) {
-            Log.w(TAG, "Unknown corpus " + sourceName);
-            return null;
-        }
-        return corpus;
-    }
-
-    public void onCorpusSelected(String corpusName) {
-        setCorpus(corpusName);
-        focusQueryTextView();
-        showInputMethodForQuery();
-    }
-
-    public void setCorpus(String corpusName) {
-        if (DBG) Log.d(TAG, "setCorpus(" + corpusName + ")");
-        Corpus corpus = getCorpus(corpusName);
-        setCorpus(corpus);
-        updateUi();
-    }
-
-    protected void setCorpus(Corpus corpus) {
-        mCorpus = corpus;
-        mSuggestionsAdapter.setPromoter(createSuggestionsPromoter());
-        Suggestions suggestions = getSuggestions();
-        if (corpus == null || suggestions == null || !suggestions.expectsCorpus(corpus)) {
-            getActivity().updateSuggestions();
-        }
-    }
-
-    public String getCorpusName() {
-        Corpus corpus = getCorpus();
-        return corpus == null ? null : corpus.getName();
-    }
-
-    public abstract Corpus getSearchCorpus();
-
-    public Corpus getWebCorpus() {
-        Corpus webCorpus = getCorpora().getWebCorpus();
-        if (webCorpus == null) {
-            Log.e(TAG, "No web corpus");
-        }
-        return webCorpus;
-    }
-
-    public void setMaxPromotedSuggestions(int maxPromoted) {
-        mSuggestionsView.setLimitSuggestionsToViewHeight(false);
-        mSuggestionsAdapter.setMaxPromoted(maxPromoted);
-    }
-
-    public void limitSuggestionsToViewHeight() {
-        mSuggestionsView.setLimitSuggestionsToViewHeight(true);
-    }
-
     public void setMaxPromotedResults(int maxPromoted) {
     }
 
@@ -247,8 +170,6 @@
         mSearchClickListener = listener;
     }
 
-    public abstract void showCorpusSelectionDialog();
-
     public void setVoiceSearchButtonClickListener(View.OnClickListener listener) {
         if (mVoiceSearchButton != null) {
             mVoiceSearchButton.setOnClickListener(listener);
@@ -273,8 +194,8 @@
         return mSuggestionsAdapter.getSuggestions();
     }
 
-    public SuggestionCursor getCurrentPromotedSuggestions() {
-        return mSuggestionsAdapter.getCurrentPromotedSuggestions();
+    public SuggestionCursor getCurrentSuggestions() {
+        return mSuggestionsAdapter.getSuggestions().getResult();
     }
 
     public void setSuggestions(Suggestions suggestions) {
@@ -338,18 +259,8 @@
 
     protected void updateQueryTextView(boolean queryEmpty) {
         if (queryEmpty) {
-            if (isSearchCorpusWeb()) {
-                mQueryTextView.setBackgroundDrawable(mQueryTextEmptyBg);
-                mQueryTextView.setHint(null);
-            } else {
-                if (mQueryTextNotEmptyBg == null) {
-                    mQueryTextNotEmptyBg =
-                            getResources().getDrawable(R.drawable.textfield_search_empty);
-                }
-                mQueryTextView.setBackgroundDrawable(mQueryTextNotEmptyBg);
-                Corpus corpus = getCorpus();
-                mQueryTextView.setHint(corpus == null ? "" : corpus.getHint());
-            }
+            mQueryTextView.setBackgroundDrawable(mQueryTextEmptyBg);
+            mQueryTextView.setHint(null);
         } else {
             mQueryTextView.setBackgroundResource(R.drawable.textfield_search);
         }
@@ -365,7 +276,7 @@
 
     protected void updateVoiceSearchButton(boolean queryEmpty) {
         if (shouldShowVoiceSearch(queryEmpty)
-                && getVoiceSearch().shouldShowVoiceSearch(getCorpus())) {
+                && getVoiceSearch().shouldShowVoiceSearch()) {
             mVoiceSearchButton.setVisibility(View.VISIBLE);
             mQueryTextView.setPrivateImeOptions(IME_OPTION_NO_MICROPHONE);
         } else {
@@ -436,18 +347,14 @@
     }
 
     private CompletionInfo[] webSuggestionsToCompletions(Suggestions suggestions) {
-        // TODO: This should also include include web search shortcuts
-        CorpusResult cursor = suggestions.getWebResult();
+        SourceResult cursor = suggestions.getWebResult();
         if (cursor == null) return null;
         int count = cursor.getCount();
         ArrayList<CompletionInfo> completions = new ArrayList<CompletionInfo>(count);
-        boolean usingWebCorpus = isSearchCorpusWeb();
         for (int i = 0; i < count; i++) {
             cursor.moveTo(i);
-            if (!usingWebCorpus || cursor.isWebSearchSuggestion()) {
-                String text1 = cursor.getSuggestionText1();
-                completions.add(new CompletionInfo(i, i, text1));
-            }
+            String text1 = cursor.getSuggestionText1();
+            completions.add(new CompletionInfo(i, i, text1));
         }
         return completions.toArray(new CompletionInfo[completions.size()]);
     }
@@ -456,14 +363,6 @@
         updateInputMethodSuggestions();
     }
 
-    /**
-     * Checks if the corpus used for typed searches is the web corpus.
-     */
-    protected boolean isSearchCorpusWeb() {
-        Corpus corpus = getSearchCorpus();
-        return corpus != null && corpus.isWebCorpus();
-    }
-
     protected boolean onSuggestionKeyDown(SuggestionsAdapter<?> adapter,
             long suggestionId, int keyCode, KeyEvent event) {
         // Treat enter or search as a click
@@ -492,6 +391,7 @@
      * Filters the suggestions list when the search text changes.
      */
     private class SearchTextWatcher implements TextWatcher {
+        @Override
         public void afterTextChanged(Editable s) {
             boolean empty = s.length() == 0;
             if (empty != mQueryWasEmpty) {
@@ -505,9 +405,11 @@
             }
         }
 
+        @Override
         public void beforeTextChanged(CharSequence s, int start, int count, int after) {
         }
 
+        @Override
         public void onTextChanged(CharSequence s, int start, int before, int count) {
         }
     }
@@ -516,6 +418,7 @@
      * Handles key events on the suggestions list view.
      */
     protected class SuggestionsViewKeyListener implements View.OnKeyListener {
+        @Override
         public boolean onKey(View v, int keyCode, KeyEvent event) {
             if (event.getAction() == KeyEvent.ACTION_DOWN
                     && v instanceof SuggestionsListView<?>) {
@@ -531,10 +434,12 @@
 
     private class InputMethodCloser implements SuggestionsView.OnScrollListener {
 
+        @Override
         public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
                 int totalItemCount) {
         }
 
+        @Override
         public void onScrollStateChanged(AbsListView view, int scrollState) {
             considerHidingInputMethod();
         }
@@ -544,6 +449,7 @@
      * Listens for clicks on the source selector.
      */
     private class SearchGoButtonClickListener implements View.OnClickListener {
+        @Override
         public void onClick(View view) {
             onSearchClicked(Logger.SEARCH_METHOD_BUTTON);
         }
@@ -553,6 +459,7 @@
      * This class handles enter key presses in the query text view.
      */
     private class QueryTextEditorActionListener implements OnEditorActionListener {
+        @Override
         public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
             boolean consumed = false;
             if (event != null) {
@@ -573,6 +480,7 @@
      * by refocusing to EditText.
      */
     private class ButtonsKeyListener implements View.OnKeyListener {
+        @Override
         public boolean onKey(View v, int keyCode, KeyEvent event) {
             return forwardKeyToQueryTextView(keyCode, event);
         }
@@ -607,6 +515,7 @@
      * Hides the input method when the suggestions get focus.
      */
     private class SuggestListFocusListener implements OnFocusChangeListener {
+        @Override
         public void onFocusChange(View v, boolean focused) {
             if (DBG) Log.d(TAG, "Suggestions focus change, now: " + focused);
             if (focused) {
@@ -616,6 +525,7 @@
     }
 
     private class QueryTextViewFocusListener implements OnFocusChangeListener {
+        @Override
         public void onFocusChange(View v, boolean focused) {
             if (DBG) Log.d(TAG, "Query focus change, now: " + focused);
             if (focused) {
@@ -641,6 +551,7 @@
     }
 
     private class CloseClickListener implements OnClickListener {
+        @Override
         public void onClick(View v) {
             if (!isQueryEmpty()) {
                 mQueryTextView.setText("");
diff --git a/src/com/android/quicksearchbox/ui/SearchActivityViewSinglePane.java b/src/com/android/quicksearchbox/ui/SearchActivityViewSinglePane.java
index 14f173d..9288fb6 100644
--- a/src/com/android/quicksearchbox/ui/SearchActivityViewSinglePane.java
+++ b/src/com/android/quicksearchbox/ui/SearchActivityViewSinglePane.java
@@ -16,10 +16,8 @@
 
 package com.android.quicksearchbox.ui;
 
-import com.android.quicksearchbox.Corpus;
-import com.android.quicksearchbox.CorpusSelectionDialog;
-import com.android.quicksearchbox.Promoter;
 import com.android.quicksearchbox.R;
+import com.android.quicksearchbox.Source;
 
 import android.content.Context;
 import android.graphics.drawable.Drawable;
@@ -32,10 +30,6 @@
  */
 public class SearchActivityViewSinglePane extends SearchActivityView {
 
-    private CorpusSelectionDialog mCorpusSelectionDialog;
-
-    private ImageButton mCorpusIndicator;
-
     public SearchActivityViewSinglePane(Context context) {
         super(context);
     }
@@ -49,80 +43,8 @@
     }
 
     @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mCorpusIndicator = (ImageButton) findViewById(R.id.corpus_indicator);
-        mCorpusIndicator.setOnKeyListener(mButtonsKeyListener);
-        mCorpusIndicator.setOnClickListener(new View.OnClickListener(){
-            public void onClick(View v) {
-                showCorpusSelectionDialog();
-            }});
-    }
-
-    @Override
     public void onResume() {
-        if (!isCorpusSelectionDialogShowing()) {
-            focusQueryTextView();
-        }
-    }
-
-    @Override
-    public void onStop() {
-        dismissCorpusSelectionDialog();
-    }
-
-    @Override
-    protected void setCorpus(Corpus corpus) {
-        super.setCorpus(corpus);
-
-        if (mCorpusIndicator != null) {
-            Drawable sourceIcon;
-            if (corpus == null) {
-                sourceIcon = getContext().getResources().getDrawable(R.mipmap.search_app_icon);
-            } else {
-                sourceIcon = corpus.getCorpusIcon();
-            }
-            mCorpusIndicator.setImageDrawable(sourceIcon);
-        }
-    }
-
-    @Override
-    protected Promoter createSuggestionsPromoter() {
-        Corpus corpus = getCorpus();
-        if (corpus == null) {
-            return getQsbApplication().createBlendingPromoter();
-        } else {
-            return getQsbApplication().createSingleCorpusPromoter(corpus);
-        }
-    }
-
-    /**
-     * Gets the corpus to use for any searches. This is the web corpus in "All" mode,
-     * and the selected corpus otherwise.
-     */
-    @Override
-    public Corpus getSearchCorpus() {
-        Corpus corpus = getCorpus();
-        return corpus == null ? getWebCorpus() : corpus;
-    }
-
-    @Override
-    public void showCorpusSelectionDialog() {
-        if (mCorpusSelectionDialog == null) {
-            mCorpusSelectionDialog = getActivity().getCorpusSelectionDialog();
-            mCorpusSelectionDialog.setOnCorpusSelectedListener(new CorpusSelectionListener());
-        }
-        mCorpusSelectionDialog.show(getCorpus());
-    }
-
-    protected boolean isCorpusSelectionDialogShowing() {
-        return mCorpusSelectionDialog != null && mCorpusSelectionDialog.isShowing();
-    }
-
-    protected void dismissCorpusSelectionDialog() {
-        if (mCorpusSelectionDialog != null) {
-            mCorpusSelectionDialog.dismiss();
-        }
+        focusQueryTextView();
     }
 
     @Override
@@ -130,11 +52,8 @@
         mQueryTextView.hideInputMethod();
     }
 
-    private class CorpusSelectionListener
-            implements CorpusSelectionDialog.OnCorpusSelectedListener {
-        public void onCorpusSelected(String corpusName) {
-            SearchActivityViewSinglePane.this.onCorpusSelected(corpusName);
-        }
+    @Override
+    public void onStop() {
     }
 
 }
diff --git a/src/com/android/quicksearchbox/ui/SearchActivityViewTwoPane.java b/src/com/android/quicksearchbox/ui/SearchActivityViewTwoPane.java
deleted file mode 100644
index 9112445..0000000
--- a/src/com/android/quicksearchbox/ui/SearchActivityViewTwoPane.java
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox.ui;
-
-import com.android.quicksearchbox.Corpus;
-import com.android.quicksearchbox.Promoter;
-import com.android.quicksearchbox.R;
-import com.android.quicksearchbox.Suggestions;
-
-import android.animation.Animator;
-import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
-import android.database.DataSetObserver;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.Menu;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ExpandableListAdapter;
-import android.widget.ImageView;
-import android.widget.PopupMenu;
-
-/**
- * Two-pane variant for the search activity view.
- */
-public class SearchActivityViewTwoPane extends SearchActivityView {
-
-    private static final int ENTRY_ANIMATION_START_DELAY = 150; // in millis
-    private static final int ENTRY_ANIMATION_DURATION = 150; // in millis
-    private static final float ANIMATION_STARTING_WIDTH_FACTOR = 0.5f;
-    private static final String TOOLBAR_ICON_METADATA_NAME = "com.android.launcher.toolbar_icon";
-
-    private ImageView mMenuButton;
-
-    // View that shows the results other than the query completions
-    private ClusteredSuggestionsView mResultsView;
-    private SuggestionsAdapter<ExpandableListAdapter> mResultsAdapter;
-    private View mResultsHeader;
-    private View mSearchPlate;
-    private boolean mJustCreated;
-
-    public SearchActivityViewTwoPane(Context context) {
-        super(context);
-    }
-
-    public SearchActivityViewTwoPane(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public SearchActivityViewTwoPane(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-
-        mMenuButton = (ImageView) findViewById(R.id.menu_button);
-        mMenuButton.setOnClickListener(new View.OnClickListener() {
-            public void onClick(View v) {
-                showPopupMenu();
-            }
-        });
-
-        mResultsView = (ClusteredSuggestionsView) findViewById(R.id.shortcuts);
-        mResultsAdapter = createClusteredSuggestionsAdapter();
-        mResultsAdapter.getListAdapter().registerDataSetObserver(new DataSetObserver(){
-            @Override
-            public void onChanged() {
-                mResultsView.expandAll();
-            }
-        });
-        mResultsView.setOnKeyListener(new SuggestionsViewKeyListener());
-        mResultsView.setFocusable(true);
-        mResultsHeader = findViewById(R.id.shortcut_title);
-        mSearchPlate = findViewById(R.id.left_pane);
-        mJustCreated = true;
-
-        View dismissBg = findViewById(R.id.dismiss_bg);
-        dismissBg.setOnClickListener(new View.OnClickListener() {
-            public void onClick(View v) {
-                if (isQueryEmpty() && mExitClickListener != null) {
-                    mExitClickListener.onClick(v);
-                }
-            }
-        });
-    }
-
-    private void showPopupMenu() {
-        PopupMenu popup = new PopupMenu(getContext(), mMenuButton);
-        Menu menu = popup.getMenu();
-        getActivity().createMenuItems(menu, false);
-        popup.show();
-    }
-
-    protected SuggestionsAdapter<ExpandableListAdapter> createClusteredSuggestionsAdapter() {
-        return new DelayingSuggestionsAdapter<ExpandableListAdapter>(
-                new ClusteredSuggestionsAdapter(
-                        getQsbApplication().getSuggestionViewFactory(),
-                        getContext()));
-    }
-
-    @Override
-    public void onResume() {
-        if (mJustCreated) {
-            setupEntryAnimations();
-            mJustCreated = false;
-        }
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
-        getActivity().overridePendingTransition(R.anim.fade_in_fast, R.anim.fade_out_fast);
-    }
-
-    private void setupEntryAnimations() {
-        // TODO: Use the left/top of the source bounds to start the animation from
-        final int endingWidth = getResources().getDimensionPixelSize(R.dimen.suggestions_width);
-        final int startingWidth = (int) (endingWidth * ANIMATION_STARTING_WIDTH_FACTOR);
-
-        ViewGroup.LayoutParams params = mSearchPlate.getLayoutParams();
-        params.width = startingWidth;
-        mSearchPlate.setLayoutParams(params);
-
-        Animator animator = ObjectAnimator.ofInt(mSearchPlate, "alpha", 0, 255);
-        animator.setDuration(ENTRY_ANIMATION_DURATION);
-        ((ValueAnimator)animator).addUpdateListener(new AnimatorUpdateListener() {
-
-            public void onAnimationUpdate(ValueAnimator animator) {
-                ViewGroup.LayoutParams params = mSearchPlate.getLayoutParams();
-                params.width = startingWidth
-                        + (int) ((Integer) animator.getAnimatedValue() / 255f
-                                * (endingWidth - startingWidth));
-                mSearchPlate.setLayoutParams(params);
-            }
-        });
-        animator.setStartDelay(ENTRY_ANIMATION_START_DELAY);
-        animator.start();
-
-    }
-
-    @Override
-    public void onStop() {
-    }
-
-    @Override
-    public void start() {
-        super.start();
-        mResultsAdapter.getListAdapter().registerDataSetObserver(new ResultsObserver());
-        mResultsView.setSuggestionsAdapter(mResultsAdapter);
-    }
-
-    @Override
-    public void destroy() {
-        mResultsView.setSuggestionsAdapter(null);
-
-        super.destroy();
-    }
-
-    @Override
-    protected Drawable getVoiceSearchIcon() {
-        ComponentName voiceSearch = getVoiceSearch().getComponent();
-        if (voiceSearch != null) {
-            // this code copied from Launcher to get the same icon that's displayed on home screen
-            try {
-                PackageManager packageManager = getContext().getPackageManager();
-                // Look for the toolbar icon specified in the activity meta-data
-                Bundle metaData = packageManager.getActivityInfo(
-                        voiceSearch, PackageManager.GET_META_DATA).metaData;
-                if (metaData != null) {
-                    int iconResId = metaData.getInt(TOOLBAR_ICON_METADATA_NAME);
-                    if (iconResId != 0) {
-                        Resources res = packageManager.getResourcesForActivity(voiceSearch);
-                        if (DBG) Log.d(TAG, "Got toolbar icon from Voice Search");
-                        return res.getDrawable(iconResId);
-                    }
-                }
-            } catch (NameNotFoundException e) {
-                // Do nothing
-            }
-        }
-        if (DBG) Log.d(TAG, "Failed to get toolbar icon from Voice Search; using default.");
-        return super.getVoiceSearchIcon();
-    }
-
-    @Override
-    public void considerHidingInputMethod() {
-        // Don't hide keyboard when interacting with suggestions list
-    }
-
-    @Override
-    public void hideSuggestions() {
-        // Never hiding suggestions view in two-pane UI
-    }
-
-    @Override
-    public void showSuggestions() {
-        // Never hiding suggestions view in two-pane UI
-    }
-
-    @Override
-    public void showCorpusSelectionDialog() {
-        // not used
-    }
-
-    @Override
-    public void clearSuggestions() {
-        super.clearSuggestions();
-        mResultsAdapter.setSuggestions(null);
-    }
-
-    @Override
-    public void setMaxPromotedResults(int maxPromoted) {
-        mResultsView.setLimitSuggestionsToViewHeight(false);
-        mResultsAdapter.setMaxPromoted(maxPromoted);
-    }
-
-    @Override
-    public void limitResultsToViewHeight() {
-        mResultsView.setLimitSuggestionsToViewHeight(true);
-    }
-
-    @Override
-    public void setSuggestionClickListener(SuggestionClickListener listener) {
-        super.setSuggestionClickListener(listener);
-        mResultsAdapter.setSuggestionClickListener(listener);
-    }
-
-    @Override
-    public void setSuggestions(Suggestions suggestions) {
-        super.setSuggestions(suggestions);
-        suggestions.acquire();
-        mResultsAdapter.setSuggestions(suggestions);
-    }
-
-    @Override
-    protected void setCorpus(Corpus corpus) {
-        super.setCorpus(corpus);
-        mResultsAdapter.setPromoter(createResultsPromoter());
-    }
-
-    @Override
-    protected Promoter createSuggestionsPromoter() {
-        return getQsbApplication().createWebPromoter();
-    }
-
-    protected Promoter createResultsPromoter() {
-        Corpus corpus = getCorpus();
-        if (corpus == null) {
-            return getQsbApplication().createResultsPromoter();
-        } else {
-            return getQsbApplication().createSingleCorpusResultsPromoter(corpus);
-        }
-    }
-
-    protected void onResultsChanged() {
-        checkHideResultsHeader();
-    }
-
-    @Override
-    protected void updateQueryTextView(boolean queryEmpty) {
-        super.updateQueryTextView(queryEmpty);
-        if (mSearchCloseButton == null) return;
-
-        if (queryEmpty) {
-            mSearchCloseButton.setImageResource(R.drawable.ic_clear_disabled);
-        } else {
-            mSearchCloseButton.setImageResource(R.drawable.ic_clear);
-        }
-    }
-
-    private void checkHideResultsHeader() {
-        if (mResultsHeader != null) {
-            if (!mResultsAdapter.isEmpty()) {
-                if (DBG) Log.d(TAG, "Results non-empty");
-                mResultsHeader.setVisibility(VISIBLE);
-            } else {
-                if (DBG) Log.d(TAG, "Results empty");
-                mResultsHeader.setVisibility(INVISIBLE);
-            }
-        }
-    }
-
-    @Override
-    public Corpus getSearchCorpus() {
-        return getWebCorpus();
-    }
-
-    protected class ResultsObserver extends DataSetObserver {
-        @Override
-        public void onChanged() {
-            onResultsChanged();
-        }
-    }
-
-}
diff --git a/src/com/android/quicksearchbox/ui/SuggestionClickListener.java b/src/com/android/quicksearchbox/ui/SuggestionClickListener.java
index 128b80a..da062cd 100644
--- a/src/com/android/quicksearchbox/ui/SuggestionClickListener.java
+++ b/src/com/android/quicksearchbox/ui/SuggestionClickListener.java
@@ -31,24 +31,6 @@
     void onSuggestionClicked(SuggestionsAdapter<?> adapter, long suggestionId);
 
     /**
-     * Called when a quick contact badge in a suggestion is clicked.
-     *
-     * @param adapter Adapter that contains the clicked suggestion.
-     * @param suggestionId The ID of the suggestion clicked. If the suggestion list is flat, this
-     *      will be the position within the list.
-     */
-    void onSuggestionQuickContactClicked(SuggestionsAdapter<?> adapter, long suggestionId);
-
-    /**
-     * Called when the user requests to remove a suggestion from the search history.
-     *
-     * @param adapter Adapter that contains the clicked suggestion.
-     * @param suggestionId The ID of the suggestion clicked. If the suggestion list is flat, this
-     *      will be the position within the list.
-     */
-    void onSuggestionRemoveFromHistoryClicked(SuggestionsAdapter<?> adapter, long suggestionId);
-
-    /**
      * Called when the "query refine" button of a suggestion is clicked.
      *
      * @param adapter Adapter that contains the clicked suggestion.
diff --git a/src/com/android/quicksearchbox/ui/SuggestionsAdapter.java b/src/com/android/quicksearchbox/ui/SuggestionsAdapter.java
index cd0626a..825ae0d 100644
--- a/src/com/android/quicksearchbox/ui/SuggestionsAdapter.java
+++ b/src/com/android/quicksearchbox/ui/SuggestionsAdapter.java
@@ -15,7 +15,6 @@
  */
 package com.android.quicksearchbox.ui;
 
-import com.android.quicksearchbox.Promoter;
 import com.android.quicksearchbox.SuggestionCursor;
 import com.android.quicksearchbox.SuggestionPosition;
 import com.android.quicksearchbox.Suggestions;
@@ -33,16 +32,6 @@
 public interface SuggestionsAdapter<A> {
 
     /**
-     * Sets the maximum number of promoted suggestions to be provided by this adapter.
-     */
-    void setMaxPromoted(int maxPromoted);
-
-    /**
-     * Sets the suggestion promoter.
-     */
-    void setPromoter(Promoter promoter);
-
-    /**
      * Sets the listener to be notified of clicks on suggestions.
      */
     void setSuggestionClickListener(SuggestionClickListener listener);
@@ -74,11 +63,6 @@
     SuggestionPosition getSuggestion(long suggestionId);
 
     /**
-     * Gets the current list of promoted suggestions.
-     */
-    SuggestionCursor getCurrentPromotedSuggestions();
-
-    /**
      * Handles a regular click on a suggestion.
      *
      * @param suggestionId The ID of the suggestion clicked. If the suggestion list is flat, this
@@ -87,22 +71,6 @@
     void onSuggestionClicked(long suggestionId);
 
     /**
-     * Handles a click on a quick contact badge.
-     *
-     * @param suggestionId The ID of the suggestion clicked. If the suggestion list is flat, this
-     *      will be the position within the list.
-     */
-    void onSuggestionQuickContactClicked(long suggestionId);
-
-    /**
-     * Handles a request to remove a suggestion from history.
-     *
-     * @param suggestionId The ID of the suggestion clicked. If the suggestion list is flat, this
-     *      will be the position within the list.
-     */
-    void onSuggestionRemoveFromHistoryClicked(long suggestionId);
-
-    /**
      * Handles a click on the query refinement button.
      *
      * @param suggestionId The ID of the suggestion clicked. If the suggestion list is flat, this
diff --git a/src/com/android/quicksearchbox/ui/SuggestionsAdapterBase.java b/src/com/android/quicksearchbox/ui/SuggestionsAdapterBase.java
index 2a97ff4..244e3f9 100644
--- a/src/com/android/quicksearchbox/ui/SuggestionsAdapterBase.java
+++ b/src/com/android/quicksearchbox/ui/SuggestionsAdapterBase.java
@@ -15,7 +15,6 @@
  */
 package com.android.quicksearchbox.ui;
 
-import com.android.quicksearchbox.Promoter;
 import com.android.quicksearchbox.Suggestion;
 import com.android.quicksearchbox.SuggestionCursor;
 import com.android.quicksearchbox.SuggestionPosition;
@@ -39,11 +38,7 @@
 
     private DataSetObserver mDataSetObserver;
 
-    private Promoter mPromoter;
-
-    private int mMaxPromoted;
-
-    private SuggestionCursor mPromotedSuggestions;
+    private SuggestionCursor mCurrentSuggestions;
     private final HashMap<String, Integer> mViewTypeMap;
     private final SuggestionViewFactory mViewFactory;
 
@@ -64,19 +59,9 @@
         }
     }
 
+    @Override
     public abstract boolean isEmpty();
 
-    /**
-     * Indicates if this adapter will publish suggestions other than those in the promoted list.
-     */
-    public abstract boolean willPublishNonPromotedSuggestions();
-
-    public void setMaxPromoted(int maxPromoted) {
-        if (DBG) Log.d(TAG, "setMaxPromoted " + maxPromoted);
-        mMaxPromoted = maxPromoted;
-        onSuggestionsChanged();
-    }
-
     public boolean isClosed() {
         return mClosed;
     }
@@ -86,19 +71,17 @@
         mClosed = true;
     }
 
-    public void setPromoter(Promoter promoter) {
-        mPromoter = promoter;
-        onSuggestionsChanged();
-    }
-
+    @Override
     public void setSuggestionClickListener(SuggestionClickListener listener) {
         mSuggestionClickListener = listener;
     }
 
+    @Override
     public void setOnFocusChangeListener(OnFocusChangeListener l) {
         mOnFocusChangeListener = l;
     }
 
+    @Override
     public void setSuggestions(Suggestions suggestions) {
         if (mSuggestions == suggestions) {
             return;
@@ -124,19 +107,21 @@
         onSuggestionsChanged();
     }
 
+    @Override
     public Suggestions getSuggestions() {
         return mSuggestions;
     }
 
+    @Override
     public abstract SuggestionPosition getSuggestion(long suggestionId);
 
-    protected int getPromotedCount() {
-        return mPromotedSuggestions == null ? 0 : mPromotedSuggestions.getCount();
+    protected int getCount() {
+        return mCurrentSuggestions == null ? 0 : mCurrentSuggestions.getCount();
     }
 
-    protected SuggestionPosition getPromotedSuggestion(int position) {
-        if (mPromotedSuggestions == null) return null;
-        return new SuggestionPosition(mPromotedSuggestions, position);
+    protected SuggestionPosition getSuggestion(int position) {
+        if (mCurrentSuggestions == null) return null;
+        return new SuggestionPosition(mCurrentSuggestions, position);
     }
 
     protected int getViewTypeCount() {
@@ -182,24 +167,15 @@
 
     protected void onSuggestionsChanged() {
         if (DBG) Log.d(TAG, "onSuggestionsChanged(" + mSuggestions + ")");
-        SuggestionCursor cursor = getPromoted(mSuggestions);
-        changePromoted(cursor);
+        SuggestionCursor cursor = null;
+        if (mSuggestions != null) {
+            cursor = mSuggestions.getResult();
+        }
+        changeSuggestions(cursor);
     }
 
-    /**
-     * Gets the cursor containing the currently shown suggestions. The caller should not hold
-     * on to or modify the returned cursor.
-     */
-    public SuggestionCursor getCurrentPromotedSuggestions() {
-        return mPromotedSuggestions;
-    }
-
-    /**
-     * Gets the cursor for the given source.
-     */
-    protected SuggestionCursor getPromoted(Suggestions suggestions) {
-        if (suggestions == null) return null;
-        return suggestions.getPromoted(mPromoter, mMaxPromoted);
+    public SuggestionCursor getCurrentSuggestions() {
+        return mCurrentSuggestions;
     }
 
     /**
@@ -208,26 +184,27 @@
      * This does not close the old cursor. Instead, all the cursors are closed in
      * {@link #setSuggestions(Suggestions)}.
      */
-    private void changePromoted(SuggestionCursor newCursor) {
+    private void changeSuggestions(SuggestionCursor newCursor) {
         if (DBG) {
             Log.d(TAG, "changeCursor(" + newCursor + ") count=" +
                     (newCursor == null ? 0 : newCursor.getCount()));
         }
-        if (newCursor == mPromotedSuggestions) {
+        if (newCursor == mCurrentSuggestions) {
             if (newCursor != null) {
                 // Shortcuts may have changed without the cursor changing.
                 notifyDataSetChanged();
             }
             return;
         }
-        mPromotedSuggestions = newCursor;
-        if (mPromotedSuggestions != null) {
+        mCurrentSuggestions = newCursor;
+        if (mCurrentSuggestions != null) {
             notifyDataSetChanged();
         } else {
             notifyDataSetInvalidated();
         }
     }
 
+    @Override
     public void onSuggestionClicked(long suggestionId) {
         if (mClosed) {
             Log.w(TAG, "onSuggestionClicked after close");
@@ -236,22 +213,7 @@
         }
     }
 
-    public void onSuggestionQuickContactClicked(long suggestionId) {
-        if (mClosed) {
-            Log.w(TAG, "onSuggestionQuickContactClicked after close");
-        } else if (mSuggestionClickListener != null) {
-            mSuggestionClickListener.onSuggestionQuickContactClicked(this, suggestionId);
-        }
-    }
-
-    public void onSuggestionRemoveFromHistoryClicked(long suggestionId) {
-        if (mClosed) {
-            Log.w(TAG, "onSuggestionRemoveFromHistoryClicked after close");
-        } else if (mSuggestionClickListener != null) {
-            mSuggestionClickListener.onSuggestionRemoveFromHistoryClicked(this, suggestionId);
-        }
-    }
-
+    @Override
     public void onSuggestionQueryRefineClicked(long suggestionId) {
         if (mClosed) {
             Log.w(TAG, "onSuggestionQueryRefineClicked after close");
@@ -260,6 +222,7 @@
         }
     }
 
+    @Override
     public abstract A getListAdapter();
 
     protected abstract void notifyDataSetInvalidated();
@@ -278,6 +241,7 @@
         public SuggestionViewClickListener(long suggestionId) {
             mSuggestionId = suggestionId;
         }
+        @Override
         public void onClick(View v) {
             onSuggestionClicked(mSuggestionId);
         }
diff --git a/src/com/android/quicksearchbox/ui/SuggestionsListAdapter.java b/src/com/android/quicksearchbox/ui/SuggestionsListAdapter.java
index 5349150..8bbdfbf 100644
--- a/src/com/android/quicksearchbox/ui/SuggestionsListAdapter.java
+++ b/src/com/android/quicksearchbox/ui/SuggestionsListAdapter.java
@@ -16,14 +16,15 @@
 
 package com.android.quicksearchbox.ui;
 
-import com.android.quicksearchbox.SuggestionPosition;
-import com.android.quicksearchbox.Suggestions;
-
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
 import android.widget.ListAdapter;
 
+import com.android.quicksearchbox.SuggestionCursor;
+import com.android.quicksearchbox.SuggestionPosition;
+import com.android.quicksearchbox.Suggestions;
+
 /**
  * Uses a {@link Suggestions} object to back a {@link SuggestionsView}.
  */
@@ -42,13 +43,8 @@
     }
 
     @Override
-    public boolean willPublishNonPromotedSuggestions() {
-        return false;
-    }
-
-    @Override
     public SuggestionPosition getSuggestion(long suggestionId) {
-        return new SuggestionPosition(getCurrentPromotedSuggestions(), (int) suggestionId);
+        return new SuggestionPosition(getCurrentSuggestions(), (int) suggestionId);
     }
 
     @Override
@@ -70,12 +66,13 @@
 
         @Override
         public int getCount() {
-            return getPromotedCount();
+            SuggestionCursor s = getCurrentSuggestions();
+            return s == null ? 0 : s.getCount();
         }
 
         @Override
         public Object getItem(int position) {
-            return getPromotedSuggestion(position);
+            return getSuggestion(position);
         }
 
         @Override
@@ -86,12 +83,12 @@
         @Override
         public View getView(int position, View convertView, ViewGroup parent) {
             return SuggestionsListAdapter.this.getView(
-                    getCurrentPromotedSuggestions(), position, position, convertView, parent);
+                    getCurrentSuggestions(), position, position, convertView, parent);
         }
 
         @Override
         public int getItemViewType(int position) {
-            return getSuggestionViewType(getCurrentPromotedSuggestions(), position);
+            return getSuggestionViewType(getCurrentSuggestions(), position);
         }
 
         @Override
diff --git a/src/com/android/quicksearchbox/ui/SuggestionsListView.java b/src/com/android/quicksearchbox/ui/SuggestionsListView.java
index 6123dd2..a162f3a 100644
--- a/src/com/android/quicksearchbox/ui/SuggestionsListView.java
+++ b/src/com/android/quicksearchbox/ui/SuggestionsListView.java
@@ -58,10 +58,4 @@
      */
     long getSelectedItemId();
 
-    /**
-     * Set whether or not to limit suggestions by view height. If {@code true}, only enough
-     * suggestions to fill the view without scrolling will be shown.
-     */
-    void setLimitSuggestionsToViewHeight(boolean limit);
-
 }
diff --git a/src/com/android/quicksearchbox/ui/SuggestionsView.java b/src/com/android/quicksearchbox/ui/SuggestionsView.java
index 6fba873..51deb67 100644
--- a/src/com/android/quicksearchbox/ui/SuggestionsView.java
+++ b/src/com/android/quicksearchbox/ui/SuggestionsView.java
@@ -16,17 +16,13 @@
 
 package com.android.quicksearchbox.ui;
 
-import com.android.quicksearchbox.R;
-import com.android.quicksearchbox.SuggestionPosition;
-
 import android.content.Context;
 import android.util.AttributeSet;
-import android.util.Log;
-import android.view.View;
-import android.widget.FrameLayout;
 import android.widget.ListAdapter;
 import android.widget.ListView;
 
+import com.android.quicksearchbox.SuggestionPosition;
+
 /**
  * Holds a list of suggestions.
  */
@@ -35,21 +31,19 @@
     private static final boolean DBG = false;
     private static final String TAG = "QSB.SuggestionsView";
 
-    private boolean mLimitSuggestionsToViewHeight;
     private SuggestionsAdapter<ListAdapter> mSuggestionsAdapter;
 
     public SuggestionsView(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
 
+    @Override
     public void setSuggestionsAdapter(SuggestionsAdapter<ListAdapter> adapter) {
         super.setAdapter(adapter == null ? null : adapter.getListAdapter());
         mSuggestionsAdapter = adapter;
-        if (mLimitSuggestionsToViewHeight) {
-            setMaxPromotedByHeight();
-        }
     }
 
+    @Override
     public SuggestionsAdapter<ListAdapter> getSuggestionsAdapter() {
         return mSuggestionsAdapter;
     }
@@ -78,44 +72,5 @@
         return (SuggestionPosition) getSelectedItem();
     }
 
-    public void setLimitSuggestionsToViewHeight(boolean limit) {
-        mLimitSuggestionsToViewHeight = limit;
-        if (mLimitSuggestionsToViewHeight) {
-            setMaxPromotedByHeight();
-        }
-    }
-
-    @Override
-    protected void onSizeChanged (int w, int h, int oldw, int oldh) {
-        if (mLimitSuggestionsToViewHeight) {
-            setMaxPromotedByHeight();
-        }
-    }
-
-    private void setMaxPromotedByHeight() {
-        if (mSuggestionsAdapter != null) {
-            float maxHeight;
-            if (getParent() instanceof FrameLayout) {
-                // We put the SuggestionView inside a frame layout so that we know what its
-                // maximum height is. Since this views height is set to 'wrap content' (in two-pane
-                // mode at least), we can't use our own height for these calculations.
-                maxHeight = ((View) getParent()).getHeight();
-                if (DBG) Log.d(TAG, "Parent height=" + maxHeight);
-            } else {
-                maxHeight = getHeight();
-                if (DBG) Log.d(TAG, "This height=" + maxHeight);
-            }
-            float suggestionHeight =
-                getContext().getResources().getDimension(R.dimen.suggestion_view_height);
-            if (suggestionHeight != 0) {
-                int suggestions = Math.max(1, (int) Math.floor(maxHeight / suggestionHeight));
-                if (DBG) {
-                    Log.d(TAG, "view height=" + maxHeight + " suggestion height=" +
-                            suggestionHeight + " -> maxSuggestions=" + suggestions);
-                }
-                mSuggestionsAdapter.setMaxPromoted(suggestions);
-            }
-        }
-    }
 
 }
diff --git a/tests/src/com/android/quicksearchbox/BlendingPromoterTest.java b/tests/src/com/android/quicksearchbox/BlendingPromoterTest.java
deleted file mode 100644
index 0a0b977..0000000
--- a/tests/src/com/android/quicksearchbox/BlendingPromoterTest.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import static com.android.quicksearchbox.SuggestionCursorUtil.assertSameSuggestions;
-import static com.android.quicksearchbox.SuggestionCursorUtil.slice;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-
-/**
- * Tests for {@link ShortcutPromoter}.
- */
-@MediumTest
-public class BlendingPromoterTest extends AndroidTestCase {
-
-    private String mQuery;
-
-    private Suggestion mS11;
-    private Suggestion mS12;
-    private Suggestion mS21;
-    private Suggestion mS22;
-    private Suggestion mWeb1;
-    private Suggestion mWeb2;
-
-    @Override
-    protected void setUp() throws Exception {
-        mQuery = "foo";
-        mS11 = MockSource.SOURCE_1.createSuggestion(mQuery + "_1_1");
-        mS12 = MockSource.SOURCE_1.createSuggestion(mQuery + "_1_2");
-        mS21 = MockSource.SOURCE_2.createSuggestion(mQuery + "_1_1");
-        mS22 = MockSource.SOURCE_2.createSuggestion(mQuery + "_1_2");
-        mWeb1 = MockSource.WEB_SOURCE.createSuggestion(mQuery + "_web_1");
-        mWeb2 = MockSource.WEB_SOURCE.createSuggestion(mQuery + "_web_2");
-    }
-
-    public void testMaxPromoted() {
-        maxPromotedTest(0);
-        maxPromotedTest(1);
-        maxPromotedTest(2);
-        maxPromotedTest(5);
-    }
-
-    public void testLimitZeroShortcutsPerSource() {
-        SuggestionCursor promoted = limit(cursor(mS11, mS12, mS21, mS22), 0, 0);
-        SuggestionCursor expected = cursor();
-        assertSameSuggestions(expected, promoted);
-    }
-
-    public void testLimitOneShortcutPerSource() {
-        SuggestionCursor promoted = limit(cursor(mS11, mS12, mS21, mS22), 1, 1);
-        SuggestionCursor expected = cursor(mS11, mS21);
-        assertSameSuggestions(expected, promoted);
-    }
-
-    public void testLimitTwoShortcutsPerSource() {
-        SuggestionCursor promoted = limit(cursor(mS11, mS12, mS21, mS22), 2, 2);
-        SuggestionCursor expected = cursor(mS11, mS12, mS21, mS22);
-        assertSameSuggestions(expected, promoted);
-    }
-
-    public void testLimitThreeShortcutsPerSource() {
-        SuggestionCursor promoted = limit(cursor(mS11, mS12, mS21, mS22), 3, 3);
-        SuggestionCursor expected = cursor(mS11, mS12, mS21, mS22);
-        assertSameSuggestions(expected, promoted);
-    }
-
-    public void testLimitOneSourceZeroPromoted() {
-        SuggestionCursor promoted = limit(cursor(mS11, mS12), 0, 0);
-        SuggestionCursor expected = cursor();
-        assertSameSuggestions(expected, promoted);
-    }
-
-    public void testLimitOneSourceOnePromoted() {
-        SuggestionCursor promoted = limit(cursor(mS11, mS12), 1, 1);
-        SuggestionCursor expected = cursor(mS11);
-        assertSameSuggestions(expected, promoted);
-    }
-
-    public void testLimitOneSourceTwoPromoted() {
-        SuggestionCursor promoted = limit(cursor(mS11, mS12), 2, 2);
-        SuggestionCursor expected = cursor(mS11, mS12);
-        assertSameSuggestions(expected, promoted);
-    }
-
-    public void testLimitNoShortcuts() {
-        SuggestionCursor promoted = limit(cursor(), 2, 2);
-        SuggestionCursor expected = cursor();
-        assertSameSuggestions(expected, promoted);
-    }
-
-    public void testLimitZeroWebShortcuts() {
-        SuggestionCursor promoted = limit(cursor(mS11, mS12, mWeb1, mWeb2), 0, 2);
-        SuggestionCursor expected = cursor(mS11, mS12);
-        assertSameSuggestions(expected, promoted);
-    }
-
-    public void testLimitTwoWebShortcuts() {
-        SuggestionCursor promoted = limit(cursor(mS11, mS12, mWeb1, mWeb2), 2, 2);
-        SuggestionCursor expected = cursor(mS11, mS12, mWeb1, mWeb2);
-        assertSameSuggestions(expected, promoted);
-    }
-
-    private void maxPromotedTest(int maxPromoted) {
-        SuggestionCursor shortcuts = cursor(mS11, mS12, mS21, mS22, mWeb1, mWeb2);
-        ListSuggestionCursorNoDuplicates promoted = promote(config(), shortcuts, maxPromoted);
-        int expectedCount = Math.min(maxPromoted, shortcuts.getCount());
-        assertEquals(expectedCount, promoted.getCount());
-        int count = Math.min(maxPromoted, shortcuts.getCount());
-        assertSameSuggestions(slice(promoted, 0, count), slice(shortcuts, 0, count));
-    }
-
-    private SuggestionCursor limit(SuggestionCursor shortcuts, int maxShortcutsPerWebSource,
-            int maxShortcutsPerNonWebSource) {
-        Config config = config(maxShortcutsPerWebSource, maxShortcutsPerNonWebSource);
-        int maxPromoted = 10;
-        return promote(config, shortcuts, maxPromoted);
-    }
-
-    private ListSuggestionCursorNoDuplicates promote(Config config, SuggestionCursor shortcuts,
-            int maxPromoted) {
-        ShortcutPromoter promoter = new ShortcutPromoter(config,
-                new RankAwarePromoter(config, null, null), null);
-        ListSuggestionCursorNoDuplicates promoted = new ListSuggestionCursorNoDuplicates(mQuery);
-        promoter.promoteShortcuts(shortcuts, maxPromoted, promoted);
-        return promoted;
-    }
-
-    private Config config() {
-        return new Config(getContext());
-    }
-
-    private Config config(final int maxShortcutsPerWebSource,
-            final int maxShortcutsPerNonWebSource) {
-        return new Config(getContext()) {
-            @Override
-            public int getMaxShortcutsPerWebSource() {
-                return maxShortcutsPerWebSource;
-            }
-            @Override
-            public int getMaxShortcutsPerNonWebSource() {
-                return maxShortcutsPerNonWebSource;
-            }
-        };
-    }
-
-    private SuggestionCursor cursor(Suggestion... suggestions) {
-        return new ListSuggestionCursor(mQuery, suggestions);
-    }
-
-}
diff --git a/tests/src/com/android/quicksearchbox/DefaultCorpusRankerTest.java b/tests/src/com/android/quicksearchbox/DefaultCorpusRankerTest.java
deleted file mode 100644
index 1e39d16..0000000
--- a/tests/src/com/android/quicksearchbox/DefaultCorpusRankerTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-
-import android.test.AndroidTestCase;
-import android.test.MoreAsserts;
-import android.test.suitebuilder.annotation.MediumTest;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Tests for {@link DefaultCorpusRankerTest}.
- */
-@MediumTest
-public class DefaultCorpusRankerTest extends AndroidTestCase {
-
-    protected MockCorpora mCorpora;
-    protected MockShortcutRepository mRepo;
-    protected DefaultCorpusRanker mRanker;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        mCorpora = new MockCorpora();
-        mCorpora.addCorpus(MockCorpus.CORPUS_1);
-        mCorpora.addCorpus(MockCorpus.CORPUS_2);
-        mCorpora.addCorpus(MockCorpus.WEB_CORPUS);
-        mRepo = new MockShortcutRepository();
-        mRanker = new DefaultCorpusRanker(mCorpora, mRepo);
-    }
-
-    public void testRankNoScores() {
-        mRanker.clear();
-        MoreAsserts.assertContentsInOrder(getRankedCorpora(),
-                MockCorpus.WEB_CORPUS, MockCorpus.CORPUS_1, MockCorpus.CORPUS_2);
-    }
-
-    public void testRankWebLowScore() {
-        setCorpusScores(1, 2, -100);
-        MoreAsserts.assertContentsInOrder(getRankedCorpora(),
-                MockCorpus.WEB_CORPUS, MockCorpus.CORPUS_2, MockCorpus.CORPUS_1);
-    }
-
-    public void testRankSomeScores() {
-        setCorpusScores(null, 1, null);
-        MoreAsserts.assertContentsInOrder(getRankedCorpora(),
-                MockCorpus.WEB_CORPUS, MockCorpus.CORPUS_2, MockCorpus.CORPUS_1);
-    }
-
-    private void setCorpusScores(Integer corpus1, Integer corpus2, Integer webCorpus) {
-        Map<String,Integer> scores = new HashMap<String,Integer>();
-        if (corpus1 != null) scores.put(MockCorpus.CORPUS_1.getName(), corpus1);
-        if (corpus2 != null) scores.put(MockCorpus.CORPUS_2.getName(), corpus2);
-        if (webCorpus != null) scores.put(MockCorpus.WEB_CORPUS.getName(), webCorpus);
-        mRepo.setCorpusScores(scores);
-        mRanker.clear();
-    }
-
-    private List<Corpus> getRankedCorpora() {
-        ConsumerTrap<List<Corpus>> consumer = new ConsumerTrap<List<Corpus>>();
-        mRanker.getCorporaInAll(consumer);
-        return consumer.getValue();
-    }
-
-}
diff --git a/tests/src/com/android/quicksearchbox/MockCorpora.java b/tests/src/com/android/quicksearchbox/MockCorpora.java
deleted file mode 100644
index 931ce75..0000000
--- a/tests/src/com/android/quicksearchbox/MockCorpora.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import android.database.DataSetObservable;
-import android.database.DataSetObserver;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-
-
-/**
- * Mock implementation of {@link Corpora}.
- */
-public class MockCorpora implements Corpora {
-
-    private static final String TAG = "QSB.MockCorpora";
-
-    private final DataSetObservable mDataSetObservable = new DataSetObservable();
-
-    private HashMap<String,Corpus> mCorporaByName = new HashMap<String,Corpus>();
-    private HashSet<Corpus> mDefaultCorpora = new HashSet<Corpus>();
-
-    private Corpus mWebCorpus;
-
-    public void addCorpus(Corpus corpus) {
-        Corpus oldCorpus = mCorporaByName.put(corpus.getName(), corpus);
-        if (oldCorpus != null) {
-            Log.d(TAG, "Replaced " + oldCorpus + " with " + corpus);
-        }
-        notifyDataSetChanged();
-    }
-
-    public void setWebCorpus(Corpus webCorpus) {
-        mWebCorpus = webCorpus;
-    }
-
-    public void addDefaultCorpus(Corpus corpus) {
-        mDefaultCorpora.add(corpus);
-    }
-
-    public List<Corpus> getAllCorpora() {
-        return Collections.unmodifiableList(new ArrayList<Corpus>(mCorporaByName.values()));
-    }
-
-    public Corpus getCorpus(String name) {
-        return mCorporaByName.get(name);
-    }
-
-    public Corpus getWebCorpus() {
-        return mWebCorpus;
-    }
-
-    public Corpus getCorpusForSource(Source source) {
-        for (Corpus corpus : mCorporaByName.values()) {
-            for (Source corpusSource : corpus.getSources()) {
-                if (corpusSource.equals(source)) {
-                    return corpus;
-                }
-            }
-        }
-        return null;
-    }
-
-    public List<Corpus> getEnabledCorpora() {
-        return getAllCorpora();
-    }
-
-    public List<Corpus> getCorporaInAll() {
-        return getAllCorpora();
-    }
-
-    public Source getSource(String name) {
-        for (Corpus corpus : mCorporaByName.values()) {
-            for (Source source : corpus.getSources()) {
-                if (source.getName().equals(name)) {
-                    return source;
-                }
-            }
-        }
-        return null;
-    }
-
-    public boolean isCorpusDefaultEnabled(Corpus corpus) {
-        return mDefaultCorpora.contains(corpus);
-    }
-
-    public boolean isCorpusEnabled(Corpus corpus) {
-        return true;
-    }
-
-    public void update() {
-    }
-
-    public void registerDataSetObserver(DataSetObserver observer) {
-        mDataSetObservable.registerObserver(observer);
-    }
-
-    public void unregisterDataSetObserver(DataSetObserver observer) {
-        mDataSetObservable.unregisterObserver(observer);
-    }
-
-    protected void notifyDataSetChanged() {
-        mDataSetObservable.notifyChanged();
-    }
-
-}
diff --git a/tests/src/com/android/quicksearchbox/MockCorpus.java b/tests/src/com/android/quicksearchbox/MockCorpus.java
deleted file mode 100644
index 97d6d71..0000000
--- a/tests/src/com/android/quicksearchbox/MockCorpus.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 2009 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.quicksearchbox;
-
-import android.content.Intent;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-
-import java.util.Collection;
-import java.util.Collections;
-
-/**
- * Mock implementation of {@link Corpus}.
- *
- */
-public class MockCorpus implements Corpus {
-
-    public static final Corpus CORPUS_1 = new MockCorpus(MockSource.SOURCE_1);
-
-    public static final Corpus CORPUS_2 = new MockCorpus(MockSource.SOURCE_2);
-
-    public static final Corpus WEB_CORPUS = new MockCorpus(MockSource.WEB_SOURCE);
-
-    private final String mName;
-
-    private final Source mSource;
-
-    private final boolean mDefaultEnabled;
-
-    public MockCorpus(Source source) {
-        this(source, true);
-    }
-
-    public MockCorpus(Source source, boolean defaultEnabled) {
-        mName = "corpus_" + source.getName();
-        mSource = source;
-        mDefaultEnabled = defaultEnabled;
-    }
-
-    public Intent createSearchIntent(String query, Bundle appData) {
-        return null;
-    }
-
-    public Intent createVoiceSearchIntent(Bundle appData) {
-        return null;
-    }
-
-    public Drawable getCorpusIcon() {
-        return null;
-    }
-
-    public Uri getCorpusIconUri() {
-        return null;
-    }
-
-    public CharSequence getLabel() {
-        return mName;
-    }
-
-    public CharSequence getHint() {
-        return null;
-    }
-
-    public String getName() {
-        return mName;
-    }
-
-    public int getQueryThreshold() {
-        return 0;
-    }
-
-    public Collection<Source> getSources() {
-        return Collections.singletonList(mSource);
-    }
-
-    public CharSequence getSettingsDescription() {
-        return null;
-    }
-
-    public CorpusResult getSuggestions(String query, int queryLimit, boolean onlyCorpus) {
-        return new Result(query, mSource.getSuggestions(query, queryLimit, true));
-    }
-
-    @Override
-    public String toString() {
-        return getName();
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (o != null && o.getClass().equals(this.getClass())) {
-            MockCorpus s = (MockCorpus) o;
-            return s.mName.equals(mName);
-        }
-        return false;
-    }
-
-    @Override
-    public int hashCode() {
-        return mName.hashCode();
-    }
-
-    private class Result extends SuggestionCursorWrapper implements CorpusResult {
-        public Result(String userQuery, SuggestionCursor cursor) {
-            super(userQuery, cursor);
-        }
-
-        public Corpus getCorpus() {
-            return MockCorpus.this;
-        }
-
-        public int getLatency() {
-            return 0;
-        }
-    }
-
-    public boolean isWebCorpus() {
-        return mSource.getName().equals(MockSource.WEB_SOURCE.getName());
-    }
-
-    public boolean queryAfterZeroResults() {
-        return false;
-    }
-
-    public boolean voiceSearchEnabled() {
-        return false;
-    }
-
-    public boolean isCorpusDefaultEnabled() {
-        return mDefaultEnabled;
-    }
-
-    public boolean includeInAll() {
-        return true;
-    }
-
-    public boolean isCorpusEnabled() {
-        return true;
-    }
-
-    public boolean isCorpusHidden() {
-        return false;
-    }
-
-}
diff --git a/tests/src/com/android/quicksearchbox/MockLogger.java b/tests/src/com/android/quicksearchbox/MockLogger.java
index 2863ac0..38a5cc3 100644
--- a/tests/src/com/android/quicksearchbox/MockLogger.java
+++ b/tests/src/com/android/quicksearchbox/MockLogger.java
@@ -16,8 +16,6 @@
 
 package com.android.quicksearchbox;
 
-import java.util.Collection;
-import java.util.List;
 
 /**
  * Mock {@code Logger} implementation.
@@ -27,25 +25,24 @@
     public MockLogger() {
     }
 
-    public void logStart(int onCreateLatency, int latency, String intentSource, Corpus corpus,
-            List<Corpus> orderedCorpora) {
+    public void logStart(int onCreateLatency, int latency, String intentSource) {
     }
 
     public void logSuggestionClick(long id,
-            SuggestionCursor suggestionCursor, Collection<Corpus> queriedCorpora,
+            SuggestionCursor suggestionCursor,
             int clickType) {
     }
 
-    public void logSearch(Corpus corpus, int startMethod, int numChars) {
+    public void logSearch(int startMethod, int numChars) {
     }
 
-    public void logVoiceSearch(Corpus corpus) {
+    public void logVoiceSearch() {
     }
 
     public void logExit(SuggestionCursor suggestionCursor, int numChars) {
     }
 
-    public void logLatency(CorpusResult result) {
+    public void logLatency(SourceResult result) {
     }
 
 }
diff --git a/tests/src/com/android/quicksearchbox/MockSearchSettings.java b/tests/src/com/android/quicksearchbox/MockSearchSettings.java
index cc2d775..e5591cf 100644
--- a/tests/src/com/android/quicksearchbox/MockSearchSettings.java
+++ b/tests/src/com/android/quicksearchbox/MockSearchSettings.java
@@ -29,18 +29,6 @@
     public void broadcastSettingsChanged() {
     }
 
-    public Intent getSearchableItemsIntent() {
-        return null;
-    }
-
-    public boolean getShowWebSuggestions() {
-        return true;
-    }
-
-    public boolean isCorpusEnabled(Corpus corpus) {
-        return true;
-    }
-
     public void upgradeSettingsIfNeeded() {
     }
 
@@ -55,14 +43,6 @@
         return 0;
     }
 
-    public Intent getSearchSettingsIntent() {
-        return null;
-    }
-
-    public boolean allowWebSearchShortcuts() {
-        return true;
-    }
-
     public boolean shouldUseGoogleCom() {
         return true;
     }
diff --git a/tests/src/com/android/quicksearchbox/MockShortcutRefresher.java b/tests/src/com/android/quicksearchbox/MockShortcutRefresher.java
deleted file mode 100644
index d5c1f11..0000000
--- a/tests/src/com/android/quicksearchbox/MockShortcutRefresher.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-
-/**
- * Mock implementation of {@link ShortcutRefresher}.
- */
-public class MockShortcutRefresher implements ShortcutRefresher {
-
-    public void cancelPendingTasks() {
-    }
-
-    public void markShortcutRefreshed(Source source, String shortcutId) {
-    }
-
-    public void refresh(Suggestion shortcut, Listener listener) {
-    }
-
-    public void reset() {
-    }
-
-    public boolean shouldRefresh(Source source, String shortcutId) {
-        return shortcutId != null;
-    }
-
-}
diff --git a/tests/src/com/android/quicksearchbox/MockShortcutRepository.java b/tests/src/com/android/quicksearchbox/MockShortcutRepository.java
deleted file mode 100644
index e7b3e26..0000000
--- a/tests/src/com/android/quicksearchbox/MockShortcutRepository.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2009 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.quicksearchbox;
-
-import com.android.quicksearchbox.util.Consumer;
-
-import java.util.Collection;
-import java.util.Map;
-
-/**
- * Mock implementation of {@link ShortcutRepository}.
- *
- */
-public class MockShortcutRepository implements ShortcutRepository {
-
-    private Map<String, Integer> mCorpusScores;
-
-    public void setCorpusScores(Map<String, Integer> corpusScores) {
-        mCorpusScores = corpusScores;
-    }
-
-    public void clearHistory() {
-    }
-
-    public void removeFromHistory(SuggestionCursor suggestions, int position) {
-    }
-
-    public void close() {
-    }
-
-    public void getShortcutsForQuery(String query, Collection<Corpus> corporaToQuery,
-            boolean allowWebSearchShortcuts, Consumer<ShortcutCursor> consumer) {
-        ShortcutCursor cursor = getShortcutsForQuery(query, corporaToQuery);
-        consumer.consume(cursor);
-    }
-
-    /**
-     * Synchronous version for use in tests that just need a ShortcutCursor.
-     */
-    public ShortcutCursor getShortcutsForQuery(String query, Collection<Corpus> corporaToQuery) {
-        // TODO: should look at corporaToQuery
-        ShortcutCursor cursor = new ShortcutCursor(query, null, null, null);
-        cursor.add(MockSource.SOURCE_1.createSuggestion(query + "_1_shortcut"));
-        cursor.add(MockSource.SOURCE_2.createSuggestion(query + "_2_shortcut"));
-        return cursor;
-    }
-
-    public void updateShortcut(Source source, String shortcutId, SuggestionCursor refreshed) {
-    }
-
-    public void getCorpusScores(Consumer<Map<String, Integer>> consumer) {
-        consumer.consume(mCorpusScores);
-    }
-
-    public void hasHistory(Consumer<Boolean> consumer) {
-        consumer.consume(false);
-    }
-
-    public void reportClick(SuggestionCursor suggestions, int position) {
-    }
-
-}
diff --git a/tests/src/com/android/quicksearchbox/MockSource.java b/tests/src/com/android/quicksearchbox/MockSource.java
index 6637bfe..b0b9889 100644
--- a/tests/src/com/android/quicksearchbox/MockSource.java
+++ b/tests/src/com/android/quicksearchbox/MockSource.java
@@ -16,16 +16,15 @@
 
 package com.android.quicksearchbox;
 
-import com.android.quicksearchbox.ui.SuggestionViewFactory;
-import com.android.quicksearchbox.util.Now;
-import com.android.quicksearchbox.util.NowOrLater;
-
 import android.content.ComponentName;
 import android.content.Intent;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
 
+import com.android.quicksearchbox.util.Now;
+import com.android.quicksearchbox.util.NowOrLater;
+
 /**
  * Mock implementation of {@link Source}.
  *
@@ -47,23 +46,16 @@
                     .setSuggestionQuery(query);
         }
 
-        @Override
-        public int getMaxShortcuts(Config config) {
-            return config.getMaxShortcutsPerWebSource();
-        }
     };
 
     private final String mName;
 
-    private final int mVersionCode;
-
     public MockSource(String name) {
         this(name, 0);
     }
 
     public MockSource(String name, int versionCode) {
         mName = name;
-        mVersionCode = versionCode;
     }
 
     public ComponentName getIntentComponent() {
@@ -76,14 +68,6 @@
         return null;
     }
 
-    public int getVersionCode() {
-        return mVersionCode;
-    }
-
-    public boolean isVersionCodeCompatible(int version) {
-        return version == mVersionCode;
-    }
-
     public String getName() {
         return getIntentComponent().flattenToShortString();
     }
@@ -133,7 +117,7 @@
         return true;
     }
 
-    public SourceResult getSuggestions(String query, int queryLimit, boolean onlySource) {
+    public SourceResult getSuggestions(String query, int queryLimit) {
         if (query.length() == 0) {
             return null;
         }
@@ -167,7 +151,7 @@
 
     @Override
     public String toString() {
-        return getName() + ":" + getVersionCode();
+        return getName();
     }
 
     private class Result extends SuggestionCursorWrapper implements SourceResult {
@@ -182,18 +166,6 @@
 
     }
 
-    public SuggestionCursor refreshShortcut(String shortcutId, String extraData) {
-        return null;
-    }
-
-    public boolean isExternal() {
-        return false;
-    }
-
-    public int getMaxShortcuts(Config config) {
-        return config.getMaxShortcutsPerNonWebSource();
-    }
-
     public boolean queryAfterZeroResults() {
         return false;
     }
diff --git a/tests/src/com/android/quicksearchbox/MockSources.java b/tests/src/com/android/quicksearchbox/MockSources.java
deleted file mode 100644
index 9651364..0000000
--- a/tests/src/com/android/quicksearchbox/MockSources.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import android.content.ComponentName;
-
-import java.util.Collection;
-import java.util.HashMap;
-
-/**
- * Mock implementation of {@link Sources}.
- */
-public class MockSources implements Sources {
-
-    private final HashMap<String, Source> mSources = new HashMap<String, Source>();
-
-    public void addSource(Source source) {
-        mSources.put(source.getName(), source);
-    }
-
-    public Source getSource(String name) {
-        return mSources.get(name);
-    }
-
-    public Collection<Source> getSources() {
-        return mSources.values();
-    }
-
-    public Source getWebSearchSource() {
-        return null;
-    }
-
-    public void update() {
-    }
-
-    public Source createSourceFor(ComponentName component) {
-        return null;
-    }
-
-}
diff --git a/tests/src/com/android/quicksearchbox/MultiSourceCorpusTest.java b/tests/src/com/android/quicksearchbox/MultiSourceCorpusTest.java
deleted file mode 100644
index db703c8..0000000
--- a/tests/src/com/android/quicksearchbox/MultiSourceCorpusTest.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.test.AndroidTestCase;
-import android.test.MoreAsserts;
-import android.test.suitebuilder.annotation.LargeTest;
-
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-
-/**
- * Tests for {@link MultiSourceCorpus}.
- */
-@LargeTest
-public class MultiSourceCorpusTest extends AndroidTestCase {
-
-    protected MultiSourceCorpus mCorpus;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        Config config = new Config(getContext());
-        // Using a single thread to make the test deterministic
-        Executor executor = Executors.newSingleThreadExecutor();
-        mCorpus = new SkeletonMultiSourceCorpus(getContext(), config, executor,
-                MockSource.SOURCE_1, MockSource.SOURCE_2);
-    }
-
-    public void testGetSources() {
-        MoreAsserts.assertContentsInOrder(mCorpus.getSources(),
-                MockSource.SOURCE_1, MockSource.SOURCE_2);
-    }
-
-    public void testGetSuggestions() {
-        ListSuggestionCursor expected = concatSuggestionCursors("foo",
-                MockSource.SOURCE_1.getSuggestions("foo", 50, false),
-                MockSource.SOURCE_2.getSuggestions("foo", 50, false));
-        CorpusResult observed = mCorpus.getSuggestions("foo", 50, false);
-        SuggestionCursorUtil.assertSameSuggestions(expected, observed);
-    }
-
-    public void testIncludeInAll() {
-        assertTrue(mCorpus.includeInAll());
-    }
-
-    private static ListSuggestionCursor concatSuggestionCursors(String query,
-            SuggestionCursor... cursors) {
-        ListSuggestionCursor out = new ListSuggestionCursor("foo");
-        for (SuggestionCursor cursor : cursors) {
-            int count = cursor.getCount();
-            for (int i = 0; i < count; i++) {
-                out.add(new SuggestionPosition(cursor, i));
-            }
-        }
-        return out;
-    }
-
-    private static class SkeletonMultiSourceCorpus extends MultiSourceCorpus {
-
-        public SkeletonMultiSourceCorpus(Context context, Config config, Executor executor,
-                Source... sources) {
-            super(context, config, executor, sources);
-        }
-
-        public Intent createSearchIntent(String query, Bundle appData) {
-            return null;
-        }
-
-        public Intent createVoiceSearchIntent(Bundle appData) {
-            return null;
-        }
-
-        public Drawable getCorpusIcon() {
-            return null;
-        }
-
-        public Uri getCorpusIconUri() {
-            return null;
-        }
-
-        public CharSequence getHint() {
-            return null;
-        }
-
-        public CharSequence getLabel() {
-            return null;
-        }
-
-        @Override
-        public int getQueryThreshold() {
-            return 0;
-        }
-
-        public CharSequence getSettingsDescription() {
-            return null;
-        }
-
-        public boolean isWebCorpus() {
-            return false;
-        }
-
-        @Override
-        public boolean queryAfterZeroResults() {
-            return false;
-        }
-
-        @Override
-        public boolean voiceSearchEnabled() {
-            return false;
-        }
-
-        public String getName() {
-            return "SkeletonMultiSourceCorpus";
-        }
-
-    }
-}
diff --git a/tests/src/com/android/quicksearchbox/RankAwarePromoterTest.java b/tests/src/com/android/quicksearchbox/RankAwarePromoterTest.java
deleted file mode 100644
index e0920a7..0000000
--- a/tests/src/com/android/quicksearchbox/RankAwarePromoterTest.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Tests for RankAwarePromoter
- */
-@SmallTest
-public class RankAwarePromoterTest extends AndroidTestCase {
-    public static final int NUM_SUGGESTIONS_ABOVE_KEYBOARD = 4;
-    public static final int MAX_PROMOTED_CORPORA = 3;
-    public static final int MAX_PROMOTED_SUGGESTIONS = 8;
-    public static final String TEST_QUERY = "query";
-
-    private final List<Corpus> mCorpora = createMockCorpora(5, MAX_PROMOTED_CORPORA);
-    private final Corpus mShortcuts = createMockShortcutsCorpus();
-    private RankAwarePromoter mPromoter;
-
-    @Override
-    public void setUp() {
-        mPromoter = new RankAwarePromoter(new Config(mContext){
-            @Override
-            public int getNumSuggestionsAboveKeyboard() {
-                return NUM_SUGGESTIONS_ABOVE_KEYBOARD;
-            }
-        }, null, null);
-    }
-
-    public void testPromotesExpectedSuggestions() {
-        List<CorpusResult> suggestions = getSuggestions(TEST_QUERY);
-        ListSuggestionCursorNoDuplicates promoted = 
-            new ListSuggestionCursorNoDuplicates(TEST_QUERY);
-        mPromoter.promoteSuggestions(suggestions, MAX_PROMOTED_SUGGESTIONS, promoted);
-
-        int[] expectedSource = {0, 1, 2, 0, 1, 2, 3, 4};
-        int[] expectedSuggestion = {1, 1, 1, 2, 2, 2, 1, 1};
-
-        assertRightSuggestionsWerePromoted(promoted, expectedSource, expectedSuggestion);
-    }
-
-    public void testWhenPromotingAlreadyPromotedResults() {
-        List<CorpusResult> suggestions = getSuggestions(TEST_QUERY);
-        ListSuggestionCursorNoDuplicates promoted =
-                new ListSuggestionCursorNoDuplicates(TEST_QUERY);
-
-        // Simulate scenario where another promoter has already put an item
-        // (e.g. a shortcut) into the promoted suggestions list, and the current
-        // promoter tries to promote the same item.
-        // The promoter must notice that this duplicate (which automatically
-        // gets filtered out by the suggestion cursor) doesn't decrease the
-        // number of slots available on the screen.
-        CorpusResult corpora2 = suggestions.get(2);
-        corpora2.moveTo(0);
-        Suggestion shortcut = new SuggestionPosition(corpora2);
-        promoted.add(shortcut);
-
-        mPromoter.promoteSuggestions(suggestions, MAX_PROMOTED_SUGGESTIONS, promoted);
-
-        int[] expectedSource = {
-                // The shortcut at the top of the list.
-                2,
-                // The promoted results. There's just one result from corpus
-                // 2 because only 2 test suggestions per corpus are generated
-                // by the test data generator, and we use up all our suggestions
-                // for corpus 2 earlier than the rest.
-                0, 1, 2, 0, 1, 3, 4};
-        int[] expectedSuggestion = {
-                // The shortcut at the top of the list.
-                1,
-                // The promoted results.
-                1, 1, 2, 2, 2, 1, 1};
-
-        assertRightSuggestionsWerePromoted(promoted, expectedSource, expectedSuggestion);
-    }
-
-    private void assertRightSuggestionsWerePromoted(ListSuggestionCursorNoDuplicates promoted,
-            int[] expectedSource, int[] expectedSuggestion) {
-        assertEquals(MAX_PROMOTED_SUGGESTIONS, promoted.getCount());
-
-        for (int i = 0; i < promoted.getCount(); i++) {
-            promoted.moveTo(i);
-            assertEquals("Source in position " + i,
-                    "MockSource Source" + expectedSource[i],
-                    promoted.getSuggestionSource().getLabel());
-            assertEquals("Suggestion in position " + i,
-                    TEST_QUERY + "_" + expectedSuggestion[i],
-                    promoted.getSuggestionText1());
-        }
-    }
-
-    public void testPromotesRightNumberOfSuggestions() {
-        List<CorpusResult> suggestions = getSuggestions(TEST_QUERY);
-        ListSuggestionCursor promoted = new ListSuggestionCursor(TEST_QUERY);
-        SuggestionCursor shortcuts = mShortcuts.
-                getSuggestions(TEST_QUERY, MAX_PROMOTED_SUGGESTIONS / 2, true);
-        for (int i = 0; i < shortcuts.getCount(); ++i) {
-            promoted.add(new SuggestionPosition(shortcuts, 1));
-        }
-        mPromoter.promoteSuggestions(suggestions, MAX_PROMOTED_SUGGESTIONS, promoted);
-        assertEquals(MAX_PROMOTED_SUGGESTIONS, promoted.getCount());
-    }
-
-    private List<CorpusResult> getSuggestions(String query) {
-        ArrayList<CorpusResult> results = new ArrayList<CorpusResult>();
-        for (Corpus corpus : mCorpora) {
-            results.add(corpus.getSuggestions(query, 10, false));
-        }
-        return results;
-    }
-
-    private static List<Corpus> createMockCorpora(int count, int defaultCount) {
-        ArrayList<Corpus> corpora = new ArrayList<Corpus>();
-        for (int i = 0; i < count; i++) {
-            Source mockSource = new MockSource("Source" + i);
-            Corpus mockCorpus = new MockCorpus(mockSource, i < defaultCount);
-            corpora.add(mockCorpus);
-        }
-        return corpora;
-    }
-
-    private static Corpus createMockShortcutsCorpus() {
-        Source mockSource = new MockSource("Shortcuts");
-        Corpus mockCorpus = new MockCorpus(mockSource, true);
-        return mockCorpus;
-    }
-
-}
diff --git a/tests/src/com/android/quicksearchbox/ResultPromoterTest.java b/tests/src/com/android/quicksearchbox/ResultPromoterTest.java
deleted file mode 100644
index 15da1ca..0000000
--- a/tests/src/com/android/quicksearchbox/ResultPromoterTest.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import static com.android.quicksearchbox.SuggestionCursorUtil.assertSameSuggestions;
-import static com.android.quicksearchbox.SuggestionCursorUtil.assertSameSuggestionsNoOrder;
-import static com.android.quicksearchbox.SuggestionCursorUtil.concat;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Tests for {@link ResultPromoter}.
- */
-@MediumTest
-public class ResultPromoterTest extends AndroidTestCase {
-
-    private static final int MAX_PROMOTED_SUGGESTIONS = 10;
-
-    private String mQuery;
-
-    private Suggestion mS11;
-    private Suggestion mS12;
-    private Suggestion mS21;
-    private Suggestion mS22;
-    private Suggestion mWeb1;
-    private Suggestion mWeb2;
-
-    private CorpusResult mCorpusResult1;
-    private CorpusResult mCorpusResult2;
-    private CorpusResult mCorpusResultWeb;
-
-    private SuggestionCursor mShortcuts;
-    private List<CorpusResult> mCorpusResults;
-
-    @Override
-    protected void setUp() throws Exception {
-        mQuery = "foo";
-        mS11 = MockSource.SOURCE_1.createSuggestion(mQuery + "_1_1");
-        mS12 = MockSource.SOURCE_1.createSuggestion(mQuery + "_1_2");
-        mS21 = MockSource.SOURCE_2.createSuggestion(mQuery + "_1_1");
-        mS22 = MockSource.SOURCE_2.createSuggestion(mQuery + "_1_2");
-        mWeb1 = MockSource.WEB_SOURCE.createSuggestion(mQuery + "_web_1");
-        mWeb2 = MockSource.WEB_SOURCE.createSuggestion(mQuery + "_web_2");
-        mShortcuts = cursor(mS11, mS12, mS21, mS22, mWeb1, mWeb2);
-        mCorpusResult1 = MockCorpus.CORPUS_1.getSuggestions(mQuery, 10, false);
-        mCorpusResult2 = MockCorpus.CORPUS_2.getSuggestions(mQuery, 10, false);
-        mCorpusResultWeb = MockCorpus.WEB_CORPUS.getSuggestions(mQuery, 10, false);
-        mCorpusResults = new ArrayList<CorpusResult>();
-        mCorpusResults.add(mCorpusResult1);
-        mCorpusResults.add(mCorpusResult2);
-        mCorpusResults.add(mCorpusResultWeb);
-    }
-
-    public void testOnlyResultShortcutsPromoted() {
-        SuggestionCursor promoted = promoteShortcuts(mShortcuts);
-        SuggestionCursor expected = cursor(mS11, mS12, mS21, mS22);
-        assertSameSuggestions(expected, promoted);
-    }
-
-    public void testOnlyResultSuggestionsPromoted() {
-        SuggestionCursor promoted = promoteSuggestions(mCorpusResults);
-        SuggestionCursor expected = concat(mCorpusResult1, mCorpusResult2);
-        assertSameSuggestionsNoOrder(expected, promoted);
-    }
-
-    private ShortcutPromoter createResultPromoter() {
-        ResultFilter results = new ResultFilter();
-        return new ShortcutPromoter(config(),
-                new RankAwarePromoter(config(), results, null), results);
-    }
-
-    private ListSuggestionCursor promoteShortcuts(SuggestionCursor shortcuts) {
-        ShortcutPromoter promoter = createResultPromoter();
-        ListSuggestionCursor promoted = new ListSuggestionCursor(mQuery);
-        promoter.promoteShortcuts(shortcuts, MAX_PROMOTED_SUGGESTIONS, promoted);
-        return promoted;
-    }
-
-    private ListSuggestionCursor promoteSuggestions(List<CorpusResult> suggestions) {
-        ResultFilter results = new ResultFilter();
-        RankAwarePromoter promoter = new RankAwarePromoter(config(), results, null);
-        ListSuggestionCursor promoted = new ListSuggestionCursor(mQuery);
-        promoter.promoteSuggestions(suggestions, MAX_PROMOTED_SUGGESTIONS, promoted);
-        return promoted;
-    }
-
-    private Config config() {
-        return new Config(getContext());
-    }
-
-    private SuggestionCursor cursor(Suggestion... suggestions) {
-        return new ListSuggestionCursor(mQuery, suggestions);
-    }
-
-}
diff --git a/tests/src/com/android/quicksearchbox/SearchableCorporaTest.java b/tests/src/com/android/quicksearchbox/SearchableCorporaTest.java
deleted file mode 100644
index 7abf5c6..0000000
--- a/tests/src/com/android/quicksearchbox/SearchableCorporaTest.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2009 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.quicksearchbox;
-
-import android.test.AndroidTestCase;
-import android.test.MoreAsserts;
-import android.test.suitebuilder.annotation.MediumTest;
-
-import java.util.Arrays;
-import java.util.Collection;
-
-/**
- * Tests for {@link SearchableCorpora}.
- *
- */
-@MediumTest
-public class SearchableCorporaTest extends AndroidTestCase {
-
-    protected SearchSettings mSettings;
-
-    protected SearchableCorpora mCorpora;
-
-    private static final MockCorpus CORPUS_1 = new MockCorpus(MockSource.SOURCE_1);
-    private static final MockCorpus CORPUS_DISABLED = new MockCorpus(MockSource.SOURCE_2);
-    private static final MockCorpus CORPUS_NOT_IN_ALL = new MockCorpus(MockSource.SOURCE_3) {
-        @Override
-        public boolean includeInAll() {
-            return false;
-        }
-    };
-    private static final MockCorpus CORPUS_WEB = new MockCorpus(MockSource.WEB_SOURCE);
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        mSettings = new MockSearchSettings() {
-            @Override
-            public boolean isCorpusEnabled(Corpus corpus) {
-                return !CORPUS_DISABLED.equals(corpus);
-            }
-        };
-        MockSources sources = new MockSources();
-        sources.addSource(MockSource.SOURCE_1);
-        sources.addSource(MockSource.SOURCE_2);
-        sources.addSource(MockSource.SOURCE_3);
-        sources.addSource(MockSource.WEB_SOURCE);
-        mCorpora = new SearchableCorpora(mContext, mSettings, sources, new MockCorpusFactory());
-        mCorpora.update();
-    }
-
-    public void testGetAllCorpora() {
-        MoreAsserts.assertContentsInAnyOrder(mCorpora.getAllCorpora(),
-                CORPUS_1, CORPUS_DISABLED, CORPUS_NOT_IN_ALL, CORPUS_WEB);
-    }
-
-    public void testEnabledCorpora() {
-        MoreAsserts.assertContentsInAnyOrder(mCorpora.getEnabledCorpora(),
-                CORPUS_1, CORPUS_NOT_IN_ALL, CORPUS_WEB);
-    }
-
-    public void testCorporaIncludedInAll() {
-        MoreAsserts.assertContentsInAnyOrder(mCorpora.getCorporaInAll(),
-                CORPUS_1, CORPUS_WEB);
-    }
-
-    public void testGetWebCorpus() {
-        assertEquals(CORPUS_WEB, mCorpora.getWebCorpus());
-    }
-
-    public void testGetCorpusForSource() {
-        assertEquals(CORPUS_1, mCorpora.getCorpusForSource(MockSource.SOURCE_1));
-        assertNull(mCorpora.getCorpusForSource(new MockSource("foo")));
-    }
-
-    public void testGetCorpus() {
-        assertEquals(CORPUS_WEB, mCorpora.getCorpus(CORPUS_WEB.getName()));
-    }
-
-    /**
-     * Mock implementation of {@link CorpusFactory}.
-     */
-    private static class MockCorpusFactory implements CorpusFactory {
-        public Collection<Corpus> createCorpora(Sources sources) {
-            return Arrays.<Corpus>asList(CORPUS_1, CORPUS_DISABLED, CORPUS_NOT_IN_ALL, CORPUS_WEB);
-        }
-    }
-
-}
diff --git a/tests/src/com/android/quicksearchbox/ShortcutRepositoryTest.java b/tests/src/com/android/quicksearchbox/ShortcutRepositoryTest.java
deleted file mode 100644
index c881c7d..0000000
--- a/tests/src/com/android/quicksearchbox/ShortcutRepositoryTest.java
+++ /dev/null
@@ -1,991 +0,0 @@
-/*
- * Copyright (C) 2009 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.quicksearchbox;
-
-import com.android.quicksearchbox.util.MockExecutor;
-import com.android.quicksearchbox.util.Util;
-
-import org.json.JSONArray;
-
-import android.app.SearchManager;
-import android.content.Intent;
-import android.test.AndroidTestCase;
-import android.test.MoreAsserts;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-/**
- * Abstract base class for tests of  {@link ShortcutRepository}
- * implementations.  Most importantly, verifies the
- * stuff we are doing with sqlite works how we expect it to.
- *
- * Attempts to test logic independent of the (sql) details of the implementation, so these should
- * be useful even in the face of a schema change.
- */
-@MediumTest
-public class ShortcutRepositoryTest extends AndroidTestCase {
-
-    private static final String TAG = "ShortcutRepositoryTest";
-
-    static final long NOW = 1239841162000L; // millis since epoch. some time in 2009
-
-    static final Source APP_SOURCE = new MockSource("com.example.app/.App");
-
-    static final Source APP_SOURCE_V2 = new MockSource("com.example.app/.App", 2);
-
-    static final Source CONTACTS_SOURCE = new MockSource("com.android.contacts/.Contacts");
-
-    static final Source BOOKMARKS_SOURCE = new MockSource("com.android.browser/.Bookmarks");
-
-    static final Source HISTORY_SOURCE = new MockSource("com.android.browser/.History");
-
-    static final Source MUSIC_SOURCE = new MockSource("com.android.music/.Music");
-
-    static final Source MARKET_SOURCE = new MockSource("com.android.vending/.Market");
-
-    static final Corpus APP_CORPUS = new MockCorpus(APP_SOURCE);
-
-    static final Corpus CONTACTS_CORPUS = new MockCorpus(CONTACTS_SOURCE);
-
-    static final Corpus WEB_CORPUS = new MockCorpus(MockSource.WEB_SOURCE);
-
-    static final int MAX_SHORTCUTS = 8;
-
-    protected Config mConfig;
-    protected MockCorpora mCorpora;
-    protected MockExecutor mLogExecutor;
-    protected ShortcutRefresher mRefresher;
-
-    protected List<Corpus> mAllowedCorpora;
-
-    protected ShortcutRepositoryImplLog mRepo;
-
-    protected ListSuggestionCursor mAppSuggestions;
-    protected ListSuggestionCursor mContactSuggestions;
-
-    protected SuggestionData mApp1;
-    protected SuggestionData mApp2;
-    protected SuggestionData mApp3;
-
-    protected SuggestionData mContact1;
-    protected SuggestionData mContact2;
-
-    protected SuggestionData mWeb1;
-
-    protected ShortcutRepositoryImplLog createShortcutRepository() {
-        return new ShortcutRepositoryImplLog(getContext(), mConfig, mCorpora,
-                mRefresher, new MockHandler(), mLogExecutor,
-                "test-shortcuts-log.db");
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        mConfig = new Config(getContext());
-        mCorpora = new MockCorpora();
-        mCorpora.addCorpus(APP_CORPUS);
-        mCorpora.addCorpus(CONTACTS_CORPUS);
-        mCorpora.addCorpus(WEB_CORPUS);
-        mRefresher = new MockShortcutRefresher();
-        mLogExecutor = new MockExecutor();
-        mRepo = createShortcutRepository();
-
-        mAllowedCorpora = new ArrayList<Corpus>(mCorpora.getAllCorpora());
-
-        mApp1 = makeApp("app1");
-        mApp2 = makeApp("app2");
-        mApp3 = makeApp("app3");
-        mAppSuggestions = new ListSuggestionCursor("foo", mApp1, mApp2, mApp3);
-
-        mContact1 = new SuggestionData(CONTACTS_SOURCE)
-                .setText1("Joe Blow")
-                .setIntentAction("view")
-                .setIntentData("contacts/joeblow")
-                .setShortcutId("j-blow");
-        mContact2 = new SuggestionData(CONTACTS_SOURCE)
-                .setText1("Mike Johnston")
-                .setIntentAction("view")
-                .setIntentData("contacts/mikeJ")
-                .setShortcutId("mo-jo");
-
-        mWeb1 = new SuggestionData(MockSource.WEB_SOURCE)
-                .setText1("foo")
-                .setIntentAction(Intent.ACTION_WEB_SEARCH)
-                .setSuggestionQuery("foo");
-
-        mContactSuggestions = new ListSuggestionCursor("foo", mContact1, mContact2);
-    }
-
-    private SuggestionData makeApp(String name) {
-        return new SuggestionData(APP_SOURCE)
-                .setText1(name)
-                .setIntentAction("view")
-                .setIntentData("apps/" + name)
-                .setShortcutId("shorcut_" + name);
-    }
-
-    private SuggestionData makeContact(String name) {
-        return new SuggestionData(CONTACTS_SOURCE)
-                .setText1(name)
-                .setIntentAction("view")
-                .setIntentData("contacts/" + name)
-                .setShortcutId("shorcut_" + name);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
-        mRepo.deleteRepository();
-    }
-
-    public void testHasHistory() {
-        assertHasHistory(false);
-        reportClickAtTime(mAppSuggestions, 0, NOW);
-        assertHasHistory(true);
-        mRepo.clearHistory();
-        mLogExecutor.runNext();
-        assertHasHistory(false);
-    }
-
-    public void testRemoveFromHistory() {
-        SuggestionData john = new SuggestionData(CONTACTS_SOURCE)
-                .setText1("john doe")
-                .setIntentAction("view")
-                .setIntentData("john_doe");
-        SuggestionData jane = new SuggestionData(CONTACTS_SOURCE)
-                .setText1("jane doe")
-                .setIntentAction("view")
-                .setIntentData("jane_doe");
-        reportClick("j", john);
-        reportClick("j", john);
-        reportClick("j", jane);
-        assertShortcuts("j", john, jane);
-        removeFromHistory(new ListSuggestionCursor("j", jane, john), 1);
-        assertShortcuts("j", jane);
-    }
-
-    public void testRemoveFromHistoryNonExisting() {
-        SuggestionData john = new SuggestionData(CONTACTS_SOURCE)
-                .setText1("john doe")
-                .setIntentAction("view")
-                .setIntentData("john_doe");
-        SuggestionData jane = new SuggestionData(CONTACTS_SOURCE)
-                .setText1("jane doe")
-                .setIntentAction("view")
-                .setIntentData("jane_doe");
-        reportClick("j", john);
-        assertShortcuts("j", john);
-        removeFromHistory(new ListSuggestionCursor("j", jane), 0);
-        assertShortcuts("j", john);
-    }
-
-    public void testNoMatch() {
-        SuggestionData clicked = new SuggestionData(CONTACTS_SOURCE)
-                .setText1("bob smith")
-                .setIntentAction("action")
-                .setIntentData("data");
-
-        reportClick("bob smith", clicked);
-        assertNoShortcuts("joe");
-    }
-
-    public void testFullPackingUnpacking() {
-        SuggestionData clicked = new SuggestionData(CONTACTS_SOURCE)
-                .setFormat("<i>%s</i>")
-                .setText1("title")
-                .setText2("description")
-                .setText2Url("description_url")
-                .setIcon1("android.resource://system/drawable/foo")
-                .setIcon2("content://test/bar")
-                .setIntentAction("action")
-                .setIntentData("data")
-                .setSuggestionQuery("query")
-                .setIntentExtraData("extradata")
-                .setShortcutId("idofshortcut")
-                .setSuggestionLogType("logtype");
-        reportClick("q", clicked);
-
-        assertShortcuts("q", clicked);
-        assertShortcuts("", clicked);
-    }
-
-    public void testSpinnerWhileRefreshing() {
-        SuggestionData clicked = new SuggestionData(CONTACTS_SOURCE)
-                .setText1("title")
-                .setText2("description")
-                .setIcon2("icon2")
-                .setSuggestionQuery("query")
-                .setIntentExtraData("extradata")
-                .setShortcutId("idofshortcut")
-                .setSpinnerWhileRefreshing(true);
-
-        reportClick("q", clicked);
-
-        String spinnerUri = Util.getResourceUri(mContext, R.drawable.search_spinner).toString();
-        SuggestionData expected = new SuggestionData(CONTACTS_SOURCE)
-                .setText1("title")
-                .setText2("description")
-                .setIcon2(spinnerUri)
-                .setSuggestionQuery("query")
-                .setIntentExtraData("extradata")
-                .setShortcutId("idofshortcut")
-                .setSpinnerWhileRefreshing(true);
-
-        assertShortcuts("q", expected);
-    }
-
-    public void testPrefixesMatch() {
-        assertNoShortcuts("bob");
-
-        SuggestionData clicked = new SuggestionData(CONTACTS_SOURCE)
-                .setText1("bob smith the third")
-                .setIntentAction("action")
-                .setIntentData("intentdata");
-
-        reportClick("bob smith", clicked);
-
-        assertShortcuts("bob smith", clicked);
-        assertShortcuts("bob s", clicked);
-        assertShortcuts("b", clicked);
-    }
-
-    public void testMatchesOneAndNotOthers() {
-        SuggestionData bob = new SuggestionData(CONTACTS_SOURCE)
-                .setText1("bob smith the third")
-                .setIntentAction("action")
-                .setIntentData("intentdata/bob");
-
-        reportClick("bob", bob);
-
-        SuggestionData george = new SuggestionData(CONTACTS_SOURCE)
-                .setText1("george jones")
-                .setIntentAction("action")
-                .setIntentData("intentdata/george");
-        reportClick("geor", george);
-
-        assertShortcuts("b for bob", "b", bob);
-        assertShortcuts("g for george", "g", george);
-    }
-
-    public void testDifferentPrefixesMatchSameEntity() {
-        SuggestionData clicked = new SuggestionData(CONTACTS_SOURCE)
-                .setText1("bob smith the third")
-                .setIntentAction("action")
-                .setIntentData("intentdata");
-
-        reportClick("bob", clicked);
-        reportClick("smith", clicked);
-        assertShortcuts("b", clicked);
-        assertShortcuts("s", clicked);
-    }
-
-    public void testMoreClicksWins() {
-        reportClick("app", mApp1);
-        reportClick("app", mApp2);
-        reportClick("app", mApp1);
-
-        assertShortcuts("expected app1 to beat app2 since it has more hits",
-                "app", mApp1, mApp2);
-
-        reportClick("app", mApp2);
-        reportClick("app", mApp2);
-
-        assertShortcuts("query 'app': expecting app2 to beat app1 since it has more hits",
-                "app", mApp2, mApp1);
-        assertShortcuts("query 'a': expecting app2 to beat app1 since it has more hits",
-                "a", mApp2, mApp1);
-    }
-
-    public void testMostRecentClickWins() {
-        // App 1 has 3 clicks
-        reportClick("app", mApp1, NOW - 5);
-        reportClick("app", mApp1, NOW - 5);
-        reportClick("app", mApp1, NOW - 5);
-        // App 2 has 2 clicks
-        reportClick("app", mApp2, NOW - 2);
-        reportClick("app", mApp2, NOW - 2);
-        // App 3 only has 1, but it's most recent
-        reportClick("app", mApp3, NOW - 1);
-
-        assertShortcuts("expected app3 to beat app1 and app2 because it's clicked last",
-                "app", mApp3, mApp1, mApp2);
-
-        reportClick("app", mApp2, NOW);
-
-        assertShortcuts("query 'app': expecting app2 to beat app1 since it's clicked last",
-                "app", mApp2, mApp1, mApp3);
-        assertShortcuts("query 'a': expecting app2 to beat app1 since it's clicked last",
-                "a", mApp2, mApp1, mApp3);
-        assertShortcuts("query '': expecting app2 to beat app1 since it's clicked last",
-                "", mApp2, mApp1, mApp3);
-    }
-
-    public void testMostRecentClickWinsOnEmptyQuery() {
-        reportClick("app", mApp1, NOW - 3);
-        reportClick("app", mApp1, NOW - 2);
-        reportClick("app", mApp2, NOW - 1);
-
-        assertShortcuts("expected app2 to beat app1 since it's clicked last", "",
-                mApp2, mApp1);
-    }
-
-    public void testMostRecentClickWinsEvenWithMoreThanLimitShortcuts() {
-        for (int i = 0; i < MAX_SHORTCUTS; i++) {
-            SuggestionData app = makeApp("TestApp" + i);
-            // Each of these shortcuts has two clicks
-            reportClick("app", app, NOW - 2);
-            reportClick("app", app, NOW - 1);
-        }
-
-        // mApp1 has only one click, but is more recent
-        reportClick("app", mApp1, NOW);
-
-        assertShortcutAtPosition(
-            "expecting app1 to beat all others since it's clicked last",
-            "app", 0, mApp1);
-    }
-
-    /**
-     * similar to {@link #testMoreClicksWins()} but clicks are reported with prefixes of the
-     * original query.  we want to make sure a match on query 'a' updates the stats for the
-     * entry it matched against, 'app'.
-     */
-    public void testPrefixMatchUpdatesSameEntry() {
-        reportClick("app", mApp1, NOW);
-        reportClick("app", mApp2, NOW);
-        reportClick("app", mApp1, NOW);
-
-        assertShortcuts("expected app1 to beat app2 since it has more hits",
-                "app", mApp1, mApp2);
-    }
-
-    private static final long DAY_MILLIS = 86400000L; // just ask the google
-    private static final long HOUR_MILLIS = 3600000L;
-
-    public void testMoreRecentlyClickedWins() {
-        reportClick("app", mApp1, NOW - DAY_MILLIS*2);
-        reportClick("app", mApp2, NOW);
-        reportClick("app", mApp3, NOW - DAY_MILLIS*4);
-
-        assertShortcuts("expecting more recently clicked app to rank higher",
-                "app", mApp2, mApp1, mApp3);
-    }
-
-    public void testMoreRecentlyClickedWinsSeconds() {
-        reportClick("app", mApp1, NOW - 10000);
-        reportClick("app", mApp2, NOW - 5000);
-        reportClick("app", mApp3, NOW);
-
-        assertShortcuts("expecting more recently clicked app to rank higher",
-                "app", mApp3, mApp2, mApp1);
-    }
-
-    public void testRecencyOverridesClicks() {
-
-        // 5 clicks, most recent half way through age limit
-        long halfWindow = mConfig.getMaxStatAgeMillis() / 2;
-        reportClick("app", mApp1, NOW - halfWindow);
-        reportClick("app", mApp1, NOW - halfWindow);
-        reportClick("app", mApp1, NOW - halfWindow);
-        reportClick("app", mApp1, NOW - halfWindow);
-        reportClick("app", mApp1, NOW - halfWindow);
-
-        // 3 clicks, the most recent very recent
-        reportClick("app", mApp2, NOW - HOUR_MILLIS);
-        reportClick("app", mApp2, NOW - HOUR_MILLIS);
-        reportClick("app", mApp2, NOW - HOUR_MILLIS);
-
-        assertShortcuts("expecting 3 recent clicks to beat 5 clicks long ago",
-                "app", mApp2, mApp1);
-    }
-
-    public void testEntryOlderThanAgeLimitFiltered() {
-        reportClick("app", mApp1);
-
-        long pastWindow = mConfig.getMaxStatAgeMillis() + 1000;
-        reportClick("app", mApp2, NOW - pastWindow);
-
-        assertShortcuts("expecting app2 not clicked on recently enough to be filtered",
-                "app", mApp1);
-    }
-
-    public void testZeroQueryResults_MoreClicksWins() {
-        reportClick("app", mApp1);
-        reportClick("app", mApp1);
-        reportClick("foo", mApp2);
-
-        assertShortcuts("", mApp1, mApp2);
-
-        reportClick("foo", mApp2);
-        reportClick("foo", mApp2);
-
-        assertShortcuts("", mApp2, mApp1);
-    }
-
-    public void testZeroQueryResults_DifferentQueryhitsCreditSameShortcut() {
-        reportClick("app", mApp1);
-        reportClick("foo", mApp2);
-        reportClick("bar", mApp2);
-
-        assertShortcuts("hits for 'foo' and 'bar' on app2 should have combined to rank it " +
-                "ahead of app1, which only has one hit.",
-                "", mApp2, mApp1);
-
-        reportClick("z", mApp1);
-        reportClick("2", mApp1);
-
-        assertShortcuts("", mApp1, mApp2);
-    }
-
-    public void testZeroQueryResults_zeroQueryHitCounts() {
-        reportClick("app", mApp1);
-        reportClick("", mApp2);
-        reportClick("", mApp2);
-
-        assertShortcuts("hits for '' on app2 should have combined to rank it " +
-                "ahead of app1, which only has one hit.",
-                "", mApp2, mApp1);
-
-        reportClick("", mApp1);
-        reportClick("", mApp1);
-
-        assertShortcuts("zero query hits for app1 should have made it higher than app2.",
-                "", mApp1, mApp2);
-
-        assertShortcuts("query for 'a' should only match app1.",
-                "a", mApp1);
-    }
-
-    public void testRefreshShortcut() {
-        final SuggestionData app1 = new SuggestionData(APP_SOURCE)
-                .setFormat("format")
-                .setText1("app1")
-                .setText2("cool app")
-                .setShortcutId("app1_id");
-
-        reportClick("app", app1);
-
-        final SuggestionData updated = new SuggestionData(APP_SOURCE)
-                .setFormat("format (updated)")
-                .setText1("app1 (updated)")
-                .setText2("cool app")
-                .setShortcutId("app1_id");
-
-        refreshShortcut(APP_SOURCE, "app1_id", updated);
-
-        assertShortcuts("expected updated properties in match",
-                "app", updated);
-    }
-
-    public void testRefreshShortcutChangedIntent() {
-
-        final SuggestionData app1 = new SuggestionData(APP_SOURCE)
-                .setIntentData("data")
-                .setFormat("format")
-                .setText1("app1")
-                .setText2("cool app")
-                .setShortcutId("app1_id");
-
-        reportClick("app", app1);
-
-        final SuggestionData updated = new SuggestionData(APP_SOURCE)
-                .setIntentData("data-updated")
-                .setFormat("format (updated)")
-                .setText1("app1 (updated)")
-                .setText2("cool app")
-                .setShortcutId("app1_id");
-
-        refreshShortcut(APP_SOURCE, "app1_id", updated);
-
-        assertShortcuts("expected updated properties in match",
-                "app", updated);
-    }
-
-    public void testInvalidateShortcut() {
-        final SuggestionData app1 = new SuggestionData(APP_SOURCE)
-                .setText1("app1")
-                .setText2("cool app")
-                .setShortcutId("app1_id");
-
-        reportClick("app", app1);
-
-        invalidateShortcut(APP_SOURCE, "app1_id");
-
-        assertNoShortcuts("should be no matches since shortcut is invalid.", "app");
-    }
-
-    public void testInvalidateShortcut_sameIdDifferentSources() {
-        final String sameid = "same_id";
-        final SuggestionData app = new SuggestionData(APP_SOURCE)
-                .setText1("app1")
-                .setText2("cool app")
-                .setShortcutId(sameid);
-        reportClick("app", app);
-        assertShortcuts("app should be there", "", app);
-
-        final SuggestionData contact = new SuggestionData(CONTACTS_SOURCE)
-                .setText1("joe blow")
-                .setText2("a good pal")
-                .setShortcutId(sameid);
-        reportClick("joe", contact);
-        reportClick("joe", contact);
-        assertShortcuts("app and contact should be there.", "", contact, app);
-
-        refreshShortcut(APP_SOURCE, sameid, null);
-        assertNoShortcuts("app should not be there.", "app");
-        assertShortcuts("contact with same shortcut id should still be there.",
-                "joe", contact);
-        assertShortcuts("contact with same shortcut id should still be there.",
-                "", contact);
-    }
-
-    public void testNeverMakeShortcut() {
-        final SuggestionData contact = new SuggestionData(CONTACTS_SOURCE)
-                .setText1("unshortcuttable contact")
-                .setText2("you didn't want to call them again anyway")
-                .setShortcutId(SearchManager.SUGGEST_NEVER_MAKE_SHORTCUT);
-        reportClick("unshortcuttable", contact);
-        assertNoShortcuts("never-shortcutted suggestion should not be there.", "unshortcuttable");
-    }
-
-    public void testCountResetAfterShortcutDeleted() {
-        reportClick("app", mApp1);
-        reportClick("app", mApp1);
-        reportClick("app", mApp1);
-        reportClick("app", mApp1);
-
-        reportClick("app", mApp2);
-        reportClick("app", mApp2);
-
-        // app1 wins 4 - 2
-        assertShortcuts("app", mApp1, mApp2);
-
-        // reset to 1
-        invalidateShortcut(APP_SOURCE, mApp1.getShortcutId());
-        reportClick("app", mApp1);
-
-        // app2 wins 2 - 1
-        assertShortcuts("expecting app1's click count to reset after being invalidated.",
-                "app", mApp2, mApp1);
-    }
-
-    public void testShortcutsAllowedCorpora() {
-        reportClick("a", mApp1);
-        reportClick("a", mContact1);
-
-        assertShortcuts("only allowed shortcuts should be returned",
-                "a", Arrays.asList(APP_CORPUS), mApp1);
-    }
-
-    //
-    // SOURCE RANKING TESTS BELOW
-    //
-
-    public void testSourceRanking_moreClicksWins() {
-        assertCorpusRanking("expected no ranking");
-
-        int minClicks = mConfig.getMinClicksForSourceRanking();
-
-        // click on an app
-        for (int i = 0; i < minClicks + 1; i++) {
-            reportClick("a", mApp1);
-        }
-        // fewer clicks on a contact
-        for (int i = 0; i < minClicks; i++) {
-            reportClick("a", mContact1);
-        }
-
-        assertCorpusRanking("expecting apps to rank ahead of contacts (more clicks)",
-                APP_CORPUS, CONTACTS_CORPUS);
-
-        // more clicks on a contact
-        reportClick("a", mContact1);
-        reportClick("a", mContact1);
-
-        assertCorpusRanking("expecting contacts to rank ahead of apps (more clicks)",
-                CONTACTS_CORPUS, APP_CORPUS);
-    }
-
-    public void testOldSourceStatsDontCount() {
-        // apps were popular back in the day
-        final long toOld = mConfig.getMaxStatAgeMillis() + 1;
-        int minClicks = mConfig.getMinClicksForSourceRanking();
-        for (int i = 0; i < minClicks; i++) {
-            reportClick("app", mApp1, NOW - toOld);
-        }
-
-        // and contacts is 1/2
-        for (int i = 0; i < minClicks; i++) {
-            reportClick("bob", mContact1, NOW);
-        }
-
-        assertCorpusRanking("old clicks for apps shouldn't count.",
-                CONTACTS_CORPUS);
-    }
-
-
-    public void testSourceRanking_filterSourcesWithInsufficientData() {
-        int minClicks = mConfig.getMinClicksForSourceRanking();
-        // not enough
-        for (int i = 0; i < minClicks - 1; i++) {
-            reportClick("app", mApp1);
-        }
-        // just enough
-        for (int i = 0; i < minClicks; i++) {
-            reportClick("bob", mContact1);
-        }
-
-        assertCorpusRanking(
-                "ordering should only include sources with at least " + minClicks + " clicks.",
-                CONTACTS_CORPUS);
-    }
-
-    // App upgrade tests
-
-    public void testAppUpgradeClearsShortcuts() {
-        reportClick("a", mApp1);
-        reportClick("add", mApp1);
-        reportClick("a", mContact1);
-
-        assertShortcuts("all shortcuts should be returned",
-                "a", mAllowedCorpora, mApp1, mContact1);
-
-        // Upgrade an existing corpus
-        MockCorpus upgradedCorpus = new MockCorpus(APP_SOURCE_V2);
-        mCorpora.addCorpus(upgradedCorpus);
-
-        List<Corpus> newAllowedCorpora = new ArrayList<Corpus>(mCorpora.getAllCorpora());
-        assertShortcuts("app shortcuts should be removed when the source was upgraded",
-                "a", newAllowedCorpora, mContact1);
-    }
-
-    public void testAppUpgradePromotesLowerRanked() {
-
-        ListSuggestionCursor expected = new ListSuggestionCursor("a");
-        for (int i = 0; i < MAX_SHORTCUTS + 1; i++) {
-            reportClick("app", mApp1, NOW);
-        }
-        expected.add(mApp1);
-
-        // Enough contact clicks to make one more shortcut than getMaxShortcutsReturned()
-        for (int i = 0; i < MAX_SHORTCUTS; i++) {
-            SuggestionData contact = makeContact("andy" + i);
-            int numClicks = MAX_SHORTCUTS - i;  // use click count to get shortcuts in order
-            for (int j = 0; j < numClicks; j++) {
-                reportClick("and", contact, NOW);
-            }
-            expected.add(contact);
-        }
-
-        // Expect the app, and then all contacts
-        assertShortcuts("app and all contacts should be returned",
-                "a", mAllowedCorpora, expected);
-
-        // Upgrade app corpus
-        MockCorpus upgradedCorpus = new MockCorpus(APP_SOURCE_V2);
-        mCorpora.addCorpus(upgradedCorpus);
-
-        // Expect all contacts
-        List<Corpus> newAllowedCorpora = new ArrayList<Corpus>(mCorpora.getAllCorpora());
-        assertShortcuts("app shortcuts should be removed when the source was upgraded "
-                + "and a contact should take its place",
-                "a", newAllowedCorpora, SuggestionCursorUtil.slice(expected, 1));
-    }
-
-    public void testIrrelevantAppUpgrade() {
-        reportClick("a", mApp1);
-        reportClick("add", mApp1);
-        reportClick("a", mContact1);
-
-        assertShortcuts("all shortcuts should be returned",
-                "a", mAllowedCorpora, mApp1, mContact1);
-
-        // Fire a corpus set update that affect no shortcuts corpus
-        MockCorpus newCorpus = new MockCorpus(new MockSource("newsource"));
-        mCorpora.addCorpus(newCorpus);
-
-        assertShortcuts("all shortcuts should be returned",
-                "a", mAllowedCorpora, mApp1, mContact1);
-    }
-
-    public void testAllowWebSearchShortcuts() {
-        reportClick("a", mApp1);
-        reportClick("a", mApp1);
-        reportClick("a", mWeb1);
-        assertShortcuts("web shortcuts should be included", "a",
-                mAllowedCorpora, true, mApp1, mWeb1);
-        assertShortcuts("web shortcuts should not be included", "a",
-                mAllowedCorpora, false, mApp1);
-    }
-
-    public void testExtraDataNull() {
-        assertExtra("Null extra", "extra_null", null);
-    }
-
-    public void testExtraDataString() {
-        assertExtra("String extra", "extra_string", "stringy-stringy-string");
-    }
-
-    public void testExtraDataInteger() {
-        assertExtra("Integer extra", "extra_int", new Integer(42));
-    }
-
-    public void testExtraDataFloat() {
-        assertExtra("Float extra", "extra_float", new Float(Math.PI));
-    }
-
-    public void testExtraDataStringWithDodgyChars() {
-        assertExtra("String extra with newlines", "extra_string", "line\nline\nline\n");
-        JSONArray a = new JSONArray();
-        a.put(true);
-        a.put(42);
-        a.put("hello");
-        a.put("hello \"again\"");
-        assertExtra("String extra with JSON", "extra_string", a.toString());
-        assertExtra("String extra with control chars", "extra_string", "\0\b\t\f\r");
-    }
-
-    // Utilities
-
-    protected ListSuggestionCursor makeCursor(String query, SuggestionData... suggestions) {
-        ListSuggestionCursor cursor = new ListSuggestionCursor(query);
-        for (SuggestionData suggestion : suggestions) {
-            cursor.add(suggestion);
-        }
-        return cursor;
-    }
-
-    protected void reportClick(String query, SuggestionData suggestion) {
-        reportClick(new ListSuggestionCursor(query, suggestion), 0);
-    }
-
-    protected void reportClick(String query, SuggestionData suggestion, long now) {
-        reportClickAtTime(new ListSuggestionCursor(query, suggestion), 0, now);
-    }
-
-    protected void reportClick(SuggestionCursor suggestions, int position) {
-        reportClickAtTime(suggestions, position, NOW);
-    }
-
-    protected void reportClickAtTime(SuggestionCursor suggestions, int position, long now) {
-        mRepo.reportClickAtTime(suggestions, position, now);
-        mLogExecutor.runNext();
-    }
-
-    protected void removeFromHistory(SuggestionCursor suggestions, int position) {
-        mRepo.removeFromHistory(suggestions, position);
-        mLogExecutor.runNext();
-    }
-
-    protected void invalidateShortcut(Source source, String shortcutId) {
-        refreshShortcut(source, shortcutId, null);
-    }
-
-    protected void refreshShortcut(Source source, String shortcutId, SuggestionData suggestion) {
-        SuggestionCursor refreshed =
-                suggestion == null ? null : new ListSuggestionCursor(null, suggestion);
-        mRepo.refreshShortcut(source, shortcutId, refreshed);
-        mLogExecutor.runNext();
-    }
-
-    protected void sourceImpressions(Source source, int clicks, int impressions) {
-        if (clicks > impressions) throw new IllegalArgumentException("ya moran!");
-
-        for (int i = 0; i < impressions; i++, clicks--) {
-            sourceImpression(source, clicks > 0);
-        }
-    }
-
-    /**
-     * Simulate an impression, and optionally a click, on a source.
-     *
-     * @param source The name of the source.
-     * @param click Whether to register a click in addition to the impression.
-     */
-    protected void sourceImpression(Source source, boolean click) {
-        sourceImpression(source, click, NOW);
-    }
-
-    protected SuggestionData sourceSuggestion(Source source) {
-        return new SuggestionData(source)
-            .setIntentAction("view")
-            .setIntentData("data/id")
-            .setShortcutId("shortcutid");
-    }
-
-    /**
-     * Simulate an impression, and optionally a click, on a source.
-     *
-     * @param source The name of the source.
-     * @param click Whether to register a click in addition to the impression.
-     */
-    protected void sourceImpression(Source source, boolean click, long now) {
-        SuggestionData suggestionClicked = !click ?
-                null : sourceSuggestion(source);
-
-        reportClick("a", suggestionClicked);
-    }
-
-    void assertNoShortcuts(String query) {
-        assertNoShortcuts("", query);
-    }
-
-    void assertNoShortcuts(String message, String query) {
-        SuggestionCursor cursor = getShortcuts(query, mAllowedCorpora);
-        try {
-            assertNull(message + ", got shortcuts", cursor);
-        } finally {
-            if (cursor != null) cursor.close();
-        }
-    }
-
-    void assertShortcuts(String query, SuggestionData... expected) {
-        assertShortcuts("", query, expected);
-    }
-
-    void assertShortcutAtPosition(String message, String query,
-            int position, SuggestionData expected) {
-        SuggestionCursor cursor = getShortcuts(query, mAllowedCorpora);
-        try {
-            SuggestionCursor expectedCursor = new ListSuggestionCursor(query, expected);
-            SuggestionCursorUtil.assertSameSuggestion(message, position, expectedCursor, cursor);
-        } finally {
-            if (cursor != null) cursor.close();
-        }
-    }
-
-    void assertShortcutCount(String message, String query, int expectedCount) {
-        SuggestionCursor cursor = getShortcuts(query, mAllowedCorpora);
-        try {
-            assertEquals(message, expectedCount, cursor.getCount());
-        } finally {
-            if (cursor != null) cursor.close();
-        }
-    }
-
-    void assertShortcuts(String message, String query, Collection<Corpus> allowedCorpora,
-            boolean allowWebSearchShortcuts, SuggestionCursor expected) {
-        SuggestionCursor cursor = mRepo.getShortcutsForQuery(query, allowedCorpora, allowWebSearchShortcuts, NOW);
-        try {
-            SuggestionCursorUtil.assertSameSuggestions(message, expected, cursor);
-        } finally {
-            if (cursor != null) cursor.close();
-        }
-    }
-
-    void assertShortcuts(String message, String query, Collection<Corpus> allowedCorpora,
-            SuggestionCursor expected) {
-        assertShortcuts(message, query, allowedCorpora, true, expected);
-    }
-
-    SuggestionCursor getShortcuts(String query, Collection<Corpus> allowedCorpora) {
-        return mRepo.getShortcutsForQuery(query, allowedCorpora, true, NOW);
-    }
-
-    void assertShortcuts(String message, String query, Collection<Corpus> allowedCorpora,
-            boolean allowWebSearchShortcuts, SuggestionData... expected) {
-        assertShortcuts(message, query, allowedCorpora, allowWebSearchShortcuts,
-                new ListSuggestionCursor(query, expected));
-    }
-
-    void assertShortcuts(String message, String query, Collection<Corpus> allowedCorpora,
-            SuggestionData... expected) {
-        assertShortcuts(message, query, allowedCorpora, new ListSuggestionCursor(query, expected));
-    }
-
-    void assertShortcuts(String message, String query, SuggestionData... expected) {
-        assertShortcuts(message, query, mAllowedCorpora, expected);
-    }
-
-    private void assertHasHistory(boolean expected) {
-        ConsumerTrap<Boolean> trap = new ConsumerTrap<Boolean>();
-        mRepo.hasHistory(trap);
-        mLogExecutor.runNext();
-        assertEquals("hasHistory() returned bad value", expected, (boolean) trap.getValue());
-    }
-
-    void assertCorpusRanking(String message, Corpus... expected) {
-        String[] expectedNames = new String[expected.length];
-        for (int i = 0; i < expected.length; i++) {
-            expectedNames[i] = expected[i].getName();
-        }
-        Map<String,Integer> scores = getCorpusScores();
-        List<String> observed = sortByValues(scores);
-        // Highest scores should come first
-        Collections.reverse(observed);
-        Log.d(TAG, "scores=" + scores);
-        MoreAsserts.assertContentsInOrder(message, observed, (Object[]) expectedNames);
-    }
-
-    private Map<String,Integer> getCorpusScores() {
-        ConsumerTrap<Map<String,Integer>> trap = new ConsumerTrap<Map<String,Integer>>();
-        mRepo.getCorpusScores(trap);
-        mLogExecutor.runNext();
-        return trap.getValue();
-    }
-
-    static <A extends Comparable<A>, B extends Comparable<B>> List<A> sortByValues(Map<A,B> map) {
-        Comparator<Map.Entry<A,B>> comp = new Comparator<Map.Entry<A,B>>() {
-            public int compare(Entry<A, B> object1, Entry<A, B> object2) {
-                int diff = object1.getValue().compareTo(object2.getValue());
-                if (diff != 0) {
-                    return diff;
-                } else {
-                    return object1.getKey().compareTo(object2.getKey());
-                }
-            }
-        };
-        ArrayList<Map.Entry<A,B>> sorted = new ArrayList<Map.Entry<A,B>>(map.size());
-        sorted.addAll(map.entrySet());
-        Collections.sort(sorted, comp);
-        ArrayList<A> out = new ArrayList<A>(sorted.size());
-        for (Map.Entry<A,B> e : sorted) {
-            out.add(e.getKey());
-        }
-        return out;
-    }
-
-    static void assertContentsInOrder(Iterable<?> actual, Object... expected) {
-        MoreAsserts.assertContentsInOrder(null, actual, expected);
-    }
-
-    void assertExtra(String message, String extraColumn, Object extraValue) {
-        SuggestionData s = sourceSuggestion(APP_SOURCE);
-        s.setExtras(new MockSuggestionExtras().put(extraColumn, extraValue));
-        reportClick("a", s);
-        assertShortcutExtra(message, "a", extraColumn, extraValue);
-    }
-
-    void assertShortcutExtra(String message, String query, String extraColumn, Object extraValue) {
-        SuggestionCursor cursor = getShortcuts(query, mAllowedCorpora);
-        try {
-            SuggestionCursorUtil.assertSuggestionExtras(message, cursor, extraColumn, extraValue);
-        } finally {
-            if (cursor != null) cursor.close();
-        }
-    }
-
-}
diff --git a/tests/src/com/android/quicksearchbox/ShouldQueryStrategyTest.java b/tests/src/com/android/quicksearchbox/ShouldQueryStrategyTest.java
deleted file mode 100644
index 03472dc..0000000
--- a/tests/src/com/android/quicksearchbox/ShouldQueryStrategyTest.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-/**
- * Tests for {@link ShouldQueryStrategy}.
- */
-@SmallTest
-public class ShouldQueryStrategyTest extends AndroidTestCase {
-
-    private ShouldQueryStrategy mShouldQuery;
-
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        mShouldQuery = new ShouldQueryStrategy(new Config(getContext()){
-            @Override
-            public boolean showSuggestionsForZeroQuery() {
-                return true;
-            }
-            @Override
-            public boolean showShortcutsForZeroQuery() {
-                return true;
-            }});
-    }
-
-    public static final Corpus CORPUS_1 = new MockCorpus(MockSource.SOURCE_1) {
-        @Override
-        public int getQueryThreshold() {
-            return 3;
-        }
-    };
-
-    public static final Corpus CORPUS_2 = new MockCorpus(MockSource.SOURCE_2) {
-        @Override
-        public boolean queryAfterZeroResults() {
-            return true;
-        }
-    };
-
-    public void testRespectsQueryThreshold() {
-        assertFalse(mShouldQuery.shouldQueryCorpus(CORPUS_1, "aa"));
-        assertTrue(mShouldQuery.shouldQueryCorpus(CORPUS_1, "aaa"));
-        assertTrue(mShouldQuery.shouldQueryCorpus(CORPUS_2, ""));
-    }
-
-    public void testQueriesAfterNoResultsWhenQueryAfterZeroIsTrue() {
-        assertTrue(mShouldQuery.shouldQueryCorpus(CORPUS_2, "query"));
-        mShouldQuery.onZeroResults(CORPUS_2, "query");
-        assertTrue(mShouldQuery.shouldQueryCorpus(CORPUS_2, "query"));
-        assertTrue(mShouldQuery.shouldQueryCorpus(CORPUS_2, "query123"));
-    }
-
-    public void testDoesntQueryLongerAfterNoResults() {
-        assertTrue(mShouldQuery.shouldQueryCorpus(CORPUS_1, "query"));
-        mShouldQuery.onZeroResults(CORPUS_1, "query");
-        // Now we don't query for queries starting with "query"
-        assertFalse(mShouldQuery.shouldQueryCorpus(CORPUS_1, "queryx"));
-        assertFalse(mShouldQuery.shouldQueryCorpus(CORPUS_1, "queryxy"));
-    }
-
-    public void testDoesntQuerySameAfterNoResults() {
-        assertTrue(mShouldQuery.shouldQueryCorpus(CORPUS_1, "query"));
-        mShouldQuery.onZeroResults(CORPUS_1, "query");
-        // Now we don't query for "query"
-        assertFalse(mShouldQuery.shouldQueryCorpus(CORPUS_1, "query"));
-    }
-
-    public void testQueriesDifferent() {
-        assertTrue(mShouldQuery.shouldQueryCorpus(CORPUS_1, "query"));
-        mShouldQuery.onZeroResults(CORPUS_1, "query");
-        // Now we do query for "queen"
-        assertTrue(mShouldQuery.shouldQueryCorpus(CORPUS_1, "queen"));
-        mShouldQuery.onZeroResults(CORPUS_1, "queen");
-        // And then not for "queens"
-        assertFalse(mShouldQuery.shouldQueryCorpus(CORPUS_1, "queens"));
-    }
-
-    public void testShorterThenDifferent() {
-        assertTrue(mShouldQuery.shouldQueryCorpus(CORPUS_1, "query"));
-        mShouldQuery.onZeroResults(CORPUS_1, "query");
-        // Should query for shorter
-        assertTrue(mShouldQuery.shouldQueryCorpus(CORPUS_1, "que"));
-        mShouldQuery.onZeroResults(CORPUS_1, "que");
-        // But not for longer after that
-        assertFalse(mShouldQuery.shouldQueryCorpus(CORPUS_1, "queen"));
-    }
-
-    public void testQueriesForShorterAfterNoResults() {
-        assertTrue(mShouldQuery.shouldQueryCorpus(CORPUS_1, "query"));
-        mShouldQuery.onZeroResults(CORPUS_1, "query");
-        // We do query for something shorter
-        assertTrue(mShouldQuery.shouldQueryCorpus(CORPUS_1, "quer"));
-    }
-
-    public void testOutOfOrder1() {
-        assertTrue(mShouldQuery.shouldQueryCorpus(CORPUS_1, "quer"));
-        // Result for something typed earlier comes in
-        mShouldQuery.onZeroResults(CORPUS_1, "que");
-        // Now we don't query for the original
-        assertFalse(mShouldQuery.shouldQueryCorpus(CORPUS_1, "quer"));
-    }
-
-    public void testOutOfOrder2() {
-        assertTrue(mShouldQuery.shouldQueryCorpus(CORPUS_1, "quer"));
-        // Result for something typed earlier comes in
-        mShouldQuery.onZeroResults(CORPUS_1, "que");
-        // Now we don't query for an extension of the original
-        assertFalse(mShouldQuery.shouldQueryCorpus(CORPUS_1, "query"));
-    }
-}
diff --git a/tests/src/com/android/quicksearchbox/SingleCorpusPromoterTest.java b/tests/src/com/android/quicksearchbox/SingleCorpusPromoterTest.java
deleted file mode 100644
index 21c4baa..0000000
--- a/tests/src/com/android/quicksearchbox/SingleCorpusPromoterTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Tests for SingleCorpusPromoter.
- */
-@SmallTest
-public class SingleCorpusPromoterTest extends AndroidTestCase {
-    public static final String TEST_QUERY = "query";
-
-    private List<Corpus> mCorpora = Arrays.asList(MockCorpus.CORPUS_1, MockCorpus.CORPUS_2);
-    private SingleCorpusPromoter mPromoter;
-
-    @Override
-    public void setUp() {
-        mPromoter = new SingleCorpusPromoter(MockCorpus.CORPUS_1, 10);
-    }
-
-    public void testPromotesOnlyGivenCorpus() {
-        Suggestions suggestions = makeSuggestions(TEST_QUERY);
-
-        ListSuggestionCursor promoted = new ListSuggestionCursor(TEST_QUERY);
-        mPromoter.pickPromoted(suggestions, 4, promoted);
-
-        assertEquals(2, promoted.getCount());
-
-        Source[] expectedSource = { MockSource.SOURCE_1, MockSource.SOURCE_1 };
-
-        for (int i = 0; i < promoted.getCount(); i++) {
-            promoted.moveTo(i);
-            assertEquals("Source in position " + i,
-                    expectedSource[i], promoted.getSuggestionSource());
-        }
-    }
-
-    private Suggestions makeSuggestions(String query) {
-        Suggestions suggestions = new Suggestions(query, mCorpora);
-        ArrayList<CorpusResult> results = new ArrayList<CorpusResult>();
-        for (Corpus corpus : mCorpora) {
-            results.add(corpus.getSuggestions(query, 10, false));
-        }
-        suggestions.addCorpusResults(results);
-        return suggestions;
-    }
-
-}
diff --git a/tests/src/com/android/quicksearchbox/SourceShortcutRefresherTest.java b/tests/src/com/android/quicksearchbox/SourceShortcutRefresherTest.java
deleted file mode 100644
index a16642c..0000000
--- a/tests/src/com/android/quicksearchbox/SourceShortcutRefresherTest.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import com.android.quicksearchbox.util.MockNamedTaskExecutor;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-
-/**
- * Tests for {@link SourceShortcutRefresher}.
- */
-@MediumTest
-public class SourceShortcutRefresherTest extends AndroidTestCase {
-
-    private final String mQuery = "foo";
-
-    private MockNamedTaskExecutor mExecutor;
-
-    private SourceShortcutRefresher mRefresher;
-
-    private RefreshListener mListener;
-
-    private Source mSource1;
-
-    private Source mRefreshedSource;
-    private String mRefreshedShortcutId;
-    private SuggestionCursor mRefreshedCursor;
-
-    @Override
-    protected void setUp() throws Exception {
-        mExecutor = new MockNamedTaskExecutor();
-        mRefresher = new SourceShortcutRefresher(mExecutor);
-        mListener = new RefreshListener();
-        mSource1 = new MockRefreshSource("source1");
-        mRefreshedSource = null;
-        mRefreshedShortcutId = null;
-        mRefreshedCursor = null;
-    }
-
-    public void testShouldRefreshTrue() {
-        assertTrue(mRefresher.shouldRefresh(mSource1, "refresh_me"));
-    }
-
-    public void testShouldRefreshFalse() {
-        assertFalse(mRefresher.shouldRefresh(null, "foo"));
-        assertFalse(mRefresher.shouldRefresh(mSource1, null));
-    }
-
-    public void testMarkShortcutRefreshed() {
-        mRefresher.markShortcutRefreshed(mSource1, "refreshed");
-        assertFalse(mRefresher.shouldRefresh(mSource1, "refreshed"));
-        assertTrue(mRefresher.shouldRefresh(mSource1, "not_refreshed"));
-    }
-
-    public void testRefreshNull() {
-        SuggestionData shortcut1 = new SuggestionData(mSource1)
-                .setShortcutId("null_refresh");
-        ListSuggestionCursor shortcuts = new ListSuggestionCursor(mQuery, shortcut1);
-        mRefresher.refresh(shortcuts, mListener);
-        assertTrue(mExecutor.runNext());
-        assertEquals(mSource1, mRefreshedSource);
-        assertEquals("null_refresh", mRefreshedShortcutId);
-        assertEquals(null, mRefreshedCursor);
-    }
-
-    public void testRefreshEmpty() {
-        SuggestionData shortcut1 = new SuggestionData(mSource1)
-                .setShortcutId("empty_refresh");
-        ListSuggestionCursor shortcuts = new ListSuggestionCursor(mQuery, shortcut1);
-        mRefresher.refresh(shortcuts, mListener);
-        assertTrue(mExecutor.runNext());
-        assertEquals(mSource1, mRefreshedSource);
-        assertEquals("empty_refresh", mRefreshedShortcutId);
-        assertEquals(null, mRefreshedCursor);
-    }
-
-    public void testRefreshSuccess() {
-        SuggestionData shortcut1 = new SuggestionData(mSource1)
-                .setShortcutId("success");
-        ListSuggestionCursor shortcuts = new ListSuggestionCursor(mQuery, shortcut1);
-        mRefresher.refresh(shortcuts, mListener);
-        assertTrue(mExecutor.runNext());
-        assertEquals(mSource1, mRefreshedSource);
-        assertEquals("success", mRefreshedShortcutId);
-        SuggestionCursor expected =
-                SuggestionCursorUtil.slice(mSource1.getSuggestions(mQuery, 1, true), 0, 1);
-        SuggestionCursorUtil.assertSameSuggestions(expected, mRefreshedCursor);
-    }
-
-    private class RefreshListener implements ShortcutRefresher.Listener {
-        public void onShortcutRefreshed(Source source, String shortcutId,
-                SuggestionCursor refreshed) {
-            mRefreshedSource = source;
-            mRefreshedShortcutId = shortcutId;
-            mRefreshedCursor = refreshed;
-        }
-    }
-
-    private class MockRefreshSource extends MockSource {
-        public MockRefreshSource(String name) {
-            super(name);
-        }
-
-        @Override
-        public SuggestionCursor refreshShortcut(String shortcutId, String extraData) {
-            if ("null_refresh".equals(shortcutId)) {
-                return null;
-            } else if ("empty_refresh".equals(shortcutId)) {
-                return new ListSuggestionCursor(mQuery);
-            } else {
-                 SuggestionCursor suggestions = getSuggestions(mQuery, 1, true);
-                 return SuggestionCursorUtil.slice(suggestions, 0, 1);
-            }
-        }
-    }
-
-}
diff --git a/tests/src/com/android/quicksearchbox/SuggestionCursorWithExtrasTest.java b/tests/src/com/android/quicksearchbox/SuggestionCursorWithExtrasTest.java
deleted file mode 100644
index d820c3a..0000000
--- a/tests/src/com/android/quicksearchbox/SuggestionCursorWithExtrasTest.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import android.app.SearchManager;
-import android.database.Cursor;
-import android.test.AndroidTestCase;
-
-import java.util.Arrays;
-import java.util.HashSet;
-
-/**
- * Tests to verify that custom columns from a suggestion cursor get propagated through QSB properly.
- */
-public class SuggestionCursorWithExtrasTest extends AndroidTestCase {
-
-    public void testSuggestionCursorExtraRowString() {
-        checkSuggestionCursorExtraColumnValue("extra_text", "Extra text");
-    }
-
-    public void testSuggestionCursorExtraRowInteger() {
-        checkSuggestionCursorExtraColumnValue("extra_int", 42);
-    }
-
-    public void testSuggestionCursorExtraRowFloat() {
-        checkSuggestionCursorExtraColumnValue("extra_float", new Float(Math.E));
-    }
-
-    public void testSuggestionCursorExtraRowNull() {
-        checkSuggestionCursorExtraColumnValue("extra_null", null);
-    }
-
-    public void testCursorExtraRowString() {
-        checkExtraRowString("stringy-string");
-        checkExtraRowString("");
-        checkExtraRowString(null);
-    }
-
-    private void checkExtraRowString(String value) {
-        String column = "extra_string";
-        Cursor c = createCursorWithExtras(column, value);
-        assertEquals("Extra column value", value, c.getString(c.getColumnIndex(column)));
-    }
-
-    public void testCursorExtraRowInt() {
-        checkCursorExtraInt(42);
-        checkCursorExtraInt(0);
-        checkCursorExtraInt(-42);
-        checkCursorExtraInt(Integer.MAX_VALUE);
-        checkCursorExtraInt(Integer.MIN_VALUE);
-    }
-
-    public void checkCursorExtraInt(int value) {
-        String column = "extra_int";
-        Cursor c = createCursorWithExtras(column, value);
-        assertEquals("Extra column value", value, c.getInt(c.getColumnIndex(column)));
-    }
-
-    public void testCursorExtraRowDouble() {
-        checkCursorExtraRowDouble(Math.PI);
-        checkCursorExtraRowDouble(-Math.PI);
-        checkCursorExtraRowDouble(0);
-        checkCursorExtraRowDouble(Double.MAX_VALUE);
-        checkCursorExtraRowDouble(Double.MIN_VALUE);
-    }
-
-    public void checkCursorExtraRowDouble(double value) {
-        String column = "extra_double";
-        Cursor c = createCursorWithExtras(column, value);
-        assertEquals("Extra column value", value, c.getDouble(c.getColumnIndex(column)));
-    }
-
-    public void testCursorExtraRowFloat() {
-        checkCursorExtraRowFloat((float) Math.E);
-        checkCursorExtraRowFloat((float) -Math.E);
-        checkCursorExtraRowFloat(0f);
-        checkCursorExtraRowFloat(Float.MAX_VALUE);
-        checkCursorExtraRowFloat(Float.MIN_VALUE);
-    }
-
-    public void checkCursorExtraRowFloat(float value) {
-        String column = "extra_float";
-        Cursor c = createCursorWithExtras(column, value);
-        assertEquals("Extra column value", value, c.getFloat(c.getColumnIndex(column)));
-    }
-
-    public void testCursorExtraRowLong() {
-        checkExtraRowLong(0xfeed0beefl);
-        checkExtraRowLong(-0xfeed0beefl);
-        checkExtraRowLong(0);
-        checkExtraRowLong(Long.MIN_VALUE);
-        checkExtraRowLong(Long.MAX_VALUE);
-    }
-
-    private void checkExtraRowLong(long value) {
-        String column = "extra_long";
-        Cursor c = createCursorWithExtras(column, value);
-        assertEquals("Extra column value", value, c.getLong(c.getColumnIndex(column)));
-    }
-
-    public void testCursorExtraRowShort() {
-        checkCursorExtraRowShort((short) 0xabc);
-        checkCursorExtraRowShort((short) -0xabc);
-        checkCursorExtraRowShort((short) 0);
-        checkCursorExtraRowShort(Short.MAX_VALUE);
-        checkCursorExtraRowShort(Short.MIN_VALUE);
-    }
-
-    private void checkCursorExtraRowShort(short value) {
-        String column = "extra_short";
-        Cursor c = createCursorWithExtras(column, value);
-        assertEquals("Extra column value", value, c.getShort(c.getColumnIndex(column)));
-    }
-
-    private Cursor createCursorWithExtras(String columnName, Object columnValue) {
-        MockSuggestionProviderCursor expectedCursor = new MockSuggestionProviderCursor(
-                new String[]{"_id",   SearchManager.SUGGEST_COLUMN_TEXT_1, columnName });
-        expectedCursor.addRow(       0,       "Text 1",                            columnValue);
-
-        // this roughly approcimates what happens to suggestions
-        CursorBackedSourceResult suggestions = new CursorBackedSourceResult(
-                MockSource.SOURCE_1, "", expectedCursor);
-        assertEquals("Number of suggestions", 1, suggestions.getCount());
-        suggestions.moveTo(0);
-        SuggestionCursorBackedCursor observedCursor = new SuggestionCursorBackedCursor(suggestions);
-
-        assertEquals("Cursor rows", 1, observedCursor.getCount());
-        HashSet<String> rows = new HashSet<String>();
-        rows.addAll(Arrays.asList(observedCursor.getColumnNames()));
-        assertTrue("Extra column present in cursor", rows.contains(columnName));
-        observedCursor.moveToFirst();
-        return observedCursor;
-    }
-
-    private void checkSuggestionCursorExtraColumnValue(String columnName, Object columnValue) {
-        MockSuggestionProviderCursor cursor = new MockSuggestionProviderCursor(
-                new String[]{"_id",   SearchManager.SUGGEST_COLUMN_TEXT_1, columnName });
-        cursor.addRow(       0,       "Text 1",                            columnValue);
-
-        CursorBackedSourceResult suggestions = new CursorBackedSourceResult(
-                MockSource.SOURCE_1, "", cursor);
-
-        assertEquals("Suggestions count matches cursor count",
-                cursor.getCount(), suggestions.getCount());
-
-        cursor.moveToFirst();
-        suggestions.moveTo(0);
-
-        SuggestionExtras extras = suggestions.getExtras();
-        assertNotNull("Suggestions extras", extras);
-        assertTrue("Extra column missing", extras.getExtraColumnNames().contains(columnName));
-        assertTrue("Spurious columns", extras.getExtraColumnNames().size() == 1);
-        Object extraValue = extras.getExtra(columnName);
-        if (columnValue == null) {
-            assertEquals("Wrong extra value", columnValue, extraValue);
-        } else {
-            assertNotNull("Extra value null", extraValue);
-            if (columnValue == null) {
-                assertEquals("Extra value wrong", columnValue, extraValue);
-            } else {
-                assertEquals("Extra value wrong", columnValue.toString(), extraValue);
-            }
-        }
-    }
-
-}
diff --git a/tests/src/com/android/quicksearchbox/SuggestionsProviderImplTest.java b/tests/src/com/android/quicksearchbox/SuggestionsProviderImplTest.java
deleted file mode 100644
index 3e12c4c..0000000
--- a/tests/src/com/android/quicksearchbox/SuggestionsProviderImplTest.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import com.android.quicksearchbox.util.MockNamedTaskExecutor;
-
-import android.os.Handler;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Tests for {@link SuggestionsProviderImpl}.
- */
-@MediumTest
-public class SuggestionsProviderImplTest extends AndroidTestCase {
-
-    private List<Corpus> mCorpora;
-    private MockNamedTaskExecutor mTaskExecutor;
-    private SuggestionsProviderImpl mProvider;
-    private MockShortcutRepository mShortcutRepo;
-
-    @Override
-    protected void setUp() throws Exception {
-        Config config = new Config(getContext());
-        mTaskExecutor = new MockNamedTaskExecutor();
-        Handler publishThread = new MockHandler();
-        mShortcutRepo = new MockShortcutRepository();
-        mCorpora = new ArrayList<Corpus>();
-        mCorpora.add(MockCorpus.CORPUS_1);
-        mCorpora.add(MockCorpus.CORPUS_2);
-        Logger logger = new MockLogger();
-        mProvider = new SuggestionsProviderImpl(config,
-                mTaskExecutor,
-                publishThread,
-                logger);
-    }
-
-    public void testSingleCorpus() {
-        Suggestions suggestions = mProvider.getSuggestions("foo",
-                Collections.singletonList(MockCorpus.CORPUS_1));
-        suggestions.setShortcuts(mShortcutRepo.getShortcutsForQuery(
-                "foo", mCorpora));
-        try {
-            assertEquals(1, suggestions.getExpectedResultCount());
-            assertEquals(0, suggestions.getResultCount());
-            assertEquals(0, promote(suggestions).getCount());
-            assertTrue(mTaskExecutor.runNext());
-            assertEquals(1, suggestions.getExpectedResultCount());
-            assertEquals(1, suggestions.getResultCount());
-            assertEquals(MockCorpus.CORPUS_1.getSuggestions("foo", 3, true).getCount(),
-                    promote(suggestions).getCount());
-            mTaskExecutor.assertDone();
-        } finally {
-            if (suggestions != null) suggestions.release();
-        }
-    }
-
-    public void testMultipleCorpora() {
-        Suggestions suggestions = mProvider.getSuggestions("foo",
-                Arrays.asList(MockCorpus.CORPUS_1, MockCorpus.CORPUS_2));
-        suggestions.setShortcuts(mShortcutRepo.getShortcutsForQuery(
-                        "foo", mCorpora));
-        try {
-            int corpus1Count = MockCorpus.CORPUS_1.getSuggestions("foo", 3, true).getCount();
-            int corpus2Count = MockCorpus.CORPUS_2.getSuggestions("foo", 3, true).getCount();
-            assertEquals(mCorpora.size(), suggestions.getExpectedResultCount());
-            assertEquals(0, suggestions.getResultCount());
-            assertEquals(0, promote(suggestions).getCount());
-            assertTrue(mTaskExecutor.runNext());
-            assertEquals(1, suggestions.getResultCount());
-            assertEquals("Incorrect promoted: " + promote(suggestions),
-                    corpus1Count, promote(suggestions).getCount());
-            assertTrue(mTaskExecutor.runNext());
-            assertEquals(2, suggestions.getResultCount());
-            assertEquals("Incorrect promoted: " + promote(suggestions),
-                    corpus1Count + corpus2Count, promote(suggestions).getCount());
-            mTaskExecutor.assertDone();
-        } finally {
-            if (suggestions != null) suggestions.release();
-        }
-    }
-
-    private SuggestionCursor promote(Suggestions suggestions) {
-        return suggestions.getPromoted(new ConcatPromoter(), 10);
-    }
-
-    private static class ConcatPromoter implements Promoter {
-        public void pickPromoted(Suggestions suggestions, int maxPromoted,
-                ListSuggestionCursor promoted) {
-            // Add suggestions
-            for (SuggestionCursor c : suggestions.getCorpusResults()) {
-                for (int i = 0; i < c.getCount(); i++) {
-                    if (promoted.getCount() >= maxPromoted) {
-                        return;
-                    }
-                    promoted.add(new SuggestionPosition(c, i));
-                }
-            }
-        }
-    }
-
-}
diff --git a/tests/src/com/android/quicksearchbox/SuggestionsTest.java b/tests/src/com/android/quicksearchbox/SuggestionsTest.java
deleted file mode 100644
index 281cf6d..0000000
--- a/tests/src/com/android/quicksearchbox/SuggestionsTest.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2009 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.quicksearchbox;
-
-import com.android.quicksearchbox.util.MockDataSetObserver;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Tests for {@link Suggestions}.
- *
- */
-@SmallTest
-public class SuggestionsTest extends AndroidTestCase {
-
-    private Suggestions mSuggestions;
-    private MockDataSetObserver mObserver;
-    private List<Corpus> mExpectedCorpora;
-
-    @Override
-    protected void setUp() throws Exception {
-        mExpectedCorpora = Arrays.asList(MockCorpus.CORPUS_1, MockCorpus.WEB_CORPUS);
-        mSuggestions = new Suggestions("foo", mExpectedCorpora);
-        mObserver = new MockDataSetObserver();
-        mSuggestions.registerDataSetObserver(mObserver);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        mSuggestions.release();
-        mSuggestions = null;
-    }
-
-    public void testGetExpectedResultCount() {
-        assertEquals(mExpectedCorpora.size(), mSuggestions.getExpectedResultCount());
-    }
-
-    public void testGetExpectedCorpora() {
-        List<Corpus> expectedCorpora = mSuggestions.getExpectedCorpora();
-        assertEquals(mExpectedCorpora.size(), expectedCorpora.size());
-        for (int i=0; i<mExpectedCorpora.size(); ++i) {
-            assertEquals(mExpectedCorpora.get(i), expectedCorpora.get(i));
-        }
-    }
-
-    public void testExpectsCorpus() {
-        for (int i=0; i<mExpectedCorpora.size(); ++i) {
-            assertTrue(mSuggestions.expectsCorpus(mExpectedCorpora.get(i)));
-        }
-        assertFalse(mSuggestions.expectsCorpus(MockCorpus.CORPUS_2));
-    }
-
-    public void testGetUserQuery() {
-        assertEquals("foo", mSuggestions.getQuery());
-    }
-
-    public void testGetIncludedCorpora() {
-        Corpus corpus = MockCorpus.CORPUS_1;
-        mSuggestions.addCorpusResults(
-                Collections.singletonList(corpus.getSuggestions("foo", 50, true)));
-        Set<Corpus> includedCorpora = mSuggestions.getIncludedCorpora();
-        assertEquals(includedCorpora.size(), 1);
-        assertTrue(includedCorpora.contains(corpus));
-    }
-
-    public void testObserverNotified() {
-        Corpus corpus = MockCorpus.CORPUS_1;
-        mObserver.assertNotChanged();
-        mObserver.assertNotInvalidated();
-        mSuggestions.addCorpusResults(
-                Collections.singletonList(corpus.getSuggestions("foo", 50, true)));
-        mObserver.assertChanged();
-        mObserver.assertNotInvalidated();
-    }
-
-}
diff --git a/tests/src/com/android/quicksearchbox/WebPromoterTest.java b/tests/src/com/android/quicksearchbox/WebPromoterTest.java
deleted file mode 100644
index 18e4c2d..0000000
--- a/tests/src/com/android/quicksearchbox/WebPromoterTest.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2010 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.quicksearchbox;
-
-import static com.android.quicksearchbox.SuggestionCursorUtil.assertSameSuggestions;
-import static com.android.quicksearchbox.SuggestionCursorUtil.concat;
-import static com.android.quicksearchbox.SuggestionCursorUtil.iterable;
-import static com.android.quicksearchbox.SuggestionCursorUtil.slice;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Tests for {@link WebPromoter}.
- */
-@MediumTest
-public class WebPromoterTest extends AndroidTestCase {
-
-    private String mQuery;
-
-    private Suggestion mS11;
-    private Suggestion mS12;
-    private Suggestion mS21;
-    private Suggestion mS22;
-    private Suggestion mWeb1;
-    private Suggestion mWeb2;
-
-    private CorpusResult mCorpusResult1;
-    private CorpusResult mCorpusResult2;
-    private CorpusResult mCorpusResultWeb;
-
-    private SuggestionCursor mShortcuts;
-    private List<CorpusResult> mCorpusResults;
-    private Suggestions mSuggestions;
-
-    @Override
-    protected void setUp() throws Exception {
-        mQuery = "foo";
-        mS11 = MockSource.SOURCE_1.createSuggestion(mQuery + "_1_1");
-        mS12 = MockSource.SOURCE_1.createSuggestion(mQuery + "_1_2");
-        mS21 = MockSource.SOURCE_2.createSuggestion(mQuery + "_1_1");
-        mS22 = MockSource.SOURCE_2.createSuggestion(mQuery + "_1_2");
-        mWeb1 = MockSource.WEB_SOURCE.createSuggestion(mQuery + "_web_1");
-        mWeb2 = MockSource.WEB_SOURCE.createSuggestion(mQuery + "_web_2");
-        mShortcuts = cursor(mS11, mS12, mS21, mS22, mWeb1, mWeb2);
-        mCorpusResult1 = MockCorpus.CORPUS_1.getSuggestions(mQuery, 10, false);
-        mCorpusResult2 = MockCorpus.CORPUS_2.getSuggestions(mQuery, 10, false);
-        mCorpusResultWeb = MockCorpus.WEB_CORPUS.getSuggestions(mQuery, 10, false);
-        mCorpusResults = new ArrayList<CorpusResult>();
-        mCorpusResults.add(mCorpusResult1);
-        mCorpusResults.add(mCorpusResult2);
-        mCorpusResults.add(mCorpusResultWeb);
-        mSuggestions = new Suggestions(mQuery,
-                Arrays.asList(MockCorpus.CORPUS_1, MockCorpus.CORPUS_2, MockCorpus.WEB_CORPUS));
-        mSuggestions.setShortcuts(new ShortcutCursor(mShortcuts));
-        mSuggestions.addCorpusResults(mCorpusResults);
-    }
-
-    public void testZeroShortcuts() {
-        SuggestionCursor promoted = promote(mSuggestions, 0, 1);
-        SuggestionCursor expected = slice(mCorpusResultWeb, 0, 1);
-        // Test sanity check: shouldn't expect any non-web suggestions
-        assertOnlyWebSuggestions(expected);
-        assertSameSuggestions(expected, promoted);
-    }
-
-    public void testZeroSuggestions() {
-        SuggestionCursor promoted = promote(mSuggestions, 1, 1);
-        SuggestionCursor expected = cursor(mWeb1);
-        // Test sanity check: shouldn't expect any non-web suggestions
-        assertOnlyWebSuggestions(expected);
-        assertSameSuggestions(expected, promoted);
-    }
-
-    public void testOnlyWebPromoted() {
-        SuggestionCursor promoted = promote(mSuggestions, 1, 2);
-        SuggestionCursor expected = concat(cursor(mWeb1), slice(mCorpusResultWeb, 0, 1));
-        // Test sanity check: shouldn't expect any non-web suggestions
-        assertOnlyWebSuggestions(expected);
-        assertSameSuggestions(expected, promoted);
-    }
-
-    private ListSuggestionCursor promote(Suggestions suggestions, int maxShortcuts,
-            int maxSuggestions) {
-        WebPromoter promoter = new WebPromoter(maxShortcuts);
-        ListSuggestionCursor promoted = new ListSuggestionCursor(mQuery);
-        promoter.pickPromoted(suggestions, maxSuggestions, promoted);
-        return promoted;
-    }
-
-    private SuggestionCursor cursor(Suggestion... suggestions) {
-        return new ListSuggestionCursor(mQuery, suggestions);
-    }
-
-    private void assertOnlyWebSuggestions(SuggestionCursor expected) {
-        for (Suggestion s : iterable(expected)) {
-            assertTrue("Not a web suggestion", s.isWebSearchSuggestion());
-        }
-    }
-
-}