Merge "Add some useful methods to OperationScheduler to inquire into the history, in case you want to second-guess its scheduling."
diff --git a/api/current.xml b/api/current.xml
index 1608ebf..40739da 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -13833,7 +13833,7 @@
 >
 <parameter name="parcel" type="android.os.Parcel">
 </parameter>
-<parameter name="flags" type="int">
+<parameter name="flagz" type="int">
 </parameter>
 </method>
 <field name="CREATOR"
@@ -38899,6 +38899,17 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_PHYSICAL_DOCK_STATE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.extra.PHYSICAL_DOCK_STATE&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="EXTRA_REMOTE_INTENT_TOKEN"
  type="java.lang.String"
  transient="false"
@@ -60401,6 +60412,102 @@
 </parameter>
 </constructor>
 </class>
+<class name="ImageFormat"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ImageFormat"
+ type="android.graphics.ImageFormat"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getBitsPerPixel"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="format" type="int">
+</parameter>
+</method>
+<field name="JPEG"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="256"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NV16"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NV21"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RGB_565"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="UNKNOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="YUY2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="20"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="Interpolator"
  extends="java.lang.Object"
  abstract="false"
@@ -64462,7 +64569,7 @@
  value="256"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -64616,7 +64723,7 @@
  value="17"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -64627,7 +64734,7 @@
  value="20"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -64638,7 +64745,7 @@
  value="16"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -78725,6 +78832,17 @@
  visibility="public"
 >
 </field>
+<field name="PASSIVE_PROVIDER"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;passive&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <class name="LocationProvider"
  extends="java.lang.Object"
@@ -119439,6 +119557,17 @@
  visibility="public"
 >
 </field>
+<field name="OperationFailedStorageBusy"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OperationFailedStorageMounted"
  type="int"
  transient="false"
@@ -136987,6 +137116,21 @@
 <parameter name="context" type="android.content.Context">
 </parameter>
 </method>
+<method name="createRecognitionManager"
+ return="android.speech.RecognitionManager"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="serviceComponent" type="android.content.ComponentName">
+</parameter>
+</method>
 <method name="destroy"
  return="void"
  abstract="false"
@@ -137385,6 +137529,30 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<method name="getVoiceDetailsIntent"
+ return="android.content.Intent"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</method>
+<field name="ACTION_GET_LANGUAGE_DETAILS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech.action.GET_LANGUAGE_DETAILS&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="ACTION_RECOGNIZE_SPEECH"
  type="java.lang.String"
  transient="false"
@@ -137407,6 +137575,17 @@
  visibility="public"
 >
 </field>
+<field name="DETAILS_META_DATA"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech.DETAILS&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="EXTRA_LANGUAGE"
  type="java.lang.String"
  transient="false"
@@ -137429,6 +137608,17 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_LANGUAGE_PREFERENCE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech.extra.LANGUAGE_PREFERENCE&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="EXTRA_MAX_RESULTS"
  type="java.lang.String"
  transient="false"
@@ -137528,6 +137718,17 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_SUPPORTED_LANGUAGES"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech.extra.SUPPORTED_LANGUAGES&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="LANGUAGE_MODEL_FREE_FORM"
  type="java.lang.String"
  transient="false"
@@ -172879,6 +173080,19 @@
  visibility="public"
 >
 </method>
+<method name="dispatchConfigurationChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="newConfig" type="android.content.res.Configuration">
+</parameter>
+</method>
 <method name="dispatchDisplayHint"
  return="void"
  abstract="false"
@@ -174570,6 +174784,19 @@
  visibility="public"
 >
 </method>
+<method name="onConfigurationChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="newConfig" type="android.content.res.Configuration">
+</parameter>
+</method>
 <method name="onCreateContextMenu"
  return="void"
  abstract="false"
@@ -190954,6 +191181,17 @@
  visibility="public"
 >
 </method>
+<method name="getBlockNetworkLoads"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getBuiltInZoomControls"
  return="boolean"
  abstract="false"
@@ -191382,6 +191620,19 @@
 <parameter name="flag" type="boolean">
 </parameter>
 </method>
+<method name="setBlockNetworkLoads"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="flag" type="boolean">
+</parameter>
+</method>
 <method name="setBuiltInZoomControls"
  return="void"
  abstract="false"
@@ -201496,6 +201747,19 @@
  native="false"
  synchronized="false"
  static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="color" type="int">
+</parameter>
+</method>
+<method name="setColorFilter"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
  final="false"
  deprecated="not deprecated"
  visibility="public"
diff --git a/camera/libcameraservice/FakeCamera.cpp b/camera/libcameraservice/FakeCamera.cpp
index 3daf47d..6749899 100644
--- a/camera/libcameraservice/FakeCamera.cpp
+++ b/camera/libcameraservice/FakeCamera.cpp
@@ -234,7 +234,7 @@
             uint8_t   y0, y1, u, v;
 
             pixels =  inputRGB[i];
-            temp = (ALPHA*(pixels & 0x001F) + BETA*(pixels>>11) );
+            temp = (BETA*(pixels & 0x001F) + ALPHA*(pixels>>11) );
             y0   = y_tab[(temp>>SHIFT1) + ((pixels>>3) & 0x00FC)];
 
             G_ds    += (pixels>>1) & 0x03E0;
@@ -242,7 +242,7 @@
             R_ds    += (pixels>>6) & 0x03E0;
 
             pixels =  inputRGB[i+1];
-            temp = (ALPHA*(pixels & 0x001F) + BETA*(pixels>>11) );
+            temp = (BETA*(pixels & 0x001F) + ALPHA*(pixels>>11) );
             y1   = y_tab[(temp>>SHIFT1) + ((pixels>>3) & 0x00FC)];
 
             G_ds    += (pixels>>1) & 0x03E0;
@@ -255,8 +255,8 @@
 
             tmp = R_ds - B_ds;
 
-            u = cb_tab[(((R_ds-G_ds)<<SHIFT2) + DELTA*tmp)>>(SHIFT2+2)];
-            v = cr_tab[(((B_ds-G_ds)<<SHIFT2) - GAMMA*tmp)>>(SHIFT2+2)];
+            u = cb_tab[(((B_ds-G_ds)<<SHIFT2) - GAMMA*tmp)>>(SHIFT2+2)];
+            v = cr_tab[(((R_ds-G_ds)<<SHIFT2) + DELTA*tmp)>>(SHIFT2+2)];
 
             tempY[0] = y0;
             tempY[1] = y1;
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index f7cb227..942a303 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -157,13 +157,18 @@
     long numIterationsLeft = gNumRepetitions;
     MediaSource::ReadOptions options;
 
+    int64_t sumDecodeUs = 0;
+
     while (numIterationsLeft-- > 0) {
         long numFrames = 0;
 
         MediaBuffer *buffer;
 
         for (;;) {
+            int64_t startDecodeUs = getNowUs();
             status_t err = rawSource->read(&buffer, &options);
+            int64_t delayDecodeUs = getNowUs() - startDecodeUs;
+
             options.clearSeekTo();
 
             if (err != OK) {
@@ -182,6 +187,8 @@
                 fflush(stdout);
             }
 
+            sumDecodeUs += delayDecodeUs;
+
             buffer->release();
             buffer = NULL;
 
@@ -210,6 +217,8 @@
 
     int64_t delay = getNowUs() - startTime;
     printf("avg. %.2f fps\n", n * 1E6 / delay);
+    printf("avg. time to decode one buffer %.2f usecs\n",
+           (double)sumDecodeUs / n);
 
     printf("decoded a total of %d frame(s).\n", n);
 }
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 4761f98..bf9e07d 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -66,10 +66,10 @@
      * The event types an {@link AccessibilityService} is interested in.
      *
      * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED
+     * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_LONG_CLICKED
      * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_FOCUSED
      * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SELECTED
      * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED
-     * @see android.view.accessibility.AccessibilityEvent#TYPE_ACTIVITY_STARTED
      * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED
      * @see android.view.accessibility.AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED
      */
@@ -115,7 +115,7 @@
         return 0;
     }
 
