Merge "Make sure that the event callback thread is Java capable in the simulator."
diff --git a/Android.mk b/Android.mk
index a48ef45..1700965 100644
--- a/Android.mk
+++ b/Android.mk
@@ -111,6 +111,7 @@
 	core/java/android/content/pm/IPackageDeleteObserver.aidl \
 	core/java/android/content/pm/IPackageInstallObserver.aidl \
 	core/java/android/content/pm/IPackageManager.aidl \
+	core/java/android/content/pm/IPackageMoveObserver.aidl \
 	core/java/android/content/pm/IPackageStatsObserver.aidl \
 	core/java/android/database/IContentObserver.aidl \
 	core/java/android/hardware/ISensorService.aidl \
diff --git a/api/current.xml b/api/current.xml
index 96220c6..86043df 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -716,6 +716,17 @@
  visibility="public"
 >
 </field>
+<field name="MOVE_PACKAGE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.permission.MOVE_PACKAGE&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="PERSISTENT_ACTIVITY"
  type="java.lang.String"
  transient="false"
@@ -13833,7 +13844,7 @@
 >
 <parameter name="parcel" type="android.os.Parcel">
 </parameter>
-<parameter name="flags" type="int">
+<parameter name="flagz" type="int">
 </parameter>
 </method>
 <field name="CREATOR"
@@ -60412,6 +60423,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"
@@ -64473,7 +64580,7 @@
  value="256"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -64627,7 +64734,7 @@
  value="17"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -64638,7 +64745,7 @@
  value="20"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -64649,7 +64756,7 @@
  value="16"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -137020,6 +137127,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"
@@ -137418,6 +137540,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"
@@ -137440,6 +137586,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"
@@ -137462,6 +137619,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"
@@ -137561,6 +137729,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"
@@ -172912,6 +173091,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"
@@ -174603,6 +174795,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"
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/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index ff16c6e..fc5707d 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -600,6 +600,7 @@
             } else if (opt.equals("-t")) {
                 installFlags |= PackageManager.INSTALL_ALLOW_TEST;
             } else if (opt.equals("-s")) {
+                // Override if -s option is specified.
                 installFlags |= PackageManager.INSTALL_EXTERNAL;
             } else {
                 System.err.println("Error: Unknown option: " + opt);
diff --git a/common/java/com/android/common/OperationScheduler.java b/common/java/com/android/common/OperationScheduler.java
index c7b12d3..0c7ca83 100644
--- a/common/java/com/android/common/OperationScheduler.java
+++ b/common/java/com/android/common/OperationScheduler.java
@@ -158,12 +158,35 @@
             time = Math.max(time, moratoriumTimeMillis);
         }
         time = Math.max(time, lastSuccessTimeMillis + options.minTriggerMillis);
-        time = Math.max(time, lastErrorTimeMillis + options.backoffFixedMillis +
-                options.backoffIncrementalMillis * errorCount);
+        if (errorCount > 0) {
+            time = Math.max(time, lastErrorTimeMillis + options.backoffFixedMillis +
+                    options.backoffIncrementalMillis * errorCount);
+        }
         return time;
     }
 
     /**
+     * Return the last time the operation completed.  Does not modify any state.
+     *
+     * @return the wall clock time when {@link #onSuccess()} was last called.
+     */
+    public long getLastSuccessTimeMillis() {
+        return mStorage.getLong(PREFIX + "lastSuccessTimeMillis", 0);
+    }
+
+    /**
+     * Return the last time the operation was attempted.  Does not modify any state.
+     *
+     * @return the wall clock time when {@link #onSuccess()} or {@link
+     * #onTransientError()} was last called.
+     */
+    public long getLastAttemptTimeMillis() {
+        return Math.max(
+                mStorage.getLong(PREFIX + "lastSuccessTimeMillis", 0),
+                mStorage.getLong(PREFIX + "lastErrorTimeMillis", 0));
+    }
+
+    /**
      * Fetch a {@link SharedPreferences} property, but force it to be before
      * a certain time, updating the value if necessary.  This is to recover
      * gracefully from clock rollbacks which could otherwise strand our timers.
@@ -273,9 +296,7 @@
      * where there is reason to hope things might start working better.
      */
     public void resetTransientError() {
-        mStorage.edit()
-                .remove(PREFIX + "lastErrorTimeMillis")
-                .remove(PREFIX + "errorCount").commit();
+        mStorage.edit().remove(PREFIX + "errorCount").commit();
     }
 
     /**
diff --git a/common/tests/src/com/android/common/OperationSchedulerTest.java b/common/tests/src/com/android/common/OperationSchedulerTest.java
index 28178b5..f728eea 100644
--- a/common/tests/src/com/android/common/OperationSchedulerTest.java
+++ b/common/tests/src/com/android/common/OperationSchedulerTest.java
@@ -28,6 +28,8 @@
         OperationScheduler scheduler = new OperationScheduler(storage);
         OperationScheduler.Options options = new OperationScheduler.Options();
         assertEquals(Long.MAX_VALUE, scheduler.getNextTimeMillis(options));
+        assertEquals(0, scheduler.getLastSuccessTimeMillis());
+        assertEquals(0, scheduler.getLastAttemptTimeMillis());
 
         long beforeTrigger = System.currentTimeMillis();
         scheduler.setTriggerTimeMillis(beforeTrigger + 1000000);
@@ -49,6 +51,9 @@
         long beforeError = System.currentTimeMillis();
         scheduler.onTransientError();
         long afterError = System.currentTimeMillis();
+        assertEquals(0, scheduler.getLastSuccessTimeMillis());
+        assertTrue(beforeError <= scheduler.getLastAttemptTimeMillis());
+        assertTrue(afterError >= scheduler.getLastAttemptTimeMillis());
         assertEquals(beforeTrigger + 1500000, scheduler.getNextTimeMillis(options));
         options.backoffFixedMillis = 1000000;
         options.backoffIncrementalMillis = 500000;
@@ -59,9 +64,18 @@
         beforeError = System.currentTimeMillis();
         scheduler.onTransientError();
         afterError = System.currentTimeMillis();
+        assertTrue(beforeError <= scheduler.getLastAttemptTimeMillis());
+        assertTrue(afterError >= scheduler.getLastAttemptTimeMillis());
         assertTrue(beforeError + 2000000 <= scheduler.getNextTimeMillis(options));
         assertTrue(afterError + 2000000 >= scheduler.getNextTimeMillis(options));
 
+        // Reset transient error: no backoff interval
+        scheduler.resetTransientError();
+        assertEquals(0, scheduler.getLastSuccessTimeMillis());
+        assertEquals(beforeTrigger + 1500000, scheduler.getNextTimeMillis(options));
+        assertTrue(beforeError <= scheduler.getLastAttemptTimeMillis());
+        assertTrue(afterError >= scheduler.getLastAttemptTimeMillis());
+
         // Permanent error holds true even if transient errors are reset
         // However, we remember that the transient error was reset...
         scheduler.onPermanentError();
@@ -75,6 +89,10 @@
         long beforeSuccess = System.currentTimeMillis();
         scheduler.onSuccess();
         long afterSuccess = System.currentTimeMillis();
+        assertTrue(beforeSuccess <= scheduler.getLastAttemptTimeMillis());
+        assertTrue(afterSuccess >= scheduler.getLastAttemptTimeMillis());
+        assertTrue(beforeSuccess <= scheduler.getLastSuccessTimeMillis());
+        assertTrue(afterSuccess >= scheduler.getLastSuccessTimeMillis());
         assertEquals(Long.MAX_VALUE, scheduler.getNextTimeMillis(options));
 
         // The moratorium is not reset by success!
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/ContextImpl.java b/core/java/android/app/ContextImpl.java
index db6a4bf..1d004ee 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -42,6 +42,7 @@
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.IPackageDeleteObserver;
 import android.content.pm.IPackageInstallObserver;
+import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageManager;
 import android.content.pm.IPackageStatsObserver;
 import android.content.pm.InstrumentationInfo;
@@ -2489,6 +2490,15 @@
         }
 
         @Override
+        public void movePackage(String packageName, IPackageMoveObserver observer, int flags) {
+            try {
+                mPM.movePackage(packageName, observer, flags);
+            } catch (RemoteException e) {
+                // Should never happen!
+            }
+        }
+
+        @Override
         public String getInstallerPackageName(String packageName) {
             try {
                 return mPM.getInstallerPackageName(packageName);
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/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index ca36df2..7945f3f 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -21,6 +21,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
+import android.util.Log;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -46,6 +47,8 @@
     private final Map<Integer, Integer> mSelectionArgsBackReferences;
     private final boolean mYieldAllowed;
 
+    private final static String TAG = "ContentProviderOperation";
+
     /**
      * Creates a {@link ContentProviderOperation} by copying the contents of a
      * {@link Builder}.
@@ -241,6 +244,7 @@
                             final String expectedValue = values.getAsString(projection[i]);
                             if (!TextUtils.equals(cursorValue, expectedValue)) {
                                 // Throw exception when expected values don't match
+                                Log.e(TAG, this.toString());
                                 throw new OperationApplicationException("Found value " + cursorValue
                                         + " when expected " + expectedValue + " for column "
                                         + projection[i]);
@@ -252,10 +256,12 @@
                 cursor.close();
             }
         } else {
+            Log.e(TAG, this.toString());
             throw new IllegalStateException("bad type, " + mType);
         }
 
         if (mExpectedCount != null && mExpectedCount != numRows) {
+            Log.e(TAG, this.toString());
             throw new OperationApplicationException("wrong number of rows: " + numRows);
         }
 
@@ -289,6 +295,7 @@
             String key = entry.getKey();
             Integer backRefIndex = mValuesBackReferences.getAsInteger(key);
             if (backRefIndex == null) {
+                Log.e(TAG, this.toString());
                 throw new IllegalArgumentException("values backref " + key + " is not an integer");
             }
             values.put(key, backRefToValue(backRefs, numBackRefs, backRefIndex));
@@ -326,6 +333,17 @@
         return newArgs;
     }
 
+    @Override
+    public String toString() {
+        return "mType: " + mType + ", mUri: " + mUri +
+                ", mSelection: " + mSelection +
+                ", mExpectedCount: " + mExpectedCount +
+                ", mYieldAllowed: " + mYieldAllowed +
+                ", mValues: " + mValues +
+                ", mValuesBackReferences: " + mValuesBackReferences +
+                ", mSelectionArgsBackReferences: " + mSelectionArgsBackReferences;
+    }
+
     /**
      * Return the string representation of the requested back reference.
      * @param backRefs an array of results
@@ -335,9 +353,10 @@
      * the numBackRefs
      * @return the string representation of the requested back reference.
      */
