Merge "Add new install flag to install on internal flash only Change default install location policy for new flag. New error code for media unavailable."
diff --git a/api/current.xml b/api/current.xml
index e6f3788..7cb44d1 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -136069,6 +136069,17 @@
  visibility="public"
 >
 </field>
+<field name="TTS_ENABLED_PLUGINS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;tts_enabled_plugins&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="TTS_USE_DEFAULTS"
  type="java.lang.String"
  transient="false"
@@ -384004,7 +384015,17 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="x" type="org.json.JSONTokener">
+<parameter name="copyFrom" type="java.util.Collection">
+</parameter>
+</constructor>
+<constructor name="JSONArray"
+ type="org.json.JSONArray"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="readFrom" type="org.json.JSONTokener">
 </parameter>
 <exception name="JSONException" type="org.json.JSONException">
 </exception>
@@ -384016,21 +384037,11 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="string" type="java.lang.String">
+<parameter name="json" type="java.lang.String">
 </parameter>
 <exception name="JSONException" type="org.json.JSONException">
 </exception>
 </constructor>
-<constructor name="JSONArray"
- type="org.json.JSONArray"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="collection" type="java.util.Collection">
-</parameter>
-</constructor>
 <method name="get"
  return="java.lang.Object"
  abstract="false"
@@ -384228,7 +384239,7 @@
 >
 <parameter name="index" type="int">
 </parameter>
-<parameter name="defaultValue" type="boolean">
+<parameter name="fallback" type="boolean">
 </parameter>
 </method>
 <method name="optDouble"
@@ -384256,7 +384267,7 @@
 >
 <parameter name="index" type="int">
 </parameter>
-<parameter name="defaultValue" type="double">
+<parameter name="fallback" type="double">
 </parameter>
 </method>
 <method name="optInt"
@@ -384284,7 +384295,7 @@
 >
 <parameter name="index" type="int">
 </parameter>
-<parameter name="defaultValue" type="int">
+<parameter name="fallback" type="int">
 </parameter>
 </method>
 <method name="optJSONArray"
@@ -384338,7 +384349,7 @@
 >
 <parameter name="index" type="int">
 </parameter>
-<parameter name="defaultValue" type="long">
+<parameter name="fallback" type="long">
 </parameter>
 </method>
 <method name="optString"
@@ -384366,7 +384377,7 @@
 >
 <parameter name="index" type="int">
 </parameter>
-<parameter name="defaultValue" type="java.lang.String">
+<parameter name="fallback" type="java.lang.String">
 </parameter>
 </method>
 <method name="put"
@@ -384546,7 +384557,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="indentFactor" type="int">
+<parameter name="indentSpaces" type="int">
 </parameter>
 <exception name="JSONException" type="org.json.JSONException">
 </exception>
@@ -384567,7 +384578,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="message" type="java.lang.String">
+<parameter name="s" type="java.lang.String">
 </parameter>
 </constructor>
 </class>
@@ -384594,9 +384605,17 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="jo" type="org.json.JSONObject">
+<parameter name="copyFrom" type="java.util.Map">
 </parameter>
-<parameter name="sa" type="java.lang.String[]">
+</constructor>
+<constructor name="JSONObject"
+ type="org.json.JSONObject"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="readFrom" type="org.json.JSONTokener">
 </parameter>
 <exception name="JSONException" type="org.json.JSONException">
 </exception>
@@ -384608,7 +384627,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="x" type="org.json.JSONTokener">
+<parameter name="json" type="java.lang.String">
 </parameter>
 <exception name="JSONException" type="org.json.JSONException">
 </exception>
@@ -384620,17 +384639,9 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="map" type="java.util.Map">
+<parameter name="copyFrom" type="org.json.JSONObject">
 </parameter>
-</constructor>
-<constructor name="JSONObject"
- type="org.json.JSONObject"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="string" type="java.lang.String">
+<parameter name="names" type="java.lang.String[]">
 </parameter>
 <exception name="JSONException" type="org.json.JSONException">
 </exception>
@@ -384645,7 +384656,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 <parameter name="value" type="java.lang.Object">
 </parameter>
@@ -384662,7 +384673,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 <exception name="JSONException" type="org.json.JSONException">
 </exception>
@@ -384677,7 +384688,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 <exception name="JSONException" type="org.json.JSONException">
 </exception>
@@ -384692,7 +384703,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 <exception name="JSONException" type="org.json.JSONException">
 </exception>
@@ -384707,7 +384718,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 <exception name="JSONException" type="org.json.JSONException">
 </exception>
@@ -384722,7 +384733,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 <exception name="JSONException" type="org.json.JSONException">
 </exception>
@@ -384737,7 +384748,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 <exception name="JSONException" type="org.json.JSONException">
 </exception>
@@ -384752,7 +384763,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 <exception name="JSONException" type="org.json.JSONException">
 </exception>
@@ -384767,7 +384778,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 <exception name="JSONException" type="org.json.JSONException">
 </exception>
@@ -384782,7 +384793,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 </method>
 <method name="isNull"
@@ -384795,7 +384806,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 </method>
 <method name="keys"
@@ -384841,7 +384852,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="n" type="java.lang.Number">
+<parameter name="number" type="java.lang.Number">
 </parameter>
 <exception name="JSONException" type="org.json.JSONException">
 </exception>
@@ -384856,7 +384867,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 </method>
 <method name="optBoolean"
@@ -384869,7 +384880,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 </method>
 <method name="optBoolean"
@@ -384882,9 +384893,9 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
-<parameter name="defaultValue" type="boolean">
+<parameter name="fallback" type="boolean">
 </parameter>
 </method>
 <method name="optDouble"
@@ -384897,7 +384908,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 </method>
 <method name="optDouble"
@@ -384910,9 +384921,9 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
-<parameter name="defaultValue" type="double">
+<parameter name="fallback" type="double">
 </parameter>
 </method>
 <method name="optInt"
@@ -384925,7 +384936,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 </method>
 <method name="optInt"
@@ -384938,9 +384949,9 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
-<parameter name="defaultValue" type="int">
+<parameter name="fallback" type="int">
 </parameter>
 </method>
 <method name="optJSONArray"
@@ -384953,7 +384964,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 </method>
 <method name="optJSONObject"
@@ -384966,7 +384977,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 </method>
 <method name="optLong"
@@ -384979,7 +384990,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 </method>
 <method name="optLong"
@@ -384992,9 +385003,9 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
-<parameter name="defaultValue" type="long">
+<parameter name="fallback" type="long">
 </parameter>
 </method>
 <method name="optString"
@@ -385007,7 +385018,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 </method>
 <method name="optString"
@@ -385020,9 +385031,9 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
-<parameter name="defaultValue" type="java.lang.String">
+<parameter name="fallback" type="java.lang.String">
 </parameter>
 </method>
 <method name="put"
@@ -385035,7 +385046,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 <parameter name="value" type="boolean">
 </parameter>
@@ -385052,7 +385063,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 <parameter name="value" type="double">
 </parameter>
@@ -385069,7 +385080,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 <parameter name="value" type="int">
 </parameter>
@@ -385086,7 +385097,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 <parameter name="value" type="long">
 </parameter>
@@ -385103,7 +385114,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 <parameter name="value" type="java.lang.Object">
 </parameter>
@@ -385120,7 +385131,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 <parameter name="value" type="java.lang.Object">
 </parameter>
@@ -385137,7 +385148,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="string" type="java.lang.String">
+<parameter name="data" type="java.lang.String">
 </parameter>
 </method>
 <method name="remove"
@@ -385150,7 +385161,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="key" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 </method>
 <method name="toJSONArray"
@@ -385178,7 +385189,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="indentFactor" type="int">
+<parameter name="indentSpaces" type="int">
 </parameter>
 <exception name="JSONException" type="org.json.JSONException">
 </exception>
@@ -385259,7 +385270,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="s" type="java.lang.String">
+<parameter name="name" type="java.lang.String">
 </parameter>
 <exception name="JSONException" type="org.json.JSONException">
 </exception>
@@ -385287,7 +385298,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="b" type="boolean">
+<parameter name="value" type="java.lang.Object">
 </parameter>
 <exception name="JSONException" type="org.json.JSONException">
 </exception>
@@ -385302,7 +385313,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="d" type="double">
+<parameter name="value" type="boolean">
 </parameter>
 <exception name="JSONException" type="org.json.JSONException">
 </exception>
@@ -385317,7 +385328,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="l" type="long">
+<parameter name="value" type="double">
 </parameter>
 <exception name="JSONException" type="org.json.JSONException">
 </exception>
@@ -385332,7 +385343,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="o" type="java.lang.Object">
+<parameter name="value" type="long">
 </parameter>
 <exception name="JSONException" type="org.json.JSONException">
 </exception>
@@ -385353,7 +385364,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="s" type="java.lang.String">
+<parameter name="in" type="java.lang.String">
 </parameter>
 </constructor>
 <method name="back"
@@ -385377,7 +385388,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="c" type="char">
+<parameter name="hex" type="char">
 </parameter>
 </method>
 <method name="more"
@@ -385427,7 +385438,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="n" type="int">
+<parameter name="length" type="int">
 </parameter>
 <exception name="JSONException" type="org.json.JSONException">
 </exception>
@@ -385470,7 +385481,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="d" type="char">
+<parameter name="excluded" type="java.lang.String">
 </parameter>
 </method>
 <method name="nextTo"
@@ -385483,7 +385494,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="delimiters" type="java.lang.String">
+<parameter name="excluded" type="char">
 </parameter>
 </method>
 <method name="nextValue"
@@ -385509,7 +385520,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="to" type="java.lang.String">
+<parameter name="thru" type="java.lang.String">
 </parameter>
 </method>
 <method name="skipTo"