-    public void writeToParcel(Parcel parcel, int flags) {
+    public void writeToParcel(Parcel parcel, int flagz) {
         parcel.writeInt(eventTypes);
         parcel.writeStringArray(packageNames);
         parcel.writeInt(feedbackType);
diff --git a/core/java/android/accounts/AbstractAccountAuthenticator.java b/core/java/android/accounts/AbstractAccountAuthenticator.java
index be2bdbe..8bc7428 100644
--- a/core/java/android/accounts/AbstractAccountAuthenticator.java
+++ b/core/java/android/accounts/AbstractAccountAuthenticator.java
@@ -296,8 +296,7 @@
      * <ul>
      * <li> {@link AccountManager#KEY_INTENT}, or
      * <li> {@link AccountManager#KEY_ACCOUNT_NAME} and {@link AccountManager#KEY_ACCOUNT_TYPE} of
-     * the account that was added, plus {@link AccountManager#KEY_AUTHTOKEN} if an authTokenType
-     * was supplied, or
+     * the account that was added, or
      * <li> {@link AccountManager#KEY_ERROR_CODE} and {@link AccountManager#KEY_ERROR_MESSAGE} to
      * indicate an error
      * </ul>
@@ -368,8 +367,7 @@
      * <ul>
      * <li> {@link AccountManager#KEY_INTENT}, or
      * <li> {@link AccountManager#KEY_ACCOUNT_NAME} and {@link AccountManager#KEY_ACCOUNT_TYPE} of
-     * the account that was added, plus {@link AccountManager#KEY_AUTHTOKEN} if an authTokenType
-     * was supplied, or
+     * the account that was added, or
      * <li> {@link AccountManager#KEY_ERROR_CODE} and {@link AccountManager#KEY_ERROR_MESSAGE} to
      * indicate an error
      * </ul>
@@ -378,7 +376,7 @@
      */
     public abstract Bundle updateCredentials(AccountAuthenticatorResponse response,
             Account account, String authTokenType, Bundle options) throws NetworkErrorException;
-    
+
     /**
      * Checks if the account supports all the specified authenticator specific features.
      * @param response to send the result back to the AccountManager, will never be null
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index be15ac9..43a0f30 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -67,6 +67,8 @@
  * cause the running thread to block until the result is returned. Keep in mind that one
  * should not block the main thread in this way. Instead one should either use a callback,
  * thus making the call asynchronous, or make the blocking call on a separate thread.
+ * getResult() will throw an {@link IllegalStateException} if you call it from the main thread
+ * before the request has completed, i.e. before the callback has been invoked.
  * <p>
  * If one wants to ensure that the callback is invoked from a specific handler then they should
  * pass the handler to the request. This makes it easier to ensure thread-safety by running
@@ -149,6 +151,8 @@
      * Get the password that is associated with the account. Returns null if the account does
      * not exist.
      * <p>
+     * It is safe to call this method from the main thread.
+     * <p>
      * Requires that the caller has permission
      * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and is running
      * with the same UID as the Authenticator for the account.
@@ -166,6 +170,8 @@
      * Get the user data named by "key" that is associated with the account.
      * Returns null if the account does not exist or if it does not have a value for key.
      * <p>
+     * It is safe to call this method from the main thread.
+     * <p>
      * Requires that the caller has permission
      * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and is running
      * with the same UID as the Authenticator for the account.
@@ -185,6 +191,8 @@
      * @return an array that contains all the authenticators known to the AccountManager service.
      * This array will be empty if there are no authenticators and will never return null.
      * <p>
+     * It is safe to call this method from the main thread.
+     * <p>
      * No permission is required to make this call.
      */
     public AuthenticatorDescription[] getAuthenticatorTypes() {
@@ -201,6 +209,8 @@
      * @return an array that contains all the accounts known to the AccountManager service.
      * This array will be empty if there are no accounts and will never return null.
      * <p>
+     * It is safe to call this method from the main thread.
+     * <p>
      * Requires that the caller has permission {@link android.Manifest.permission#GET_ACCOUNTS}
      */
     public Account[] getAccounts() {
@@ -219,6 +229,8 @@
      * @return an array that contains the accounts that match the specified type. This array
      * will be empty if no accounts match. It will never return null.
      * <p>
+     * It is safe to call this method from the main thread.
+     * <p>
      * Requires that the caller has permission {@link android.Manifest.permission#GET_ACCOUNTS}
      */
     public Account[] getAccountsByType(String type) {
@@ -243,6 +255,22 @@
      * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value,
      * which will then block until the request completes.
      * <p>
+     * Do not block the main thread waiting this method's result.
+     * <p>
+     * Not allowed from main thread (but allowed from other threads):
+     * <pre>
+     * Boolean result = hasFeatures(account, features, callback, handler).getResult();
+     * </pre>
+     * Allowed from main thread:
+     * <pre>
+     * hasFeatures(account, features, new AccountManagerCallback<Boolean>() {
+     *    public void run(AccountManagerFuture<Boolean> future) {
+     *        Boolean result = future.getResult();
+     *        // use result
+     *    }
+     * }, handler);
+     * </pre>
+     * <p>
      * Requires that the caller has permission {@link android.Manifest.permission#GET_ACCOUNTS}.
      *
      * @param account The {@link Account} to test
@@ -274,6 +302,8 @@
     /**
      * Add an account to the AccountManager's set of known accounts.
      * <p>
+     * It is safe to call this method from the main thread.
+     * <p>
      * Requires that the caller has permission
      * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and is running
      * with the same UID as the Authenticator for the account.
@@ -304,6 +334,22 @@
      * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value,
      * which will then block until the request completes.
      * <p>
+     * Do not block the main thread waiting this method's result.
+     * <p>
+     * Not allowed from main thread (but allowed from other threads):
+     * <pre>
+     * Boolean result = removeAccount(account, callback, handler).getResult();
+     * </pre>
+     * Allowed from main thread:
+     * <pre>
+     * removeAccount(account, new AccountManagerCallback<Boolean>() {
+     *    public void run(AccountManagerFuture<Boolean> future) {
+     *        Boolean result = future.getResult();
+     *        // use result
+     *    }
+     * }, handler);
+     * </pre>
+     * <p>
      * Requires that the caller has permission {@link android.Manifest.permission#MANAGE_ACCOUNTS}.
      *
      * @param account The {@link Account} to remove
@@ -334,6 +380,8 @@
      * Removes the given authtoken. If this authtoken does not exist for the given account type
      * then this call has no effect.
      * <p>
+     * It is safe to call this method from the main thread.
+     * <p>
      * Requires that the caller has permission {@link android.Manifest.permission#MANAGE_ACCOUNTS}.
      * @param accountType the account type of the authtoken to invalidate
      * @param authToken the authtoken to invalidate
@@ -353,6 +401,8 @@
      * asking the authenticaticor to generate one. If the account or the
      * authtoken do not exist then null is returned.
      * <p>
+     * It is safe to call this method from the main thread.
+     * <p>
      * Requires that the caller has permission
      * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and is running
      * with the same UID as the Authenticator for the account.
@@ -381,6 +431,8 @@
      * Sets the password for the account. The password may be null. If the account does not exist
      * then this call has no affect.
      * <p>
+     * It is safe to call this method from the main thread.
+     * <p>
      * Requires that the caller has permission
      * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and is running
      * with the same UID as the Authenticator for the account.
@@ -404,6 +456,8 @@
      * Sets the password for account to null. If the account does not exist then this call
      * has no effect.
      * <p>
+     * It is safe to call this method from the main thread.
+     * <p>
      * Requires that the caller has permission {@link android.Manifest.permission#MANAGE_ACCOUNTS}.
      * @param account the account whose password is to be cleared. Must not be null.
      */
@@ -424,6 +478,8 @@
      * Sets account's userdata named "key" to the specified value. If the account does not
      * exist then this call has no effect.
      * <p>
+     * It is safe to call this method from the main thread.
+     * <p>
      * Requires that the caller has permission
      * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and is running
      * with the same UID as the Authenticator for the account.
@@ -452,6 +508,8 @@
      * Sets the authtoken named by "authTokenType" to the value specified by authToken.
      * If the account does not exist then this call has no effect.
      * <p>
+     * It is safe to call this method from the main thread.
+     * <p>
      * Requires that the caller has permission
      * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and is running
      * with the same UID as the Authenticator for the account.
@@ -473,6 +531,8 @@
      * {@link #getAuthToken(Account, String, boolean, AccountManagerCallback, Handler)}
      * then extracts and returns the value of {@link #KEY_AUTHTOKEN} from its result.
      * <p>
+     * It is not safe to call this method from the main thread. See {@link #getAuthToken}.
+     * <p>
      * Requires that the caller has permission {@link android.Manifest.permission#USE_CREDENTIALS}.
      * @param account the account whose authtoken is to be retrieved, must not be null
      * @param authTokenType the type of authtoken to retrieve
@@ -505,9 +565,8 @@
      * in the result.
      * <p>
      * If the authenticator needs to prompt the user for credentials it will return an intent to
-     * the activity that will do the prompting. If an activity is supplied then that activity
-     * will be used to launch the intent and the result will come from it. Otherwise a result will
-     * be returned that contains the intent.
+     * an activity that will do the prompting. The supplied activity will be used to launch the
+     * intent and the result will come from the launched activity.
      * <p>
      * This call returns immediately but runs asynchronously and the result is accessed via the
      * {@link AccountManagerFuture} that is returned. This future is also passed as the sole
@@ -518,6 +577,23 @@
      * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value,
      * which will then block until the request completes.
      * <p>
+     * Do not block the main thread waiting this method's result.
+     * <p>
+     * Not allowed from main thread (but allowed from other threads):
+     * <pre>
+     * Bundle result = getAuthToken(
+     *   account, authTokenType, options, activity, callback, handler).getResult();
+     * </pre>
+     * Allowed from main thread:
+     * <pre>
+     * getAuthToken(account, authTokenType, options, activity, new AccountManagerCallback<Bundle>() {
+     *    public void run(AccountManagerFuture<Bundle> future) {
+     *        Bundle result = future.getResult();
+     *        // use result
+     *    }
+     * }, handler);
+     * </pre>
+     * <p>
      * Requires that the caller has permission {@link android.Manifest.permission#USE_CREDENTIALS}.
      *
      * @param account The account whose credentials are to be updated.
@@ -525,8 +601,9 @@
      * May be null.
      * @param options authenticator specific options for the request
      * @param activity If the authenticator returns a {@link #KEY_INTENT} in the result then
-     * the intent will be started with this activity. If activity is null then the result will
-     * be returned as-is.
+     * the intent will be started with this activity. If you do not with to have the intent
+     * started automatically then use the other form,
+     * {@link #getAuthToken(Account, String, boolean, AccountManagerCallback, android.os.Handler)}
      * @param callback A callback to invoke when the request completes. If null then
      * no callback is invoked.
      * @param handler The {@link Handler} to use to invoke the callback. If null then the
@@ -578,6 +655,23 @@
      * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value,
      * which will then block until the request completes.
      * <p>
+     * Do not block the main thread waiting this method's result.
+     * <p>
+     * Not allowed from main thread (but allowed from other threads):
+     * <pre>
+     * Bundle result = getAuthToken(
+     *   account, authTokenType, notifyAuthFailure, callback, handler).getResult();
+     * </pre>
+     * Allowed from main thread:
+     * <pre>
+     * getAuthToken(account, authTokenType, notifyAuthFailure, new AccountManagerCallback<Bundle>() {
+     *    public void run(AccountManagerFuture<Bundle> future) {
+     *        Bundle result = future.getResult();
+     *        // use result
+     *    }
+     * }, handler);
+     * </pre>
+     * <p>
      * Requires that the caller has permission {@link android.Manifest.permission#USE_CREDENTIALS}.
      *
      * @param account The account whose credentials are to be updated.
@@ -625,6 +719,23 @@
      * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value,
      * which will then block until the request completes.
      * <p>
+     * Do not block the main thread waiting this method's result.
+     * <p>
+     * Not allowed from main thread (but allowed from other threads):
+     * <pre>
+     * Bundle result = addAccount(
+     *   account, authTokenType, features, options, activity, callback, handler).getResult();
+     * </pre>
+     * Allowed from main thread:
+     * <pre>
+     * addAccount(account, authTokenType, features, options, activity, new AccountManagerCallback<Bundle>() {
+     *    public void run(AccountManagerFuture<Bundle> future) {
+     *        Bundle result = future.getResult();
+     *        // use result
+     *    }
+     * }, handler);
+     * </pre>
+     * <p>
      * Requires that the caller has permission {@link android.Manifest.permission#MANAGE_ACCOUNTS}.
      *
      * @param accountType The type of account to add. This must not be null.
@@ -646,7 +757,6 @@
      * <ul>
      * <li> {@link #KEY_INTENT}, or
      * <li> {@link #KEY_ACCOUNT_NAME}, {@link #KEY_ACCOUNT_TYPE}
-     * and {@link #KEY_AUTHTOKEN} (if an authTokenType was specified).
      * </ul>
      */
     public AccountManagerFuture<Bundle> addAccount(final String accountType,
@@ -667,6 +777,51 @@
         }.start();
     }
 
+    /**
+     * Queries for accounts that match the given account type and feature set.
+     * <p>
+     * This call returns immediately but runs asynchronously and the result is accessed via the
+     * {@link AccountManagerFuture} that is returned. This future is also passed as the sole
+     * parameter to the {@link AccountManagerCallback}. If the caller wished to use this
+     * method asynchronously then they will generally pass in a callback object that will get
+     * invoked with the {@link AccountManagerFuture}. If they wish to use it synchronously then
+     * they will generally pass null for the callback and instead call
+     * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value,
+     * which will then block until the request completes.
+     * <p>
+     * Do not block the main thread waiting this method's result.
+     * <p>
+     * Not allowed from main thread (but allowed from other threads):
+     * <pre>
+     * Account[] result =
+     *   getAccountsByTypeAndFeatures(accountType, features, callback, handler).getResult();
+     * </pre>
+     * Allowed from main thread:
+     * <pre>
+     * getAccountsByTypeAndFeatures(accountType, features, new AccountManagerCallback<Account[]>() {
+     *    public void run(AccountManagerFuture<Account[]> future) {
+     *         Account[] result = future.getResult();
+     *        // use result
+     *    }
+     * }, handler);
+     * </pre>
+     * <p>
+     * Requires that the caller has permission {@link android.Manifest.permission#GET_ACCOUNTS}.
+     *
+     * @param type The type of {@link Account} to return. If null is passed in then an empty
+     * array will be returned.
+     * @param features the features with which to filter the accounts list. Each returned account
+     * will have all specified features. This may be null, which will mean the account list will
+     * not be filtered by features, making this functionally identical to
+     * {@link #getAccountsByType(String)}.
+     * @param callback A callback to invoke when the request completes. If null then
+     * no callback is invoked.
+     * @param handler The {@link Handler} to use to invoke the callback. If null then the
+     * main thread's {@link Handler} is used.
+     * @return an {@link AccountManagerFuture} that represents the future result of the call.
+     * The future result is a an {@link Account} array that contains accounts of the specified
+     * type that match all the requested features.
+     */
     public AccountManagerFuture<Account[]> getAccountsByTypeAndFeatures(
             final String type, final String[] features,
             AccountManagerCallback<Account[]> callback, Handler handler) {
@@ -709,6 +864,23 @@
      * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value,
      * which will then block until the request completes.
      * <p>
+     * Do not block the main thread waiting this method's result.
+     * <p>
+     * Not allowed from main thread (but allowed from other threads):
+     * <pre>
+     * Bundle result = confirmCredentials(
+     *   account, options, activity, callback, handler).getResult();
+     * </pre>
+     * Allowed from main thread:
+     * <pre>
+     * confirmCredentials(account, options, activity, new AccountManagerCallback<Bundle>() {
+     *    public void run(AccountManagerFuture<Bundle> future) {
+     *        Bundle result = future.getResult();
+     *        // use result
+     *    }
+     * }, handler);
+     * </pre>
+     * <p>
      * Requires that the caller has permission {@link android.Manifest.permission#MANAGE_ACCOUNTS}.
      *
      * @param account The account whose credentials are to be checked
@@ -757,6 +929,23 @@
      * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value,
      * which will then block until the request completes.
      * <p>
+     * Do not block the main thread waiting this method's result.
+     * <p>
+     * Not allowed from main thread (but allowed from other threads):
+     * <pre>
+     * Bundle result = updateCredentials(
+     *   account, authTokenType, options, activity, callback, handler).getResult();
+     * </pre>
+     * Allowed from main thread:
+     * <pre>
+     * updateCredentials(account, authTokenType, options, activity, new AccountManagerCallback<Bundle>() {
+     *    public void run(AccountManagerFuture<Bundle> future) {
+     *        Bundle result = future.getResult();
+     *        // use result
+     *    }
+     * }, handler);
+     * </pre>
+     * <p>
      * Requires that the caller has permission {@link android.Manifest.permission#MANAGE_ACCOUNTS}.
      *
      * @param account The account whose credentials are to be updated.
@@ -775,7 +964,7 @@
      * <ul>
      * <li> {@link #KEY_INTENT}, which is to be used to prompt the user for the credentials
      * <li> {@link #KEY_ACCOUNT_NAME} and {@link #KEY_ACCOUNT_TYPE} if the user enters the correct
-     * credentials, and optionally a {@link #KEY_AUTHTOKEN} if an authTokenType was provided.
+     * credentials.
      * </ul>
      * If the user presses "back" then the request will be canceled.
      */
@@ -807,6 +996,22 @@
      * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value,
      * which will then block until the request completes.
      * <p>
+     * Do not block the main thread waiting this method's result.
+     * <p>
+     * Not allowed from main thread (but allowed from other threads):
+     * <pre>
+     * Bundle result = editProperties(accountType, activity, callback, handler).getResult();
+     * </pre>
+     * Allowed from main thread:
+     * <pre>
+     * editProperties(accountType, activity, new AccountManagerCallback<Bundle>() {
+     *    public void run(AccountManagerFuture<Bundle> future) {
+     *        Bundle result = future.getResult();
+     *        // use result
+     *    }
+     * }, handler);
+     * </pre>
+     * <p>
      * Requires that the caller has permission {@link android.Manifest.permission#MANAGE_ACCOUNTS}.
      *
      * @param accountType The account type of the authenticator whose properties are to be edited.
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 7850124..770554e 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -466,7 +466,8 @@
 
         public TestFeaturesSession(IAccountManagerResponse response,
                 Account account, String[] features) {
-            super(response, account.type, false /* expectActivityLaunch */);
+            super(response, account.type, false /* expectActivityLaunch */,
+                    true /* stripAuthTokenFromResult */);
             mFeatures = features;
             mAccount = account;
         }
@@ -520,7 +521,8 @@
     private class RemoveAccountSession extends Session {
         final Account mAccount;
         public RemoveAccountSession(IAccountManagerResponse response, Account account) {
-            super(response, account.type, false /* expectActivityLaunch */);
+            super(response, account.type, false /* expectActivityLaunch */,
+                    true /* stripAuthTokenFromResult */);
             mAccount = account;
         }
 
@@ -794,7 +796,8 @@
                 }
             }
 
-            new Session(response, account.type, expectActivityLaunch) {
+            new Session(response, account.type, expectActivityLaunch,
+                    false /* stripAuthTokenFromResult */) {
                 protected String toDebugString(long now) {
                     if (loginOptions != null) loginOptions.keySet();
                     return super.toDebugString(now) + ", getAuthToken"
@@ -945,7 +948,8 @@
         checkManageAccountsPermission();
         long identityToken = clearCallingIdentity();
         try {
-            new Session(response, accountType, expectActivityLaunch) {
+            new Session(response, accountType, expectActivityLaunch,
+                    true /* stripAuthTokenFromResult */) {
                 public void run() throws RemoteException {
                     mAuthenticator.addAccount(this, mAccountType, authTokenType, requiredFeatures,
                             options);
@@ -970,7 +974,8 @@
         checkManageAccountsPermission();
         long identityToken = clearCallingIdentity();
         try {
-            new Session(response, account.type, expectActivityLaunch) {
+            new Session(response, account.type, expectActivityLaunch,
+                    true /* stripAuthTokenFromResult */) {
                 public void run() throws RemoteException {
                     mAuthenticator.confirmCredentials(this, account, options);
                 }
@@ -990,7 +995,8 @@
         checkManageAccountsPermission();
         long identityToken = clearCallingIdentity();
         try {
-            new Session(response, account.type, expectActivityLaunch) {
+            new Session(response, account.type, expectActivityLaunch,
+                    true /* stripAuthTokenFromResult */) {
                 public void run() throws RemoteException {
                     mAuthenticator.updateCredentials(this, account, authTokenType, loginOptions);
                 }
@@ -1012,7 +1018,8 @@
         checkManageAccountsPermission();
         long identityToken = clearCallingIdentity();
         try {
-            new Session(response, accountType, expectActivityLaunch) {
+            new Session(response, accountType, expectActivityLaunch,
+                    true /* stripAuthTokenFromResult */) {
                 public void run() throws RemoteException {
                     mAuthenticator.editProperties(this, mAccountType);
                 }
@@ -1034,7 +1041,8 @@
 
         public GetAccountsByTypeAndFeatureSession(IAccountManagerResponse response,
             String type, String[] features) {
-            super(response, type, false /* expectActivityLaunch */);
+            super(response, type, false /* expectActivityLaunch */,
+                    true /* stripAuthTokenFromResult */);
             mFeatures = features;
         }
 
@@ -1176,11 +1184,14 @@
 
         IAccountAuthenticator mAuthenticator = null;
 
+        private final boolean mStripAuthTokenFromResult;
+
         public Session(IAccountManagerResponse response, String accountType,
-                boolean expectActivityLaunch) {
+                boolean expectActivityLaunch, boolean stripAuthTokenFromResult) {
             super();
             if (response == null) throw new IllegalArgumentException("response is null");
             if (accountType == null) throw new IllegalArgumentException("accountType is null");
+            mStripAuthTokenFromResult = stripAuthTokenFromResult;
             mResponse = response;
             mAccountType = accountType;
             mExpectActivityLaunch = expectActivityLaunch;
@@ -1319,6 +1330,9 @@
                         response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
                                 "null bundle returned");
                     } else {
+                        if (mStripAuthTokenFromResult) {
+                            result.remove(AccountManager.KEY_AUTHTOKEN);
+                        }
                         response.onResult(result);
                     }
                 } catch (RemoteException e) {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 56e44c8..13cc3ba 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1392,7 +1392,7 @@
             r.startsNotResumed = notResumed;
             r.createdConfig = config;
 
-            synchronized (mRelaunchingActivities) {
+            synchronized (mPackages) {
                 mRelaunchingActivities.add(r);
             }
 
@@ -1523,8 +1523,11 @@
         }
 
         public void scheduleConfigurationChanged(Configuration config) {
-            synchronized (mRelaunchingActivities) {
-                mPendingConfiguration = config;
+            synchronized (mPackages) {
+                if (mPendingConfiguration == null ||
+                        mPendingConfiguration.isOtherSeqNewer(config)) {
+                    mPendingConfiguration = config;
+                }
             }
             queueOrSendMessage(H.CONFIGURATION_CHANGED, config);
         }
@@ -2060,6 +2063,7 @@
             = new HashMap<IBinder, Service>();
     AppBindData mBoundApplication;
     Configuration mConfiguration;
+    Configuration mResConfiguration;
     Application mInitialApplication;
     final ArrayList<Application> mAllApplications
             = new ArrayList<Application>();
@@ -2073,14 +2077,6 @@
     boolean mSystemThread = false;
     boolean mJitEnabled = false;
 
-    /**
-     * Activities that are enqueued to be relaunched.  This list is accessed
-     * by multiple threads, so you must synchronize on it when accessing it.
-     */
-    final ArrayList<ActivityRecord> mRelaunchingActivities
-            = new ArrayList<ActivityRecord>();
-    Configuration mPendingConfiguration = null;
-
     // These can be accessed by multiple threads; mPackages is the lock.
     // XXX For now we keep around information about all packages we have
     // seen, not removing entries from this map.
@@ -2092,6 +2088,9 @@
     DisplayMetrics mDisplayMetrics = null;
     HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
         = new HashMap<ResourcesKey, WeakReference<Resources> >();
+    final ArrayList<ActivityRecord> mRelaunchingActivities
+            = new ArrayList<ActivityRecord>();
+        Configuration mPendingConfiguration = null;
 
     // The lock of mProviderMap protects the following variables.
     final HashMap<String, ProviderRecord> mProviderMap
@@ -3555,7 +3554,7 @@
         // First: make sure we have the most recent configuration and most
         // recent version of the activity, or skip it if some previous call
         // had taken a more recent version.
-        synchronized (mRelaunchingActivities) {
+        synchronized (mPackages) {
             int N = mRelaunchingActivities.size();
             IBinder token = tmp.token;
             tmp = null;
@@ -3585,8 +3584,12 @@
             // assume that is really what we want regardless of what we
             // may have pending.
             if (mConfiguration == null
-                    || mConfiguration.diff(tmp.createdConfig) != 0) {
-                changedConfig = tmp.createdConfig;
+                    || (tmp.createdConfig.isOtherSeqNewer(mConfiguration)
+                            && mConfiguration.diff(tmp.createdConfig) != 0)) {
+                if (changedConfig == null
+                        || tmp.createdConfig.isOtherSeqNewer(changedConfig)) {
+                    changedConfig = tmp.createdConfig;
+                }
             }
         }
         
@@ -3761,62 +3764,81 @@
         }
     }
 
-    final void handleConfigurationChanged(Configuration config) {
+    final void applyConfigurationToResourcesLocked(Configuration config) {
+        if (mResConfiguration == null) {
+            mResConfiguration = new Configuration();
+        }
+        if (!mResConfiguration.isOtherSeqNewer(config)) {
+            return;
+        }
+        mResConfiguration.updateFrom(config);
+        DisplayMetrics dm = getDisplayMetricsLocked(true);
 
-        synchronized (mRelaunchingActivities) {
-            if (mPendingConfiguration != null) {
-                config = mPendingConfiguration;
-                mPendingConfiguration = null;
-            }
+        // set it for java, this also affects newly created Resources
+        if (config.locale != null) {
+            Locale.setDefault(config.locale);
         }
 
-        ArrayList<ComponentCallbacks> callbacks
-                = new ArrayList<ComponentCallbacks>();
+        Resources.updateSystemConfiguration(config, dm);
 
-        if (DEBUG_CONFIGURATION) Log.v(TAG, "Handle configuration changed: "
-                + config);
+        ContextImpl.ApplicationPackageManager.configurationChanged();
+        //Log.i(TAG, "Configuration changed in " + currentPackageName());
         
-        synchronized(mPackages) {
+        Iterator<WeakReference<Resources>> it =
+            mActiveResources.values().iterator();
+        //Iterator<Map.Entry<String, WeakReference<Resources>>> it =
+        //    mActiveResources.entrySet().iterator();
+        while (it.hasNext()) {
+            WeakReference<Resources> v = it.next();
+            Resources r = v.get();
+            if (r != null) {
+                r.updateConfiguration(config, dm);
+                //Log.i(TAG, "Updated app resources " + v.getKey()
+                //        + " " + r + ": " + r.getConfiguration());
+            } else {
+                //Log.i(TAG, "Removing old resources " + v.getKey());
+                it.remove();
+            }
+        }
+    }
+    
+    final void handleConfigurationChanged(Configuration config) {
+
+        ArrayList<ComponentCallbacks> callbacks = null;
+
+        synchronized (mPackages) {
+            if (mPendingConfiguration != null) {
+                if (!mPendingConfiguration.isOtherSeqNewer(config)) {
+                    config = mPendingConfiguration;
+                }
+                mPendingConfiguration = null;
+            }
+
+            if (config == null) {
+                return;
+            }
+            
+            if (DEBUG_CONFIGURATION) Log.v(TAG, "Handle configuration changed: "
+                    + config);
+        
+            applyConfigurationToResourcesLocked(config);
+            
             if (mConfiguration == null) {
                 mConfiguration = new Configuration();
             }
+            if (!mConfiguration.isOtherSeqNewer(config)) {
+                return;
+            }
             mConfiguration.updateFrom(config);
-            DisplayMetrics dm = getDisplayMetricsLocked(true);
-
-            // set it for java, this also affects newly created Resources
-            if (config.locale != null) {
-                Locale.setDefault(config.locale);
-            }
-
-            Resources.updateSystemConfiguration(config, dm);
-
-            ContextImpl.ApplicationPackageManager.configurationChanged();
-            //Log.i(TAG, "Configuration changed in " + currentPackageName());
-            {
-                Iterator<WeakReference<Resources>> it =
-                    mActiveResources.values().iterator();
-                //Iterator<Map.Entry<String, WeakReference<Resources>>> it =
-                //    mActiveResources.entrySet().iterator();
-                while (it.hasNext()) {
-                    WeakReference<Resources> v = it.next();
-                    Resources r = v.get();
-                    if (r != null) {
-                        r.updateConfiguration(config, dm);
-                        //Log.i(TAG, "Updated app resources " + v.getKey()
-                        //        + " " + r + ": " + r.getConfiguration());
-                    } else {
-                        //Log.i(TAG, "Removing old resources " + v.getKey());
-                        it.remove();
-                    }
-                }
-            }
 
             callbacks = collectComponentCallbacksLocked(false, config);
         }
 
-        final int N = callbacks.size();
-        for (int i=0; i<N; i++) {
-            performConfigurationChanged(callbacks.get(i), config);
+        if (callbacks != null) {
+            final int N = callbacks.size();
+            for (int i=0; i<N; i++) {
+                performConfigurationChanged(callbacks.get(i), config);
+            }
         }
     }
 
@@ -3856,7 +3878,7 @@
         ArrayList<ComponentCallbacks> callbacks
                 = new ArrayList<ComponentCallbacks>();
 
-        synchronized(mPackages) {
+        synchronized (mPackages) {
             callbacks = collectComponentCallbacksLocked(true, null);
         }
 
@@ -4348,6 +4370,25 @@
                         "Unable to instantiate Application():" + e.toString(), e);
             }
         }
+        
+        ViewRoot.addConfigCallback(new ComponentCallbacks() {
+            public void onConfigurationChanged(Configuration newConfig) {
+                synchronized (mPackages) {
+                    if (mPendingConfiguration == null ||
+                            mPendingConfiguration.isOtherSeqNewer(newConfig)) {
+                        mPendingConfiguration = newConfig;
+                        
+                        // We need to apply this change to the resources
+                        // immediately, because upon returning the view
+                        // hierarchy will be informed about it.
+                        applyConfigurationToResourcesLocked(newConfig);
+                    }
+                }
+                queueOrSendMessage(H.CONFIGURATION_CHANGED, newConfig);
+            }
+            public void onLowMemory() {
+            }
+        });
     }
 
     private final void detach()
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 52cdc74..ce5f1bf 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -1690,6 +1690,25 @@
     }
 
     /**
+     * Gets the name of the web search activity.
+     *
+     * @return The name of the default activity for web searches. This activity
+     *         can be used to get web search suggestions. Returns {@code null} if
+     *         there is no default web search activity.
+     *
+     * @hide
+     */
+    public ComponentName getWebSearchActivity() {
+        ComponentName globalSearch = getGlobalSearchActivity();
+        if (globalSearch == null) {
+            return null;
+        }
+        Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
+        intent.setPackage(globalSearch.getPackageName());
+        return intent.resolveActivity(mContext.getPackageManager());
+    }
+
+    /**
      * Similar to {@link #startSearch} but actually fires off the search query after invoking
      * the search dialog.  Made available for testing purposes.
      *
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index 8ec5bd4..6767332 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -56,6 +56,8 @@
  * <li><a href="#ServiceLifecycle">Service Lifecycle</a>
  * <li><a href="#Permissions">Permissions</a>
  * <li><a href="#ProcessLifecycle">Process Lifecycle</a>
+ * <li><a href="#LocalServiceSample">Local Service Sample</a>
+ * <li><a href="#RemoteMessengerServiceSample">Remote Messenger Service Sample</a>
  * </ol>
  * 
  * <a name="ServiceLifecycle"></a>
@@ -166,6 +168,64 @@
  * (such as an {@link android.app.Activity}) can, of course, increase the
  * importance of the overall
  * process beyond just the importance of the service itself.
+ * 
+ * <a name="LocalServiceSample"></a>
+ * <h3>Local Service Sample</h3>
+ * 
+ * <p>One of the most common uses of a Service is as a secondary component
+ * running alongside other parts of an application, in the same process as
+ * the rest of the components.  All components of an .apk run in the same
+ * process unless explicitly stated otherwise, so this is a typical situation.
+ * 
+ * <p>When used in this way, by assuming the
+ * components are in the same process, you can greatly simplify the interaction
+ * between them: clients of the service can simply cast the IBinder they
+ * receive from it to a concrete class published by the service.
+ * 
+ * <p>An example of this use of a Service is shown here.  First is the Service
+ * itself, publishing a custom class when bound:
+ * 
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/LocalService.java
+ *      service}
+ * 
+ * <p>With that done, one can now write client code that directly accesses the
+ * running service, such as:
+ * 
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceActivities.java
+ *      bind}
+ * 
+ * <a name="RemoteMessengerServiceSample"></a>
+ * <h3>Remote Messenger Service Sample</h3>
+ * 
+ * <p>If you need to be able to write a Service that can perform complicated
+ * communication with clients in remote processes (beyond simply the use of
+ * {@link Context#startService(Intent) Context.startService} to send
+ * commands to it), then you can use the {@link android.os.Messenger} class
+ * instead of writing full AIDL files.
+ * 
+ * <p>An example of a Service that uses Messenger as its client interface
+ * is shown here.  First is the Service itself, publishing a Messenger to
+ * an internal Handler when bound:
+ * 
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/MessengerService.java
+ *      service}
+ * 
+ * <p>If we want to make this service run in a remote process (instead of the
+ * standard one for its .apk), we can use <code>android:process</code> in its
+ * manifest tag to specify one:
+ * 
+ * {@sample development/samples/ApiDemos/AndroidManifest.xml remote_service_declaration}
+ * 
+ * <p>Note that the name "remote" chosen here is arbitrary, and you can use
+ * other names if you want additional processes.  The ':' prefix appends the
+ * name to your package's standard process name.
+ * 
+ * <p>With that done, clients can now bind to the service and send messages
+ * to it.  Note that this allows clients to register with it to receive
+ * messages back as well:
+ * 
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/MessengerServiceActivities.java
+ *      bind}
  */
 public abstract class Service extends ContextWrapper implements ComponentCallbacks {
     private static final String TAG = "Service";
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index b792965..251813e 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -112,11 +112,9 @@
     /** Default priority when not set or when the device is unpaired */
     public static final int PRIORITY_UNDEFINED = -1;
 
-    /** The voice dialer 'works' but the user experience is poor. The voice
-     *  recognizer has trouble dealing with the 8kHz SCO signal, and it still
-     *  requires visual confirmation. Disable for cupcake.
-     */
-    public static final boolean DISABLE_BT_VOICE_DIALING = true;
+    /** Set this to true to prevent the bluetooth headset from
+     * activating the VoiceDialer. */
+    public static final boolean DISABLE_BT_VOICE_DIALING = false;
 
     /**
      * An interface for notifying BluetoothHeadset IPC clients when they have
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index d31b25b..1b0437c 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1815,11 +1815,18 @@
 
     /**
      * Broadcast Action:  A sticky broadcast indicating the phone was docked
-     * or undocked.  Includes the extra
-     * field {@link #EXTRA_DOCK_STATE}, containing the current dock state. It also
-     * includes the boolean extra field {@link #EXTRA_CAR_MODE_ENABLED}, indicating
-     * the state of the car mode.
-     * This is intended for monitoring the current dock state.
+     * or undocked.
+     *
+     * <p>The intent will have the following extra values:
+     * <ul>
+     *   <li><em>{@link #EXTRA_DOCK_STATE}</em> - the current dock
+     *       state, which depends on the state of the car mode.</li>
+     *   <li><em>{@link #EXTRA_PHYSICAL_DOCK_STATE}</em> - the physical dock
+     *       state.</li>
+     *   <li><em>{@link #EXTRA_CAR_MODE_ENABLED}</em> - a boolean indicating the
+     *       state of the car mode.</li>
+     * </ul>
+     * <p>This is intended for monitoring the current dock state.
      * To launch an activity from a dock state change, use {@link #CATEGORY_CAR_DOCK}
      * or {@link #CATEGORY_DESK_DOCK} instead.
      */
@@ -2154,6 +2161,16 @@
     public static final int EXTRA_DOCK_STATE_CAR = 2;
 
     /**
+     * Used as an int extra field in {@link android.content.Intent#ACTION_DOCK_EVENT}
+     * intents to request the physical dock state. Possible values are
+     * {@link android.content.Intent#EXTRA_DOCK_STATE_UNDOCKED},
+     * {@link android.content.Intent#EXTRA_DOCK_STATE_DESK}, or
+     * {@link android.content.Intent#EXTRA_DOCK_STATE_CAR}.
+     */
+    public static final String EXTRA_PHYSICAL_DOCK_STATE =
+            "android.intent.extra.PHYSICAL_DOCK_STATE";
+
+    /**
      * Used as an boolean extra field in {@link android.content.Intent#ACTION_DOCK_EVENT}
      * intents to indicate that the car mode is enabled or not.
      */
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 9ff2e25..317e5a9 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -115,6 +115,11 @@
     private static final long DEFAULT_MAX_SYNC_RETRY_TIME_IN_SECONDS = 60 * 60; // one hour
 
     /**
+     * How long to wait before retrying a sync that failed due to one already being in progress.
+     */
+    private static final int DELAY_RETRY_SYNC_IN_PROGRESS_IN_SECONDS = 10;
+
+    /**
      * An error notification is sent if sync of any of the providers has been failing for this long.
      */
     private static final long ERROR_NOTIFICATION_DELAY_MS = 1000 * 60 * 10; // 10 minutes
@@ -447,17 +452,6 @@
     }
 
     /**
-     * Returns whether or not sync is enabled.  Sync can be enabled by
-     * setting the system property "ro.config.sync" to the value "yes".
-     * This is normally done at boot time on builds that support sync.
-     * @return true if sync is enabled
-     */
-    private boolean isSyncEnabled() {
-        // Require the precise value "yes" to discourage accidental activation.
-        return "yes".equals(SystemProperties.get("ro.config.sync"));
-    }
-
-    /**
      * Initiate a sync. This can start a sync for all providers
      * (pass null to url, set onlyTicklable to false), only those
      * providers that are marked as ticklable (pass null to url,
@@ -488,13 +482,6 @@
             Bundle extras, long delay, boolean onlyThoseWithUnkownSyncableState) {
         boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
 
-        if (!isSyncEnabled()) {
-            if (isLoggable) {
-                Log.v(TAG, "not syncing because sync is disabled");
-            }
-            return;
-        }
-
         final boolean backgroundDataUsageAllowed = !mBootCompleted ||
                 getConnectivityManager().getBackgroundDataSetting();
 
@@ -825,6 +812,14 @@
                         + "it achieved some success");
             }
             scheduleSyncOperation(operation);
+        } else if (syncResult.syncAlreadyInProgress) {
+            if (isLoggable) {
+                Log.d(TAG, "retrying sync operation that failed because there was already a "
+                        + "sync in progress: " + operation);
+            }
+            scheduleSyncOperation(new SyncOperation(operation.account, operation.syncSource,
+                    operation.authority, operation.extras,
+                    DELAY_RETRY_SYNC_IN_PROGRESS_IN_SECONDS));
         } else if (syncResult.hasSoftError()) {
             if (isLoggable) {
                 Log.d(TAG, "retrying sync operation because it encountered a soft error: "
@@ -922,9 +917,7 @@
     protected void dump(FileDescriptor fd, PrintWriter pw) {
         StringBuilder sb = new StringBuilder();
         dumpSyncState(pw, sb);
-        if (isSyncEnabled()) {
-            dumpSyncHistory(pw, sb);
-        }
+        dumpSyncHistory(pw, sb);
 
         pw.println();
         pw.println("SyncAdapters:");
@@ -940,7 +933,6 @@
     }
 
     protected void dumpSyncState(PrintWriter pw, StringBuilder sb) {
-        pw.print("sync enabled: "); pw.println(isSyncEnabled());
         pw.print("data connected: "); pw.println(mDataConnectionIsConnected);
         pw.print("memory low: "); pw.println(mStorageIsLow);
 
@@ -1456,11 +1448,6 @@
                 boolean backgroundDataUsageAllowed) {
             Account[] accounts = mAccounts;
 
-            // Sync is disabled, drop this operation.
-            if (!isSyncEnabled()) {
-                return false;
-            }
-
             // skip the sync if the account of this operation no longer exists
             if (!ArrayUtils.contains(accounts, account)) {
                 return false;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index ff2ed3d..8576de2 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1153,7 +1153,9 @@
      *
      * @return Returns a ResolveInfo containing the final activity intent that
      *         was determined to be the best action.  Returns null if no
-     *         matching activity was found.
+     *         matching activity was found. If multiple matching activities are
+     *         found and there is no default set, returns a ResolveInfo
+     *         containing something else, such as the activity resolver.
      *
      * @see #MATCH_DEFAULT_ONLY
      * @see #GET_INTENT_FILTERS
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index aa5f128..6490b65 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -193,6 +193,11 @@
     public int uiMode;
 
     /**
+     * @hide Internal book-keeping.
+     */
+    public int seq;
+    
+    /**
      * Construct an invalid Configuration.  You must call {@link #setToDefaults}
      * for this object to be valid.  {@more}
      */
@@ -220,6 +225,7 @@
         orientation = o.orientation;
         screenLayout = o.screenLayout;
         uiMode = o.uiMode;
+        seq = o.seq;
     }
 
     public String toString() {
@@ -250,6 +256,10 @@
         sb.append(screenLayout);
         sb.append(" uiMode=");
         sb.append(uiMode);
+        if (seq != 0) {
+            sb.append(" seq=");
+            sb.append(seq);
+        }
         sb.append('}');
         return sb.toString();
     }
@@ -260,7 +270,7 @@
     public void setToDefaults() {
         fontScale = 1;
         mcc = mnc = 0;
-        locale = Locale.getDefault();
+        locale = null;
         userSetLocale = false;
         touchscreen = TOUCHSCREEN_UNDEFINED;
         keyboard = KEYBOARD_UNDEFINED;
@@ -271,6 +281,7 @@
         orientation = ORIENTATION_UNDEFINED;
         screenLayout = SCREENLAYOUT_SIZE_UNDEFINED;
         uiMode = UI_MODE_TYPE_NORMAL;
+        seq = 0;
     }
 
     /** {@hide} */
@@ -357,6 +368,10 @@
             uiMode = delta.uiMode;
         }
         
+        if (delta.seq != 0) {
+            seq = delta.seq;
+        }
+        
         return changed;
     }
 
@@ -456,6 +471,35 @@
     }
     
     /**
+     * @hide Return true if the sequence of 'other' is better than this.  Assumes
+     * that 'this' is your current sequence and 'other' is a new one you have
+     * received some how and want to compare with what you have.
+     */
+    public boolean isOtherSeqNewer(Configuration other) {
+        if (other == null) {
+            // Sanity check.
+            return false;
+        }
+        if (other.seq == 0) {
+            // If the other sequence is not specified, then we must assume
+            // it is newer since we don't know any better.
+            return true;
+        }
+        if (seq == 0) {
+            // If this sequence is not specified, then we also consider the
+            // other is better.  Yes we have a preference for other.  Sue us.
+            return true;
+        }
+        int diff = other.seq - seq;
+        if (diff > 0x10000) {
+            // If there has been a sufficiently large jump, assume the
+            // sequence has wrapped around.
+            return false;
+        }
+        return diff > 0;
+    }
+    
+    /**
      * Parcelable methods
      */
     public int describeContents() {
@@ -488,6 +532,7 @@
         dest.writeInt(orientation);
         dest.writeInt(screenLayout);
         dest.writeInt(uiMode);
+        dest.writeInt(seq);
     }
 
     public static final Parcelable.Creator<Configuration> CREATOR
@@ -522,6 +567,7 @@
         orientation = source.readInt();
         screenLayout = source.readInt();
         uiMode = source.readInt();
+        seq = source.readInt();
     }
 
     public int compareTo(Configuration that) {
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index ae8e297..a5e39d4 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -39,6 +39,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.ref.WeakReference;
+import java.util.Locale;
 
 /**
  * Class for accessing an application's resources.  This sits on top of the
@@ -1259,6 +1260,9 @@
             if (config != null) {
                 configChanges = mConfiguration.updateFrom(config);
             }
+            if (mConfiguration.locale == null) {
+                mConfiguration.locale = Locale.getDefault();
+            }
             if (metrics != null) {
                 mMetrics.setTo(metrics);
                 mMetrics.updateMetrics(mCompatibilityInfo,
diff --git a/core/java/android/database/sqlite/SQLiteClosable.java b/core/java/android/database/sqlite/SQLiteClosable.java
index 7776520..e589f34 100644
--- a/core/java/android/database/sqlite/SQLiteClosable.java
+++ b/core/java/android/database/sqlite/SQLiteClosable.java
@@ -16,6 +16,8 @@
 
 package android.database.sqlite;
 
+import android.database.CursorWindow;
+
 /**
  * An object create from a SQLiteDatabase that can be closed.
  */
@@ -29,9 +31,9 @@
         synchronized(mLock) {
             if (mReferenceCount <= 0) {
                 throw new IllegalStateException(
-                        "attempt to acquire a reference on an already-closed SQLiteClosable obj.");
+                        "attempt to acquire a reference on an already-closed " + getObjInfo());
             }
-            mReferenceCount++;     
+            mReferenceCount++;
         }
     }
     
@@ -52,4 +54,24 @@
             }
         }        
     }
+
+    private String getObjInfo() {
+        StringBuilder buff = new StringBuilder();
+        buff.append(this.getClass().getName());
+        buff.append(" Obj");
+        buff.append(" (");
+        if (this instanceof SQLiteDatabase) {
+            buff.append("database = ");
+            buff.append(((SQLiteDatabase)this).getPath());
+        } else if (this instanceof SQLiteProgram || this instanceof SQLiteStatement ||
+                this instanceof SQLiteQuery) {
+            buff.append("mSql = ");
+            buff.append(((SQLiteProgram)this).mSql);
+        } else if (this instanceof CursorWindow) {
+            buff.append("mStartPos = ");
+            buff.append(((CursorWindow)this).getStartPosition());
+        }
+        buff.append(") ");
+        return buff.toString();
+    }
 }
diff --git a/core/java/android/database/sqlite/SQLiteCompiledSql.java b/core/java/android/database/sqlite/SQLiteCompiledSql.java
index 79527b4..eb85822 100644
--- a/core/java/android/database/sqlite/SQLiteCompiledSql.java
+++ b/core/java/android/database/sqlite/SQLiteCompiledSql.java
@@ -44,6 +44,9 @@
      */
     /* package */ int nStatement = 0;
 
+    /** when in cache and is in use, this member is set */
+    private boolean mInUse = false;
+
     /* package */ SQLiteCompiledSql(SQLiteDatabase db, String sql) {
         mDatabase = db;
         this.nHandle = db.mNativeHandle;
@@ -92,6 +95,18 @@
         }
     }
 
+    /* package */ synchronized boolean isInUse() {
+        return mInUse;
+    }
+
+    /* package */ synchronized void acquire() {
+        mInUse = true;
+    }
+
+    /* package */ synchronized void release() {
+        mInUse = false;
+    }
+
     /**
      * Make sure that the native resource is cleaned up.
      */
diff --git a/core/java/android/database/sqlite/SQLiteProgram.java b/core/java/android/database/sqlite/SQLiteProgram.java
index 2d0aa39..2bb2f5d 100644
--- a/core/java/android/database/sqlite/SQLiteProgram.java
+++ b/core/java/android/database/sqlite/SQLiteProgram.java
@@ -58,32 +58,51 @@
 
             // add it to the cache of compiled-sqls
             db.addToCompiledQueries(sql, mCompiledSql);
+            mCompiledSql.acquire();
+        } else {
+            // it is already in compiled-sql cache.
+            if (mCompiledSql.isInUse()) {
+                // but the CompiledSql in cache is in use by some other SQLiteProgram object.
+                // we can't have two different SQLiteProgam objects can't share the same
+                // CompiledSql object. create a new one.
+                // finalize it when I am done with it in "this" object.
+                mCompiledSql = new SQLiteCompiledSql(db, sql);
+            } else {
+                // the CompiledSql in cache is NOT in use by any other SQLiteProgram object.
+                // it is safe to give it to this SQLIteProgram Object.
+                mCompiledSql.acquire();
+            }
         }
         nStatement = mCompiledSql.nStatement;
     }
 
     @Override
     protected void onAllReferencesReleased() {
-        releaseCompiledSqlIfInCache();
+        releaseCompiledSqlIfNotInCache();
         mDatabase.releaseReference();
         mDatabase.removeSQLiteClosable(this);
     }
 
     @Override
     protected void onAllReferencesReleasedFromContainer() {
-        releaseCompiledSqlIfInCache();
+        releaseCompiledSqlIfNotInCache();
         mDatabase.releaseReference();
     }
 
-    private void releaseCompiledSqlIfInCache() {
+    private void releaseCompiledSqlIfNotInCache() {
         if (mCompiledSql == null) {
             return;
         }
         synchronized(mDatabase.mCompiledQueries) {
             if (!mDatabase.mCompiledQueries.containsValue(mCompiledSql)) {
+                // it is NOT in compiled-sql cache. i.e., responsibility of
+                // release this statement is on me.
                 mCompiledSql.releaseSqlStatement();
                 mCompiledSql = null; // so that GC doesn't call finalize() on it
                 nStatement = 0;
+            } else {
+                // it is in compiled-sql cache. reset its CompiledSql#mInUse flag
+                mCompiledSql.release();
             }
         }
     }
diff --git a/core/java/android/gesture/Learner.java b/core/java/android/gesture/Learner.java
index 60997e0..a105652 100755
--- a/core/java/android/gesture/Learner.java
+++ b/core/java/android/gesture/Learner.java
@@ -72,7 +72,8 @@
         for (int i = 0; i < count; i++) {
             final Instance instance = instances.get(i);
             // the label can be null, as specified in Instance
-            if ((instance.label == null && name == null) || instance.label.equals(name)) {
+            if ((instance.label == null && name == null)
+                    || (instance.label != null && instance.label.equals(name))) {
                 toDelete.add(instance);
             }
         }
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index c0bff66..6dba94d 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -26,7 +26,7 @@
 import android.util.Log;
 import android.view.Surface;
 import android.view.SurfaceHolder;
-import android.graphics.PixelFormat;
+import android.graphics.ImageFormat;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -192,7 +192,7 @@
          * The callback that delivers the preview frames.
          *
          * @param data The contents of the preview frame in the format defined
-         *  by {@link android.graphics.PixelFormat}, which can be queried
+         *  by {@link android.graphics.ImageFormat}, which can be queried
          *  with {@link android.hardware.Camera.Parameters#getPreviewFormat()}.
          *  If {@link android.hardware.Camera.Parameters#setPreviewFormat(int)}
          *             is never called, the default will be the YCbCr_420_SP
@@ -276,7 +276,7 @@
      * Adds a pre-allocated buffer to the callback buffer queue.
      * Preview width and height can be determined from getPreviewSize, and bitsPerPixel can be
      * found from from  {@link android.hardware.Camera.Parameters#getPreviewFormat()} and
-     * {@link android.graphics.PixelFormat#getPixelFormatInfo(int, PixelFormat)}
+     * {@link android.graphics.ImageFormat#getBitsPerPixel(int)}
      *
      * Alternatively, a buffer from a previous callback may be passed in or used
      * to determine the size of new preview frame buffers.
@@ -1086,15 +1086,15 @@
         /**
          * Sets the image format for preview pictures.
          * <p>If this is never called, the default format will be
-         * {@link android.graphics.PixelFormat#YCbCr_420_SP}, which
+         * {@link android.graphics.ImageFormat#NV21}, which
          * uses the NV21 encoding format.</p>
          *
          * @param pixel_format the desired preview picture format, defined
-         *   by one of the {@link android.graphics.PixelFormat} constants.
-         *   (E.g., <var>PixelFormat.YCbCr_420_SP</var> (default),
-         *                      <var>PixelFormat.RGB_565</var>, or
-         *                      <var>PixelFormat.JPEG</var>)
-         * @see android.graphics.PixelFormat
+         *   by one of the {@link android.graphics.ImageFormat} constants.
+         *   (E.g., <var>ImageFormat.NV21</var> (default),
+         *                      <var>ImageFormat.RGB_565</var>, or
+         *                      <var>ImageFormat.JPEG</var>)
+         * @see android.graphics.ImageFormat
          */
         public void setPreviewFormat(int pixel_format) {
             String s = cameraFormatForPixelFormat(pixel_format);
@@ -1110,7 +1110,7 @@
          * Returns the image format for preview pictures got from
          * {@link PreviewCallback}.
          *
-         * @return the {@link android.graphics.PixelFormat} int representing
+         * @return the {@link android.graphics.ImageFormat} int representing
          *         the preview picture format.
          */
         public int getPreviewFormat() {
@@ -1128,7 +1128,7 @@
             ArrayList<Integer> formats = new ArrayList<Integer>();
             for (String s : split(str)) {
                 int f = pixelFormatForCameraFormat(s);
-                if (f == PixelFormat.UNKNOWN) continue;
+                if (f == ImageFormat.UNKNOWN) continue;
                 formats.add(f);
             }
             return formats;
@@ -1171,10 +1171,10 @@
          * Sets the image format for pictures.
          *
          * @param pixel_format the desired picture format
-         *                     (<var>PixelFormat.YCbCr_420_SP (NV21)</var>,
-         *                      <var>PixelFormat.RGB_565</var>, or
-         *                      <var>PixelFormat.JPEG</var>)
-         * @see android.graphics.PixelFormat
+         *                     (<var>ImageFormat.NV21</var>,
+         *                      <var>ImageFormat.RGB_565</var>, or
+         *                      <var>ImageFormat.JPEG</var>)
+         * @see android.graphics.ImageFormat
          */
         public void setPictureFormat(int pixel_format) {
             String s = cameraFormatForPixelFormat(pixel_format);
@@ -1189,7 +1189,7 @@
         /**
          * Returns the image format for pictures.
          *
-         * @return the PixelFormat int representing the picture format
+         * @return the ImageFormat int representing the picture format
          */
         public int getPictureFormat() {
             return pixelFormatForCameraFormat(get(KEY_PICTURE_FORMAT));
@@ -1198,7 +1198,7 @@
         /**
          * Gets the supported picture formats.
          *
-         * @return a List of Integer objects (values are PixelFormat.XXX). This
+         * @return a List of Integer objects (values are ImageFormat.XXX). This
          *         method will always return a list with at least one element.
          */
         public List<Integer> getSupportedPictureFormats() {
@@ -1206,7 +1206,7 @@
             ArrayList<Integer> formats = new ArrayList<Integer>();
             for (String s : split(str)) {
                 int f = pixelFormatForCameraFormat(s);
-                if (f == PixelFormat.UNKNOWN) continue;
+                if (f == ImageFormat.UNKNOWN) continue;
                 formats.add(f);
             }
             return formats;
@@ -1214,35 +1214,35 @@
 
         private String cameraFormatForPixelFormat(int pixel_format) {
             switch(pixel_format) {
-            case PixelFormat.YCbCr_422_SP: return PIXEL_FORMAT_YUV422SP;
-            case PixelFormat.YCbCr_420_SP: return PIXEL_FORMAT_YUV420SP;
-            case PixelFormat.YCbCr_422_I:  return PIXEL_FORMAT_YUV422I;
-            case PixelFormat.RGB_565:      return PIXEL_FORMAT_RGB565;
-            case PixelFormat.JPEG:         return PIXEL_FORMAT_JPEG;
-            default:                       return null;
+            case ImageFormat.NV16:      return PIXEL_FORMAT_YUV422SP;
+            case ImageFormat.NV21:      return PIXEL_FORMAT_YUV420SP;
+            case ImageFormat.YUY2:      return PIXEL_FORMAT_YUV422I;
+            case ImageFormat.RGB_565:   return PIXEL_FORMAT_RGB565;
+            case ImageFormat.JPEG:      return PIXEL_FORMAT_JPEG;
+            default:                    return null;
             }
         }
 
         private int pixelFormatForCameraFormat(String format) {
             if (format == null)
-                return PixelFormat.UNKNOWN;
+                return ImageFormat.UNKNOWN;
 
             if (format.equals(PIXEL_FORMAT_YUV422SP))
-                return PixelFormat.YCbCr_422_SP;
+                return ImageFormat.NV16;
 
             if (format.equals(PIXEL_FORMAT_YUV420SP))
-                return PixelFormat.YCbCr_420_SP;
+                return ImageFormat.NV21;
 
             if (format.equals(PIXEL_FORMAT_YUV422I))
-                return PixelFormat.YCbCr_422_I;
+                return ImageFormat.YUY2;
 
             if (format.equals(PIXEL_FORMAT_RGB565))
-                return PixelFormat.RGB_565;
+                return ImageFormat.RGB_565;
 
             if (format.equals(PIXEL_FORMAT_JPEG))
-                return PixelFormat.JPEG;
+                return ImageFormat.JPEG;
 
-            return PixelFormat.UNKNOWN;
+            return ImageFormat.UNKNOWN;
         }
 
         /**
diff --git a/core/java/android/os/HandlerThread.java b/core/java/android/os/HandlerThread.java
index 65301e4..911439a 100644
--- a/core/java/android/os/HandlerThread.java
+++ b/core/java/android/os/HandlerThread.java
@@ -53,9 +53,9 @@
         Looper.prepare();
         synchronized (this) {
             mLooper = Looper.myLooper();
-            Process.setThreadPriority(mPriority);
             notifyAll();
         }
+        Process.setThreadPriority(mPriority);
         onLooperPrepared();
         Looper.loop();
         mTid = -1;
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index f48f45f..92041d8 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -148,4 +148,18 @@
      */
     void detachPppd(String tty);
 
+    /**
+     * Turn on USB RNDIS support - this will turn off thinks like adb/mass-storage
+     */
+    void startUsbRNDIS();
+
+    /**
+     * Turn off USB RNDIS support
+     */
+    void stopUsbRNDIS();
+
+    /**
+     * Check the status of USB RNDIS support
+     */
+    boolean isUsbRNDISStarted();
 }
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
index 4130109..476da1d 100644
--- a/core/java/android/os/Message.java
+++ b/core/java/android/os/Message.java
@@ -40,20 +40,36 @@
      */
     public int what;
 
-    // Use these fields instead of using the class's Bundle if you can. 
-    /** arg1 and arg2 are lower-cost alternatives to using {@link #setData(Bundle) setData()}
-    if you only need to store a few integer values. */
+    /**
+     * arg1 and arg2 are lower-cost alternatives to using
+     * {@link #setData(Bundle) setData()} if you only need to store a
+     * few integer values.
+     */
     public int arg1; 
 
-    /** arg1 and arg2 are lower-cost alternatives to using {@link #setData(Bundle) setData()}
-    if you only need to store a few integer values.*/ 
+    /**
+     * arg1 and arg2 are lower-cost alternatives to using
+     * {@link #setData(Bundle) setData()} if you only need to store a
+     * few integer values.
+     */
     public int arg2;
 
-    /** An arbitrary object to send to the recipient.  This must be null when
-     * sending messages across processes. */
+    /**
+     * An arbitrary object to send to the recipient.  When using
+     * {@link Messenger} to send the message across processes this can only
+     * be non-null if it contains a Parcelable of a framework class (not one
+     * implemented by the application).   For other data transfer use
+     * {@link #setData}.
+     * 
+     * <p>Note that Parcelable objects here are not supported prior to
+     * the {@link android.os.Build.VERSION_CODES#FROYO} release.
+     */
     public Object obj;
 
-    /** Optional Messenger where replies to this message can be sent.
+    /**
+     * Optional Messenger where replies to this message can be sent.  The
+     * semantics of exactly how this is used are up to the sender and
+     * receiver.
      */
     public Messenger replyTo;
     
@@ -278,14 +294,22 @@
      * the <em>target</em> {@link Handler} that is receiving this Message to
      * dispatch it.  If
      * not set, the message will be dispatched to the receiving Handler's
-     * {@link Handler#handleMessage(Message Handler.handleMessage())}. */
+     * {@link Handler#handleMessage(Message Handler.handleMessage())}.
+     */
     public Runnable getCallback() {
         return callback;
     }
     
     /** 
      * Obtains a Bundle of arbitrary data associated with this
-     * event, lazily creating it if necessary. Set this value by calling {@link #setData(Bundle)}.
+     * event, lazily creating it if necessary. Set this value by calling
+     * {@link #setData(Bundle)}.  Note that when transferring data across
+     * processes via {@link Messenger}, you will need to set your ClassLoader
+     * on the Bundle via {@link Bundle#setClassLoader(ClassLoader)
+     * Bundle.setClassLoader()} so that it can instantiate your objects when
+     * you retrieve them.
+     * @see #peekData()
+     * @see #setData(Bundle)
      */
     public Bundle getData() {
         if (data == null) {
@@ -297,14 +321,21 @@
 
     /** 
      * Like getData(), but does not lazily create the Bundle.  A null
-     * is returned if the Bundle does not already exist.
+     * is returned if the Bundle does not already exist.  See
+     * {@link #getData} for further information on this.
+     * @see #getData()
+     * @see #setData(Bundle)
      */
     public Bundle peekData() {
         return data;
     }
 
-    /** Sets a Bundle of arbitrary data values. Use arg1 and arg1 members 
-     * as a lower cost way to send a few simple integer values, if you can. */
+    /**
+     * Sets a Bundle of arbitrary data values. Use arg1 and arg1 members 
+     * as a lower cost way to send a few simple integer values, if you can.
+     * @see #getData() 
+     * @see #peekData()
+     */
     public void setData(Bundle data) {
         this.data = data;
     }
@@ -381,13 +412,25 @@
     }
 
     public void writeToParcel(Parcel dest, int flags) {
-        if (obj != null || callback != null) {
+        if (callback != null) {
             throw new RuntimeException(
-                "Can't marshal objects across processes.");
+                "Can't marshal callbacks across processes.");
         }
         dest.writeInt(what);
         dest.writeInt(arg1);
         dest.writeInt(arg2);
+        if (obj != null) {
+            try {
+                Parcelable p = (Parcelable)obj;
+                dest.writeInt(1);
+                dest.writeParcelable(p, flags);
+            } catch (ClassCastException e) {
+                throw new RuntimeException(
+                    "Can't marshal non-Parcelable objects across processes.");
+            }
+        } else {
+            dest.writeInt(0);
+        }
         dest.writeLong(when);
         dest.writeBundle(data);
         Messenger.writeMessengerOrNullToParcel(replyTo, dest);
@@ -397,6 +440,9 @@
         what = source.readInt();
         arg1 = source.readInt();
         arg2 = source.readInt();
+        if (source.readInt() != 0) {
+            obj = source.readParcelable(getClass().getClassLoader());
+        }
         when = source.readLong();
         data = source.readBundle();
         replyTo = Messenger.readMessengerOrNullFromParcel(source);
diff --git a/core/java/android/os/storage/IMountService.aidl b/core/java/android/os/storage/IMountService.aidl
index 816baf3..79a6cfe 100644
--- a/core/java/android/os/storage/IMountService.aidl
+++ b/core/java/android/os/storage/IMountService.aidl
@@ -63,7 +63,7 @@
      * Safely unmount external storage at given mount point.
      * Returns an int consistent with MountServiceResultCode
      */
-    int unmountVolume(String mountPoint);
+    int unmountVolume(String mountPoint, boolean force);
 
     /**
      * Format external storage given a mount point.
@@ -100,7 +100,7 @@
      * NOTE: Ensure all references are released prior to deleting.
      * Returns an int consistent with MountServiceResultCode
      */
-    int destroySecureContainer(String id);
+    int destroySecureContainer(String id, boolean force);
 
     /*
      * Mount a secure container with the specified key and owner UID.
@@ -112,7 +112,7 @@
      * Unount a secure container.
      * Returns an int consistent with MountServiceResultCode
      */
-    int unmountSecureContainer(String id);
+    int unmountSecureContainer(String id, boolean force);
 
     /*
      * Returns true if the specified container is mounted
diff --git a/core/java/android/os/storage/StorageResultCode.java b/core/java/android/os/storage/StorageResultCode.java
index 249bacf..07d95df 100644
--- a/core/java/android/os/storage/StorageResultCode.java
+++ b/core/java/android/os/storage/StorageResultCode.java
@@ -64,4 +64,10 @@
      */
     public static final int OperationFailedStorageMounted     = -6;
 
+    /**
+     * Operation failed: Storage is busy.
+     * @see android.os.storage.StorageManager
+     */
+    public static final int OperationFailedStorageBusy        = -7;
+
 }
diff --git a/core/java/android/pim/RecurrenceSet.java b/core/java/android/pim/RecurrenceSet.java
index bd7924a..5d09fb5 100644
--- a/core/java/android/pim/RecurrenceSet.java
+++ b/core/java/android/pim/RecurrenceSet.java
@@ -48,7 +48,8 @@
      * events table in the CalendarProvider.
      * @param values The values retrieved from the Events table.
      */
-    public RecurrenceSet(ContentValues values) {
+    public RecurrenceSet(ContentValues values)
+            throws EventRecurrence.InvalidFormatException {
         String rruleStr = values.getAsString(Calendar.Events.RRULE);
         String rdateStr = values.getAsString(Calendar.Events.RDATE);
         String exruleStr = values.getAsString(Calendar.Events.EXRULE);
@@ -65,7 +66,8 @@
      * @param cursor The cursor containing the RRULE, RDATE, EXRULE, and EXDATE
      * columns.
      */
-    public RecurrenceSet(Cursor cursor) {
+    public RecurrenceSet(Cursor cursor)
+            throws EventRecurrence.InvalidFormatException {
         int rruleColumn = cursor.getColumnIndex(Calendar.Events.RRULE);
         int rdateColumn = cursor.getColumnIndex(Calendar.Events.RDATE);
         int exruleColumn = cursor.getColumnIndex(Calendar.Events.EXRULE);
@@ -78,12 +80,14 @@
     }
 
     public RecurrenceSet(String rruleStr, String rdateStr,
-                  String exruleStr, String exdateStr) {
+                  String exruleStr, String exdateStr)
+            throws EventRecurrence.InvalidFormatException {
         init(rruleStr, rdateStr, exruleStr, exdateStr);
     }
 
     private void init(String rruleStr, String rdateStr,
-                      String exruleStr, String exdateStr) {
+                      String exruleStr, String exdateStr)
+            throws EventRecurrence.InvalidFormatException {
         if (!TextUtils.isEmpty(rruleStr) || !TextUtils.isEmpty(rdateStr)) {
 
             if (!TextUtils.isEmpty(rruleStr)) {
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index eb48a0c..52de64c 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -28,6 +28,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -226,7 +227,7 @@
             
             @Override
             public void resized(int w, int h, Rect coveredInsets,
-                    Rect visibleInsets, boolean reportDraw) {
+                    Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
                 Message msg = mCaller.obtainMessageI(MSG_WINDOW_RESIZED,
                         reportDraw ? 1 : 0);
                 mCaller.sendMessage(msg);
diff --git a/core/java/android/speech/RecognitionManager.java b/core/java/android/speech/RecognitionManager.java
index 7f55ad6..16b1f89 100644
--- a/core/java/android/speech/RecognitionManager.java
+++ b/core/java/android/speech/RecognitionManager.java
@@ -98,6 +98,9 @@
 
     /** Context with which the manager was created */
     private final Context mContext;
+    
+    /** Component to direct service intent to */
+    private final ComponentName mServiceComponent;
 
     /** Handler that will execute the main tasks */
     private Handler mHandler = new Handler() {
@@ -133,8 +136,9 @@
      * The right way to create a {@code RecognitionManager} is by using
      * {@link #createRecognitionManager} static factory method
      */
-    private RecognitionManager(final Context context) {
+    private RecognitionManager(final Context context, final ComponentName serviceComponent) {
         mContext = context;
+        mServiceComponent = serviceComponent;
     }
 
     /**
@@ -184,11 +188,31 @@
      * @return a new {@code RecognitionManager}
      */
     public static RecognitionManager createRecognitionManager(final Context context) {
+        return createRecognitionManager(context, null);
+    }
+
+    /**
+     * Factory method to create a new {@code RecognitionManager}, please note that
+     * {@link #setRecognitionListener(RecognitionListener)} must be called before dispatching any
+     * command to the created {@code RecognitionManager}.
+     * 
+     * Use this version of the method to specify a specific service to direct this
+     * {@link RecognitionManager} to. Normally you would not use this; use
+     * {@link #createRecognitionManager(Context)} instead to use the system default
+     * recognition service.
+     * 
+     * @param context in which to create {@code RecognitionManager}
+     * @param serviceComponent the {@link ComponentName} of a specific service to direct this
+     *        {@code RecognitionManager} to
+     * @return a new {@code RecognitionManager}
+     */
+    public static RecognitionManager createRecognitionManager(final Context context,
+            final ComponentName serviceComponent) {
         if (context == null) {
             throw new IllegalArgumentException("Context cannot be null)");
         }
         checkIsCalledFromMainThread();
-        return new RecognitionManager(context);
+        return new RecognitionManager(context, serviceComponent);
     }
 
     /**
@@ -222,17 +246,22 @@
             mConnection = new Connection();
             
             Intent serviceIntent = new Intent(RecognitionService.SERVICE_INTERFACE);
-            String serviceComponent = Settings.Secure.getString(mContext.getContentResolver(),
-                    Settings.Secure.VOICE_RECOGNITION_SERVICE);
             
-            if (TextUtils.isEmpty(serviceComponent)) {
-                Log.e(TAG, "no selected voice recognition service");
-                mListener.onError(ERROR_CLIENT);
-                return;
+            if (mServiceComponent == null) {
+                String serviceComponent = Settings.Secure.getString(mContext.getContentResolver(),
+                        Settings.Secure.VOICE_RECOGNITION_SERVICE);
+                
+                if (TextUtils.isEmpty(serviceComponent)) {
+                    Log.e(TAG, "no selected voice recognition service");
+                    mListener.onError(ERROR_CLIENT);
+                    return;
+                }
+                
+                serviceIntent.setComponent(ComponentName.unflattenFromString(serviceComponent));                
+            } else {
+                serviceIntent.setComponent(mServiceComponent);
             }
             
-            serviceIntent.setComponent(ComponentName.unflattenFromString(serviceComponent));
-            
             if (!mContext.bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE)) {
                 Log.e(TAG, "bind to recognition service failed");
                 mConnection = null;
diff --git a/core/java/android/speech/RecognizerIntent.java b/core/java/android/speech/RecognizerIntent.java
index 5f651e1..7c15cec 100644
--- a/core/java/android/speech/RecognizerIntent.java
+++ b/core/java/android/speech/RecognizerIntent.java
@@ -16,9 +16,17 @@
 
 package android.speech;
 
+import java.util.ArrayList;
+
 import android.app.Activity;
 import android.content.ActivityNotFoundException;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
 
 /**
  * Constants for supporting speech recognition through starting an {@link Intent}
@@ -208,4 +216,92 @@
      * an activity result. In a PendingIntent, the lack of this extra indicates failure.
      */
     public static final String EXTRA_RESULTS = "android.speech.extra.RESULTS";
+    
+    /**
+     * Returns the broadcast intent to fire with
+     * {@link Context#sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, Bundle)}
+     * to receive details from the package that implements voice search.
+     * <p>
+     * This is based on the value specified by the voice search {@link Activity} in
+     * {@link #DETAILS_META_DATA}, and if this is not specified, will return null. Also if there
+     * is no chosen default to resolve for {@link #ACTION_WEB_SEARCH}, this will return null.
+     * <p>
+     * If an intent is returned and is fired, a {@link Bundle} of extras will be returned to the
+     * provided result receiver, and should ideally contain values for
+     * {@link #EXTRA_LANGUAGE_PREFERENCE} and {@link #EXTRA_SUPPORTED_LANGUAGES}.
+     * <p>
+     * (Whether these are actually provided is up to the particular implementation. It is
+     * recommended that {@link Activity}s implementing {@link #ACTION_WEB_SEARCH} provide this
+     * information, but it is not required.)
+     * 
+     * @param context a context object
+     * @return the broadcast intent to fire or null if not available
+     */
+    public static final Intent getVoiceDetailsIntent(Context context) {
+        Intent voiceSearchIntent = new Intent(ACTION_WEB_SEARCH);
+        ResolveInfo ri = context.getPackageManager().resolveActivity(
+                voiceSearchIntent, PackageManager.GET_META_DATA);
+        if (ri == null || ri.activityInfo == null || ri.activityInfo.metaData == null) return null;
+        
+        String className = ri.activityInfo.metaData.getString(DETAILS_META_DATA);
+        if (className == null) return null;
+        
+        Intent detailsIntent = new Intent(ACTION_GET_LANGUAGE_DETAILS);
+        detailsIntent.setComponent(new ComponentName(ri.activityInfo.packageName, className));
+        return detailsIntent;
+    }
+    
+    /**
+     * Meta-data name under which an {@link Activity} implementing {@link #ACTION_WEB_SEARCH} can
+     * use to expose the class name of a {@link BroadcastReceiver} which can respond to request for
+     * more information, from any of the broadcast intents specified in this class.
+     * <p>
+     * Broadcast intents can be directed to the class name specified in the meta-data by creating
+     * an {@link Intent}, setting the component with
+     * {@link Intent#setComponent(android.content.ComponentName)}, and using
+     * {@link Context#sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, android.os.Bundle)}
+     * with another {@link BroadcastReceiver} which can receive the results.
+     * <p>
+     * The {@link #getVoiceDetailsIntent(Context)} method is provided as a convenience to create
+     * a broadcast intent based on the value of this meta-data, if available.
+     * <p>
+     * This is optional and not all {@link Activity}s which implement {@link #ACTION_WEB_SEARCH}
+     * are required to implement this. Thus retrieving this meta-data may be null.
+     */
+    public static final String DETAILS_META_DATA = "android.speech.DETAILS";
+    
+    /**
+     * A broadcast intent which can be fired to the {@link BroadcastReceiver} component specified
+     * in the meta-data defined in the {@link #DETAILS_META_DATA} meta-data of an
+     * {@link Activity} satisfying {@link #ACTION_WEB_SEARCH}.
+     * <p>
+     * When fired with
+     * {@link Context#sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, android.os.Bundle)},
+     * a {@link Bundle} of extras will be returned to the provided result receiver, and should
+     * ideally contain values for {@link #EXTRA_LANGUAGE_PREFERENCE} and
+     * {@link #EXTRA_SUPPORTED_LANGUAGES}.
+     * <p>
+     * (Whether these are actually provided is up to the particular implementation. It is
+     * recommended that {@link Activity}s implementing {@link #ACTION_WEB_SEARCH} provide this
+     * information, but it is not required.)
+     */
+    public static final String ACTION_GET_LANGUAGE_DETAILS =
+            "android.speech.action.GET_LANGUAGE_DETAILS";
+    
+    /**
+     * The key to the extra in the {@link Bundle} returned by {@link #ACTION_GET_LANGUAGE_DETAILS}
+     * which is a {@link String} that represents the current language preference this user has
+     * specified - a locale string like "en-US".
+     */
+    public static final String EXTRA_LANGUAGE_PREFERENCE =
+            "android.speech.extra.LANGUAGE_PREFERENCE";
+    
+    /**
+     * The key to the extra in the {@link Bundle} returned by {@link #ACTION_GET_LANGUAGE_DETAILS}
+     * which is an {@link ArrayList} of {@link String}s that represents the languages supported by
+     * this implementation of voice recognition - a list of strings like "en-US", "cmn-Hans-CN",
+     * etc.
+     */
+    public static final String EXTRA_SUPPORTED_LANGUAGES =
+            "android.speech.extra.SUPPORTED_LANGUAGES";
 }
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 71302cb..3b09808 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -17,6 +17,7 @@
 
 package android.view;
 
+import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
@@ -44,7 +45,7 @@
     void executeCommand(String command, String parameters, in ParcelFileDescriptor descriptor);
 
     void resized(int w, int h, in Rect coveredInsets, in Rect visibleInsets,
-            boolean reportDraw);
+            boolean reportDraw, in Configuration newConfig);
     void dispatchKey(in KeyEvent event);
     void dispatchPointer(in MotionEvent event, long eventTime, boolean callWhenDone);
     void dispatchTrackball(in MotionEvent event, long eventTime, boolean callWhenDone);
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 0ebe360..9b7b2f4 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -64,8 +64,6 @@
     void addAppToken(int addPos, IApplicationToken token,
             int groupId, int requestedOrientation, boolean fullscreen);
     void setAppGroupId(IBinder token, int groupId);
-    Configuration updateOrientationFromAppTokens(in Configuration currentConfig,
-            IBinder freezeThisOneIfNeeded);
     void setAppOrientation(IApplicationToken token, int requestedOrientation);
     int getAppOrientation(IApplicationToken token);
     void setFocusedApp(IBinder token, boolean moveFocusNow);
@@ -85,6 +83,13 @@
     void moveAppTokensToTop(in List<IBinder> tokens);
     void moveAppTokensToBottom(in List<IBinder> tokens);
 
+    // Re-evaluate the current orientation from the caller's state.
+    // If there is a change, the new Configuration is returned and the
+    // caller must call setNewConfiguration() sometime later.
+    Configuration updateOrientationFromAppTokens(in Configuration currentConfig,
+            IBinder freezeThisOneIfNeeded);
+    void setNewConfiguration(in Configuration config);
+    
     // these require DISABLE_KEYGUARD permission
     void disableKeyguard(IBinder token, String tag);
     void reenableKeyguard(IBinder token);
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index ca5e1de..d7f2539 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -19,6 +19,7 @@
 import com.android.internal.view.BaseIWindow;
 
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.CompatibilityInfo.Translator;
 import android.graphics.Canvas;
@@ -504,7 +505,7 @@
         }
 
         public void resized(int w, int h, Rect coveredInsets,
-                Rect visibleInsets, boolean reportDraw) {
+                Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
             SurfaceView surfaceView = mSurfaceView.get();
             if (surfaceView != null) {
                 if (localLOGV) Log.v(
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index e5db120..2eb633f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -20,6 +20,7 @@
 import com.android.internal.view.menu.MenuBuilder;
 
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
@@ -3050,6 +3051,7 @@
      *
      * @param enabled True if this view is enabled, false otherwise.
      */
+    @RemotableViewMethod
     public void setEnabled(boolean enabled) {
         if (enabled == isEnabled()) return;
 
@@ -3932,6 +3934,32 @@
     }
 
     /**
+     * Dispatch a notification about a resource configuration change down
+     * the view hierarchy.
+     * ViewGroups should override to route to their children.
+     *
+     * @param newConfig The new resource configuration.
+     *
+     * @see #onConfigurationChanged
+     */
+    public void dispatchConfigurationChanged(Configuration newConfig) {
+        onConfigurationChanged(newConfig);
+    }
+
+    /**
+     * Called when the current configuration of the resources being used
+     * by the application have changed.  You can use this to decide when
+     * to reload resources that can changed based on orientation and other
+     * configuration characterstics.  You only need to use this if you are
+     * not relying on the normal {@link android.app.Activity} mechanism of
+     * recreating the activity instance upon a configuration change.
+     *
+     * @param newConfig The new resource configuration.
+     */
+    protected void onConfigurationChanged(Configuration newConfig) {
+    }
+
+    /**
      * Private function to aggregate all per-view attributes in to the view
      * root.
      */
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 2ed623d..0663215 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -19,6 +19,7 @@
 import com.android.internal.R;
 
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -722,6 +723,19 @@
     /**
      * {@inheritDoc}
      */
+    @Override
+    public void dispatchConfigurationChanged(Configuration newConfig) {
+        super.dispatchConfigurationChanged(newConfig);
+        final int count = mChildrenCount;
+        final View[] children = mChildren;
+        for (int i = 0; i < count; i++) {
+            children[i].dispatchConfigurationChanged(newConfig);
+        }
+    }
+    
+    /**
+     * {@inheritDoc}
+     */
     public void recomputeViewAttributes(View child) {
         ViewParent parent = mParent;
         if (parent != null) parent.recomputeViewAttributes(this);
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 07b2d1c..264b8c9 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -41,7 +41,9 @@
 import android.widget.Scroller;
 import android.content.pm.PackageManager;
 import android.content.res.CompatibilityInfo;
+import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.content.ComponentCallbacks;
 import android.content.Context;
 import android.app.ActivityManagerNative;
 import android.Manifest;
@@ -101,6 +103,9 @@
     static final ArrayList<Runnable> sFirstDrawHandlers = new ArrayList<Runnable>();
     static boolean sFirstDrawComplete = false;
     
+    static final ArrayList<ComponentCallbacks> sConfigCallbacks
+            = new ArrayList<ComponentCallbacks>();
+    
     private static int sDrawTime;
 
     long mLastTrackballTime = 0;
@@ -171,6 +176,12 @@
     final ViewTreeObserver.InternalInsetsInfo mLastGivenInsets
             = new ViewTreeObserver.InternalInsetsInfo();
 
+    class ResizedInfo {
+        Rect coveredInsets;
+        Rect visibleInsets;
+        Configuration newConfig;
+    }
+    
     boolean mScrollMayChange;
     int mSoftInputMode;
     View mLastScrolledFocus;
@@ -265,6 +276,12 @@
         }
     }
     
+    public static void addConfigCallback(ComponentCallbacks callback) {
+        synchronized (sConfigCallbacks) {
+            sConfigCallbacks.add(callback);
+        }
+    }
+    
     // FIXME for perf testing only
     private boolean mProfile = false;
 
@@ -1782,23 +1799,33 @@
             handleGetNewSurface();
             break;
         case RESIZED:
-            Rect coveredInsets = ((Rect[])msg.obj)[0];
-            Rect visibleInsets = ((Rect[])msg.obj)[1];
+            ResizedInfo ri = (ResizedInfo)msg.obj;
 
             if (mWinFrame.width() == msg.arg1 && mWinFrame.height() == msg.arg2
-                    && mPendingContentInsets.equals(coveredInsets)
-                    && mPendingVisibleInsets.equals(visibleInsets)) {
+                    && mPendingContentInsets.equals(ri.coveredInsets)
+                    && mPendingVisibleInsets.equals(ri.visibleInsets)) {
                 break;
             }
             // fall through...
         case RESIZED_REPORT:
             if (mAdded) {
+                Configuration config = ((ResizedInfo)msg.obj).newConfig;
+                if (config != null) {
+                    synchronized (sConfigCallbacks) {
+                        for (int i=sConfigCallbacks.size()-1; i>=0; i--) {
+                            sConfigCallbacks.get(i).onConfigurationChanged(config);
+                        }
+                    }
+                    if (mView != null) {
+                        mView.dispatchConfigurationChanged(config);
+                    }
+                }
                 mWinFrame.left = 0;
                 mWinFrame.right = msg.arg1;
                 mWinFrame.top = 0;
                 mWinFrame.bottom = msg.arg2;
-                mPendingContentInsets.set(((Rect[])msg.obj)[0]);
-                mPendingVisibleInsets.set(((Rect[])msg.obj)[1]);
+                mPendingContentInsets.set(((ResizedInfo)msg.obj).coveredInsets);
+                mPendingVisibleInsets.set(((ResizedInfo)msg.obj).visibleInsets);
                 if (msg.what == RESIZED_REPORT) {
                     mReportNextDraw = true;
                 }
@@ -2587,7 +2614,7 @@
     }
 
     public void dispatchResized(int w, int h, Rect coveredInsets,
-            Rect visibleInsets, boolean reportDraw) {
+            Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
         if (DEBUG_LAYOUT) Log.v(TAG, "Resizing " + this + ": w=" + w
                 + " h=" + h + " coveredInsets=" + coveredInsets.toShortString()
                 + " visibleInsets=" + visibleInsets.toShortString()
@@ -2601,7 +2628,11 @@
         }
         msg.arg1 = w;
         msg.arg2 = h;
-        msg.obj = new Rect[] { new Rect(coveredInsets), new Rect(visibleInsets) };
+        ResizedInfo ri = new ResizedInfo();
+        ri.coveredInsets = new Rect(coveredInsets);
+        ri.visibleInsets = new Rect(visibleInsets);
+        ri.newConfig = newConfig;
+        msg.obj = ri;
         sendMessage(msg);
     }
 
@@ -2802,11 +2833,11 @@
         }
 
         public void resized(int w, int h, Rect coveredInsets,
-                Rect visibleInsets, boolean reportDraw) {
+                Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
             final ViewRoot viewRoot = mViewRoot.get();
             if (viewRoot != null) {
                 viewRoot.dispatchResized(w, h, coveredInsets,
-                        visibleInsets, reportDraw);
+                        visibleInsets, reportDraw, newConfig);
             }
         }
 
diff --git a/core/java/android/webkit/DateSorter.java b/core/java/android/webkit/DateSorter.java
index 16feaa9..bc135046 100644
--- a/core/java/android/webkit/DateSorter.java
+++ b/core/java/android/webkit/DateSorter.java
@@ -26,7 +26,7 @@
  * Sorts dates into the following groups:
  *   Today
  *   Yesterday
- *   five days ago
+ *   seven days ago
  *   one month ago
  *   older than a month ago
  */
@@ -41,7 +41,7 @@
     private long [] mBins = new long[DAY_COUNT-1];
     private String [] mLabels = new String[DAY_COUNT];
     
-    private static final int NUM_DAYS_AGO = 5;
+    private static final int NUM_DAYS_AGO = 7;
 
     /**
      * @param context Application context
diff --git a/core/java/android/webkit/GeolocationPermissions.java b/core/java/android/webkit/GeolocationPermissions.java
index d12d828..4565b756 100755
--- a/core/java/android/webkit/GeolocationPermissions.java
+++ b/core/java/android/webkit/GeolocationPermissions.java
@@ -23,6 +23,7 @@
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.Vector;
 
 
 /**
@@ -61,11 +62,8 @@
     private Handler mHandler;
     private Handler mUIHandler;
 
-    // Members used to transfer the origins and permissions between threads.
-    private Set<String> mOrigins;
-    private boolean mAllowed;
-    private Set<String> mOriginsToClear;
-    private Set<String> mOriginsToAllow;
+    // A queue to store messages until the handler is ready.
+    private Vector<Message> mQueuedMessages;
 
     // Message ids
     static final int GET_ORIGINS = 0;
@@ -126,7 +124,7 @@
      * Creates the message handler. Must be called on the WebKit thread.
      * @hide
      */
-    public void createHandler() {
+    public synchronized void createHandler() {
         if (mHandler == null) {
             mHandler = new Handler() {
                 @Override
@@ -134,21 +132,21 @@
                     // Runs on the WebKit thread.
                     switch (msg.what) {
                         case GET_ORIGINS: {
-                            getOriginsImpl();
+                            Set origins = nativeGetOrigins();
                             ValueCallback callback = (ValueCallback) msg.obj;
                             Map values = new HashMap<String, Object>();
                             values.put(CALLBACK, callback);
-                            values.put(ORIGINS, mOrigins);
+                            values.put(ORIGINS, origins);
                             postUIMessage(Message.obtain(null, RETURN_ORIGINS, values));
                             } break;
                         case GET_ALLOWED: {
                             Map values = (Map) msg.obj;
                             String origin = (String) values.get(ORIGIN);
                             ValueCallback callback = (ValueCallback) values.get(CALLBACK);
-                            getAllowedImpl(origin);
+                            boolean allowed = nativeGetAllowed(origin);
                             Map retValues = new HashMap<String, Object>();
                             retValues.put(CALLBACK, callback);
-                            retValues.put(ALLOWED, new Boolean(mAllowed));
+                            retValues.put(ALLOWED, new Boolean(allowed));
                             postUIMessage(Message.obtain(null, RETURN_ALLOWED, retValues));
                             } break;
                         case CLEAR:
@@ -164,15 +162,12 @@
                 }
             };
 
-            if (mOriginsToClear != null) {
-                for (String origin : mOriginsToClear) {
-                    nativeClear(origin);
+            // Handle the queued messages
+            if (mQueuedMessages != null) {
+                while (!mQueuedMessages.isEmpty()) {
+                    mHandler.sendMessage(mQueuedMessages.remove(0));
                 }
-            }
-            if (mOriginsToAllow != null) {
-                for (String origin : mOriginsToAllow) {
-                    nativeAllow(origin);
-                }
+                mQueuedMessages = null;
             }
         }
     }
@@ -180,9 +175,15 @@
     /**
      * Utility function to send a message to our handler.
      */
-    private void postMessage(Message msg) {
-        assert(mHandler != null);
-        mHandler.sendMessage(msg);
+    private synchronized void postMessage(Message msg) {
+        if (mHandler == null) {
+            if (mQueuedMessages == null) {
+                mQueuedMessages = new Vector<Message>();
+            }
+            mQueuedMessages.add(msg);
+        } else {
+            mHandler.sendMessage(msg);
+        }
     }
 
     /**
@@ -207,8 +208,8 @@
     public void getOrigins(ValueCallback<Set<String> > callback) {
         if (callback != null) {
             if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
-                getOriginsImpl();
-                callback.onReceiveValue(mOrigins);
+                Set origins = nativeGetOrigins();
+                callback.onReceiveValue(origins);
             } else {
                 postMessage(Message.obtain(null, GET_ORIGINS, callback));
             }
@@ -216,14 +217,6 @@
     }
 
     /**
-     * Helper method to get the set of origins.
-     */
-    private void getOriginsImpl() {
-        // Called on the WebKit thread.
-        mOrigins = nativeGetOrigins();
-    }
-
-    /**
      * Gets the permission state for the specified origin.
      *
      * Callback is a ValueCallback object whose onReceiveValue method will be
@@ -238,8 +231,8 @@
             return;
         }
         if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
-            getAllowedImpl(origin);
-            callback.onReceiveValue(new Boolean(mAllowed));
+            boolean allowed = nativeGetAllowed(origin);
+            callback.onReceiveValue(new Boolean(allowed));
         } else {
             Map values = new HashMap<String, Object>();
             values.put(ORIGIN, origin);
@@ -249,31 +242,13 @@
     }
 
     /**
-     * Helper method to get the permission state for the specified origin.
-     */
-    private void getAllowedImpl(String origin) {
-        // Called on the WebKit thread.
-        mAllowed = nativeGetAllowed(origin);
-    }
-
-    /**
      * Clears the permission state for the specified origin. This method may be
      * called before the WebKit thread has intialized the message handler.
      * Messages will be queued until this time.
      */
     public void clear(String origin) {
         // Called on the UI thread.
-        if (mHandler == null) {
-            if (mOriginsToClear == null) {
-                mOriginsToClear = new HashSet<String>();
-            }
-            mOriginsToClear.add(origin);
-            if (mOriginsToAllow != null) {
-                mOriginsToAllow.remove(origin);
-            }
-        } else {
-            postMessage(Message.obtain(null, CLEAR, origin));
-        }
+        postMessage(Message.obtain(null, CLEAR, origin));
     }
 
     /**
@@ -283,17 +258,7 @@
      */
     public void allow(String origin) {
         // Called on the UI thread.
-        if (mHandler == null) {
-            if (mOriginsToAllow == null) {
-                mOriginsToAllow = new HashSet<String>();
-            }
-            mOriginsToAllow.add(origin);
-            if (mOriginsToClear != null) {
-                mOriginsToClear.remove(origin);
-            }
-        } else {
-            postMessage(Message.obtain(null, ALLOW, origin));
-        }
+        postMessage(Message.obtain(null, ALLOW, origin));
     }
 
     /**
diff --git a/core/java/android/webkit/MimeTypeMap.java b/core/java/android/webkit/MimeTypeMap.java
index a9d6ff6..3ed9851 100644
--- a/core/java/android/webkit/MimeTypeMap.java
+++ b/core/java/android/webkit/MimeTypeMap.java
@@ -368,6 +368,7 @@
             sMimeTypeMap.loadEntry("application/x-xcf", "xcf");
             sMimeTypeMap.loadEntry("application/x-xfig", "fig");
             sMimeTypeMap.loadEntry("application/xhtml+xml", "xhtml");
+            sMimeTypeMap.loadEntry("audio/3gpp", "3gpp");
             sMimeTypeMap.loadEntry("audio/basic", "snd");
             sMimeTypeMap.loadEntry("audio/midi", "mid");
             sMimeTypeMap.loadEntry("audio/midi", "midi");
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 39e5275..662be95 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -916,9 +916,12 @@
     }
 
     /**
-     * Tell the WebView to block network image. This is only checked when
-     * getLoadsImagesAutomatically() is true.
-     * @param flag True if the WebView should block network image
+     * Tell the WebView to block network images. This is only checked when
+     * {@link #getLoadsImagesAutomatically} is true. If you set the value to
+     * false, images will automatically be loaded. Use this api to reduce
+     * bandwidth only. Use {@link #setBlockNetworkLoads} if possible.
+     * @param flag True if the WebView should block network images.
+     * @see #setBlockNetworkLoads
      */
     public synchronized void setBlockNetworkImage(boolean flag) {
         if (mBlockNetworkImage != flag) {
@@ -928,17 +931,21 @@
     }
 
     /**
-     * Return true if the WebView will block network image. The default is false.
-     * @return True if the WebView blocks network image.
+     * Return true if the WebView will block network images. The default is
+     * false.
+     * @return True if the WebView blocks network images.
      */
     public synchronized boolean getBlockNetworkImage() {
         return mBlockNetworkImage;
     }
 
     /**
-     * @hide
-     * Tell the WebView to block all network load requests.
-     * @param flag True if the WebView should block all network loads
+     * Tell the WebView to block all network load requests. If you set the
+     * value to false, you must call {@link android.webkit.WebView#reload} to
+     * fetch remote resources. This flag supercedes the value passed to
+     * {@link #setBlockNetworkImage}.
+     * @param flag True if the WebView should block all network loads.
+     * @see android.webkit.WebView#reload
      */
     public synchronized void setBlockNetworkLoads(boolean flag) {
         if (mBlockNetworkLoads != flag) {
@@ -948,9 +955,8 @@
     }
 
     /**
-     * @hide
-     * Return true if the WebView will block all network loads.
-     * The default is false.
+     * Return true if the WebView will block all network loads. The default is
+     * false.
      * @return True if the WebView blocks all network loads.
      */
     public synchronized boolean getBlockNetworkLoads() {
diff --git a/core/java/android/webkit/WebStorage.java b/core/java/android/webkit/WebStorage.java
index cf71a84..9314d7b 100644
--- a/core/java/android/webkit/WebStorage.java
+++ b/core/java/android/webkit/WebStorage.java
@@ -146,7 +146,7 @@
      * @hide
      * Message handler, webcore side
      */
-    public void createHandler() {
+    public synchronized void createHandler() {
         if (mHandler == null) {
             mHandler = new Handler() {
                 @Override
@@ -342,7 +342,7 @@
     /**
      * Utility function to send a message to our handler
      */
-    private void postMessage(Message msg) {
+    private synchronized void postMessage(Message msg) {
         if (mHandler != null) {
             mHandler.sendMessage(msg);
         }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 9672892..adae0cb 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -3088,14 +3088,11 @@
         Rect vBox = contentToViewRect(contentBounds);
         Rect visibleRect = new Rect();
         calcOurVisibleRect(visibleRect);
-        // The IME may have shown, resulting in the textfield being offscreen.
-        // If so, the textfield will be scrolled on screen, so treat it as
-        // though it is on screen.  If it is on screen, place the WebTextView in
-        // its new place, accounting for our new scroll/zoom values.
-        InputMethodManager imm = InputMethodManager.peekInstance();
-        if ((imm != null && imm.isActive(mWebTextView))
-                || (allowIntersect ? Rect.intersects(visibleRect, vBox)
-                : visibleRect.contains(vBox))) {
+        // If the textfield is on screen, place the WebTextView in
+        // its new place, accounting for our new scroll/zoom values,
+        // and adjust its textsize.
+        if (allowIntersect ? Rect.intersects(visibleRect, vBox)
+                : visibleRect.contains(vBox)) {
             mWebTextView.setRect(vBox.left, vBox.top, vBox.width(),
                     vBox.height());
             mWebTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
@@ -4439,6 +4436,7 @@
             ted.mX = viewToContentX((int) x + mScrollX);
             ted.mY = viewToContentY((int) y + mScrollY);
             ted.mEventTime = eventTime;
+            ted.mMetaState = ev.getMetaState();
             mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
             mLastSentTouchTime = eventTime;
         }
@@ -4702,6 +4700,7 @@
                             ted.mX = viewToContentX((int) x + mScrollX);
                             ted.mY = viewToContentY((int) y + mScrollY);
                             ted.mEventTime = eventTime;
+                            ted.mMetaState = ev.getMetaState();
                             mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
                         } else if (mFullScreenHolder == null) {
                             doDoubleTap();
@@ -5738,6 +5737,11 @@
                         ted.mX = viewToContentX((int) mLastTouchX + mScrollX);
                         ted.mY = viewToContentY((int) mLastTouchY + mScrollY);
                         ted.mEventTime = SystemClock.uptimeMillis();
+                        // metaState for long press is tricky. Should it be the state
+                        // when the press started or when the press was released? Or
+                        // some intermediary key state? For simplicity for now, we
+                        // don't set it.
+                        ted.mMetaState = 0;
                         mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
                     } else if (mPreventDrag == PREVENT_DRAG_NO) {
                         mTouchMode = TOUCH_DONE_MODE;
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 3a3e445..361ec56 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -515,7 +515,7 @@
     private native void nativeTouchUp(int touchGeneration,
             int framePtr, int nodePtr, int x, int y);
 
-    private native int nativeHandleTouchEvent(int action, int x, int y, long time);
+    private native int nativeHandleTouchEvent(int action, int x, int y, long time, int metaState);
 
     private native void nativeUpdateFrameCache();
 
@@ -735,6 +735,7 @@
         int mX;
         int mY;
         long mEventTime;
+        int mMetaState;
     }
 
     static class GeolocationPermissionsData {
@@ -1198,7 +1199,7 @@
                                     mWebView.mPrivateHandler,
                                     WebView.PREVENT_TOUCH_ID, ted.mAction,
                                     nativeHandleTouchEvent(ted.mAction, ted.mX,
-                                    ted.mY, ted.mEventTime)).sendToTarget();
+                                    ted.mY, ted.mEventTime, ted.mMetaState)).sendToTarget();
                             break;
                         }
 
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 254efe7..a79bbee 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2364,7 +2364,16 @@
     public void draw(Canvas canvas) {
         super.draw(canvas);
         if (mFastScroller != null) {
-            mFastScroller.draw(canvas);
+            final int scrollY = mScrollY;
+            if (scrollY != 0) {
+                // Pin the fast scroll thumb to the top/bottom during overscroll.
+                int restoreCount = canvas.save();
+                canvas.translate(0, (float) scrollY);
+                mFastScroller.draw(canvas);
+                canvas.restoreToCount(restoreCount);
+            } else {
+                mFastScroller.draw(canvas);
+            }
         }
     }
 
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 3853359..233ce30 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -32,6 +32,7 @@
 import android.net.Uri;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.view.RemotableViewMethod;
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
@@ -69,6 +70,7 @@
     private ColorFilter mColorFilter;
     private int mAlpha = 255;
     private int mViewAlphaScale = 256;
+    private boolean mColorMod = false;
 
     private Drawable mDrawable = null;
     private int[] mState = null;
@@ -138,7 +140,7 @@
 
         int tint = a.getInt(com.android.internal.R.styleable.ImageView_tint, 0);
         if (tint != 0) {
-            setColorFilter(tint, PorterDuff.Mode.SRC_ATOP);
+            setColorFilter(tint);
         }
         
         mCropToPadding = a.getBoolean(
@@ -877,6 +879,18 @@
         setColorFilter(new PorterDuffColorFilter(color, mode));
     }
 
+    /**
+     * Set a tinting option for the image. Assumes
+     * {@link PorterDuff.Mode#SRC_ATOP} blending mode.
+     *
+     * @param color Color tint to apply.
+     * @attr ref android.R.styleable#ImageView_tint
+     */
+    @RemotableViewMethod
+    public final void setColorFilter(int color) {
+        setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
+    }
+
     public final void clearColorFilter() {
         setColorFilter(null);
     }
@@ -889,22 +903,29 @@
     public void setColorFilter(ColorFilter cf) {
         if (mColorFilter != cf) {
             mColorFilter = cf;
+            mColorMod = true;
             applyColorMod();
             invalidate();
         }
     }
 
+    @RemotableViewMethod
     public void setAlpha(int alpha) {
         alpha &= 0xFF;          // keep it legal
         if (mAlpha != alpha) {
             mAlpha = alpha;
+            mColorMod = true;
             applyColorMod();
             invalidate();
         }
     }
 
     private void applyColorMod() {
-        if (mDrawable != null) {
+        // Only mutate and apply when modifications have occurred. This should
+        // not reset the mColorMod flag, since these filters need to be
+        // re-applied if the Drawable is changed.
+        if (mDrawable != null && mColorMod) {
+            mDrawable = mDrawable.mutate();
             mDrawable.setColorFilter(mColorFilter);
             mDrawable.setAlpha(mAlpha * mViewAlphaScale >> 8);
         }
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index c428dc0..2feed03 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -16,14 +16,17 @@
 
 package android.widget;
 
+import com.android.internal.R;
+import com.google.android.collect.Lists;
+
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.graphics.PixelFormat;
 import android.graphics.Paint;
-import android.graphics.drawable.Drawable;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
 import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.AttributeSet;
@@ -31,16 +34,13 @@
 import android.view.FocusFinder;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
+import android.view.SoundEffectConstants;
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
 import android.view.ViewParent;
-import android.view.SoundEffectConstants;
 import android.view.accessibility.AccessibilityEvent;
 
-import com.google.android.collect.Lists;
-import com.android.internal.R;
-
 import java.util.ArrayList;
 
 /*
@@ -2722,7 +2722,8 @@
 
     /**
      * Determine the distance to the nearest edge of a view in a particular
-     * direciton.
+     * direction.
+     * 
      * @param descendant A descendant of this list.
      * @return The distance, or 0 if the nearest edge is already on screen.
      */
@@ -3091,9 +3092,9 @@
             previouslyFocusedRect.offset(mScrollX, mScrollY);
 
             final ListAdapter adapter = mAdapter;
-            final int firstPosition = mFirstPosition;
-            // Don't cache the result of getChildCount here, it could change in layoutChildren.
-            if (adapter.getCount() < getChildCount() + firstPosition) {
+            // Don't cache the result of getChildCount or mFirstPosition here,
+            // it could change in layoutChildren.
+            if (adapter.getCount() < getChildCount() + mFirstPosition) {
                 mLayoutMode = LAYOUT_NORMAL;
                 layoutChildren();
             }
@@ -3103,6 +3104,7 @@
             Rect otherRect = mTempRect;
             int minDistance = Integer.MAX_VALUE;
             final int childCount = getChildCount();
+            final int firstPosition = mFirstPosition;
 
             for (int i = 0; i < childCount; i++) {
                 // only consider selectable views
@@ -3307,9 +3309,9 @@
      * Sets the checked state of the specified position. The is only valid if
      * the choice mode has been set to {@link #CHOICE_MODE_SINGLE} or
      * {@link #CHOICE_MODE_MULTIPLE}.
-     *
+     * 
      * @param position The item whose checked state is to be checked
-     * @param value The new checked sate for the item
+     * @param value The new checked state for the item
      */
     public void setItemChecked(int position, boolean value) {
         if (mChoiceMode == CHOICE_MODE_NONE) {
@@ -3392,10 +3394,11 @@
     }
 
     /**
-     * Returns the set of checked items ids. The result is only valid if
-     * the choice mode has not been set to {@link #CHOICE_MODE_SINGLE}.
-     *
-     * @return A new array which contains the id of each checked item in the list.
+     * Returns the set of checked items ids. The result is only valid if the
+     * choice mode has not been set to {@link #CHOICE_MODE_SINGLE}.
+     * 
+     * @return A new array which contains the id of each checked item in the
+     *         list.
      */
     public long[] getCheckItemIds() {
         if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null && mAdapter != null) {
@@ -3404,11 +3407,23 @@
             final long[] ids = new long[count];
             final ListAdapter adapter = mAdapter;
 
+            int checkedCount = 0;
             for (int i = 0; i < count; i++) {
-                ids[i]= adapter.getItemId(states.keyAt(i));
+                if (states.valueAt(i)) {
+                    ids[checkedCount++] = adapter.getItemId(states.keyAt(i));
+                }
             }
 
-            return ids;
+            // Trim array if needed. mCheckStates may contain false values
+            // resulting in checkedCount being smaller than count.
+            if (checkedCount == count) {
+                return ids;
+            } else {
+                final long[] result = new long[checkedCount];
+                System.arraycopy(ids, 0, result, 0, checkedCount);
+
+                return result;
+            }
         }
 
         return new long[0];
diff --git a/core/java/android/widget/ViewFlipper.java b/core/java/android/widget/ViewFlipper.java
index aee25b0..8034961 100644
--- a/core/java/android/widget/ViewFlipper.java
+++ b/core/java/android/widget/ViewFlipper.java
@@ -38,7 +38,7 @@
 @RemoteView
 public class ViewFlipper extends ViewAnimator {
     private static final String TAG = "ViewFlipper";
-    private static final boolean LOGD = true;
+    private static final boolean LOGD = false;
 
     private static final int DEFAULT_INTERVAL = 3000;
 
diff --git a/core/java/com/android/internal/app/DisableCarModeActivity.java b/core/java/com/android/internal/app/DisableCarModeActivity.java
new file mode 100644
index 0000000..95dc1f9
--- /dev/null
+++ b/core/java/com/android/internal/app/DisableCarModeActivity.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app;
+
+import android.app.Activity;
+import android.app.IUiModeManager;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+public class DisableCarModeActivity extends Activity {
+    private static final String TAG = "DisableCarModeActivity";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        try {
+            IUiModeManager uiModeManager = IUiModeManager.Stub.asInterface(
+                    ServiceManager.getService("uimode"));
+            uiModeManager.disableCarMode();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to disable car mode", e);
+        }
+        finish();
+    }
+
+}
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index c5b869b..bc7dbf4 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -93,7 +93,7 @@
 
    public static boolean unMountSdDir(String cid) {
     try {
-        int rc = getMountService().unmountSecureContainer(cid);
+        int rc = getMountService().unmountSecureContainer(cid, false);
         if (rc != StorageResultCode.OperationSucceeded) {
             Log.e(TAG, "Failed to unmount " + cid + " with rc " + rc);
             return false;
@@ -148,7 +148,7 @@
 
     public static boolean destroySdDir(String cid) {
         try {
-            int rc = getMountService().destroySecureContainer(cid);
+            int rc = getMountService().destroySecureContainer(cid, false);
             if (rc != StorageResultCode.OperationSucceeded) {
                 Log.i(TAG, "Failed to destroy container " + cid);
                 return false;
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 15dcbd6..22c6e79 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -1,5 +1,6 @@
 package com.android.internal.view;
 
+import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
@@ -17,7 +18,7 @@
     }
     
     public void resized(int w, int h, Rect coveredInsets,
-            Rect visibleInsets, boolean reportDraw) {
+            Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
         if (reportDraw) {
             try {
                 mSession.finishDrawing(this);
diff --git a/core/jni/android/graphics/YuvToJpegEncoder.cpp b/core/jni/android/graphics/YuvToJpegEncoder.cpp
index e6a1872..819cce8 100644
--- a/core/jni/android/graphics/YuvToJpegEncoder.cpp
+++ b/core/jni/android/graphics/YuvToJpegEncoder.cpp
@@ -7,9 +7,9 @@
 #include <jni.h>
 
 YuvToJpegEncoder* YuvToJpegEncoder::create(int format, int* strides) {
-    // Only PIXEL_FORMAT_YCbCr_420_SP and PIXEl_FOMAT_YCbCr_422_I are supported
+    // Only ImageFormat.NV21 and ImageFormat.YUY2 are supported
     // for now.
-    if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP) {
+    if (format == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
         return new Yuv420SpToJpegEncoder(strides);
     } else if (format == HAL_PIXEL_FORMAT_YCbCr_422_I) {
         return new Yuv422IToJpegEncoder(strides);
diff --git a/core/jni/android_database_SQLiteDatabase.cpp b/core/jni/android_database_SQLiteDatabase.cpp
index c197010..26d0e86 100644
--- a/core/jni/android_database_SQLiteDatabase.cpp
+++ b/core/jni/android_database_SQLiteDatabase.cpp
@@ -470,7 +470,7 @@
     if (errcode == SQLITE_DONE) {
         throw_sqlite3_exception(env, errcode, NULL, message);
     } else {
-        char temp[20];
+        char temp[21];
         sprintf(temp, "error code %d", errcode);
         throw_sqlite3_exception(env, errcode, temp, message);
     }
diff --git a/core/jni/android_database_SQLiteProgram.cpp b/core/jni/android_database_SQLiteProgram.cpp
index 32018eb..c247bbd 100644
--- a/core/jni/android_database_SQLiteProgram.cpp
+++ b/core/jni/android_database_SQLiteProgram.cpp
@@ -45,8 +45,8 @@
 
 static void native_compile(JNIEnv* env, jobject object, jstring sqlString)
 {
-    char buf[32];
-    sprintf(buf, "android_database_SQLiteProgram->native_compile() not implemented");
+    char buf[65];
+    strcpy(buf, "android_database_SQLiteProgram->native_compile() not implemented");
     throw_sqlite3_exception(env, GET_HANDLE(env, object), buf);
     return;
 }
@@ -152,8 +152,8 @@
 
 static void native_finalize(JNIEnv* env, jobject object)
 {
-    char buf[32];
-    sprintf(buf, "android_database_SQLiteProgram->native_finalize() not implemented");
+    char buf[66];
+    strcpy(buf, "android_database_SQLiteProgram->native_finalize() not implemented");
     throw_sqlite3_exception(env, GET_HANDLE(env, object), buf);
     return;
 }
diff --git a/core/jni/android_graphics_PixelFormat.cpp b/core/jni/android_graphics_PixelFormat.cpp
index 0643622..5b8363c 100644
--- a/core/jni/android_graphics_PixelFormat.cpp
+++ b/core/jni/android_graphics_PixelFormat.cpp
@@ -48,11 +48,35 @@
         JNIEnv* env, jobject clazz, jint format, jobject pixelFormatObject)
 {
     PixelFormatInfo info;
-    status_t err = getPixelFormatInfo(format, &info);
+    status_t err;
+
+    // we need this for backward compatibility with PixelFormat's
+    // deprecated constants
+    switch (format) {
+    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+        // defined as the bytes per pixel of the Y plane
+        info.bytesPerPixel = 1;
+        info.bitsPerPixel = 16;
+        goto done;
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+        // defined as the bytes per pixel of the Y plane
+        info.bytesPerPixel = 1;
+        info.bitsPerPixel = 12;
+        goto done;
+    case HAL_PIXEL_FORMAT_YCbCr_422_I:
+        // defined as the bytes per pixel of the Y plane
+        info.bytesPerPixel = 1;
+        info.bitsPerPixel = 16;
+        goto done;
+    }
+
+    err = getPixelFormatInfo(format, &info);
     if (err < 0) {
         doThrow(env, "java/lang/IllegalArgumentException");
         return;
     }
+
+done:
     env->SetIntField(pixelFormatObject, offsets.bytesPerPixel, info.bytesPerPixel);
     env->SetIntField(pixelFormatObject, offsets.bitsPerPixel,  info.bitsPerPixel);
 }
diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp
index 4e1ae62..5432efb 100644
--- a/core/jni/android_server_BluetoothEventLoop.cpp
+++ b/core/jni/android_server_BluetoothEventLoop.cpp
@@ -1122,9 +1122,10 @@
     if (dbus_set_error_from_message(&err, msg)) {
         if (dbus_error_has_name(&err, "org.bluez.Error.AlreadyExists")) {
             result = CREATE_DEVICE_ALREADY_EXISTS;
+        } else {
+            result = CREATE_DEVICE_FAILED;
         }
         LOG_AND_FREE_DBUS_ERROR(&err);
-        result = CREATE_DEVICE_FAILED;
     }
     env->CallVoidMethod(nat->me,
                         method_onCreateDeviceResult,
diff --git a/core/jni/android_util_FileObserver.cpp b/core/jni/android_util_FileObserver.cpp
index 13a1645..65e7130 100644
--- a/core/jni/android_util_FileObserver.cpp
+++ b/core/jni/android_util_FileObserver.cpp
@@ -71,28 +71,32 @@
             return;
         }
         
-    	while (num_bytes >= (int)sizeof(*event))
-    	{
-			int event_size;
-			event = (struct inotify_event *)(event_buf + event_pos);
-			
+        while (num_bytes >= (int)sizeof(*event))
+        {
+            int event_size;
+            event = (struct inotify_event *)(event_buf + event_pos);
+
             jstring path = NULL;
             
             if (event->len > 0)
             {
                 path = env->NewStringUTF(event->name);
             }
-            
-		    env->CallVoidMethod(object, method_onEvent, event->wd, event->mask, path);
+
+            env->CallVoidMethod(object, method_onEvent, event->wd, event->mask, path);
+            if (env->ExceptionCheck()) {
+                env->ExceptionDescribe();
+                env->ExceptionClear();
+            }
             if (path != NULL)
             {
                 env->DeleteLocalRef(path);
             }
-		    
-		    event_size = sizeof(*event) + event->len;
-			num_bytes -= event_size;
-			event_pos += event_size;
-		}
+
+            event_size = sizeof(*event) + event->len;
+            num_bytes -= event_size;
+            event_pos += event_size;
+        }
     }
     
 #endif // HAVE_INOTIFY
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a27d28f..333db05 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1252,6 +1252,10 @@
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
         </activity>
+        <activity android:name="com.android.internal.app.DisableCarModeActivity"
+                android:theme="@style/Theme.NoDisplay"
+                android:excludeFromRecents="true">
+        </activity>
         <activity android:name="com.android.internal.app.RingtonePickerActivity"
                 android:theme="@style/Theme.Dialog.Alert"
                 android:excludeFromRecents="true"
diff --git a/core/res/res/drawable-hdpi/stat_notify_car_mode.png b/core/res/res/drawable-hdpi/stat_notify_car_mode.png
new file mode 100644
index 0000000..6c51b32
--- /dev/null
+++ b/core/res/res/drawable-hdpi/stat_notify_car_mode.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_car_mode.png b/core/res/res/drawable-mdpi/stat_notify_car_mode.png
new file mode 100644
index 0000000..c664244
--- /dev/null
+++ b/core/res/res/drawable-mdpi/stat_notify_car_mode.png
Binary files differ
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 6f34b4f..cdf38b9 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2261,4 +2261,9 @@
     <!-- See TETHER_STOP_DIALOG.  If there was an error disconnect, this is the text. -->
     <string name="tether_stop_error_message">We\'ve encountered a problem turning off Tethering. Please try again.</string>
 
+    <!-- Strings for car mode notification -->
+    <!-- Shown when car mode is enabled -->
+    <string name="car_mode_disable_notification_title">Car mode enabled</string>
+    <string name="car_mode_disable_notification_message">Select to disable car mode.</string>
+
 </resources>
diff --git a/core/res/res/xml-mdpi/password_kbd_qwerty.xml b/core/res/res/xml-mdpi/password_kbd_qwerty.xml
index a3d4e88..bae1b42 100755
--- a/core/res/res/xml-mdpi/password_kbd_qwerty.xml
+++ b/core/res/res/xml-mdpi/password_kbd_qwerty.xml
@@ -80,8 +80,8 @@
         <Key android:keyLabel="=" />
         <Key android:codes="46" android:keyLabel="."
             android:keyWidth="10%p"/>
-        <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
-            android:iconPreview="@drawable/sym_keyboard_feedback_return"
+        <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_ok"
+            android:iconPreview="@drawable/sym_keyboard_feedback_ok"
             android:keyWidth="20%p" android:keyEdgeFlags="right"/>
     </Row>
 
diff --git a/core/res/res/xml-mdpi/password_kbd_qwerty_shifted.xml b/core/res/res/xml-mdpi/password_kbd_qwerty_shifted.xml
index 2285d91..612df9c 100755
--- a/core/res/res/xml-mdpi/password_kbd_qwerty_shifted.xml
+++ b/core/res/res/xml-mdpi/password_kbd_qwerty_shifted.xml
@@ -79,8 +79,8 @@
             android:keyWidth="20%p" android:isRepeatable="true"/>
         <Key android:keyLabel="+" />
         <Key android:codes="46" android:keyLabel="."/>
-        <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
-            android:iconPreview="@drawable/sym_keyboard_feedback_return"
+        <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_ok"
+            android:iconPreview="@drawable/sym_keyboard_feedback_ok"
             android:keyWidth="20%p" android:keyEdgeFlags="right"/>
     </Row>
 
diff --git a/core/tests/coretests/src/android/database/DatabaseGeneralTest.java b/core/tests/coretests/src/android/database/DatabaseGeneralTest.java
index ca650e0..e43031c 100644
--- a/core/tests/coretests/src/android/database/DatabaseGeneralTest.java
+++ b/core/tests/coretests/src/android/database/DatabaseGeneralTest.java
@@ -944,6 +944,7 @@
         Assert.assertNull(cur.getString(3));
         Assert.assertEquals(1234, cur.getLong(4));
         Assert.assertNull(cur.getString(5));
+        cur.close();
 
         cv = new ContentValues();
         cv.put("s", "two");
@@ -956,6 +957,7 @@
         Assert.assertNull(cur.getString(3));
         Assert.assertEquals(1234, cur.getLong(4));
         Assert.assertNull(cur.getString(5));
+        cur.close();
 
         cv = new ContentValues();
         cv.put("t", "goodbye world");
@@ -975,6 +977,7 @@
         Assert.assertEquals(2345, cur.getLong(3));
         Assert.assertEquals(3456, cur.getLong(4));
         Assert.assertEquals("tricky", cur.getString(5));
+        cur.close();
 
         cv = new ContentValues();
         cv.put("s", "three");
@@ -987,6 +990,7 @@
         Assert.assertEquals("three", cur.getString(1));
         Assert.assertEquals("hello world", cur.getString(2));
         Assert.assertEquals(6789, cur.getLong(3));
+        cur.close();
 
         ih.close();
     }
diff --git a/core/tests/coretests/src/android/database/sqlite/SQLiteGeneralTest.java b/core/tests/coretests/src/android/database/sqlite/SQLiteGeneralTest.java
new file mode 100644
index 0000000..af7ccce
--- /dev/null
+++ b/core/tests/coretests/src/android/database/sqlite/SQLiteGeneralTest.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.database.sqlite;
+
+import android.content.Context;
+import android.test.AndroidTestCase;
+import android.test.FlakyTest;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import java.io.File;
+
+public class SQLiteGeneralTest extends AndroidTestCase {
+
+    private SQLiteDatabase mDatabase;
+    private File mDatabaseFile;
+    Boolean exceptionRecvd = false;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        exceptionRecvd = false;
+        File dbDir = getContext().getDir(this.getClass().getName(), Context.MODE_PRIVATE);
+        mDatabaseFile = new File(dbDir, "database_test.db");
+        if (mDatabaseFile.exists()) {
+            mDatabaseFile.delete();
+        }
+        mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null);
+        assertNotNull(mDatabase);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mDatabase.close();
+        mDatabaseFile.delete();
+        super.tearDown();
+    }
+
+    @LargeTest
+    public void testUseOfSameSqlStatementBy2Threads() throws Exception {
+        mDatabase.execSQL("CREATE TABLE test_pstmt (i INTEGER PRIMARY KEY, j text);");
+
+        // thread 1 creates a prepared statement
+        final String stmt = "SELECT * FROM test_pstmt WHERE i = ?";
+
+        // start 2 threads to do repeatedly execute "stmt"
+        // since these 2 threads are executing the same sql, they each should get
+        // their own copy and
+        // there SHOULD NOT be an error from sqlite: "prepared statement is busy"
+        class RunStmtThread extends Thread {
+            private static final int N = 1000;
+            @Override public void run() {
+                int i = 0;
+                try {
+                    // execute many times
+                    for (i = 0; i < N; i++) {
+                        SQLiteStatement s1 = mDatabase.compileStatement(stmt);
+                        s1.bindLong(1, i);
+                        s1.execute();
+                        s1.close();
+                    }
+                } catch (SQLiteException e) {
+                    fail("SQLiteException: " + e.getMessage());
+                    return;
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    fail("random unexpected exception: " + e.getMessage());
+                    return;
+                }
+            }
+        }
+        RunStmtThread t1 = new RunStmtThread();
+        t1.start();
+        RunStmtThread t2 = new RunStmtThread();
+        t2.start();
+        while (t1.isAlive() || t2.isAlive()) {
+            Thread.sleep(1000);
+        }
+    }
+
+    @FlakyTest
+    public void testUseOfSamePreparedStatementBy2Threads() throws Exception {
+        mDatabase.execSQL("CREATE TABLE test_pstmt (i INTEGER PRIMARY KEY, j text);");
+
+        // thread 1 creates a prepared statement
+        final String stmt = "SELECT * FROM test_pstmt WHERE i = ?";
+        final SQLiteStatement s1 = mDatabase.compileStatement(stmt);
+
+        // start 2 threads to do repeatedly execute "stmt"
+        // since these 2 threads are executing the same prepared statement,
+        // should see an error from sqlite: "prepared statement is busy"
+        class RunStmtThread extends Thread {
+            private static final int N = 1000;
+            @Override public void run() {
+                int i = 0;
+                try {
+                    // execute many times
+                    for (i = 0; i < N; i++) {
+                        s1.bindLong(1, i);
+                        s1.execute();
+                    }
+                } catch (SQLiteException e) {
+                    // expect it
+                    assertTrue(e.getMessage().contains("library routine called out of sequence:"));
+                    exceptionRecvd = true;
+                    return;
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    fail("random unexpected exception: " + e.getMessage());
+                    return;
+                }
+            }
+        }
+        RunStmtThread t1 = new RunStmtThread();
+        t1.start();
+        RunStmtThread t2 = new RunStmtThread();
+        t2.start();
+        while (t1.isAlive() || t2.isAlive()) {
+            Thread.sleep(1000);
+        }
+        assertTrue(exceptionRecvd);
+    }
+}
diff --git a/core/tests/coretests/src/android/widget/listview/ListGetCheckItemIdsTest.java b/core/tests/coretests/src/android/widget/listview/ListGetCheckItemIdsTest.java
new file mode 100644
index 0000000..33d61a0
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/listview/ListGetCheckItemIdsTest.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.listview;
+
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.ListView;
+
+import java.util.Arrays;
+
+/**
+ * Testing the ListView getCheckItemIds() method in different situations.
+ */
+public class ListGetCheckItemIdsTest extends ActivityInstrumentationTestCase2<ListSimple> {
+    private ListView mListView;
+
+    public ListGetCheckItemIdsTest() {
+        super(ListSimple.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mListView = getActivity().getListView();
+    }
+
+    private void assertChecked(String message, long... expectedIds) {
+        // Sort the two arrays since we are actually doing a set equality.
+        long[] checkItemIds = mListView.getCheckItemIds();
+        long[] sortedCheckItemsIds = new long[checkItemIds.length];
+        System.arraycopy(checkItemIds, 0, sortedCheckItemsIds, 0, checkItemIds.length);
+        Arrays.sort(sortedCheckItemsIds);
+
+        long[] sortedExpectedIds = new long[expectedIds.length];
+        System.arraycopy(expectedIds, 0, sortedExpectedIds, 0, expectedIds.length);
+        Arrays.sort(sortedExpectedIds);
+
+        assertTrue(message, Arrays.equals(sortedExpectedIds, sortedCheckItemsIds));
+    }
+
+    @MediumTest
+    @UiThreadTest
+    public void testNoneCheck() {
+        mListView.setChoiceMode(ListView.CHOICE_MODE_NONE);
+
+        mListView.setItemChecked(0, true);
+        assertChecked("None check choice has item checked");
+    }
+
+    @MediumTest
+    @UiThreadTest
+    public void testSimpleCheck() {
+        mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+        assertChecked("Item checked when setting Single mode");
+
+        // Test a check at each position
+        int childCount = mListView.getChildCount();
+        for (int i=0; i<childCount; i++) {
+            mListView.setItemChecked(i, true);
+            assertChecked("Only element " + i + " should be checked", i);
+        }
+
+        // Check an element and uncheck some others
+        for (int i = 0; i < childCount; i++) {
+            mListView.setItemChecked(i, true);
+            mListView.setItemChecked((i - 3 + childCount) % childCount, false);
+            mListView.setItemChecked((i + 1) % childCount, false);
+            assertChecked("Only element " + i + " should be checked", i);
+        }
+    }
+
+    @MediumTest
+    @UiThreadTest
+    public void testMultipleCheck() {
+        mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
+        assertChecked("Item checked when setting Multiple mode");
+
+        int childCount = mListView.getChildCount();
+        assertTrue("Tests requires at least 4 items", childCount >= 4);
+
+        mListView.setItemChecked(1, true);
+        assertChecked("First element non checked", 1);
+
+        mListView.setItemChecked(3, true);
+        assertChecked("Second element not checked", 1, 3);
+
+        mListView.setItemChecked(0, true);
+        assertChecked("Third element not checked", 0, 1, 3);
+
+        mListView.setItemChecked(2, false);
+        assertChecked("Unchecked element appears checked", 0, 1, 3);
+
+        mListView.setItemChecked(1, false);
+        assertChecked("Unchecked element remains", 0, 3);
+
+        mListView.setItemChecked(2, false);
+        assertChecked("Already unchecked element appears", 0, 3);
+
+        mListView.setItemChecked(3, false);
+        assertChecked("Unchecked 3 remains", 0);
+
+        mListView.setItemChecked(3, false);
+        assertChecked("Twice unchecked 3 remains", 0);
+
+        mListView.setItemChecked(0, false);
+        assertChecked("Checked items after last element unchecked");
+    }
+
+    @MediumTest
+    @UiThreadTest
+    public void testClearChoices() {
+        mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+        mListView.setItemChecked(0, true);
+        mListView.clearChoices();
+        assertChecked("Item checked after SINGLE clear choice");
+
+        mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
+        int childCount = mListView.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            mListView.setItemChecked(0, i % 3 == 0);
+        }
+        mListView.clearChoices();
+        assertChecked("Item checked after MULTIPLE clear choice");
+    }
+}
diff --git a/graphics/java/android/graphics/AvoidXfermode.java b/graphics/java/android/graphics/AvoidXfermode.java
index 2ed042b..7e2722d 100644
--- a/graphics/java/android/graphics/AvoidXfermode.java
+++ b/graphics/java/android/graphics/AvoidXfermode.java
@@ -38,15 +38,15 @@
      *
      * There are two modes, and each mode interprets a tolerance value.
      *
-     * AVOID: In this mode, drawing is allowed only on destination pixels that
+     * Avoid: In this mode, drawing is allowed only on destination pixels that
      * are different from the op-color.
-     *   Tolerance near 0: avoid anything close to the op-color
-     *   Tolerance near 255: avoid only colors very close to the op-color
-     *
-     * TARGET: In this mode, drawing only occurs on destination pixels that
+     * Tolerance near 0: avoid any colors even remotely similar to the op-color
+     * Tolerance near 255: avoid only colors nearly identical to the op-color
+     
+     * Target: In this mode, drawing only occurs on destination pixels that
      * are similar to the op-color
-     *   Tolerance near 0: draw on colors that are very close to op-color
-     *   Tolerance near 255: draw on colors that  to the op-color
+     * Tolerance near 0: draw only on colors that are nearly identical to the op-color
+     * Tolerance near 255: draw on any colors even remotely similar to the op-color
      */
     public AvoidXfermode(int opColor, int tolerance, Mode mode) {
         if (tolerance < 0 || tolerance > 255) {
diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java
new file mode 100644
index 0000000..f126374
--- /dev/null
+++ b/graphics/java/android/graphics/ImageFormat.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+public class ImageFormat
+{
+    /* these constants are chosen to be binary compatible with
+     * their previous location in PixelFormat.java */
+    
+    public static final int UNKNOWN = 0;
+
+    /** RGB format used for pictures encoded as RGB_565   
+     *  see {@link android.hardware.Camera.Parameters#setPictureFormat(int)}.
+     */
+    public static final int RGB_565 = 4;
+
+    /**
+     * YCbCr formats, used for video. These are not necessarily supported
+     * by the hardware.
+     */
+    public static final int NV16 = 0x10;
+
+    
+    /** YCrCb format used for images, which uses the NV21 encoding format.   
+     *  This is the default format for camera preview images, when not
+     *  otherwise set with 
+     *  {@link android.hardware.Camera.Parameters#setPreviewFormat(int)}.
+     */
+    public static final int NV21 = 0x11;
+
+
+    /** YCbCr format used for images, which uses YUYV (YUY2) encoding format.
+     *  This is an alternative format for camera preview images. Whether this
+     *  format is supported by the camera hardware can be determined by
+     *  {@link android.hardware.Camera.Parameters#getSupportedPreviewFormats()}.
+     */
+    public static final int YUY2 = 0x14;
+
+    
+    /**
+     * Encoded formats.  These are not necessarily supported by the hardware.
+     */
+    public static final int JPEG = 0x100;
+
+
+    /**
+     * Use this function to retrieve the number of bits per pixel of
+     * an ImageFormat.
+     * @param format
+     * @return the number of bits per pixel of the given format or -1 if the
+     * format doesn't exist or is not supported.
+     */
+    public static int getBitsPerPixel(int format) {
+        switch (format) {
+            case RGB_565:   return 16;
+            case NV16:      return 16;
+            case NV21:      return 12;
+            case YUY2:      return 16;
+        }
+        return -1;
+    }
+}
diff --git a/graphics/java/android/graphics/PixelFormat.java b/graphics/java/android/graphics/PixelFormat.java
index c76cee7..182f14d 100644
--- a/graphics/java/android/graphics/PixelFormat.java
+++ b/graphics/java/android/graphics/PixelFormat.java
@@ -18,8 +18,7 @@
 
 public class PixelFormat
 {
-    /* these constants need to match those
-       in ui/PixelFormat.h & pixelflinger/format.h */
+    /* these constants need to match those in hardware/hardware.h */
     
     public static final int UNKNOWN     = 0;
 
@@ -46,30 +45,34 @@
     public static final int L_8         = 9;
     public static final int LA_88       = 0xA;
     public static final int RGB_332     = 0xB;
-    
+
+
     /**
-     * YCbCr formats, used for video. These are not necessarily supported
-     * by the hardware.
+     * @deprecated use {@link android.graphics.ImageFormat#NV16 
+     * ImageFormat.NV16} instead.
      */
+    @Deprecated
     public static final int YCbCr_422_SP= 0x10;
 
-    /** YCbCr format used for images, which uses the NV21 encoding format.   
-     *  This is the default format for camera preview images, when not
-     *  otherwise set with 
-     *  {@link android.hardware.Camera.Parameters#setPreviewFormat(int)}.
+    /**
+     * @deprecated use {@link android.graphics.ImageFormat#NV21 
+     * ImageFormat.NV21} instead.
      */
+    @Deprecated
     public static final int YCbCr_420_SP= 0x11;
 
-    /** YCbCr format used for images, which uses YUYV (YUY2) encoding format.
-     *  This is an alternative format for camera preview images. Whether this
-     *  format is supported by the camera hardware can be determined by
-     *  {@link android.hardware.Camera.Parameters#getSupportedPreviewFormats()}.
+    /**
+     * @deprecated use {@link android.graphics.ImageFormat#YUY2 
+     * ImageFormat.YUY2} instead.
      */
+    @Deprecated
     public static final int YCbCr_422_I = 0x14;
 
     /**
-     * Encoded formats.  These are not necessarily supported by the hardware.
+     * @deprecated use {@link android.graphics.ImageFormat#JPEG 
+     * ImageFormat.JPEG} instead.
      */
+    @Deprecated
     public static final int JPEG        = 0x100;
 
     /*
diff --git a/graphics/java/android/graphics/YuvImage.java b/graphics/java/android/graphics/YuvImage.java
index 5a4531b..9368da6 100644
--- a/graphics/java/android/graphics/YuvImage.java
+++ b/graphics/java/android/graphics/YuvImage.java
@@ -22,7 +22,7 @@
  * YuvImage contains YUV data and provides a method that compresses a region of
  * the YUV data to a Jpeg. The YUV data should be provided as a single byte
  * array irrespective of the number of image planes in it.
- * Currently only PixelFormat.YCbCr_420_SP and PixelFormat.YCbCr_422_I are supported.
+ * Currently only ImageFormat.NV21 and ImageFormat.YUY2 are supported.
  *
  * To compress a rectangle region in the YUV data, users have to specify the
  * region by left, top, width and height.
@@ -77,11 +77,11 @@
      *                null.
      */
     public YuvImage(byte[] yuv, int format, int width, int height, int[] strides) {
-        if (format != PixelFormat.YCbCr_420_SP &&
-                format != PixelFormat.YCbCr_422_I) {
+        if (format != ImageFormat.NV21 &&
+                format != ImageFormat.YUY2) {
             throw new IllegalArgumentException(
-                    "only support PixelFormat.YCbCr_420_SP " +
-                    "and PixelFormat.YCbCr_422_I for now");
+                    "only support ImageFormat.NV21 " +
+                    "and ImageFormat.YUY2 for now");
         }
 
         if (width <= 0  || height <= 0) {
@@ -107,7 +107,7 @@
 
     /**
      * Compress a rectangle region in the YuvImage to a jpeg.
-     * Only PixelFormat.YCbCr_420_SP and PixelFormat.YCbCr_422_I
+     * Only ImageFormat.NV21 and ImageFormat.YUY2
      * are supported for now.
      *
      * @param rectangle The rectangle region to be compressed. The medthod checks if rectangle is
@@ -181,14 +181,14 @@
 
     int[] calculateOffsets(int left, int top) {
         int[] offsets = null;
-        if (mFormat == PixelFormat.YCbCr_420_SP) {
+        if (mFormat == ImageFormat.NV21) {
             offsets = new int[] {top * mStrides[0] + left,
                   mHeight * mStrides[0] + top / 2 * mStrides[1]
                   + left / 2 * 2 };
             return offsets;
         }
 
-        if (mFormat == PixelFormat.YCbCr_422_I) {
+        if (mFormat == ImageFormat.YUY2) {
             offsets = new int[] {top * mStrides[0] + left / 2 * 4};
             return offsets;
         }
@@ -198,12 +198,12 @@
 
     private int[] calculateStrides(int width, int format) {
         int[] strides = null;
-        if (format == PixelFormat.YCbCr_420_SP) {
+        if (format == ImageFormat.NV21) {
             strides = new int[] {width, width};
             return strides;
         }
 
-        if (format == PixelFormat.YCbCr_422_I) {
+        if (format == ImageFormat.YUY2) {
             strides = new int[] {width * 2};
             return strides;
         }
@@ -214,7 +214,7 @@
    private void adjustRectangle(Rect rect) {
        int width = rect.width();
        int height = rect.height();
-       if (mFormat == PixelFormat.YCbCr_420_SP) {
+       if (mFormat == ImageFormat.NV21) {
            // Make sure left, top, width and height are all even.
            width &= ~1;
            height &= ~1;
@@ -224,7 +224,7 @@
            rect.bottom = rect.top + height;
         }
 
-        if (mFormat == PixelFormat.YCbCr_422_I) {
+        if (mFormat == ImageFormat.YUY2) {
             // Make sure left and width are both even.
             width &= ~1;
             rect.left &= ~1;
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index b1d588e..b94df84 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -238,7 +238,10 @@
             final int count = sets.length;
             mStateListState.mStateSets = new int[count][];
             for (int i = 0; i < count; i++) {
-                mStateListState.mStateSets[i] = sets[i].clone();
+                final int[] set = sets[i];
+                if (set != null) {
+                    mStateListState.mStateSets[i] = set.clone();
+                }
             }
             mMutated = true;
         }
diff --git a/include/ui/Region.h b/include/ui/Region.h
index 2bcad5b..925fd06 100644
--- a/include/ui/Region.h
+++ b/include/ui/Region.h
@@ -21,7 +21,6 @@
 #include <sys/types.h>
 
 #include <utils/Vector.h>
-#include <binder/Parcel.h>
 
 #include <ui/Rect.h>
 
@@ -39,7 +38,6 @@
                         Region();
                         Region(const Region& rhs);
     explicit            Region(const Rect& rhs);
-    explicit            Region(const Parcel& parcel);
     explicit            Region(const void* buffer);
                         ~Region();
                         
@@ -118,10 +116,6 @@
             // be sorted in Y and X and must not make the region invalid.
             void        addRectUnchecked(int l, int t, int r, int b);
 
-            // flatten/unflatten a region to/from a Parcel
-            status_t    write(Parcel& parcel) const;
-            status_t    read(const Parcel& parcel);
-
             // flatten/unflatten a region to/from a raw buffer
             ssize_t     write(void* buffer, size_t size) const;
     static  ssize_t     writeEmpty(void* buffer, size_t size);
diff --git a/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp
index 207ad15..6288bc4 100644
--- a/libs/rs/rsElement.cpp
+++ b/libs/rs/rsElement.cpp
@@ -34,6 +34,12 @@
 
 Element::~Element()
 {
+    for (uint32_t ct = 0; ct < mRSC->mStateElement.mElements.size(); ct++) {
+        if (mRSC->mStateElement.mElements[ct] == this) {
+            mRSC->mStateElement.mElements.removeAt(ct);
+            break;
+        }
+    }
     clear();
 }
 
@@ -78,27 +84,62 @@
 }
 
 
-Element * Element::create(Context *rsc, RsDataType dt, RsDataKind dk,
+const Element * Element::create(Context *rsc, RsDataType dt, RsDataKind dk,
                             bool isNorm, uint32_t vecSize)
 {
+    // Look for an existing match.
+    for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) {
+        const Element *ee = rsc->mStateElement.mElements[ct];
+        if (!ee->getFieldCount() &&
+            (ee->getComponent().getType() == dt) &&
+            (ee->getComponent().getKind() == dk) &&
+            (ee->getComponent().getIsNormalized() == isNorm) &&
+            (ee->getComponent().getVectorSize() == vecSize)) {
+            // Match
+            ee->incUserRef();
+            return ee;
+        }
+    }
+
     Element *e = new Element(rsc);
     e->mComponent.set(dt, dk, isNorm, vecSize);
     e->mBits = e->mComponent.getBits();
+    rsc->mStateElement.mElements.push(e);
     return e;
 }
 
-Element * Element::create(Context *rsc, size_t count, const Element **ein,
+const Element * Element::create(Context *rsc, size_t count, const Element **ein,
                             const char **nin, const size_t * lengths)
 {
+    // Look for an existing match.
+    for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) {
+        const Element *ee = rsc->mStateElement.mElements[ct];
+        if (ee->getFieldCount() == count) {
+            bool match = true;
+            for (uint32_t i=0; i < count; i++) {
+                if ((ee->mFields[i].e.get() != ein[i]) ||
+                    (ee->mFields[i].name.length() != lengths[i]) ||
+                    (ee->mFields[i].name != nin[i])) {
+                    match = false;
+                    break;
+                }
+            }
+            if (match) {
+                ee->incUserRef();
+                return ee;
+            }
+        }
+    }
+
     Element *e = new Element(rsc);
     e->mFields = new ElementField_t [count];
     e->mFieldCount = count;
-
     for (size_t ct=0; ct < count; ct++) {
         e->mFields[ct].e.set(ein[ct]);
         e->mFields[ct].name.setTo(nin[ct], lengths[ct]);
     }
 
+    rsc->mStateElement.mElements.push(e);
     return e;
 }
 
@@ -168,6 +209,7 @@
 
 ElementState::~ElementState()
 {
+    rsAssert(!mElements.size());
 }
 
 
@@ -184,9 +226,9 @@
                             uint32_t vecSize)
 {
     //LOGE("rsi_ElementCreate %i %i %i %i", dt, dk, norm, vecSize);
-    Element *e = Element::create(rsc, dt, dk, norm, vecSize);
+    const Element *e = Element::create(rsc, dt, dk, norm, vecSize);
     e->incUserRef();
-    return e;
+    return (RsElement)e;
 }
 
 RsElement rsi_ElementCreate2(Context *rsc,
@@ -196,9 +238,9 @@
                              const size_t * nameLengths)
 {
     //LOGE("rsi_ElementCreate2 %i", count);
-    Element *e = Element::create(rsc, count, (const Element **)ein, names, nameLengths);
+    const Element *e = Element::create(rsc, count, (const Element **)ein, names, nameLengths);
     e->incUserRef();
-    return e;
+    return (RsElement)e;
 }
 
 
diff --git a/libs/rs/rsElement.h b/libs/rs/rsElement.h
index 777e8ee..02a1ca2 100644
--- a/libs/rs/rsElement.h
+++ b/libs/rs/rsElement.h
@@ -60,9 +60,9 @@
 
     void dumpLOGV(const char *prefix) const;
 
-    static Element * create(Context *rsc, RsDataType dt, RsDataKind dk,
+    static const Element * create(Context *rsc, RsDataType dt, RsDataKind dk,
                             bool isNorm, uint32_t vecSize);
-    static Element * create(Context *rsc, size_t count, const Element **,
+    static const Element * create(Context *rsc, size_t count, const Element **,
                             const char **, const size_t * lengths);
 
 protected:
@@ -89,6 +89,8 @@
     ElementState();
     ~ElementState();
 
+    // Cache of all existing elements.
+    Vector<const Element *> mElements;
 };
 
 
diff --git a/libs/rs/rsObjectBase.cpp b/libs/rs/rsObjectBase.cpp
index 89c5b00..677413e 100644
--- a/libs/rs/rsObjectBase.cpp
+++ b/libs/rs/rsObjectBase.cpp
@@ -191,6 +191,7 @@
     LOGV("Dumping all objects");
     const ObjectBase * o = rsc->mObjHead;
     while (o) {
+        LOGV(" Object %p", o);
         o->dumpLOGV("  ");
         o = o->mNext;
     }
diff --git a/libs/rs/rsObjectBase.h b/libs/rs/rsObjectBase.h
index f247022..bb03b87 100644
--- a/libs/rs/rsObjectBase.h
+++ b/libs/rs/rsObjectBase.h
@@ -56,6 +56,7 @@
 protected:
     const char *mAllocFile;
     uint32_t mAllocLine;
+    Context *mRSC;
 
 private:
     void add() const;
@@ -64,7 +65,6 @@
     bool checkDelete() const;
 
     char * mName;
-    Context *mRSC;
     mutable int32_t mSysRefCount;
     mutable int32_t mUserRefCount;
 
diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp
index 28f13d4..a2b2df4 100644
--- a/libs/rs/rsProgramVertex.cpp
+++ b/libs/rs/rsProgramVertex.cpp
@@ -364,7 +364,7 @@
 
 void ProgramVertexState::init(Context *rsc, int32_t w, int32_t h)
 {
-    RsElement e = Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1);
+    RsElement e = (RsElement) Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1);
 
     rsi_TypeBegin(rsc, e);
     rsi_TypeAdd(rsc, RS_DIMENSION_X, 48);
diff --git a/libs/rs/rsType.cpp b/libs/rs/rsType.cpp
index 22a267a..9d24c6c 100644
--- a/libs/rs/rsType.cpp
+++ b/libs/rs/rsType.cpp
@@ -31,6 +31,12 @@
 
 Type::~Type()
 {
+    for (uint32_t ct = 0; ct < mRSC->mStateType.mTypes.size(); ct++) {
+        if (mRSC->mStateType.mTypes[ct] == this) {
+            mRSC->mStateType.mTypes.removeAt(ct);
+            break;
+        }
+    }
     if (mLODs) {
         delete [] mLODs;
     }
@@ -341,6 +347,18 @@
 {
     TypeState * stc = &rsc->mStateType;
 
+    for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
+        Type *t = stc->mTypes[ct];
+        if (t->getElement() != stc->mElement.get()) continue;
+        if (t->getDimX() != stc->mX) continue;
+        if (t->getDimY() != stc->mY) continue;
+        if (t->getDimZ() != stc->mZ) continue;
+        if (t->getDimLOD() != stc->mLOD) continue;
+        if (t->getDimFaces() != stc->mFaces) continue;
+        t->incUserRef();
+        return t;
+    }
+
     Type * st = new Type(rsc);
     st->incUserRef();
     st->setDimX(stc->mX);
@@ -351,7 +369,7 @@
     st->setDimFaces(stc->mFaces);
     st->compute();
     stc->mElement.clear();
-
+    stc->mTypes.push(st);
     return st;
 }
 
diff --git a/libs/rs/rsType.h b/libs/rs/rsType.h
index 4fa4933..28e6274 100644
--- a/libs/rs/rsType.h
+++ b/libs/rs/rsType.h
@@ -137,6 +137,10 @@
     uint32_t mLOD;
     bool mFaces;
     ObjectBaseRef<const Element> mElement;
+
+
+    // Cache of all existing types.
+    Vector<Type *> mTypes;
 };
 
 
diff --git a/libs/surfaceflinger_client/LayerState.cpp b/libs/surfaceflinger_client/LayerState.cpp
index 114a9e9..01c4c7e 100644
--- a/libs/surfaceflinger_client/LayerState.cpp
+++ b/libs/surfaceflinger_client/LayerState.cpp
@@ -22,17 +22,37 @@
 
 status_t layer_state_t::write(Parcel& output) const
 {
+    status_t err;
+
+    size_t len = transparentRegion.write(NULL, 0);
+    err = output.writeInt32(len);
+    if (err < NO_ERROR) return err;
+
+    void* buf = output.writeInplace(len);
+    if (buf == NULL) return NO_MEMORY;
+
+    err = transparentRegion.write(buf, len);
+    if (err < NO_ERROR) return err;
+
+    // NOTE: regions are at the end of the structure
     size_t size = sizeof(layer_state_t);
-    transparentRegion.write(output);
     size -= sizeof(transparentRegion);
-    output.write(this, size);
-    return NO_ERROR;
+    err = output.write(this, size);
+    return err;
 }
 
 status_t layer_state_t::read(const Parcel& input)
 {
+    status_t err;
+    size_t len = input.readInt32();
+    void const* buf = input.readInplace(len);
+    if (buf == NULL) return NO_MEMORY;
+
+    err = transparentRegion.read(buf);
+    if (err < NO_ERROR) return err;
+
+    // NOTE: regions are at the end of the structure
     size_t size = sizeof(layer_state_t);
-    transparentRegion.read(input);
     size -= sizeof(transparentRegion);
     input.read(this, size);
     return NO_ERROR;
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index d21ed57..12db908 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -63,16 +63,10 @@
 {
 }
 
-Region::Region(const Parcel& parcel)
-{
-    status_t err = read(parcel);
-    LOGE_IF(err<0, "error %s reading Region from parcel", strerror(err));
-}
-
 Region::Region(const void* buffer)
 {
     status_t err = read(buffer);
-    LOGE_IF(err<0, "error %s reading Region from parcel", strerror(err));
+    LOGE_IF(err<0, "error %s reading Region from buffer", strerror(err));
 }
 
 Region::~Region()
@@ -532,37 +526,6 @@
 
 // ----------------------------------------------------------------------------
 
-status_t Region::write(Parcel& parcel) const
-{
-#if VALIDATE_REGIONS
-    validate(*this, "write(Parcel)");
-#endif
-    status_t err;
-    const size_t count = mStorage.size();
-    const size_t sizeNeeded = sizeof(int32_t) + (1+count)*sizeof(Rect);
-    void* buffer = parcel.writeInplace(sizeNeeded);
-    if (!buffer) return NO_MEMORY;
-    ssize_t written = Region::write(buffer, sizeNeeded);
-    if (written < 0) return status_t(written);
-    return NO_ERROR;
-}
-
-status_t Region::read(const Parcel& parcel)
-{
-    void const* buffer = parcel.readInplace(sizeof(int32_t));
-    if (!buffer) return NO_MEMORY;
-    const size_t count = *static_cast<int32_t const *>(buffer);
-    void const* dummy = parcel.readInplace((1+count)*sizeof(Rect));
-    if (!dummy) return NO_MEMORY;
-    const size_t sizeNeeded = sizeof(int32_t) + (1+count)*sizeof(Rect);
-    const ssize_t read = Region::read(buffer);
-    if (read < 0) return status_t(read);
-#if VALIDATE_REGIONS
-    validate(*this, "read(Parcel)");
-#endif
-    return NO_ERROR;
-}
-
 ssize_t Region::write(void* buffer, size_t size) const
 {
 #if VALIDATE_REGIONS
@@ -570,12 +533,14 @@
 #endif
     const size_t count = mStorage.size();
     const size_t sizeNeeded = sizeof(int32_t) + (1+count)*sizeof(Rect);
-    if (sizeNeeded > size) return NO_MEMORY;
-    int32_t* const p = static_cast<int32_t*>(buffer); 
-    *p = count;
-    memcpy(p+1, &mBounds, sizeof(Rect));
-    if (count) {
-        memcpy(p+5, mStorage.array(), count*sizeof(Rect));
+    if (buffer != NULL) {
+        if (sizeNeeded > size) return NO_MEMORY;
+        int32_t* const p = static_cast<int32_t*>(buffer);
+        *p = count;
+        memcpy(p+1, &mBounds, sizeof(Rect));
+        if (count) {
+            memcpy(p+5, mStorage.array(), count*sizeof(Rect));
+        }
     }
     return ssize_t(sizeNeeded);
 }
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 8c24ee1..2c0399e 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -59,8 +59,10 @@
 
     Location getLastKnownLocation(String provider);
 
-    /* used by location providers to tell the location manager when it has a new location */
-    void reportLocation(in Location location);
+    // Used by location providers to tell the location manager when it has a new location.
+    // Passive is true if the location is coming from the passive provider, in which case
+    // it need not be shared with other providers.
+    void reportLocation(in Location location, boolean passive);
 
     String getFromLocation(double latitude, double longitude, int maxResults,
         in GeocoderParams params, out List<Address> addrs);
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 9027fc2..da760a1 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -81,6 +81,19 @@
     public static final String GPS_PROVIDER = "gps";
 
     /**
+     * A special location provider for receiving locations without actually initiating
+     * a location fix. This provider can be used to passively receive location updates
+     * when other applications or services request them without actually requesting
+     * the locations yourself.  This provider will return locations generated by other
+     * providers.  You can query the {@link Location#getProvider()} method to determine
+     * the origin of the location update.
+     *
+     * Requires the permission android.permission.ACCESS_FINE_LOCATION, although if the GPS
+     * is not enabled this provider might only return coarse fixes.
+     */
+    public static final String PASSIVE_PROVIDER = "passive";
+
+    /**
      * Key used for the Bundle extra holding a boolean indicating whether
      * a proximity alert is entering (true) or exiting (false)..
      */
diff --git a/location/java/android/location/LocationProvider.java b/location/java/android/location/LocationProvider.java
index 3faba58..bb3e2a5 100644
--- a/location/java/android/location/LocationProvider.java
+++ b/location/java/android/location/LocationProvider.java
@@ -71,6 +71,10 @@
      * false otherwise.
      */
     public boolean meetsCriteria(Criteria criteria) {
+        // We do not want to match the special passive provider based on criteria.
+        if (LocationManager.PASSIVE_PROVIDER.equals(mName)) {
+            return false;
+        }
         if ((criteria.getAccuracy() != Criteria.NO_REQUIREMENT) && 
             (criteria.getAccuracy() < getAccuracy())) {
             return false;
diff --git a/location/java/android/location/provider/LocationProvider.java b/location/java/android/location/provider/LocationProvider.java
index 0d028c0..4163def 100644
--- a/location/java/android/location/provider/LocationProvider.java
+++ b/location/java/android/location/provider/LocationProvider.java
@@ -156,7 +156,7 @@
      */
     public void reportLocation(Location location) {
         try {
-            mLocationManager.reportLocation(location);
+            mLocationManager.reportLocation(location, false);
         } catch (RemoteException e) {
             Log.e(TAG, "RemoteException in reportLocation: ", e);
         }
diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java
index dce3b27..8e84106 100755
--- a/location/java/com/android/internal/location/GpsLocationProvider.java
+++ b/location/java/com/android/internal/location/GpsLocationProvider.java
@@ -863,7 +863,7 @@
             }
 
             try {
-                mLocationManager.reportLocation(mLocation);
+                mLocationManager.reportLocation(mLocation, false);
             } catch (RemoteException e) {
                 Log.e(TAG, "RemoteException calling reportLocation");
             }
diff --git a/location/java/com/android/internal/location/MockProvider.java b/location/java/com/android/internal/location/MockProvider.java
index 2f6fdee..bc1893e 100644
--- a/location/java/com/android/internal/location/MockProvider.java
+++ b/location/java/com/android/internal/location/MockProvider.java
@@ -143,7 +143,7 @@
         mLocation.set(l);
         mHasLocation = true;
         try {
-            mLocationManager.reportLocation(mLocation);
+            mLocationManager.reportLocation(mLocation, false);
         } catch (RemoteException e) {
             Log.e(TAG, "RemoteException calling reportLocation");
         }
diff --git a/location/java/com/android/internal/location/PassiveProvider.java b/location/java/com/android/internal/location/PassiveProvider.java
new file mode 100644
index 0000000..7eb711d
--- /dev/null
+++ b/location/java/com/android/internal/location/PassiveProvider.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.location;
+
+import android.location.ILocationManager;
+import android.location.Location;
+import android.location.LocationManager;
+import android.location.LocationProvider;
+import android.location.LocationProviderInterface;
+import android.net.NetworkInfo;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * A passive location provider reports locations received from other providers
+ * for clients that want to listen passively without actually triggering
+ * location updates.
+ *
+ * {@hide}
+ */
+public class PassiveProvider implements LocationProviderInterface {
+
+    private static final String TAG = "PassiveProvider";
+
+    private final ILocationManager mLocationManager;
+    private boolean mTracking;
+
+    public PassiveProvider(ILocationManager locationManager) {
+        mLocationManager = locationManager;
+    }
+
+    public String getName() {
+        return LocationManager.PASSIVE_PROVIDER;
+    }
+
+    public boolean requiresNetwork() {
+        return false;
+    }
+
+    public boolean requiresSatellite() {
+        return false;
+    }
+
+    public boolean requiresCell() {
+        return false;
+    }
+
+    public boolean hasMonetaryCost() {
+        return false;
+    }
+
+    public boolean supportsAltitude() {
+        return false;
+    }
+
+    public boolean supportsSpeed() {
+        return false;
+    }
+
+    public boolean supportsBearing() {
+        return false;
+    }
+
+    public int getPowerRequirement() {
+        return -1;
+    }
+
+    public int getAccuracy() {
+        return -1;
+    }
+
+    public boolean isEnabled() {
+        return true;
+    }
+
+    public void enable() {
+    }
+
+    public void disable() {
+    }
+
+    public int getStatus(Bundle extras) {
+        if (mTracking) {
+            return LocationProvider.AVAILABLE;
+        } else {
+            return LocationProvider.TEMPORARILY_UNAVAILABLE;
+        }
+    }
+
+    public long getStatusUpdateTime() {
+        return -1;
+    }
+
+    public void enableLocationTracking(boolean enable) {
+        mTracking = enable;
+    }
+
+    public void setMinTime(long minTime) {
+    }
+
+    public void updateNetworkState(int state, NetworkInfo info) {
+    }
+
+    public void updateLocation(Location location) {
+        if (mTracking) {
+            try {
+                // pass the location back to the location manager
+                mLocationManager.reportLocation(location, true);
+            } catch (RemoteException e) {
+                Log.e(TAG, "RemoteException calling reportLocation");
+            }
+        }
+    }
+
+    public boolean sendExtraCommand(String command, Bundle extras) {
+        return false;
+    }
+
+    public void addListener(int uid) {
+    }
+
+    public void removeListener(int uid) {
+    }
+}
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 34252ab..1f02608 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -500,22 +500,6 @@
             doScanFile(path, mimeType, lastModified, fileSize, false);
         }
 
-        private boolean isMetadataSupported(int fileType) {
-            if (mFileType == MediaFile.FILE_TYPE_MP3 ||
-                    mFileType == MediaFile.FILE_TYPE_MP4 ||
-                    mFileType == MediaFile.FILE_TYPE_M4A ||
-                    mFileType == MediaFile.FILE_TYPE_3GPP ||
-                    mFileType == MediaFile.FILE_TYPE_3GPP2 ||
-                    mFileType == MediaFile.FILE_TYPE_OGG ||
-                    mFileType == MediaFile.FILE_TYPE_AAC ||
-                    mFileType == MediaFile.FILE_TYPE_MID ||
-                    mFileType == MediaFile.FILE_TYPE_WMA) {
-                // we only extract metadata from MP3, M4A, OGG, MID, AAC and WMA files.
-                // check MP4 files, to determine if they contain only audio.
-                return true;
-            }
-            return false;
-        }
         public Uri doScanFile(String path, String mimeType, long lastModified, long fileSize, boolean scanAlways) {
             Uri result = null;
 //            long t1 = System.currentTimeMillis();
@@ -531,10 +515,8 @@
                     boolean music = (lowpath.indexOf(MUSIC_DIR) > 0) ||
                         (!ringtones && !notifications && !alarms && !podcasts);
 
-                    if( isMetadataSupported(mFileType) ) {
+                    if (!MediaFile.isImageFileType(mFileType)) {
                         processFile(path, mimeType, this);
-                    } else if (MediaFile.isImageFileType(mFileType)) {
-                        // we used to compute the width and height but it's not worth it
                     }
 
                     result = endFile(entry, ringtones, notifications, alarms, music, podcasts);
diff --git a/media/libmedia/MediaScanner.cpp b/media/libmedia/MediaScanner.cpp
index f201667..43762e7 100644
--- a/media/libmedia/MediaScanner.cpp
+++ b/media/libmedia/MediaScanner.cpp
@@ -58,7 +58,7 @@
 
     int pathRemaining = PATH_MAX - pathLength;
     strcpy(pathBuffer, path);
-    if (pathBuffer[pathLength - 1] != '/') {
+    if (pathLength > 0 && pathBuffer[pathLength - 1]) {
         pathBuffer[pathLength] = '/';
         pathBuffer[pathLength + 1] = 0;
         --pathRemaining;
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index b4fc035..50dad33 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1614,6 +1614,8 @@
     size_t actualSize = (*me->mCallback)(
             me, buffer->raw, buffer->size, me->mCallbackCookie);
 
+    buffer->size = actualSize;
+
     if (actualSize > 0) {
         me->snoopWrite(buffer->raw, actualSize);
     }
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index 12d7ee2..7997cd6 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -99,13 +99,13 @@
                     : AudioSystem::CHANNEL_OUT_MONO,
                 8192, 0, &AudioCallback, this, 0);
 
-        if (mAudioTrack->initCheck() != OK) {
+        if ((err = mAudioTrack->initCheck()) != OK) {
             delete mAudioTrack;
             mAudioTrack = NULL;
 
             mSource->stop();
 
-            return mAudioTrack->initCheck();
+            return err;
         }
 
         mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 1c9f4fd..b3a73b0 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -178,7 +178,8 @@
 }
 
 AwesomePlayer::AwesomePlayer()
-    : mTimeSource(NULL),
+    : mQueueStarted(false),
+      mTimeSource(NULL),
       mVideoRendererIsPreview(false),
       mAudioPlayer(NULL),
       mFlags(0),
@@ -201,13 +202,13 @@
 
     mAudioStatusEventPending = false;
 
-    mQueue.start();
-
     reset();
 }
 
 AwesomePlayer::~AwesomePlayer() {
-    mQueue.stop();
+    if (mQueueStarted) {
+        mQueue.stop();
+    }
 
     reset();
 
@@ -401,6 +402,9 @@
 
 void AwesomePlayer::onBufferingUpdate() {
     Mutex::Autolock autoLock(mLock);
+    if (!mBufferingEventPending) {
+        return;
+    }
     mBufferingEventPending = false;
 
     if (mDurationUs >= 0) {
@@ -425,6 +429,9 @@
     // Posted whenever any stream finishes playing.
 
     Mutex::Autolock autoLock(mLock);
+    if (!mStreamDoneEventPending) {
+        return;
+    }
     mStreamDoneEventPending = false;
 
     if (mFlags & LOOPING) {
@@ -437,6 +444,8 @@
         notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
 
         pause_l();
+
+        mFlags |= AT_EOS;
     }
 }
 
@@ -511,6 +520,12 @@
 
     postBufferingEvent_l();
 
+    if (mFlags & AT_EOS) {
+        // Legacy behaviour, if a stream finishes playing and then
+        // is started again, we play from the start...
+        seekTo_l(0);
+    }
+
     return OK;
 }
 
@@ -645,6 +660,7 @@
 status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
     mSeeking = true;
     mSeekTimeUs = timeUs;
+    mFlags &= ~AT_EOS;
 
     seekAudioIfNecessary_l();
 
@@ -918,6 +934,12 @@
 
 void AwesomePlayer::onCheckAudioStatus() {
     Mutex::Autolock autoLock(mLock);
+    if (!mAudioStatusEventPending) {
+        // Event was dispatched and while we were blocking on the mutex,
+        // has already been cancelled.
+        return;
+    }
+
     mAudioStatusEventPending = false;
 
     if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
@@ -977,6 +999,11 @@
         return UNKNOWN_ERROR;  // async prepare already pending
     }
 
+    if (!mQueueStarted) {
+        mQueue.start();
+        mQueueStarted = true;
+    }
+
     mFlags |= PREPARING;
     mAsyncPrepareEvent = new AwesomeEvent(
             this, &AwesomePlayer::onPrepareAsyncEvent);
@@ -1077,7 +1104,7 @@
     state->mUriHeaders = mUriHeaders;
     state->mFileSource = mFileSource;
 
-    state->mFlags = mFlags & (PLAYING | LOOPING);
+    state->mFlags = mFlags & (PLAYING | LOOPING | AT_EOS);
     getPosition_l(&state->mPositionUs);
 
     if (mLastVideoBuffer) {
@@ -1138,7 +1165,7 @@
 
     seekTo_l(state->mPositionUs);
 
-    mFlags = state->mFlags & LOOPING;
+    mFlags = state->mFlags & (LOOPING | AT_EOS);
 
     if (state->mLastVideoFrame && mISurface != NULL) {
         mVideoRenderer =
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 75b7b6f..6cf7cff 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -102,7 +102,6 @@
     { MEDIA_MIMETYPE_IMAGE_JPEG, "OMX.TI.JPEG.decode" },
     { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.TI.MP3.decode" },
     { MEDIA_MIMETYPE_AUDIO_MPEG, "MP3Decoder" },
-    { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.decode" },
     { MEDIA_MIMETYPE_AUDIO_AMR_NB, "AMRNBDecoder" },
     { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.decode" },
     { MEDIA_MIMETYPE_AUDIO_AMR_WB, "AMRWBDecoder" },
diff --git a/media/libstagefright/Prefetcher.cpp b/media/libstagefright/Prefetcher.cpp
index 76ca77b..363e121 100644
--- a/media/libstagefright/Prefetcher.cpp
+++ b/media/libstagefright/Prefetcher.cpp
@@ -337,24 +337,20 @@
 void PrefetchedSource::cacheMore() {
     MediaSource::ReadOptions options;
 
-    {
-        Mutex::Autolock autoLock(mLock);
+    Mutex::Autolock autoLock(mLock);
 
-        if (!mStarted) {
-            return;
-        }
+    if (!mStarted) {
+        return;
+    }
 
-        if (mSeekTimeUs >= 0) {
-            options.setSeekTo(mSeekTimeUs);
-            mSeekTimeUs = -1;
-        }
+    if (mSeekTimeUs >= 0) {
+        options.setSeekTo(mSeekTimeUs);
+        mSeekTimeUs = -1;
     }
 
     MediaBuffer *buffer;
     status_t err = mSource->read(&buffer, &options);
 
-    Mutex::Autolock autoLock(mLock);
-
     if (err != OK) {
         mReachedEOS = true;
         mCondition.signal();
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 114d4c6..ce8eeae 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -92,12 +92,14 @@
         FIRST_FRAME = 4,
         PREPARING   = 8,
         PREPARED    = 16,
+        AT_EOS      = 32,
     };
 
     mutable Mutex mLock;
 
     OMXClient mClient;
     TimedEventQueue mQueue;
+    bool mQueueStarted;
     wp<MediaPlayerBase> mListener;
 
     sp<ISurface> mISurface;
diff --git a/services/java/com/android/server/AccessibilityManagerService.java b/services/java/com/android/server/AccessibilityManagerService.java
index 407983d..477ea0c 100644
--- a/services/java/com/android/server/AccessibilityManagerService.java
+++ b/services/java/com/android/server/AccessibilityManagerService.java
@@ -16,8 +16,6 @@
 
 package com.android.server;
 
-import static android.util.Config.LOGV;
-
 import com.android.internal.os.HandlerCaller;
 import com.android.internal.os.HandlerCaller.SomeArgs;
 
@@ -47,6 +45,7 @@
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.text.TextUtils.SimpleStringSplitter;
+import android.util.Config;
 import android.util.Log;
 import android.util.SparseArray;
 import android.view.accessibility.AccessibilityEvent;
@@ -137,10 +136,6 @@
 
         registerPackageChangeAndBootCompletedBroadcastReceiver();
         registerSettingsContentObservers();
-
-        synchronized (mLock) {
-            populateAccessibilityServiceListLocked();
-        }
     }
 
     /**
@@ -155,13 +150,19 @@
             public void onReceive(Context context, Intent intent) {
                 synchronized (mLock) {
                     populateAccessibilityServiceListLocked();
-                    manageServicesLocked();
 
                     if (intent.getAction() == Intent.ACTION_BOOT_COMPLETED) {
+                        // get the accessibility enabled setting on boot
                         mIsEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
                                 Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1;
-                        updateClientsLocked();
+
+                        // if accessibility is enabled inform our clients we are on
+                        if (mIsEnabled) {
+                            updateClientsLocked();
+                        }
                     }
+
+                    manageServicesLocked();
                 }
             }
         };
@@ -169,7 +170,6 @@
         // package changes
         IntentFilter packageFilter = new IntentFilter();
         packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
-        packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
         packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
         packageFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
         packageFilter.addDataScheme("package");
@@ -409,7 +409,7 @@
 
         try {
             listener.onAccessibilityEvent(event);
-            if (LOGV) {
+            if (Config.DEBUG) {
                 Log.i(LOG_TAG, "Event " + event + " sent to " + listener);
             }
         } catch (RemoteException re) {
@@ -434,7 +434,7 @@
         mServices.remove(service);
         mHandler.removeMessages(service.mId);
 
-        if (LOGV) {
+        if (Config.DEBUG) {
             Log.i(LOG_TAG, "Dead service " + service.mService + " removed");
         }
 
@@ -547,6 +547,7 @@
 
         Map<ComponentName, Service> componentNameToServiceMap = mComponentNameToServiceMap;
         List<Service> services = mServices;
+        boolean isEnabled = mIsEnabled;
 
         for (int i = 0, count = installedServices.size(); i < count; i++) {
             ServiceInfo intalledService = installedServices.get(i);
@@ -554,7 +555,7 @@
                     intalledService.name);
             Service service = componentNameToServiceMap.get(componentName);
 
-            if (enabledServices.contains(componentName)) {
+            if (isEnabled && enabledServices.contains(componentName)) {
                 if (service == null) {
                     new Service(componentName).bind();
                 }
@@ -578,6 +579,7 @@
             } catch (RemoteException re) {
                 mClients.remove(i);
                 count--;
+                i--;
             }
         }
     }
diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java
index b566fb7e..4791718 100644
--- a/services/java/com/android/server/DockObserver.java
+++ b/services/java/com/android/server/DockObserver.java
@@ -22,8 +22,10 @@
 import android.app.IActivityManager;
 import android.app.IUiModeManager;
 import android.app.KeyguardManager;
-import android.app.StatusBarManager;
+import android.app.Notification;
+import android.app.NotificationManager;
 import android.app.PendingIntent;
+import android.app.StatusBarManager;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.content.ActivityNotFoundException;
@@ -55,6 +57,8 @@
 import android.text.format.Time;
 import android.util.Log;
 
+import com.android.internal.R;
+import com.android.internal.app.DisableCarModeActivity;
 import com.android.internal.widget.LockPatternUtils;
 
 import java.io.FileNotFoundException;
@@ -101,6 +105,7 @@
     private final Context mContext;
 
     private PowerManagerService mPowerManager;
+    private NotificationManager mNotificationManager;
 
     private KeyguardManager.KeyguardLock mKeyguardLock;
     private boolean mKeyguardDisabled;
@@ -125,7 +130,8 @@
 
             // Launch a dock activity
             String category;
-            if (mCarModeEnabled || mDockState == Intent.EXTRA_DOCK_STATE_CAR) {
+            if (mCarModeEnabled) {
+                // Only launch car home when car mode is enabled.
                 category = Intent.CATEGORY_CAR_DOCK;
             } else if (mDockState == Intent.EXTRA_DOCK_STATE_DESK) {
                 category = Intent.CATEGORY_DESK_DOCK;
@@ -332,9 +338,13 @@
                         if (mCarModeEnabled && mDockState != Intent.EXTRA_DOCK_STATE_CAR) {
                             // Pretend to be in DOCK_STATE_CAR.
                             intent.putExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_CAR);
+                        } else if (!mCarModeEnabled && mDockState == Intent.EXTRA_DOCK_STATE_CAR) {
+                            // Pretend to be in DOCK_STATE_UNDOCKED.
+                            intent.putExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED);
                         } else {
                             intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState);
                         }
+                        intent.putExtra(Intent.EXTRA_PHYSICAL_DOCK_STATE, mDockState);
                         intent.putExtra(Intent.EXTRA_CAR_MODE_ENABLED, mCarModeEnabled);
 
                         // Check if this is Bluetooth Dock
@@ -462,6 +472,52 @@
         }
     };
 
+    private void adjustStatusBarCarMode() {
+        if (mStatusBarManager == null) {
+            mStatusBarManager = (StatusBarManager) mContext.getSystemService(Context.STATUS_BAR_SERVICE);
+        }
+
+        // Fear not: StatusBarService manages a list of requests to disable
+        // features of the status bar; these are ORed together to form the
+        // active disabled list. So if (for example) the device is locked and
+        // the status bar should be totally disabled, the calls below will
+        // have no effect until the device is unlocked.
+        if (mStatusBarManager != null) {
+            long ident = Binder.clearCallingIdentity();
+            mStatusBarManager.disable(mCarModeEnabled
+                ? StatusBarManager.DISABLE_NOTIFICATION_TICKER
+                : StatusBarManager.DISABLE_NONE);
+            Binder.restoreCallingIdentity(ident);
+        }
+
+        if (mNotificationManager == null) {
+            mNotificationManager = (NotificationManager)
+                    mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+        }
+
+        if (mNotificationManager != null) {
+            long ident = Binder.clearCallingIdentity();
+            if (mCarModeEnabled) {
+                Intent carModeOffIntent = new Intent(mContext, DisableCarModeActivity.class);
+
+                Notification n = new Notification();
+                n.icon = R.drawable.stat_notify_car_mode;
+                n.defaults = Notification.DEFAULT_LIGHTS;
+                n.flags = Notification.FLAG_ONGOING_EVENT;
+                n.when = 0;
+                n.setLatestEventInfo(
+                        mContext,
+                        mContext.getString(R.string.car_mode_disable_notification_title),
+                        mContext.getString(R.string.car_mode_disable_notification_message),
+                        PendingIntent.getActivity(mContext, 0, carModeOffIntent, 0));
+                mNotificationManager.notify(0, n);
+            } else {
+                mNotificationManager.cancel(0);
+            }
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
     private void setCarMode(boolean enabled) throws RemoteException {
         mCarModeEnabled = enabled;
         if (enabled) {
@@ -475,23 +531,7 @@
             setMode(Configuration.UI_MODE_TYPE_NORMAL,
                     Configuration.UI_MODE_NIGHT_UNDEFINED);
         }
-
-        if (mStatusBarManager == null) {
-            mStatusBarManager = (StatusBarManager) mContext.getSystemService(Context.STATUS_BAR_SERVICE);
-        }
-
-        // Fear not: StatusBarService manages a list of requests to disable
-        // features of the status bar; these are ORed together to form the
-        // active disabled list. So if (for example) the device is locked and
-        // the status bar should be totally disabled, the calls below will
-        // have no effect until the device is unlocked.
-        if (mStatusBarManager != null) {
-            long ident = Binder.clearCallingIdentity();
-            mStatusBarManager.disable(enabled 
-                ? StatusBarManager.DISABLE_NOTIFICATION_TICKER
-                : StatusBarManager.DISABLE_NONE);
-            Binder.restoreCallingIdentity(ident);
-        }
+        adjustStatusBarCarMode();
     }
 
     private void setMode(int modeType, int modeNight) throws RemoteException {
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index e12f2e1..004fcf13 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -71,6 +71,7 @@
 import com.android.internal.location.GpsNetInitiatedHandler;
 import com.android.internal.location.LocationProviderProxy;
 import com.android.internal.location.MockProvider;
+import com.android.internal.location.PassiveProvider;
 
 /**
  * The service class that manages LocationProviders and issues location
@@ -452,6 +453,11 @@
             mGpsLocationProvider = gpsProvider;
         }
 
+        // create a passive location provider, which is always enabled
+        PassiveProvider passiveProvider = new PassiveProvider(this);
+        addProvider(passiveProvider);
+        mEnabledProviders.add(passiveProvider.getName());
+
         // initialize external network location and geocoder services
         Resources resources = mContext.getResources();
         String serviceName = resources.getString(
@@ -538,7 +544,8 @@
     }
 
     private void checkPermissionsSafe(String provider) {
-        if (LocationManager.GPS_PROVIDER.equals(provider)
+        if ((LocationManager.GPS_PROVIDER.equals(provider)
+                 || LocationManager.PASSIVE_PROVIDER.equals(provider))
             && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
                 != PackageManager.PERMISSION_GRANTED)) {
             throw new SecurityException("Requires ACCESS_FINE_LOCATION permission");
@@ -554,7 +561,8 @@
     }
 
     private boolean isAllowedProviderSafe(String provider) {
-        if (LocationManager.GPS_PROVIDER.equals(provider)
+        if ((LocationManager.GPS_PROVIDER.equals(provider)
+                || LocationManager.PASSIVE_PROVIDER.equals(provider))
             && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
                 != PackageManager.PERMISSION_GRANTED)) {
             return false;
@@ -1343,7 +1351,7 @@
         }
     }
 
-    public void reportLocation(Location location) {
+    public void reportLocation(Location location, boolean passive) {
         if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
                 != PackageManager.PERMISSION_GRANTED) {
             throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission");
@@ -1351,6 +1359,7 @@
 
         mLocationHandler.removeMessages(MESSAGE_LOCATION_CHANGED, location);
         Message m = Message.obtain(mLocationHandler, MESSAGE_LOCATION_CHANGED, location);
+        m.arg1 = (passive ? 1 : 0);
         mLocationHandler.sendMessageAtFrontOfQueue(m);
     }
 
@@ -1415,8 +1424,8 @@
         return true;
     }
 
-    private void handleLocationChangedLocked(Location location) {
-        String provider = location.getProvider();
+    private void handleLocationChangedLocked(Location location, boolean passive) {
+        String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
         ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
         if (records == null || records.size() == 0) {
             return;
@@ -1502,17 +1511,20 @@
                     synchronized (mLock) {
                         Location location = (Location) msg.obj;
                         String provider = location.getProvider();
+                        boolean passive = (msg.arg1 == 1);
 
-                        // notify other providers of the new location
-                        for (int i = mProviders.size() - 1; i >= 0; i--) {
-                            LocationProviderInterface p = mProviders.get(i);
-                            if (!provider.equals(p.getName())) {
-                                p.updateLocation(location);
+                        if (!passive) {
+                            // notify other providers of the new location
+                            for (int i = mProviders.size() - 1; i >= 0; i--) {
+                                LocationProviderInterface p = mProviders.get(i);
+                                if (!provider.equals(p.getName())) {
+                                    p.updateLocation(location);
+                                }
                             }
                         }
 
                         if (isAllowedBySettingsLocked(provider)) {
-                            handleLocationChangedLocked(location);
+                            handleLocationChangedLocked(location, passive);
                         }
                     }
                 }
@@ -1687,6 +1699,10 @@
         boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
         checkMockPermissionsSafe();
 
+        if (LocationManager.PASSIVE_PROVIDER.equals(name)) {
+            throw new IllegalArgumentException("Cannot mock the passive location provider");
+        }
+
         long identity = Binder.clearCallingIdentity();
         synchronized (mLock) {
             MockProvider provider = new MockProvider(name, this,
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 4e2ffa4..2a78806 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -97,7 +97,7 @@
         public static final int OpFailedMediaBlank             = 402;
         public static final int OpFailedMediaCorrupt           = 403;
         public static final int OpFailedVolNotMounted          = 404;
-        public static final int OpFailedVolBusy                = 405;
+        public static final int OpFailedStorageBusy            = 405;
 
         /*
          * 600 series - Unsolicited broadcasts.
@@ -142,13 +142,31 @@
             if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
                 mBooted = true;
 
-                String path = Environment.getExternalStorageDirectory().getPath();
-                if (getVolumeState(path).equals(Environment.MEDIA_UNMOUNTED)) {
-                    int rc = doMountVolume(path);
-                    if (rc != StorageResultCode.OperationSucceeded) {
-                        Log.e(TAG, String.format("Boot-time mount failed (%d)", rc));
-                    }
+                /*
+                 * In the simulator, we need to broadcast a volume mounted event
+                 * to make the media scanner run.
+                 */
+                if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
+                    notifyVolumeStateChange(null, "/sdcard", VolumeState.NoMedia, VolumeState.Mounted);
+                    return;
                 }
+                new Thread() {
+                    public void run() {
+                        try {
+                            String path = Environment.getExternalStorageDirectory().getPath();
+                            if (getVolumeState(
+                                    Environment.getExternalStorageDirectory().getPath()).equals(
+                                            Environment.MEDIA_UNMOUNTED)) {
+                                int rc = doMountVolume(path);
+                                if (rc != StorageResultCode.OperationSucceeded) {
+                                    Log.e(TAG, String.format("Boot-time mount failed (%d)", rc));
+                                }
+                            }
+                        } catch (Exception ex) {
+                            Log.e(TAG, "Boot-time mount exception", ex);
+                        }
+                    }
+                }.start();
             }
         }
     };
@@ -184,7 +202,7 @@
         String vs = getVolumeState(path);
         if (enable && vs.equals(Environment.MEDIA_MOUNTED)) {
             mUmsEnabling = enable; // Override for isUsbMassStorageEnabled()
-            int rc = doUnmountVolume(path);
+            int rc = doUnmountVolume(path, false);
             mUmsEnabling = false; // Clear override
             if (rc != StorageResultCode.OperationSucceeded) {
                 Log.e(TAG, String.format("Failed to unmount before enabling UMS (%d)", rc));
@@ -527,7 +545,7 @@
         return rc;
     }
 
-    private int doUnmountVolume(String path) {
+    private int doUnmountVolume(String path, boolean force) {
         if (!getVolumeState(path).equals(Environment.MEDIA_MOUNTED)) {
             return VoldResponseCode.OpFailedVolNotMounted;
         }
@@ -537,7 +555,8 @@
         // notified that the applications installed on the media will be killed.
         mPms.updateExternalMediaStatus(false);
         try {
-            mConnector.doCommand(String.format("volume unmount %s", path));
+            mConnector.doCommand(String.format(
+                    "volume unmount %s%s", path, (force ? " force" : "")));
             return StorageResultCode.OperationSucceeded;
         } catch (NativeDaemonConnectorException e) {
             // Don't worry about mismatch in PackageManager since the
@@ -545,6 +564,8 @@
             int code = e.getCode();
             if (code == VoldResponseCode.OpFailedVolNotMounted) {
                 return StorageResultCode.OperationFailedStorageNotMounted;
+            } else if (code == VoldResponseCode.OpFailedStorageBusy) {
+                return StorageResultCode.OperationFailedStorageBusy;
             } else {
                 return StorageResultCode.OperationFailedInternalError;
             }
@@ -639,15 +660,6 @@
     public MountService(Context context) {
         mContext = context;
 
-        /*
-         * Vold does not run in the simulator, so fake out a mounted
-         * event to trigger MediaScanner
-         */
-        if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
-            updatePublicVolumeState("/sdcard", Environment.MEDIA_MOUNTED);
-            return;
-        }
-
         // XXX: This will go away soon in favor of IMountServiceObserver
         mPms = (PackageManagerService) ServiceManager.getService("package");
 
@@ -656,6 +668,16 @@
 
         mListeners = new ArrayList<MountServiceBinderListener>();
 
+        /*
+         * Vold does not run in the simulator, so pretend the connector thread
+         * ran and did its thing.
+         */
+        if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
+            mReady = true;
+            mUmsEnabling = true;
+            return;
+        }
+
         mConnector = new NativeDaemonConnector(this, "vold", 10, "VoldConnector");
         mReady = false;
         Thread thread = new Thread(mConnector, NativeDaemonConnector.class.getName());
@@ -733,7 +755,7 @@
             /*
              * If the media is mounted, then gracefully unmount it.
              */
-            if (doUnmountVolume(path) != StorageResultCode.OperationSucceeded) {
+            if (doUnmountVolume(path, true) != StorageResultCode.OperationSucceeded) {
                 Log.e(TAG, "Failed to unmount media for shutdown");
             }
         }
@@ -782,11 +804,11 @@
         return doMountVolume(path);
     }
 
-    public int unmountVolume(String path) {
+    public int unmountVolume(String path, boolean force) {
         validatePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
         waitForReady();
 
-        return doUnmountVolume(path);
+        return doUnmountVolume(path, force);
     }
 
     public int formatVolume(String path) {
@@ -878,16 +900,21 @@
         return rc;
     }
 
-    public int destroySecureContainer(String id) {
+    public int destroySecureContainer(String id, boolean force) {
         validatePermission(android.Manifest.permission.ASEC_DESTROY);
         waitForReady();
         warnOnNotMounted();
 
         int rc = StorageResultCode.OperationSucceeded;
         try {
-            mConnector.doCommand(String.format("asec destroy %s", id));
+            mConnector.doCommand(String.format("asec destroy %s%s", id, (force ? " force" : "")));
         } catch (NativeDaemonConnectorException e) {
-            rc = StorageResultCode.OperationFailedInternalError;
+            int code = e.getCode();
+            if (code == VoldResponseCode.OpFailedStorageBusy) {
+                rc = StorageResultCode.OperationFailedStorageBusy;
+            } else {
+                rc = StorageResultCode.OperationFailedInternalError;
+            }
         }
 
         if (rc == StorageResultCode.OperationSucceeded) {
@@ -928,7 +955,7 @@
         return rc;
     }
 
-    public int unmountSecureContainer(String id) {
+    public int unmountSecureContainer(String id, boolean force) {
         validatePermission(android.Manifest.permission.ASEC_MOUNT_UNMOUNT);
         waitForReady();
         warnOnNotMounted();
@@ -940,11 +967,16 @@
          }
 
         int rc = StorageResultCode.OperationSucceeded;
-        String cmd = String.format("asec unmount %s", id);
+        String cmd = String.format("asec unmount %s%s", id, (force ? " force" : ""));
         try {
             mConnector.doCommand(cmd);
         } catch (NativeDaemonConnectorException e) {
-            rc = StorageResultCode.OperationFailedInternalError;
+            int code = e.getCode();
+            if (code == VoldResponseCode.OpFailedStorageBusy) {
+                rc = StorageResultCode.OperationFailedStorageBusy;
+            } else {
+                rc = StorageResultCode.OperationFailedInternalError;
+            }
         }
 
         if (rc == StorageResultCode.OperationSucceeded) {
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index d41aacf..958d089 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -28,6 +28,7 @@
 import android.net.INetworkManagementEventObserver;
 import android.os.INetworkManagementService;
 import android.os.Handler;
+import android.os.SystemProperties;
 import android.text.TextUtils;
 import android.util.Log;
 import java.util.ArrayList;
@@ -59,6 +60,10 @@
         public static final int TetherStatusResult        = 210;
         public static final int IpFwdStatusResult         = 211;
         public static final int InterfaceGetCfgResult     = 213;
+        public static final int SoftapStatusResult        = 214;
+        public static final int UsbRNDISStatusResult      = 215;
+
+        public static final int InterfaceChange           = 600;
     }
 
     /**
@@ -83,6 +88,10 @@
 
         mObservers = new ArrayList<INetworkManagementEventObserver>();
 
+        if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
+            return;
+        }
+
         mConnector = new NativeDaemonConnector(
                 new NetdCallbackReceiver(), "netd", 10, "NetdConnector");
         Thread thread = new Thread(mConnector, NativeDaemonConnector.class.getName());
@@ -147,12 +156,35 @@
         public void onDaemonConnected() {
             new Thread() {
                 public void run() {
-                    // XXX: Run some tests
                 }
             }.start();
         }
         public boolean onEvent(int code, String raw, String[] cooked) {
-           return false;
+            if (code == NetdResponseCode.InterfaceChange) {
+                /*
+                 * a network interface change occured
+                 * Format: "NNN Iface added <name>"
+                 *         "NNN Iface removed <name>"
+                 *         "NNN Iface changed <name> <up/down>"
+                 */
+                if (cooked.length < 4 || !cooked[1].equals("Iface")) {
+                    throw new IllegalStateException(
+                            String.format("Invalid event from daemon (%s)", raw));
+                }
+                if (cooked[2].equals("added")) {
+                    notifyInterfaceAdded(cooked[3]);
+                    return true;
+                } else if (cooked[2].equals("removed")) {
+                    notifyInterfaceRemoved(cooked[3]);
+                    return true;
+                } else if (cooked[2].equals("changed") && cooked.length == 5) {
+                    notifyInterfaceLinkStatusChanged(cooked[3], cooked[4].equals("up"));
+                    return true;
+                }
+                throw new IllegalStateException(
+                        String.format("Invalid event from daemon (%s)", raw));
+            }
+            return false;
         }
     }
 
@@ -393,4 +425,35 @@
                 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
         mConnector.doCommand(String.format("pppd detach %s", tty));
     }
+
+    public void startUsbRNDIS() throws IllegalStateException {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
+        mConnector.doCommand("usb startrndis");
+    }
+
+    public void stopUsbRNDIS() throws IllegalStateException {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
+        mConnector.doCommand("usb stoprndis");
+    }
+
+    public boolean isUsbRNDISStarted() throws IllegalStateException {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
+        ArrayList<String> rsp = mConnector.doCommand("usb rndisstatus");
+
+        for (String line : rsp) {
+            String []tok = line.split(" ");
+            int code = Integer.parseInt(tok[0]);
+            if (code == NetdResponseCode.UsbRNDISStatusResult) {
+                if (tok[2].equals("started"))
+                    return true;
+                return false;
+            } else {
+                throw new IllegalStateException(String.format("Unexpected response code %d", code));
+            }
+        }
+        throw new IllegalStateException("Got an empty response");
+    }
 }
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 7fcf900..a481036 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -373,10 +373,15 @@
     boolean mLayoutNeeded = true;
     boolean mAnimationPending = false;
     boolean mDisplayFrozen = false;
+    boolean mWaitingForConfig = false;
     boolean mWindowsFreezingScreen = false;
     long mFreezeGcPending = 0;
     int mAppsFreezingScreen = 0;
 
+    int mLayoutSeq = 0;
+    
+    Configuration mCurConfiguration = new Configuration();
+    
     // This is held as long as we have the screen frozen, to give us time to
     // perform a rotation animation when turning off shows the lock screen which
     // changes the orientation.
@@ -1828,7 +1833,7 @@
             }
 
             if (attrs.type >= FIRST_SUB_WINDOW && attrs.type <= LAST_SUB_WINDOW) {
-                attachedWindow = windowForClientLocked(null, attrs.token);
+                attachedWindow = windowForClientLocked(null, attrs.token, false);
                 if (attachedWindow == null) {
                     Log.w(TAG, "Attempted to add window with token that is not a window: "
                           + attrs.token + ".  Aborting.");
@@ -1988,6 +1993,10 @@
             if (localLOGV) Log.v(
                 TAG, "New client " + client.asBinder()
                 + ": window=" + win);
+            
+            if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked()) {
+                reportNewConfig = true;
+            }
         }
 
         // sendNewConfiguration() checks caller permissions so we must call it with
@@ -1997,14 +2006,6 @@
         final long origId = Binder.clearCallingIdentity();
         if (reportNewConfig) {
             sendNewConfiguration();
-        } else {
-            // Update Orientation after adding a window, only if the window needs to be
-            // displayed right away
-            if (win.isVisibleOrAdding()) {
-                if (updateOrientationFromAppTokensUnchecked(null, null) != null) {
-                    sendNewConfiguration();
-                }
-            }
         }
         Binder.restoreCallingIdentity(origId);
 
@@ -2013,7 +2014,7 @@
 
     public void removeWindow(Session session, IWindow client) {
         synchronized(mWindowMap) {
-            WindowState win = windowForClientLocked(session, client);
+            WindowState win = windowForClientLocked(session, client, false);
             if (win == null) {
                 return;
             }
@@ -2081,8 +2082,9 @@
         // Removing a visible window will effect the computed orientation
         // So just update orientation if needed.
         if (wasVisible && computeForcedAppOrientationLocked()
-                != mForcedAppOrientation) {
-            mH.sendMessage(mH.obtainMessage(H.COMPUTE_AND_SEND_NEW_CONFIGURATION));
+                != mForcedAppOrientation
+                && updateOrientationFromAppTokensLocked()) {
+            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
         }
         updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
         Binder.restoreCallingIdentity(origId);
@@ -2177,7 +2179,7 @@
         long origId = Binder.clearCallingIdentity();
         try {
             synchronized (mWindowMap) {
-                WindowState w = windowForClientLocked(session, client);
+                WindowState w = windowForClientLocked(session, client, false);
                 if ((w != null) && (w.mSurface != null)) {
                     if (SHOW_TRANSACTIONS) Log.i(TAG, ">>> OPEN TRANSACTION");
                     Surface.openTransaction();
@@ -2203,7 +2205,7 @@
         long origId = Binder.clearCallingIdentity();
         try {
             synchronized (mWindowMap) {
-                WindowState w = windowForClientLocked(session, client);
+                WindowState w = windowForClientLocked(session, client, false);
                 if (w != null) {
                     w.mGivenInsetsPending = false;
                     w.mGivenContentInsets.set(contentInsets);
@@ -2221,7 +2223,7 @@
     public void getWindowDisplayFrame(Session session, IWindow client,
             Rect outDisplayFrame) {
         synchronized(mWindowMap) {
-            WindowState win = windowForClientLocked(session, client);
+            WindowState win = windowForClientLocked(session, client, false);
             if (win == null) {
                 outDisplayFrame.setEmpty();
                 return;
@@ -2291,11 +2293,11 @@
             Surface outSurface) {
         boolean displayed = false;
         boolean inTouchMode;
-        Configuration newConfig = null;
+        boolean configChanged;
         long origId = Binder.clearCallingIdentity();
 
         synchronized(mWindowMap) {
-            WindowState win = windowForClientLocked(session, client);
+            WindowState win = windowForClientLocked(session, client, false);
             if (win == null) {
                 return 0;
             }
@@ -2507,7 +2509,7 @@
             if (assignLayers) {
                 assignLayersLocked();
             }
-            newConfig = updateOrientationFromAppTokensLocked(null, null);
+            configChanged = updateOrientationFromAppTokensLocked();
             performLayoutAndPlaceSurfacesLocked();
             if (displayed && win.mIsWallpaper) {
                 updateWallpaperOffsetLocked(win, mDisplay.getWidth(),
@@ -2533,7 +2535,7 @@
             inTouchMode = mInTouchMode;
         }
 
-        if (newConfig != null) {
+        if (configChanged) {
             sendNewConfiguration();
         }
 
@@ -2546,7 +2548,7 @@
     public void finishDrawingWindow(Session session, IWindow client) {
         final long origId = Binder.clearCallingIdentity();
         synchronized(mWindowMap) {
-            WindowState win = windowForClientLocked(session, client);
+            WindowState win = windowForClientLocked(session, client, false);
             if (win != null && win.finishDrawingLocked()) {
                 if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
                     adjustWallpaperWindowsLocked();
@@ -2988,62 +2990,62 @@
     }
 
     public int getOrientationFromAppTokensLocked() {
-            int pos = mAppTokens.size() - 1;
-            int curGroup = 0;
-            int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-            boolean findingBehind = false;
-            boolean haveGroup = false;
-            boolean lastFullscreen = false;
-            while (pos >= 0) {
-                AppWindowToken wtoken = mAppTokens.get(pos);
-                pos--;
-                // if we're about to tear down this window and not seek for
-                // the behind activity, don't use it for orientation
-                if (!findingBehind
-                        && (!wtoken.hidden && wtoken.hiddenRequested)) {
+        int pos = mAppTokens.size() - 1;
+        int curGroup = 0;
+        int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+        boolean findingBehind = false;
+        boolean haveGroup = false;
+        boolean lastFullscreen = false;
+        while (pos >= 0) {
+            AppWindowToken wtoken = mAppTokens.get(pos);
+            pos--;
+            // if we're about to tear down this window and not seek for
+            // the behind activity, don't use it for orientation
+            if (!findingBehind
+                    && (!wtoken.hidden && wtoken.hiddenRequested)) {
+                continue;
+            }
+
+            if (!haveGroup) {
+                // We ignore any hidden applications on the top.
+                if (wtoken.hiddenRequested || wtoken.willBeHidden) {
                     continue;
                 }
-
-                if (!haveGroup) {
-                    // We ignore any hidden applications on the top.
-                    if (wtoken.hiddenRequested || wtoken.willBeHidden) {
-                        continue;
-                    }
-                    haveGroup = true;
-                    curGroup = wtoken.groupId;
-                    lastOrientation = wtoken.requestedOrientation;
-                } else if (curGroup != wtoken.groupId) {
-                    // If we have hit a new application group, and the bottom
-                    // of the previous group didn't explicitly say to use
-                    // the orientation behind it, and the last app was
-                    // full screen, then we'll stick with the
-                    // user's orientation.
-                    if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
-                            && lastFullscreen) {
-                        return lastOrientation;
-                    }
+                haveGroup = true;
+                curGroup = wtoken.groupId;
+                lastOrientation = wtoken.requestedOrientation;
+            } else if (curGroup != wtoken.groupId) {
+                // If we have hit a new application group, and the bottom
+                // of the previous group didn't explicitly say to use
+                // the orientation behind it, and the last app was
+                // full screen, then we'll stick with the
+                // user's orientation.
+                if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
+                        && lastFullscreen) {
+                    return lastOrientation;
                 }
-                int or = wtoken.requestedOrientation;
-                // If this application is fullscreen, and didn't explicitly say
-                // to use the orientation behind it, then just take whatever
-                // orientation it has and ignores whatever is under it.
-                lastFullscreen = wtoken.appFullscreen;
-                if (lastFullscreen
-                        && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
-                    return or;
-                }
-                // If this application has requested an explicit orientation,
-                // then use it.
-                if (or == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE ||
-                        or == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ||
-                        or == ActivityInfo.SCREEN_ORIENTATION_SENSOR ||
-                        or == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR ||
-                        or == ActivityInfo.SCREEN_ORIENTATION_USER) {
-                    return or;
-                }
-                findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
             }
-            return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+            int or = wtoken.requestedOrientation;
+            // If this application is fullscreen, and didn't explicitly say
+            // to use the orientation behind it, then just take whatever
+            // orientation it has and ignores whatever is under it.
+            lastFullscreen = wtoken.appFullscreen;
+            if (lastFullscreen
+                    && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
+                return or;
+            }
+            // If this application has requested an explicit orientation,
+            // then use it.
+            if (or == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE ||
+                    or == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ||
+                    or == ActivityInfo.SCREEN_ORIENTATION_SENSOR ||
+                    or == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR ||
+                    or == ActivityInfo.SCREEN_ORIENTATION_USER) {
+                return or;
+            }
+            findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
+        }
+        return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
     }
 
     public Configuration updateOrientationFromAppTokens(
@@ -3053,81 +3055,75 @@
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
-        Configuration config;
+        Configuration config = null;
         long ident = Binder.clearCallingIdentity();
-        config = updateOrientationFromAppTokensUnchecked(currentConfig,
-                freezeThisOneIfNeeded);
+        
+        synchronized(mWindowMap) {
+            if (updateOrientationFromAppTokensLocked()) {
+                if (freezeThisOneIfNeeded != null) {
+                    AppWindowToken wtoken = findAppWindowToken(
+                            freezeThisOneIfNeeded);
+                    if (wtoken != null) {
+                        startAppFreezingScreenLocked(wtoken,
+                                ActivityInfo.CONFIG_ORIENTATION);
+                    }
+                }
+                config = computeNewConfigurationLocked();
+                
+            } else if (currentConfig != null) {
+                // No obvious action we need to take, but if our current
+                // state mismatches the activity maanager's, update it
+                mTempConfiguration.setToDefaults();
+                if (computeNewConfigurationLocked(mTempConfiguration)) {
+                    if (currentConfig.diff(mTempConfiguration) != 0) {
+                        mWaitingForConfig = true;
+                        mLayoutNeeded = true;
+                        startFreezingDisplayLocked();
+                        config = new Configuration(mTempConfiguration);
+                    }
+                }
+            }
+        }
+        
         Binder.restoreCallingIdentity(ident);
         return config;
     }
 
-    Configuration updateOrientationFromAppTokensUnchecked(
-            Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
-        Configuration config;
-        synchronized(mWindowMap) {
-            config = updateOrientationFromAppTokensLocked(currentConfig, freezeThisOneIfNeeded);
-            if (config != null) {
-                mLayoutNeeded = true;
-                performLayoutAndPlaceSurfacesLocked();
-            }
-        }
-        return config;
-    }
-
     /*
+     * Determine the new desired orientation of the display, returning
+     * a non-null new Configuration if it has changed from the current
+     * orientation.  IF TRUE IS RETURNED SOMEONE MUST CALL
+     * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE
+     * SCREEN.  This will typically be done for you if you call
+     * sendNewConfiguration().
+     * 
      * The orientation is computed from non-application windows first. If none of
      * the non-application windows specify orientation, the orientation is computed from
      * application tokens.
      * @see android.view.IWindowManager#updateOrientationFromAppTokens(
      * android.os.IBinder)
      */
-    Configuration updateOrientationFromAppTokensLocked(
-            Configuration appConfig, IBinder freezeThisOneIfNeeded) {
+    boolean updateOrientationFromAppTokensLocked() {
         boolean changed = false;
         long ident = Binder.clearCallingIdentity();
         try {
             int req = computeForcedAppOrientationLocked();
 
             if (req != mForcedAppOrientation) {
-                changed = true;
                 mForcedAppOrientation = req;
                 //send a message to Policy indicating orientation change to take
                 //action like disabling/enabling sensors etc.,
                 mPolicy.setCurrentOrientationLw(req);
-            }
-
-            if (changed) {
-                changed = setRotationUncheckedLocked(
-                        WindowManagerPolicy.USE_LAST_ROTATION,
-                        mLastRotationFlags & (~Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE));
-                if (changed) {
-                    if (freezeThisOneIfNeeded != null) {
-                        AppWindowToken wtoken = findAppWindowToken(
-                                freezeThisOneIfNeeded);
-                        if (wtoken != null) {
-                            startAppFreezingScreenLocked(wtoken,
-                                    ActivityInfo.CONFIG_ORIENTATION);
-                        }
-                    }
-                    return computeNewConfigurationLocked();
+                if (setRotationUncheckedLocked(WindowManagerPolicy.USE_LAST_ROTATION,
+                        mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE)) {
+                    changed = true;
                 }
             }
 
-            // No obvious action we need to take, but if our current
-            // state mismatches the activity maanager's, update it
-            if (appConfig != null) {
-                mTempConfiguration.setToDefaults();
-                if (computeNewConfigurationLocked(mTempConfiguration)) {
-                    if (appConfig.diff(mTempConfiguration) != 0) {
-                        return new Configuration(mTempConfiguration);
-                    }
-                }
-            }
+            return changed;
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
-
-        return null;
     }
 
     int computeForcedAppOrientationLocked() {
@@ -3138,6 +3134,19 @@
         return req;
     }
 
+    public void setNewConfiguration(Configuration config) {
+        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
+                "setNewConfiguration()")) {
+            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
+        }
+
+        synchronized(mWindowMap) {
+            mCurConfiguration = new Configuration(config);
+            mWaitingForConfig = false;
+            performLayoutAndPlaceSurfacesLocked();
+        }
+    }
+    
     public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "setAppOrientation()")) {
@@ -3648,9 +3657,7 @@
                     mLayoutNeeded = true;
                     performLayoutAndPlaceSurfacesLocked();
                 }
-                if (mAppsFreezingScreen == 0 && !mWindowsFreezingScreen) {
-                    stopFreezingDisplayLocked();
-                }
+                stopFreezingDisplayLocked();
             }
         }
     }
@@ -4403,20 +4410,21 @@
             changed = setRotationUncheckedLocked(rotation, animFlags);
         }
 
-        if (changed) {
-            sendNewConfiguration();
-            synchronized(mWindowMap) {
-                mLayoutNeeded = true;
-                performLayoutAndPlaceSurfacesLocked();
-            }
-        } else if (alwaysSendConfiguration) {
-            //update configuration ignoring orientation change
+        if (changed || alwaysSendConfiguration) {
             sendNewConfiguration();
         }
 
         Binder.restoreCallingIdentity(origId);
     }
 
+    /**
+     * Apply a new rotation to the screen, respecting the requests of
+     * applications.  Use WindowManagerPolicy.USE_LAST_ROTATION to simply
+     * re-evaluate the desired rotation.
+     * 
+     * Returns null if the rotation has been changed.  In this case YOU
+     * MUST CALL setNewConfiguration() TO UNFREEZE THE SCREEN.
+     */
     public boolean setRotationUncheckedLocked(int rotation, int animFlags) {
         boolean changed;
         if (rotation == WindowManagerPolicy.USE_LAST_ROTATION) {
@@ -4442,6 +4450,8 @@
             mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
             mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT),
                     2000);
+            mWaitingForConfig = true;
+            mLayoutNeeded = true;
             startFreezingDisplayLocked();
             Log.i(TAG, "Setting rotation to " + rotation + ", animFlags=" + animFlags);
             mQueue.setOrientation(rotation);
@@ -6707,7 +6717,8 @@
                 long ident = Binder.clearCallingIdentity();
                 try {
                     return mPolicy.performHapticFeedbackLw(
-                            windowForClientLocked(this, window), effectId, always);
+                            windowForClientLocked(this, window, true),
+                            effectId, always);
                 } finally {
                     Binder.restoreCallingIdentity(ident);
                 }
@@ -6718,7 +6729,8 @@
             synchronized(mWindowMap) {
                 long ident = Binder.clearCallingIdentity();
                 try {
-                    setWindowWallpaperPositionLocked(windowForClientLocked(this, window),
+                    setWindowWallpaperPositionLocked(
+                            windowForClientLocked(this, window, true),
                             x, y, xStep, yStep);
                 } finally {
                     Binder.restoreCallingIdentity(ident);
@@ -6736,7 +6748,7 @@
                 long ident = Binder.clearCallingIdentity();
                 try {
                     return sendWindowWallpaperCommandLocked(
-                            windowForClientLocked(this, window),
+                            windowForClientLocked(this, window, true),
                             action, x, y, z, extras, sync);
                 } finally {
                     Binder.restoreCallingIdentity(ident);
@@ -6852,6 +6864,10 @@
 
         WindowState mNextOutsideTouch;
 
+        int mLayoutSeq = -1;
+        
+        Configuration mConfiguration = null;
+        
         // Actual frame shown on-screen (may be modified by animation)
         final Rect mShownFrame = new Rect();
         final Rect mLastShownFrame = new Rect();
@@ -7980,7 +7996,7 @@
             public void binderDied() {
                 try {
                     synchronized(mWindowMap) {
-                        WindowState win = windowForClientLocked(mSession, mClient);
+                        WindowState win = windowForClientLocked(mSession, mClient, false);
                         Log.i(TAG, "WIN DEATH: " + win);
                         if (win != null) {
                             removeWindowLocked(mSession, win);
@@ -8056,8 +8072,6 @@
         }
 
         void dump(PrintWriter pw, String prefix) {
-            StringBuilder sb = new StringBuilder(64);
-
             pw.print(prefix); pw.print("mSession="); pw.print(mSession);
                     pw.print(" mClient="); pw.println(mClient.asBinder());
             pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
@@ -8105,7 +8119,8 @@
                 pw.print(prefix); pw.print("mRelayoutCalled="); pw.println(mRelayoutCalled);
             }
             pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
-                    pw.print(" h="); pw.println(mRequestedHeight);
+                    pw.print(" h="); pw.print(mRequestedHeight);
+                    pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
             if (mXOffset != 0 || mYOffset != 0) {
                 pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
                         pw.print(" y="); pw.println(mYOffset);
@@ -8119,6 +8134,7 @@
                 pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
                         pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
             }
+            pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
             pw.print(prefix); pw.print("mShownFrame=");
                     mShownFrame.printShortString(pw);
                     pw.print(" last="); mLastShownFrame.printShortString(pw);
@@ -8693,7 +8709,7 @@
         public static final int FORCE_GC = 15;
         public static final int ENABLE_SCREEN = 16;
         public static final int APP_FREEZE_TIMEOUT = 17;
-        public static final int COMPUTE_AND_SEND_NEW_CONFIGURATION = 18;
+        public static final int SEND_NEW_CONFIGURATION = 18;
 
         private Session mLastReportedHold;
 
@@ -9019,10 +9035,9 @@
                     break;
                 }
 
-                case COMPUTE_AND_SEND_NEW_CONFIGURATION: {
-                    if (updateOrientationFromAppTokensUnchecked(null, null) != null) {
-                        sendNewConfiguration();
-                    }
+                case SEND_NEW_CONFIGURATION: {
+                    removeMessages(SEND_NEW_CONFIGURATION);
+                    sendNewConfiguration();
                     break;
                 }
 
@@ -9064,23 +9079,33 @@
     // Internals
     // -------------------------------------------------------------
 
-    final WindowState windowForClientLocked(Session session, IWindow client) {
-        return windowForClientLocked(session, client.asBinder());
+    final WindowState windowForClientLocked(Session session, IWindow client,
+            boolean throwOnError) {
+        return windowForClientLocked(session, client.asBinder(), throwOnError);
     }
 
-    final WindowState windowForClientLocked(Session session, IBinder client) {
+    final WindowState windowForClientLocked(Session session, IBinder client,
+            boolean throwOnError) {
         WindowState win = mWindowMap.get(client);
         if (localLOGV) Log.v(
             TAG, "Looking up client " + client + ": " + win);
         if (win == null) {
-            RuntimeException ex = new RuntimeException();
-            Log.w(TAG, "Requested window " + client + " does not exist", ex);
+            RuntimeException ex = new IllegalArgumentException(
+                    "Requested window " + client + " does not exist");
+            if (throwOnError) {
+                throw ex;
+            }
+            Log.w(TAG, "Failed looking up window", ex);
             return null;
         }
         if (session != null && win.mSession != session) {
-            RuntimeException ex = new RuntimeException();
-            Log.w(TAG, "Requested window " + client + " is in session " +
-                  win.mSession + ", not " + session, ex);
+            RuntimeException ex = new IllegalArgumentException(
+                    "Requested window " + client + " is in session " +
+                    win.mSession + ", not " + session);
+            if (throwOnError) {
+                throw ex;
+            }
+            Log.w(TAG, "Failed looking up window", ex);
             return null;
         }
 
@@ -9183,6 +9208,13 @@
             return;
         }
 
+        if (mWaitingForConfig) {
+            // Our configuration has changed (most likely rotation), but we
+            // don't yet have the complete configuration to report to
+            // applications.  Don't do any window layout until we have it.
+            return;
+        }
+        
         boolean recoveringMemory = false;
         if (mForceRemoves != null) {
             recoveringMemory = true;
@@ -9249,6 +9281,10 @@
         while (mLayoutNeeded) {
             mPolicy.beginLayoutLw(dw, dh);
 
+            int seq = mLayoutSeq+1;
+            if (seq < 0) seq = 0;
+            mLayoutSeq = seq;
+            
             // First perform layout of any root windows (not attached
             // to another window).
             int topAttached = -1;
@@ -9266,7 +9302,7 @@
                         || win.mAttachedHidden
                         || win.mExiting || win.mDestroying;
 
-                if (win.mLayoutAttached) {
+                if (!win.mLayoutAttached) {
                     if (DEBUG_LAYOUT) Log.v(TAG, "First pass " + win
                             + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
                             + " mLayoutAttached=" + win.mLayoutAttached);
@@ -9286,6 +9322,7 @@
                 if (!gone || !win.mHaveFrame) {
                     if (!win.mLayoutAttached) {
                         mPolicy.layoutWindowLw(win, win.mAttrs, null);
+                        win.mLayoutSeq = seq;
                         if (DEBUG_LAYOUT) Log.v(TAG, "-> mFrame="
                                 + win.mFrame + " mContainingFrame="
                                 + win.mContainingFrame + " mDisplayFrame="
@@ -9316,6 +9353,7 @@
                     if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
                             || !win.mHaveFrame) {
                         mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
+                        win.mLayoutSeq = seq;
                         if (DEBUG_LAYOUT) Log.v(TAG, "-> mFrame="
                                 + win.mFrame + " mContainingFrame="
                                 + win.mContainingFrame + " mDisplayFrame="
@@ -9336,11 +9374,8 @@
                 Log.w(TAG, "Layout repeat aborted after too many iterations");
                 mLayoutNeeded = false;
                 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
-                    Configuration newConfig = updateOrientationFromAppTokensLocked(
-                            null, null);
-                    if (newConfig != null) {
-                        mLayoutNeeded = true;
-                        mH.sendEmptyMessage(H.COMPUTE_AND_SEND_NEW_CONFIGURATION);
+                    if (updateOrientationFromAppTokensLocked()) {
+                        mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
                     }
                 }
             } else {
@@ -9349,10 +9384,8 @@
                 repeats++;
                 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
                     if (DEBUG_LAYOUT) Log.v(TAG, "Computing new config from layout");
-                    Configuration newConfig = updateOrientationFromAppTokensLocked(
-                            null, null);
-                    if (newConfig != null) {
-                        mH.sendEmptyMessage(H.COMPUTE_AND_SEND_NEW_CONFIGURATION);
+                    if (updateOrientationFromAppTokensLocked()) {
+                        mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
                     }
                 }
             }
@@ -9996,14 +10029,22 @@
                             }
                         }
                     }
-                    if (!w.mAppFreezing) {
+                    if (!w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) {
                         w.mContentInsetsChanged =
                             !w.mLastContentInsets.equals(w.mContentInsets);
                         w.mVisibleInsetsChanged =
                             !w.mLastVisibleInsets.equals(w.mVisibleInsets);
+                        boolean configChanged =
+                            w.mConfiguration != mCurConfiguration
+                            && (w.mConfiguration == null
+                                    || mCurConfiguration.diff(w.mConfiguration) != 0);
+                        if (localLOGV) Log.v(TAG, "Resizing " + w
+                                + ": configChanged=" + configChanged
+                                + " last=" + w.mLastFrame + " frame=" + w.mFrame);
                         if (!w.mLastFrame.equals(w.mFrame)
                                 || w.mContentInsetsChanged
-                                || w.mVisibleInsetsChanged) {
+                                || w.mVisibleInsetsChanged
+                                || configChanged) {
                             w.mLastFrame.set(w.mFrame);
                             w.mLastContentInsets.set(w.mContentInsets);
                             w.mLastVisibleInsets.set(w.mVisibleInsets);
@@ -10014,7 +10055,7 @@
                                 if (DEBUG_ORIENTATION) Log.v(TAG,
                                         "Resizing while display frozen: " + w);
                                 w.mOrientationChanging = true;
-                                if (mWindowsFreezingScreen) {
+                                if (!mWindowsFreezingScreen) {
                                     mWindowsFreezingScreen = true;
                                     // XXX should probably keep timeout from
                                     // when we first froze the display.
@@ -10327,9 +10368,7 @@
                 mWindowsFreezingScreen = false;
                 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
             }
-            if (mAppsFreezingScreen == 0) {
-                stopFreezingDisplayLocked();
-            }
+            stopFreezingDisplayLocked();
         }
 
         i = mResizingWindows.size();
@@ -10340,9 +10379,20 @@
                 try {
                     if (DEBUG_ORIENTATION) Log.v(TAG, "Reporting new frame to "
                             + win + ": " + win.mFrame);
+                    boolean configChanged =
+                        win.mConfiguration != mCurConfiguration
+                        && (win.mConfiguration == null
+                                || mCurConfiguration.diff(win.mConfiguration) != 0);
+                    win.mConfiguration = mCurConfiguration;
+                    if (DEBUG_ORIENTATION && configChanged) {
+                        Log.i(TAG, "Sending new config to window " + win + ": "
+                                + win.mFrame.width() + "x" + win.mFrame.height()
+                                + " / " + win.mConfiguration);
+                    }
                     win.mClient.resized(win.mFrame.width(),
                             win.mFrame.height(), win.mLastContentInsets,
-                            win.mLastVisibleInsets, win.mDrawPending);
+                            win.mLastVisibleInsets, win.mDrawPending,
+                            configChanged ? win.mConfiguration : null);
                     win.mContentInsetsChanged = false;
                     win.mVisibleInsetsChanged = false;
                 } catch (RemoteException e) {
@@ -10732,6 +10782,10 @@
             return;
         }
 
+        if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen) {
+            return;
+        }
+        
         mDisplayFrozen = false;
         mH.removeMessages(H.APP_FREEZE_TIMEOUT);
         if (PROFILE_ORIENTATION) {
@@ -10921,7 +10975,9 @@
                 pw.print("  mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
                 pw.print("  mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
             }
-            pw.print("  mInTouchMode="); pw.println(mInTouchMode);
+            pw.print("  mCurConfiguration="); pw.println(this.mCurConfiguration);
+            pw.print("  mInTouchMode="); pw.print(mInTouchMode);
+                    pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
             pw.print("  mSystemBooted="); pw.print(mSystemBooted);
                     pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
             pw.print("  mLayoutNeeded="); pw.print(mLayoutNeeded);
@@ -10939,7 +10995,8 @@
                     pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
             pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
                     pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen);
-                    pw.print(" mAppsFreezingScreen="); pw.println(mAppsFreezingScreen);
+                    pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen);
+                    pw.print(" mWaitingForConfig="); pw.println(mWaitingForConfig);
             pw.print("  mRotation="); pw.print(mRotation);
                     pw.print(", mForcedAppOrientation="); pw.print(mForcedAppOrientation);
                     pw.print(", mRequestedRotation="); pw.println(mRequestedRotation);
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 3ecfd8a..45c3f00 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -766,6 +766,12 @@
     Configuration mConfiguration = new Configuration();
 
     /**
+     * Current sequencing integer of the configuration, for skipping old
+     * configurations.
+     */
+    int mConfigurationSeq = 0;
+    
+    /**
      * Hardware-reported OpenGLES version.
      */
     final int GL_ES_VERSION;
@@ -2662,20 +2668,6 @@
                         mConfiguration,
                         next.mayFreezeScreenLocked(next.app) ? next : null);
                 if (config != null) {
-                    /*
-                     * Explicitly restore the locale to the one from the
-                     * old configuration, since the one that comes back from
-                     * the window manager has the default (boot) locale.
-                     *
-                     * It looks like previously the locale picker only worked
-                     * by coincidence: usually it would do its setting of
-                     * the locale after the activity transition, so it didn't
-                     * matter that this lost it.  With the synchronized
-                     * block now keeping them from happening at the same time,
-                     * this one always would happen second and undo what the
-                     * locale picker had just done.
-                     */
-                    config.locale = mConfiguration.locale;
                     next.frozenBeforeDestroy = true;
                 }
                 updated = updateConfigurationLocked(config, next);
@@ -4638,11 +4630,12 @@
         if (activity != null && activity.shortComponentName != null) {
             info.append(" (").append(activity.shortComponentName).append(")");
         }
+        info.append("\n");
         if (annotation != null) {
-            info.append("\nReason: ").append(annotation).append("\n");
+            info.append("Reason: ").append(annotation).append("\n");
         }
         if (parent != null && parent != activity) {
-            info.append("\nParent: ").append(parent.shortComponentName);
+            info.append("Parent: ").append(parent.shortComponentName).append("\n");
         }
 
         String cpuInfo = null;
@@ -8346,7 +8339,9 @@
             mAlwaysFinishActivities = alwaysFinishActivities;
             // This happens before any activities are started, so we can
             // change mConfiguration in-place.
+            mConfiguration.locale = Locale.getDefault();
             mConfiguration.updateFrom(configuration);
+            mConfigurationSeq = mConfiguration.seq = 1;
             if (DEBUG_CONFIGURATION) Log.v(TAG, "Initial config: " + mConfiguration);
         }
     }
@@ -13089,6 +13084,11 @@
                                      values.userSetLocale);
                 }
 
+                mConfigurationSeq++;
+                if (mConfigurationSeq <= 0) {
+                    mConfigurationSeq = 1;
+                }
+                newConfig.seq = mConfigurationSeq;
                 mConfiguration = newConfig;
                 Log.i(TAG, "Config changed: " + newConfig);
                 
@@ -13145,6 +13145,10 @@
             }
         }
         
+        if (values != null && mWindowManager != null) {
+            mWindowManager.setNewConfiguration(mConfiguration);
+        }
+        
         return kept;
     }
 
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 89761a8..2f2cc32 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -29,6 +29,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.util.Log;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -267,6 +268,9 @@
                         int[] outId = new int[1];
                         inm.enqueueNotification(localPackageName, localForegroundId,
                                 localForegroundNoti, outId);
+                    } catch (RuntimeException e) {
+                        Log.w(ActivityManagerService.TAG, "Error showing notification for service",
+                            e);
                     } catch (RemoteException e) {
                     }
                 }
@@ -288,6 +292,9 @@
                     }
                     try {
                         inm.cancelNotification(localPackageName, localForegroundId);
+                    } catch (RuntimeException e) {
+                        Log.w(ActivityManagerService.TAG, "Error canceling notification for"
+                            + " service", e);
                     } catch (RemoteException e) {
                     }
                 }
diff --git a/services/java/com/android/server/status/StatusBarService.java b/services/java/com/android/server/status/StatusBarService.java
index c7c3335..dab8b72 100644
--- a/services/java/com/android/server/status/StatusBarService.java
+++ b/services/java/com/android/server/status/StatusBarService.java
@@ -972,7 +972,7 @@
             return;
         }
 
-        prepareTracking(0);
+        prepareTracking(0, true);
         performFling(0, 2000.0f, true);
     }
     
@@ -980,7 +980,9 @@
         if (SPEW) {
             Log.d(TAG, "animateCollapse(): mExpanded=" + mExpanded
                     + " mExpandedVisible=" + mExpandedVisible
+                    + " mExpanded=" + mExpanded
                     + " mAnimating=" + mAnimating
+                    + " mAnimY=" + mAnimY
                     + " mAnimVel=" + mAnimVel);
         }
         
@@ -988,12 +990,16 @@
             return;
         }
 
+        int y;
         if (mAnimating) {
-            return;
+            y = (int)mAnimY;
+        } else {
+            y = mDisplay.getHeight()-1;
         }
-
-        int y = mDisplay.getHeight()-1;
-        prepareTracking(y);
+        // Let the fling think that we're open so it goes in the right direction
+        // and doesn't try to re-open the windowshade.
+        mExpanded = true;
+        prepareTracking(y, false);
         performFling(y, -2000.0f, true);
     }
     
@@ -1108,10 +1114,9 @@
         }
     }
     
-    void prepareTracking(int y) {
+    void prepareTracking(int y, boolean opening) {
         mTracking = true;
         mVelocityTracker = VelocityTracker.obtain();
-        boolean opening = !mExpanded;
         if (opening) {
             mAnimAccel = 2000.0f;
             mAnimVel = 200;
@@ -1199,10 +1204,11 @@
     }
     
     boolean interceptTouchEvent(MotionEvent event) {
-        if (SPEW) Log.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event);
+        if (SPEW) Log.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled="
+                + mDisabled);
 
         if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
-            return true;
+            return false;
         }
         
         final int statusBarSize = mStatusBarView.getHeight();
@@ -1218,7 +1224,7 @@
             }
             if ((!mExpanded && y < hitSize) ||
                     (mExpanded && y > (mDisplay.getHeight()-hitSize))) {
-                prepareTracking(y);
+                prepareTracking(y, !mExpanded); // opening if we're not already fully visible
                 mVelocityTracker.addMovement(event);
             }
         } else if (mTracking) {
@@ -1679,9 +1685,7 @@
         if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
             if ((net & StatusBarManager.DISABLE_EXPAND) != 0) {
                 Log.d(TAG, "DISABLE_EXPAND: yes");
-                mAnimating = false;
-                updateExpandedViewPos(0);
-                performCollapse();
+                animateCollapse();
             }
         }
         if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
diff --git a/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java b/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java
index 7569d7a..3bbb447 100755
--- a/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java
@@ -73,11 +73,65 @@
 
         for (int i = 0; i < containers.length; i++) {
             if (containers[i].startsWith("com.android.unittests.AsecTests.")) {
-                ms.destroySecureContainer(containers[i]);
+                ms.destroySecureContainer(containers[i], true);
             }
         }
     }
 
+    private boolean containerExists(String localId) throws RemoteException {
+        IMountService ms = getMs();
+        String[] containers = ms.getSecureContainerList();
+        String fullId = "com.android.unittests.AsecTests." + localId;
+
+        for (int i = 0; i < containers.length; i++) {
+            if (containers[i].equals(fullId)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private int createContainer(String localId, int size, String key) throws RemoteException {
+        Assert.assertTrue(isMediaMounted());
+        String fullId = "com.android.unittests.AsecTests." + localId;
+
+        IMountService ms = getMs();
+        return ms.createSecureContainer(fullId, size, "fat", key, android.os.Process.myUid());
+    }
+
+    private int mountContainer(String localId, String key) throws RemoteException {
+        Assert.assertTrue(isMediaMounted());
+        String fullId = "com.android.unittests.AsecTests." + localId;
+
+        IMountService ms = getMs();
+        return ms.mountSecureContainer(fullId, key, android.os.Process.myUid());
+    }
+
+    private int renameContainer(String localId1, String localId2) throws RemoteException {
+        Assert.assertTrue(isMediaMounted());
+        String fullId1 = "com.android.unittests.AsecTests." + localId1;
+        String fullId2 = "com.android.unittests.AsecTests." + localId2;
+
+        IMountService ms = getMs();
+        return ms.renameSecureContainer(fullId1, fullId2);
+    }
+
+    private int unmountContainer(String localId, boolean force) throws RemoteException {
+        Assert.assertTrue(isMediaMounted());
+        String fullId = "com.android.unittests.AsecTests." + localId;
+
+        IMountService ms = getMs();
+        return ms.unmountSecureContainer(fullId, force);
+    }
+
+    private int destroyContainer(String localId, boolean force) throws RemoteException {
+        Assert.assertTrue(isMediaMounted());
+        String fullId = "com.android.unittests.AsecTests." + localId;
+
+        IMountService ms = getMs();
+        return ms.destroySecureContainer(fullId, force);
+    }
+
     private IMountService getMs() {
         IBinder service = ServiceManager.getService("mount");
         if (service != null) {
@@ -100,67 +154,174 @@
     }
 
     public void testCreateContainer() {
-        Assert.assertTrue(isMediaMounted());
-        IMountService ms = getMs();
         try {
-            int rc = ms.createSecureContainer("com.android.unittests.AsecTests.testCreateContainer", 4, "fat", "none", 1000);
-            Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    createContainer("testCreateContainer", 4, "none"));
+            Assert.assertEquals(true, containerExists("testCreateContainer"));
+        } catch (Exception e) {
+            failStr(e);
+        }
+    }
+
+    public void testCreateMinSizeContainer() {
+        try {
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    createContainer("testCreateContainer", 1, "none"));
+            Assert.assertEquals(true, containerExists("testCreateContainer"));
+        } catch (Exception e) {
+            failStr(e);
+        }
+    }
+
+    public void testCreateZeroSizeContainer() {
+        try {
+            Assert.assertEquals(StorageResultCode.OperationFailedInternalError,
+                    createContainer("testCreateZeroContainer", 0, "none"));
+        } catch (Exception e) {
+            failStr(e);
+        }
+    }
+
+    public void testCreateDuplicateContainer() {
+        try {
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    createContainer("testCreateDupContainer", 4, "none"));
+
+            Assert.assertEquals(StorageResultCode.OperationFailedInternalError,
+                    createContainer("testCreateDupContainer", 4, "none"));
         } catch (Exception e) {
             failStr(e);
         }
     }
 
     public void testDestroyContainer() {
-        Assert.assertTrue(isMediaMounted());
-        IMountService ms = getMs();
         try {
-            int rc = ms.createSecureContainer("com.android.unittests.AsecTests.testDestroyContainer", 4, "fat", "none", 1000);
-            Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
-            rc = ms.destroySecureContainer("com.android.unittests.AsecTests.testDestroyContainer");
-            Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    createContainer("testDestroyContainer", 4, "none"));
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    destroyContainer("testDestroyContainer", false));
         } catch (Exception e) {
             failStr(e);
         }
     }
 
     public void testMountContainer() {
-        Assert.assertTrue(isMediaMounted());
-        IMountService ms = getMs();
         try {
-            int rc = ms.createSecureContainer(
-                    "com.android.unittests.AsecTests.testMountContainer", 4, "fat", "none", 1000);
-            Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    createContainer("testMountContainer", 4, "none"));
 
-            rc = ms.unmountSecureContainer("com.android.unittests.AsecTests.testMountContainer");
-            Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    unmountContainer("testMountContainer", false));
 
-            rc = ms.mountSecureContainer("com.android.unittests.AsecTests.testMountContainer", "none", 1000);
-            Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    mountContainer("testMountContainer", "none"));
         } catch (Exception e) {
             failStr(e);
         }
     }
 
     public void testMountBadKey() {
-        Assert.assertTrue(isMediaMounted());
+        try {
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    createContainer("testMountBadKey", 4, "00000000000000000000000000000000"));
+
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    unmountContainer("testMountBadKey", false));
+
+            Assert.assertEquals(StorageResultCode.OperationFailedInternalError,
+                    mountContainer("testMountContainer", "000000000000000000000000000000001"));
+
+            Assert.assertEquals(StorageResultCode.OperationFailedInternalError,
+                    mountContainer("testMountContainer", "none"));
+        } catch (Exception e) {
+            failStr(e);
+        }
+    }
+
+    public void testUnmountBusyContainer() {
         IMountService ms = getMs();
         try {
-            int rc = ms.createSecureContainer(
-                    "com.android.unittests.AsecTests.testMountBadKey", 4, "fat",
-                            "00000000000000000000000000000000", 1000);
-            Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    createContainer("testUnmountBusyContainer", 4, "none"));
 
-            rc = ms.unmountSecureContainer("com.android.unittests.AsecTests.testMountBadKey");
-            Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
+            String path = ms.getSecureContainerPath("com.android.unittests.AsecTests.testUnmountBusyContainer");
 
-            rc = ms.mountSecureContainer(
-                    "com.android.unittests.AsecTests.testMountBadKey",
-                            "00000000000000000000000000000001", 1001);
-            Assert.assertEquals(StorageResultCode.OperationFailedInternalError, rc);
+            File f = new File(path, "reference");
+            FileOutputStream fos = new FileOutputStream(f);
 
-            rc = ms.mountSecureContainer(
-                    "com.android.unittests.AsecTests.testMountBadKey", "none", 1001);
-            Assert.assertEquals(StorageResultCode.OperationFailedInternalError, rc);
+            Assert.assertEquals(StorageResultCode.OperationFailedStorageBusy,
+                    unmountContainer("testUnmountBusyContainer", false));
+
+            fos.close();
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    unmountContainer("testUnmountBusyContainer", false));
+        } catch (Exception e) {
+            failStr(e);
+        }
+    }
+
+    public void testDestroyBusyContainer() {
+        IMountService ms = getMs();
+        try {
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    createContainer("testDestroyBusyContainer", 4, "none"));
+
+            String path = ms.getSecureContainerPath("com.android.unittests.AsecTests.testDestroyBusyContainer");
+
+            File f = new File(path, "reference");
+            FileOutputStream fos = new FileOutputStream(f);
+
+            Assert.assertEquals(StorageResultCode.OperationFailedStorageBusy,
+                    destroyContainer("testDestroyBusyContainer", false));
+
+            fos.close();
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    destroyContainer("testDestroyBusyContainer", false));
+        } catch (Exception e) {
+            failStr(e);
+        }
+    }
+
+    public void testRenameContainer() {
+        try {
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    createContainer("testRenameContainer.1", 4, "none"));
+
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    unmountContainer("testRenameContainer.1", false));
+
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    renameContainer("testRenameContainer.1", "testRenameContainer.2"));
+
+            Assert.assertEquals(false, containerExists("testRenameContainer.1"));
+            Assert.assertEquals(true, containerExists("testRenameContainer.2"));
+        } catch (Exception e) {
+            failStr(e);
+        }
+    }
+
+    public void testRenameMountedContainer() {
+        try {
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    createContainer("testRenameContainer.1", 4, "none"));
+
+            Assert.assertEquals(StorageResultCode.OperationFailedStorageMounted,
+                    renameContainer("testRenameContainer.1", "testRenameContainer.2"));
+        } catch (Exception e) {
+            failStr(e);
+        }
+    }
+
+    public void testRenameToExistingContainer() {
+        try {
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    createContainer("testRenameContainer.1", 4, "none"));
+
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    createContainer("testRenameContainer.2", 4, "none"));
+
+            Assert.assertEquals(StorageResultCode.OperationFailedStorageMounted,
+                    renameContainer("testRenameContainer.1", "testRenameContainer.2"));
         } catch (Exception e) {
             failStr(e);
         }
diff --git a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
index 8f4d0a1..be9571c 100755
--- a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
@@ -716,7 +716,7 @@
         }
         try {
         String mPath = Environment.getExternalStorageDirectory().toString();
-        int ret = getMs().unmountVolume(mPath);
+        int ret = getMs().unmountVolume(mPath, false);
         return ret == StorageResultCode.OperationSucceeded;
         } catch (RemoteException e) {
             return true;
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java b/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
index 50451e7..ce1bf8d 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
@@ -47,6 +47,7 @@
     private static final int EVENT_RELEASE_TOUCH_POINT = 16;
     private static final int EVENT_CLEAR_TOUCH_POINTS = 17;
     private static final int EVENT_CANCEL_TOUCH_POINT = 18;
+    private static final int EVENT_SET_TOUCH_MODIFIER = 19;
     
     private static final int LAYOUT_CLEAR_LIST = 20;
     private static final int LAYOUT_DISPLAY = 21;
@@ -145,6 +146,13 @@
             mEventSender.updateTouchPoint(id, x, y);
             break;
 
+        case EVENT_SET_TOUCH_MODIFIER:
+            Bundle modifierArgs = (Bundle) msg.obj;
+            String modifier = modifierArgs.getString("modifier");
+            boolean enabled = modifierArgs.getBoolean("enabled");
+            mEventSender.setTouchModifier(modifier, enabled);
+            break;
+
         case EVENT_RELEASE_TOUCH_POINT:
             mEventSender.releaseTouchPoint(msg.arg1);
             break;
@@ -320,7 +328,10 @@
     }
 
     public void setTouchModifier(String modifier, boolean enabled) {
-        // TODO(benm): Android doesn't support key modifiers on touch events yet.
+        Bundle map = new Bundle();
+        map.putString("modifier", modifier);
+        map.putBoolean("enabled", enabled);
+        obtainMessage(EVENT_SET_TOUCH_MODIFIER, map).sendToTarget();
     }
 
     public void touchMove() {
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
index 4d51356..14a6abf 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
@@ -51,24 +51,10 @@
 
     }
 
-    public static String isKnownBug(String file) {
-        int index = file.indexOf("fast");
-        if (index != -1) {
-            String sub = file.substring(index);
-            // Log.e("FileFilter", "Looking for:"+sub);
-            if (bugList.containsKey(sub))
-                return bugList.get(sub);
-        }
-        return null;
-    }
-
     final static HashSet<String> ignoreResultList = new HashSet<String>();
-    final static Hashtable<String, String> bugList = 
-        new Hashtable<String, String>();
- 
+
     static {
         fillIgnoreResultSet();
-        fillBugTable();
     }
 
     static final String[] ignoreTestDirs = {
@@ -84,38 +70,35 @@
 
     static final String [] ignoreTestList = {
         "editing/selection/move-left-right.html",
-        "fast/events/touch/basic-multi-touch-events.html", // We do not support multi touch events.
         "fast/js/regexp-charclass-crash.html", // RegExp is too large, causing OOM
         "fast/regex/test1.html", // RegExp is exponential
         "fast/regex/slow.html", // RegExp is exponential
-        "storage/domstorage/localstorage/iframe-events.html", // Expects test to be in LayoutTests
         "storage/domstorage/localstorage/private-browsing-affects-storage.html", // No notion of private browsing.
-        "storage/domstorage/sessionstorage/iframe-events.html", // Expects test to be in LayoutTests
         "storage/domstorage/sessionstorage/private-browsing-affects-storage.html", // No notion of private browsing.
         "storage/private-browsing-readonly.html", // No notion of private browsing.
     };
 
     static void fillIgnoreResultSet() {
         ignoreResultList.add("fast/css/case-transform.html"); // will not fix #619707
-        ignoreResultList.add("fast/css/computed-style.html"); // different platform defaults for font and different screen size
         ignoreResultList.add("fast/dom/Element/offsetLeft-offsetTop-body-quirk.html"); // different screen size result in extra spaces in Apple compared to us
         ignoreResultList.add("fast/dom/Window/Plug-ins.html"); // need test plugin
         ignoreResultList.add("fast/dom/Window/window-properties.html"); // xslt and xpath elements missing from property list
         ignoreResultList.add("fast/dom/Window/window-screen-properties.html"); // pixel depth
         ignoreResultList.add("fast/dom/Window/window-xy-properties.html"); // requires eventSender.mouseDown(),mouseUp()
-        ignoreResultList.add("fast/dom/character-index-for-point.html"); // requires textInputController.characterIndexForPoint
+        ignoreResultList.add("fast/dom/attribute-namespaces-get-set.html"); // http://b/733229
         ignoreResultList.add("fast/dom/gc-9.html"); // requires xpath support
         ignoreResultList.add("fast/dom/global-constructors.html"); // requires xslt and xpath support
         ignoreResultList.add("fast/dom/object-embed-plugin-scripting.html"); // dynamic plugins not supported
         ignoreResultList.add("fast/dom/tabindex-clamp.html"); // there is extra spacing in the file due to multiple input boxes fitting on one line on Apple, ours are wrapped. Space at line ends are stripped.
         ignoreResultList.add("fast/events/anchor-image-scrolled-x-y.html"); // requires eventSender.mouseDown(),mouseUp()
+        ignoreResultList.add("fast/events/arrow-navigation.html"); // http://b/735233
         ignoreResultList.add("fast/events/capture-on-target.html"); // requires eventSender.mouseDown(),mouseUp()
         ignoreResultList.add("fast/events/dblclick-addEventListener.html"); // requires eventSender.mouseDown(),mouseUp()
         ignoreResultList.add("fast/events/drag-in-frames.html"); // requires eventSender.mouseDown(),mouseUp()
         ignoreResultList.add("fast/events/drag-outside-window.html"); // requires eventSender.mouseDown(),mouseUp()
-        ignoreResultList.add("fast/events/event-sender-mouse-click.html"); // requires eventSender.mouseDown(),mouseUp()
         ignoreResultList.add("fast/events/event-view-toString.html"); // requires eventSender.mouseDown(),mouseUp()
         ignoreResultList.add("fast/events/frame-click-focus.html"); // requires eventSender.mouseDown(),mouseUp()
+        ignoreResultList.add("fast/events/frame-tab-focus.html"); // http://b/734308
         ignoreResultList.add("fast/events/iframe-object-onload.html"); // there is extra spacing in the file due to multiple frame boxes fitting on one line on Apple, ours are wrapped. Space at line ends are stripped.
         ignoreResultList.add("fast/events/input-image-scrolled-x-y.html"); // requires eventSender.mouseDown(),mouseUp()
         ignoreResultList.add("fast/events/mouseclick-target-and-positioning.html"); // requires eventSender.mouseDown(),mouseUp()
@@ -123,70 +106,49 @@
         ignoreResultList.add("fast/events/mouseover-mouseout2.html"); // requires eventSender.mouseDown(),mouseUp()
         ignoreResultList.add("fast/events/mouseup-outside-button.html"); // requires eventSender.mouseDown(),mouseUp()
         ignoreResultList.add("fast/events/mouseup-outside-document.html"); // requires eventSender.mouseDown(),mouseUp()
-        ignoreResultList.add("fast/events/objc-event-api.html"); // eventSender.mouseDown(), mouseUp() and objc API missing
-        ignoreResultList.add("fast/events/objc-keyboard-event-creation.html"); // eventSender.mouseDown(), mouseUp() and objc API missing
         ignoreResultList.add("fast/events/onclick-list-marker.html"); // requires eventSender.mouseDown(),mouseUp()
         ignoreResultList.add("fast/events/ondragenter.html"); // requires eventSender.mouseDown(),mouseUp()
         ignoreResultList.add("fast/events/onload-webkit-before-webcore.html"); // missing space in textrun, ok as text is wrapped. ignore. #714933
+        ignoreResultList.add("fast/events/option-tab.html"); // http://b/734308
         ignoreResultList.add("fast/events/window-events-bubble.html"); // requires eventSender.mouseDown(),mouseUp()
         ignoreResultList.add("fast/events/window-events-bubble2.html"); // requires eventSender.mouseDown(),mouseUp()
         ignoreResultList.add("fast/events/window-events-capture.html"); // requires eventSender.mouseDown(),mouseUp()
-        ignoreResultList.add("fast/forms/attributed-strings.html"); // missing support for textInputController.makeAttributedString()
         ignoreResultList.add("fast/forms/drag-into-textarea.html"); // requires eventSender.mouseDown(),mouseUp()
+        ignoreResultList.add("fast/forms/focus-control-to-page.html"); // http://b/716638
+        ignoreResultList.add("fast/forms/focus2.html"); // http://b/735111
         ignoreResultList.add("fast/forms/form-data-encoding-2.html"); // charset convert. #516936 ignore, won't fix
         ignoreResultList.add("fast/forms/form-data-encoding.html"); // charset convert. #516936 ignore, won't fix
         ignoreResultList.add("fast/forms/input-appearance-maxlength.html"); // execCommand "insertText" not supported
         ignoreResultList.add("fast/forms/input-select-on-click.html"); // requires eventSender.mouseDown(),mouseUp()
-        ignoreResultList.add("fast/forms/input-truncate-newline.html"); // Copy&Paste commands not supported
         ignoreResultList.add("fast/forms/listbox-onchange.html"); // requires eventSender.mouseDown(),mouseUp()
+        ignoreResultList.add("fast/forms/listbox-selection.html"); // http://b/735116
         ignoreResultList.add("fast/forms/onselect-textarea.html"); // requires eventSender.mouseMoveTo, mouseDown & mouseUp and abs. position of mouse to select a word. ignore, won't fix #716583
         ignoreResultList.add("fast/forms/onselect-textfield.html"); // requires eventSender.mouseMoveTo, mouseDown & mouseUp and abs. position of mouse to select a word. ignore, won't fix #716583
         ignoreResultList.add("fast/forms/plaintext-mode-1.html"); // not implemented queryCommandEnabled:BackColor, Undo & Redo
         ignoreResultList.add("fast/forms/search-cancel-button-mouseup.html"); // requires eventSender.mouseDown(),mouseUp()
+        ignoreResultList.add("fast/forms/search-event-delay.html"); // http://b/735120
         ignoreResultList.add("fast/forms/select-empty-list.html"); // requires eventSender.mouseDown(),mouseUp()
+        ignoreResultList.add("fast/forms/select-type-ahead-non-latin.html"); // http://b/735244
         ignoreResultList.add("fast/forms/selected-index-assert.html"); // not capturing the console messages
         ignoreResultList.add("fast/forms/selection-functions.html"); // there is extra spacing as the text areas and input boxes fit next to each other on Apple, but are wrapped on our screen.
         ignoreResultList.add("fast/forms/textarea-appearance-wrap.html"); // Our text areas are a little thinner than Apples. Also RTL test failes
-        ignoreResultList.add("fast/forms/textarea-hard-linewrap.html"); // Our text areas are a little thinner than Apples
         ignoreResultList.add("fast/forms/textarea-initial-caret-position.html"); // Text selection done differently on our platform. When a inputbox gets focus, the entire block is selected.
         ignoreResultList.add("fast/forms/textarea-no-scroll-on-blur.html"); // Text selection done differently on our platform. When a inputbox gets focus, the entire block is selected.
         ignoreResultList.add("fast/forms/textarea-paste-newline.html"); // Copy&Paste commands not supported
         ignoreResultList.add("fast/forms/textarea-scrolled-endline-caret.html"); // requires eventSender.mouseDown(),mouseUp()
+        ignoreResultList.add("fast/frames/iframe-window-focus.html"); // http://b/735140
         ignoreResultList.add("fast/frames/frameElement-widthheight.html"); // screen width&height are different
         ignoreResultList.add("fast/frames/frame-js-url-clientWidth.html"); // screen width&height are different
+        ignoreResultList.add("fast/html/tab-order.html"); // http://b/719289
         ignoreResultList.add("fast/js/navigator-mimeTypes-length.html"); // dynamic plugins not supported
+        ignoreResultList.add("fast/js/string-capitalization.html"); // http://b/516936
         ignoreResultList.add("fast/loader/local-JavaScript-from-local.html"); // Requires LayoutTests to exist at /tmp/LayoutTests
         ignoreResultList.add("fast/loader/local-iFrame-source-from-local.html"); // Requires LayoutTests to exist at /tmp/LayoutTests
         ignoreResultList.add("fast/loader/opaque-base-url.html"); // extra spacing because iFrames rendered next to each other on Apple
+        ignoreResultList.add("fast/overflow/scroll-vertical-not-horizontal.html"); // http://b/735196
         ignoreResultList.add("fast/parser/script-tag-with-trailing-slash.html"); // not capturing the console messages
         ignoreResultList.add("fast/replaced/image-map.html"); // requires eventSender.mouseDown(),mouseUp()
-        ignoreResultList.add("fast/text/attributed-substring-from-range.html"); //  requires JS test API, textInputController
-        ignoreResultList.add("fast/text/attributed-substring-from-range-001.html"); //  requires JS test API, textInputController
         ignoreResultList.add("fast/text/plain-text-line-breaks.html"); // extra spacing because iFrames rendered next to each other on Apple
     }
 
-    static void fillBugTable() {
-        bugList.put("fast/forms/focus-control-to-page.html", "716638");
-        bugList.put("fast/html/tab-order.html", "719289");
-        bugList.put("fast/dom/attribute-namespaces-get-set.html", "733229");
-        bugList.put("fast/dom/set-innerHTML.html", "733823");
-        bugList.put("fast/dom/xmlhttprequest-get.html", "733846");
-        bugList.put("fast/encoding/css-charset-default.html", "733856");
-        bugList.put("fast/encoding/default-xhtml-encoding.html", "733882");
-        bugList.put("fast/encoding/meta-in-xhtml.html", "733882");
-        bugList.put("fast/events/frame-tab-focus.html", "734308");
-        bugList.put("fast/events/option-tab.html", "734308");
-        bugList.put("fast/forms/focus2.html", "735111");
-        bugList.put("fast/forms/listbox-selection.html", "735116");
-        bugList.put("fast/forms/search-event-delay.html", "735120");
-        bugList.put("fast/frames/iframe-window-focus.html", "735140");
-        bugList.put("fast/innerHTML/004.html", "733882");
-        bugList.put("fast/js/string-capitalization.html", "516936");
-        bugList.put("fast/js/string-concatenate-outofmemory.html","735152");
-        bugList.put("fast/parser/external-entities.html", "735176");
-        bugList.put("fast/overflow/scroll-vertical-not-horizontal.html", "735196");
-        bugList.put("fast/events/arrow-navigation.html", "735233");
-        bugList.put("fast/forms/select-type-ahead-non-latin.html", "735244");
-    }
-
 }
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java
index 1a265e8..ef0c6c6 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java
@@ -54,6 +54,9 @@
         String[] files = d.list();
         for (int i = 0; i < files.length; i++) {
             String s = dir + "/" + files[i];
+            if (s.endsWith("TEMPLATE.html")) {
+                continue;
+            }
             if (FileFilter.ignoreTest(s)) {
                 Log.v(LOGTAG, "  Ignoring: " + s);
                 continue;
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
index 2667520..02a7046 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
@@ -716,6 +716,7 @@
         mCanOpenWindows = false;
         mEventSender.resetMouse();
         mEventSender.clearTouchPoints();
+        mEventSender.clearTouchMetaState();
         mPageFinished = false;
         mOneHundredPercentComplete = false;
         mDumpWebKitData = false;
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/WebViewEventSender.java b/tests/DumpRenderTree/src/com/android/dumprendertree/WebViewEventSender.java
index 996eaba..0c2347d 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/WebViewEventSender.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/WebViewEventSender.java
@@ -207,7 +207,7 @@
 
         tp.setDownTime(SystemClock.uptimeMillis());
         MotionEvent event = MotionEvent.obtain(tp.downTime(), tp.downTime(),
-                MotionEvent.ACTION_DOWN, tp.getX(), tp.getY(), 0);
+                MotionEvent.ACTION_DOWN, tp.getX(), tp.getY(), mTouchMetaState);
         mWebView.onTouchEvent(event);
     }
 
@@ -223,7 +223,7 @@
         }
 
         MotionEvent event = MotionEvent.obtain(tp.downTime(), SystemClock.uptimeMillis(),
-                MotionEvent.ACTION_MOVE, tp.getX(), tp.getY(), 0);
+                MotionEvent.ACTION_MOVE, tp.getX(), tp.getY(), mTouchMetaState);
         mWebView.onTouchEvent(event);
 
         tp.setMoved(false);
@@ -237,7 +237,7 @@
         }
 
         MotionEvent event = MotionEvent.obtain(tp.downTime(), SystemClock.uptimeMillis(),
-                MotionEvent.ACTION_UP, tp.getX(), tp.getY(), 0);
+                MotionEvent.ACTION_UP, tp.getX(), tp.getY(), mTouchMetaState);
         mWebView.onTouchEvent(event);
 
         if (tp.isReleased()) {
@@ -253,7 +253,7 @@
 
         if (tp.cancelled()) {
             MotionEvent event = MotionEvent.obtain(tp.downTime(), SystemClock.uptimeMillis(),
-                    MotionEvent.ACTION_CANCEL, tp.getX(), tp.getY(), 0);
+                    MotionEvent.ACTION_CANCEL, tp.getX(), tp.getY(), mTouchMetaState);
             mWebView.onTouchEvent(event);
         }
     }
@@ -285,8 +285,20 @@
     }
 
     public void setTouchModifier(String modifier, boolean enabled) {
-        // TODO(benm): This needs implementing when Android supports sending key modifiers
-        // in touch events.
+        int mask = 0;
+        if ("alt".equals(modifier.toLowerCase())) {
+            mask = KeyEvent.META_ALT_ON;
+        } else if ("shift".equals(modifier.toLowerCase())) {
+            mask = KeyEvent.META_SHIFT_ON;
+        } else if ("ctrl".equals(modifier.toLowerCase())) {
+            mask = KeyEvent.META_SYM_ON;
+        }
+
+        if (enabled) {
+            mTouchMetaState |= mask;
+        } else {
+            mTouchMetaState &= ~mask;
+        }
     }
 
     public void releaseTouchPoint(int id) {
@@ -302,6 +314,10 @@
         mTouchPoints.clear();
     }
 
+    public void clearTouchMetaState() {
+        mTouchMetaState = 0;
+    }
+
     private int contentsToWindowX(int x) {
         return (int) (x * mWebView.getScale()) - mWebView.getScrollX();
     }
@@ -352,4 +368,5 @@
     };
 
     private Vector<TouchPoint> mTouchPoints;
+    private int mTouchMetaState;
 }
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index 663a33a..dc442aa 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -938,17 +938,17 @@
     uint8_t mask = 0;
     uint8_t value = 0;
     if (strcmp(name, kWildcardName) == 0) {
-        mask = out->MASK_KEYSHIDDEN;
-        value = out->KEYSHIDDEN_ANY;
+        mask = ResTable_config::MASK_KEYSHIDDEN;
+        value = ResTable_config::KEYSHIDDEN_ANY;
     } else if (strcmp(name, "keysexposed") == 0) {
-        mask = out->MASK_KEYSHIDDEN;
-        value = out->KEYSHIDDEN_NO;
+        mask = ResTable_config::MASK_KEYSHIDDEN;
+        value = ResTable_config::KEYSHIDDEN_NO;
     } else if (strcmp(name, "keyshidden") == 0) {
-        mask = out->MASK_KEYSHIDDEN;
-        value = out->KEYSHIDDEN_YES;
+        mask = ResTable_config::MASK_KEYSHIDDEN;
+        value = ResTable_config::KEYSHIDDEN_YES;
     } else if (strcmp(name, "keyssoft") == 0) {
-        mask = out->MASK_KEYSHIDDEN;
-        value = out->KEYSHIDDEN_SOFT;
+        mask = ResTable_config::MASK_KEYSHIDDEN;
+        value = ResTable_config::KEYSHIDDEN_SOFT;
     }
 
     if (mask != 0) {
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index a389bfb..0b531c2 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -382,7 +382,7 @@
         }
         attr.createIfNeeded(outTable);
         if (!attr.hasErrors) {
-            char buf[10];
+            char buf[11];
             sprintf(buf, "%d", l10n_required);
             err = outTable->addBag(attr.sourcePos, myPackage, attr16, attr.ident,
                     String16(""), String16("^l10n"), String16(buf), NULL, NULL);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 990498f..41d9f9d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -30,6 +30,7 @@
 import com.android.tools.layoutlib.create.MethodAdapter;
 import com.android.tools.layoutlib.create.OverrideMethod;
 
+import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Rect;
@@ -1133,7 +1134,7 @@
         }
 
         @SuppressWarnings("unused")
-        public void resized(int arg0, int arg1, Rect arg2, Rect arg3, boolean arg4)
+        public void resized(int arg0, int arg1, Rect arg2, Rect arg3, boolean arg4, Configuration arg5)
                 throws RemoteException {
             // pass for now.
         }