-    private static long backRefToValue(ContentProviderResult[] backRefs, int numBackRefs,
+    private long backRefToValue(ContentProviderResult[] backRefs, int numBackRefs,
             Integer backRefIndex) {
         if (backRefIndex >= numBackRefs) {
+            Log.e(TAG, this.toString());
             throw new ArrayIndexOutOfBoundsException("asked for back ref " + backRefIndex
                     + " but there are only " + numBackRefs + " back refs");
         }
diff --git a/core/java/android/content/ContentValues.java b/core/java/android/content/ContentValues.java
index 532cc03..c04625d 100644
--- a/core/java/android/content/ContentValues.java
+++ b/core/java/android/content/ContentValues.java
@@ -39,14 +39,14 @@
      * Creates an empty set of values using the default initial size
      */
     public ContentValues() {
-        // Choosing a default size of 8 based on analysis of typical 
+        // Choosing a default size of 8 based on analysis of typical
         // consumption by applications.
         mValues = new HashMap<String, Object>(8);
     }
 
     /**
      * Creates an empty set of values using the given initial size
-     * 
+     *
      * @param size the initial size of the set of values
      */
     public ContentValues(int size) {
@@ -55,7 +55,7 @@
 
     /**
      * Creates a set of values copied from the given set
-     * 
+     *
      * @param from the values to copy
      */
     public ContentValues(ContentValues from) {
@@ -65,7 +65,7 @@
     /**
      * Creates a set of values copied from the given HashMap. This is used
      * by the Parcel unmarshalling code.
-     * 
+     *
      * @param from the values to start with
      * {@hide}
      */
@@ -174,7 +174,7 @@
     public void put(String key, Boolean value) {
         mValues.put(key, value);
     }
-    
+
     /**
      * Adds a value to the set.
      *
@@ -187,7 +187,7 @@
 
     /**
      * Adds a null value to the set.
-     * 
+     *
      * @param key the name of the value to make null
      */
     public void putNull(String key) {
@@ -196,7 +196,7 @@
 
     /**
      * Returns the number of values.
-     * 
+     *
      * @return the number of values
      */
     public int size() {
@@ -223,7 +223,7 @@
      * Returns true if this object has the named value.
      *
      * @param key the value to check for
-     * @return {@code true} if the value is present, {@code false} otherwise 
+     * @return {@code true} if the value is present, {@code false} otherwise
      */
     public boolean containsKey(String key) {
         return mValues.containsKey(key);
@@ -242,7 +242,7 @@
 
     /**
      * Gets a value and converts it to a String.
-     * 
+     *
      * @param key the value to get
      * @return the String for the value
      */
@@ -253,7 +253,7 @@
 
     /**
      * Gets a value and converts it to a Long.
-     * 
+     *
      * @param key the value to get
      * @return the Long value, or null if the value is missing or cannot be converted
      */
@@ -270,7 +270,7 @@
                     return null;
                 }
             } else {
-                Log.e(TAG, "Cannot cast value for " + key + " to a Long");
+                Log.e(TAG, "Cannot cast value for " + key + " to a Long: " + value, e);
                 return null;
             }
         }
@@ -278,7 +278,7 @@
 
     /**
      * Gets a value and converts it to an Integer.
-     * 
+     *
      * @param key the value to get
      * @return the Integer value, or null if the value is missing or cannot be converted
      */
@@ -295,7 +295,7 @@
                     return null;
                 }
             } else {
-                Log.e(TAG, "Cannot cast value for " + key + " to a Integer");
+                Log.e(TAG, "Cannot cast value for " + key + " to a Integer: " + value, e);
                 return null;
             }
         }
@@ -303,7 +303,7 @@
 
     /**
      * Gets a value and converts it to a Short.
-     * 
+     *
      * @param key the value to get
      * @return the Short value, or null if the value is missing or cannot be converted
      */
@@ -320,7 +320,7 @@
                     return null;
                 }
             } else {
-                Log.e(TAG, "Cannot cast value for " + key + " to a Short");
+                Log.e(TAG, "Cannot cast value for " + key + " to a Short: " + value, e);
                 return null;
             }
         }
@@ -328,7 +328,7 @@
 
     /**
      * Gets a value and converts it to a Byte.
-     * 
+     *
      * @param key the value to get
      * @return the Byte value, or null if the value is missing or cannot be converted
      */
@@ -345,7 +345,7 @@
                     return null;
                 }
             } else {
-                Log.e(TAG, "Cannot cast value for " + key + " to a Byte");
+                Log.e(TAG, "Cannot cast value for " + key + " to a Byte: " + value, e);
                 return null;
             }
         }
@@ -353,7 +353,7 @@
 
     /**
      * Gets a value and converts it to a Double.
-     * 
+     *
      * @param key the value to get
      * @return the Double value, or null if the value is missing or cannot be converted
      */
@@ -370,7 +370,7 @@
                     return null;
                 }
             } else {
-                Log.e(TAG, "Cannot cast value for " + key + " to a Double");
+                Log.e(TAG, "Cannot cast value for " + key + " to a Double: " + value, e);
                 return null;
             }
         }
@@ -378,7 +378,7 @@
 
     /**
      * Gets a value and converts it to a Float.
-     * 
+     *
      * @param key the value to get
      * @return the Float value, or null if the value is missing or cannot be converted
      */
@@ -395,7 +395,7 @@
                     return null;
                 }
             } else {
-                Log.e(TAG, "Cannot cast value for " + key + " to a Float");
+                Log.e(TAG, "Cannot cast value for " + key + " to a Float: " + value, e);
                 return null;
             }
         }
@@ -403,7 +403,7 @@
 
     /**
      * Gets a value and converts it to a Boolean.
-     * 
+     *
      * @param key the value to get
      * @return the Boolean value, or null if the value is missing or cannot be converted
      */
@@ -415,7 +415,7 @@
             if (value instanceof CharSequence) {
                 return Boolean.valueOf(value.toString());
             } else {
-                Log.e(TAG, "Cannot cast value for " + key + " to a Boolean");
+                Log.e(TAG, "Cannot cast value for " + key + " to a Boolean: " + value, e);
                 return null;
             }
         }
@@ -424,7 +424,7 @@
     /**
      * Gets a value that is a byte array. Note that this method will not convert
      * any other types to byte arrays.
-     * 
+     *
      * @param key the value to get
      * @return the byte[] value, or null is the value is missing or not a byte[]
      */
@@ -439,13 +439,13 @@
 
     /**
      * Returns a set of all of the keys and values
-     * 
+     *
      * @return a set of all of the keys and values
      */
     public Set<Map.Entry<String, Object>> valueSet() {
         return mValues.entrySet();
     }
-    
+
     public static final Parcelable.Creator<ContentValues> CREATOR =
             new Parcelable.Creator<ContentValues>() {
         @SuppressWarnings({"deprecation", "unchecked"})
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 4ddb819..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
@@ -807,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: "
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 47789a5..7a02a98 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -26,6 +26,7 @@
 import android.content.pm.IPackageInstallObserver;
 import android.content.pm.IPackageDeleteObserver;
 import android.content.pm.IPackageDataObserver;
+import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageStatsObserver;
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.PackageInfo;
@@ -309,4 +310,6 @@
     void updateExternalMediaStatus(boolean mounted);
 
     String nextPackageToClean(String lastPackage);
+
+    void movePackage(String packageName, IPackageMoveObserver observer, int flags);
 }