@@ -385535,7 +385546,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="message" type="java.lang.String">
+<parameter name="text" type="java.lang.String">
 </parameter>
 </method>
 </class>
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index cc1167f..e9b21f1 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -115,8 +115,8 @@
     dump_file("KERNEL WAKELOCKS", "/proc/wakelocks");
     dump_file("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
 
+    run_command("VOLD DUMP", 10, "vdc", "dump", NULL);
     run_command("SECURE CONTAINERS", 10, "vdc", "asec", "list", NULL);
-    run_command("MOUNTED FILESYSTEMS", 10, "df", NULL);
 
     run_command("PROCESSES", 10, "ps", "-P", NULL);
     run_command("PROCESSES AND THREADS", 10, "ps", "-t", "-p", "-P", NULL);
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 86224c5d..a1ca707 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -43,1176 +43,18 @@
  * 
  * <p>In practice, you won't interact with this class directly, as search
  * services are provided through methods in {@link android.app.Activity Activity}
- * methods and the the {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH}
- * {@link android.content.Intent Intent}.  This class does provide a basic
- * overview of search services and how to integrate them with your activities.
- * If you do require direct access to the SearchManager, do not instantiate 
- * this class directly; instead, retrieve it through
+ * and the {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH}
+ * {@link android.content.Intent Intent}.
+ * If you do require direct access to the SearchManager, do not instantiate
+ * this class directly. Instead, retrieve it through
  * {@link android.content.Context#getSystemService
  * context.getSystemService(Context.SEARCH_SERVICE)}.
- * 
- * <p>Topics covered here:
- * <ol>
- * <li><a href="#DeveloperGuide">Developer Guide</a>
- * <li><a href="#HowSearchIsInvoked">How Search Is Invoked</a>
- * <li><a href="#ImplementingSearchForYourApp">Implementing Search for Your App</a>
- * <li><a href="#Suggestions">Search Suggestions</a>
- * <li><a href="#ExposingSearchSuggestionsToQuickSearchBox">Exposing Search Suggestions to
- * Quick Search Box</a></li>
- * <li><a href="#ActionKeys">Action Keys</a>
- * <li><a href="#SearchabilityMetadata">Searchability Metadata</a>
- * <li><a href="#PassingSearchContext">Passing Search Context</a>
- * <li><a href="#ProtectingUserPrivacy">Protecting User Privacy</a>
- * </ol>
- * 
- * <a name="DeveloperGuide"></a>
- * <h3>Developer Guide</h3>
- * 
- * <p>The ability to search for user, system, or network based data is considered to be
- * a core user-level feature of the Android platform.  At any time, the user should be
- * able to use a familiar command, button, or keystroke to invoke search, and the user
- * should be able to search any data which is available to them.
- * 
- * <p>To make search appear to the user as a seamless system-wide feature, the application
- * framework centrally controls it, offering APIs to individual applications to control how they
- * are searched. Applications can customize how search is invoked, how the search dialog looks,
- * and what type of search results are available, including suggestions that are available as the
- * user types.
  *
- * <p>Even applications which are not searchable will by default support the invocation of
- * search to trigger Quick Search Box, the system's 'global search'.
- * 
- * <a name="HowSearchIsInvoked"></a>
- * <h3>How Search Is Invoked</h3>
- * 
- * <p>Unless impossible or inapplicable, all applications should support
- * invoking the search UI.  This means that when the user invokes the search command, 
- * a search UI will be presented to them.  The search command is currently defined as a menu
- * item called "Search" (with an alphabetic shortcut key of "S"), or on many devices, a dedicated
- * search button key.
- * <p>If your application is not inherently searchable, the default implementation will cause
- * the search UI to be invoked in a "global search" mode known as Quick Search Box.  As the user
- * types, search suggestions from across the device and the web will be surfaced, and if they
- * click the "Search" button, this will bring the browser to the front and will launch a web-based
- * search.  The user will be able to click the "Back" button and return to your application.
- * <p>In general this is implemented by your activity, or the {@link android.app.Activity Activity}
- * base class, which captures the search command and invokes the SearchManager to 
- * display and operate the search UI.  You can also cause the search UI to be presented in response
- * to user keystrokes in your activity (for example, to instantly start filter searching while
- * viewing a list and typing any key).
- * <p>The search UI is presented as a floating 
- * window and does not cause any change in the activity stack.  If the user 
- * cancels search, the previous activity re-emerges.  If the user launches a 
- * search, this will be done by sending a search {@link android.content.Intent Intent} (see below), 
- * and the normal intent-handling sequence will take place (your activity will pause,
- * etc.)
- * <p><b>What you need to do:</b> First, you should consider the way in which you want to
- * handle invoking search.  There are four broad (and partially overlapping) categories for 
- * you to choose from.
- * <ul><li>You can capture the search command yourself, by including a <i>search</i>
- * button or menu item - and invoking the search UI directly.</li>
- * <li>You can provide a <i>type-to-search</i> feature, in which search is invoked automatically
- * when the user enters any characters.</li>
- * <li>Even if your application is not inherently searchable, you can allow global search, 
- * via the search key (or even via a search menu item).
- * <li>You can disable search entirely.  This should only be used in very rare circumstances,
- * as search is a system-wide feature and users will expect it to be available in all contexts.</li>
- * </ul>
- * 
- * <p><b>How to define a search menu.</b>  The system provides the following resources which may
- * be useful when adding a search item to your menu:
- * <ul><li>android.R.drawable.ic_search_category_default is an icon you can use in your menu.</li>
- * <li>{@link #MENU_KEY SearchManager.MENU_KEY} is the recommended alphabetic shortcut.</li>
- * </ul>
- * 
- * <p><b>How to invoke search directly.</b>  In order to invoke search directly, from a button
- * or menu item, you can launch a generic search by calling
- * {@link android.app.Activity#onSearchRequested onSearchRequested} as shown:
- * <pre class="prettyprint">
- * onSearchRequested();</pre>
- * 
- * <p><b>How to implement type-to-search.</b>  While setting up your activity, call
- * {@link android.app.Activity#setDefaultKeyMode setDefaultKeyMode}:
- * <pre class="prettyprint">
- * setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);   // search within your activity
- * setDefaultKeyMode(DEFAULT_KEYS_SEARCH_GLOBAL);  // search using platform global search</pre>
- * 
- * <p><b>How to start global search.</b>  In addition to searching within
- * your activity or application, you can also use the Search Manager to invoke a platform-global
- * search, which uses Quick Search Box to search across the device and the web.
- * Override {@link android.app.Activity#onSearchRequested} and call
- * {@link android.app.Activity#startSearch} with {@code globalSearch} set to {@code true}.
- * 
- * <p><b>How to disable search from your activity.</b> Search is a system-wide feature and users
- * will expect it to be available in all contexts.  If your UI design absolutely precludes
- * launching search, override {@link android.app.Activity#onSearchRequested onSearchRequested}
- * as shown:
- * <pre class="prettyprint">
- * &#64;Override
- * public boolean onSearchRequested() {
- *    return false;
- * }</pre> 
- * 
- * <p><b>Managing focus and knowing if search is active.</b>  The search UI is not a separate
- * activity, and when the UI is invoked or dismissed, your activity will not typically be paused,
- * resumed, or otherwise notified by the methods defined in 
- * <a href="{@docRoot}guide/topics/fundamentals.html#actlife">Application Fundamentals: 
- * Activity Lifecycle</a>.  The search UI is
- * handled in the same way as other system UI elements which may appear from time to time, such as 
- * notifications, screen locks, or other system alerts:  
- * <p>When the search UI appears, your activity will lose input focus.
- * <p>When the search activity is dismissed, there are three possible outcomes:
- * <ul><li>If the user simply canceled the search UI, your activity will regain input focus and
- * proceed as before.  See {@link #setOnDismissListener} and {@link #setOnCancelListener} if you 
- * required direct notification of search dialog dismissals.</li>
- * <li>If the user launched a search, and this required switching to another activity to receive
- * and process the search {@link android.content.Intent Intent}, your activity will receive the 
- * normal sequence of activity pause or stop notifications.</li>
- * <li>If the user launched a search, and the current activity is the recipient of the search 
- * {@link android.content.Intent Intent}, you will receive notification via the 
- * {@link android.app.Activity#onNewIntent onNewIntent()} method.</li></ul>
- * <p>This list is provided in order to clarify the ways in which your activities will interact with
- * the search UI.  More details on searchable activities and search intents are provided in the
- * sections below.
- *
- * <a name="ImplementingSearchForYourApp"></a>
- * <h3>Implementing Search for Your App</h3>
- *
- * <p>The following steps are necessary in order to implement search.
- * <ul>
- * <li>Implement search invocation as described above.  (Strictly speaking, 
- * these are decoupled, but it would make little sense to be "searchable" but not 
- * "search-invoking".)</li>
- * <li>Your application should have an activity that takes a search string and
- * converts it to a list of results.  This could be your primary display activity
- * or it could be a dedicated search results activity.  This is your <i>searchable</i>
- * activity and every query-search application must have one.</li>
- * <li>In the searchable activity, in onCreate(), you must receive and handle the 
- * {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH}
- * {@link android.content.Intent Intent}.  The text to search (query string) for is provided by 
- * calling 
- * {@link #QUERY getStringExtra(SearchManager.QUERY)}.</li>
- * <li>To identify and support your searchable activity, you'll need to 
- * provide an XML file providing searchability configuration parameters, a reference to that 
- * in your searchable activity's
- * <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a> entry, and an
- * intent-filter declaring that you can receive ACTION_SEARCH intents. This is described in more
- * detail in the <a href="#SearchabilityMetadata">Searchability Metadata</a> section.</li>
- * <li>Your <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a> also needs a
- * metadata entry providing a global reference to the searchable activity. This is the "glue"
- * directing the search UI, when invoked from any of your <i>other</i> activities, to use your
- * application as the default search context.  This is also described in more detail in the 
- * <a href="#SearchabilityMetadata">Searchability Metadata</a> section.</li> 
- * <li>Finally, you may want to define your search results activity as single-top with the 
- * {@link android.R.attr#launchMode singleTop} launchMode flag.  This allows the system 
- * to launch searches from/to the same activity without creating a pile of them on the 
- * activity stack.  If you do this, be sure to also override 
- * {@link android.app.Activity#onNewIntent onNewIntent} to handle the
- * updated intents (with new queries) as they arrive.</li>
- * </ul>
- *
- * <p>Code snippet showing handling of intents in your search activity:
- * <pre class="prettyprint">
- * &#64;Override
- * protected void onCreate(Bundle icicle) {
- *     super.onCreate(icicle);
- *     
- *     final Intent queryIntent = getIntent();
- *     final String queryAction = queryIntent.getAction();
- *     if (Intent.ACTION_SEARCH.equals(queryAction)) {
- *         doSearchWithIntent(queryIntent);
- *     }
- * }
- * 
- * private void doSearchWithIntent(final Intent queryIntent) {
- *     final String queryString = queryIntent.getStringExtra(SearchManager.QUERY);
- *     doSearchWithQuery(queryString);
- * }</pre>
- * 
- * <a name="Suggestions"></a>
- * <h3>Search Suggestions</h3>
- * 
- * <p>A powerful feature of the search system is the ability of any application to easily provide
- * live "suggestions" in order to prompt the user.  Each application implements suggestions in a 
- * different, unique, and appropriate way.  Suggestions be drawn from many sources, including but 
- * not limited to:
- * <ul>
- * <li>Actual searchable results (e.g. names in the address book)</li>
- * <li>Recently entered queries</li>
- * <li>Recently viewed data or results</li>
- * <li>Contextually appropriate queries or results</li>
- * <li>Summaries of possible results</li>
- * </ul>
- * 
- * <p>Once an application is configured to provide search suggestions, those same suggestions can
- * easily be made available to the system-wide Quick Search Box, providing faster access to its
- * content from one central prominent place. See
- * <a href="#ExposingSearchSuggestionsToQuickSearchBox">Exposing Search Suggestions to Quick Search
- * Box</a> for more details.
- * 
- * <p>The primary form of suggestions is known as <i>queried suggestions</i> and is based on query
- * text that the user has already typed.  This would generally be based on partial matches in
- * the available data.  In certain situations - for example, when no query text has been typed yet -
- * an application may also opt to provide <i>zero-query suggestions</i>.
- * These would typically be drawn from the same data source, but because no partial query text is 
- * available, they should be weighted based on other factors - for example, most recent queries 
- * or most recent results.
- * 
- * <p><b>Overview of how suggestions are provided.</b>  Suggestions are accessed via a
- * {@link android.content.ContentProvider Content Provider}. When the search manager identifies a 
- * particular activity as searchable, it will check for certain metadata which indicates that
- * there is also a source of suggestions.  If suggestions are provided, the following steps are
- * taken.
- * <ul><li>Using formatting information found in the metadata, the user's query text (whatever
- * has been typed so far) will be formatted into a query and sent to the suggestions 
- * {@link android.content.ContentProvider Content Provider}.</li>
- * <li>The suggestions {@link android.content.ContentProvider Content Provider} will create a
- * {@link android.database.Cursor Cursor} which can iterate over the possible suggestions.</li>
- * <li>The search manager will populate a list using display data found in each row of the cursor,
- * and display these suggestions to the user.</li>
- * <li>If the user types another key, or changes the query in any way, the above steps are repeated
- * and the suggestions list is updated or repopulated.</li>
- * <li>If the user clicks or touches the "GO" button, the suggestions are ignored and the search is
- * launched using the normal {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} type of 
- * {@link android.content.Intent Intent}.</li>
- * <li>If the user uses the directional controls to navigate the focus into the suggestions list,
- * the query text will be updated while the user navigates from suggestion to suggestion.  The user
- * can then click or touch the updated query and edit it further.  If the user navigates back to
- * the edit field, the original typed query is restored.</li>
- * <li>If the user clicks or touches a particular suggestion, then a combination of data from the 
- * cursor and
- * values found in the metadata are used to synthesize an Intent and send it to the application.
- * Depending on the design of the activity and the way it implements search, this might be a
- * {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} (in order to launch a query), or it
- * might be a {@link android.content.Intent#ACTION_VIEW ACTION_VIEW}, in order to proceed directly
- * to display of specific data.</li>
- * </ul>
- *  
- * <p><b>Simple Recent-Query-Based Suggestions.</b>  The Android framework provides a simple Search
- * Suggestions provider, which simply records and replays recent queries.  For many applications,
- * this will be sufficient.  The basic steps you will need to
- * do, in order to use the built-in recent queries suggestions provider, are as follows:
- * <ul>
- * <li>Implement and test query search, as described in the previous sections.</li>
- * <li>Create a Provider within your application by extending 
- * {@link android.content.SearchRecentSuggestionsProvider}.</li>
- * <li>Create a manifest entry describing your provider.</li>
- * <li>Update your searchable activity's XML configuration file with information about your
- * provider.</li>
- * <li>In your searchable activities, capture any user-generated queries and record them
- * for future searches by calling {@link android.provider.SearchRecentSuggestions#saveRecentQuery}.
- * </li>
- * </ul>
- * <p>For complete implementation details, please refer to 
- * {@link android.content.SearchRecentSuggestionsProvider}.  The rest of the information in this
- * section should not be necessary, as it refers to custom suggestions providers.
- * 
- * <p><b>Creating a Customized Suggestions Provider:</b>  In order to create more sophisticated
- * suggestion providers, you'll need to take the following steps:
- * <ul>
- * <li>Implement and test query search, as described in the previous sections.</li>
- * <li>Decide how you wish to <i>receive</i> suggestions.  Just like queries that the user enters,
- * suggestions will be delivered to your searchable activity as 
- * {@link android.content.Intent Intent} messages;  Unlike simple queries, you have quite a bit of
- * flexibility in forming those intents.  A query search application will probably
- * wish to continue receiving the {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} 
- * {@link android.content.Intent Intent}, which will launch a query search using query text as
- * provided by the suggestion.  A filter search application will probably wish to 
- * receive the {@link android.content.Intent#ACTION_VIEW ACTION_VIEW} 
- * {@link android.content.Intent Intent}, which will take the user directly to a selected entry.
- * Other interesting suggestions, including hybrids, are possible, and the suggestion provider
- * can easily mix-and-match results to provide a richer set of suggestions for the user.  Finally,
- * you'll need to update your searchable activity (or other activities) to receive the intents
- * as you've defined them.</li>
- * <li>Implement a Content Provider that provides suggestions.  If you already have one, and it 
- * has access to your suggestions data, you can use that provider. If not, you'll have to create 
- * one. You'll also provide information about your Content Provider in your 
- * package's <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a>.</li>
- * <li>Update your searchable activity's XML configuration file.  There are two categories of
- * information used for suggestions:
- * <ul><li>The first is (required) data that the search manager will
- * use to format the queries which are sent to the Content Provider.</li>
- * <li>The second is (optional) parameters to configure structure
- * if intents generated by suggestions.</li></li>
- * </ul>
- * </ul>
- * 
- * <p><b>Configuring your Content Provider to Receive Suggestion Queries.</b>  The basic job of
- * a search suggestions {@link android.content.ContentProvider Content Provider} is to provide
- * "live" (while-you-type) conversion of the user's query text into a set of zero or more 
- * suggestions. Each application is free to define the conversion, and as described above there are
- * many possible solutions.  This section simply defines how to communicate with the suggestion
- * provider.  
- * 
- * <p>The Search Manager must first determine if your package provides suggestions.  This is done
- * by examination of your searchable meta-data XML file.  The android:searchSuggestAuthority
- * attribute, if provided, is the signal to obtain & display suggestions.
- * 
- * <p>Every query includes a Uri, and the Search Manager will format the Uri as shown:
- * <p><pre class="prettyprint">
- * content:// your.suggest.authority / your.suggest.path / SearchManager.SUGGEST_URI_PATH_QUERY
- *    </pre>
- * 
- * <p>Your Content Provider can receive the query text in one of two ways.
- * <ul>
- * <li><b>Query provided as a selection argument.</b>  If you define the attribute value
- * android:searchSuggestSelection and include a string, this string will be passed as the 
- * <i>selection</i> parameter to your Content Provider's query function.  You must define a single
- * selection argument, using the '?' character.  The user's query text will be passed to you
- * as the first element of the selection arguments array.</li>
- * <li><b>Query provided with Data Uri.</b>  If you <i>do not</i> define the attribute value
- * android:searchSuggestSelection, then the Search Manager will append another "/" followed by
- * the user's query to the query Uri.  The query will be encoding using Uri encoding rules - don't
- * forget to decode it.  (See {@link android.net.Uri#getPathSegments} and
- * {@link android.net.Uri#getLastPathSegment} for helpful utilities you can use here.)</li>
- * </ul>
- *
- * <p><b>Providing access to Content Providers that require permissions.</b>  If your content
- * provider declares an android:readPermission in your application's manifest, you must provide
- * access to the search infrastructure to the search suggestion path by including a path-permission
- * that grants android:readPermission access to "android.permission.GLOBAL_SEARCH". Granting access
- * explicitly to the search infrastructure ensures it will be able to access the search suggestions
- * without needing to know ahead of time any other details of the permissions protecting your
- * provider.  Content providers that require no permissions are already available to the search
- * infrastructure.  Here is an example of a provider that protects access to it with permissions,
- * and provides read access to the search infrastructure to the path that it expects to receive the
- * suggestion query on:
- * <pre class="prettyprint">
- * &lt;provider android:name="MyProvider" android:authorities="myprovider"
- *        android:readPermission="android.permission.READ_MY_DATA"
- *        android:writePermission="android.permission.WRITE_MY_DATA"&gt;
- *    &lt;path-permission android:path="/search_suggest_query"
- *            android:readPermission="android.permission.GLOBAL_SEARCH" /&gt;
- * &lt;/provider&gt;
- * </pre>
- *
- * <p><b>Handling empty queries.</b>  Your application should handle the "empty query"
- * (no user text entered) case properly, and generate useful suggestions in this case.  There are a
- * number of ways to do this;  Two are outlined here:
- * <ul><li>For a simple filter search of local data, you could simply present the entire dataset,
- * unfiltered.  (example: People)</li>
- * <li>For a query search, you could simply present the most recent queries.  This allows the user
- * to quickly repeat a recent search.</li></ul>
- *
- * <p><b>The Format of Individual Suggestions.</b>  Your suggestions are communicated back to the
- * Search Manager by way of a {@link android.database.Cursor Cursor}.  The Search Manager will
- * usually pass a null Projection, which means that your provider can simply return all appropriate
- * columns for each suggestion.  The columns currently defined are:
- * 
- * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
- *
- *     <thead>
- *     <tr><th>Column Name</th> <th>Description</th> <th>Required?</th></tr>
- *     </thead>
- *
- *     <tbody>
- *     <tr><th>{@link #SUGGEST_COLUMN_FORMAT}</th>
- *         <td><i>Unused - can be null.</i></td>
- *         <td align="center">No</td>
- *     </tr>
- *     
- *     <tr><th>{@link #SUGGEST_COLUMN_TEXT_1}</th>
- *         <td>This is the line of text that will be presented to the user as the suggestion.</td>
- *         <td align="center">Yes</td>
- *     </tr>
- *     
- *     <tr><th>{@link #SUGGEST_COLUMN_TEXT_2}</th>
- *         <td>If your cursor includes this column, then all suggestions will be provided in a 
- *             two-line format.  The data in this column will be displayed as a second, smaller
- *             line of text below the primary suggestion, or it can be null or empty to indicate no
- *             text in this row's suggestion.</td>
- *         <td align="center">No</td>
- *     </tr>
- *     
- *     <tr><th>{@link #SUGGEST_COLUMN_ICON_1}</th>
- *         <td>If your cursor includes this column, then all suggestions will be provided in an
- *             icons+text format.  This value should be a reference to the icon to
- *             draw on the left side, or it can be null or zero to indicate no icon in this row.
- *             </td>
- *         <td align="center">No.</td>
- *     </tr>
- *     
- *     <tr><th>{@link #SUGGEST_COLUMN_ICON_2}</th>
- *         <td>If your cursor includes this column, then all suggestions will be provided in an
- *             icons+text format.  This value should be a reference to the icon to
- *             draw on the right side, or it can be null or zero to indicate no icon in this row.
- *             </td>
- *         <td align="center">No.</td>
- *     </tr>
- *     
- *     <tr><th>{@link #SUGGEST_COLUMN_INTENT_ACTION}</th>
- *         <td>If this column exists <i>and</i> this element exists at the given row, this is the 
- *             action that will be used when forming the suggestion's intent.  If the element is 
- *             not provided, the action will be taken from the android:searchSuggestIntentAction 
- *             field in your XML metadata.  <i>At least one of these must be present for the 
- *             suggestion to generate an intent.</i>  Note:  If your action is the same for all 
- *             suggestions, it is more efficient to specify it using XML metadata and omit it from 
- *             the cursor.</td>
- *         <td align="center">No</td>
- *     </tr>
- *     
- *     <tr><th>{@link #SUGGEST_COLUMN_INTENT_DATA}</th>
- *         <td>If this column exists <i>and</i> this element exists at the given row, this is the 
- *             data that will be used when forming the suggestion's intent.  If the element is not 
- *             provided, the data will be taken from the android:searchSuggestIntentData field in 
- *             your XML metadata.  If neither source is provided, the Intent's data field will be 
- *             null.  Note:  If your data is the same for all suggestions, or can be described 
- *             using a constant part and a specific ID, it is more efficient to specify it using 
- *             XML metadata and omit it from the cursor.</td>
- *         <td align="center">No</td>
- *     </tr>
- *     
- *     <tr><th>{@link #SUGGEST_COLUMN_INTENT_DATA_ID}</th>
- *         <td>If this column exists <i>and</i> this element exists at the given row, then "/" and 
- *             this value will be appended to the data field in the Intent.  This should only be 
- *             used if the data field has already been set to an appropriate base string.</td>
- *         <td align="center">No</td>
- *     </tr>
- *     
- *     <tr><th>{@link #SUGGEST_COLUMN_INTENT_EXTRA_DATA}</th>
- *         <td>If this column exists <i>and</i> this element exists at a given row, this is the
- *             data that will be used when forming the suggestion's intent.  If not provided,
- *             the Intent's extra data field will be null.  This column allows suggestions to
- *             provide additional arbitrary data which will be included as an extra under the
- *             key {@link #EXTRA_DATA_KEY}.</td>
- *         <td align="center">No.</td>
- *     </tr>
- *
- *     <tr><th>{@link #SUGGEST_COLUMN_QUERY}</th>
- *         <td>If this column exists <i>and</i> this element exists at the given row, this is the 
- *             data that will be used when forming the suggestion's query.</td>
- *         <td align="center">Required if suggestion's action is 
- *             {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH}, optional otherwise.</td>
- *     </tr>
- *
- *     <tr><th>{@link #SUGGEST_COLUMN_SHORTCUT_ID}</th>
- *         <td>This column is used to indicate whether a search suggestion should be stored as a
- *             shortcut, and whether it should be validated.  Shortcuts are usually formed when the
- *             user clicks a suggestion from Quick Search Box.  If missing, the result will be
- *             stored as a shortcut and never refreshed.  If set to
- *             {@link #SUGGEST_NEVER_MAKE_SHORTCUT}, the result will not be stored as a shortcut.
- *             Otherwise, the shortcut id will be used to check back for for an up to date
- *             suggestion using {@link #SUGGEST_URI_PATH_SHORTCUT}. Read more about shortcut
- *             refreshing in the section about
- *             <a href="#ExposingSearchSuggestionsToQuickSearchBox">exposing search suggestions to
- *             Quick Search Box</a>.</td>
- *         <td align="center">No.  Only applicable to sources included in Quick Search Box.</td>
- *     </tr>
- *
- *     <tr><th>{@link #SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING}</th>
- *         <td>This column is used to specify that a spinner should be shown in lieu of an icon2
- *             while the shortcut of this suggestion is being refreshed in Quick Search Box.</td>
- *         <td align="center">No.  Only applicable to sources included in Quick Search Box.</td>
- *     </tr>
- * 
- *     <tr><th><i>Other Columns</i></th>
- *         <td>Finally, if you have defined any <a href="#ActionKeys">Action Keys</a> and you wish 
- *             for them to have suggestion-specific definitions, you'll need to define one 
- *             additional column per action key.  The action key will only trigger if the 
- *             currently-selection suggestion has a non-empty string in the corresponding column.  
- *             See the section on <a href="#ActionKeys">Action Keys</a> for additional details and 
- *             implementation steps.</td>
- *         <td align="center">No</td>
- *     </tr>
- *     
- *     </tbody>
- * </table>
- *
- * <p>Clearly there are quite a few permutations of your suggestion data, but in the next section
- * we'll look at a few simple combinations that you'll select from. 
- *
- * <p><b>The Format Of Intents Sent By Search Suggestions.</b>  Although there are many ways to 
- * configure these intents, this document will provide specific information on just a few of them.  
- * <ul><li><b>Launch a query.</b>  In this model, each suggestion represents a query that your
- * searchable activity can perform, and the {@link android.content.Intent Intent} will be formatted
- * exactly like those sent when the user enters query text and clicks the "GO" button:
- *   <ul>
- *   <li><b>Action:</b> {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} provided
- *   using your XML metadata (android:searchSuggestIntentAction).</li>
- *   <li><b>Data:</b> empty (not used).</li>
- *   <li><b>Query:</b> query text supplied by the cursor.</li>
- *   </ul>
- * </li>
- * <li><b>Go directly to a result, using a complete Data Uri.</b>  In this model, the user will be 
- * taken directly to a specific result.
- *   <ul>
- *   <li><b>Action:</b> {@link android.content.Intent#ACTION_VIEW ACTION_VIEW}</li>
- *   <li><b>Data:</b> a complete Uri, supplied by the cursor, that identifies the desired data.
- *   </li>
- *   <li><b>Query:</b> query text supplied with the suggestion (probably ignored)</li>
- *   </ul>
- * </li>
- * <li><b>Go directly to a result, using a synthesized Data Uri.</b>  This has the same result
- * as the previous suggestion, but provides the Data Uri in a different way.
- *   <ul>
- *   <li><b>Action:</b> {@link android.content.Intent#ACTION_VIEW ACTION_VIEW}</li>
- *   <li><b>Data:</b> The search manager will assemble a Data Uri using the following elements:  
- *   a Uri fragment provided in your XML metadata (android:searchSuggestIntentData), followed by 
- *   a single "/", followed by the value found in the {@link #SUGGEST_COLUMN_INTENT_DATA_ID} 
- *   entry in your cursor.</li>
- *   <li><b>Query:</b> query text supplied with the suggestion (probably ignored)</li>
- *   </ul>
- * </li>
- * </ul>
- * <p>This list is not meant to be exhaustive.  Applications should feel free to define other types
- * of suggestions.  For example, you could reduce long lists of results to summaries, and use one
- * of the above intents (or one of your own) with specially formatted Data Uri's to display more
- * detailed results.  Or you could display textual shortcuts as suggestions, but launch a display
- * in a more data-appropriate format such as media artwork.
- * 
- * <p><b>Suggestion Rewriting.</b>  If the user navigates through the suggestions list, the UI
- * may temporarily rewrite the user's query with a query that matches the currently selected 
- * suggestion. This enables the user to see what query is being suggested, and also allows the user
- * to click or touch in the entry EditText element and make further edits to the query before
- * dispatching it.  In order to perform this correctly, the Search UI needs to know exactly what
- * text to rewrite the query with.
- * 
- * <p>For each suggestion, the following logic is used to select a new query string:
- * <ul><li>If the suggestion provides an explicit value in the {@link #SUGGEST_COLUMN_QUERY} 
- * column, this value will be used.</li>
- * <li>If the metadata includes the queryRewriteFromData flag, and the suggestion provides an 
- * explicit value for the intent Data field, this Uri will be used.  Note that this should only be
- * used with Uri's that are intended to be user-visible, such as HTTP.  Internal Uri schemes should
- * not be used in this way.</li>
- * <li>If the metadata includes the queryRewriteFromText flag, the text in 
- * {@link #SUGGEST_COLUMN_TEXT_1} will be used.  This should be used for suggestions in which no
- * query text is provided and the SUGGEST_COLUMN_INTENT_DATA values are not suitable for user 
- * inspection and editing.</li></ul>
- *
- * <a name="ExposingSearchSuggestionsToQuickSearchBox"></a>
- * <h3>Exposing Search Suggestions to Quick Search Box</h3>
- * 
- * <p>Once your application is set up to provide search suggestions, making them available to the
- * globally accessable Quick Search Box is as easy as setting android:includeInGlobalSearch to
- * "true" in your searchable metadata file.  Beyond that, here are some more details of how
- * suggestions interact with Quick Search Box, and optional ways that you may customize suggestions
- * for your application.
- * 
- * <p><b>Important Note:</b>  By default, your application will not be enabled as a suggestion
- * provider (or "searchable item") in Quick Search Box. Once your app is installed, the user must
- * enable it as a "searchable item" in the Search settings in order to receive your app's
- * suggestions in Quick Search Box. You should consider how to message this to users of your app -
- * perhaps with a note to the user the first time they launch the app about how to enable search
- * suggestions. This gives your app a chance to be queried for suggestions as the user types into
- * Quick Search Box, though exactly how or if your suggestions will be surfaced is decided by Quick
- * Search Box.
- *
- * <p><b>Source Ranking:</b>  Once your application's search results are made available to Quick
- * Search Box, how they surface to the user for a particular query will be determined as appropriate
- * by Quick Search Box ranking. This may depend on how many other apps have results for that query,
- * and how often the user has clicked on your results compared to the other apps - but there is no
- * guarantee about how ranking will occur, or whether your app's suggestions will show at all for
- * a given query.  In general, you can expect that providing quality results will increase the
- * likelihood that your app's suggestions are provided in a prominent position, and apps that
- * provide lower quality suggestions will be more likely to be ranked lower and/or not displayed.
- *
- * <p><b>Search Settings:</b>  Each app that is available to Quick Search Box has an entry in the
- * system settings where the user can enable or disable the inclusion of its results.  Below the
- * name of the application, each application may provide a brief description of what kind of
- * information will be made available via a search settings description string pointed to by the
- * android:searchSettingsDescription attribute in the searchable metadata. Note that the
- * user will need to visit this settings menu to enable search suggestions for your app before your
- * app will have a chance to provide search suggestions to Quick Search Box - see the section
- * called "Important Note" above.
- *
- * <p><b>Shortcuts:</b>  Suggestions that are clicked on by the user may be automatically made into
- * shortcuts, which are suggestions that have been copied from your provider in order to be quickly
- * displayed without the need to re-query the original sources. Shortcutted suggestions may be
- * displayed for the query that yielded the suggestion and for any prefixes of that query. You can
- * request how to have your app's suggestions made into shortcuts, and whether they should be
- * refreshed, using the {@link #SUGGEST_COLUMN_SHORTCUT_ID} column:
- * <ul><li>Suggestions that do not include a shortcut id column will be made into shortcuts and
- * never refreshed.  This makes sense for suggestions that refer to data that will never be changed
- * or removed.</li>
- * <li>Suggestions that include a shortcut id will be re-queried for a fresh version of the
- * suggestion each time the shortcut is displayed.  The shortcut will be quickly displayed with
- * whatever data was most recently available until the refresh query returns, after which the
- * suggestion will be dynamically refreshed with the up to date information.  The shortcut refresh
- * query will be sent to your suggestion provider with a uri of {@link #SUGGEST_URI_PATH_SHORTCUT}.
- * The result should contain one suggestion using the same columns as the suggestion query, or be
- * empty, indicating that the shortcut is no longer valid.  Shortcut ids make sense when referring
- * to data that may change over time, such as a contact's presence status.  If a suggestion refers
- * to data that could take longer to refresh, such as a network based refresh of a stock quote, you
- * may include {@link #SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING} to show a progress spinner for the
- * right hand icon until the refresh is complete.</li>
- * <li>Finally, to prevent a suggestion from being copied into a shortcut, you may provide a
- * shortcut id with a value of {@link #SUGGEST_NEVER_MAKE_SHORTCUT}.</li></ul>
- * 
- * Note that Quick Search Box will ultimately decide whether to shortcut your app's suggestions,
- * considering these values as a strong request from your application.
- * 
- * <a name="ActionKeys"></a>
- * <h3>Action Keys</h3>
- * 
- * <p>Searchable activities may also wish to provide shortcuts based on the various action keys
- * available on the device.  The most basic example of this is the contacts app, which enables the
- * green "dial" key for quick access during searching.  Not all action keys are available on 
- * every device, and not all are allowed to be overriden in this way.  (For example, the "Home"
- * key must always return to the home screen, with no exceptions.)
- * 
- * <p>In order to define action keys for your searchable application, you must do two things.
- * 
- * <ul>
- * <li>You'll add one or more <i>actionkey</i> elements to your searchable metadata configuration
- * file.  Each element defines one of the keycodes you are interested in, 
- * defines the conditions under which they are sent, and provides details
- * on how to communicate the action key event back to your searchable activity.</li>
- * <li>In your broadcast receiver, if you wish, you can check for action keys by checking the 
- * extras field of the {@link android.content.Intent Intent}.</li>
- * </ul>
- * 
- * <p><b>Updating metadata.</b>  For each keycode of interest, you must add an &lt;actionkey&gt;
- * element.  Within this element you must define two or three attributes.  The first attribute,
- * &lt;android:keycode&gt;, is required;  It is the key code of the action key event, as defined in 
- * {@link android.view.KeyEvent}.  The remaining two attributes define the value of the actionkey's
- * <i>message</i>, which will be passed to your searchable activity in the 
- * {@link android.content.Intent Intent} (see below for more details).  Although each of these 
- * attributes is optional, you must define one or both for the action key to have any effect.
- * &lt;android:queryActionMsg&gt; provides the message that will be sent if the action key is 
- * pressed while the user is simply entering query text.  &lt;android:suggestActionMsgColumn&gt;
- * is used when action keys are tied to specific suggestions.  This attribute provides the name
- * of a <i>column</i> in your suggestion cursor;  The individual suggestion, in that column,
- * provides the message.  (If the cell is empty or null, that suggestion will not work with that
- * action key.)
- * <p>See the <a href="#SearchabilityMetadata">Searchability Metadata</a> section for more details 
- * and examples.
- * 
- * <p><b>Receiving Action Keys</b>  Intents launched by action keys will be specially marked
- * using a combination of values.  This enables your searchable application to examine the intent,
- * if necessary, and perform special processing.  For example, clicking a suggested contact might
- * simply display them;  Selecting a suggested contact and clicking the dial button might
- * immediately call them.
- * 
- * <p>When a search {@link android.content.Intent Intent} is launched by an action key, two values
- * will be added to the extras field.
- * <ul>
- * <li>To examine the key code, use {@link android.content.Intent#getIntExtra 
- * getIntExtra(SearchManager.ACTION_KEY)}.</li>
- * <li>To examine the message string, use {@link android.content.Intent#getStringExtra 
- * getStringExtra(SearchManager.ACTION_MSG)}</li>
- * </ul>
- * 
- * <a name="SearchabilityMetadata"></a>
- * <h3>Searchability Metadata</h3>
- * 
- * <p>Every activity that is searchable must provide a small amount of additional information
- * in order to properly configure the search system.  This controls the way that your search
- * is presented to the user, and controls for the various modalities described previously.
- * 
- * <p>If your application is not searchable,
- * then you do not need to provide any search metadata, and you can skip the rest of this section.
- * When this search metadata cannot be found, the search manager will assume that the activity 
- * does not implement search.  (Note: to implement web-based search, you will need to add
- * the android.app.default_searchable metadata to your manifest, as shown below.)
- * 
- * <p>Values you supply in metadata apply only to each local searchable activity.  Each
- * searchable activity can define a completely unique search experience relevant to its own
- * capabilities and user experience requirements, and a single application can even define multiple
- * searchable activities.
- *
- * <p><b>Metadata for searchable activity.</b>  As with your search implementations described 
- * above, you must first identify which of your activities is searchable.  In the 
- * <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a> entry for this activity, you must 
- * provide two elements:
- * <ul><li>An intent-filter specifying that you can receive and process the 
- * {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} {@link android.content.Intent Intent}.
- * </li>
- * <li>A reference to a small XML file (typically called "searchable.xml") which contains the
- * remaining configuration information for how your application implements search.</li></ul>
- * 
- * <p>Here is a snippet showing the necessary elements in the 
- * <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a> entry for your searchable activity.
- * <pre class="prettyprint">
- *        &lt;!-- Search Activity - searchable --&gt;
- *        &lt;activity android:name="MySearchActivity" 
- *                  android:label="Search"
- *                  android:launchMode="singleTop"&gt;
- *            &lt;intent-filter&gt;
- *                &lt;action android:name="android.intent.action.SEARCH" /&gt;
- *                &lt;category android:name="android.intent.category.DEFAULT" /&gt;
- *            &lt;/intent-filter&gt;
- *            &lt;meta-data android:name="android.app.searchable" 
- *                       android:resource="@xml/searchable" /&gt;
- *        &lt;/activity&gt;</pre>
- *
- * <p>Next, you must provide the rest of the searchability configuration in 
- * the small XML file, stored in the ../xml/ folder in your build.  The XML file is a 
- * simple enumeration of the search configuration parameters for searching within this activity,
- * application, or package.  Here is a sample XML file (named searchable.xml, for use with
- * the above manifest) for a query-search activity.
- *
- * <pre class="prettyprint">
- * &lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
- *     android:label="@string/search_label"
- *     android:hint="@string/search_hint" &gt;
- * &lt;/searchable&gt;</pre>
- *
- * <p>Note that all user-visible strings <i>must</i> be provided in the form of "@string" 
- * references.  Hard-coded strings, which cannot be localized, will not work properly in search
- * metadata.
- * 
- * <p>Attributes you can set in search metadata:
- * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
- *
- *     <thead>
- *     <tr><th>Attribute</th> <th>Description</th> <th>Required?</th></tr>
- *     </thead>
- *
- *     <tbody>
- *     <tr><th>android:label</th>
- *         <td>This is the name for your application that will be presented to the user in a 
- *             list of search targets, or in the search box as a label.</td>
- *         <td align="center">Yes</td>
- *     </tr>
- *     
- *     <tr><th>android:icon</th>
- *         <td><strong>This is deprecated.</strong><br/>The default
- *           application icon is now always used, so this attribute is
- *           obsolete.</td>
- *         <td align="center">No</td>
- *     </tr>
- *     
- *     <tr><th>android:hint</th>
- *         <td>This is the text to display in the search text field when no text
- *             has been entered by the user.</td>
- *         <td align="center">No</td>
- *     </tr>
- *     
- *     <tr><th>android:searchMode</th>
- *         <td>If provided and non-zero, sets additional modes for control of the search 
- *             presentation.  The following mode bits are defined:
- *             <table border="2" align="center" frame="hsides" rules="rows">
- *                 <tbody>
- *                 <tr><th>showSearchLabelAsBadge</th>
- *                     <td>If set, this flag enables the display of the search target (label) 
- *                         above the search box. As an alternative, you may
- *                         want to instead use "hint" text in the search box.
- *                         See the "android:hint" attribute above.</td>
- *                 </tr>
- *                 <tr><th>showSearchIconAsBadge</th>
- *                     <td><strong>This is deprecated.</strong><br/>The default
- *                         application icon is now always used, so this
- *                         option is obsolete.</td>
- *                 </tr>
- *                 <tr><th>queryRewriteFromData</th>
- *                     <td>If set, this flag causes the suggestion column SUGGEST_COLUMN_INTENT_DATA
- *                         to be considered as the text for suggestion query rewriting.  This should
- *                         only be used when the values in SUGGEST_COLUMN_INTENT_DATA are suitable
- *                         for user inspection and editing - typically, HTTP/HTTPS Uri's.</td>
- *                 </tr>
- *                 <tr><th>queryRewriteFromText</th>
- *                     <td>If set, this flag causes the suggestion column SUGGEST_COLUMN_TEXT_1 to 
- *                         be considered as the text for suggestion query rewriting.  This should 
- *                         be used for suggestions in which no query text is provided and the 
- *                         SUGGEST_COLUMN_INTENT_DATA values are not suitable for user inspection 
- *                         and editing.</td>
- *                 </tr>
- *                 </tbody>
- *            </table>
- *            Note that the icon of your app will likely be shown alongside any badge you specify,
- *            to differentiate search in your app from Quick Search Box. The display of this icon
- *            is not under the app's control.
- *         </td>
- *            
- *         <td align="center">No</td>
- *     </tr>
- *     
- *     <tr><th>android:inputType</th>
- *         <td>If provided, supplies a hint about the type of search text the user will be
- *             entering.  For most searches, in which free form text is expected, this attribute
- *             need not be provided.  Suitable values for this attribute are described in the
- *             <a href="../R.attr.html#inputType">inputType</a> attribute.</td>
- *         <td align="center">No</td>
- *     </tr>
- *     <tr><th>android:imeOptions</th>
- *         <td>If provided, supplies additional options for the input method.
- *             For most searches, in which free form text is expected, this attribute
- *             need not be provided, and will default to "actionSearch".
- *             Suitable values for this attribute are described in the
- *             <a href="../R.attr.html#imeOptions">imeOptions</a> attribute.</td>
- *         <td align="center">No</td>
- *     </tr>
- *     
- *     </tbody>
- * </table>
- * 
- * <p><b>Styleable Resources in your Metadata.</b>  It's possible to provide alternate strings
- * for your searchable application, in order to provide localization and/or to better visual 
- * presentation on different device configurations.  Each searchable activity has a single XML 
- * metadata file, but any resource references can be replaced at runtime based on device
- * configuration, language setting, and other system inputs.
- * 
- * <p>A concrete example is the "hint" text you supply using the android:searchHint attribute.
- * In portrait mode you'll have less screen space and may need to provide a shorter string, but
- * in landscape mode you can provide a longer, more descriptive hint.  To do this, you'll need to
- * define two or more strings.xml files, in the following directories:
- * <ul><li>.../res/values-land/strings.xml</li>
- * <li>.../res/values-port/strings.xml</li>
- * <li>.../res/values/strings.xml</li></ul>
- * 
- * <p>For more complete documentation on this capability, see
- * <a href="{@docRoot}guide/topics/resources/resources-i18n.html#AlternateResources">Resources and 
- * Internationalization: Alternate Resources</a>.
- *
- * <p><b>Metadata for non-searchable activities.</b>  Activities which are part of a searchable
- * application, but don't implement search itself, require a bit of "glue" in order to cause
- * them to invoke search using your searchable activity as their primary context.  If this is not
- * provided, then searches from these activities will use the system default search context.
- * 
- * <p>The simplest way to specify this is to add a <i>search reference</i> element to the
- * application entry in the <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a> file.  
- * The value of this reference should be the name of your searchable activity.
- * It is typically prefixed by '.' to indicate that it's in the same package.
- *
- * <p>Here is a snippet showing the necessary addition to the manifest entry for your 
- * non-searchable activities.
- * <pre class="prettyprint">
- *        &lt;application&gt;
- *            &lt;meta-data android:name="android.app.default_searchable"
- *                       android:value=".MySearchActivity" /&gt;
- *            
- *            &lt;!-- followed by activities, providers, etc... --&gt;
- *        &lt;/application&gt;</pre>
- *
- * <p>You can also specify android.app.default_searchable on a per-activity basis, by including
- * the meta-data element (as shown above) in one or more activity sections.  If found, these will
- * override the reference in the application section.  The only reason to configure your application
- * this way would be if you wish to partition it into separate sections with different search 
- * behaviors;  Otherwise this configuration is not recommended.
- * 
- * <p><b>Additional metadata for search suggestions.</b>  If you have defined a content provider
- * to generate search suggestions, you'll need to publish it to the system, and you'll need to 
- * provide a bit of additional XML metadata in order to configure communications with it.
- * 
- * <p>First, in your <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a>, you'll add the
- * following lines.
- * <pre class="prettyprint">
- *        &lt;!-- Content provider for search suggestions --&gt;
- *        &lt;provider android:name="YourSuggestionProviderClass"
- *                android:authorities="your.suggestion.authority" /&gt;</pre>
- * 
- * <p>Next, you'll add a few lines to your XML metadata file, as shown:
- * <pre class="prettyprint">
- *     &lt;!-- Required attribute for any suggestions provider --&gt;
- *     android:searchSuggestAuthority="your.suggestion.authority"
- *     
- *     &lt;!-- Optional attribute for configuring queries --&gt;
- *     android:searchSuggestSelection="field =?"
- *     
- *     &lt;!-- Optional attributes for configuring intent construction --&gt;
- *     android:searchSuggestIntentAction="intent action string"
- *     android:searchSuggestIntentData="intent data Uri" /&gt;</pre>
- * 
- * <p>Elements of search metadata that support suggestions:
- * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
- *
- *     <thead>
- *     <tr><th>Attribute</th> <th>Description</th> <th>Required?</th></tr>
- *     </thead>
- *
- *     <tbody>
- *     <tr><th>android:searchSuggestAuthority</th>
- *         <td>This value must match the authority string provided in the <i>provider</i> section 
- *             of your <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a>.</td>
- *         <td align="center">Yes</td>
- *     </tr>
- *     
- *     <tr><th>android:searchSuggestPath</th>
- *         <td>If provided, this will be inserted in the suggestions query Uri, after the authority
- *             you have provide but before the standard suggestions path.  This is only required if
- *             you have a single content provider issuing different types of suggestions (e.g. for
- *             different data types) and you need a way to disambiguate the suggestions queries
- *             when they are received.</td>
- *         <td align="center">No</td>
- *     </tr>
- *     
- *     <tr><th>android:searchSuggestSelection</th>
- *         <td>If provided, this value will be passed into your query function as the 
- *             <i>selection</i> parameter.  Typically this will be a WHERE clause for your database, 
- *             and will contain a single question mark, which represents the actual query string 
- *             that has been typed by the user.  However, you can also use any non-null value
- *             to simply trigger the delivery of the query text (via selection arguments), and then
- *             use the query text in any way appropriate for your provider (ignoring the actual
- *             text of the selection parameter.)</td>
- *         <td align="center">No</td>
- *     </tr>
- *     
- *     <tr><th>android:searchSuggestIntentAction</th>
- *         <td>If provided, and not overridden by the selected suggestion, this value will be 
- *             placed in the action field of the {@link android.content.Intent Intent} when the 
- *             user clicks a suggestion.</td>
- *         <td align="center">No</td>
- *     
- *     <tr><th>android:searchSuggestIntentData</th>
- *         <td>If provided, and not overridden by the selected suggestion, this value will be 
- *             placed in the data field of the {@link android.content.Intent Intent} when the user 
- *             clicks a suggestion.</td>
- *         <td align="center">No</td>
- *     </tr>
- *     
- *     </tbody>
- * </table>
- *
- * <p>Elements of search metadata that configure search suggestions being available to Quick Search
- * Box:
- * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
- *
- *     <thead>
- *     <tr><th>Attribute</th> <th>Description</th> <th>Required?</th></tr>
- *     </thead>
- *
- *     <tr><th>android:includeInGlobalSearch</th>
- *         <td>If true, indicates the search suggestions provided by your application should be
- *             included in the globally accessible Quick Search Box.  The attributes below are only
- *             applicable if this is set to true.</td>
- *         <td align="center">Yes</td>
- *     </tr>
- *
- *     <tr><th>android:searchSettingsDescription</th>
- *         <td>If provided, provides a brief description of the search suggestions that are provided
- *             by your application to Quick Search Box, and will be displayed in the search settings
- *             entry for your application.</td>
- *         <td align="center">No</td>
- *     </tr>
- *
- *     <tr><th>android:queryAfterZeroResults</th>
- *         <td>Indicates whether a source should be invoked for supersets of queries it has
- *             returned zero results for in the past.  For example, if a source returned zero
- *             results for "bo", it would be ignored for "bob".  If set to false, this source
- *             will only be ignored for a single session; the next time the search dialog is
- *             invoked, all sources will be queried.  The default value is false.</td>
- *         <td align="center">No</td>
- *     </tr>
- *
- *     <tr><th>android:searchSuggestThreshold</th>
- *         <td>Indicates the minimum number of characters needed to trigger a source from Quick
- *             Search Box.  Only guarantees that a source will not be queried for anything shorter
- *             than the threshold.  The default value is 0.</td>
- *         <td align="center">No</td>
- *     </tr>
- *
- *     </tbody>
- * </table>
- *
- * <p><b>Additional metadata for search action keys.</b>  For each action key that you would like to
- * define, you'll need to add an additional element defining that key, and using the attributes
- * discussed in <a href="#ActionKeys">Action Keys</a>.  A simple example is shown here:
- * 
- * <pre class="prettyprint">&lt;actionkey
- *     android:keycode="KEYCODE_CALL"
- *     android:queryActionMsg="call"
- *     android:suggestActionMsg="call"
- *     android:suggestActionMsgColumn="call_column" /&gt;</pre>
- *
- * <p>Elements of search metadata that support search action keys.  Note that although each of the
- * action message elements are marked as <i>optional</i>, at least one must be present for the 
- * action key to have any effect.
- * 
- * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
- *
- *     <thead>
- *     <tr><th>Attribute</th> <th>Description</th> <th>Required?</th></tr>
- *     </thead>
- *
- *     <tbody>
- *     <tr><th>android:keycode</th>
- *         <td>This attribute denotes the action key you wish to respond to.  Note that not
- *             all action keys are actually supported using this mechanism, as many of them are
- *             used for typing, navigation, or system functions.  This will be added to the 
- *             {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} intent that is passed to 
- *             your searchable activity.  To examine the key code, use 
- *             {@link android.content.Intent#getIntExtra getIntExtra(SearchManager.ACTION_KEY)}.  
- *             <p>Note, in addition to the keycode, you must also provide one or more of the action
- *             specifier attributes.</td>
- *         <td align="center">Yes</td>
- *     </tr>
- *     
- *     <tr><th>android:queryActionMsg</th>
- *         <td>If you wish to handle an action key during normal search query entry, you
- *          must define an action string here.  This will be added to the 
- *          {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} intent that is passed to your
- *          searchable activity.  To examine the string, use 
- *          {@link android.content.Intent#getStringExtra 
- *          getStringExtra(SearchManager.ACTION_MSG)}.</td>
- *         <td align="center">No</td>
- *     </tr>
- *     
- *     <tr><th>android:suggestActionMsg</th>
- *         <td>If you wish to handle an action key while a suggestion is being displayed <i>and
- *             selected</i>, there are two ways to handle this.  If <i>all</i> of your suggestions
- *             can handle the action key, you can simply define the action message using this 
- *             attribute.  This will be added to the 
- *             {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} intent that is passed to
- *             your searchable activity.  To examine the string, use 
- *             {@link android.content.Intent#getStringExtra 
- *             getStringExtra(SearchManager.ACTION_MSG)}.</td>
- *         <td align="center">No</td>
- *     </tr>
- *     
- *     <tr><th>android:suggestActionMsgColumn</th>
- *         <td>If you wish to handle an action key while a suggestion is being displayed <i>and
- *             selected</i>, but you do not wish to enable this action key for every suggestion, 
- *             then you can use this attribute to control it on a suggestion-by-suggestion basis.
- *             First, you must define a column (and name it here) where your suggestions will 
- *             include the action string.  Then, in your content provider, you must provide this
- *             column, and when desired, provide data in this column.
- *             The search manager will look at your suggestion cursor, using the string 
- *             provided here in order to select a column, and will use that to select a string from 
- *             the cursor.  That string will be added to the 
- *             {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} intent that is passed to 
- *             your searchable activity.  To examine the string, use 
- *             {@link android.content.Intent#getStringExtra 
- *             getStringExtra(SearchManager.ACTION_MSG)}.  <i>If the data does not exist for the
- *             selection suggestion, the action key will be ignored.</i></td>
- *         <td align="center">No</td>
- *     </tr>
- * 
- *     </tbody>
- * </table>
- * 
- * <p><b>Additional metadata for enabling voice search.</b>  To enable voice search for your
- * activity, you can add fields to the metadata that enable and configure voice search.  When
- * enabled (and available on the device), a voice search button will be displayed in the
- * Search UI.  Clicking this button will launch a voice search activity.  When the user has
- * finished speaking, the voice search phrase will be transcribed into text and presented to the
- * searchable activity as if it were a typed query.
- * 
- * <p>Elements of search metadata that support voice search:
- * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
- *
- *     <thead>
- *     <tr><th>Attribute</th> <th>Description</th> <th>Required?</th></tr>
- *     </thead>
- *     
- *     <tr><th>android:voiceSearchMode</th>
- *         <td>If provided and non-zero, enables voice search.  (Voice search may not be
- *             provided by the device, in which case these flags will have no effect.)  The
- *             following mode bits are defined:
- *             <table border="2" align="center" frame="hsides" rules="rows">
- *                 <tbody>
- *                 <tr><th>showVoiceSearchButton</th>
- *                     <td>If set, display a voice search button.  This only takes effect if voice
- *                         search is available on the device.  If set, then launchWebSearch or
- *                         launchRecognizer must also be set.</td>
- *                 </tr>
- *                 <tr><th>launchWebSearch</th>
- *                     <td>If set, the voice search button will take the user directly to a 
- *                         built-in voice web search activity.  Most applications will not use this
- *                         flag, as it will take the user away from the activity in which search
- *                         was invoked.</td>
- *                 </tr>
- *                 <tr><th>launchRecognizer</th>
- *                     <td>If set, the voice search button will take the user directly to a
- *                         built-in voice recording activity.  This activity will prompt the user
- *                         to speak, transcribe the spoken text, and forward the resulting query
- *                         text to the searchable activity, just as if the user had typed it into
- *                         the search UI and clicked the search button.</td>
- *                 </tr>
- *                 </tbody>
- *            </table></td>
- *         <td align="center">No</td>
- *     </tr>
- *     
- *     <tr><th>android:voiceLanguageModel</th>
- *         <td>If provided, this specifies the language model that should be used by the voice
- *             recognition system.  
- *             See {@link android.speech.RecognizerIntent#EXTRA_LANGUAGE_MODEL}
- *             for more information.  If not provided, the default value
- *             {@link android.speech.RecognizerIntent#LANGUAGE_MODEL_FREE_FORM} will be used.</td>
- *         <td align="center">No</td>
- *     </tr>
- *     
- *     <tr><th>android:voicePromptText</th>
- *         <td>If provided, this specifies a prompt that will be displayed during voice input.
- *             (If not provided, a default prompt will be displayed.)</td>
- *         <td align="center">No</td>
- *     </tr>
- *     
- *     <tr><th>android:voiceLanguage</th>
- *         <td>If provided, this specifies the spoken language to be expected.  This is only
- *             needed if it is different from the current value of
- *             {@link java.util.Locale#getDefault()}.
- *             </td>
- *         <td align="center">No</td>
- *     </tr>
- *     
- *     <tr><th>android:voiceMaxResults</th>
- *         <td>If provided, enforces the maximum number of results to return, including the "best"
- *             result which will always be provided as the SEARCH intent's primary query.  Must be
- *             one or greater.  Use {@link android.speech.RecognizerIntent#EXTRA_RESULTS} 
- *             to get the results from the intent.  If not provided, the recognizer will choose
- *             how many results to return.</td>
- *         <td align="center">No</td>
- *     </tr>
- * 
- *     </tbody>
- * </table>
- * 
- * <a name="PassingSearchContext"></a>
- * <h3>Passing Search Context</h3>
- * 
- * <p>In order to improve search experience, an application may wish to specify
- * additional data along with the search, such as local history or context.  For
- * example, a maps search would be improved by including the current location.  
- * In order to simplify the structure of your activities, this can be done using 
- * the search manager.
- *
- * <p>Any data can be provided at the time the search is launched, as long as it
- * can be stored in a {@link android.os.Bundle Bundle} object.
- *
- * <p>To pass application data into the Search Manager, you'll need to override
- * {@link android.app.Activity#onSearchRequested onSearchRequested} as follows:
- *
- * <pre class="prettyprint">
- * &#64;Override
- * public boolean onSearchRequested() {
- *     Bundle appData = new Bundle();
- *     appData.put...();
- *     appData.put...();
- *     startSearch(null, false, appData, false);
- *     return true;
- * }</pre> 
- *
- * <p>To receive application data from the Search Manager, you'll extract it from
- * the {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH}
- * {@link android.content.Intent Intent} as follows:
- *
- * <pre class="prettyprint">
- * final Bundle appData = queryIntent.getBundleExtra(SearchManager.APP_DATA);
- * if (appData != null) {
- *     appData.get...();
- *     appData.get...();
- * }</pre>
- * 
- * <a name="ProtectingUserPrivacy"></a>
- * <h3>Protecting User Privacy</h3>
- * 
- * <p>Many users consider their activities on the phone, including searches, to be private 
- * information.  Applications that implement search should take steps to protect users' privacy
- * wherever possible.  This section covers two areas of concern, but you should consider your search
- * design carefully and take any additional steps necessary.
- * 
- * <p><b>Don't send personal information to servers, and if you do, don't log it.</b>
- * "Personal information" is information that can personally identify your users, such as name, 
- * email address or billing information, or other data which can be reasonably linked to such 
- * information.  If your application implements search with the assistance of a server, try to 
- * avoid sending personal information with your searches.  For example, if you are searching for 
- * businesses near a zip code, you don't need to send the user ID as well - just send the zip code
- * to the server.  If you do need to send personal information, you should take steps to avoid 
- * logging it.  If you must log it, you should protect that data very carefully, and erase it as 
- * soon as possible.
- * 
- * <p><b>Provide the user with a way to clear their search history.</b>  The Search Manager helps
- * your application provide context-specific suggestions.  Sometimes these suggestions are based
- * on previous searches, or other actions taken by the user in an earlier session.  A user may not
- * wish for previous searches to be revealed to other users, for instance if they share their phone
- * with a friend.  If your application provides suggestions that can reveal previous activities,
- * you should implement a "Clear History" menu, preference, or button.  If you are using 
- * {@link android.provider.SearchRecentSuggestions}, you can simply call its 
- * {@link android.provider.SearchRecentSuggestions#clearHistory() clearHistory()} method from
- * your "Clear History" UI.  If you are implementing your own form of recent suggestions, you'll 
- * need to provide a similar a "clear history" API in your provider, and call it from your
- * "Clear History" UI.
+ * <div class="special">
+ * <p>For a guide to using the search dialog and adding search
+ * suggestions in your application, see the Dev Guide topic about <strong><a
+ * href="{@docRoot}guide/topics/search/index.html">Search</a></strong>.</p>
+ * </div>
  */
 public class SearchManager 
         implements DialogInterface.OnDismissListener, DialogInterface.OnCancelListener
diff --git a/core/java/android/provider/Calendar.java b/core/java/android/provider/Calendar.java
index 1c5fca3..ba63a66 100644
--- a/core/java/android/provider/Calendar.java
+++ b/core/java/android/provider/Calendar.java
@@ -1279,9 +1279,9 @@
             }
 
             Intent intent = new Intent(EVENT_REMINDER_ACTION);
+            intent.setData(ContentUris.withAppendedId(Calendar.CONTENT_URI, alarmTime));
             intent.putExtra(ALARM_TIME, alarmTime);
-            PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent,
-                    PendingIntent.FLAG_CANCEL_CURRENT);
+            PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
             manager.set(AlarmManager.RTC_WAKEUP, alarmTime, pi);
         }
 
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 66f340e..13f8780 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2458,6 +2458,11 @@
         public static final String TTS_DEFAULT_VARIANT = "tts_default_variant";
 
         /**
+         * Space delimited list of plugin packages that are enabled.
+         */
+        public static final String TTS_ENABLED_PLUGINS = "tts_enabled_plugins";
+
+        /**
          * Whether to notify the user of open networks.
          * <p>
          * If not connected and the scan results have an open network, we will
@@ -3286,6 +3291,7 @@
             TTS_DEFAULT_SYNTH,
             TTS_DEFAULT_LANG,
             TTS_DEFAULT_COUNTRY,
+            TTS_ENABLED_PLUGINS,
             WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
             WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY,
             WIFI_NUM_ALLOWED_CHANNELS,
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index ec7424ba..e901cc5 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1160,6 +1160,14 @@
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         super.onLayout(changed, l, t, r, b);
         mInLayout = true;
+        if (changed) {
+            int childCount = getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                getChildAt(i).forceLayout();
+            }
+            mRecycler.markChildrenDirty();
+        }
+
         layoutChildren();
         mInLayout = false;
         
@@ -4142,6 +4150,25 @@
             mCurrentScrap = scrapViews[0];
             mScrapViews = scrapViews;
         }
+        
+        public void markChildrenDirty() {
+            if (mViewTypeCount == 1) {
+                final ArrayList<View> scrap = mCurrentScrap;
+                final int scrapCount = scrap.size();
+                for (int i = 0; i < scrapCount; i++) {
+                    scrap.get(i).forceLayout();
+                }
+            } else {
+                final int typeCount = mViewTypeCount;
+                for (int i = 0; i < typeCount; i++) {
+                    final ArrayList<View> scrap = mScrapViews[i];
+                    final int scrapCount = scrap.size();
+                    for (int j = 0; j < scrapCount; j++) {
+                        scrap.get(j).forceLayout();
+                    }
+                }
+            }
+        }
 
         public boolean shouldRecycleViewType(int viewType) {
             return viewType >= 0;
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index 9537ba0..5b52107 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -660,14 +660,20 @@
 
                 final boolean below = !mPopup.isAboveAnchor();
 
-                final ListAdapter adapter = mDropDownList.getAdapter();
-                final boolean allEnabled = adapter.areAllItemsEnabled();
+                final ListAdapter adapter = mAdapter;
+                
+                boolean allEnabled;
+                int firstItem = Integer.MAX_VALUE;
+                int lastItem = Integer.MIN_VALUE;
 
-                final int firstItem = allEnabled ? 0 :
-                        mDropDownList.lookForSelectablePosition(0, true);
-                final int lastItem = allEnabled ? adapter.getCount() - 1 :
-                        mDropDownList.lookForSelectablePosition(adapter.getCount() - 1, false);
-
+                if (adapter != null) {
+                    allEnabled = adapter.areAllItemsEnabled();
+                    firstItem = allEnabled ? 0 :
+                            mDropDownList.lookForSelectablePosition(0, true);
+                    lastItem = allEnabled ? adapter.getCount() - 1 :
+                            mDropDownList.lookForSelectablePosition(adapter.getCount() - 1, false);                    
+                }
+                
                 if ((below && keyCode == KeyEvent.KEYCODE_DPAD_UP && curIndex <= firstItem) ||
                         (!below && keyCode == KeyEvent.KEYCODE_DPAD_DOWN && curIndex >= lastItem)) {
                     // When the selection is at the top, we block the key
@@ -985,6 +991,11 @@
 
     /** {@inheritDoc} */
     public void onFilterComplete(int count) {
+        updateDropDownForFilter(count);
+
+    }
+
+    private void updateDropDownForFilter(int count) {
         // Not attached to window, don't update drop-down
         if (getWindowVisibility() == View.GONE) return;
 
@@ -1214,18 +1225,30 @@
         ViewGroup dropDownView;
         int otherHeights = 0;
 
-        if (mAdapter != null) {
+        final ListAdapter adapter = mAdapter;
+        if (adapter != null) {
             InputMethodManager imm = InputMethodManager.peekInstance();
             if (imm != null) {
-                int N = mAdapter.getCount();
-                if (N > 20) N = 20;
-                CompletionInfo[] completions = new CompletionInfo[N];
-                for (int i = 0; i < N; i++) {
-                    Object item = mAdapter.getItem(i);
-                    long id = mAdapter.getItemId(i);
-                    completions[i] = new CompletionInfo(id, i,
-                            convertSelectionToString(item));
+                final int count = Math.min(adapter.getCount(), 20);
+                CompletionInfo[] completions = new CompletionInfo[count];
+                int realCount = 0;
+
+                for (int i = 0; i < count; i++) {
+                    if (adapter.isEnabled(i)) {
+                        realCount++;
+                        Object item = adapter.getItem(i);
+                        long id = adapter.getItemId(i);
+                        completions[i] = new CompletionInfo(id, i,
+                                convertSelectionToString(item));
+                    }
                 }
+                
+                if (realCount != count) {
+                    CompletionInfo[] tmp = new CompletionInfo[realCount];
+                    System.arraycopy(completions, 0, tmp, 0, realCount);
+                    completions = tmp;
+                }
+
                 imm.displayCompletions(this, completions);
             }
         }
@@ -1253,7 +1276,7 @@
 
             mDropDownList = new DropDownListView(context);
             mDropDownList.setSelector(mDropDownListHighlight);
-            mDropDownList.setAdapter(mAdapter);
+            mDropDownList.setAdapter(adapter);
             mDropDownList.setVerticalFadingEdgeEnabled(true);
             mDropDownList.setOnItemClickListener(mDropDownItemClickListener);
             mDropDownList.setFocusable(true);
@@ -1599,6 +1622,16 @@
             if (isPopupShowing()) {
                 // This will resize the popup to fit the new adapter's content
                 showDropDown();
+            } else if (mAdapter != null) {
+                // If the popup is not showing already, showing it will cause
+                // the list of data set observers attached to the adapter to
+                // change. We can't do it from here, because we are in the middle
+                // of iterating throught he list of observers.
+                post(new Runnable() {
+                    public void run() {
+                        updateDropDownForFilter(mAdapter.getCount());
+                    }
+                });
             }
         }
 
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index 65a4673..e27bb4fe 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -304,8 +304,8 @@
                             childLeft = parentLeft + lp.leftMargin;
                             break;
                         case Gravity.CENTER_HORIZONTAL:
-                            childLeft = parentLeft + (parentRight - parentLeft + lp.leftMargin +
-                                    lp.rightMargin - width) / 2;
+                            childLeft = parentLeft + (parentRight - parentLeft - width) / 2 +
+                                    lp.leftMargin - lp.rightMargin;
                             break;
                         case Gravity.RIGHT:
                             childLeft = parentRight - width - lp.rightMargin;
@@ -319,8 +319,8 @@
                             childTop = parentTop + lp.topMargin;
                             break;
                         case Gravity.CENTER_VERTICAL:
-                            childTop = parentTop + (parentBottom - parentTop + lp.topMargin +
-                                    lp.bottomMargin - height) / 2;
+                            childTop = parentTop + (parentBottom - parentTop - height) / 2 +
+                                    lp.topMargin - lp.bottomMargin;
                             break;
                         case Gravity.BOTTOM:
                             childTop = parentBottom - height - lp.bottomMargin;
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index cf2ed86..0378328 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -1048,16 +1048,18 @@
         if (isShowing() && mPopupView != null) {
             unregisterForScrollChanged();
 
-            mWindowManager.removeView(mPopupView);
-
-            if (mPopupView != mContentView && mPopupView instanceof ViewGroup) {
-                ((ViewGroup) mPopupView).removeView(mContentView);
-            }
-            mPopupView = null;
-            mIsShowing = false;
-
-            if (mOnDismissListener != null) {
-                mOnDismissListener.onDismiss();
+            try {
+                mWindowManager.removeView(mPopupView);                
+            } finally {
+                if (mPopupView != mContentView && mPopupView instanceof ViewGroup) {
+                    ((ViewGroup) mPopupView).removeView(mContentView);
+                }
+                mPopupView = null;
+                mIsShowing = false;
+    
+                if (mOnDismissListener != null) {
+                    mOnDismissListener.onDismiss();
+                }
             }
         }
     }
diff --git a/core/java/com/android/internal/util/HierarchicalStateMachine.java b/core/java/com/android/internal/util/HierarchicalStateMachine.java
index bebf051..7d7f130 100644
--- a/core/java/com/android/internal/util/HierarchicalStateMachine.java
+++ b/core/java/com/android/internal/util/HierarchicalStateMachine.java
@@ -1167,6 +1167,21 @@
         return Message.obtain(mHsmHandler, what, obj);
     }
 
+
+    /**
+     * Enqueue a message to this state machine.
+     */
+    public final void sendMessage(int what) {
+        mHsmHandler.sendMessage(obtainMessage(what));
+    }
+
+    /**
+     * Enqueue a message to this state machine.
+     */
+    public final void sendMessage(int what, Object obj) {
+        mHsmHandler.sendMessage(obtainMessage(what,obj));
+    }
+
     /**
      * Enqueue a message to this state machine.
      */
@@ -1177,6 +1192,20 @@
     /**
      * Enqueue a message to this state machine after a delay.
      */
+    public final void sendMessageDelayed(int what, long delayMillis) {
+        mHsmHandler.sendMessageDelayed(obtainMessage(what), delayMillis);
+    }
+
+    /**
+     * Enqueue a message to this state machine after a delay.
+     */
+    public final void sendMessageDelayed(int what, Object obj, long delayMillis) {
+        mHsmHandler.sendMessageDelayed(obtainMessage(what, obj), delayMillis);
+    }
+
+    /**
+     * Enqueue a message to this state machine after a delay.
+     */
     public final void sendMessageDelayed(Message msg, long delayMillis) {
         mHsmHandler.sendMessageDelayed(msg, delayMillis);
     }
@@ -1185,6 +1214,22 @@
      * Enqueue a message to the front of the queue for this state machine.
      * Protected, may only be called by instances of HierarchicalStateMachine.
      */
+    protected final void sendMessageAtFrontOfQueue(int what, Object obj) {
+        mHsmHandler.sendMessageAtFrontOfQueue(obtainMessage(what, obj));
+    }
+
+    /**
+     * Enqueue a message to the front of the queue for this state machine.
+     * Protected, may only be called by instances of HierarchicalStateMachine.
+     */
+    protected final void sendMessageAtFrontOfQueue(int what) {
+        mHsmHandler.sendMessageAtFrontOfQueue(obtainMessage(what));
+    }
+
+    /**
+     * Enqueue a message to the front of the queue for this state machine.
+     * Protected, may only be called by instances of HierarchicalStateMachine.
+     */
     protected final void sendMessageAtFrontOfQueue(Message msg) {
         mHsmHandler.sendMessageAtFrontOfQueue(msg);
     }
diff --git a/core/res/res/layout-land/usb_storage_activity.xml b/core/res/res/layout-land/usb_storage_activity.xml
index d714479..50ca569 100644
--- a/core/res/res/layout-land/usb_storage_activity.xml
+++ b/core/res/res/layout-land/usb_storage_activity.xml
@@ -24,7 +24,7 @@
 
         <TextView android:id="@+id/banner"
             android:layout_centerHorizontal="true"
-            android:layout_below="@id/icon"
+            android:layout_alignParentTop="true"
             android:layout_marginTop="10dip"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
@@ -45,8 +45,8 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_centerHorizontal="true"
-            android:layout_below="@id/message"
-            android:layout_marginTop="20dip"
+            android:layout_alignParentBottom="true"
+            android:layout_marginBottom="20dip"
             >
 
             <Button android:id="@+id/mount_button" 
@@ -64,6 +64,13 @@
                 android:paddingRight="18dip"
                 android:text="@string/usb_storage_stop_button_mount"
                 />
+            <ProgressBar android:id="@+id/progress"
+                android:visibility="gone"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:indeterminate="true"
+                style="?android:attr/progressBarStyle"
+                />
 
         </RelativeLayout>
     </RelativeLayout>
diff --git a/core/res/res/layout/usb_storage_activity.xml b/core/res/res/layout/usb_storage_activity.xml
index 86bfadb..76c30fd 100644
--- a/core/res/res/layout/usb_storage_activity.xml
+++ b/core/res/res/layout/usb_storage_activity.xml
@@ -37,8 +37,8 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_centerHorizontal="true"
-        android:layout_below="@id/message"
-        android:layout_marginTop="20dip"
+        android:layout_alignParentBottom="true"
+        android:layout_marginBottom="20dip"
         >
 
         <Button android:id="@+id/mount_button" 
@@ -56,6 +56,13 @@
             android:paddingRight="18dip"
             android:text="@string/usb_storage_stop_button_mount"
             />
+        <ProgressBar android:id="@+id/progress"
+            android:visibility="gone"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:indeterminate="true"
+            style="?android:attr/progressBarStyle"
+            />
 
     </RelativeLayout>
 </RelativeLayout>
diff --git a/core/tests/coretests/src/android/os/HierarchicalStateMachineTest.java b/core/tests/coretests/src/android/os/HierarchicalStateMachineTest.java
index 20c55c2..c51fecc 100644
--- a/core/tests/coretests/src/android/os/HierarchicalStateMachineTest.java
+++ b/core/tests/coretests/src/android/os/HierarchicalStateMachineTest.java
@@ -109,7 +109,7 @@
         synchronized (smQuitTest) {
             // Send 6 messages
             for (int i = 1; i <= 6; i++) {
-                smQuitTest.sendMessage(smQuitTest.obtainMessage(i));
+                smQuitTest.sendMessage(i);
             }
 
             // First two are ignored
@@ -297,8 +297,8 @@
 
         synchronized (sm1) {
             // Send two messages
-            sm1.sendMessage(sm1.obtainMessage(TEST_CMD_1));
-            sm1.sendMessage(sm1.obtainMessage(TEST_CMD_2));
+            sm1.sendMessage(TEST_CMD_1);
+            sm1.sendMessage(TEST_CMD_2);
 
             try {
                 // wait for the messages to be handled
@@ -402,8 +402,8 @@
 
         synchronized (sm2) {
             // Send two messages
-            sm2.sendMessage(sm2.obtainMessage(TEST_CMD_1));
-            sm2.sendMessage(sm2.obtainMessage(TEST_CMD_2));
+            sm2.sendMessage(TEST_CMD_1);
+            sm2.sendMessage(TEST_CMD_2);
 
             try {
                 // wait for the messages to be handled
@@ -494,8 +494,8 @@
 
         synchronized (sm3) {
             // Send two messages
-            sm3.sendMessage(sm3.obtainMessage(TEST_CMD_1));
-            sm3.sendMessage(sm3.obtainMessage(TEST_CMD_2));
+            sm3.sendMessage(TEST_CMD_1);
+            sm3.sendMessage(TEST_CMD_2);
 
             try {
                 // wait for the messages to be handled
@@ -587,8 +587,8 @@
 
         synchronized (sm4) {
             // Send two messages
-            sm4.sendMessage(sm4.obtainMessage(TEST_CMD_1));
-            sm4.sendMessage(sm4.obtainMessage(TEST_CMD_2));
+            sm4.sendMessage(TEST_CMD_1);
+            sm4.sendMessage(TEST_CMD_2);
 
             try {
                 // wait for the messages to be handled
@@ -861,12 +861,12 @@
 
         synchronized (sm5) {
             // Send 6 messages
-            sm5.sendMessage(sm5.obtainMessage(TEST_CMD_1));
-            sm5.sendMessage(sm5.obtainMessage(TEST_CMD_2));
-            sm5.sendMessage(sm5.obtainMessage(TEST_CMD_3));
-            sm5.sendMessage(sm5.obtainMessage(TEST_CMD_4));
-            sm5.sendMessage(sm5.obtainMessage(TEST_CMD_5));
-            sm5.sendMessage(sm5.obtainMessage(TEST_CMD_6));
+            sm5.sendMessage(TEST_CMD_1);
+            sm5.sendMessage(TEST_CMD_2);
+            sm5.sendMessage(TEST_CMD_3);
+            sm5.sendMessage(TEST_CMD_4);
+            sm5.sendMessage(TEST_CMD_5);
+            sm5.sendMessage(TEST_CMD_6);
 
             try {
                 // wait for the messages to be handled
@@ -950,7 +950,7 @@
         class S1 extends HierarchicalState {
 
             @Override protected void enter() {
-                sendMessage(obtainMessage(TEST_CMD_1));
+                sendMessage(TEST_CMD_1);
             }
 
             @Override protected boolean processMessage(Message message) {
@@ -994,7 +994,7 @@
         synchronized (sm6) {
             // Send a message
             sentTimeMsg2 = SystemClock.elapsedRealtime();
-            sm6.sendMessageDelayed(sm6.obtainMessage(TEST_CMD_2), DELAY_TIME);
+            sm6.sendMessageDelayed(TEST_CMD_2, DELAY_TIME);
 
             try {
                 // wait for the messages to be handled
@@ -1045,7 +1045,7 @@
                 return true;
             }
             @Override protected void exit() {
-                sendMessage(obtainMessage(TEST_CMD_2));
+                sendMessage(TEST_CMD_2);
             }
         }
 
@@ -1053,7 +1053,7 @@
 
             @Override protected void enter() {
                 // Send a delayed message as a watch dog
-                sendMessageDelayed(obtainMessage(TEST_CMD_3), SM7_DELAY_TIME);
+                sendMessageDelayed(TEST_CMD_3, SM7_DELAY_TIME);
             }
 
             @Override protected boolean processMessage(Message message) {
@@ -1103,7 +1103,7 @@
         synchronized (sm7) {
             // Send a message
             sentTimeMsg2 = SystemClock.elapsedRealtime();
-            sm7.sendMessage(sm7.obtainMessage(TEST_CMD_1));
+            sm7.sendMessage(TEST_CMD_1);
 
             try {
                 // wait for the messages to be handled
@@ -1178,7 +1178,7 @@
         synchronized (sm) {
             // Send 2 messages
             for (int i = 1; i <= 2; i++) {
-                sm.sendMessage(sm.obtainMessage(i));
+                sm.sendMessage(i);
             }
 
             try {
@@ -1262,7 +1262,7 @@
             // Send messages to each of the state machines
             for (StateMachineSharedThread sm : sms) {
                 for (int i = 1; i <= 4; i++) {
-                    sm.sendMessage(sm.obtainMessage(i));
+                    sm.sendMessage(i);
                 }
             }
 
@@ -1295,8 +1295,8 @@
         Hsm1 sm = Hsm1.makeHsm1();
 
         // Send messages
-        sm.sendMessage(sm.obtainMessage(Hsm1.CMD_1));
-        sm.sendMessage(sm.obtainMessage(Hsm1.CMD_2));
+        sm.sendMessage(Hsm1.CMD_1);
+        sm.sendMessage(Hsm1.CMD_2);
 
         synchronized (sm) {
             // Wait for the last state machine to notify its done
@@ -1389,7 +1389,7 @@
             switch(message.what) {
             case CMD_2:
                 // CMD_2 will arrive in mS2 before CMD_3
-                sendMessage(obtainMessage(CMD_3));
+                sendMessage(CMD_3);
                 deferMessage(message);
                 transitionTo(mS2);
                 retVal = true;
@@ -1435,7 +1435,7 @@
             Log.d(TAG, "S2.processMessage what=" + message.what);
             switch(message.what) {
             case(CMD_2):
-                sendMessage(obtainMessage(CMD_4));
+                sendMessage(CMD_4);
                 retVal = true;
                 break;
             case(CMD_3):
@@ -1457,7 +1457,7 @@
     class P2 extends HierarchicalState {
         @Override protected void enter() {
             Log.d(TAG, "P2.enter");
-            sendMessage(obtainMessage(CMD_5));
+            sendMessage(CMD_5);
         }
         @Override protected boolean processMessage(Message message) {
             Log.d(TAG, "P2.processMessage what=" + message.what);
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index 13d752a..dce78c4 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -143,6 +143,7 @@
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></li>
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></li>
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/path-permission-element.html">&lt;path-permission&gt;</a></li>
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></li>
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/permission-group-element.html">&lt;permission-group&gt;</a></li>
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/permission-tree-element.html">&lt;permission-tree&gt;</a></li>
@@ -198,7 +199,18 @@
           </a></li>
       <li><a href="<?cs var:toroot?>guide/topics/wireless/bluetooth.html">
             <span class="en">Bluetooth</span>
-          </a> <span class="new">new!</span></li>
+          </a></li>
+      <li class="toggle-list">
+        <div><a href="<?cs var:toroot?>guide/topics/search/index.html">
+            <span class="en">Search</span>
+          </a> <span class="new">new!</span></div>
+          <ul>
+            <li><a href="<?cs var:toroot?>guide/topics/search/search-dialog.html">Using the Android Search Dialog</a></li>
+            <li><a href="<?cs var:toroot?>guide/topics/search/adding-recent-query-suggestions.html">Adding Recent Query Suggestions</a></li>
+            <li><a href="<?cs var:toroot?>guide/topics/search/adding-custom-suggestions.html">Adding Custom Suggestions</a></li>
+            <li><a href="<?cs var:toroot?>guide/topics/search/searchable-config.html">Searchable Configuration</a></li>
+          </ul>
+      </li>
     </ul>
   </li>
   
diff --git a/docs/html/guide/topics/search/adding-custom-suggestions.jd b/docs/html/guide/topics/search/adding-custom-suggestions.jd
new file mode 100644
index 0000000..9ea4c8b
--- /dev/null
+++ b/docs/html/guide/topics/search/adding-custom-suggestions.jd
@@ -0,0 +1,699 @@
+page.title=Adding Custom Suggestions
+parent.title=Search
+parent.link=index.html
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+<h2>Key classes</h2>
+<ol>
+<li>{@link android.app.SearchManager}</li>
+<li>{@link android.content.SearchRecentSuggestionsProvider}</li>
+<li>{@link android.content.ContentProvider}</li>
+</ol>
+<h2>In this document</h2>
+<ol>
+<li><a href="#TheBasics">The Basics</a></li>
+<li><a href="#CustomSearchableConfiguration">Modifying the searchable configuration</a></li>
+<li><a href="#CustomContentProvider">Creating a Content Provider</a>
+  <ol>
+    <li><a href="#HandlingSuggestionQuery">Handling a suggestion query</a></li>
+    <li><a href="#SuggestionTable">Building a suggestion table</a></li>
+  </ol>
+</li>
+<li><a href="#IntentForSuggestions">Declaring an Intent for suggestions</a>
+  <ol>
+    <li><a href="#IntentAction">Declaring the Intent action</a></li>
+    <li><a href="#IntentData">Declaring the Intent data</a></li>
+  </ol>
+</li>
+<li><a href="#HandlingIntent">Handling the Intent</a></li>
+<li><a href="#RewritingQueryText">Rewriting the query text</a></li>
+<li><a href="#QSB">Exposing search suggestions to Quick Search Box</a></li>
+</ol>
+<h2>See also</h2>
+<ol>
+<li><a href="searchable-config.html">Searchable Configuration</a></li>
+<li><a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a></li>
+<li><a href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable
+Dictionary sample app</a></li>
+</ol>
+</div>
+</div>
+
+<p>The Android search framework provides the ability for your application to
+provide suggestions while the user types into the Android search dialog. In this guide, you'll learn
+how to create custom suggestions. These are suggestions based on custom data provided by your
+application. For example, if your application is a word dictionary, you can suggest words from the
+dictionary that match the text entered so far. These are the most valuable suggestions because you
+can effectively predict what the user wants and provide instant access to it. Once you provide
+custom suggestions, you then make them available to the system-wide Quick Search Box, providing
+access to your content from outside your application.</p>
+
+<p>Before you begin, you need to have implemented the Android search dialog for searches in your
+application. If you haven't done this, see <a href="search-dialog.html">Using the Android Search
+Dialog</a>.</p>
+
+
+<h2 id="TheBasics">The Basics</h2>
+
+<img src="{@docRoot}images/search/search-suggest-custom.png" alt="" height="417"
+style="float:right;clear:right;" />
+
+<p>When the user selects a custom suggestions, the Search Manager will send a customized Intent to
+your searchable Activity. Whereas a normal search query will send an Intent with the {@link
+android.content.Intent#ACTION_SEARCH} action, you can instead define your custom suggestions to use
+{@link android.content.Intent#ACTION_VIEW} (or any other action), and also include additional data
+that's relevant to the selected suggestion. Continuing
+the dictionary example, when the user selects a suggestion, your application can immediately
+open the definition for that word, instead of searching the dictionary for matches.</p>
+
+<p>To provide custom suggestions, you need to do the following:</p>
+
+<ul>
+  <li>Implement a basic searchable Activity, as described in <a
+href="search-dialog.html">Using the Android Search Dialog</a>.</li>
+  <li>Build a table (such as in an {@link android.database.sqlite.SQLiteDatabase}) for your
+suggestions and format the table with required columns.</li>
+  <li>Create a <a href="{@docRoot}guide/topics/providers/content-providers.html">Content
+Provider</a> that has access to your suggestions table and declare the provider
+in your manifest.</li>
+  <li>Declare the type of {@link android.content.Intent} to be sent when the user selects a
+suggestion (including a custom action and custom data). </li>
+  <li>Modify the searchable configuration with information about the content provider.</li>
+</ul>
+
+<p>Just like the Search Manager handles the rendering of the search dialog, it will also do the work
+to display all search suggestions below the search dialog. All you need to do is provide a source
+from which the suggestions can be retrieved.</p>
+
+<p class="note"><strong>Note:</strong> If you're not familiar with creating Content
+Providers, please read the <a href="{@docRoot}guide/topics/providers/content-providers.html">Content
+Providers</a> developer guide before you continue.</p>
+
+<p>When the Search Manager identifies that your Activity is searchable and also provides search
+suggestions, the following procedure will take place as soon as the user types into the Android
+search box:</p>
+
+<ul>
+  <li>The Search Manager takes the search query text (whatever has been typed so far) and performs a
+query to the content provider that manages your suggestions.</li>
+  <li>Your content provider then returns a {@link android.database.Cursor} that points to all
+suggestions that are relevant to the search query text.</li>
+  <li>The Search Manager then displays the list of suggestions provided by the Cursor (as
+demonstrated in the screenshot to the right).</li>
+</ul>
+
+<p>At this point, the following may happen:</p>
+
+<ul>
+  <li>If the user types another key, or changes the query in any way, the above steps are repeated
+and the suggestion list is updated as appropriate. </li>
+  <li>If the user executes the search, the suggestions are ignored and the search is delivered 
+to your searchable Activity using the normal {@link android.content.Intent#ACTION_SEARCH}
+Intent.</li>
+  <li>If the user selects a suggestion, an Intent is sent to your searchable Activity, carrying a
+custom action and custom data so that your application can open the suggested content.</li>
+</ul>
+
+
+
+<h2 id="CustomSearchableConfiguration">Modifying the searchable configuration</h2>
+
+<p>To add support for custom suggestions, add the {@code android:searchSuggestAuthority} attribute
+to the {@code &lt;searchable&gt;} element in your searchable configuration file. For example:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
+    android:label="@string/app_label"
+    android:hint="@string/search_hint"
+    android:searchSuggestAuthority="my.package.MyCustomSuggestionProvider" >
+&lt;/searchable>
+</pre>
+
+<p>You may require some additional attributes, depending on the type of Intent you attach
+to each suggestion and how you want to format queries to your content provider. The other optional
+attributes are discussed in the relevant sections below.</p>
+
+
+<h2 id="CustomContentProvider">Creating a Content Provider</h2>
+
+<p>Creating a content provider for custom suggestions requires previous knowledge about Content
+Providers that's covered in the <a
+href="{@docRoot}guide/topics/providers/content-providers.html">Content Provider</a> developer
+guide. For the most part, a content provider for custom suggestions is the
+same as any other content provider. However, for each suggestion you provide, the respective row in
+the {@link android.database.Cursor} must include specific columns that the Search Manager
+understands.</p>
+
+<p>When the user starts typing into the search dialog, the Search Manager will query your Content
+Provider for suggestions by calling {@link
+android.content.ContentProvider#query(Uri,String[],String,String[],String) query()} each time
+a letter is typed. In your implementation of {@link
+android.content.ContentProvider#query(Uri,String[],String,String[],String) query()}, your
+content provider must search your suggestion data and return a {@link
+android.database.Cursor} that points to the rows you determine to be good suggestions.</p>
+
+<p>The following two sections describe how the Search Manager will send requests to your Content
+Provider and how you can handle them, and define the columns that the Search Manager understands and
+expects to be provided in the {@link android.database.Cursor} returned with each query.</p>
+
+
+<h3 id="HandlingSuggestionQuery">Handling the suggestion query</h3>
+
+<p>When the Search Manager makes a request for suggestions from your content provider, it will call
+{@link android.content.ContentProvider#query(Uri,String[],String,String[],String)}. You must
+implement this method in your content provider so that it will search your suggestions and return a
+Cursor that contains the suggestions you deem relevant.</p>
+
+<p>Here's a summary of the parameters that the Search Manager will pass to your {@link
+android.content.ContentProvider#query(Uri,String[],String,String[],String) query()} method
+(listed in order):</p>
+
+<dl>
+  <dt><code>uri</code></dt>
+  <dd>This will always be a content {@link android.net.Uri}, formatted as:
+<pre class="no-pretty-print">
+content://<em>your.authority</em>/<em>optional.suggest.path</em>/<em>{@link
+android.app.SearchManager#SUGGEST_URI_PATH_QUERY}</em>
+</pre>
+<p>The default behavior is for Search Manager to pass this URI and append it with the query text.
+For example:</p>
+<pre class="no-pretty-print">
+content://<em>your.authority</em>/<em>optional.suggest.path</em>/<em>{@link
+android.app.SearchManager#SUGGEST_URI_PATH_QUERY}</em>/puppies
+</pre>
+<p>The query text on the end will be encoded using URI encoding rules, so you may need to decode
+it.</p>
+<p>The <em>{@code optional.suggest.path}</em> portion is only included in the URI if you have set
+such a path in your searchable configuration file with the {@code android:searchSuggestPath}
+attribute. This is only needed if you use the same content provider for multiple searchable
+activities, in which case you need to disambiguate the source of the suggestion query.</p>
+<p>Note that {@link android.app.SearchManager#SUGGEST_URI_PATH_QUERY} is not the literal
+string provided in the URI, but a constant that you should use if you need to refer to this
+path.</p>
+  </dd>
+
+  <dt><code>projection</code></dt>
+  <dd>This is always null</dd>
+
+  <dt><code>selection</code></dt>
+  <dd>This is the value provided in the {@code android:searchSuggestSelection} attribute of
+your searchable configuration file, or null if you have not declared the {@code
+android:searchSuggestSelection} attribute. More about this below.</dd>
+
+  <dt><code>selectionArgs</code></dt>
+  <dd>This contains the search query as the first (and only) element of the array if you have
+declared the {@code android:searchSuggestSelection} attribute in your searchable configuration. If
+you have not declared {@code android:searchSuggestSelection}, then this parameter is null. More
+about this below.</dd>
+
+  <dt><code>sortOrder</code></dt>
+  <dd>This is always null</dd>
+</dl>
+
+<p>As you may have realized, there are two ways by which the Search Manager can send you the search
+query text. The default manner is for the query text to be included as the last path of the content
+URI that is passed in the {@code uri} parameter. However, if you include a selection value in your 
+searchable configuration's {@code
+android:searchSuggestSelection} attribute, then the query text will instead be passed as the first
+element of the {@code selectionArgs} string array. Both options are summarized below.</p>
+
+
+<h4>Get the query in the Uri</h4>
+
+<p>By default, the query will be appended as the last segment of the {@code uri}
+parameter (a {@link android.net.Uri} object). To retrieve the query text in this case, simply use
+{@link android.net.Uri#getLastPathSegment()}. For example:</p>
+
+<pre>
+String query = uri.getLastPathSegment().toLowerCase();
+</pre>
+
+<p>This will return the last segment of the Uri, which is the query text entered in the search
+dialog.</p>
+
+
+
+<h4>Get the query in the selection arguments</h4>
+
+<p>Instead of using the URI, you may decide it makes more sense for your {@link
+android.content.ContentProvider#query(Uri,String[],String,String[],String) query()} method to
+receive everything it needs to perform the look-up and you want the
+{@code selection} and {@code selectionArgs} parameters to carry values. In this case, you can
+add the {@code android:searchSuggestSelection} attribute to your searchable configuration with your
+SQLite selection string. In this selection string, you can include a question mark ("?") as
+a placeholder for the actual search query. This selection string will be delivered as the
+{@code selection} string parameter, and the query entered into the search dialog will be delivered
+as the first element in the {@code selectionArgs} string array parameter.</p>
+
+<p>For example, here's how you might form the {@code android:searchSuggestSelection} attribute to
+create a full-text search statement:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
+    android:label="@string/app_label"
+    android:hint="@string/search_hint"
+    android:searchSuggestAuthority="my.package.MyCustomSuggestionProvider"
+    android:searchSuggestIntentAction="android.Intent.action.VIEW"
+    android:searchSuggestSelection="word MATCH ?">
+&lt;/searchable>
+</pre>
+
+<p>When you then receive the {@code selection} and {@code selectionArgs} parameters in your {@link
+android.content.ContentProvider#query(Uri,String[],String,String[],String) ContentProvider.query()}
+method, they will carry the selection ("word MATCH ?") and the query text, respectively. When
+these are passed to an SQLite {@link
+android.database.sqlite.SQLiteDatabase#query(String,String[],String,String[],String,String,
+String) query} method, they will be synthesized together (replacing the question mark with the query
+text, wrapped in single-quotes). Note that if you chose this method and need to add any wildcards to
+your query text, you must do so by appending (and/or prefixing) them to the {@code selectionArgs}
+parameter, because this is the value that will be wrapped in quotes and inserted in place of the
+question mark.</p>
+
+<p class="note"><strong>Tip:</strong> If you don't want to define a selection clause in
+the {@code android:searchSuggestSelection} attribute, but would still like to receive the query
+text in the {@code selectionArgs} parameter, simply provide a non-null value for the {@code
+android:searchSuggestSelection} attribute. This will trigger the query to be passed in {@code
+selectionArgs} and you can ignore the {@code selection} parameter. In this way, you can instead
+define the actual selection clause at a lower level so that your content provider doesn't have to
+handle it.</p>
+
+
+
+<h3 id="SuggestionTable">Building a suggestion table</h3>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+<h2>Creating a Cursor on the fly</h2>
+<p>If your search suggestions are not stored in a table format using the columns required by the
+Search Manager, then you can search your suggestion data for matches and then format them
+into the necessary table on the fly. To do so, create a {@link android.database.MatrixCursor} using
+the required column names and then add a row for each suggestion using {@link
+android.database.MatrixCursor#addRow(Object[])}. Return the final product from your Content
+Provider's {@link
+android.content.ContentProvider#query(Uri,String[],String,String[],String) query()} method.</p>
+</div>
+</div>
+
+<p>When you return suggestions to the Search Manager with a {@link android.database.Cursor}, the
+Search Manager expects there to be specific columns in each row. So, regardless of whether you
+decide to store
+your suggestion data in an SQLite database on the device, a database on a web server, or another
+format on the device or web, you must format the suggestions as rows in a table and
+present them with a {@link android.database.Cursor}. There are several columns that the Search
+Manager will understand, but only two are required:</p>
+
+<dl>
+  <dt>{@link android.provider.BaseColumns#_ID}</dt>
+  <dd>This is the unique row ID for each suggestion. The search dialog requires this in order
+to present the suggestions in a ListView.</dd>
+  <dt>{@link android.app.SearchManager#SUGGEST_COLUMN_TEXT_1}</dt>
+  <dd>This is the line of text that will be presented to the user as a suggestion.</dd>
+</dl>
+
+<p>The following columns are all optional (and most will be discussed further in the following
+sections, so you may want to skip this list for now):</p>
+
+<dl>
+  <dt>{@link android.app.SearchManager#SUGGEST_COLUMN_TEXT_2}</dt>
+  <dd>If your Cursor  includes this column, then all suggestions will be provided in a two-line
+format. The data in this column will be displayed as a second, smaller line of text below the
+primary suggestion text. It can be null or empty to indicate no secondary text.</dd>
+  <dt>{@link android.app.SearchManager#SUGGEST_COLUMN_ICON_1}</dt>
+  <dd>If your Cursor  includes this column, then all suggestions will be provided in an
+icon-plus-text format with the icon on the left side. This value should be a reference to the
+icon. It can be null or zero to indicate no icon in this row.</dd>
+  <dt>{@link android.app.SearchManager#SUGGEST_COLUMN_ICON_2}</dt>
+  <dd>If your Cursor  includes this column, then all suggestions will be provided in an
+icon-plus-text format with the icon on the right side. This value should be a reference to the
+icon. It can be null or zero to indicate no icon in this row.</dd>
+  <dt>{@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_ACTION}</dt>
+  <dd>If this column exists and this element exists at the given row, this is the action that will
+be used when forming the suggestion's Intent . If the element is not provided, the action will be
+taken from the {@code android:searchSuggestIntentAction} field in your searchable configuration. At
+least one of these
+must be present for the suggestion to generate an Intent. Note: If your action is the same for all
+suggestions, it is more efficient to specify the action using {@code
+android:searchSuggestIntentAction} and omit this column from the Cursor .</dd>
+  <dt>{@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA}</dt>
+  <dd>If this column exists and this element exists at the given row, this is the data that will be
+used when forming the suggestion's Intent. If the element is not provided, the data will be taken
+from the {@code android:searchSuggestIntentData} field in your searchable configuration. If neither
+source is provided,
+the Intent's data field will be null. Note: If your data is the same for all suggestions, or can be
+described using a constant part and a specific ID, it is more efficient to specify it using {@code
+android:searchSuggestIntentData} and omit this column from the Cursor .
+</dd>
+  <dt>{@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA_ID}</dt>
+  <dd>If this column exists and this element exists at the given row, then "/" and this value will
+be appended to the data field in the Intent. This should only be used if the data field specified
+by the {@code android:searchSuggestIntentData} attribute in the searchable configuration has already
+been set to an appropriate base string.</dd>
+  <dt>{@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_EXTRA_DATA}</dt>
+  <dd>If this column exists and this element exists at a given row, this is the <em>extra</em> data
+that will be used when forming the suggestion's Intent. If not provided, the Intent's extra data
+field will be
+null. This column allows suggestions to provide additional arbitrary data which will be
+included as an extra in the Intent's {@link android.app.SearchManager#EXTRA_DATA_KEY} key.</dd>
+  <dt>{@link android.app.SearchManager#SUGGEST_COLUMN_QUERY}</dt>
+  <dd>If this column exists and this element exists at the given row, this is the data that will be
+used when forming the suggestion's query, included as an extra in the Intent's {@link
+android.app.SearchManager#QUERY} key. Required if suggestion's action is {@link
+android.content.Intent#ACTION_SEARCH}, optional otherwise.</dd>
+  <dt>{@link android.app.SearchManager#SUGGEST_COLUMN_SHORTCUT_ID}</dt>
+  <dd>Only used when providing suggestions for Quick Search Box. This column is used to indicate
+whether a search suggestion should be stored as a
+shortcut, and whether it should be validated. Shortcuts are usually formed when the user clicks a
+suggestion from Quick Search Box. If missing, the result will be stored as a shortcut and never
+refreshed. If set to {@link android.app.SearchManager#SUGGEST_NEVER_MAKE_SHORTCUT}, the result will
+not be stored as a shortcut.
+Otherwise, the shortcut id will be used to check back for for an up to date suggestion using
+{@link android.app.SearchManager#SUGGEST_URI_PATH_SHORTCUT}.</dd>
+  <dt>{@link android.app.SearchManager#SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING}</dt>
+  <dd>Only used when providing suggestions for Quick Search Box. This column is used to specify that
+a spinner should be shown instead of an icon from {@link
+android.app.SearchManager#SUGGEST_COLUMN_ICON_2}
+while the shortcut of this suggestion is being refreshed in Quick Search Box.</dd>
+</dl>
+
+<p>Again, most of these columns will be discussed in the relevant sections below, so don't worry if
+they don't make sense to you now.</p>
+
+
+
+<h2 id="IntentForSuggestions">Declaring an Intent for suggestions</h2>
+
+<p>When the user selects a suggestion from the list that appears below the search
+dialog (instead of performing a search), the Search Manager will send
+a custom {@link android.content.Intent} to your searchable Activity. You must define both the
+<em>action</em> and <em>data</em> for the Intent.</p>
+
+
+<h3 id="IntentAction">Declaring the Intent action</h3>
+
+<p>The most common Intent action for a custom suggestion is {@link
+android.content.Intent#ACTION_VIEW}, which is appropriate when
+you want to open something, like the definition for a word, a person's contact information, or a web
+page. However, the Intent action can be whatever you want and can even be different for each
+suggestion.</p>
+
+<p>To declare an Intent action that will be the same for all suggestions, define the action in
+the {@code android:searchSuggestIntentAction} attribute of your searchable configuration file. For
+example:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
+    android:label="@string/app_label"
+    android:hint="@string/search_hint"
+    android:searchSuggestAuthority="my.package.MySuggestionProvider"
+    android:searchSuggestIntentAction="android.Intent.action.VIEW" >
+&lt;/searchable>
+</pre>
+
+<p>If you want to declare an Intent action that's unique for each suggestion, add the {@link
+android.app.SearchManager#SUGGEST_COLUMN_INTENT_ACTION} column to
+your suggestions table and, for each suggestion, place in it the action to use (such as
+{@code "android.Intent.action.VIEW"}). </p>
+
+<p>You can also combine these two techniques. For instance, you can include the {@code
+android:searchSuggestIntentAction} attribute with an action to be used with all suggestions by
+default, then override this action for some suggestions by declaring a different action in the
+{@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_ACTION} column. If you do not include
+a value in the {@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_ACTION} column, then the
+Intent provided in the {@code android:searchSuggestIntentAction} attribute will be used.</p>
+
+<p class="note"><strong>Note</strong>: If you do not include the
+{@code android:searchSuggestIntentAction} attribute in your searchable configuration, then you
+<em>must</em> include a value in the {@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_ACTION}
+column for every suggestion, or the Intent will fail.</p>
+
+
+<h3 id="IntentData">Declaring Intent data</h3>
+
+<p>When the user selects a suggestion, your searchable Activity will receive the Intent with the
+action you've defined (as discussed in the previous section), but the Intent must also carry
+data in order for your Activity to identify which suggestions was selected. Specifically,
+the data should be something unique for each suggestion, such as the row ID for the suggestion in
+your suggestions table. When the Intent is received,
+you can retrieve the attached data with {@link android.content.Intent#getData()} or {@link
+android.content.Intent#getDataString()}.</p>
+
+<p>There are two ways to define the data that is included with the Intent:</p>
+
+<ol type="a">
+  <li>Define the data for each suggestion inside the {@link
+android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA} column of your suggestions table.</li>
+  <li>Fragment a data URI into two pieces: the portion common to all suggestions and the portion
+unique to each suggestion. Place these parts into the {@code android:searchSuggestIntentData}
+attribute of the searchable configuration and the {@link
+android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA_ID} column of your
+suggestions table, respectively.</li>
+</ol>
+
+<p>The first option is straight-forward. Simply provide all necessary data information for each
+Intent in the suggestions table by including the {@link
+android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA} column and then populating it with unique
+data for each row. The data from this column will be attached to the Intent exactly as it
+is found in this column. You can then retrieve it with with {@link android.content.Intent#getData()}
+or {@link android.content.Intent#getDataString()}.</p>
+
+<p class="note"><strong>Tip</strong>: It's usually easiest to use the table's row ID as the
+Intent data because it's always unique. And the easiest way to do that is by using the
+{@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA} column name as an alias for the row ID
+column. See the <a
+href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable Dictionary sample
+app</a> for an example in which {@link android.database.sqlite.SQLiteQueryBuilder} is used to
+create a projection map of column names to aliases.</p>
+
+<p>The second option is to fragment your data URI into the common piece and the unique piece.
+Declare the piece of the URI that is common to all suggestions in the {@code
+android:searchSuggestIntentData} attribute of your searchable configuration. For example:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
+    android:label="@string/app_label"
+    android:hint="@string/search_hint"
+    android:searchSuggestAuthority="my.package.MySuggestionProvider"
+    android:searchSuggestIntentAction="android.Intent.action.VIEW"
+    android:searchSuggestIntentData="content://my.package/datatable" >
+&lt;/searchable>
+</pre>
+
+<p>Now include the final path for each suggestion (the unique part) in the {@link
+android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA_ID}
+column of your suggestions table. When the user selects a suggestion, the Search Manager will take
+the string from {@code android:searchSuggestIntentData}, append a slash ("/") and then add the
+respective value from the {@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA_ID} column to
+form a complete content URI. You can then retrieve the {@link android.net.Uri} with with {@link
+android.content.Intent#getData()}.</p>
+
+<h4>Add more data</h4>
+
+<p>If you need to express even more information with your Intent, you can add another table column,
+{@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_EXTRA_DATA}, which can store additional
+information about the suggestion. The data saved in this column will be placed in {@link
+android.app.SearchManager#EXTRA_DATA_KEY} of the Intent's extra Bundle.</p>
+
+
+<h2 id="HandlingIntent">Handling the Intent</h2>
+
+<p>Now that your search dialog provides custom search suggestions with custom formatted Intents, you
+need your searchable Activity to handle these Intents as they are delivered once the user selects a
+suggestion. (This is, of course, in addition to handling the {@link
+android.content.Intent#ACTION_SEARCH} Intent, which your searchable Activity already does.)
+Accepting the new Intent is rather self-explanatory, so we'll skip straight to an example:</p>
+
+<pre>
+Intent intent = getIntent();
+if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
+    // Handle the normal search query case
+    String query = intent.getStringExtra(SearchManager.QUERY);
+    doSearch(query);
+} else if (Intent.ACTION_VIEW.equals(intent.getAction())) {
+    // Handle a suggestions click (because my suggestions all use ACTION_VIEW)
+    Uri data = intent.getData());
+    showResult(rowId);
+}
+</pre>
+
+<p>In this example, the Intent action is {@link
+android.content.Intent#ACTION_VIEW} and the data carries a complete URI pointing to the suggested
+item, as synthesized by the {@code android:searchSuggestIntentData} string and {@link
+android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA_ID} column. The URI is then passed to a local
+method that will query the content provider for the item specified by the URI and show it.</p>
+
+
+
+<h2 id="RewritingQueryText">Rewriting the query text</h2>
+
+<p>If the user navigates through the suggestions list using the device directional controls, the
+text in the search dialog won't change, by default. However, you can temporarily rewrite the
+user's query text as it appears in the text box with
+a query that matches the currently selected suggestion. This enables the user to see what query is
+being suggested (if appropriate) and then select the search box and edit the query before
+dispatching it as a search.</p>
+
+<p>You can rewrite the query text in the following ways:</p>
+
+<ol type="a">
+  <li>Add the {@code android:searchMode} attribute to your searchable configuration with the
+"queryRewriteFromText" value. In this case, the content from the suggestion's {@link
+android.app.SearchManager#SUGGEST_COLUMN_TEXT_1}
+column will be used to rewrite the query text.</li>
+  <li>Add the {@code android:searchMode} attribute to your searchable configuration with the
+"queryRewriteFromData" value. In this case, the content from the suggestion's
+{@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA} column will be used to rewrite the
+query text. Note that this should only
+be used with Uri's or other data formats that are intended to be user-visible, such as HTTP URLs.
+Internal Uri schemes should not be used to rewrite the query in this way.</li>
+  <li>Provide a unique query text string in the {@link
+android.app.SearchManager#SUGGEST_COLUMN_QUERY} column of your suggestions table. If this column is
+present and contains a value for the current suggestion, it will be used to rewrite the query text
+(and override either of the previous implementations).</li>
+</ol>
+
+
+<h2 id="QSB">Exposing search suggestions to Quick Search Box</h2>
+
+<p>Once your application is configured to provide custom search suggestions, making them available
+to the globally-accessible Quick Search Box is as easy as modifying your searchable configuration to
+include {@code android:includeInGlobalSearch} as "true".</p>
+
+<p>The only scenario in which additional work will be required is if your content provider  for
+custom suggestions requires a permission for read access. In which case, you need to add a special
+{@code &lt;path-permission>} element for the provider to grant Quick Search Box read access to your
+content provider. For example:</p>
+
+<pre>
+&lt;provider android:name="MySuggestionProvider"
+          android:authorities="my.package.authority"
+          android:readPermission="com.example.provider.READ_MY_DATA"
+          android:writePermission="com.example.provider.WRITE_MY_DATA">
+  &lt;path-permission android:pathPrefix="/search_suggest_query"
+                   android:readPermission="android.permission.GLOBAL_SEARCH" />
+&lt;/provider>
+</pre>
+
+<p>In this example, the provider restricts read and write access to the content. The
+{@code &lt;path-permission>} element amends the restriction by granting read access to content
+inside the {@code "/search_suggest_query"} path prefix when the {@code
+"android.permission.GLOBAL_SEARCH"} permission exists. This grants access to Quick Search Box
+so that it may query your content provider for suggestions.</p>
+
+<p>Content providers that enforce no permissions are already available to the search
+infrastructure.</p>
+
+
+<h3 id="EnablingSuggestions">Enabling suggestions on a device</h3>
+
+<p>When your application is configured to provide suggestions in Quick Search Box, it is not
+actually enabled to provide suggestions in Quick Search Box, by default. It is the user's choice
+whether to include suggestions from your application in the Quick Search Box. To enable search
+suggestions from your application, the user must open "Searchable items" (in Settings > Search) and
+enable your application as a searchable item.</p>
+
+<p>Each application that is available to Quick Search Box has an entry in the Searchable items
+settings page. The entry includes the name of the application and a short description of what
+content can be searched from the application and made available for suggestions in Quick Search Box.
+To define the description text for your searchable application, add the {@code
+android:searchSettingsDescription} attribute to your searchable configuration. For example:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
+    android:label="@string/app_label"
+    android:hint="@string/search_hint"
+    android:searchSuggestAuthority="my.package.MySuggestionProvider"
+    android:searchSuggestIntentAction="android.Intent.action.VIEW"
+    android:includeInGlobalSearch="true"
+    android:searchSettingsDescription="@string/search_description" >
+&lt;/searchable>
+</pre>
+
+<p>The string for {@code android:searchSettingsDescription} should be as concise as possible and
+state the content that is searchable. For example, "Artists, albums, and tracks" for a music
+application, or "Saved notes" for a notepad application. Providing this description is important so
+the user knows what kind of suggestions will be provided. This attribute should always be included
+when {@code android:includeInGlobalSearch} is "true".</p>
+
+<p>Remember that the user must visit this settings menu to enable search suggestions for your
+application before your search suggestions will appear in Quick Search Box. As such, if search is an
+important aspect of your application, then you may want to consider a way to message this to your
+users &mdash; perhaps with a note the first time they launch the app about how to enable search
+suggestions for Quick Search Box.</p>
+
+
+<h3 id="ManagingShortcuts">Managing Quick Search Box suggestion shortcuts</h3>
+
+<p>Suggestions that the user selects from Quick Search Box may be automatically made into shortcuts.
+These are suggestions that the Search Manager has copied from your content provider  so it can
+quickly access the suggestion without the need to re-query your content provider. </p>
+
+<p>By default, this is enabled for all suggestions retrieved by Quick Search Box, but if your
+suggestion data may change over time, then you can request that the shortcuts be refreshed. For
+instance, if your suggestions refer to dynamic data, such as a contact's presence status, then you
+should request that the suggestion shortcuts be refreshed when shown to the user. To do so,
+include the {@link android.app.SearchManager#SUGGEST_COLUMN_SHORTCUT_ID} in your suggestions table.
+Using this column, you can
+configure the shortcut behavior for each suggestion in the following ways:</p>
+
+<ol type="a">
+  <li>Have Quick Search Box re-query your content provider for a fresh version of the shortcutted
+suggestion.
+    <p>Provide a value in the {@link android.app.SearchManager#SUGGEST_COLUMN_SHORTCUT_ID} column
+and the suggestion will be
+re-queried for a fresh version of the suggestion each time the shortcut is displayed. The shortcut
+will be quickly displayed with whatever data was most recently available until the refresh query
+returns, after which the suggestion will be dynamically refreshed with the new information. The
+refresh query will be sent to your content provider with a URI path of {@link
+android.app.SearchManager#SUGGEST_URI_PATH_SHORTCUT}
+(instead of {@link android.app.SearchManager#SUGGEST_URI_PATH_QUERY}). The Cursor you return should
+contain one suggestion using the
+same columns as the original suggestion, or be empty, indicating that the shortcut is no
+longer valid (in which case, the suggestion will disappear and the shortcut will be removed).</p>
+    <p>If a suggestion refers to data that could take longer to refresh, such as a network based
+refresh, you may also add the {@link
+android.app.SearchManager#SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING} column to your suggestions
+table with a value
+of "true" in order to show a progress spinner for the right hand icon until the refresh is complete.
+(Any value other than "true" will not show the progress spinner.)</p></li>
+  <li>Prevent the suggestion from being copied into a shortcut at all.
+    <p>Provide a value of {@link android.app.SearchManager#SUGGEST_NEVER_MAKE_SHORTCUT} in the
+{@link android.app.SearchManager#SUGGEST_COLUMN_SHORTCUT_ID} column. In
+this case, the suggestion will never be copied into a shortcut. This should only be necessary if you
+absolutely do not want the previously copied suggestion to appear at all. (Recall that if you
+provide a normal value for the column then the suggestion shortcut will appear only until the
+refresh query returns.)</p></li>
+  <li>Allow the default shortcut behavior to apply.
+    <p>Simply leave the {@link android.app.SearchManager#SUGGEST_COLUMN_SHORTCUT_ID} empty for each
+suggestion that will not change and can be saved as a shortcut.</p></li>
+</ol>
+
+<p>Of course, if none of your suggestions will ever change, then you do not need the
+{@link android.app.SearchManager#SUGGEST_COLUMN_SHORTCUT_ID} column at all.</p>
+
+<p class="note"><strong>Note</strong>: Quick Search Box will ultimately decide whether to shortcut
+your app's suggestions, considering these values as a strong request from your application.</p>
+
+
+<h3 id="AboutRanking">About Quick Search Box suggestion ranking</h3>
+
+<p>Once your application's search results are made available to Quick Search Box, how they surface
+to the user for a particular query will be determined as appropriate by Quick Search Box ranking.
+This may depend on how many other apps have results for that query, and how often the user has
+selected on your results compared to those of the other apps. There is no guarantee about how
+ranking will occur, or whether your app's suggestions will show at all for a given query. In
+general, you can expect that providing quality results will increase the likelihood that your app's
+suggestions are provided in a prominent position, and apps that provide lower quality suggestions
+will be more likely to be ranked lower and/or not displayed.</p>
+
+<div class="special">
+<p>See the <a href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable
+Dictionary sample app</a> for a complete demonstration of custom search suggestions.</p>
+</div>
+
diff --git a/docs/html/guide/topics/search/adding-recent-query-suggestions.jd b/docs/html/guide/topics/search/adding-recent-query-suggestions.jd
new file mode 100644
index 0000000..37e0e82
--- /dev/null
+++ b/docs/html/guide/topics/search/adding-recent-query-suggestions.jd
@@ -0,0 +1,225 @@
+page.title=Adding Recent Query Suggestions
+parent.title=Search
+parent.link=index.html
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+<h2>Key classes</h2>
+<ol>
+<li>{@link android.provider.SearchRecentSuggestions}</li>
+<li>{@link android.content.SearchRecentSuggestionsProvider}</li>
+</ol>
+<h2>In this document</h2>
+<ol>
+<li><a href="#TheBasics">The Basics</a></li>
+<li><a href="#RecentQuerySearchableConfiguration">Modifying the searchable
+configuration</a></li>
+<li><a href="#RecentQueryContentProvider">Creating a Content Provider</a></li>
+<li><a href="#SavingQueries">Saving queries</a></li>
+<li><a href="#ClearingSuggestionData">Clearing the suggestion data</a></li>
+</ol>
+<h2>See also</h2>
+<ol>
+<li><a href="searchable-config.html">Searchable Configuration</a></li>
+</ol>
+</div>
+</div>
+
+<p>The Android search framework provides the ability for your application to
+provide suggestions while the user types into the Android search dialog. In this guide, you'll learn
+how to create recent query suggestions. These are suggestions based
+on queries previously entered by the user. So, if the user previously searched for "puppies" then it
+will appear as a suggestion as they begin typing the same string of text. The screenshot below
+shows an example of recent query suggestions.</p>
+
+<p>Before you begin, you need to have implemented the Android search dialog for searches in your
+application. If you haven't done this, see <a href="search-dialog.html">Using the Android Search
+Dialog</a>.</p>
+
+
+<h2 id="TheBasics">The Basics</h2>
+
+<img src="{@docRoot}images/search/search-suggest-recent-queries.png" alt="" height="417"
+style="float:right;clear:right;" />
+
+<p>Recent query suggestions are simply saved searches. When the user selects one of
+the suggestions, your searchable Activity will receive a normal {@link
+android.content.Intent#ACTION_SEARCH} Intent with the suggestion as the search query, which your
+searchable Activity will already handle.</p>
+
+<p>To provide recent queries suggestions, you need to:</p>
+
+<ul>
+  <li>Implement a basic searchable Activity, as documented in <a
+href="{@docRoot}guide/topics/search/search-dialog.html">Using the Android Search Dialog</a>.</li>
+  <li>Create a content provider that extends {@link
+android.content.SearchRecentSuggestionsProvider} and declare it in your application manifest.</li>
+  <li>Modify the searchable configuration with information about the content provider.</li>
+  <li>Save queries to your content provider each time a search is made.</li>
+</ul>
+
+<p>Just like the Search Manager handles the rendering of the search dialog, it will also do the work
+to display all search suggestions below the search dialog. All you need to do is provide a source
+from which the suggestions can be retrieved.</p>
+
+<p>When the Search Manager identifies that your Activity is searchable and also provides search
+suggestions, the following procedure will take place as soon as the user types into the Android
+search box:</p>
+
+<ul>
+  <li>The Search Manager takes the search query text (whatever has been typed so far) and performs a
+query to the content provider that manages your suggestions.</li>
+  <li>Your content provider then returns a {@link android.database.Cursor} that points to all
+suggestions that are relevant to the search query text.</li>
+  <li>The Search Manager then displays the list of suggestions provided by the Cursor (as
+demonstrated in the screenshot to the right).</li>
+</ul>
+
+<p>At this point, the following may happen:</p>
+
+<ul>
+  <li>If the user types another key, or changes the query in any way, the above steps are repeated
+and the suggestion list is updated as appropriate.</li>
+  <li>If the user executes the search, the suggestions are ignored and the search is delivered
+to your searchable Activity using the normal {@link android.content.Intent#ACTION_SEARCH}
+Intent.</li>
+  <li>If the user selects a suggestion, a normal
+{@link android.content.Intent#ACTION_SEARCH} Intent is triggered, using the suggested text as the
+query.</li>
+</ul>
+
+<p>As you'll soon discover, the {@link android.content.SearchRecentSuggestionsProvider} class that
+you'll extend for your content provider will automatically do the work described above, so there's
+actually very little code to write.</p>
+
+
+<h2 id="RecentQuerySearchableConfiguration">Modifying the searchable configuration</h2>
+
+<p>First, you need to add the {@code android:searchSuggestAuthority} and
+{@code android:searchSuggestSelection} attributes to the {@code &lt;searchable&gt;} element in your
+searchable configuration file. For example:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
+    android:label="@string/app_label"
+    android:hint="@string/search_hint"
+    android:searchSuggestAuthority="my.package.MySuggestionProvider"
+    android:searchSuggestSelection=" ?" >
+&lt;/searchable>
+</pre>
+
+<p>The value for {@code android:searchSuggestAuthority} should be a fully-qualified name for
+your content provider: your application package name followed by the name of your content provider.
+This string must match the authority used in the content provider (discussed in the next section).
+</p>
+
+<p>The value for {@code android:searchSuggestSelection} must be a single question-mark, preceded by
+a space (" ?"), which is simply a placeholder for the SQLite selection argument (which will be
+automatically replaced by the query text entered by the user).</p>
+
+
+<h2 id="RecentQueryContentProvider">Creating a Content Provider</h2>
+
+<p>The content provider that you need for recent query suggestions must be an implementation
+of {@link android.content.SearchRecentSuggestionsProvider}. This class does practically everything
+for you. All you have to do is write a class constructor that executes one line of code.</p>
+
+<p>For example, here's a complete implementation of a content provider for recent query
+suggestions:</p>
+
+<pre>
+public class MySuggestionProvider extends SearchRecentSuggestionsProvider {
+    public final static String AUTHORITY = "my.package.MySuggestionProvider";
+    public final static int MODE = DATABASE_MODE_QUERIES;
+
+    public MySuggestionProvider() {
+        setupSuggestions(AUTHORITY, MODE);
+    }
+}
+</pre>
+
+<p>The call to {@link android.content.SearchRecentSuggestionsProvider#setupSuggestions(String,int)}
+passes the name of the search authority (matching the one in the searchable configuration) and a
+database mode. The database mode must include {@link
+android.content.SearchRecentSuggestionsProvider#DATABASE_MODE_QUERIES} and can optionally include
+{@link
+android.content.SearchRecentSuggestionsProvider#DATABASE_MODE_2LINES}, which will add another column
+to the suggestions table that allows you to provide a second line of text with each suggestion. For
+example:</p>
+<pre>
+public final static int MODE = DATABASE_MODE_QUERIES | DATABASE_MODE_2LINES;
+</pre>
+
+<p>In the following section, you'll see how to save both lines of text.</p>
+
+<p>Now simply declare the content provider in your application manifest with the same authority
+string used in the class (and in the searchable configuration). For example:</p>
+
+<pre>
+&lt;application>
+    &lt;provider android:name=".MySuggestionProvider"
+              android:authorities="my.package.authority" />
+    ...
+&lt;/application>
+</pre>
+
+
+<h2 id="SavingQueries">Saving queries</h2>
+
+<p>In order to populate your collection of recent queries, you need to add each query
+received by your searchable Activity to the content provider you've just built. To do this, create
+an instance of {@link
+android.provider.SearchRecentSuggestions} and call {@link
+android.provider.SearchRecentSuggestions#saveRecentQuery(String,String)} each time your searchable
+Activity receives a query. For example, here's how you can save the query during your
+Activity's {@link android.app.Activity#onCreate(Bundle) onCreate()} method:</p>
+
+<pre>
+&#64;Override
+public void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    setContentView(R.layout.main);
+
+    Intent Intent  = getIntent();
+
+    if (Intent.ACTION_SEARCH.equals(Intent .getAction())) {
+        String query = Intent .getStringExtra(SearchManager.QUERY);
+        SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,
+                MySuggestionProvider.AUTHORITY, MySuggestionProvider.MODE);
+        suggestions.saveRecentQuery(query, null);
+    }
+}
+</pre>
+
+<p>Notice that the {@link android.content.SearchRecentSuggestionsProvider} constructor requires the
+same authority and database mode declared by your content provider.</p>
+
+<p>The {@link android.provider.SearchRecentSuggestions#saveRecentQuery(String,String)} method takes
+the search query string as the first parameter and, optionally, a second string to include as the
+second line of the suggestion. The second parameter is only used if you've enabled two-line mode
+for the search suggestions with {@link
+android.content.SearchRecentSuggestionsProvider#DATABASE_MODE_2LINES}. If you have enabled
+two-line mode, then the query text will be matched against this second line as well.</p>
+
+<p>That's all that's needed to build a recent queries suggestion provider. However, there's one
+other important thing to do: provide the ability for the user to clear this search history.</p>
+
+
+<h2 id="ClearingSuggestionData">Clearing the suggestion data</h2>
+
+<p>To protect the user's privacy, you should always provide a way for the user to clear the recent
+query suggestions. To clear the recent queries, simply call {@link
+android.provider.SearchRecentSuggestions#clearHistory()}. For example:</p>
+
+<pre>
+SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,
+        HelloSuggestionProvider.AUTHORITY, HelloSuggestionProvider.MODE);
+suggestions.clearHistory();
+</pre>
+
+<p>Simply execute this from your choice of a "Clear Search History" menu item,
+preference item, or button. You should also provide a confirmation dialog when this is pressed, to
+verify that the user wants to delete their search history.</p>
+
diff --git a/docs/html/guide/topics/search/index.jd b/docs/html/guide/topics/search/index.jd
new file mode 100644
index 0000000..b2252bb
--- /dev/null
+++ b/docs/html/guide/topics/search/index.jd
@@ -0,0 +1,111 @@
+page.title=Search
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+<h2>Topics</h2>
+<ol>
+<li><a href="search-dialog.html">Using the Android Search Dialog</a></li>
+<li><a href="adding-recent-query-suggestions.html">Adding Recent Query Suggestions</a></li>
+<li><a href="adding-custom-suggestions.html">Adding Custom Suggestions</a></li>
+</ol>
+<h2>Reference</h2>
+<ol>
+<li><a href="searchable-config.html">Searchable Configuration</a></li>
+</ol>
+<h2>See also</h2>
+<ol>
+<li><a href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable
+Dictionary sample app</a></li>
+</ol>
+</div>
+</div>
+
+
+<p>The ability to search is considered to be a core user feature on Android. The user should be able
+to search any data that is available to them, whether the content is located on the device or the
+Internet. This experience should be seamless and consistent across the entire
+system, which is why Android provides a simple search framework to help you provide users with
+a familiar search dialog and a great search experience.</p>
+
+<img src="{@docRoot}images/search/search-suggest-custom.png" alt="" height="417"
+style="float:right;clear:right;" />
+
+<p>Android's search framework provides a user interface in which the user can perform a search and
+an interaction layer that communicates with your application. This way, you don't have to build
+a search box that the user must find in order to begin a search. Instead,
+a custom search dialog will appear at the top of the screen at the user's command.
+The search framework will manage the search dialog and when the user executes their search, the
+search framework will pass the query text to your application so that your application can begin a
+search. The screenshot to the right shows an example of the search dialog (using
+search suggestions).</p>
+
+<p>Once your application is set up to use the search dialog, you can:</p>
+
+<ul>
+<li>Customize some of the search dialog characteristics</li>
+<li>Enable voice search</li>
+<li>Provide search suggestions based on recent user queries</li>
+<li>Provide search suggestions that match actual results in your application data</li>
+<li>Offer your application's search suggestions in the system-wide Quick Search Box</li>
+</ul>
+
+<p>The following documents will teach you how to use the search dialog in
+your application:</p>
+
+<dl>
+  <dt><strong><a href="search-dialog.html">Using the Android Search Dialog</a></strong></dt>
+  <dd>How to set up your application to use the search dialog for searches. </dd>
+  <dt><strong><a href="adding-recent-query-suggestions.html">Adding Recent Query
+Suggestions</a></strong></dt>
+  <dd>How to show suggestions based on queries previously used in the search dialog.</dd>
+  <dt><strong><a href="adding-custom-suggestions.html">Adding Custom Suggestions</a></strong></dt>
+  <dd>How to show suggestions based on custom data from your application and offer your suggestions
+in the system-wide Quick Search Box.</dd>
+</dl>
+
+<p>Also, the <strong><a href="searchable-config.html">Searchable Configuration</a></strong> document
+provides a reference for the searchable configuration file (though the above
+documents also discuss the configuration file in terms of specific behaviors).</p>
+
+<p class="note"><strong>Note</strong>: The search framework does <em>not</em> provide APIs to
+perform searches on your data. Performing actual searches is a task that you must accomplish
+using APIs appropriate for your data, such as those in {@link android.database.sqlite}
+if your data is in an SQLite database.</p>
+
+
+<h2>Protecting User Privacy</h2>
+
+<p>When you implement search in your application, you should take steps to protect the user's
+privacy whenever possible. Many users consider their activities on the phone, including searches, to
+be private information. To protect the user's privacy, you should abide by the following
+principles:</p>
+
+<ul>
+<li><strong>Don't send personal information to servers, and if you do, don't log it.</strong>
+<p>"Personal information" is information that can personally identify your users, such as their
+name, email address, billing information, or other data which can be reasonably linked to such
+information. If
+your application implements search with the assistance of a server, try to avoid sending personal
+information along with the search queries. For example, if you are searching for businesses near a
+zip code,
+you don't need to send the user ID as well &mdash; send only the zip code to the server. If you must
+send the personal information, you should take steps to avoid logging it. If you must log it, you
+should protect that data very carefully and erase it as soon as possible.</p>
+</li>
+<li><strong>Provide the user with a way to clear their search history.</strong>
+<p>The search framework helps your application provide context-specific suggestions while they type.
+Sometimes these
+suggestions are based on previous searches, or other actions taken by the user in an earlier
+session. A user may not wish for previous searches to be revealed to other users, for instance if
+they share their phone with a friend. If your application provides suggestions that can reveal
+previous activities, you should implement a "Clear History" menu item, preference, or button. If you
+are
+using {@link android.provider.SearchRecentSuggestions}, you can simply call its {@link
+android.provider.SearchRecentSuggestions#clearHistory()} method. If you are implementing custom
+suggestions, you'll need to provide a
+similar "clear history" method in your provider that can be invoked by the user.</p>
+</li>
+</ul>
+
+
diff --git a/docs/html/guide/topics/search/search-dialog.jd b/docs/html/guide/topics/search/search-dialog.jd
new file mode 100644
index 0000000..718668c
--- /dev/null
+++ b/docs/html/guide/topics/search/search-dialog.jd
@@ -0,0 +1,542 @@
+page.title=Using the Android Search Dialog
+parent.title=Search
+parent.link=index.html
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+<h2>Key classes</h2>
+<ol>
+<li>{@link android.app.SearchManager}</li>
+</ol>
+<h2>In this document</h2>
+<ol>
+<li><a href="#TheBasics">The Basics</a></li>
+<li><a href="#SearchableConfiguration">Creating a Searchable Configuration</a></li>
+<li><a href="#SearchableActivity">Creating a Searchable Activity</a>
+  <ol>
+    <li><a href="#DeclaringSearchableActivity">Declaring a searchable Activity</a></li>
+    <li><a href="#PerformingSearch">Performing a search</a></li>
+  </ol>
+</li>
+<li><a href="#InvokingTheSearchDialog">Invoking the Search Dialog</a>
+  <ol>
+    <li><a href="#LifeCycle">The impact of the search dialog on your Activity life-cycle</a></li>
+  </ol>
+</li>
+<li><a href="#SearchContextData">Passing Search Context Data</a></li>
+<li><a href="#VoiceSearch">Adding Voice Search</a></li>
+</ol>
+<h2>See also</h2>
+<ol>
+<li><a href="adding-recent-query-suggestions.html">Adding Recent Query Suggestions</a></li>
+<li><a href="adding-custom-suggestions.html">Adding Custom Suggestions</a></li>
+<li><a href="searchable-config.html">Searchable Configuration</a></li>
+<li><a href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable
+Dictionary App</a></li>
+</ol>
+</div>
+</div>
+
+<p>When you want to provide search in your application, the last thing you should have to worry
+about is where to put your search box. By using the Android search framework, your application will
+reveal a custom search dialog whenever the user requests it. At the
+press of a dedicated search key or an API call from your application, the search dialog will
+appear at the top of the screen and will automatically show your application icon. An example is
+shown in the screenshot below.</p>
+
+<p>This guide will teach you how to set up your application to provide search in a custom search
+dialog. In doing so, you will provide a standardized search experience and be able to add
+features like voice search and search suggestions.</p>
+
+
+<h2 id="TheBasics">The Basics</h2>
+
+<img src="{@docRoot}images/search/search-ui.png" alt="" height="417"
+style="float:right;clear:right;" />
+
+<p>The Android search framework will manage the search dialog on your behalf; you never need
+to draw it or worry about where it is, and your current Activity will not be
+interrupted. The {@link android.app.SearchManager} is the component that does this work for
+you (hereafter, referred to as "the Search Manager"). It manages the life of the Android search
+dialog and will send your application the search query when executed by the user.</p>
+
+<p>When the user executes a search, the Search Manager will use a specially-formed Intent to pass
+the search query to the Activity that you've declared to handle searches. Essentially, all you
+need is an Activity that receives this Intent, performs the search, and presents the results.
+Specifically, what you need is the following:</p>
+
+<dl>
+  <dt>A searchable configuration</dt>
+  <dd>This is an XML file that configures the search dialog and includes settings for
+features such as the hint text shown in text box and settings voice search and search
+suggestion.</dd>
+  <dt>A searchable Activity</dt>
+  <dd>This is the {@link android.app.Activity} that receives the search query then
+searches your data and displays the search results.</dd>
+  <dt>A mechanism by which the user can invoke search</dt>
+  <dd>By default, the device search key (if available) will invoke the search dialog once
+you've configured a searchable Activity. However, you should always provide another means by
+which the user can invoke a search, such as with a search button in the Options Menu or elsewhere in
+the Activity UI, because not all devices provide a dedicated search key.</dd>
+</dl>
+
+
+<h2 id="SearchableConfiguration">Creating a Searchable Configuration</h2>
+
+<p>The searchable configuration is an XML file that defines several settings for the Android search
+dialog in your application. This file is traditionally named {@code searchable.xml} and must be
+saved in the {@code res/xml/} project directory.</p>
+
+<p>The file must consist of the {@code &lt;searchable&gt;} element as the root node and specify one
+or more attributes that configure your search dialog. For example:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
+    android:label="@string/app_label" >
+&lt;/searchable>
+</pre>
+
+<p>This is the minimum configuration required in order to provide the search dialog. The {@code
+android:label} attribute is the only required attribute and points to a string resource, which
+should normally be the same as the application. (Although it's required, this
+label isn't actually shown to the user until you enable suggestions for Quick Search Box.)</p>
+
+<p>There are several other attributes accepted by the {@code &lt;searchable&gt;} element. Most of
+which apply only when configuring features such as search suggestions and voice
+search. However, we recommend that you always include the {@code android:hint} attribute, which
+specifies a string resource for the text to display in the search dialog's text box before the user
+enters their query&mdash;it provides important clues to the user about what they can search. </p>
+
+<p class="note"><strong>Tip:</strong> For consistency among other
+Android applications, you should format the string for {@code android:hint} as "Search
+<em>&lt;content-or-product&gt;</em>". For example, "Search songs and artists" or "Search
+YouTube".</p>
+
+<p>Next, you'll hook this configuration into your application.</p>
+
+
+<h2 id="SearchableActivity">Creating a Searchable Activity</h2>
+
+<p>When the user executes a search from the search dialog, the Search Manager will send
+your searchable {@link android.app.Activity} the search query with the {@link
+android.content.Intent#ACTION_SEARCH} {@link android.content.Intent}. Your searchable Activity will
+then search your data and present the results.</p>
+
+
+<h3 id="DeclaringSearchableActivity">Declaring a searchable Activity</h3>
+
+<p>If you don't have one already, create an {@link android.app.Activity} that will be used to
+perform searches, then declare it to
+accept the {@link android.content.Intent#ACTION_SEARCH} {@link android.content.Intent} and apply the
+searchable configuration. To do so, you need to add an {@code
+&lt;intent-filter&gt;} element and a {@code &lt;meta-data&gt;} element to the
+appropriate {@code &lt;activity&gt;} element in your manifest file. For example:</p>
+
+<pre>
+&lt;application ... >
+    &lt;activity android:name=".MySearchableActivity" >
+        &lt;intent-filter>
+            &lt;action android:name="android.intent.action.SEARCH" />
+        &lt;/intent-filter>
+        &lt;meta-data android:name="android.app.searchable"
+                   android:resource="@xml/searchable"/>
+    &lt;/activity>
+    ...
+&lt;/application>
+</pre>
+
+<p>The {@code android:name} attribute in the {@code &lt;meta-data&gt;} element must be defined with
+{@code "android.app.searchable"} and the {@code android:resource} attribute value must be a
+reference to the searchable configuration file saved in {@code res/xml} (in this example, it
+refers to the {@code res/xml/searchable.xml} file).</p>
+
+<p class="note">If you're wondering why the {@code
+&lt;intent-filter&gt;} does not include a {@code &lt;category&gt;} with the {@code DEFAULT}
+value, it's because the Intent that is delivered to this Activity when a search is executed will
+explicitly define this Activity as the component for the Intent (which the Search Manager knows
+from the searcahble meta-data declared for the Activity).</p>
+
+<p>Be aware that the search dialog will not be available from within every
+Activity of your application, by default. Rather, the search dialog will be presented to
+users only when they
+invoke search from a searchable context of your application. A searchable context is any Activity
+for which you have
+declared searchable meta-data in the manifest file. For example, the searchable Activity itself
+(declared in the manifest snippet above) is
+a searchable context because it contains searchable meta-data that defines the
+searchable configuration. Any other Activity in your application is not a searchable context, by
+default, and thus, will not reveal the search dialog. You probably do want the
+search dialog to be available from every Activity in your application, so this can be easily
+fixed.</p>
+
+<p>If you want all of your activities to provide the search dialog, add another {@code
+&lt;meta-data&gt;} element inside the {@code
+&lt;application&gt;} element. Use this element to declare the existing searchable Activity as the
+default searchable Activity. For example:</p>
+
+<pre>
+&lt;application ... >
+    &lt;activity android:name=".MySearchableActivity" >
+        &lt;intent-filter>
+            &lt;action android:name="android.intent.action.SEARCH" />
+        &lt;/intent-filter>
+        &lt;meta-data android:name="android.app.searchable"
+                   android:resource="@xml/searchable"/>
+    &lt;/activity>
+    &lt;activity android:name=".AnotherActivity" ... >
+    &lt;/activity>
+    &lt;!-- this one declares the searchable Activity for the whole app --&gt;
+    &lt;meta-data android:name="android.app.default_searchable"
+               android:value=".MySearchableActivity" />
+    ...
+&lt;/application>
+</pre>
+
+<p>The {@code &lt;meta-data&gt;} element with the {@code android:name} attribute value of
+{@code "android.app.default_searchable"} specifies a default searchable Activity for the context in
+which it is placed (which, in this case, is the entire application). The searchable Activity to
+use is specified with the {@code android:value} attribute. All other activities in the
+application, such as {@code AnotherActivity}, are now considered a searchable context and can invoke
+the search dialog. When a search is executed, {@code MySearchableActivity} will
+be launched to handle the search query.</p>
+
+<p>Notice that this allows you to control which activities provide search at a more granular level.
+To specify only an individual Activity as a searchable context, simply place the {@code
+&lt;meta-data&gt;} with the {@code
+"android.app.default_searchable"} name inside the respective {@code &lt;activity&gt;}
+element (rather than inside the {@code &lt;application&gt;}). And, while it is uncommon, you can
+even create more than one searchable Activity and provide each one in different contexts of your
+application, either by declaring a different searchable Activity in each {@code &lt;activity&gt;}
+element, or declaring a default searchable Activity for the entire application and then overriding
+it with a different {@code &lt;meta-data&gt;} element inside certain activities.</p>
+
+
+<h3 id="PerformingSearch">Performing a search</h3>
+
+<p>Once your Activity is declared searchable, performing the actual search involves three steps:
+receiving the query, searching your data, and presenting the results.</p>
+
+<p>Traditionally, your search results should be presented in a {@link android.widget.ListView}
+(assuming that our results are text-based), so
+you may want your searchable Activity to extend {@link android.app.ListActivity}, which 
+provides easy access to {@link android.widget.ListView} APIs. (See the <a
+href="{@docRoot}resources/tutorials/views/hello-listview.html">List View Tutorial</a> for a simple
+{@link android.app.ListActivity} sample.)</p>
+
+
+<h4 id="ReceivingTheQuery">Receiving the query</h4>
+
+<p>When a search is executed from the search dialog, your searchable Activity will be opened
+with the {@link android.content.Intent#ACTION_SEARCH} {@link android.content.Intent}, which carries
+the search query in the
+{@link android.app.SearchManager#QUERY QUERY} extra. All you need to do is check for
+this Intent and extract the string. For example, here's how you can get the query when your
+Activity launches:</p>
+
+<pre>
+&#64;Override
+public void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    setContentView(R.layout.search);
+
+    Intent intent = getIntent();
+
+    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
+      String query = intent.getStringExtra(SearchManager.QUERY);
+      doMySearch(query);
+    }
+}
+</pre>
+
+<p>The {@link android.app.SearchManager#QUERY QUERY} string is always included with
+the {@link android.content.Intent#ACTION_SEARCH} Intent. In this example, the query is
+retrieved and passed to a local {@code doMySearch()} method where the actual search operation
+is done.</p>
+
+
+<h4 id="SearchingYourData">Searching your data</h4>
+
+<p>The process of storing and searching your data is a process that's unique to your application.
+There are many ways that you might do this and discussing all options is beyond the scope of
+this document. This guide will not teach you how to store your data and search it; this
+is something you must carefully consider in terms of your needs and your data. However, here are
+some tips you may be able to apply:</p>
+
+  <ul>
+    <li>If your data is stored in a SQLite database on the device, performing a full-text search
+(using FTS3, rather than a LIKE query) can provide a more robust search across text data and can
+produce results many, many times faster. See <a href="http://sqlite.org/fts3.html">sqlite.org</a>
+for information about FTS3 and the {@link android.database.sqlite.SQLiteDatabase} class for
+information about SQLite on Android. Also look at the <a
+href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable Dictionary</a> sample
+application to see a complete SQLite implementation that performs searches with FTS3.</li>
+    <li>If your data is stored online, then the perceived search performance may be
+inhibited by the user's data connection. You may want to display a spinning progress wheel until
+your search returns. See {@link android.net} for a reference of network APIs and <a
+href="guide/topics/ui/dialogs.html#ProgressDialog">Creating a Progress Dialog</a> to see how
+you can display a progress wheel.</li>
+  </ul>
+
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+<h2>About Adapters</h2>
+<p>An Adapter will bind individual items from a set of data into individual {@link
+android.view.View} objects. When the Adapter
+is applied to a {@link android.widget.ListView}, the Views are injected as individual items of the
+list. {@link
+android.widget.Adapter} is simply an interface, so implementations such as {@link
+android.widget.CursorAdapter} (for binding data from a {@link android.database.Cursor}) are needed.
+If none of the existing implementations work for your data, then you should implement your own from
+{@link android.widget.BaseAdapter}. Install the SDK Samples package for API Level 4 to see a
+version of the Searchable Dictionary that creates a custom BaseAdapter.</p>
+</div>
+</div>
+
+<p>Regardless of where your data lives and how you search it, we recommend that you return search
+results to your searchable Activity with an {@link android.widget.Adapter}. This way, you can easily
+present all the search results in a {@link android.widget.ListView}. If your data comes from a
+SQLite database query, then you can easily apply your results to a {@link android.widget.ListView}
+using a {@link android.widget.CursorAdapter}. If your data comes in some other type of format, then
+you can create an extension of the {@link android.widget.BaseAdapter}.</p>
+
+<h4 id="PresentingTheResults">Presenting the results</h4>
+
+<p>Presenting your search results is mostly a UI detail and not something covered by the search
+framework APIs. However, a simple solution is to create your searchable Activity to extend {@link
+android.app.ListActivity} and then call {@link
+android.app.ListActivity#setListAdapter(ListAdapter)}, passing it an {@link
+android.widget.Adapter} that is bound to your data. This will automatically project all the
+results into the Activity {@link android.widget.ListView}.</p>
+
+<p>For more help presenting your results, see the {@link android.app.ListActivity}
+documentation.</p>
+
+<p>Also see the <a
+href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable Dictionary</a> sample
+application for an a complete demonstration of how to search an SQLite database and use an
+{@link android.widget.Adapter} to provide resuls in a {@link android.widget.ListView}.</p>
+
+
+<h2 id="InvokingTheSearchDialog">Invoking the Search Dialog</h2>
+
+<p>Once you have a searchable Activity in place, invoking the search dialog so the user can
+submit a
+query is easy. Many Android devices provide a dedicated search key and when it is pressed while the
+user is within a searchable context of your application, the search dialog will be revealed.
+However,
+you should never assume that a search key is available on the user's device and should always
+provide a search button in your UI that will invoke search.</p>
+
+<p>To invoke search from your Activity, simply call {@link
+android.app.Activity#onSearchRequested()}.</p>
+
+<p>For example, you should provide a menu item in your <a
+href="{@docRoot}guide/topics/ui/menus.html#options-menu">Options Menu</a> or a button in your UI to
+invoke search with this method. For your convenience, this <a
+href="{@docRoot}shareables/search_icons.zip">search_icons.zip</a> file includes icons for
+medium and high density screens, which you can use for your menu item or button (low density
+screens will automatically scale-down the hdpi image by one half). </p>
+
+<!-- ... maybe this should go into the Creating Menus document ....
+<p>If you chose to provide a shortcut key for the menu item,  using {@link
+android.view.MenuItem#setAlphabeticShortcut(char)}, then SearchManager.MENU_KEY is the recommended
+key character, representing the default search key.</p>
+-->
+
+<p>You can also enable "type-to-search" functionality in your Activity by calling {@link
+android.app.Activity#setDefaultKeyMode(int) setDefaultKeyMode}({@link
+android.app.Activity#DEFAULT_KEYS_SEARCH_LOCAL}). When this is enabled and the user begins typing on
+the keyboard, search will automatically be
+invoked and the keystrokes will be inserted in the search dialog. Be sure to enable this mode
+during your Activity {@link android.app.Activity#onCreate(Bundle) onCreate()} method.</p>
+
+
+<h3 id="LifeCycle">The impact of the search dialog on your Activity life-cycle</h3>
+
+<p>The search dialog behaves like a {@link android.app.Dialog} that floats at the top of the
+screen. It
+does not cause any change in the Activity stack, so no life-cycle methods (such as {@link
+android.app.Activity#onPause()}) will
+be called. All that happens is your Activity loses input focus as it is given to the search dialog.
+</p>
+
+<p>If you want to be notified when search is invoked, simply override the {@link
+android.app.Activity#onSearchRequested()} method. When this is called, you can do any work you may
+want to do when your Activity looses input focus (such as pause animations). But unless you are
+<a href="#SearchContextData">Passing Search Context Data</a> (discussed above), you should always
+call the super class implementation. For example:</p>
+
+<pre>
+&#64;Override
+public boolean onSearchRequested() {
+    pauseSomeStuff();
+    return super.onSearchRequested();
+}
+</pre>
+
+<p>If the user cancels search by pressing the device Back key, the Activity in which search was
+invoked will re-gain input focus. You can register to be notified when the search dialog is
+closed with {@link android.app.SearchManager#setOnDismissListener(SearchManager.OnDismissListener)}
+and/or {@link android.app.SearchManager#setOnCancelListener(SearchManager.OnCancelListener)}. You
+should normally only need to register the {@link android.app.SearchManager.OnDismissListener
+OnDismissListener}, because this is called every time that the search dialog is closed. The {@link
+android.app.SearchManager.OnCancelListener OnCancelListener} only pertains to events in which the
+user explicitly left the search dialog, so it is not called when a search is executed (in which
+case, the search dialog naturally disappears).</p>
+
+<p>If the current Activity is not the searchable Activity, then the normal Activity life-cycle
+events will be triggered once the user executes a search (the current Activity will receive {@link
+android.app.Activity#onPause()} and so forth, as
+described in <a href="{@docRoot}guide/topics/fundamentals.html#lcycles">Application
+Fundamentals</a>). If, however, the current Activity is the searchable Activity, then one of two
+things will happen:</p>
+
+<ul>
+  <li>By default, the searchable Activity will receive the {@link
+android.content.Intent#ACTION_SEARCH} Intent with a call to {@link
+android.app.Activity#onCreate(Bundle) onCreate()} and a new instance of the
+Activity will be brought to the top of the stack. You'll now have two instances of your searchable
+Activity in the Activity stack (so pressing the Back key will go back to the previous instance of
+the searchable Activity, rather than exiting the searchable Activity).</li>
+  <li>On the other hand, if the Activity has set {@code android:launchMode} to "singleTop" then the
+searchable Activity will receive the {@link android.content.Intent#ACTION_SEARCH} Intent with a call
+to {@link android.app.Activity#onNewIntent(Intent)}, passing the new {@link
+android.content.Intent#ACTION_SEARCH} Intent here. For example, here's how you might want to handle
+this case:
+<pre>
+&#64;Override
+public void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    setContentView(R.layout.search);
+    handleIntent(getIntent());
+}
+
+&#64;Override
+protected void onNewIntent(Intent intent) {
+    setIntent(intent);
+    handleIntent(intent);
+}
+
+private void handleIntent(Intent intent) {
+    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
+      String query = intent.getStringExtra(SearchManager.QUERY);
+      doMySearch(query);
+    }
+}
+</pre>
+
+<p>Compared to the example code in the section about <a href="#PerfomingSearch">Performing a
+Search</a>, all the code to handle the
+search Intent has been moved outside the {@link android.app.Activity#onCreate(Bundle)
+onCreate()} method so it can also be executed from {@link android.app.Activity#onNewIntent(Intent)
+onNewIntent()}.
+It's important to note that when {@link android.app.Activity#onNewIntent(Intent)} is
+called, the Activity has not been restarted, so the {@link android.app.Activity#getIntent()} method
+will still return the Intent that was first received with {@link
+android.app.Activity#onCreate(Bundle) onCreate()}. This is why {@link
+android.app.Activity#setIntent(Intent)} is called inside {@link
+android.app.Activity#onNewIntent(Intent)} (just in case you call {@link
+android.app.Activity#getIntent()} at a later time).</p>
+
+</li>
+</ul>
+
+<p>This second scenario is normally ideal, because the chances are good that once a search is
+completed, the user will perform additional searches and it's a bad experience if your application
+piles multiple instances of the searchable Activity on the stack. So we recommend that you set your
+searchable Activity to "singleTop" launch mode in the application manifest. For example:</p>
+
+<pre>
+&lt;activity android:name=".MySearchableActivity"
+              android:launchMode="singleTop" >
+    &lt;intent-filter>
+        &lt;action android:name="android.intent.action.SEARCH" />
+    &lt;/intent-filter>
+    &lt;meta-data android:name="android.app.searchable"
+                      android:resource="@xml/searchable"/>
+  &lt;/activity>
+</pre>
+
+
+<h2 id="SearchContextData">Passing Search Context Data</h2>
+
+<p>In order to refine your search criteria, you may want to provide some additional
+data to your searchable Activity when a search is executed. For instance, when you search your data,
+you may want to filter results based on more than just the search query text. In a simple
+case, you could just make your refinements inside the searchable Activity, for every search made.
+If, however, your
+search criteria may vary from one searchable context to another, then you can pass whatever data is
+necessary to refine your search in the {@link android.app.SearchManager#APP_DATA} Bundle, which is
+included in the {@link android.content.Intent#ACTION_SEARCH} Intent.</p>
+
+<p>To pass this kind of data to your searchable Activity, you need to override  {@link
+android.app.Activity#onSearchRequested()} method for the Activity in which search will be invoked.
+For example:</p>
+
+<pre>
+&#64;Override
+public boolean onSearchRequested() {
+     Bundle appData = new Bundle();
+     appData.putBoolean(MySearchableActivity.JARGON, true);
+     startSearch(null, false, appData, false);
+     return true;
+ }
+</pre>
+
+<p>Returning "true" indicates that you have successfully handled this callback event. Then in your
+searchable Activity, you can extract this data from the {@link
+android.app.SearchManager#APP_DATA} {@link android.os.Bundle} to refine the search. For example:</p>
+
+<pre>
+ Bundle appData = getIntent().getBundleExtra(SearchManager.APP_DATA);
+ if (appData != null) {
+     boolean jargon = appData.getBoolean(MySearchableActivity.JARGON);
+ }
+</pre>
+
+<p class="caution"><strong>Note:</strong> You should never call the {@link
+android.app.Activity#startSearch(String,boolean,Bundle,boolean) startSearch()} method from outside
+the {@link android.app.Activity#onSearchRequested()} callback method. When you want to invoke the
+search dialog, always call {@link android.app.Activity#onSearchRequested()} so that custom
+implementations (such as the addition of {@code appData}, in the above example) can be accounted
+for.</p>
+
+
+<h2 id="VoiceSearch">Adding Voice Search</h2>
+
+<p>You can easily add voice search functionality to your search dialog by adding the {@code
+android:voiceSearchMode} attribute to your searchable configuration. This will add a voice search
+button in the search dialog that, when clicked, will launch a voice prompt. When the user
+has finished speaking, the transcribed search query will be sent to your searchable
+Activity.</p>
+
+<p>To enable voice search for your activity, add the {@code android:voiceSearchMode}
+attribute to your searchable configuration. For example:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
+    android:label="@string/search_label"
+    android:hint="@string/search_hint"
+    android:voiceSearchMode="showVoiceSearchButton|launchRecognizer" >
+&lt;/searchable>
+</pre>
+
+<p>The value {@code showVoiceSearchButton} is required to enable voice
+search, while the second value, {@code launchRecognizer}, specifies that the voice search button
+should launch a recognizer that returns the transcribed text to the searchable Activity. This is
+how most applications should declare this attribute.</p>
+
+<p>There are some additional attributes you can provide to specify the voice search behavior, such
+as the language to be expected and the maximum number of results to return. See the <a
+href="searchable-config.html">Searchable Configuration</a> for more information about the
+available attributes.</p>
+
+<p class="note"><strong>Note:</strong> Carefully consider whether voice search is appropriate for
+your application. All searches performed with the voice search button will be immediately sent to
+your searchable Activity without a chance for the user to review the transcribed query. Be sure to
+sufficiently test the voice recognition and ensure that it understands the types of queries that
+the user will submit inside your application.</p>
diff --git a/docs/html/guide/topics/search/searchable-config.jd b/docs/html/guide/topics/search/searchable-config.jd
new file mode 100644
index 0000000..71566de
--- /dev/null
+++ b/docs/html/guide/topics/search/searchable-config.jd
@@ -0,0 +1,361 @@
+page.title=Searchable Configuration
+parent.title=Search
+parent.link=index.html
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+<h2>See also</h2>
+<ol>
+  <li><a href="search-dialog.html">Using the Android Search Dialog</a></li>
+  <li><a href="adding-recent-query-suggestions.html">Adding Recent Query Suggestions</a></li>
+  <li><a href="adding-custom-suggestions.html">Adding Custom Suggestions</a></li>
+</ol>
+</div>
+</div>
+
+<p>In order to utilize the Android search framework and provide a custom search dialog, your
+application must provide a search
+configuration in the form of an XML resource. This document describes the search configuration XML
+in terms of its syntax and usage. For a more complete discussion about how to implement search
+features for your application, see the companion documents about <a
+href="index.html">Search</a>.</p>
+
+<dl class="xml">
+
+<dt>file location:</dt>
+<dd><code>res/xml/<em>filename</em>.xml</code><br/>
+The filename will be used as the resource ID.</dd>
+
+<dt>syntax:</dt>
+<dd>
+<pre class="stx">
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;<a href="#searchable-element">searchable</a> xmlns:android="http://schemas.android.com/apk/res/android"
+    android:label="<em>string resource</em>"
+    android:hint="<em>string resource</em>"
+    android:searchMode=["queryRewriteFromData" | "queryRewriteFromText"]
+    android:searchButtonText="<em>string resource</em>"
+    android:inputType="<em>{@link android.R.attr#inputType}</em>"
+    android:imeOptions="<em>{@link android.R.attr#imeOptions}</em>"
+    android:searchSuggestAuthority="<em>string</em>"
+    android:searchSuggestPath="<em>string</em>"
+    android:searchSuggestSelection="<em>string</em>"
+    android:searchSuggestIntentAction="<em>string</em>"
+    android:searchSuggestIntentData="<em>string</em>"
+    android:searchSuggestThreshold="<em>int</em>"
+    android:includeInGlobalSearch=["true" | "false"]
+    android:searchSettingsDescription="<em>string resource</em>"
+    android:queryAfterZeroResults=["true" | "false"]
+    android:voiceSearchMode=["showVoiceSearchButton" | "launchWebSearch" | "launchRecognizer"]
+    android:voiceLanguageModel=["free-form" | "web_search"]
+    android:voicePromptText="<em>string resource</em>"
+    android:voiceLanguage="<em>string</em>"
+    android:voiceMaxResults="<em>int</em>"
+    &gt;
+    &lt;<a href="#actionkey-element">actionkey</a>
+        android:keycode="<em>{@link android.view.KeyEvent KEYCODE}</em>"
+        android:queryActionMsg="<em>string</em>"
+        android:suggestActionMsg="<em>string</em>"
+        android:suggestActionMsgColumn="<em>string</em>" &gt;
+&lt;/searchable&gt;
+</pre>
+</dd>
+
+<dt>elements:</dt>
+<dd>
+<dl class="tag-list">
+  <dt id="searchable-element"><code>&lt;searchable&gt;</code></dt>
+  <dd>Defines all search configurations used with the search dialog.
+    <p class="caps">attributes:</p>
+      <dl class="atn-list">
+      <dt><code>android:label</code></dt>
+      <dd><em>String resource</em>. <strong>Required</strong>. This is the name of your application.
+It should normally be the same as the name applied to the {@code android:label} attribute of your <a
+href="{@docRoot}guide/topics/manifest/activity-element.html#label">{@code &lt;activity&gt;}</a> or
+<a href="{@docRoot}guide/topics/manifest/application-element.html#label">{@code
+&lt;application&gt;}</a> manifest element. This is only visible to the user when you set
+<code>android:includeInGlobalSearch</code> "true", in which case, this label is used to identify
+your application as a searchable item in the system's search settings.</dd>
+      <dt><code>android:hint</code></dt>
+      <dd><em>String resource</em>. The text to display in the search text field when no text has
+        been entered. This is recommended in order to provide a hint to the user about what
+content is searchable. For consistency among other Android applications, you should format the
+string for {@code android:hint} as "Search <em>&lt;content-or-product&gt;</em>". For example,
+"Search songs and artists" or "Search YouTube".</dd>
+      <dt><code>android:searchMode</code></dt>
+      <dd><em>Keyword</em>. Sets additional modes that control the search presentation.
+Specifically, the available modes define how the query text in the search dialog's text box
+should be rewritten when a suggestion is focused. The following mode values are accepted:
+        <table>
+          <tr><th>Value</th><th>Description</th></tr>
+          <tr>
+            <td><code>"queryRewriteFromData"</code></td>
+            <td>If set, this causes the suggestion column
+            {@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA} to be considered as the
+text for suggestion query
+            rewriting. This should only be used when the values in 
+            {@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA} are suitable for user
+inspection and editing -
+            typically, HTTP/HTTPS Uri's.</td>
+          </tr>
+          <tr>
+            <td><code>"queryRewriteFromText"</code></td>
+            <td>If set, this causes the suggestion
+            column {@link android.app.SearchManager#SUGGEST_COLUMN_TEXT_1} to be considered as the
+text for suggestion query
+            rewriting. This should be used for suggestions in which no query 
+            text is provided and the {@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA}
+values are not suitable
+            for user inspection and editing.</td>
+          </tr>
+        </table>
+        <p>For more information, see the discussion about rewriting the query text in <a
+href="adding-custom-suggestions.html#RewritingQueryText">Adding Custom Suggestions</a>.</p>
+      </dd>
+      <dt><code>android:searchButtonText</code></dt>
+      <dd><em>String resource</em>. The text to display in the button that executes the search. By
+default, the button shows a search icon (a magnifying glass), which is ideal for
+internationalization.</dd>
+      <dt><code>android:inputType</code></dt>
+      <dd><em>Keyword</em>. Defines the type of input method (soft-keyboard) to use with the search
+dialog. For most searches, in which free form text is expected, this attribute is not needed and
+the default input method should be used. See {@link android.R.attr#inputType} for a list of suitable
+values for this attribute.</dd>
+      <dt><code>android:imeOptions</code></dt>
+      <dd><em>Keyword</em>. Supplies additional options for the input method.
+        For most searches, in  which free form text is expected, this attribute is not needed,
+        and will default to "actionSearch" (provides the "search" button instead of a carriage
+return). See {@link android.R.attr#imeOptions} for a list of suitable values for this attribute.
+      </dd>
+    </dl>
+
+    <p>If you have defined a content provider to generate search suggestions, you need to
+    define additional attributes in order to configure communications with the Content
+    Provider. When providing search suggestions, you'll need some of the following
+    {@code &lt;searchable>} attributes:</p><br/>
+
+      <dl class="atn-list">
+      <dt><code>android:searchSuggestAuthority</code></dt>
+        <dd><em>String</em>. <strong>Required to provide search suggestions</strong>.
+        This value must match the authority string provided in the {@code android:authorities}
+attribute of the {@code &lt;provider>} element.</dd>
+      <dt><code>android:searchSuggestPath</code></dt>
+        <dd><em>String</em>. This path will be used as a portion of the suggestions
+        query {@link android.net.Uri}, after the prefix and authority, but before
+the standard suggestions path.
+        This is only required if you have a single content provider issuing different types
+        of suggestions (e.g. for different data types) and you need 
+        a way to disambiguate the suggestions queries when they are received.</dd>
+      <dt><code>android:searchSuggestSelection</code></dt>
+        <dd><em>String</em>. This value will be passed into your
+        query function as the {@code selection} parameter. Typically this will be a WHERE clause
+for your database, and should contain a single question mark, which is a place-holder for the
+actual query string that has been typed by the user. However, you can also use any non-null
+value to simply trigger the delivery of the query text via the {@code
+selectionArgs} parameter (and then ignore the {@code selection} parameter).</dd>
+      <dt><code>android:searchSuggestIntentAction</code></dt>
+        <dd><em>String</em>. The default Intent action to be used when a user
+        clicks on a search suggestion (such as {@code "android.intent.action.VIEW"}).
+        If not overridden by the selected suggestion (via the {@link
+android.app.SearchManager#SUGGEST_COLUMN_INTENT_ACTION} column), this value will
+        be placed in the action field of the {@link android.content.Intent} when the 
+        user clicks a suggestion.</dd>
+      <dt><code>android:searchSuggestIntentData</code></dt>
+        <dd><em>String</em>. The default Intent data to be used when a user
+        clicks on a search suggestion.
+        If not overridden by the selected suggestion (via the {@link
+android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA} column), this value will be
+        placed in the data field of the {@link android.content.Intent} when the user clicks 
+        a suggestion.</dd>
+      <dt><code>android:searchSuggestThreshold</code></dt>
+        <dd><em>Integer</em>. The minimum number of characters needed to
+        trigger a suggestion look-up. Only guarantees that a source will not be
+        queried for anything shorter than the threshold. The default value is 0.</dd>
+      </dl>
+
+    <p>For more information about the above attributes for search suggestions, see the guides for
+    <a href="adding-recent-query-suggestions.html">Adding Recent Query Suggestions</a> and
+    <a href="adding-custom-suggestions.html">Adding Custom Suggestions</a>.</p>
+
+    <p>Beyond providing search suggestions while using your application's search dialog, you
+    can also configure your search suggestions to be made available to Quick Search Box,
+    which will allow users so receive search suggestions from your application content from outside
+    your application. When providing search suggestions to Quick Search Box, you'll need some of the
+    following {@code &lt;searchable>} attributes:</p><br/>
+
+      <dl class="atn-list">
+      <dt><code>android:includeInGlobalSearch</code></dt>
+        <dd><em>Boolean</em>. <strong>Required to provide search suggestions in
+        Quick Search Box</strong>. "true" if you want your suggestions to be
+        included in the globally accessible Quick Search Box. Note that the user must
+        still enable your application as a searchable item in the system search settings in order
+        for your suggestions to appear in Quick Search Box.</dd>
+      <dt><code>android:searchSettingsDescription</code></dt>
+        <dd><em>String</em>. Provides a brief description of the search suggestions that you provide
+to Quick Search Box, which will be displayed in the searchable items entry for your application.
+Your description should concisely describe the content that is searchable. For example, "Artists,
+albums, and tracks" for a music application, or "Saved notes" for a notepad application.</dd>
+      <dt><code>android:queryAfterZeroResults</code></dt>
+        <dd><em>Boolean</em>. "true" if you want your content provider to be invoked for
+        supersets of queries that have returned zero results for in the past. For example, if a
+        source returned zero results for "bo", it would be ignored for "bob". If "false",
+        this source will only be ignored for a single session; the next time the search dialog
+        is invoked, all sources will be queried. The default value is false.</dd>
+      </dl>
+
+    <p>To enable voice search for your search dialog, you'll need some of the
+    following {@code &lt;searchable>} attributes:</p><br/>
+
+      <dl class="atn-list">
+        <dt><code>android:voiceSearchMode</code></dt>
+        <dd><em>Keyword</em>. <strong>Required to provide voice search capabilities</strong>.
+          Enables voice search for the search dialog, with a specific mode for voice search.
+          (Voice search may not be provided by the device, in which case these flags will
+          have no effect.) The following mode values are accepted:
+          <table>
+            <tr><th>Value</th><th>Description</th></tr>
+            <tr>
+              <td><code>"showVoiceSearchButton"</code></td>
+              <td>Display a voice search button. This only
+              takes effect if voice search is available on the device. If set, then either
+              {@code "launchWebSearch"} or {@code "launchRecognizer"} must also be set
+              (separated by the pipe | character).</td>
+            </tr>
+            <tr>
+              <td><code>"launchWebSearch"</code></td>
+              <td>The voice search button will take the user directly
+              to a built-in voice web search activity. Most applications will not use this flag, as 
+              it will take the user away from the Activity in which search was invoked.</td>
+            </tr>
+            <tr>
+              <td><code>"launchRecognizer"</code></td>
+              <td>The voice search button will take
+              the user directly to a built-in voice recording activity. This Activity
+              will prompt the user to speak, transcribe the spoken text, and forward the resulting 
+              query text to the searchable Activity, just as if the user had typed it into the
+              search UI and clicked the search button.</td>
+            </tr>
+          </table>
+        </dd>
+        <dt><code>android:voiceLanguageModel</code></dt>
+          <dd><em>Keyword</em>. The language model that
+          should be used by the voice recognition system. The following values are accepted:
+          <table>
+            <tr><th>Value</th><th>Description</th></tr>
+            <tr>
+              <td><code>"free_form"</code></td>
+              <td>Use a language model based on free-form speech recognition. This is the
+default.</td>
+            </tr>
+            <tr>
+              <td><code>"web_search"</code></td>
+              <td>Use a language model based on web search terms.</td>
+            </tr>
+          </table>
+          <p>Also see 
+          {@link android.speech.RecognizerIntent#EXTRA_LANGUAGE_MODEL} for more
+          information.</p></dd>
+        <dt><code>android:voicePromptText</code></dt>
+          <dd><em>String</em>. An additional message to display in the voice input dialog.</dd>
+        <dt><code>android:voiceLanguage</code></dt>
+          <dd><em>String</em>. The spoken language to be expected, expressed as the string value of
+a constants in {@link java.util.Locale} (for example, {@code "de"} for German or {@code "fr"} for
+French). This is only needed if it is different from the current value of {@link
+java.util.Locale#getDefault() Locale.getDefault()}.</dd>
+        <dt><code>android:voiceMaxResults</code></dt>
+          <dd><em>Integer</em>. Forces the maximum number of results to return,
+          including the "best" result which will always be provided as the {@link
+android.content.Intent#ACTION_SEARCH} Intent's primary
+          query. Must be 1 or greater. Use {@link android.speech.RecognizerIntent#EXTRA_RESULTS} to
+get the results from the Intent.
+          If not provided, the recognizer will choose how many results to return.</dd>
+      </dl>
+  </dd> <!-- end searchable element -->
+
+
+  <dt id="actionkey-element"><code>&lt;actionkey&gt;</code></dt>
+  <dd>Defines a shortcut key for a search action, in order to provide special behaviors at the touch
+of a button, based on the current query or focused suggestion. ​For example, the Contacts
+application enables the device call key for suggestions. So, when
+the user focuses on a search suggestion using the directional controls and then presses the call
+key, the application will immediately initiate a phone call to the suggested contact.
+    <p>Not all action keys are available on every device, and not
+all keys are allowed to be overriden in this way. For example, the "Home" key cannot be used and
+must always return to the home screen. Also be sure not to define an action
+key for a key that's needed for typing a search query. This essentially limits the
+available and reasonable action keys to the call button and menu button. Also note that action
+keys are not generally discoverable, so you should not provide them as a core user feature.</p>
+      <p class="caps">attributes:</p>
+      <dl class="atn-list">
+      <dt><code>android:keycode</code></dt>
+        <dd><em>String</em>. <strong>Required</strong>. A key code from {@link
+android.view.KeyEvent} that represents the action key
+        you wish to respond to (for example {@code "KEYCODE_CALL"}). This will be added to the
+        {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} Intent that is passed to your 
+        searchable Activity. To examine the key code, use 
+        {@link android.content.Intent#getIntExtra getIntExtra(SearchManager.ACTION_KEY)}.
+        In addition to the key code, you must also provide one or more of
+        the action specifier attributes below.  Not all action keys
+are actually supported using this mechanism, as many of them are used for typing,
+        navigation, or system functions. Note that although each of the action message elements are
+optional, at least one must be present for the action key to have any effect.</dd>
+      <dt><code>android:queryActionMsg</code></dt>
+        <dd><em>String</em>. An action message to be sent if the action key is pressed while the
+user is simply entering query text. This will be added to the
+        {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} Intent that is 
+        passed to your searchable Activity. To examine the string, use 
+        {@link android.content.Intent#getStringExtra
+        getStringExtra(SearchManager.ACTION_MSG)}.</dd>
+      <dt><code>android:suggestActionMsg</code></dt>
+        <dd><em>String</em>. An action message to be sent if the action key is pressed while a
+        suggestion is focused. This will be added to the
+        Intent that is passed to your searchable Activity (using the action you've defined for
+        the suggestion). To examine the string,
+        use {@link android.content.Intent#getStringExtra 
+        getStringExtra(SearchManager.ACTION_MSG)}. Note that this should only be used if all your
+suggestions support this action key. If not all suggestions can handle the same action key, then
+you must instead use the following {@code android:suggestActionMsgColumn} attribute.</dd>
+      <dt><code>android:suggestActionMsgColumn</code></dt>
+        <dd><em>String</em>. The name of the column in your content provider that defines the
+action message for this action key, which is to be sent if the action key is pressed while a
+        suggestion is focused. This attribute lets you control the
+action key on a suggestion-by-suggestion basis, because, instead of using the {@code
+android:suggestActionMsg} attribute to define the action message for all suggestions, each entry in
+your content provider provides its own action message. First, you must define a column in your
+content provider for each suggestion to provide an action message, then provide the name of that
+column in this attribute. The search manager will look at your suggestion cursor,
+        using the string provided here in order to select your action message column, and
+        then select the action message string from the cursor. That string will be added to the
+        Intent that is passed to your searchable Activity (using the action you've defined for
+        suggestions). To examine the string, use {@link
+android.content.Intent#getStringExtra getStringExtra(SearchManager.ACTION_MSG)}. If the data
+does not exist for the selected suggestion, the action key will be ignored.</dd>
+      </dl>
+  </dd><!-- end action key -->
+ </dl>
+</dd><!-- end  elements  -->
+
+
+<dt>example:</dt>
+<dd>XML file saved at <code>res/xml/searchable.xml</code>:
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
+    android:label="@string/search_label"
+    android:hint="@string/search_hint"
+    android:searchSuggestAuthority="dictionary"
+    android:searchSuggestIntentAction="android.intent.action.VIEW"
+    android:includeInGlobalSearch="true"
+    android:searchSettingsDescription="@string/settings_description" >
+&lt;/searchable>
+</pre>
+
+</dd> <!-- end example -->
+
+
+</dl>
+
+
+
+
diff --git a/docs/html/images/search/search-suggest-custom.png b/docs/html/images/search/search-suggest-custom.png
new file mode 100644
index 0000000..be14219
--- /dev/null
+++ b/docs/html/images/search/search-suggest-custom.png
Binary files differ
diff --git a/docs/html/images/search/search-suggest-recent-queries.png b/docs/html/images/search/search-suggest-recent-queries.png
new file mode 100644
index 0000000..869edf2
--- /dev/null
+++ b/docs/html/images/search/search-suggest-recent-queries.png
Binary files differ
diff --git a/docs/html/images/search/search-ui.png b/docs/html/images/search/search-ui.png
new file mode 100644
index 0000000..19ecc19
--- /dev/null
+++ b/docs/html/images/search/search-ui.png
Binary files differ
diff --git a/docs/html/shareables/search_icons.zip b/docs/html/shareables/search_icons.zip
new file mode 100644
index 0000000..bc98465
--- /dev/null
+++ b/docs/html/shareables/search_icons.zip
Binary files differ
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 7902212..815a367 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -72,6 +72,10 @@
 // 50 * ~20msecs = 1 second
 static const int8_t kMaxTrackRetries = 50;
 static const int8_t kMaxTrackStartupRetries = 50;
+// allow less retry attempts on direct output thread.
+// direct outputs can be a scarce resource in audio hardware and should
+// be released as quickly as possible.
+static const int8_t kMaxTrackRetriesDirect = 2;
 
 static const int kDumpLockRetries = 50;
 static const int kDumpLockSleep = 20000;
@@ -1794,6 +1798,9 @@
     uint32_t activeSleepTime = activeSleepTimeUs();
     uint32_t idleSleepTime = idleSleepTimeUs();
     uint32_t sleepTime = idleSleepTime;
+    // use shorter standby delay as on normal output to release
+    // hardware resources as soon as possible
+    nsecs_t standbyDelay = microseconds(activeSleepTime*2);
 
 
     while (!exitPending())
@@ -1810,6 +1817,7 @@
                 mixBufferSize = mFrameCount*mFrameSize;
                 activeSleepTime = activeSleepTimeUs();
                 idleSleepTime = idleSleepTimeUs();
+                standbyDelay = microseconds(activeSleepTime*2);
             }
 
             // put audio hardware into standby after short delay
@@ -1842,7 +1850,7 @@
                         }
                     }
 
-                    standbyTime = systemTime() + kStandbyTimeInNsecs;
+                    standbyTime = systemTime() + standbyDelay;
                     sleepTime = idleSleepTime;
                     continue;
                 }
@@ -1896,7 +1904,7 @@
                     }
 
                     // reset retry count
-                    track->mRetryCount = kMaxTrackRetries;
+                    track->mRetryCount = kMaxTrackRetriesDirect;
                     activeTrack = t;
                     mixerStatus = MIXER_TRACKS_READY;
                 } else {
@@ -1949,7 +1957,7 @@
                 activeTrack->releaseBuffer(&buffer);
             }
             sleepTime = 0;
-            standbyTime = systemTime() + kStandbyTimeInNsecs;
+            standbyTime = systemTime() + standbyDelay;
         } else {
             if (sleepTime == 0) {
                 if (mixerStatus == MIXER_TRACKS_ENABLED) {
diff --git a/libs/audioflinger/AudioPolicyManagerBase.cpp b/libs/audioflinger/AudioPolicyManagerBase.cpp
index a61221a..c8b3f48 100644
--- a/libs/audioflinger/AudioPolicyManagerBase.cpp
+++ b/libs/audioflinger/AudioPolicyManagerBase.cpp
@@ -458,11 +458,8 @@
     }
 #endif //AUDIO_POLICY_TEST
 
-    // open a direct output if:
-    // 1 a direct output is explicitely requested
-    // 2 the audio format is compressed
-    if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
-         (format !=0 && !AudioSystem::isLinearPCM(format))) {
+    // open a direct output if required by specified parameters
+    if (needsDirectOuput(stream, samplingRate, format, channels, flags, device)) {
 
         LOGV("getOutput() opening direct output device %x", device);
         AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
@@ -472,7 +469,7 @@
         outputDesc->mChannels = channels;
         outputDesc->mLatency = 0;
         outputDesc->mFlags = (AudioSystem::output_flags)(flags | AudioSystem::OUTPUT_FLAG_DIRECT);
-        outputDesc->mRefCount[stream] = 1;
+        outputDesc->mRefCount[stream] = 0;
         output = mpClientInterface->openOutput(&outputDesc->mDevice,
                                         &outputDesc->mSamplingRate,
                                         &outputDesc->mFormat,
@@ -609,6 +606,9 @@
             setStrategyMute(STRATEGY_MEDIA, false, mA2dpOutput, mOutputs.valueFor(mHardwareOutput)->mLatency*2);
         }
 #endif
+        if (output != mHardwareOutput) {
+            setOutputDevice(mHardwareOutput, getNewDevice(mHardwareOutput), true);
+        }
         return NO_ERROR;
     } else {
         LOGW("stopOutput() refcount is already 0 for output %d", output);
@@ -1550,10 +1550,10 @@
     }
 #ifdef WITH_A2DP
     // filter devices according to output selected
-    if (output == mHardwareOutput) {
-        device &= ~AudioSystem::DEVICE_OUT_ALL_A2DP;
-    } else {
+    if (output == mA2dpOutput) {
         device &= AudioSystem::DEVICE_OUT_ALL_A2DP;
+    } else {
+        device &= ~AudioSystem::DEVICE_OUT_ALL_A2DP;
     }
 #endif
 
@@ -1562,8 +1562,7 @@
     //  - the requestede device is 0
     //  - the requested device is the same as current device and force is not specified.
     // Doing this check here allows the caller to call setOutputDevice() without conditions
-    if (device == 0 ||
-        (device == prevDevice && !force)) {
+    if ((device == 0 || device == prevDevice) && !force) {
         LOGV("setOutputDevice() setting same device %x or null device for output %d", device, output);
         return;
     }
@@ -1666,7 +1665,7 @@
     int volInt = (100 * (index - streamDesc.mIndexMin)) / (streamDesc.mIndexMax - streamDesc.mIndexMin);
     volume = AudioSystem::linearToLog(volInt);
 
-    // if a heaset is connected, apply the following rules to ring tones and notifications
+    // if a headset is connected, apply the following rules to ring tones and notifications
     // to avoid sound level bursts in user's ears:
     // - always attenuate ring tones and notifications volume by 6dB
     // - if music is playing, always limit the volume to current music volume,
@@ -1825,6 +1824,17 @@
     }
 }
 
+bool AudioPolicyManagerBase::needsDirectOuput(AudioSystem::stream_type stream,
+                                    uint32_t samplingRate,
+                                    uint32_t format,
+                                    uint32_t channels,
+                                    AudioSystem::output_flags flags,
+                                    uint32_t device)
+{
+   return ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
+          (format !=0 && !AudioSystem::isLinearPCM(format)));
+}
+
 // --- AudioOutputDescriptor class implementation
 
 AudioPolicyManagerBase::AudioOutputDescriptor::AudioOutputDescriptor()
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 4fa3327..4d364ab 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -18,6 +18,7 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.content.ComponentName;
 import android.content.Context;
 import android.database.ContentObserver;
 import android.os.Binder;
@@ -29,6 +30,7 @@
 import android.os.ServiceManager;
 import android.provider.Settings;
 import android.util.Log;
+import android.view.KeyEvent;
 
 import java.util.Iterator;
 import java.util.HashMap;
@@ -1179,7 +1181,7 @@
      * Map to convert focus event listener IDs, as used in the AudioService audio focus stack,
      * to actual listener objects.
      */
-    private HashMap<String, OnAudioFocusChangeListener> mFocusIdListenerMap =
+    private HashMap<String, OnAudioFocusChangeListener> mAudioFocusIdListenerMap =
             new HashMap<String, OnAudioFocusChangeListener>();
     /**
      * Lock to prevent concurrent changes to the list of focus listeners for this AudioManager
@@ -1188,13 +1190,14 @@
     private final Object mFocusListenerLock = new Object();
 
     private OnAudioFocusChangeListener findFocusListener(String id) {
-        return mFocusIdListenerMap.get(id);
+        return mAudioFocusIdListenerMap.get(id);
     }
 
     /**
      * Handler for audio focus events coming from the audio service.
      */
-    private FocusEventHandlerDelegate mFocusEventHandlerDelegate = new FocusEventHandlerDelegate();
+    private FocusEventHandlerDelegate mAudioFocusEventHandlerDelegate =
+            new FocusEventHandlerDelegate();
     /**
      * Event id denotes a loss of focus
      */
@@ -1239,18 +1242,18 @@
         }
     }
 
-    private IAudioFocusDispatcher mFocusDispatcher = new IAudioFocusDispatcher.Stub() {
+    private IAudioFocusDispatcher mAudioFocusDispatcher = new IAudioFocusDispatcher.Stub() {
 
         public void dispatchAudioFocusChange(int focusChange, String id) {
-            Message m = mFocusEventHandlerDelegate.getHandler().obtainMessage(focusChange, id);
-            mFocusEventHandlerDelegate.getHandler().sendMessage(m);
+            Message m = mAudioFocusEventHandlerDelegate.getHandler().obtainMessage(focusChange, id);
+            mAudioFocusEventHandlerDelegate.getHandler().sendMessage(m);
         }
 
     };
 
-    private String getIdForFocusListener(OnAudioFocusChangeListener l) {
+    private String getIdForAudioFocusListener(OnAudioFocusChangeListener l) {
         if (l == null) {
-            return new String();
+            return new String(this.toString());
         } else {
             return new String(this.toString() + l.toString());
         }
@@ -1260,14 +1263,11 @@
      * Register a listener for audio focus updates.
      */
     public void registerAudioFocusListener(OnAudioFocusChangeListener l) {
-        if (l == null) {
-            return;
-        }
         synchronized(mFocusListenerLock) {
-            if (mFocusIdListenerMap.containsKey(getIdForFocusListener(l))) {
+            if (mAudioFocusIdListenerMap.containsKey(getIdForAudioFocusListener(l))) {
                 return;
             }
-            mFocusIdListenerMap.put(getIdForFocusListener(l), l);
+            mAudioFocusIdListenerMap.put(getIdForAudioFocusListener(l), l);
         }
     }
 
@@ -1278,13 +1278,13 @@
         // notify service to remove it from audio focus stack
         IAudioService service = getService();
         try {
-            service.unregisterFocusClient(getIdForFocusListener(l));
+            service.unregisterAudioFocusClient(getIdForAudioFocusListener(l));
         } catch (RemoteException e) {
             Log.e(TAG, "Can't call unregisterFocusClient() from AudioService due to "+e);
         }
         // remove locally
         synchronized(mFocusListenerLock) {
-            mFocusIdListenerMap.remove(getIdForFocusListener(l));
+            mAudioFocusIdListenerMap.remove(getIdForAudioFocusListener(l));
         }
     }
 
@@ -1318,7 +1318,7 @@
         IAudioService service = getService();
         try {
             status = service.requestAudioFocus(streamType, durationHint, mICallBack,
-                    mFocusDispatcher, getIdForFocusListener(l));
+                    mAudioFocusDispatcher, getIdForAudioFocusListener(l));
         } catch (RemoteException e) {
             Log.e(TAG, "Can't call requestAudioFocus() from AudioService due to "+e);
         }
@@ -1336,7 +1336,8 @@
         registerAudioFocusListener(l);
         IAudioService service = getService();
         try {
-            status = service.abandonAudioFocus(mFocusDispatcher, getIdForFocusListener(l));
+            status = service.abandonAudioFocus(mAudioFocusDispatcher,
+                    getIdForAudioFocusListener(l));
         } catch (RemoteException e) {
             Log.e(TAG, "Can't call abandonAudioFocus() from AudioService due to "+e);
         }
@@ -1344,6 +1345,63 @@
     }
 
 
+    //====================================================================
+    // Remote Control
+    /**
+     * @hide
+     * TODO unhide for SDK
+     * TODO document for SDK
+     * @param eventReceiver identifier of a {@link android.content.BroadcastReceiver}
+     *      that will receive the media button intent. This broadcast receiver must be declared
+     *      in the application manifest.
+     */
+    public void registerMediaButtonEventReceiver(ComponentName eventReceiver) {
+        //TODO enforce the rule about the receiver being declared in the manifest
+        IAudioService service = getService();
+        try {
+            service.registerMediaButtonEventReceiver(eventReceiver);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in registerMediaButtonEventReceiver"+e);
+        }
+    }
+
+    /**
+     * @hide
+     * TODO unhide for SDK
+     * TODO document for SDK
+     * @param eventReceiverClass class of a {@link android.content.BroadcastReceiver} that will
+     *     receive the media button intent. This broadcast receiver must be declared in the
+     *     application manifest.
+     */
+    public void registerMediaButtonEventReceiver(Class<?> eventReceiverClass) {
+        registerMediaButtonEventReceiver(new ComponentName(
+                eventReceiverClass.getPackage().getName(), eventReceiverClass.getName()));
+    }
+
+    /**
+     * @hide
+     * TODO unhide for SDK
+     * TODO document for SDK
+     */
+    public void unregisterMediaButtonEventReceiver(ComponentName eventReceiver) {
+        IAudioService service = getService();
+        try {
+            service.unregisterMediaButtonEventReceiver(eventReceiver);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in unregisterMediaButtonEventReceiver"+e);
+        }
+    }
+
+    /**
+     * @hide
+     * TODO unhide for SDK
+     * TODO document for SDK
+     */
+    public void unregisterMediaButtonEventReceiver(Class<?> eventReceiverClass) {
+        unregisterMediaButtonEventReceiver(new ComponentName(
+                eventReceiverClass.getPackage().getName(), eventReceiverClass.getName()));
+    }
+
     /**
      *  @hide
      *  Reload audio settings. This method is called by Settings backup
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 618f239..81e17b7 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -18,6 +18,7 @@
 
 import android.app.ActivityManagerNative;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -41,6 +42,7 @@
 import android.provider.Settings;
 import android.provider.Settings.System;
 import android.util.Log;
+import android.view.KeyEvent;
 import android.view.VolumePanel;
 import android.os.SystemProperties;
 
@@ -224,6 +226,10 @@
     // Broadcast receiver for device connections intent broadcasts
     private final BroadcastReceiver mReceiver = new AudioServiceBroadcastReceiver();
 
+    //  Broadcast receiver for media button broadcasts (separate from mReceiver to
+    //  independently change its priority)
+    private final BroadcastReceiver mMediaButtonReceiver = new MediaButtonBroadcastReceiver();
+
     // Devices currently connected
     private HashMap <Integer, String> mConnectedDevices = new HashMap <Integer, String>();
 
@@ -269,6 +275,10 @@
         intentFilter.addAction(Intent.ACTION_DOCK_EVENT);
         context.registerReceiver(mReceiver, intentFilter);
 
+        // Register for media button intent broadcasts.
+        intentFilter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);
+        intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+        context.registerReceiver(mMediaButtonReceiver, intentFilter);
     }
 
     private void createAudioSystemThread() {
@@ -1667,7 +1677,7 @@
             if (signal) {
                 // notify the new top of the stack it gained focus
                 if (!mFocusStack.empty() && (mFocusStack.peek().mFocusDispatcher != null)
-                        && canReassignFocus()) {
+                        && canReassignAudioFocus()) {
                     try {
                         mFocusStack.peek().mFocusDispatcher.dispatchAudioFocusChange(
                                 AudioManager.AUDIOFOCUS_GAIN, mFocusStack.peek().mClientId);
@@ -1714,7 +1724,7 @@
      * Helper function:
      * Returns true if the system is in a state where the focus can be reevaluated, false otherwise.
      */
-    private boolean canReassignFocus() {
+    private boolean canReassignAudioFocus() {
         // focus requests are rejected during a phone call
         if (getMode() == AudioSystem.MODE_IN_CALL) {
             Log.i(TAG, " AudioFocus  can't be reassigned during a call, exiting");
@@ -1747,7 +1757,7 @@
     }
 
 
-    /** @see AudioManager#requestAudioFocus(int, int, IBinder, IAudioFocusDispatcher, String) */
+    /** @see AudioManager#requestAudioFocus(IAudioFocusDispatcher, int, int) */
     public int requestAudioFocus(int mainStreamType, int durationHint, IBinder cb,
             IAudioFocusDispatcher fd, String clientId) {
         Log.i(TAG, " AudioFocus  requestAudioFocus() from " + clientId);
@@ -1759,7 +1769,7 @@
             return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
         }
 
-        if (!canReassignFocus()) {
+        if (!canReassignAudioFocus()) {
             return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
         }
 
@@ -1803,7 +1813,7 @@
         return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
     }
 
-    /** @see AudioManager#abandonAudioFocus(IBinder, IAudioFocusDispatcher, String) */
+    /** @see AudioManager#abandonAudioFocus(IAudioFocusDispatcher) */
     public int abandonAudioFocus(IAudioFocusDispatcher fl, String clientId) {
         Log.i(TAG, " AudioFocus  abandonAudioFocus() from " + clientId);
 
@@ -1814,15 +1824,141 @@
     }
 
 
-    public void unregisterFocusClient(String clientId) {
+    public void unregisterAudioFocusClient(String clientId) {
         removeFocusStackEntry(clientId, false);
     }
 
 
+    //==========================================================================================
+    // RemoteControl
+    //==========================================================================================
+    /**
+     * Receiver for media button intents. Handles the dispatching of the media button event
+     * to one of the registered listeners, or if there was none, resumes the intent broadcast
+     * to the rest of the system.
+     */
+    private class MediaButtonBroadcastReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (!Intent.ACTION_MEDIA_BUTTON.equals(action)) {
+                return;
+            }
+            KeyEvent event = (KeyEvent) intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
+            if (event != null) {
+                // if in a call or ringing, do not break the current phone app behavior
+                // TODO modify this to let the phone app specifically get the RC focus
+                //      add modify the phone app to take advantage of the new API
+                if ((getMode() == AudioSystem.MODE_IN_CALL) ||
+                        (getMode() == AudioSystem.MODE_RINGTONE)) {
+                    return;
+                }
+                synchronized(mRCStack) {
+                    if (!mRCStack.empty()) {
+                        // create a new intent specifically aimed at the current registered listener
+                        Intent targetedIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
+                        targetedIntent.putExtras(intent.getExtras());
+                        targetedIntent.setComponent(mRCStack.peek().mReceiverComponent);
+                        // trap the current broadcast
+                        abortBroadcast();
+                        //Log.v(TAG, " Sending intent" + targetedIntent);
+                        context.sendBroadcast(targetedIntent, null);
+                    }
+                }
+            }
+        }
+    }
+
+    private static class RemoteControlStackEntry {
+        public ComponentName mReceiverComponent;// always non null
+        // TODO implement registration expiration?
+        //public int mRegistrationTime;
+
+        public RemoteControlStackEntry() {
+        }
+
+        public RemoteControlStackEntry(ComponentName r) {
+            mReceiverComponent = r;
+        }
+    }
+
+    private Stack<RemoteControlStackEntry> mRCStack = new Stack<RemoteControlStackEntry>();
+
+    /**
+     * Helper function:
+     * Display in the log the current entries in the remote control focus stack
+     */
+    private void dumpRCStack(PrintWriter pw) {
+        pw.println("Remote Control stack entries:");
+        synchronized(mRCStack) {
+            Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
+            while(stackIterator.hasNext()) {
+                RemoteControlStackEntry fse = stackIterator.next();
+                pw.println("     receiver:" + fse.mReceiverComponent);
+            }
+        }
+    }
+
+    /**
+     * Helper function:
+     * Set the new remote control receiver at the top of the RC focus stack
+     */
+    private void pushMediaButtonReceiver(ComponentName newReceiver) {
+        // already at top of stack?
+        if (!mRCStack.empty() && mRCStack.peek().mReceiverComponent.equals(newReceiver)) {
+            return;
+        }
+        Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
+        while(stackIterator.hasNext()) {
+            RemoteControlStackEntry rcse = (RemoteControlStackEntry)stackIterator.next();
+            if(rcse.mReceiverComponent.equals(newReceiver)) {
+                mRCStack.remove(rcse);
+                break;
+            }
+        }
+        mRCStack.push(new RemoteControlStackEntry(newReceiver));
+    }
+
+    /**
+     * Helper function:
+     * Remove the remote control receiver from the RC focus stack
+     */
+    private void removeMediaButtonReceiver(ComponentName newReceiver) {
+        Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
+        while(stackIterator.hasNext()) {
+            RemoteControlStackEntry rcse = (RemoteControlStackEntry)stackIterator.next();
+            if(rcse.mReceiverComponent.equals(newReceiver)) {
+                mRCStack.remove(rcse);
+                break;
+            }
+        }
+    }
+
+
+    /** see AudioManager.registerMediaButtonEventReceiver(ComponentName eventReceiver) */
+    public void registerMediaButtonEventReceiver(ComponentName eventReceiver) {
+        Log.i(TAG, "  Remote Control   registerMediaButtonEventReceiver() for " + eventReceiver);
+
+        synchronized(mRCStack) {
+            pushMediaButtonReceiver(eventReceiver);
+        }
+    }
+
+    /** see AudioManager.unregisterMediaButtonEventReceiver(ComponentName eventReceiver) */
+    public void unregisterMediaButtonEventReceiver(ComponentName eventReceiver) {
+        Log.i(TAG, "  Remote Control   registerMediaButtonEventReceiver() for " + eventReceiver);
+
+        synchronized(mRCStack) {
+            removeMediaButtonReceiver(eventReceiver);
+        }
+    }
+
+
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        // TODO probably a lot more to do here than just the audio focus stack
+        // TODO probably a lot more to do here than just the audio focus and remote control stacks
         dumpFocusStack(pw);
+        dumpRCStack(pw);
     }
 
 
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index b275488..953892b 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.content.ComponentName;
 import android.media.IAudioFocusDispatcher;
 
 /**
@@ -76,5 +77,9 @@
 
     int abandonAudioFocus(IAudioFocusDispatcher l, String clientId);
     
-    void unregisterFocusClient(String clientId);
+    void unregisterAudioFocusClient(String clientId);
+
+    void registerMediaButtonEventReceiver(in ComponentName eventReceiver);
+
+    void unregisterMediaButtonEventReceiver(in ComponentName eventReceiver);
 }
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 4b364f2..5e6ce42 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -358,7 +358,7 @@
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     unsigned int result = 0;
     if (af == 0) return result;
-    if (ioHandle == NULL) return result;
+    if (ioHandle == 0) return result;
 
     result = af->getInputFramesLost(ioHandle);
     return result;
@@ -556,7 +556,18 @@
                                     output_flags flags)
 {
     audio_io_handle_t output = 0;
-    if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) == 0) {
+    // Do not use stream to output map cache if the direct output
+    // flag is set or if we are likely to use a direct output
+    // (e.g voice call stream @ 8kHz could use BT SCO device and be routed to
+    // a direct output on some platforms).
+    // TODO: the output cache and stream to output mapping implementation needs to
+    // be reworked for proper operation with direct outputs. This code is too specific
+    // to the first use case we want to cover (Voice Recognition and Voice Dialer over
+    // Bluetooth SCO
+    if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) == 0 &&
+        ((stream != AudioSystem::VOICE_CALL && stream != AudioSystem::BLUETOOTH_SCO) ||
+         channels != AudioSystem::CHANNEL_OUT_MONO ||
+         (samplingRate != 8000 && samplingRate != 16000))) {
         Mutex::Autolock _l(gLock);
         output = AudioSystem::gStreamOutputMap.valueFor(stream);
         LOGV_IF((output != 0), "getOutput() read %d from cache for stream %d", output, stream);
diff --git a/media/libstagefright/codecs/aacdec/AACDecoder.cpp b/media/libstagefright/codecs/aacdec/AACDecoder.cpp
index f0b66c9..fe84b38 100644
--- a/media/libstagefright/codecs/aacdec/AACDecoder.cpp
+++ b/media/libstagefright/codecs/aacdec/AACDecoder.cpp
@@ -199,7 +199,16 @@
     mConfig->pOutputBuffer_plus = NULL;
     mConfig->repositionFlag = false;
 
-    CHECK_EQ(PVMP4AudioDecodeFrame(mConfig, mDecoderBuf), MP4AUDEC_SUCCESS);
+    Int decoderErr = PVMP4AudioDecodeFrame(mConfig, mDecoderBuf);
+
+    if (decoderErr != MP4AUDEC_SUCCESS) {
+        LOGE("AAC decoder returned error %d", decoderErr);
+
+        buffer->release();
+        buffer = NULL;
+
+        return ERROR_MALFORMED;
+    }
 
     buffer->set_range(
             0, mConfig->frameLength * sizeof(int16_t) * mConfig->desiredChannels);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
index 8202efd..5ed68c5 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
@@ -212,8 +212,13 @@
     }
 
     private void terminateMessageLooper() {
-        mLooper.quit();
-        mCamera.release();
+        try {
+            mLooper.quit();
+            mCamera.release();
+            Thread.sleep(1500);
+        } catch (Exception e) {
+            Log.v(TAG, e.toString());
+        }
     }
 
     private final class RawPreviewCallback implements PreviewCallback {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java
index 4c259f1..7174e2b 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java
@@ -40,6 +40,7 @@
         Log.v(TAG, "testAlbumArt starts.");
         MediaMetadataRetriever retriever = new MediaMetadataRetriever();
         boolean supportWMA = MediaProfileReader.getWMAEnable();
+        boolean hasFailed = false;
         boolean supportWMV = MediaProfileReader.getWMVEnable();
         retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
         for (int i = 0, n = MediaNames.ALBUMART_TEST_FILES.length; i < n; ++i) {
@@ -58,15 +59,18 @@
                 // A better test would be to compare the retrieved album art with the
                 // known result.
                 if (albumArt == null) {  // Do we have expect in JUnit?
-                    fail("Fails to extract album art for " + MediaNames.ALBUMART_TEST_FILES[i]);
+                    Log.e(TAG, "Fails to extract album art for " + MediaNames.ALBUMART_TEST_FILES[i]);
+                    hasFailed = true;
                 }
             } catch(Exception e) {
-                throw new Exception("Fails to setDataSource for " + MediaNames.ALBUMART_TEST_FILES[i], e);
+                Log.e(TAG, "Fails to setDataSource for " + MediaNames.ALBUMART_TEST_FILES[i]);
+                hasFailed = true;
             }
             Thread.yield();  // Don't be evil
         }
         retriever.release();
         Log.v(TAG, "testAlbumArt completes.");
+        assertTrue(!hasFailed);
     }
 
     // Test frame capture
@@ -75,6 +79,7 @@
         MediaMetadataRetriever retriever = new MediaMetadataRetriever();
         boolean supportWMA = MediaProfileReader.getWMAEnable();
         boolean supportWMV = MediaProfileReader.getWMVEnable();
+        boolean hasFailed = false;
         Log.v(TAG, "Thumbnail processing starts");
         long startedAt = System.currentTimeMillis();
         for(int i = 0, n = MediaNames.THUMBNAIL_CAPTURE_TEST_FILES.length; i < n; ++i) {
@@ -94,22 +99,26 @@
                     bitmap.compress(Bitmap.CompressFormat.JPEG, 75, stream);
                     stream.close();
                 } catch (Exception e) {
-                    throw new Exception("Fails to convert the bitmap to a JPEG file for " + MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i], e);
+                    Log.e(TAG, "Fails to convert the bitmap to a JPEG file for " + MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i]);
+                    hasFailed = true;
                 }
             } catch(Exception e) {
-                throw new Exception("Fails to setDataSource for file " + MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i], e);
+                Log.e(TAG, "Fails to setDataSource for file " + MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i]);
+                hasFailed = true;
             }
             Thread.yield();  // Don't be evil
         }
         long endedAt = System.currentTimeMillis();
-        Log.v(TAG, "Average processing time per thumbnail: " + (endedAt - startedAt)/MediaNames.THUMBNAIL_CAPTURE_TEST_FILES.length + " ms");
         retriever.release();
+        assertTrue(!hasFailed);
+        Log.v(TAG, "Average processing time per thumbnail: " + (endedAt - startedAt)/MediaNames.THUMBNAIL_CAPTURE_TEST_FILES.length + " ms");
     }
     
     @LargeTest
     public static void testMetadataRetrieval() throws Exception {
         boolean supportWMA = MediaProfileReader.getWMAEnable();
         boolean supportWMV = MediaProfileReader.getWMVEnable();
+        boolean hasFailed = false;
         MediaMetadataRetriever retriever = new MediaMetadataRetriever();
         retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
         for(int i = 0, n = MediaNames.METADATA_RETRIEVAL_TEST_FILES.length; i < n; ++i) {
@@ -124,17 +133,20 @@
                 retriever.setDataSource(MediaNames.METADATA_RETRIEVAL_TEST_FILES[i]);
                 extractAllSupportedMetadataValues(retriever);
             } catch(Exception e) {
-                throw new Exception("Fails to setDataSource for file " + MediaNames.METADATA_RETRIEVAL_TEST_FILES[i], e);
+                Log.e(TAG, "Fails to setDataSource for file " + MediaNames.METADATA_RETRIEVAL_TEST_FILES[i]);
+                hasFailed = true;
             }
             Thread.yield();  // Don't be evil
         }
         retriever.release();
+        assertTrue(!hasFailed);
     }
 
     // If the specified call order and valid media file is used, no exception
     // should be thrown.
     @MediumTest
     public static void testBasicNormalMethodCallSequence() throws Exception {
+        boolean hasFailed = false;
         MediaMetadataRetriever retriever = new MediaMetadataRetriever();
         retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
         try {
@@ -153,19 +165,29 @@
             */
             extractAllSupportedMetadataValues(retriever);
         } catch(Exception e) {
-            throw new Exception("Fails to setDataSource for " + MediaNames.TEST_PATH_1, e);
+            Log.e(TAG, "Fails to setDataSource for " + MediaNames.TEST_PATH_1, e);
+            hasFailed = true;
         }
         retriever.release();
+        assertTrue(!hasFailed);
     }
 
     // If setDataSource() has not been called, both captureFrame() and extractMetadata() must
     // return null.
     @MediumTest
     public static void testBasicAbnormalMethodCallSequence() {
+        boolean hasFailed = false;
         MediaMetadataRetriever retriever = new MediaMetadataRetriever();
         retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
-        assertTrue(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM) == null);
-        assertTrue(retriever.captureFrame() == null);
+        if (retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM) != null) {
+            Log.e(TAG, "No album metadata expected, but is available");
+            hasFailed = true;
+        }
+        if (retriever.captureFrame() != null) {
+            Log.e(TAG, "No frame expected, but is available");
+            hasFailed = true;
+        }
+        assertTrue(!hasFailed);
     }
 
     // Test setDataSource()
@@ -173,42 +195,60 @@
     public static void testSetDataSource() {
         MediaMetadataRetriever retriever = new MediaMetadataRetriever();
         retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
+        boolean hasFailed = false;
 
         // Null pointer argument
         try {
             String path = null;
             retriever.setDataSource(path);
-            fail("IllegalArgumentException must be thrown.");
+            Log.e(TAG, "IllegalArgumentException failed to be thrown.");
+            hasFailed = true;
         } catch(Exception e) {
-            assertTrue(e instanceof IllegalArgumentException);
+            if (!(e instanceof IllegalArgumentException)) {
+                Log.e(TAG, "Expected a IllegalArgumentException, but got a different exception");
+                hasFailed = true;
+            }
         }
 
         // Use mem:// path
         try {
             retriever.setDataSource(MediaNames.TEST_PATH_5);
-            fail("IllegalArgumentException must be thrown.");
+            Log.e(TAG, "IllegalArgumentException failed to be thrown.");
+            hasFailed = true;
         } catch(Exception e) {
-            assertTrue(e instanceof IllegalArgumentException);
+            if (!(e instanceof IllegalArgumentException)) {
+                Log.e(TAG, "Expected a IllegalArgumentException, but got a different exception");
+                hasFailed = true;
+            }
         }
 
         // The pathname does not correspond to any existing file
         try {
             retriever.setDataSource(MediaNames.TEST_PATH_4);
-            fail("Runtime exception must be thrown.");
+            Log.e(TAG, "RuntimeException failed to be thrown.");
+            hasFailed = true;
         } catch(Exception e) {
-            assertTrue(e instanceof RuntimeException);
+            if (!(e instanceof RuntimeException)) {
+                Log.e(TAG, "Expected a RuntimeException, but got a different exception");
+                hasFailed = true;
+            }
         }
 
         // The pathname does correspond to a file, but this file
         // is not a valid media file
         try {
             retriever.setDataSource(MediaNames.TEST_PATH_3);
-            fail("Runtime exception must be thrown.");
+            Log.e(TAG, "RuntimeException failed to be thrown.");
+            hasFailed = true;
         } catch(Exception e) {
-            assertTrue(e instanceof RuntimeException);
+            if (!(e instanceof RuntimeException)) {
+                Log.e(TAG, "Expected a RuntimeException, but got a different exception");
+                hasFailed = true;
+            }
         }
         
         retriever.release();
+        assertTrue(!hasFailed);
     }
 
     // Due to the lack of permission to access hardware decoder, any calls
@@ -218,6 +258,7 @@
     public static void testIntendedUsage() {
         // By default, capture frame and retrieve metadata
         MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+        boolean hasFailed = false;
         // retriever.setDataSource(MediaNames.TEST_PATH_1);
         // assertTrue(retriever.captureFrame() != null);
         // assertTrue(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) != null);
@@ -225,8 +266,14 @@
         // Do not capture frame or retrieve metadata
         retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY & MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
         retriever.setDataSource(MediaNames.TEST_PATH_1);
-        assertTrue(retriever.captureFrame() == null);
-        assertTrue(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) == null);
+        if (retriever.captureFrame() != null) {
+            Log.e(TAG, "No frame expected, but is available");
+            hasFailed = true;
+        }
+        if (retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) != null) {
+            Log.e(TAG, "No num track metadata expected, but is available");
+            hasFailed = true;
+        }
 
         // Capture frame only
         // retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY);
@@ -236,7 +283,10 @@
         // Retriever metadata only
         retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
         retriever.setDataSource(MediaNames.TEST_PATH_1);
-        assertTrue(retriever.captureFrame() == null);
+        if (retriever.captureFrame() != null) {
+            Log.e(TAG, "No frame expected, but is available");
+            hasFailed = true;
+        }
 
         // Capture frame and retrieve metadata
         // retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY | MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
@@ -244,6 +294,7 @@
         // assertTrue(retriever.captureFrame() != null);
         // assertTrue(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) != null);
         retriever.release();
+        assertTrue(!hasFailed);
     }
 
     // TODO:
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index e336a35..11020c2 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -1463,8 +1463,6 @@
     void showInputMethodMenu() {
         if (DEBUG) Slog.v(TAG, "Show switching menu");
 
-        hideInputMethodMenu();
-
         final Context context = mContext;
 
         final PackageManager pm = context.getPackageManager();
@@ -1479,67 +1477,69 @@
             return;
         }
         
-        int N = immis.size();
+        synchronized (mMethodMap) {
+            hideInputMethodMenuLocked();
 
-        mItems = new CharSequence[N];
-        mIms = new InputMethodInfo[N];
-
-        for (int i = 0; i < N; ++i) {
-            InputMethodInfo property = immis.get(i);
-            if (property == null) {
-                i--;
-                N--;
-                continue;
+            int N = immis.size();
+    
+            mItems = new CharSequence[N];
+            mIms = new InputMethodInfo[N];
+    
+            int j = 0;
+            for (int i = 0; i < N; ++i) {
+                InputMethodInfo property = immis.get(i);
+                if (property == null) {
+                    continue;
+                }
+                mItems[j] = property.loadLabel(pm);
+                mIms[j] = property;
+                j++;
             }
-            mItems[i] = property.loadLabel(pm);
-            mIms[i] = property;
-        }
-
-        int checkedItem = 0;
-        for (int i = 0; i < N; ++i) {
-            if (mIms[i].getId().equals(lastInputMethodId)) {
-                checkedItem = i;
-                break;
+    
+            int checkedItem = 0;
+            for (int i = 0; i < N; ++i) {
+                if (mIms[i].getId().equals(lastInputMethodId)) {
+                    checkedItem = i;
+                    break;
+                }
             }
-        }
-
-        AlertDialog.OnClickListener adocl = new AlertDialog.OnClickListener() {
-            public void onClick(DialogInterface dialog, int which) {
-                hideInputMethodMenu();
-            }
-        };
-
-        TypedArray a = context.obtainStyledAttributes(null,
-                com.android.internal.R.styleable.DialogPreference,
-                com.android.internal.R.attr.alertDialogStyle, 0);
-        mDialogBuilder = new AlertDialog.Builder(context)
-                .setTitle(com.android.internal.R.string.select_input_method)
-                .setOnCancelListener(new OnCancelListener() {
-                    public void onCancel(DialogInterface dialog) {
-                        hideInputMethodMenu();
-                    }
-                })
-                .setIcon(a.getDrawable(
-                        com.android.internal.R.styleable.DialogPreference_dialogTitle));
-        a.recycle();
-
-        mDialogBuilder.setSingleChoiceItems(mItems, checkedItem,
-                new AlertDialog.OnClickListener() {
-                    public void onClick(DialogInterface dialog, int which) {
-                        synchronized (mMethodMap) {
-                            if (mIms == null || mIms.length <= which) {
-                                return;
-                            }
-                            InputMethodInfo im = mIms[which];
+    
+            AlertDialog.OnClickListener adocl = new AlertDialog.OnClickListener() {
+                public void onClick(DialogInterface dialog, int which) {
+                    hideInputMethodMenu();
+                }
+            };
+    
+            TypedArray a = context.obtainStyledAttributes(null,
+                    com.android.internal.R.styleable.DialogPreference,
+                    com.android.internal.R.attr.alertDialogStyle, 0);
+            mDialogBuilder = new AlertDialog.Builder(context)
+                    .setTitle(com.android.internal.R.string.select_input_method)
+                    .setOnCancelListener(new OnCancelListener() {
+                        public void onCancel(DialogInterface dialog) {
                             hideInputMethodMenu();
-                            if (im != null) {
-                                setInputMethodLocked(im.getId());
+                        }
+                    })
+                    .setIcon(a.getDrawable(
+                            com.android.internal.R.styleable.DialogPreference_dialogTitle));
+            a.recycle();
+    
+            mDialogBuilder.setSingleChoiceItems(mItems, checkedItem,
+                    new AlertDialog.OnClickListener() {
+                        public void onClick(DialogInterface dialog, int which) {
+                            synchronized (mMethodMap) {
+                                if (mIms == null || mIms.length <= which) {
+                                    return;
+                                }
+                                InputMethodInfo im = mIms[which];
+                                hideInputMethodMenu();
+                                if (im != null) {
+                                    setInputMethodLocked(im.getId());
+                                }
                             }
                         }
-                    }
-                });
+                    });
 
-        synchronized (mMethodMap) {
             mSwitchingDialog = mDialogBuilder.create();
             mSwitchingDialog.getWindow().setType(
                     WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG);
diff --git a/services/java/com/android/server/status/UsbStorageActivity.java b/services/java/com/android/server/status/UsbStorageActivity.java
index c1c8c22..b3ee257 100644
--- a/services/java/com/android/server/status/UsbStorageActivity.java
+++ b/services/java/com/android/server/status/UsbStorageActivity.java
@@ -28,6 +28,7 @@
 import android.content.DialogInterface.OnCancelListener;
 import android.os.Bundle;
 import android.os.Environment;
+import android.os.Handler;
 import android.os.IBinder;
 import android.os.storage.IMountService;
 import android.os.storage.StorageManager;
@@ -36,8 +37,10 @@
 import android.os.ServiceManager;
 import android.widget.ImageView;
 import android.widget.Button;
+import android.widget.ProgressBar;
 import android.widget.TextView;
 import android.view.View;
+import android.view.Window;
 import android.util.Log;
 
 /**
@@ -48,8 +51,10 @@
 public class UsbStorageActivity extends Activity
         implements View.OnClickListener, OnCancelListener {
     private static final String TAG = "UsbStorageActivity";
+
     private Button mMountButton;
     private Button mUnmountButton;
+    private ProgressBar mProgressBar;
     private TextView mBanner;
     private TextView mMessage;
     private ImageView mIcon;
@@ -71,11 +76,8 @@
     private StorageEventListener mStorageListener = new StorageEventListener() {
         @Override
         public void onStorageStateChanged(String path, String oldState, String newState) {
-            if (newState.equals(Environment.MEDIA_SHARED)) {
-                switchDisplay(true);
-            } else {
-                switchDisplay(false);
-            }
+            final boolean on = newState.equals(Environment.MEDIA_SHARED);
+            switchDisplay(on);
         }
     };
     
@@ -90,6 +92,9 @@
             }
         }
 
+        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+        setProgressBarIndeterminateVisibility(true);
+
         setTitle(getString(com.android.internal.R.string.usb_storage_activity_title));
 
         setContentView(com.android.internal.R.layout.usb_storage_activity);
@@ -102,16 +107,19 @@
         mMountButton.setOnClickListener(this);
         mUnmountButton = (Button) findViewById(com.android.internal.R.id.unmount_button);
         mUnmountButton.setOnClickListener(this);
+        mProgressBar = (ProgressBar) findViewById(com.android.internal.R.id.progress);
     }
 
     private void switchDisplay(boolean usbStorageInUse) {
         if (usbStorageInUse) {
+            mProgressBar.setVisibility(View.GONE);
             mUnmountButton.setVisibility(View.VISIBLE);
             mMountButton.setVisibility(View.GONE);
             mIcon.setImageResource(com.android.internal.R.drawable.usb_android_connected);
             mBanner.setText(com.android.internal.R.string.usb_storage_stop_title);
             mMessage.setText(com.android.internal.R.string.usb_storage_stop_message);
         } else {
+            mProgressBar.setVisibility(View.GONE);
             mUnmountButton.setVisibility(View.GONE);
             mMountButton.setVisibility(View.VISIBLE);
             mIcon.setImageResource(com.android.internal.R.drawable.usb_android);
@@ -189,6 +197,25 @@
         showDialog(id);
     }
 
+    private void switchUsbMassStorageAsync(boolean on) {
+        mUnmountButton.setVisibility(View.GONE);
+        mMountButton.setVisibility(View.GONE);
+
+        mProgressBar.setVisibility(View.VISIBLE);
+        // will be hidden once USB mass storage kicks in (or fails)
+        
+        final boolean _on = on;
+        new Thread() {
+            public void run() {
+                if (_on) {
+                    mStorageManager.enableUsbMassStorage();
+                } else {
+                    mStorageManager.disableUsbMassStorage();
+                }
+            }
+        }.start();
+    }
+
     private void checkStorageUsers() {
         IMountService ims = getMountService();
         if (ims == null) {
@@ -208,18 +235,17 @@
             showDialogInner(DLG_CONFIRM_KILL_STORAGE_USERS);
         } else {
             if (localLOGV) Log.i(TAG, "Enabling UMS");
-            mStorageManager.enableUsbMassStorage();
+            switchUsbMassStorageAsync(true);
         }
     }
 
     public void onClick(View v) {
-        Log.i(TAG, "Clicked button");
         if (v == mMountButton) {
            // Check for list of storage users and display dialog if needed.
             checkStorageUsers();
         } else if (v == mUnmountButton) {
             if (localLOGV) Log.i(TAG, "Disabling UMS");
-            mStorageManager.disableUsbMassStorage();
+            switchUsbMassStorageAsync(false);
         }
     }
 
diff --git a/tests/AndroidTests/src/com/android/unit_tests/internal/util/HanziToPinyinTest.java b/tests/AndroidTests/src/com/android/unit_tests/internal/util/HanziToPinyinTest.java
index 8e1ff0b..71a8ea7 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/internal/util/HanziToPinyinTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/internal/util/HanziToPinyinTest.java
@@ -17,6 +17,7 @@
 package com.android.unit_tests.internal.util;
 
 import java.text.Collator;
+import java.util.Arrays;
 import java.util.ArrayList;
 import java.util.Locale;
 
@@ -37,6 +38,9 @@
 
     @SmallTest
     public void testGetToken() throws Exception {
+        if (!Arrays.asList(Collator.getAvailableLocales()).contains(Locale.CHINA)) {
+            return;
+        }
         ArrayList<Token> tokens = HanziToPinyin.getInstance().get(ONE_HANZI);
         assertEquals(tokens.size(), 1);
         assertEquals(tokens.get(0).type, Token.PINYIN);
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
index 297b963..506de83 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
@@ -95,7 +95,8 @@
         ignoreResultList.add("http/tests/appcache/max-size.html"); // no layoutTestController.setAppCacheMaximumSize
         ignoreResultList.add("http/tests/appcache/manifest-with-empty-file.html"); // flaky
         ignoreResultList.add("http/tests/appcache/whitelist-wildcard.html"); // file not found
-        ignoreResultList.add("storage/database-lock-after-reload.html"); // failure
+        ignoreResultList.add("storage/database-lock-after-reload.html"); // Succeeds but DumpRenderTree does not read result correctly
+        ignoreResultList.add("storage/hash-change-with-xhr.html"); // Succeeds but DumpRenderTree does not read result correctly
 
         // Will always fail
         ignoreResultList.add("dom/svg/level3/xpath"); // XPath not supported
@@ -116,6 +117,9 @@
         ignoreResultList.add("fast/workers/shared-worker-shared.html"); // shared workers not supported
         ignoreResultList.add("fast/workers/shared-worker-simple.html"); // shared workers not supported
         ignoreResultList.add("fast/xpath"); // XPath not supported
+        ignoreResultList.add("storage/domstorage/localstorage/private-browsing-affects-storage.html"); // private browsing not supported
+        ignoreResultList.add("storage/domstorage/sessionstorage/private-browsing-affects-storage.html"); // private browsing not supported
+        ignoreResultList.add("storage/private-browsing-readonly.html"); // private browsing not supported
 
         // TODO: These need to be triaged
         ignoreResultList.add("fast/css/case-transform.html"); // will not fix #619707
@@ -189,9 +193,6 @@
         ignoreResultList.add("fast/replaced/image-map.html"); // requires eventSender.mouseDown(),mouseUp()
         ignoreResultList.add("fast/text/plain-text-line-breaks.html"); // extra spacing because iFrames rendered next to each other on Apple
         ignoreResultList.add("profiler"); // profiler is not supported
-        ignoreResultList.add("storage/domstorage/localstorage/private-browsing-affects-storage.html"); // No notion of private browsing.
-        ignoreResultList.add("storage/domstorage/sessionstorage/private-browsing-affects-storage.html"); // No notion of private browsing.
-        ignoreResultList.add("storage/private-browsing-readonly.html"); // No notion of private browsing.
         ignoreResultList.add("svg"); // svg is not supported
 
     }