diff --git a/core/java/android/content/pm/IPackageMoveObserver.aidl b/core/java/android/content/pm/IPackageMoveObserver.aidl
new file mode 100644
index 0000000..baa1595
--- /dev/null
+++ b/core/java/android/content/pm/IPackageMoveObserver.aidl
@@ -0,0 +1,27 @@
+/*
+**
+** Copyright 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.content.pm;
+
+/**
+ * Callback for moving package resources from the Package Manager.
+ * @hide
+ */
+oneway interface IPackageMoveObserver {
+    void packageMoved(in String packageName, int returnCode);
+}
+
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index ff2ed3d..2edb430 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -551,6 +551,69 @@
     public static final int DONT_DELETE_DATA = 0x00000001;
 
     /**
+     * Return code that is passed to the {@link IPackageMoveObserver} by
+     * {@link #movePackage(android.net.Uri, IPackageMoveObserver)}
+     * when the package has been successfully moved by the system.
+     * @hide
+     */
+    public static final int MOVE_SUCCEEDED = 1;
+    /**
+     * Error code that is passed to the {@link IPackageMoveObserver} by
+     * {@link #movePackage(android.net.Uri, IPackageMoveObserver)}
+     * when the package hasn't been successfully moved by the system
+     * because of insufficient memory on specified media.
+     * @hide
+     */
+    public static final int MOVE_FAILED_INSUFFICIENT_STORAGE = -1;
+
+    /**
+     * Error code that is passed to the {@link IPackageMoveObserver} by
+     * {@link #movePackage(android.net.Uri, IPackageMoveObserver)}
+     * if the specified package doesn't exist.
+     * @hide
+     */
+    public static final int MOVE_FAILED_DOESNT_EXIST = -2;
+
+    /**
+     * Error code that is passed to the {@link IPackageMoveObserver} by
+     * {@link #movePackage(android.net.Uri, IPackageMoveObserver)}
+     * if the specified package cannot be moved since its a system package.
+     * @hide
+     */
+    public static final int MOVE_FAILED_SYSTEM_PACKAGE = -3;
+
+    /**
+     * Error code that is passed to the {@link IPackageMoveObserver} by
+     * {@link #movePackage(android.net.Uri, IPackageMoveObserver)}
+     * if the specified package cannot be moved since its forward locked.
+     * @hide
+     */
+    public static final int MOVE_FAILED_FORWARD_LOCKED = -4;
+
+    /**
+     * Error code that is passed to the {@link IPackageMoveObserver} by
+     * {@link #movePackage(android.net.Uri, IPackageMoveObserver)}
+     * if the specified package cannot be moved to the specified location.
+     * @hide
+     */
+    public static final int MOVE_FAILED_INVALID_LOCATION = -5;
+
+    /**
+     * Flag parameter for {@link #movePackage} to indicate that
+     * the package should be moved to internal storage if its
+     * been installed on external media.
+     * @hide
+     */
+    public static final int MOVE_INTERNAL = 0x00000001;
+
+    /**
+     * Flag parameter for {@link #movePackage} to indicate that
+     * the package should be moved to external media.
+     * @hide
+     */
+    public static final int MOVE_EXTERNAL_MEDIA = 0x00000002;
+
+    /**
      * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device has a camera facing away
      * from the screen.
@@ -1153,7 +1216,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
@@ -1920,4 +1985,23 @@
      * Return whether the device has been booted into safe mode.
      */
     public abstract boolean isSafeMode();
+
+    /**
+     * Attempts to move package resources from internal to external media or vice versa.
+     * Since this may take a little while, the result will
+     * be posted back to the given observer.   This call may fail if the calling context
+     * lacks the {@link android.Manifest.permission#MOVE_PACKAGE} permission, if the
+     * named package cannot be found, or if the named package is a "system package".
+     *
+     * @param packageName The name of the package to delete
+     * @param observer An observer callback to get notified when the package move is
+     * complete. {@link android.content.pm.IPackageMoveObserver#packageMoved(boolean)} will be
+     * called when that happens.  observer may be null to indicate that no callback is desired.
+     * @param flags To indicate install location {@link #MOVE_INTERNAL} or
+     * {@link #MOVE_EXTERNAL_MEDIA}
+     *
+     * @hide
+     */
+    public abstract void movePackage(
+            String packageName, IPackageMoveObserver observer, int flags);
 }
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/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/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/GestureDetector.java b/core/java/android/view/GestureDetector.java
index 58f998e..c1e1049 100644
--- a/core/java/android/view/GestureDetector.java
+++ b/core/java/android/view/GestureDetector.java
@@ -494,6 +494,9 @@
 
             mLastMotionX = x;
             mLastMotionY = y;
+            if (mCurrentDownEvent != null) {
+                mCurrentDownEvent.recycle();
+            }
             mCurrentDownEvent = MotionEvent.obtain(ev);
             mAlwaysInTapRegion = true;
             mAlwaysInBiggerTapRegion = true;
@@ -562,10 +565,14 @@
 
                 if ((Math.abs(velocityY) > mMinimumFlingVelocity)
                         || (Math.abs(velocityX) > mMinimumFlingVelocity)){
-                    handled = mListener.onFling(mCurrentDownEvent, currentUpEvent, velocityX, velocityY);
+                    handled = mListener.onFling(mCurrentDownEvent, ev, velocityX, velocityY);
                 }
             }
-            mPreviousUpEvent = MotionEvent.obtain(ev);
+            if (mPreviousUpEvent != null) {
+                mPreviousUpEvent.recycle();
+            }
+            // Hold the event we obtained above - listeners may have changed the original.
+            mPreviousUpEvent = currentUpEvent;
             mVelocityTracker.recycle();
             mVelocityTracker = null;
             mIsDoubleTapping = false;
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 bc49439..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;
@@ -3933,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/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 5f5df56..adae0cb 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -4436,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;
         }
@@ -4699,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();
@@ -5735,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/ListView.java b/core/java/android/widget/ListView.java
index 5308725c..2feed03 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -3092,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();
             }
@@ -3104,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
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index bcddca1..2f6dd1e 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -295,14 +295,18 @@
      */
     private static class DropDownAdapter implements ListAdapter, SpinnerAdapter {
         private SpinnerAdapter mAdapter;
+        private ListAdapter mListAdapter;
 
         /**
-         * <p>Creates a new ListAddapter wrapper for the specified adapter.</p>
+         * <p>Creates a new ListAdapter wrapper for the specified adapter.</p>
          *
          * @param adapter the Adapter to transform into a ListAdapter
          */
         public DropDownAdapter(SpinnerAdapter adapter) {
             this.mAdapter = adapter;
+            if (adapter instanceof ListAdapter) {
+                this.mListAdapter = (ListAdapter) adapter;
+            }
         }
 
         public int getCount() {
@@ -343,21 +347,29 @@
         }
 
         /**
-         * <p>Always returns false.</p>
-         *
-         * @return false
+         * If the wrapped SpinnerAdapter is also a ListAdapter, delegate this call.
+         * Otherwise, return true. 
          */
         public boolean areAllItemsEnabled() {
-            return true;
+            final ListAdapter adapter = mListAdapter;
+            if (adapter != null) {
+                return adapter.areAllItemsEnabled();
+            } else {
+                return true;
+            }
         }
 
         /**
-         * <p>Always returns false.</p>
-         *
-         * @return false
+         * If the wrapped SpinnerAdapter is also a ListAdapter, delegate this call.
+         * Otherwise, return true.
          */
         public boolean isEnabled(int position) {
-            return true;
+            final ListAdapter adapter = mListAdapter;
+            if (adapter != null) {
+                return adapter.isEnabled(position);
+            } else {
+                return true;
+            }
         }
 
         public int getItemViewType(int position) {
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_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/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 333db05..63584ed 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1041,6 +1041,12 @@
         android:description="@string/permdesc_deletePackages"
         android:protectionLevel="signatureOrSystem" />
 
+    <!-- Allows an application to move location of installed package. -->
+    <permission android:name="android.permission.MOVE_PACKAGE"
+        android:label="@string/permlab_movePackage"
+        android:description="@string/permdesc_movePackage"
+        android:protectionLevel="signatureOrSystem" />
+
     <!-- Allows an application to change whether an application component (other than its own) is
          enabled or not. -->
     <permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index cdf38b9..98b8863 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -680,6 +680,11 @@
         restricted usually to system process.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_movePackage">Move application resources</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_movePackage">Allows an application to move application resources from internal to external media and vice versa.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_readLogs">read system log files</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_readLogs">Allows an application to read from the
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/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/libs/rs/java/Fountain/AndroidManifest.xml b/libs/rs/java/Fountain/AndroidManifest.xml
index 1185930..951c451 100644
--- a/libs/rs/java/Fountain/AndroidManifest.xml
+++ b/libs/rs/java/Fountain/AndroidManifest.xml
@@ -1,7 +1,9 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.fountain">
-    <application android:label="Fountain">
+    <application 
+        android:label="Fountain"
+        android:icon="@drawable/test_pattern">
         <activity android:name="Fountain">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
diff --git a/libs/rs/java/Fountain/res/drawable/test_pattern.png b/libs/rs/java/Fountain/res/drawable/test_pattern.png
new file mode 100644
index 0000000..e7d1455
--- /dev/null
+++ b/libs/rs/java/Fountain/res/drawable/test_pattern.png
Binary files differ
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/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/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 59a5f9d..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();
 
@@ -443,6 +444,8 @@
         notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
 
         pause_l();
+
+        mFlags |= AT_EOS;
     }
 }
 
@@ -517,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;
 }
 
@@ -651,6 +660,7 @@
 status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
     mSeeking = true;
     mSeekTimeUs = timeUs;
+    mFlags &= ~AT_EOS;
 
     seekAudioIfNecessary_l();
 
@@ -989,6 +999,11 @@
         return UNKNOWN_ERROR;  // async prepare already pending
     }
 
+    if (!mQueueStarted) {
+        mQueue.start();
+        mQueueStarted = true;
+    }
+
     mFlags |= PREPARING;
     mAsyncPrepareEvent = new AwesomeEvent(
             this, &AwesomePlayer::onPrepareAsyncEvent);
@@ -1089,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) {
@@ -1150,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/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/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index 933a7e5..95ab684 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -102,7 +102,11 @@
             File sourceFile = new File(archiveFilePath);
             DisplayMetrics metrics = new DisplayMetrics();
             metrics.setToDefaults();
-            PackageParser.Package pkg = packageParser.parsePackage(sourceFile, archiveFilePath, metrics, 0);
+            PackageParser.Package pkg = packageParser.parsePackage(sourceFile,
+                    archiveFilePath, metrics, 0);
+            // Nuke the parser reference right away and force a gc
+            Runtime.getRuntime().gc();
+            packageParser = null;
             if (pkg == null) {
                 Log.w(TAG, "Failed to parse package");
                 return PackageHelper.RECOMMEND_FAILED_INVALID_APK;
@@ -115,7 +119,7 @@
                 return PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
             } else {
                 // Implies install on internal storage.
-                return 0;
+                return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
             }
         }
     };
diff --git a/services/java/com/android/server/AccessibilityManagerService.java b/services/java/com/android/server/AccessibilityManagerService.java
index 3027a92..477ea0c 100644
--- a/services/java/com/android/server/AccessibilityManagerService.java
+++ b/services/java/com/android/server/AccessibilityManagerService.java
@@ -579,6 +579,7 @@
             } catch (RemoteException re) {
                 mClients.remove(i);
                 count--;
+                i--;
             }
         }
     }
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index d6e23fb..2a78806 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -150,13 +150,23 @@
                     notifyVolumeStateChange(null, "/sdcard", VolumeState.NoMedia, VolumeState.Mounted);
                     return;
                 }
-                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));
+                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();
             }
         }
     };
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 1015028..958d089 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -425,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/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 4326efc..252f2a6 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -44,6 +44,7 @@
 import android.content.pm.IPackageDeleteObserver;
 import android.content.pm.IPackageInstallObserver;
 import android.content.pm.IPackageManager;
+import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageStatsObserver;
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.PackageInfo;
@@ -142,6 +143,9 @@
         FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
 
     private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
+    // Suffix used during package installation when copying/moving
+    // package apks to install directory.
+    private static final String INSTALL_PACKAGE_SUFFIX = "-";
 
     static final int SCAN_MONITOR = 1<<0;
     static final int SCAN_NO_DEX = 1<<1;
@@ -321,8 +325,8 @@
     };
 
     class PackageHandler extends Handler {
-        final ArrayList<InstallParams> mPendingInstalls =
-            new ArrayList<InstallParams>();
+        final ArrayList<HandlerParams> mPendingInstalls =
+            new ArrayList<HandlerParams>();
         // Service Connection to remote media container service to copy
         // package uri's from external media onto secure containers
         // or internal storage.
@@ -334,20 +338,19 @@
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case INIT_COPY: {
-                    InstallParams params = (InstallParams) msg.obj;
+                    HandlerParams params = (HandlerParams) msg.obj;
                     Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
                     if (mContainerService != null) {
                         // No need to add to pending list. Use remote stub directly
-                        handleStartCopy(params);
+                        params.handleStartCopy(mContainerService);
                     } else {
                         if (mContext.bindService(service, mDefContainerConn,
                                 Context.BIND_AUTO_CREATE)) {
                             mPendingInstalls.add(params);
                         } else {
                             Log.e(TAG, "Failed to bind to media container service");
-                            // Indicate install failure TODO add new error code
-                            processPendingInstall(createInstallArgs(params),
-                                    PackageManager.INSTALL_FAILED_INTERNAL_ERROR);
+                            // Indicate service bind error
+                            params.handleServiceError();
                         }
                     }
                     break;
@@ -358,9 +361,9 @@
                         mContainerService = (IMediaContainerService) msg.obj;
                     }
                     if (mPendingInstalls.size() > 0) {
-                        InstallParams params = mPendingInstalls.remove(0);
+                        HandlerParams params = mPendingInstalls.remove(0);
                         if (params != null) {
-                            handleStartCopy(params);
+                            params.handleStartCopy(mContainerService);
                         }
                     }
                     break;
@@ -421,54 +424,6 @@
                 } break;
             }
         }
-
-        // Utility method to initiate copying apk via media
-        // container service.
-        private void handleStartCopy(InstallParams params) {
-            int ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
-            if (mContainerService != null) {
-                // Remote call to find out default install location
-                int loc = params.getInstallLocation(mContainerService);
-                // Use install location to create InstallArgs and temporary
-                // install location
-                if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE){
-                    ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
-                } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
-                    ret = PackageManager.INSTALL_FAILED_INVALID_APK;
-                } else {
-                    if ((params.flags & PackageManager.INSTALL_EXTERNAL) == 0){
-                        if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
-                            // Set the flag to install on external media.
-                            params.flags |= PackageManager.INSTALL_EXTERNAL;
-                        } else {
-                            // Make sure the flag for installing on external
-                            // media is unset
-                            params.flags &= ~PackageManager.INSTALL_EXTERNAL;
-                        }
-                    }
-                    // Disable forward locked apps on sdcard.
-                    if ((params.flags & PackageManager.INSTALL_FORWARD_LOCK) != 0 &&
-                            (params.flags & PackageManager.INSTALL_EXTERNAL) != 0) {
-                        // Make sure forward locked apps can only be installed
-                        // on internal storage
-                        Log.w(TAG, "Cannot install protected apps on sdcard");
-                        ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
-                    } else {
-                        ret = PackageManager.INSTALL_SUCCEEDED;
-                    }
-                }
-            }
-            mHandler.sendEmptyMessage(MCS_UNBIND);
-            // Create the file args now.
-            InstallArgs args = createInstallArgs(params);
-            if (ret == PackageManager.INSTALL_SUCCEEDED) {
-                // Create copy only if we are not in an erroneous state.
-                args.createCopyFile();
-                // Remote call to initiate copy
-                ret = args.copyApk(mContainerService);
-            }
-            processPendingInstall(args, ret);
-        }
     }
 
     static boolean installOnSd(int flags) {
@@ -2180,8 +2135,8 @@
         int i;
         for (i=0; i<files.length; i++) {
             File file = new File(dir, files[i]);
-            if (files[i] != null && files[i].endsWith(".zip")) {
-                // Public resource for forward locked package. Ignore
+            if (!isPackageFilename(files[i])) {
+                // Ignore entries which are not apk's
                 continue;
             }
             PackageParser.Package pkg = scanPackageLI(file,
@@ -2936,11 +2891,6 @@
             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
         }
 
-        // We don't expect installation to fail beyond this point,
-        if ((scanMode&SCAN_MONITOR) != 0) {
-            mAppDirs.put(pkg.mPath, pkg);
-        }
-
         // Request the ActivityManager to kill the process(only for existing packages)
         // so that we do not end up in a confused state while the user is still using the older
         // version of the application while the new one gets installed.
@@ -2950,6 +2900,10 @@
         }
 
         synchronized (mPackages) {
+            // We don't expect installation to fail beyond this point,
+            if ((scanMode&SCAN_MONITOR) != 0) {
+                mAppDirs.put(pkg.mPath, pkg);
+            }
             // Add the new setting to mSettings
             mSettings.insertPackageSettingLP(pkgSetting, pkg);
             // Add the new setting to mPackages
@@ -4224,19 +4178,24 @@
                     return;
                 }
 
+                // Ignore packages that are being installed or
+                // have just been installed.
+                if (ignoreCodePath(fullPathStr)) {
+                    return;
+                }
+                PackageParser.Package p = null;
+                synchronized (mPackages) {
+                    p = mAppDirs.get(fullPathStr);
+                }
                 if ((event&REMOVE_EVENTS) != 0) {
-                    synchronized (mInstallLock) {
-                        PackageParser.Package p = mAppDirs.get(fullPathStr);
-                        if (p != null) {
-                            removePackageLI(p, true);
-                            removedPackage = p.applicationInfo.packageName;
-                            removedUid = p.applicationInfo.uid;
-                        }
+                    if (p != null) {
+                        removePackageLI(p, true);
+                        removedPackage = p.applicationInfo.packageName;
+                        removedUid = p.applicationInfo.uid;
                     }
                 }
 
                 if ((event&ADD_EVENTS) != 0) {
-                    PackageParser.Package p = mAppDirs.get(fullPathStr);
                     if (p == null) {
                         p = scanPackageLI(fullPath,
                                 (mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
@@ -4312,13 +4271,6 @@
                     }
                     args.doPostInstall(res.returnCode);
                 }
-                if (args.observer != null) {
-                    try {
-                        args.observer.packageInstalled(res.name, res.returnCode);
-                    } catch (RemoteException e) {
-                        Log.i(TAG, "Observer no longer exists.");
-                    }
-                }
                 // There appears to be a subtle deadlock condition if the sendPackageBroadcast
                 // call appears in the synchronized block above.
                 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
@@ -4345,15 +4297,29 @@
                     }
                 }
                 Runtime.getRuntime().gc();
+                if (args.observer != null) {
+                    try {
+                        args.observer.packageInstalled(res.name, res.returnCode);
+                    } catch (RemoteException e) {
+                        Log.i(TAG, "Observer no longer exists.");
+                    }
+                }
             }
         });
     }
 
-    static final class InstallParams {
+    interface HandlerParams {
+        void handleStartCopy(IMediaContainerService imcs);
+        void handleServiceError();
+    }
+
+    class InstallParams implements HandlerParams {
         final IPackageInstallObserver observer;
         int flags;
         final Uri packageURI;
         final String installerPackageName;
+        private InstallArgs mArgs;
+        private int mRet;
         InstallParams(Uri packageURI,
                 IPackageInstallObserver observer, int flags,
                 String installerPackageName) {
@@ -4363,13 +4329,118 @@
             this.installerPackageName = installerPackageName;
         }
 
-        public int getInstallLocation(IMediaContainerService imcs) {
+        private int getInstallLocation(IMediaContainerService imcs) {
             try {
                 return imcs.getRecommendedInstallLocation(packageURI);
             } catch (RemoteException e) {
             }
             return  -1;
         }
+
+        public void handleStartCopy(IMediaContainerService imcs) {
+            int ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+            if (imcs != null) {
+                // Remote call to find out default install location
+                int loc = getInstallLocation(imcs);
+                // Use install location to create InstallArgs and temporary
+                // install location
+                if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE){
+                    ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+                } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
+                    ret = PackageManager.INSTALL_FAILED_INVALID_APK;
+                } else {
+                    if ((flags & PackageManager.INSTALL_EXTERNAL) == 0){
+                        if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
+                            // Set the flag to install on external media.
+                            flags |= PackageManager.INSTALL_EXTERNAL;
+                        } else {
+                            // Make sure the flag for installing on external
+                            // media is unset
+                            flags &= ~PackageManager.INSTALL_EXTERNAL;
+                        }
+                    }
+                    // Disable forward locked apps on sdcard.
+                    if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0 &&
+                            (flags & PackageManager.INSTALL_EXTERNAL) != 0) {
+                        // Make sure forward locked apps can only be installed
+                        // on internal storage
+                        Log.w(TAG, "Cannot install protected apps on sdcard");
+                        ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
+                    } else {
+                        ret = PackageManager.INSTALL_SUCCEEDED;
+                    }
+                }
+            }
+            // Create the file args now.
+            mArgs = createInstallArgs(this);
+            if (ret == PackageManager.INSTALL_SUCCEEDED) {
+                // Create copy only if we are not in an erroneous state.
+                // Remote call to initiate copy using temporary file
+                ret = mArgs.copyApk(imcs, true);
+            }
+            mRet = ret;
+            mHandler.sendEmptyMessage(MCS_UNBIND);
+            handleReturnCode();
+        }
+
+        void handleReturnCode() {
+            processPendingInstall(mArgs, mRet);
+        }
+
+        public void handleServiceError() {
+            mArgs = createInstallArgs(this);
+            mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+            handleReturnCode();
+        }
+    };
+
+    /*
+     * Utility class used in movePackage api.
+     * srcArgs and targetArgs are not set for invalid flags and make
+     * sure to do null checks when invoking methods on them.
+     * We probably want to return ErrorPrams for both failed installs
+     * and moves.
+     */
+    class MoveParams implements HandlerParams {
+        final IPackageMoveObserver observer;
+        final int flags;
+        final String packageName;
+        final InstallArgs srcArgs;
+        final InstallArgs targetArgs;
+        int mRet;
+        MoveParams(InstallArgs srcArgs,
+                IPackageMoveObserver observer,
+                int flags, String packageName) {
+            this.srcArgs = srcArgs;
+            this.observer = observer;
+            this.flags = flags;
+            this.packageName = packageName;
+            if (srcArgs != null) {
+                Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath()));
+                targetArgs = createInstallArgs(packageUri, flags, packageName);
+            } else {
+                targetArgs = null;
+            }
+        }
+
+        public void handleStartCopy(IMediaContainerService imcs) {
+            // Create the file args now.
+            mRet = targetArgs.copyApk(imcs, false);
+            targetArgs.doPreInstall(mRet);
+            mHandler.sendEmptyMessage(MCS_UNBIND);
+            handleReturnCode();
+        }
+
+        void handleReturnCode() {
+            targetArgs.doPostInstall(mRet);
+            // TODO invoke pending move
+            processPendingMove(this, mRet);
+        }
+
+        public void handleServiceError() {
+            mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+            handleReturnCode();
+        }
     };
 
     private InstallArgs createInstallArgs(InstallParams params) {
@@ -4388,8 +4459,18 @@
         }
     }
 
+    private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName) {
+        if (installOnSd(flags)) {
+            String cid = getNextCodePath(null, pkgName, "/" + SdInstallArgs.RES_FILE_NAME);
+            return new SdInstallArgs(packageURI, cid);
+        } else {
+            return new FileInstallArgs(packageURI, pkgName);
+        }
+    }
+
     static abstract class InstallArgs {
         final IPackageInstallObserver observer;
+        // Always refers to PackageManager flags only
         final int flags;
         final Uri packageURI;
         final String installerPackageName;
@@ -4404,7 +4485,7 @@
         }
 
         abstract void createCopyFile();
-        abstract int copyApk(IMediaContainerService imcs);
+        abstract int copyApk(IMediaContainerService imcs, boolean temp);
         abstract int doPreInstall(int status);
         abstract boolean doRename(int status, String pkgName, String oldCodePath);
         abstract int doPostInstall(int status);
@@ -4419,6 +4500,7 @@
         File installDir;
         String codeFileName;
         String resourceFileName;
+        boolean created = false;
 
         FileInstallArgs(InstallParams params) {
             super(params.packageURI, params.observer,
@@ -4433,6 +4515,15 @@
             resourceFileName = fullResourcePath;
         }
 
+        FileInstallArgs(Uri packageURI, String pkgName) {
+            super(packageURI, null, 0, null);
+            boolean fwdLocked = isFwdLocked(flags);
+            installDir = fwdLocked ? mDrmAppPrivateInstallDir : mAppInstallDir;
+            String apkName = getNextCodePath(null, pkgName, ".apk");
+            codeFileName = new File(installDir, apkName + ".apk").getPath();
+            resourceFileName = getResourcePathFromCodePath();
+        }
+
         String getCodePath() {
             return codeFileName;
         }
@@ -4442,11 +4533,29 @@
             installDir = fwdLocked ? mDrmAppPrivateInstallDir : mAppInstallDir;
             codeFileName = createTempPackageFile(installDir).getPath();
             resourceFileName = getResourcePathFromCodePath();
+            created = true;
         }
 
-        int copyApk(IMediaContainerService imcs) {
+        int copyApk(IMediaContainerService imcs, boolean temp) {
+            if (temp) {
+                // Generate temp file name
+                createCopyFile();
+            }
             // Get a ParcelFileDescriptor to write to the output file
             File codeFile = new File(codeFileName);
+            if (!created) {
+                try {
+                    codeFile.createNewFile();
+                    // Set permissions
+                    if (!setPermissions()) {
+                        // Failed setting permissions.
+                        return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+                    }
+                } catch (IOException e) {
+                   Log.w(TAG, "Failed to create file " + codeFile);
+                   return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+                }
+            }
             ParcelFileDescriptor out = null;
             try {
             out = ParcelFileDescriptor.open(codeFile,
@@ -4491,7 +4600,7 @@
                 codeFileName = desFile.getPath();
                 resourceFileName = getResourcePathFromCodePath();
                 // Set permissions
-                if (!setPermissions(pkgName)) {
+                if (!setPermissions()) {
                     // Failed setting permissions.
                     return false;
                 }
@@ -4558,7 +4667,7 @@
             }
         }
 
-        private boolean setPermissions(String pkgName) {
+        private boolean setPermissions() {
             // TODO Do this in a more elegant way later on. for now just a hack
             if (!isFwdLocked(flags)) {
                 final int filePermissions =
@@ -4594,7 +4703,7 @@
         }
 
         SdInstallArgs(String fullCodePath, String fullResourcePath) {
-            super(null, null, ApplicationInfo.FLAG_ON_SDCARD, null);
+            super(null, null, PackageManager.INSTALL_EXTERNAL, null);
             // Extract cid from fullCodePath
             int eidx = fullCodePath.lastIndexOf("/");
             String subStr1 = fullCodePath.substring(0, eidx);
@@ -4604,7 +4713,12 @@
         }
 
         SdInstallArgs(String cid) {
-            super(null, null,  ApplicationInfo.FLAG_ON_SDCARD, null);
+            super(null, null, PackageManager.INSTALL_EXTERNAL, null);
+            this.cid = cid;
+        }
+
+        SdInstallArgs(Uri packageURI, String cid) {
+            super(packageURI, null, PackageManager.INSTALL_EXTERNAL, null);
             this.cid = cid;
         }
 
@@ -4612,7 +4726,10 @@
             cid = getTempContainerId();
         }
 
-        int copyApk(IMediaContainerService imcs) {
+        int copyApk(IMediaContainerService imcs, boolean temp) {
+            if (temp) {
+                createCopyFile();
+            }
             try {
                 cachePath = imcs.copyResourceToContainer(
                         packageURI, cid,
@@ -4771,8 +4888,8 @@
             if (sidx != -1) {
                 subStr = subStr.substring(sidx + prefix.length());
                 if (subStr != null) {
-                    if (subStr.startsWith("-")) {
-                        subStr = subStr.substring(1);
+                    if (subStr.startsWith(INSTALL_PACKAGE_SUFFIX)) {
+                        subStr = subStr.substring(INSTALL_PACKAGE_SUFFIX.length());
                     }
                     try {
                         idx = Integer.parseInt(subStr);
@@ -4786,10 +4903,26 @@
                 }
             }
         }
-        idxStr = "-" + Integer.toString(idx);
+        idxStr = INSTALL_PACKAGE_SUFFIX + Integer.toString(idx);
         return prefix + idxStr;
     }
 
+    // Utility method used to ignore ADD/REMOVE events
+    // by directory observer.
+    private static boolean ignoreCodePath(String fullPathStr) {
+        String apkName = getApkName(fullPathStr);
+        int idx = apkName.lastIndexOf(INSTALL_PACKAGE_SUFFIX);
+        if (idx != -1 && ((idx+1) < apkName.length())) {
+            // Make sure the package ends with a numeral
+            String version = apkName.substring(idx+1);
+            try {
+                Integer.parseInt(version);
+                return true;
+            } catch (NumberFormatException e) {}
+        }
+        return false;
+    }
+    
     // Utility method that returns the relative package path with respect
     // to the installation directory. Like say for /data/data/com.test-1.apk
     // string com.test-1 is returned.
@@ -5055,6 +5188,19 @@
         }
     }
 
+    // Utility method used to move dex files during install.
+    private int moveDexFiles(PackageParser.Package newPackage) {
+        int retCode;
+        if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
+            retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
+            if (retCode != 0) {
+                Log.e(TAG, "Couldn't rename dex file: " + newPackage.mPath);
+                return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+            }
+        }
+        return PackageManager.INSTALL_SUCCEEDED;
+    }
+
     private void updateSettingsLI(PackageParser.Package newPackage,
             String installerPackageName, PackageInstalledInfo res) {
         String pkgName = newPackage.packageName;
@@ -5066,27 +5212,20 @@
             mSettings.writeLP();
         }
 
-        int retCode = 0;
-        if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
-            retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
-            if (retCode != 0) {
-                Log.e(TAG, "Couldn't rename dex file: " + newPackage.mPath);
-                res.returnCode =  PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
-                return;
-            }
+        if ((res.returnCode = moveDexFiles(newPackage))
+                != PackageManager.INSTALL_SUCCEEDED) {
+            // Discontinue if moving dex files failed.
+            return;
         }
-        res.returnCode = setPermissionsLI(newPackage);
-        if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
+        if((res.returnCode = setPermissionsLI(newPackage))
+                != PackageManager.INSTALL_SUCCEEDED) {
+            if (mInstaller != null) {
+                mInstaller.rmdex(newPackage.mScanPath);
+            }
             return;
         } else {
             Log.d(TAG, "New package installed in " + newPackage.mPath);
         }
-        if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
-            if (mInstaller != null) {
-                mInstaller.rmdex(newPackage.mScanPath);
-            }
-        }
-
         synchronized (mPackages) {
             grantPermissionsLP(newPackage, true);
             res.name = pkgName;
@@ -6765,9 +6904,13 @@
         HashSet<String> loadedPermissions = new HashSet<String>();
 
         GrantedPermissions(int pkgFlags) {
+            setFlags(pkgFlags);
+        }
+
+        void setFlags(int pkgFlags) {
             this.pkgFlags = (pkgFlags & ApplicationInfo.FLAG_SYSTEM) |
-                    (pkgFlags & ApplicationInfo.FLAG_FORWARD_LOCK) |
-                    (pkgFlags & ApplicationInfo.FLAG_ON_SDCARD);
+            (pkgFlags & ApplicationInfo.FLAG_FORWARD_LOCK) |
+            (pkgFlags & ApplicationInfo.FLAG_ON_SDCARD);
         }
     }
 
@@ -8662,11 +8805,6 @@
                    uidArr[di++] = uidList[i];
                }
            }
-           if (true) {
-               for (int j = 0; j < num; j++) {
-                   Log.i(TAG, "uidArr[" + j + "]=" + uidArr[j]);
-               }
-           }
        }
        if (mediaStatus) {
            if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading packages");
@@ -8779,4 +8917,145 @@
            }
        }
    }
+
+   public void movePackage(final String packageName,
+           final IPackageMoveObserver observer, final int flags) {
+       if (packageName == null) {
+           return;
+       }
+       mContext.enforceCallingOrSelfPermission(
+               android.Manifest.permission.MOVE_PACKAGE, null);
+       int returnCode = PackageManager.MOVE_SUCCEEDED;
+       int currFlags = 0;
+       int newFlags = 0;
+       synchronized (mPackages) {
+           PackageParser.Package pkg = mPackages.get(packageName);
+           if (pkg == null) {
+               returnCode =  PackageManager.MOVE_FAILED_DOESNT_EXIST;
+           }
+           // Disable moving fwd locked apps and system packages
+           if (pkg.applicationInfo != null &&
+                   (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+               Log.w(TAG, "Cannot move system application");
+               returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
+           } else if (pkg.applicationInfo != null &&
+                   (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) {
+               Log.w(TAG, "Cannot move forward locked app.");
+               returnCode = PackageManager.MOVE_FAILED_FORWARD_LOCKED;
+           } else {
+               // Find install location first
+               if ((flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 &&
+                       (flags & PackageManager.MOVE_INTERNAL) != 0) {
+                   Log.w(TAG, "Ambigous flags specified for move location.");
+                   returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
+               } else {
+                   newFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 ?
+                           PackageManager.INSTALL_EXTERNAL : 0;
+                   currFlags = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_ON_SDCARD) != 0 ?
+                           PackageManager.INSTALL_EXTERNAL : 0;
+                   if (newFlags == currFlags) {
+                       Log.w(TAG, "No move required. Trying to move to same location");
+                       returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
+                   }
+               }
+           }
+           if (returnCode != PackageManager.MOVE_SUCCEEDED) {
+               processPendingMove(new MoveParams(null, observer, 0, null), returnCode);
+           } else {
+               Message msg = mHandler.obtainMessage(INIT_COPY);
+               InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir,
+                       pkg.applicationInfo.publicSourceDir);
+               MoveParams mp = new MoveParams(srcArgs, observer, newFlags,
+                       packageName);
+               msg.obj = mp;
+               mHandler.sendMessage(msg);
+           }
+       }
+   }
+
+   private void processPendingMove(final MoveParams mp, final int currentStatus) {
+       // Queue up an async operation since the package deletion may take a little while.
+       mHandler.post(new Runnable() {
+           public void run() {
+               mHandler.removeCallbacks(this);
+               int returnCode = currentStatus;
+               boolean moveSucceeded = (returnCode == PackageManager.MOVE_SUCCEEDED);
+               if (moveSucceeded) {
+                   int uid = -1;
+                   synchronized (mPackages) {
+                       uid = mPackages.get(mp.packageName).applicationInfo.uid;
+                   }
+                   ArrayList<String> pkgList = new ArrayList<String>();
+                   pkgList.add(mp.packageName);
+                   int uidArr[] = new int[] { uid };
+                   // Send resources unavailable broadcast
+                   sendResourcesChangedBroadcast(false, pkgList, uidArr);
+
+                   // Update package code and resource paths
+                   synchronized (mPackages) {
+                       PackageParser.Package pkg = mPackages.get(mp.packageName);
+                       if (pkg != null) {
+                           String oldCodePath = pkg.mPath;
+                           String newCodePath = mp.targetArgs.getCodePath();
+                           String newResPath = mp.targetArgs.getResourcePath();
+                           pkg.mPath = newCodePath;
+                           // Move dex files around
+                           if (moveDexFiles(pkg)
+                                   != PackageManager.INSTALL_SUCCEEDED) {
+                               // Moving of dex files failed. Set
+                               // error code and abort move.
+                               pkg.mPath = pkg.mScanPath;
+                               returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
+                               moveSucceeded = false;
+                           } else {
+                               pkg.mScanPath = newCodePath;
+                               pkg.applicationInfo.sourceDir = newCodePath;
+                               pkg.applicationInfo.publicSourceDir = newResPath;
+                               PackageSetting ps = (PackageSetting) pkg.mExtras;
+                               ps.codePath = new File(pkg.applicationInfo.sourceDir);
+                               ps.codePathString = ps.codePath.getPath();
+                               ps.resourcePath = new File(pkg.applicationInfo.publicSourceDir);
+                               ps.resourcePathString = ps.resourcePath.getPath();
+                               // Set the application info flag correctly.
+                               if ((mp.flags & PackageManager.INSTALL_EXTERNAL) != 0) {
+                                   pkg.applicationInfo.flags |= ApplicationInfo.FLAG_ON_SDCARD;
+                               } else {
+                                   pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_ON_SDCARD;
+                               }
+                               ps.setFlags(pkg.applicationInfo.flags);
+                               mAppDirs.remove(oldCodePath);
+                               mAppDirs.put(newCodePath, pkg);
+                               // Persist settings
+                               mSettings.writeLP();
+                           }
+                       }
+                   }
+                   if (moveSucceeded) {
+                       // Delete older code
+                       synchronized (mInstallLock) {
+                           mp.srcArgs.cleanUpResourcesLI();
+                       }
+                       // Send resources available broadcast
+                       sendResourcesChangedBroadcast(true, pkgList, uidArr);
+                       Runtime.getRuntime().gc();
+                   }
+               }
+               if (!moveSucceeded){
+                   // Clean up failed installation
+                   if (mp.targetArgs != null) {
+                       mp.targetArgs.doPostInstall(
+                               PackageManager.INSTALL_FAILED_INTERNAL_ERROR);
+                   }
+               }
+               IPackageMoveObserver observer = mp.observer;
+               if (observer != null) {
+                   try {
+                       observer.packageMoved(mp.packageName, returnCode);
+                   } catch (RemoteException e) {
+                       Log.i(TAG, "Observer no longer exists.");
+                   }
+               }
+           }
+       });
+   }
 }
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 7fcf900..a481036e 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 47a58cf..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);
@@ -8347,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);
         }
     }
@@ -13090,6 +13084,11 @@
                                      values.userSetLocale);
                 }
 
+                mConfigurationSeq++;
+                if (mConfigurationSeq <= 0) {
+                    mConfigurationSeq = 1;
+                }
+                newConfig.seq = mConfigurationSeq;
                 mConfiguration = newConfig;
                 Log.i(TAG, "Config changed: " + newConfig);
                 
@@ -13146,6 +13145,10 @@
             }
         }
         
+        if (values != null && mWindowManager != null) {
+            mWindowManager.setNewConfiguration(mConfiguration);
+        }
+        
         return kept;
     }
 
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/test-runner/android/test/mock/MockPackageManager.java b/test-runner/android/test/mock/MockPackageManager.java
index f1ba44a..2ccc9bb 100644
--- a/test-runner/android/test/mock/MockPackageManager.java
+++ b/test-runner/android/test/mock/MockPackageManager.java
@@ -26,6 +26,7 @@
 import android.content.pm.IPackageDeleteObserver;
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.IPackageInstallObserver;
+import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageStatsObserver;
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.PackageInfo;
@@ -308,6 +309,14 @@
             int flags, String installerPackageName) {
         throw new UnsupportedOperationException();
     }
+
+    /**
+     * @hide - to match hiding in superclass
+     */
+    @Override
+    public void movePackage(String packageName, IPackageMoveObserver observer, int flags) {
+        throw new UnsupportedOperationException();
+    }
     
     @Override
     public String getInstallerPackageName(String packageName) {
diff --git a/tests/AndroidTests/AndroidManifest.xml b/tests/AndroidTests/AndroidManifest.xml
index 28f1e73..e06c3a8 100644
--- a/tests/AndroidTests/AndroidManifest.xml
+++ b/tests/AndroidTests/AndroidManifest.xml
@@ -28,6 +28,7 @@
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
     <uses-permission android:name="android.permission.INSTALL_PACKAGES" />
     <uses-permission android:name="android.permission.DELETE_PACKAGES" />
+    <uses-permission android:name="android.permission.MOVE_PACKAGE" />
     <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
     <uses-permission android:name="android.permission.ASEC_ACCESS" />
     <uses-permission android:name="android.permission.ASEC_CREATE" />
diff --git a/tests/AndroidTests/res/raw/install_loc_auto b/tests/AndroidTests/res/raw/install_loc_auto
index 60dda18..d5d2739 100644
--- a/tests/AndroidTests/res/raw/install_loc_auto
+++ b/tests/AndroidTests/res/raw/install_loc_auto
Binary files differ
diff --git a/tests/AndroidTests/res/raw/install_loc_internal b/tests/AndroidTests/res/raw/install_loc_internal
index 1bc33ca..eb6279a 100644
--- a/tests/AndroidTests/res/raw/install_loc_internal
+++ b/tests/AndroidTests/res/raw/install_loc_internal
Binary files differ
diff --git a/tests/AndroidTests/res/raw/install_loc_sdcard b/tests/AndroidTests/res/raw/install_loc_sdcard
index 6604e35..c774989 100644
--- a/tests/AndroidTests/res/raw/install_loc_sdcard
+++ b/tests/AndroidTests/res/raw/install_loc_sdcard
Binary files differ
diff --git a/tests/AndroidTests/res/raw/install_loc_unspecified b/tests/AndroidTests/res/raw/install_loc_unspecified
index 88bbace..ab226c6 100644
--- a/tests/AndroidTests/res/raw/install_loc_unspecified
+++ b/tests/AndroidTests/res/raw/install_loc_unspecified
Binary files differ
diff --git a/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java b/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java
index bdf397c..3bbb447 100755
--- a/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java
@@ -78,6 +78,60 @@
         }
     }
 
+    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,143 +154,174 @@
     }
 
     public void testCreateContainer() {
-        Assert.assertTrue(isMediaMounted());
-        IMountService ms = getMs();
         try {
-            int rc = ms.createSecureContainer("com.android.unittests.AsecTests.testCreateContainer",
-                    4, "fat", "none", android.os.Process.myUid());
-            Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
-        } catch (Exception e) {
-            failStr(e);
-        }
-    }
-
-    public void testCreateZeroSizeContainer() {
-        Assert.assertTrue(isMediaMounted());
-        IMountService ms = getMs();
-        try {
-            int rc = ms.createSecureContainer("com.android.unittests.AsecTests.testCreateZeroSizeContainer",
-                    0, "fat", "none", android.os.Process.myUid());
-            Assert.assertEquals(StorageResultCode.OperationFailedInternalError, rc);
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    createContainer("testCreateContainer", 4, "none"));
+            Assert.assertEquals(true, containerExists("testCreateContainer"));
         } catch (Exception e) {
             failStr(e);
         }
     }
 
     public void testCreateMinSizeContainer() {
-        Assert.assertTrue(isMediaMounted());
-        IMountService ms = getMs();
         try {
-            int rc = ms.createSecureContainer("com.android.unittests.AsecTests.testCreateMinSizeContainer",
-                    1, "fat", "none", android.os.Process.myUid());
-            Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
+            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", android.os.Process.myUid());
-            Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
-            rc = ms.destroySecureContainer("com.android.unittests.AsecTests.testDestroyContainer", true);
-            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", android.os.Process.myUid());
-            Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    createContainer("testMountContainer", 4, "none"));
 
-            rc = ms.unmountSecureContainer("com.android.unittests.AsecTests.testMountContainer", false);
-            Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    unmountContainer("testMountContainer", false));
 
-            rc = ms.mountSecureContainer("com.android.unittests.AsecTests.testMountContainer", "none",
-                    android.os.Process.myUid());
-            Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    mountContainer("testMountContainer", "none"));
         } catch (Exception e) {
             failStr(e);
         }
     }
 
     public void testMountBadKey() {
-        Assert.assertTrue(isMediaMounted());
-        IMountService ms = getMs();
         try {
-            int rc = ms.createSecureContainer(
-                    "com.android.unittests.AsecTests.testMountBadKey", 4, "fat",
-                            "00000000000000000000000000000000", android.os.Process.myUid());
-            Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    createContainer("testMountBadKey", 4, "00000000000000000000000000000000"));
 
-            rc = ms.unmountSecureContainer("com.android.unittests.AsecTests.testMountBadKey", false);
-            Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    unmountContainer("testMountBadKey", false));
 
-            rc = ms.mountSecureContainer(
-                    "com.android.unittests.AsecTests.testMountBadKey",
-                            "00000000000000000000000000000001", 1001);
-            Assert.assertEquals(StorageResultCode.OperationFailedInternalError, rc);
+            Assert.assertEquals(StorageResultCode.OperationFailedInternalError,
+                    mountContainer("testMountContainer", "000000000000000000000000000000001"));
 
-            rc = ms.mountSecureContainer(
-                    "com.android.unittests.AsecTests.testMountBadKey", "none", 1001);
-            Assert.assertEquals(StorageResultCode.OperationFailedInternalError, rc);
+            Assert.assertEquals(StorageResultCode.OperationFailedInternalError,
+                    mountContainer("testMountContainer", "none"));
         } catch (Exception e) {
             failStr(e);
         }
     }
 
     public void testUnmountBusyContainer() {
-        Assert.assertTrue(isMediaMounted());
         IMountService ms = getMs();
         try {
-            int rc = ms.createSecureContainer("com.android.unittests.AsecTests.testUnmountBusyContainer",
-                    4, "fat", "none", android.os.Process.myUid());
-            Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    createContainer("testUnmountBusyContainer", 4, "none"));
 
             String path = ms.getSecureContainerPath("com.android.unittests.AsecTests.testUnmountBusyContainer");
-            Context con = super.getContext();
 
             File f = new File(path, "reference");
             FileOutputStream fos = new FileOutputStream(f);
-            rc = ms.unmountSecureContainer("com.android.unittests.AsecTests.testUnmountBusyContainer", false);
-            Assert.assertEquals(StorageResultCode.OperationFailedStorageBusy, rc);
-            fos.close();
 
-            rc = ms.unmountSecureContainer("com.android.unittests.AsecTests.testUnmountBusyContainer", false);
-            Assert.assertEquals(StorageResultCode.OperationSucceeded, 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() {
-        Assert.assertTrue(isMediaMounted());
         IMountService ms = getMs();
         try {
-            int rc = ms.createSecureContainer("com.android.unittests.AsecTests.testUnmountBusyContainer",
-                    4, "fat", "none", android.os.Process.myUid());
-            Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    createContainer("testDestroyBusyContainer", 4, "none"));
 
-            String path = ms.getSecureContainerPath("com.android.unittests.AsecTests.testUnmountBusyContainer");
-            Context con = super.getContext();
+            String path = ms.getSecureContainerPath("com.android.unittests.AsecTests.testDestroyBusyContainer");
 
             File f = new File(path, "reference");
             FileOutputStream fos = new FileOutputStream(f);
-            rc = ms.destroySecureContainer("com.android.unittests.AsecTests.testUnmountBusyContainer", false);
-            Assert.assertEquals(StorageResultCode.OperationFailedStorageBusy, rc);
-            fos.close();
 
-            rc = ms.destroySecureContainer("com.android.unittests.AsecTests.testUnmountBusyContainer", false);
-            Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
+            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 be9571c..9c5c44d 100755
--- a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
@@ -37,6 +37,7 @@
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.IPackageInstallObserver;
 import android.content.pm.IPackageDeleteObserver;
+import android.content.pm.IPackageMoveObserver;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageParser;
@@ -159,6 +160,7 @@
         PackageInstallObserver observer = new PackageInstallObserver();
         final boolean received = false;
         mContext.registerReceiver(receiver, receiver.filter);
+        final boolean DEBUG = true;
         try {
             // Wait on observer
             synchronized(observer) {
@@ -173,6 +175,7 @@
                         throw new Exception("Timed out waiting for packageInstalled callback");
                     }
                     if (observer.returnCode != PackageManager.INSTALL_SUCCEEDED) {
+                        Log.i(TAG, "Failed to install with error code = " + observer.returnCode);
                         return false;
                     }
                     // Verify we received the broadcast
@@ -237,7 +240,9 @@
         File sourceFile = new File(archiveFilePath);
         DisplayMetrics metrics = new DisplayMetrics();
         metrics.setToDefaults();
-        return packageParser.parsePackage(sourceFile, archiveFilePath, metrics, 0);
+        PackageParser.Package pkg = packageParser.parsePackage(sourceFile, archiveFilePath, metrics, 0);
+        packageParser = null;
+        return pkg;
     }
 
     private void assertInstall(String pkgName, int flags) {
@@ -297,6 +302,25 @@
         return installFromRawResource("install.apk", R.raw.install, flags, cleanUp,
                 false, -1);
     }
+
+    public void clearSecureContainersForPkg(String pkgName) {
+        IMountService ms = getMs();
+        try {
+            String list[] = ms.getSecureContainerList();
+            if (list != null) {
+                for (String cid : list) {
+                    boolean delete = false;
+                    // STOPSHIP issues with rename should be fixed.
+                    if (cid.contains(pkgName) ||
+                            cid.contains("smdltmp")) {
+                        Log.i(TAG, "Destroying container " + cid);
+                        ms.destroySecureContainer(cid, true);
+                    }
+                }
+            }
+        } catch (RemoteException e) {}
+    }
+
     /*
      * Utility function that reads a apk bundled as a raw resource
      * copies it into own data directory and invokes
@@ -310,11 +334,15 @@
         PackageParser.Package pkg = parsePackage(packageURI);
         assertNotNull(pkg);
         InstallParams ip = null;
+        // Make sure the package doesn't exist
+        getPm().deletePackage(pkg.packageName, null, 0);
+        // Clean up the containers as well
+        if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) {
+            clearSecureContainersForPkg(pkg.packageName);
+        }
         try {
             try {
                 if (fail) {
-                    // Make sure it doesn't exist
-                    getPm().deletePackage(pkg.packageName, null, 0);
                     assertTrue(invokeInstallPackageFail(packageURI, flags,
                             pkg.packageName, result));
                     assertNotInstalled(pkg.packageName);
@@ -811,7 +839,7 @@
 
     public void testManifestInstallLocationSdcard() {
         installFromRawResource("install.apk", R.raw.install_loc_sdcard,
-                PackageManager.INSTALL_EXTERNAL, true, false, -1);
+                0, true, false, -1);
     }
 
     public void testManifestInstallLocationAuto() {
@@ -826,10 +854,186 @@
 
     public void testManifestInstallLocationFwdLockedSdcard() {
         installFromRawResource("install.apk", R.raw.install_loc_sdcard,
-                PackageManager.INSTALL_FORWARD_LOCK |
-                PackageManager.INSTALL_EXTERNAL, true, true,
+                PackageManager.INSTALL_FORWARD_LOCK, true, true,
                 PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION);
     }
+
+    public void xxxtestClearAllSecureContainers() {
+        IMountService ms = getMs();
+        try {
+            String list[] = ms.getSecureContainerList();
+            if (list != null) {
+                for (String cid : list) {
+                    Log.i(TAG, "Destroying container " + cid);
+                    ms.destroySecureContainer(cid, false);
+                }
+            }
+        } catch (RemoteException e) {}
+    }
+
+    class MoveReceiver extends GenericReceiver {
+        String pkgName;
+        final static int INVALID = -1;
+        final static int REMOVED = 1;
+        final static int ADDED = 2;
+        int removed = INVALID;
+
+        MoveReceiver(String pkgName) {
+            this.pkgName = pkgName;
+            filter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
+            filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
+            super.setFilter(filter);
+        }
+
+        public boolean notifyNow(Intent intent) {
+            String action = intent.getAction();
+            Log.i(TAG, "MoveReceiver::" + action);
+            if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
+                String[] list = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+                if (list != null) {
+                    for (String pkg : list) {
+                        if (pkg.equals(pkgName)) {
+                            removed = REMOVED;
+                            break;
+                        }
+                    }
+                }
+                removed = REMOVED;
+            } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
+                if (removed != REMOVED) {
+                    return false;
+                }
+                String[] list = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+                if (list != null) {
+                    for (String pkg : list) {
+                        if (pkg.equals(pkgName)) {
+                            removed = ADDED;
+                            return true;
+                        }
+                    }
+                }
+            }
+            return false;
+        }
+    }
+
+    private class PackageMoveObserver extends IPackageMoveObserver.Stub {
+        public int returnCode;
+        private boolean doneFlag = false;
+
+        public void packageMoved(String packageName, int returnCode) {
+            synchronized(this) {
+                this.returnCode = returnCode;
+                doneFlag = true;
+                notifyAll();
+            }
+        }
+
+        public boolean isDone() {
+            return doneFlag;
+        }
+    }
+
+    public boolean invokeMovePackage(String pkgName, int flags,
+            GenericReceiver receiver) throws Exception {
+        PackageMoveObserver observer = new PackageMoveObserver();
+        final boolean received = false;
+        mContext.registerReceiver(receiver, receiver.filter);
+        try {
+            // Wait on observer
+            synchronized(observer) {
+                synchronized (receiver) {
+                    getPm().movePackage(pkgName, observer, flags);
+                    long waitTime = 0;
+                    while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
+                        observer.wait(WAIT_TIME_INCR);
+                        waitTime += WAIT_TIME_INCR;
+                    }
+                    if(!observer.isDone()) {
+                        throw new Exception("Timed out waiting for pkgmove callback");
+                    }
+                    if (observer.returnCode != PackageManager.MOVE_SUCCEEDED) {
+                        return false;
+                    }
+                    // Verify we received the broadcast
+                    waitTime = 0;
+                    while((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
+                        receiver.wait(WAIT_TIME_INCR);
+                        waitTime += WAIT_TIME_INCR;
+                    }
+                    if(!receiver.isDone()) {
+                        throw new Exception("Timed out waiting for MOVE notifications");
+                    }
+                    return receiver.received;
+                }
+            }
+        } finally {
+            mContext.unregisterReceiver(receiver);
+        }
+    }
+
+    /*
+     * Utility function that reads a apk bundled as a raw resource
+     * copies it into own data directory and invokes
+     * PackageManager api to install first and then replace it
+     * again.
+     */
+    public void moveFromRawResource(int installFlags, int moveFlags,
+            int expRetCode) {
+        // Install first
+        InstallParams ip = sampleInstallFromRawResource(installFlags, false);
+        ApplicationInfo oldAppInfo = null;
+        try {
+            oldAppInfo = getPm().getApplicationInfo(ip.pkg.packageName, 0);
+        } catch (NameNotFoundException e) {
+            failStr("Pkg hasnt been installed correctly");
+        }
+
+        // Create receiver based on expRetCode
+        MoveReceiver receiver = new MoveReceiver(ip.pkg.packageName);
+        try {
+            boolean retCode = invokeMovePackage(ip.pkg.packageName, moveFlags,
+                    receiver);
+            if (expRetCode == PackageManager.MOVE_SUCCEEDED) {
+                assertTrue(retCode);
+                ApplicationInfo info = getPm().getApplicationInfo(ip.pkg.packageName, 0);
+                assertNotNull(info);
+                if ((moveFlags & PackageManager.MOVE_INTERNAL) != 0) {
+                    assertTrue((info.flags & ApplicationInfo.FLAG_ON_SDCARD) == 0);
+                } else if ((moveFlags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0){
+                    assertTrue((info.flags & ApplicationInfo.FLAG_ON_SDCARD) != 0);
+                }
+            } else {
+                assertFalse(retCode);
+                ApplicationInfo info = getPm().getApplicationInfo(ip.pkg.packageName, 0);
+                assertNotNull(info);
+                assertEquals(oldAppInfo.flags, info.flags);
+            }
+        } catch (Exception e) {
+            failStr("Failed with exception : " + e);
+        } finally {
+            cleanUpInstall(ip);
+        }
+    }
+
+    public void testMoveAppInternalToExternal() {
+        moveFromRawResource(0, PackageManager.MOVE_EXTERNAL_MEDIA,
+                PackageManager.MOVE_SUCCEEDED);
+    }
+
+    public void testMoveAppInternalToInternal() {
+        moveFromRawResource(0, PackageManager.MOVE_INTERNAL,
+                PackageManager.MOVE_FAILED_INVALID_LOCATION);
+    }
+
+    public void testMoveAppExternalToExternal() {
+        moveFromRawResource(PackageManager.INSTALL_EXTERNAL, PackageManager.MOVE_EXTERNAL_MEDIA,
+                PackageManager.MOVE_FAILED_INVALID_LOCATION);
+    }
+    public void testMoveAppExternalToInternal() {
+        moveFromRawResource(PackageManager.INSTALL_EXTERNAL, PackageManager.MOVE_INTERNAL,
+                PackageManager.MOVE_SUCCEEDED);
+    }
     /*
      * TODO's
      * check version numbers for upgrades
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 dc442aa..69b2207 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -985,14 +985,14 @@
     uint8_t mask = 0;
     uint8_t value = 0;
     if (strcmp(name, kWildcardName) == 0) {
-        mask = out->MASK_NAVHIDDEN;
-        value = out->NAVHIDDEN_ANY;
+        mask = ResTable_config::MASK_NAVHIDDEN;
+        value = ResTable_config::NAVHIDDEN_ANY;
     } else if (strcmp(name, "navexposed") == 0) {
-        mask = out->MASK_NAVHIDDEN;
-        value = out->NAVHIDDEN_NO;
+        mask = ResTable_config::MASK_NAVHIDDEN;
+        value = ResTable_config::NAVHIDDEN_NO;
     } else if (strcmp(name, "navhidden") == 0) {
-        mask = out->MASK_NAVHIDDEN;
-        value = out->NAVHIDDEN_YES;
+        mask = ResTable_config::MASK_NAVHIDDEN;
+        value = ResTable_config::NAVHIDDEN_YES;
     }
 
     if (mask != 0) {
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.
         }