Merge "Update status bar icons for BT reverse tethering." into honeycomb
diff --git a/api/11.xml b/api/11.xml
index 43bb440..e2f8025 100644
--- a/api/11.xml
+++ b/api/11.xml
@@ -61129,17 +61129,6 @@
  visibility="public"
 >
 </method>
-<method name="getGL"
- return="javax.microedition.khronos.opengles.GL"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="getHeight"
  return="int"
  abstract="false"
diff --git a/api/current.xml b/api/current.xml
index 57a76de..8b0c555 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -1255,17 +1255,6 @@
  visibility="public"
 >
 </field>
-<field name="WRITE_MEDIA_STORAGE"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;android.permission.WRITE_MEDIA_STORAGE&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="WRITE_SECURE_SETTINGS"
  type="java.lang.String"
  transient="false"
@@ -1486,7 +1475,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="17432591"
+ value="17432589"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1519,29 +1508,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="17432593"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="animator_fade_in"
- type="int"
- transient="false"
- volatile="false"
- value="17432589"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="animator_fade_out"
- type="int"
- transient="false"
- volatile="false"
- value="17432590"
+ value="17432591"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1596,7 +1563,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="17432592"
+ value="17432590"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1618,7 +1585,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="17432594"
+ value="17432592"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -19996,6 +19963,42 @@
 </parameter>
 </method>
 </class>
+<class name="ArgbEvaluator"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.animation.TypeEvaluator">
+</implements>
+<constructor name="ArgbEvaluator"
+ type="android.animation.ArgbEvaluator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="evaluate"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fraction" type="float">
+</parameter>
+<parameter name="startValue" type="java.lang.Object">
+</parameter>
+<parameter name="endValue" type="java.lang.Object">
+</parameter>
+</method>
+</class>
 <class name="DoubleEvaluator"
  extends="java.lang.Object"
  abstract="false"
@@ -20962,42 +20965,6 @@
 </parameter>
 </method>
 </class>
-<class name="RGBEvaluator"
- extends="java.lang.Object"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<implements name="android.animation.TypeEvaluator">
-</implements>
-<constructor name="RGBEvaluator"
- type="android.animation.RGBEvaluator"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<method name="evaluate"
- return="java.lang.Object"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="fraction" type="float">
-</parameter>
-<parameter name="startValue" type="java.lang.Object">
-</parameter>
-<parameter name="endValue" type="java.lang.Object">
-</parameter>
-</method>
-</class>
 <interface name="TimeInterpolator"
  abstract="true"
  static="false"
@@ -58409,6 +58376,17 @@
  visibility="public"
 >
 </method>
+<method name="isEnabled"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <field name="applicationInfo"
  type="android.content.pm.ApplicationInfo"
  transient="false"
@@ -78255,17 +78233,6 @@
  visibility="public"
 >
 </method>
-<method name="getGL"
- return="javax.microedition.khronos.opengles.GL"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="deprecated"
- visibility="protected"
->
-</method>
 <method name="getHeight"
  return="int"
  abstract="false"
@@ -136934,6 +136901,19 @@
  deprecated="not deprecated"
  visibility="protected"
 >
+<parameter name="result" type="Result">
+</parameter>
+</method>
+<method name="onCancelled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
 </method>
 <method name="onPostExecute"
  return="void"
@@ -140826,6 +140806,17 @@
  visibility="public"
 >
 </method>
+<method name="isExternalStorageEmulated"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isExternalStorageRemovable"
  return="boolean"
  abstract="false"
@@ -166353,8 +166344,6 @@
 </parameter>
 <parameter name="mips" type="android.renderscript.Allocation.MipmapControl">
 </parameter>
-<parameter name="layout" type="android.renderscript.Allocation.CubemapLayout">
-</parameter>
 <parameter name="usage" type="int">
 </parameter>
 </method>
@@ -166372,8 +166361,6 @@
 </parameter>
 <parameter name="b" type="android.graphics.Bitmap">
 </parameter>
-<parameter name="layout" type="android.renderscript.Allocation.CubemapLayout">
-</parameter>
 </method>
 <method name="createFromBitmap"
  return="android.renderscript.Allocation"
@@ -166633,39 +166620,6 @@
 >
 </field>
 </class>
-<class name="Allocation.CubemapLayout"
- extends="java.lang.Enum"
- abstract="false"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-<method name="valueOf"
- return="android.renderscript.Allocation.CubemapLayout"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="name" type="java.lang.String">
-</parameter>
-</method>
-<method name="values"
- return="android.renderscript.Allocation.CubemapLayout[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-</class>
 <class name="Allocation.MipmapControl"
  extends="java.lang.Enum"
  abstract="false"
@@ -198616,6 +198570,17 @@
 <exception name="IOException" type="java.io.IOException">
 </exception>
 </method>
+<method name="isLenient"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="nextBoolean"
  return="boolean"
  abstract="false"
@@ -198746,21 +198711,6 @@
 <exception name="IOException" type="java.io.IOException">
 </exception>
 </method>
-<method name="syntaxError"
- return="java.io.IOException"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="message" type="java.lang.String">
-</parameter>
-<exception name="IOException" type="java.io.IOException">
-</exception>
-</method>
 </class>
 <class name="JsonToken"
  extends="java.lang.Enum"
@@ -198893,6 +198843,17 @@
 <exception name="IOException" type="java.io.IOException">
 </exception>
 </method>
+<method name="isLenient"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="name"
  return="android.util.JsonWriter"
  abstract="false"
@@ -198934,6 +198895,19 @@
 <parameter name="indent" type="java.lang.String">
 </parameter>
 </method>
+<method name="setLenient"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="lenient" type="boolean">
+</parameter>
+</method>
 <method name="value"
  return="android.util.JsonWriter"
  abstract="false"
@@ -198994,6 +198968,21 @@
 <exception name="IOException" type="java.io.IOException">
 </exception>
 </method>
+<method name="value"
+ return="android.util.JsonWriter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.Number">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
 </class>
 <class name="Log"
  extends="java.lang.Object"
@@ -199373,6 +199362,25 @@
 </parameter>
 </method>
 </class>
+<class name="MalformedJsonException"
+ extends="java.io.IOException"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="MalformedJsonException"
+ type="android.util.MalformedJsonException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
 <class name="MonthDisplayHelper"
  extends="java.lang.Object"
  abstract="false"
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java
index 6e589e4..bcab66e 100644
--- a/core/java/android/animation/AnimatorInflater.java
+++ b/core/java/android/animation/AnimatorInflater.java
@@ -215,7 +215,7 @@
                 (toType <= TypedValue.TYPE_LAST_COLOR_INT))) {
             // special case for colors: ignore valueType and get ints
             getFloats = false;
-            anim.setEvaluator(new RGBEvaluator());
+            anim.setEvaluator(new ArgbEvaluator());
         }
 
         if (getFloats) {
diff --git a/core/java/android/animation/RGBEvaluator.java b/core/java/android/animation/ArgbEvaluator.java
similarity index 97%
rename from core/java/android/animation/RGBEvaluator.java
rename to core/java/android/animation/ArgbEvaluator.java
index bae0af0..c3875be 100644
--- a/core/java/android/animation/RGBEvaluator.java
+++ b/core/java/android/animation/ArgbEvaluator.java
@@ -20,7 +20,7 @@
  * This evaluator can be used to perform type interpolation between integer
  * values that represent ARGB colors.
  */
-public class RGBEvaluator implements TypeEvaluator {
+public class ArgbEvaluator implements TypeEvaluator {
 
     /**
      * This function returns the calculated in-between value for a color
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index cfecec1..f884473 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -862,7 +862,7 @@
      * of <code>startValue</code> and <code>endValue</code> in the constructor. But if these values
      * are not one of these primitive types, or if different evaluation is desired (such as is
      * necessary with int values that represent colors), a custom evaluator needs to be assigned.
-     * For example, when running an animation on color values, the {@link RGBEvaluator}
+     * For example, when running an animation on color values, the {@link ArgbEvaluator}
      * should be used to get correct RGB color interpolation.
      *
      * <p>If this ValueAnimator has only one set of values being animated between, this evaluator
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 8b292c9..2fa2834 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -237,43 +237,7 @@
     private BroadcastReceiver mConnectivityIntentReceiver =
             new BroadcastReceiver() {
         public void onReceive(Context context, Intent intent) {
-            NetworkInfo networkInfo =
-                    intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
-            NetworkInfo.State state = (networkInfo == null ? NetworkInfo.State.UNKNOWN :
-                    networkInfo.getState());
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "received connectivity action.  network info: " + networkInfo);
-            }
-
-            final boolean wasConnected = mDataConnectionIsConnected;
-            // only pay attention to the CONNECTED and DISCONNECTED states.
-            // if connected, we are connected.
-            // if disconnected, we may not be connected.  in some cases, we may be connected on
-            // a different network.
-            // e.g., if switching from GPRS to WiFi, we may receive the CONNECTED to WiFi and
-            // DISCONNECTED for GPRS in any order.  if we receive the CONNECTED first, and then
-            // a DISCONNECTED, we want to make sure we set mDataConnectionIsConnected to true
-            // since we still have a WiFi connection.
-            switch (state) {
-                case CONNECTED:
-                    mDataConnectionIsConnected = true;
-                    break;
-                case DISCONNECTED:
-                    mDataConnectionIsConnected = !intent.getBooleanExtra(
-                            ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
-                    break;
-                default:
-                    // ignore the rest of the states -- leave our boolean alone.
-            }
-            if (mDataConnectionIsConnected) {
-                if (!wasConnected) {
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.v(TAG, "Reconnection detected: clearing all backoffs");
-                    }
-                    mSyncStorageEngine.clearAllBackoffs();
-                }
-                sendCheckAlarmsMessage();
-            }
+            sendCheckAlarmsMessage();
         }
     };
 
@@ -1409,8 +1373,12 @@
         public void handleMessage(Message msg) {
             long earliestFuturePollTime = Long.MAX_VALUE;
             long nextPendingSyncTime = Long.MAX_VALUE;
+            // Setting the value here instead of a method because we want the dumpsys logs
+            // to have the most recent value used.
             try {
                 waitUntilReadyToRun();
+                NetworkInfo networkInfo = getConnectivityManager().getActiveNetworkInfo();
+                mDataConnectionIsConnected = (networkInfo != null) && networkInfo.isConnected();
                 mSyncManagerWakeLock.acquire();
                 // Always do this first so that we be sure that any periodic syncs that
                 // are ready to run have been converted into pending syncs. This allows the
diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java
index f16c4ef..2812477 100644
--- a/core/java/android/content/pm/ComponentInfo.java
+++ b/core/java/android/content/pm/ComponentInfo.java
@@ -98,6 +98,13 @@
         }
         return name;
     }
+
+    /**
+     * Return whether this component and its enclosing application are enabled.
+     */
+    public boolean isEnabled() {
+        return enabled && applicationInfo.enabled;
+    }
     
     /**
      * Return the icon resource identifier to use for this component.  If
diff --git a/core/java/android/database/sqlite/SQLiteStatement.java b/core/java/android/database/sqlite/SQLiteStatement.java
index 5e96928..c76cc6c 100644
--- a/core/java/android/database/sqlite/SQLiteStatement.java
+++ b/core/java/android/database/sqlite/SQLiteStatement.java
@@ -131,6 +131,10 @@
             long retValue = native_1x1_long();
             mDatabase.logTimeStat(mSql, timeStart);
             return retValue;
+        } catch (SQLiteDoneException e) {
+            throw new SQLiteDoneException(
+                    "expected 1 row from this query but query returned no data. check the query: " +
+                    mSql);
         } finally {
             releaseAndUnlock();
         }
@@ -150,6 +154,10 @@
             String retValue = native_1x1_string();
             mDatabase.logTimeStat(mSql, timeStart);
             return retValue;
+        } catch (SQLiteDoneException e) {
+            throw new SQLiteDoneException(
+                    "expected 1 row from this query but query returned no data. check the query: " +
+                    mSql);
         } finally {
             releaseAndUnlock();
         }
@@ -172,6 +180,10 @@
         } catch (IOException ex) {
             Log.e(TAG, "simpleQueryForBlobFileDescriptor() failed", ex);
             return null;
+        } catch (SQLiteDoneException e) {
+            throw new SQLiteDoneException(
+                    "expected 1 row from this query but query returned no data. check the query: " +
+                    mSql);
         } finally {
             releaseAndUnlock();
         }
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java
index 46a29a9..9f7e31c 100644
--- a/core/java/android/os/AsyncTask.java
+++ b/core/java/android/os/AsyncTask.java
@@ -26,6 +26,7 @@
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
@@ -115,11 +116,11 @@
  * <h2>Cancelling a task</h2>
  * <p>A task can be cancelled at any time by invoking {@link #cancel(boolean)}. Invoking
  * this method will cause subsequent calls to {@link #isCancelled()} to return true.
- * After invoking this method, {@link #onCancelled()}, instead of {@link #onPostExecute(Object)}
- * will be invoked after {@link #doInBackground(Object[])} returns. To ensure that
- * a task is cancelled as quickly as possible, you should always check the return
- * value of {@link #isCancelled()} periodically from {@link #doInBackground(Object[])},
- * if possible (inside a loop for instance.)</p>
+ * After invoking this method, {@link #onCancelled(Object)}, instead of
+ * {@link #onPostExecute(Object)} will be invoked after {@link #doInBackground(Object[])}
+ * returns. To ensure that a task is cancelled as quickly as possible, you should always
+ * check the return value of {@link #isCancelled()} periodically from
+ * {@link #doInBackground(Object[])}, if possible (inside a loop for instance.)</p>
  *
  * <h2>Threading rules</h2>
  * <p>There are a few threading rules that must be followed for this class to
@@ -173,6 +174,8 @@
     private final FutureTask<Result> mFuture;
 
     private volatile Status mStatus = Status.PENDING;
+    
+    private final AtomicBoolean mTaskInvoked = new AtomicBoolean();
 
     /**
      * Indicates the current status of the task. Each status will be set only once
@@ -204,15 +207,10 @@
     public AsyncTask() {
         mWorker = new WorkerRunnable<Params, Result>() {
             public Result call() throws Exception {
+                mTaskInvoked.set(true);
+
                 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
-
-                Result result = doInBackground(mParams);
-
-                Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
-                        new AsyncTaskResult<Result>(AsyncTask.this, result));
-                message.sendToTarget();
-
-                return result;
+                return postResult(doInBackground(mParams));
             }
         };
 
@@ -220,14 +218,16 @@
             @Override
             protected void done() {
                 try {
-                    get();
+                    final Result result = get();
+
+                    postResultIfNotInvoked(result);
                 } catch (InterruptedException e) {
                     android.util.Log.w(LOG_TAG, e);
                 } catch (ExecutionException e) {
                     throw new RuntimeException("An error occured while executing doInBackground()",
                             e.getCause());
                 } catch (CancellationException e) {
-                    // Taken care of in the WorkerRunnable
+                    postResultIfNotInvoked(null);
                 } catch (Throwable t) {
                     throw new RuntimeException("An error occured while executing "
                             + "doInBackground()", t);
@@ -236,6 +236,20 @@
         };
     }
 
+    private void postResultIfNotInvoked(Result result) {
+        final boolean wasTaskInvoked = mTaskInvoked.get();
+        if (!wasTaskInvoked) {
+            postResult(result);
+        }
+    }
+
+    private Result postResult(Result result) {
+        Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
+                new AsyncTaskResult<Result>(this, result));
+        message.sendToTarget();
+        return result;
+    }
+
     /**
      * Returns the current status of this task.
      *
@@ -282,7 +296,7 @@
      *
      * @see #onPreExecute
      * @see #doInBackground
-     * @see #onCancelled() 
+     * @see #onCancelled(Object) 
      */
     @SuppressWarnings({"UnusedDeclaration"})
     protected void onPostExecute(Result result) {
@@ -302,9 +316,33 @@
     }
 
     /**
-     * Runs on the UI thread after {@link #cancel(boolean)} is invoked and
-     * {@link #doInBackground(Object[])} has finished.
+     * <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and
+     * {@link #doInBackground(Object[])} has finished.</p>
+     * 
+     * <p>The default implementation simply invokes {@link #onCancelled()} and
+     * ignores the result. If you write your own implementation, do not call
+     * <code>super.onCancelled(result)</code>.</p>
      *
+     * @param result The result, if any, computed in
+     *               {@link #doInBackground(Object[])}, can be null
+     * 
+     * @see #cancel(boolean)
+     * @see #isCancelled()
+     */
+    @SuppressWarnings({"UnusedParameters"})
+    protected void onCancelled(Result result) {
+        onCancelled();
+    }    
+    
+    /**
+     * <p>Applications should preferably override {@link #onCancelled(Object)}.
+     * This method is invoked by the default implementation of
+     * {@link #onCancelled(Object)}.</p>
+     * 
+     * <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and
+     * {@link #doInBackground(Object[])} has finished.</p>
+     *
+     * @see #onCancelled(Object) 
      * @see #cancel(boolean)
      * @see #isCancelled()
      */
@@ -335,7 +373,7 @@
      * whether the thread executing this task should be interrupted in
      * an attempt to stop the task.</p>
      * 
-     * <p>Calling this method will result in {@link #onCancelled()} being
+     * <p>Calling this method will result in {@link #onCancelled(Object)} being
      * invoked on the UI thread after {@link #doInBackground(Object[])}
      * returns. Calling this method guarantees that {@link #onPostExecute(Object)}
      * is never invoked. After invoking this method, you should check the
@@ -352,7 +390,7 @@
      *         <tt>true</tt> otherwise
      *
      * @see #isCancelled()
-     * @see #onCancelled()
+     * @see #onCancelled(Object)
      */
     public final boolean cancel(boolean mayInterruptIfRunning) {
         return mFuture.cancel(mayInterruptIfRunning);
@@ -452,7 +490,7 @@
 
     private void finish(Result result) {
         if (isCancelled()) {
-            onCancelled();
+            onCancelled(result);
         } else {
             onPostExecute(result);
         }
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 4688847..4f188f8 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -414,8 +414,6 @@
      * emulated. If true, the device does not have real external storage
      * and certain system services such as the package manager use this
      * to determine where to install an application.
-     *
-     * @hide
      */
     public static boolean isExternalStorageEmulated() {
         if (mIsExternalStorageEmulated == null) {
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index d1ca0c9..ee091f0 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -3430,12 +3430,6 @@
      * <th colspan='4'>PhoneLookup</th>
      * </tr>
      * <tr>
-     * <td>long</td>
-     * <td>{@link #_ID}</td>
-     * <td>read-only</td>
-     * <td>Data row ID.</td>
-     * </tr>
-     * <tr>
      * <td>String</td>
      * <td>{@link #NUMBER}</td>
      * <td>read-only</td>
@@ -3462,6 +3456,12 @@
      * <th colspan='4'>Join with {@link Contacts}</th>
      * </tr>
      * <tr>
+     * <td>long</td>
+     * <td>{@link #_ID}</td>
+     * <td>read-only</td>
+     * <td>Contact ID.</td>
+     * </tr>
+     * <tr>
      * <td>String</td>
      * <td>{@link #LOOKUP_KEY}</td>
      * <td>read-only</td>
diff --git a/core/java/android/util/JsonReader.java b/core/java/android/util/JsonReader.java
index 8025545..8f44895 100644
--- a/core/java/android/util/JsonReader.java
+++ b/core/java/android/util/JsonReader.java
@@ -16,6 +16,7 @@
 
 package android.util;
 
+import java.io.EOFException;
 import java.io.IOException;
 import java.io.Reader;
 import java.io.Closeable;
@@ -249,6 +250,13 @@
     }
 
     /**
+     * Returns true if this parser is liberal in what it accepts.
+     */
+    public boolean isLenient() {
+        return lenient;
+    }
+
+    /**
      * Consumes the next token from the JSON stream and asserts that it is the
      * beginning of a new array.
      */
@@ -311,7 +319,7 @@
             case EMPTY_DOCUMENT:
                 replaceTop(JsonScope.NONEMPTY_DOCUMENT);
                 JsonToken firstToken = nextValue();
-                if (token != JsonToken.BEGIN_ARRAY && token != JsonToken.BEGIN_OBJECT) {
+                if (!lenient && token != JsonToken.BEGIN_ARRAY && token != JsonToken.BEGIN_OBJECT) {
                     throw new IOException(
                             "Expected JSON document to start with '[' or '{' but was " + token);
                 }
@@ -327,7 +335,15 @@
             case NONEMPTY_OBJECT:
                 return nextInObject(false);
             case NONEMPTY_DOCUMENT:
-                return token = JsonToken.END_DOCUMENT;
+                try {
+                    JsonToken token = nextValue();
+                    if (lenient) {
+                        return token;
+                    }
+                    throw syntaxError("Expected EOF");
+                } catch (EOFException e) {
+                    return token = JsonToken.END_DOCUMENT; // TODO: avoid throwing here?
+                }
             case CLOSED:
                 throw new IllegalStateException("JsonReader is closed");
             default:
@@ -758,7 +774,7 @@
             }
         }
 
-        throw syntaxError("End of input");
+        throw new EOFException("End of input");
     }
 
     private void checkLenient() throws IOException {
@@ -1030,8 +1046,6 @@
      * form -12.34e+56. Fractional and exponential parts are optional. Leading
      * zeroes are not allowed in the value or exponential part, but are allowed
      * in the fraction.
-     *
-     * <p>This has a side effect of setting isInteger.
      */
     private JsonToken decodeNumber(char[] chars, int offset, int length) {
         int i = offset;
@@ -1085,8 +1099,8 @@
      * Throws a new IO exception with the given message and a context snippet
      * with this reader's content.
      */
-    public IOException syntaxError(String message) throws IOException {
-        throw new JsonSyntaxException(message + " near " + getSnippet());
+    private IOException syntaxError(String message) throws IOException {
+        throw new MalformedJsonException(message + " near " + getSnippet());
     }
 
     private CharSequence getSnippet() {
@@ -1097,10 +1111,4 @@
         snippet.append(buffer, pos, afterPos);
         return snippet;
     }
-
-    private static class JsonSyntaxException extends IOException {
-        private JsonSyntaxException(String s) {
-            super(s);
-        }
-    }
 }
diff --git a/core/java/android/util/JsonWriter.java b/core/java/android/util/JsonWriter.java
index 89cad79..47e84c5 100644
--- a/core/java/android/util/JsonWriter.java
+++ b/core/java/android/util/JsonWriter.java
@@ -138,6 +138,8 @@
      */
     private String separator = ":";
 
+    private boolean lenient;
+
     /**
      * Creates a new instance that writes a JSON-encoded stream to {@code out}.
      * For best performance, ensure {@link Writer} is buffered; wrapping in
@@ -169,6 +171,29 @@
     }
 
     /**
+     * Configure this writer to relax its syntax rules. By default, this writer
+     * only emits well-formed JSON as specified by <a
+     * href="http://www.ietf.org/rfc/rfc4627.txt">RFC 4627</a>. Setting the writer
+     * to lenient permits the following:
+     * <ul>
+     *   <li>Top-level values of any type. With strict writing, the top-level
+     *       value must be an object or an array.
+     *   <li>Numbers may be {@link Double#isNaN() NaNs} or {@link
+     *       Double#isInfinite() infinities}.
+     * </ul>
+     */
+    public void setLenient(boolean lenient) {
+        this.lenient = lenient;
+    }
+
+    /**
+     * Returns true if this writer has relaxed syntax rules.
+     */
+    public boolean isLenient() {
+        return lenient;
+    }
+
+    /**
      * Begins encoding a new array. Each call to this method must be paired with
      * a call to {@link #endArray}.
      *
@@ -306,11 +331,11 @@
      * Encodes {@code value}.
      *
      * @param value a finite value. May not be {@link Double#isNaN() NaNs} or
-     *     {@link Double#isInfinite() infinities}.
+     *     {@link Double#isInfinite() infinities} unless this writer is lenient.
      * @return this writer.
      */
     public JsonWriter value(double value) throws IOException {
-        if (Double.isNaN(value) || Double.isInfinite(value)) {
+        if (!lenient && (Double.isNaN(value) || Double.isInfinite(value))) {
             throw new IllegalArgumentException("Numeric values must be finite, but was " + value);
         }
         beforeValue(false);
@@ -330,6 +355,28 @@
     }
 
     /**
+     * Encodes {@code value}.
+     *
+     * @param value a finite value. May not be {@link Double#isNaN() NaNs} or
+     *     {@link Double#isInfinite() infinities} unless this writer is lenient.
+     * @return this writer.
+     */
+    public JsonWriter value(Number value) throws IOException {
+        if (value == null) {
+            return nullValue();
+        }
+
+        String string = value.toString();
+        if (!lenient &&
+                (string.equals("-Infinity") || string.equals("Infinity") || string.equals("NaN"))) {
+            throw new IllegalArgumentException("Numeric values must be finite, but was " + value);
+        }
+        beforeValue(false);
+        out.append(string);
+        return this;
+    }
+
+    /**
      * Ensures all buffered data is written to the underlying {@link Writer}
      * and flushes that writer.
      */
@@ -364,7 +411,6 @@
             switch (c) {
                 case '"':
                 case '\\':
-                case '/':
                     out.write('\\');
                     out.write(c);
                     break;
@@ -439,7 +485,7 @@
     private void beforeValue(boolean root) throws IOException {
         switch (peek()) {
             case EMPTY_DOCUMENT: // first in document
-                if (!root) {
+                if (!lenient && !root) {
                     throw new IllegalStateException(
                             "JSON must start with an array or an object.");
                 }
diff --git a/core/java/android/util/MalformedJsonException.java b/core/java/android/util/MalformedJsonException.java
new file mode 100644
index 0000000..63c19ff
--- /dev/null
+++ b/core/java/android/util/MalformedJsonException.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 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.util;
+
+import java.io.IOException;
+
+/**
+ * Thrown when a reader encounters malformed JSON. Some syntax errors can be
+ * ignored by calling {@link JsonReader#setLenient(boolean)}.
+ */
+public final class MalformedJsonException extends IOException {
+    private static final long serialVersionUID = 1L;
+
+    public MalformedJsonException(String message) {
+        super(message);
+    }
+}
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 366393c..7c55f7b 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -1073,11 +1073,6 @@
                             }
                         }
                         surfaceChanged = true;
-
-                        if (mAttachInfo.mHardwareRenderer != null) {
-                            // This will bail out early if already initialized
-                            mAttachInfo.mHardwareRenderer.initialize(mHolder);
-                        }
                     }
                     if (surfaceChanged) {
                         mSurfaceHolderCallback.surfaceChanged(mSurfaceHolder,
diff --git a/core/java/android/webkit/FindActionModeCallback.java b/core/java/android/webkit/FindActionModeCallback.java
index 700d313..a322fa3d 100644
--- a/core/java/android/webkit/FindActionModeCallback.java
+++ b/core/java/android/webkit/FindActionModeCallback.java
@@ -34,7 +34,7 @@
 import android.view.inputmethod.InputMethodManager;
 
 class FindActionModeCallback implements ActionMode.Callback, TextWatcher,
-        View.OnLongClickListener {
+        View.OnLongClickListener, View.OnClickListener {
     private View mCustomView;
     private EditText mEditText;
     private TextView mMatches;
@@ -53,6 +53,7 @@
         // Override long click so that select ActionMode is not opened, which
         // would exit find ActionMode.
         mEditText.setOnLongClickListener(this);
+        mEditText.setOnClickListener(this);
         setText("");
         mMatches = (TextView) mCustomView.findViewById(
                 com.android.internal.R.id.matches);
@@ -105,7 +106,17 @@
             throw new AssertionError(
                     "No WebView for FindActionModeCallback::findNext");
         }
+        if (!mMatchesFound) {
+            findAll();
+            return;
+        }
+        if (0 == mNumberOfMatches) {
+            // There are no matches, so moving to the next match will not do
+            // anything.
+            return;
+        }
         mWebView.findNext(next);
+        updateMatchesString();
     }
 
     /*
@@ -158,6 +169,13 @@
     @Override
     public boolean onLongClick(View v) { return true; }
 
+    // OnClickListener implementation
+
+    @Override
+    public void onClick(View v) {
+        findNext(true);
+    }
+
     // ActionMode.Callback implementation
 
     @Override
@@ -193,15 +211,6 @@
                     "No WebView for FindActionModeCallback::onActionItemClicked");
         }
         mInput.hideSoftInputFromWindow(mWebView.getWindowToken(), 0);
-        if (!mMatchesFound) {
-            findAll();
-            return true;
-        }
-        if (0 == mNumberOfMatches) {
-            // There are no matches, so moving to the next match will not do
-            // anything.
-            return true;
-        }
         switch(item.getItemId()) {
             case com.android.internal.R.id.find_prev:
                 findNext(false);
@@ -212,7 +221,6 @@
             default:
                 return false;
         }
-        updateMatchesString();
         return true;
     }
 
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index 4c2f0b4..1313fcc 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -204,11 +204,6 @@
             case KeyEvent.KEYCODE_DPAD_RIGHT:
             case KeyEvent.KEYCODE_DPAD_UP:
             case KeyEvent.KEYCODE_DPAD_DOWN:
-                if (!mWebView.nativeCursorMatchesFocus()) {
-                    return down ? mWebView.onKeyDown(keyCode, event) : mWebView
-                            .onKeyUp(keyCode, event);
-
-                }
                 isArrowKey = true;
                 break;
         }
@@ -258,10 +253,6 @@
             if (isPopupShowing()) {
                 return super.dispatchKeyEvent(event);
             }
-            if (!mWebView.nativeCursorMatchesFocus()) {
-                return down ? mWebView.onKeyDown(keyCode, event) : mWebView
-                        .onKeyUp(keyCode, event);
-            }
             // Center key should be passed to a potential onClick
             if (!down) {
                 mWebView.centerKeyPressOnTextField();
@@ -753,12 +744,7 @@
         if (event.getAction() != MotionEvent.ACTION_MOVE) {
             return false;
         }
-        // If the Cursor is not on the text input, webview should handle the
-        // trackball
-        if (!mWebView.nativeCursorMatchesFocus()) {
-            return mWebView.onTrackballEvent(event);
-        }
-        Spannable text = (Spannable) getText();
+        Spannable text = getText();
         MovementMethod move = getMovementMethod();
         if (move != null && getLayout() != null &&
             move.onTrackballEvent(this, text, event)) {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 61f0bce..4a9e441 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -56,6 +56,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
+import android.os.SystemClock;
 import android.provider.Settings;
 import android.speech.tts.TextToSpeech;
 import android.text.Selection;
@@ -2617,10 +2618,6 @@
     private int computeRealHorizontalScrollRange() {
         if (mDrawHistory) {
             return mHistoryWidth;
-        } else if (mHorizontalScrollBarMode == SCROLLBAR_ALWAYSOFF
-                && !mZoomManager.canZoomOut()) {
-            // only honor the scrollbar mode when it is at minimum zoom level
-            return computeHorizontalScrollExtent();
         } else {
             // to avoid rounding error caused unnecessary scrollbar, use floor
             return (int) Math.floor(mContentWidth * mZoomManager.getScale());
@@ -2651,10 +2648,6 @@
     private int computeRealVerticalScrollRange() {
         if (mDrawHistory) {
             return mHistoryHeight;
-        } else if (mVerticalScrollBarMode == SCROLLBAR_ALWAYSOFF
-                && !mZoomManager.canZoomOut()) {
-            // only honor the scrollbar mode when it is at minimum zoom level
-            return computeVerticalScrollExtent();
         } else {
             // to avoid rounding error caused unnecessary scrollbar, use floor
             return (int) Math.floor(mContentHeight * mZoomManager.getScale());
@@ -2961,12 +2954,12 @@
      * @return boolean True if the find dialog is shown, false otherwise.
      */
     public boolean showFindDialog(String text, boolean showIme) {
-        mFindCallback = new FindActionModeCallback(mContext);
-        if (startActionMode(mFindCallback) == null) {
+        FindActionModeCallback callback = new FindActionModeCallback(mContext);
+        if (startActionMode(callback) == null) {
             // Could not start the action mode, so end Find on page
-            mFindCallback = null;
             return false;
         }
+        mFindCallback = callback;
         setFindIsUp(true);
         mFindCallback.setWebView(this);
         if (showIme) {
@@ -4564,14 +4557,6 @@
             return true;
         }
 
-        if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT
-                || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
-            if (!nativePageShouldHandleShiftAndArrows() && !nativeCursorWantsKeyEvents()
-                    && !mSelectingText) {
-                setUpSelect();
-            }
-        }
-
         if (keyCode == KeyEvent.KEYCODE_PAGE_UP) {
             if (event.hasNoModifiers()) {
                 pageUp(false);
@@ -4662,12 +4647,6 @@
             if (!wantsKeyEvents) return false;
         }
 
-        if (keyCode != KeyEvent.KEYCODE_SHIFT_LEFT
-                && keyCode != KeyEvent.KEYCODE_SHIFT_RIGHT) {
-            // turn off copy select if a shift-key combo is pressed
-            selectionDone();
-        }
-
         if (getSettings().getNavDump()) {
             switch (keyCode) {
                 case KeyEvent.KEYCODE_4:
@@ -4766,14 +4745,6 @@
             return true;
         }
 
-        if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT
-                || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
-            if (!nativePageShouldHandleShiftAndArrows() && copySelection()) {
-                selectionDone();
-                return true;
-            }
-        }
-
         if (keyCode >= KeyEvent.KEYCODE_DPAD_UP
                 && keyCode <= KeyEvent.KEYCODE_DPAD_RIGHT) {
             if (nativePageShouldHandleShiftAndArrows()) {
@@ -5234,7 +5205,8 @@
         // Textfields, plugins, and contentEditable nodes need to receive the
         // shift up key even if another key was released while the shift key
         // was held down.
-        if (!inEditingMode() && (mNativeClass == 0
+        boolean inEditingMode = inEditingMode();
+        if (!inEditingMode && (mNativeClass == 0
                 || !nativePageShouldHandleShiftAndArrows())) {
             if (event.getAction() == KeyEvent.ACTION_DOWN) {
                 mGotKeyDown = true;
@@ -5251,7 +5223,13 @@
         }
 
         if (dispatch) {
-            return super.dispatchKeyEvent(event);
+            if (inEditingMode) {
+                // Ensure that the WebTextView gets the event, even if it does
+                // not currently have a bounds.
+                return mWebTextView.dispatchKeyEvent(event);
+            } else {
+                return super.dispatchKeyEvent(event);
+            }
         } else {
             // We didn't dispatch, so let something else handle the key
             return false;
@@ -5344,17 +5322,10 @@
                 + " numPointers=" + ev.getPointerCount());
         }
 
-        int action = ev.getAction();
-        float x = ev.getX();
-        float y = ev.getY();
-        long eventTime = ev.getEventTime();
-
-        // mDeferMultitouch is a hack for layout tests, where it is used to
-        // force passing multi-touch events to webkit.
-        // FIXME: always pass multi-touch events to webkit and remove everything
-        // related to mDeferMultitouch.
-        if (ev.getPointerCount() > 1 &&
-                (mDeferMultitouch || mZoomManager.isZoomScaleFixed())) {
+        // Always pass multi-touch event to WebKit first.
+        // If WebKit doesn't consume it and set preventDefault to true,
+        // WebView's private handler will handle it.
+        if (ev.getPointerCount() > 1) {
             if (DebugFlags.WEB_VIEW) {
                 Log.v(LOGTAG, "passing " + ev.getPointerCount() + " points to webkit");
             }
@@ -5362,59 +5333,15 @@
             return true;
         }
 
-        final ScaleGestureDetector detector =
-                mZoomManager.getMultiTouchGestureDetector();
+        return handleTouchEventCommon(ev);
+    }
 
-        if (mZoomManager.supportsMultiTouchZoom() && ev.getPointerCount() > 1) {
-            if (!detector.isInProgress() &&
-                    ev.getActionMasked() != MotionEvent.ACTION_POINTER_DOWN) {
-                // Insert a fake pointer down event in order to start
-                // the zoom scale detector.
-                MotionEvent temp = MotionEvent.obtain(ev);
-                // Clear the original event and set it to
-                // ACTION_POINTER_DOWN.
-                try {
-                    temp.setAction(temp.getAction() &
-                            ~MotionEvent.ACTION_MASK |
-                            MotionEvent.ACTION_POINTER_DOWN);
-                    detector.onTouchEvent(temp);
-                } finally {
-                    temp.recycle();
-                }
-            }
+    private boolean handleTouchEventCommon(MotionEvent ev) {
+        int action = ev.getAction();
+        float x = ev.getX();
+        float y = ev.getY();
+        long eventTime = ev.getEventTime();
 
-            detector.onTouchEvent(ev);
-
-            if (detector.isInProgress()) {
-                mLastTouchTime = eventTime;
-                cancelLongPress();
-                mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
-                if (!mZoomManager.supportsPanDuringZoom()) {
-                    return true;
-                }
-                mTouchMode = TOUCH_DRAG_MODE;
-                if (mVelocityTracker == null) {
-                    mVelocityTracker = VelocityTracker.obtain();
-                }
-            }
-
-            x = detector.getFocusX();
-            y = detector.getFocusY();
-            action = ev.getAction() & MotionEvent.ACTION_MASK;
-            if (action == MotionEvent.ACTION_POINTER_DOWN) {
-                cancelTouch();
-                action = MotionEvent.ACTION_DOWN;
-            } else if (action == MotionEvent.ACTION_POINTER_UP) {
-                // set mLastTouchX/Y to the remaining point
-                mLastTouchX = x;
-                mLastTouchY = y;
-            } else if (action == MotionEvent.ACTION_MOVE) {
-                // negative x or y indicate it is on the edge, skip it.
-                if (x < 0 || y < 0) {
-                    return true;
-                }
-            }
-        }
 
         // Due to the touch screen edge effect, a touch closer to the edge
         // always snapped to the edge. As getViewWidth() can be different from
@@ -5627,22 +5554,6 @@
                         break;
                     }
 
-                    // Only lock dragging to one axis if we don't have a scale in progress.
-                    // Scaling implies free-roaming movement. Note this is only ever a question
-                    // if mZoomManager.supportsPanDuringZoom() is true.
-                    if (detector != null && !detector.isInProgress()) {
-                        // if it starts nearly horizontal or vertical, enforce it
-                        int ax = Math.abs(deltaX);
-                        int ay = Math.abs(deltaY);
-                        if (ax > MAX_SLOPE_FOR_DIAG * ay) {
-                            mSnapScrollMode = SNAP_X;
-                            mSnapPositive = deltaX > 0;
-                        } else if (ay > MAX_SLOPE_FOR_DIAG * ax) {
-                            mSnapScrollMode = SNAP_Y;
-                            mSnapPositive = deltaY > 0;
-                        }
-                    }
-
                     mTouchMode = TOUCH_DRAG_MODE;
                     mLastTouchX = x;
                     mLastTouchY = y;
@@ -5899,13 +5810,82 @@
             ted.mPoints[c] = new Point(x, y);
         }
         ted.mMetaState = ev.getMetaState();
-        ted.mReprocess = mDeferTouchProcess;
+        ted.mReprocess = true;
+        ted.mMotionEvent = MotionEvent.obtain(ev);
         mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
         cancelLongPress();
         mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
         mPreventDefault = PREVENT_DEFAULT_IGNORE;
     }
 
+    private boolean handleMultiTouchInWebView(MotionEvent ev) {
+        if (DebugFlags.WEB_VIEW) {
+            Log.v(LOGTAG, "multi-touch: " + ev + " at " + ev.getEventTime()
+                + " mTouchMode=" + mTouchMode
+                + " numPointers=" + ev.getPointerCount()
+                + " scrolloffset=(" + mScrollX + "," + mScrollY + ")");
+        }
+
+        final ScaleGestureDetector detector =
+            mZoomManager.getMultiTouchGestureDetector();
+        int action = ev.getAction();
+        float x = ev.getX();
+        float y = ev.getY();
+        long eventTime = ev.getEventTime();
+
+        if (!detector.isInProgress() &&
+            ev.getActionMasked() != MotionEvent.ACTION_POINTER_DOWN) {
+            // Insert a fake pointer down event in order to start
+            // the zoom scale detector.
+            MotionEvent temp = MotionEvent.obtain(ev);
+            // Clear the original event and set it to
+            // ACTION_POINTER_DOWN.
+            try {
+                temp.setAction(temp.getAction() &
+                ~MotionEvent.ACTION_MASK |
+                MotionEvent.ACTION_POINTER_DOWN);
+                detector.onTouchEvent(temp);
+            } finally {
+                temp.recycle();
+            }
+        }
+
+        detector.onTouchEvent(ev);
+
+        if (detector.isInProgress()) {
+            if (DebugFlags.WEB_VIEW) {
+                Log.v(LOGTAG, "detector is in progress");
+            }
+            mLastTouchTime = eventTime;
+            cancelLongPress();
+            mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
+            if (!mZoomManager.supportsPanDuringZoom()) {
+                return false;
+            }
+            mTouchMode = TOUCH_DRAG_MODE;
+            if (mVelocityTracker == null) {
+                mVelocityTracker = VelocityTracker.obtain();
+            }
+        }
+
+        action = ev.getAction() & MotionEvent.ACTION_MASK;
+        if (action == MotionEvent.ACTION_POINTER_DOWN) {
+            cancelTouch();
+            action = MotionEvent.ACTION_DOWN;
+        } else if (action == MotionEvent.ACTION_POINTER_UP) {
+            // set mLastTouchX/Y to the remaining point
+            mLastTouchX = x;
+            mLastTouchY = y;
+        } else if (action == MotionEvent.ACTION_MOVE) {
+            // negative x or y indicate it is on the edge, skip it.
+            if (x < 0 || y < 0) {
+                return false;
+            }
+        }
+
+        return handleTouchEventCommon(ev);
+    }
+
     private void cancelWebCoreTouchEvent(int x, int y, boolean removeEvents) {
         if (shouldForwardTouchEvent()) {
             if (removeEvents) {
@@ -7278,6 +7258,13 @@
                         // prevent default is not called in WebCore, so the
                         // message needs to be reprocessed in UI
                         TouchEventData ted = (TouchEventData) msg.obj;
+
+                        if (ted.mPoints.length > 1) {  // for multi-touch.
+                            handleMultiTouchInWebView(ted.mMotionEvent);
+                            break;
+                        }
+
+                        // Following is for single touch.
                         switch (ted.mAction) {
                             case MotionEvent.ACTION_DOWN:
                                 mLastDeferTouchX = contentToViewX(ted.mPoints[0].x)
@@ -8103,7 +8090,6 @@
     private native int      nativeCursorFramePointer();
     private native Rect     nativeCursorNodeBounds();
     private native int nativeCursorNodePointer();
-    /* package */ native boolean nativeCursorMatchesFocus();
     private native boolean  nativeCursorIntersects(Rect visibleRect);
     private native boolean  nativeCursorIsAnchor();
     private native boolean  nativeCursorIsTextInput();
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index a482b74..8d5e71a 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -33,6 +33,7 @@
 import android.util.Log;
 import android.util.SparseBooleanArray;
 import android.view.KeyEvent;
+import android.view.MotionEvent;
 import android.view.SurfaceView;
 import android.view.View;
 import android.webkit.DeviceMotionService;
@@ -114,8 +115,8 @@
      */
     private int mViewportDensityDpi = -1;
 
-    private int mRestoredScale = 0;
-    private int mRestoredTextWrapScale = 0;
+    private float mRestoredScale = 0;
+    private float mRestoredTextWrapScale = 0;
     private int mRestoredX = 0;
     private int mRestoredY = 0;
 
@@ -830,6 +831,7 @@
         Point[] mPoints;
         int mMetaState;
         boolean mReprocess;
+        MotionEvent mMotionEvent;
     }
 
     static class GeolocationPermissionsData {
@@ -2243,8 +2245,8 @@
         }
 
         // reset the scroll position, the restored offset and scales
-        mWebkitScrollX = mWebkitScrollY = mRestoredX = mRestoredY
-                = mRestoredScale = mRestoredTextWrapScale = 0;
+        mWebkitScrollX = mWebkitScrollY = mRestoredX = mRestoredY = 0;
+        mRestoredScale = mRestoredTextWrapScale = 0;
     }
 
     // called by JNI
@@ -2350,9 +2352,9 @@
         mInitialViewState.mMobileSite = (0 == mViewportWidth);
         if (mRestoredScale > 0) {
             mInitialViewState.mIsRestored = true;
-            mInitialViewState.mViewScale = mRestoredScale / 100.0f;
+            mInitialViewState.mViewScale = mRestoredScale;
             if (mRestoredTextWrapScale > 0) {
-                mInitialViewState.mTextWrapScale = mRestoredTextWrapScale / 100.0f;
+                mInitialViewState.mTextWrapScale = mRestoredTextWrapScale;
             } else {
                 mInitialViewState.mTextWrapScale = mInitialViewState.mViewScale;
             }
@@ -2409,7 +2411,7 @@
                 // know the exact scale. If mRestoredScale is non-zero, use it;
                 // otherwise just use mTextWrapScale as the initial scale.
                 data.mScale = mInitialViewState.mViewScale == 0
-                        ? (mRestoredScale > 0 ? mRestoredScale / 100.0f
+                        ? (mRestoredScale > 0 ? mRestoredScale
                                 : mInitialViewState.mTextWrapScale)
                         : mInitialViewState.mViewScale;
                 if (DebugFlags.WEB_VIEW_CORE) {
@@ -2442,7 +2444,7 @@
     }
 
     // called by JNI
-    private void restoreScale(int scale, int textWrapScale) {
+    private void restoreScale(float scale, float textWrapScale) {
         if (mBrowserFrame.firstLayoutDone() == false) {
             mRestoredScale = scale;
             if (mSettings.getUseWideViewPort()) {
diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java
index 7b9def0..e1392ae 100644
--- a/core/java/android/webkit/WebViewDatabase.java
+++ b/core/java/android/webkit/WebViewDatabase.java
@@ -223,6 +223,7 @@
                         null);
             }
         }
+        mDatabase.enableWriteAheadLogging();
 
         // mDatabase should not be null,
         // the only case is RequestAPI test has problem to create db
@@ -233,7 +234,7 @@
         }
 
         if (mDatabase.getVersion() != DATABASE_VERSION) {
-            mDatabase.beginTransaction();
+            mDatabase.beginTransactionNonExclusive();
             try {
                 upgradeDatabase();
                 mDatabase.setTransactionSuccessful();
@@ -261,6 +262,7 @@
                         CACHE_DATABASE_FILE, 0, null);
             }
         }
+        mCacheDatabase.enableWriteAheadLogging();
 
         // mCacheDatabase should not be null,
         // the only case is RequestAPI test has problem to create db
@@ -271,7 +273,7 @@
         }
 
         if (mCacheDatabase.getVersion() != CACHE_DATABASE_VERSION) {
-            mCacheDatabase.beginTransaction();
+            mCacheDatabase.beginTransactionNonExclusive();
             try {
                 upgradeCacheDatabase();
                 bootstrapCacheDatabase();
@@ -648,7 +650,7 @@
                         + "WebViewWorkerThread instead of from "
                         + Thread.currentThread().getName());
             }
-            mCacheDatabase.beginTransaction();
+            mCacheDatabase.beginTransactionNonExclusive();
             return true;
         }
         return false;
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 2fd5bb1..b4a33de 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -150,6 +150,12 @@
     private static float MINIMUM_SCALE_INCREMENT = 0.01f;
 
     /*
+     *  The touch points could be changed even the fingers stop moving.
+     *  We use the following to filter out the zooming jitters.
+     */
+    private static float MINIMUM_SCALE_WITHOUT_JITTER = 0.05f;
+
+    /*
      * The following member variables are only to be used for animating zoom. If
      * mZoomScale is non-zero then we are in the middle of a zoom animation. The
      * other variables are used as a cache (e.g. inverse) or as a way to store
@@ -684,6 +690,10 @@
                 } else {
                     scale = Math.max(scale, mActualScale * 0.8f);
                 }
+                // if the scale change is too small, regard it as jitter and skip it.
+                if (Math.abs(scale - mActualScale) < MINIMUM_SCALE_WITHOUT_JITTER) {
+                    return false;
+                }
                 setZoomCenter(detector.getFocusX(), detector.getFocusY());
                 setZoomScale(scale, false);
                 mWebView.invalidate();
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index b85670c..bccde8d 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -4810,7 +4810,10 @@
             if (mFiltered && mPopup != null && mPopup.isShowing()) {
                 if (event.getAction() == KeyEvent.ACTION_DOWN
                         && event.getRepeatCount() == 0) {
-                    getKeyDispatcherState().startTracking(event, this);
+                    KeyEvent.DispatcherState state = getKeyDispatcherState();
+                    if (state != null) {
+                        state.startTracking(event, this);
+                    }
                     handled = true;
                 } else if (event.getAction() == KeyEvent.ACTION_UP
                         && event.isTracking() && !event.isCanceled()) {
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index ee037cd..4d8d21f 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -607,10 +607,16 @@
             // special case for the back key, we do not even try to send it
             // to the drop down list but instead, consume it immediately
             if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
-                getKeyDispatcherState().startTracking(event, this);
+                KeyEvent.DispatcherState state = getKeyDispatcherState();
+                if (state != null) {
+                    state.startTracking(event, this);
+                }
                 return true;
             } else if (event.getAction() == KeyEvent.ACTION_UP) {
-                getKeyDispatcherState().handleUpEvent(event);
+                KeyEvent.DispatcherState state = getKeyDispatcherState();
+                if (state != null) {
+                    state.handleUpEvent(event);
+                }
                 if (event.isTracking() && !event.isCanceled()) {
                     dismissDropDown();
                     return true;
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 3bba816..444a163d 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -915,10 +915,16 @@
             // to the drop down list but instead, consume it immediately
             final View anchorView = mDropDownAnchorView;
             if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
-                anchorView.getKeyDispatcherState().startTracking(event, this);
+                KeyEvent.DispatcherState state = anchorView.getKeyDispatcherState();
+                if (state != null) {
+                    state.startTracking(event, this);
+                }
                 return true;
             } else if (event.getAction() == KeyEvent.ACTION_UP) {
-                anchorView.getKeyDispatcherState().handleUpEvent(event);
+                KeyEvent.DispatcherState state = anchorView.getKeyDispatcherState();
+                if (state != null) {
+                    state.handleUpEvent(event);
+                }
                 if (event.isTracking() && !event.isCanceled()) {
                     dismiss();
                     return true;
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 5a5b6f4..79d6a81 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -1468,12 +1468,17 @@
             if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
                 if (event.getAction() == KeyEvent.ACTION_DOWN
                         && event.getRepeatCount() == 0) {
-                    getKeyDispatcherState().startTracking(event, this);
+                    KeyEvent.DispatcherState state = getKeyDispatcherState();
+                    if (state != null) {
+                        state.startTracking(event, this);
+                    }
                     return true;
-                } else if (event.getAction() == KeyEvent.ACTION_UP
-                        && getKeyDispatcherState().isTracking(event) && !event.isCanceled()) {
-                    dismiss();
-                    return true;
+                } else if (event.getAction() == KeyEvent.ACTION_UP) {
+                    KeyEvent.DispatcherState state = getKeyDispatcherState();
+                    if (state != null && state.isTracking(event) && !event.isCanceled()) {
+                        dismiss();
+                        return true;
+                    }
                 }
                 return super.dispatchKeyEvent(event);
             } else {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index cc5be00..a1c286f 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4672,6 +4672,9 @@
                     // don't let it be inserted into the text.
                     if ((event.getFlags() & KeyEvent.FLAG_EDITOR_ACTION) != 0
                             || shouldAdvanceFocusOnEnter()) {
+                        if (mOnClickListener != null) {
+                            return 0;
+                        }
                         return -1;
                     }
                 }
@@ -4780,7 +4783,6 @@
         }
 
         hideControllers();
-        stopSelectionActionMode();
 
         switch (keyCode) {
             case KeyEvent.KEYCODE_DPAD_CENTER:
@@ -5119,6 +5121,7 @@
         if (mInputMethodState != null) {
             mInputMethodState.mExtracting = req;
         }
+        // This stops a possible text selection mode. Maybe not intended.
         hideControllers();
     }
     
@@ -6781,7 +6784,7 @@
         sendOnTextChanged(buffer, start, before, after);
         onTextChanged(buffer, start, before, after);
 
-        // Hide the controller if the amount of content changed
+        // Hide the controllers if the amount of content changed
         if (before != after) {
             hideControllers();
         }
@@ -8207,9 +8210,12 @@
             selectCurrentWord();
         }
 
-        final InputMethodManager imm = (InputMethodManager)
-                getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
-        imm.showSoftInput(this, 0, null);
+        if (!mTextIsSelectable) {
+            // Show the IME, except when selection non editable text.
+            final InputMethodManager imm = (InputMethodManager)
+                    getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+            imm.showSoftInput(this, 0, null);
+        }
 
         ActionMode.Callback actionModeCallback = new SelectionActionModeCallback();
         mSelectionActionMode = startActionMode(actionModeCallback);
@@ -8233,6 +8239,7 @@
 
     private void stopSelectionActionMode() {
         if (mSelectionActionMode != null) {
+            // This will hide the mSelectionModifierCursorController
             mSelectionActionMode.finish();
         }
     }
@@ -8356,8 +8363,12 @@
             if (mCustomSelectionActionModeCallback != null) {
                 mCustomSelectionActionModeCallback.onDestroyActionMode(mode);
             }
-            Selection.setSelection((Spannable) mText, getSelectionStart());
-            hideSelectionModifierCursorController();
+            Selection.setSelection((Spannable) mText, getSelectionEnd());
+
+            if (mSelectionModifierCursorController != null) {
+                mSelectionModifierCursorController.hide();
+            }
+
             mSelectionActionMode = null;
         }
     }
@@ -9173,16 +9184,12 @@
         }
     }
 
-    private void hideSelectionModifierCursorController() {
-        // No need to create the controller to hide it.
-        if (mSelectionModifierCursorController != null) {
-            mSelectionModifierCursorController.hide();
-        }
-    }
-    
+    /**
+     * Hides the insertion controller and stops text selection mode, hiding the selection controller
+     */
     private void hideControllers() {
         hideInsertionPointCursorController();
-        hideSelectionModifierCursorController();
+        stopSelectionActionMode();
     }
 
     /**
diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java
index 9381675..463902f 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuView.java
@@ -139,6 +139,10 @@
         mReserveOverflow = reserveOverflow;
     }
     
+    public View getOverflowButton() {
+        return mOverflowButton;
+    }
+
     @Override
     protected LayoutParams generateDefaultLayoutParams() {
         LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index fe41f52..b93fac4 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -68,6 +68,10 @@
         }
     }
 
+    public void setAnchorView(View anchor) {
+        mAnchorView = new WeakReference<View>(anchor);
+    }
+
     public void show() {
         if (!tryShow()) {
             throw new IllegalStateException("MenuPopupHelper cannot be used without an anchor");
diff --git a/core/jni/com_android_internal_os_ZygoteInit.cpp b/core/jni/com_android_internal_os_ZygoteInit.cpp
index ada4dd3..52e8f42 100644
--- a/core/jni/com_android_internal_os_ZygoteInit.cpp
+++ b/core/jni/com_android_internal_os_ZygoteInit.cpp
@@ -45,14 +45,10 @@
 static jint com_android_internal_os_ZygoteInit_setreuid(
     JNIEnv* env, jobject clazz, jint ruid, jint euid)
 {
-    int err;
-
-    errno = 0;
-    err = setreuid(ruid, euid);
-
-    //LOGI("setreuid(%d,%d) err %d errno %d", ruid, euid, err, errno);
-
-    return errno;
+    if (setreuid(ruid, euid) < 0) {
+        return errno;
+    }
+    return 0;
 }
 
 /*
@@ -62,14 +58,10 @@
 static jint com_android_internal_os_ZygoteInit_setregid(
     JNIEnv* env, jobject clazz, jint rgid, jint egid)
 {
-    int err;
-
-    errno = 0;
-    err = setregid(rgid, egid);
-
-    //LOGI("setregid(%d,%d) err %d errno %d", rgid, egid, err, errno);
-
-    return errno;
+    if (setregid(rgid, egid) < 0) {
+        return errno;
+    }
+    return 0;
 }
 
 /*
@@ -79,13 +71,10 @@
 static jint com_android_internal_os_ZygoteInit_setpgid(
     JNIEnv* env, jobject clazz, jint pid, jint pgid)
 {
-    int err;
-
-    errno = 0;
-
-    err = setpgid(pid, pgid);
-
-    return errno;
+    if (setpgid(pid, pgid) < 0) {
+        return errno;
+    }
+    return 0;
 }
 
 /*
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 1d43442..67adc28 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -540,7 +540,8 @@
         android:description="@string/permdesc_sdcardWrite"
         android:protectionLevel="dangerous" />
 
-    <!-- Allows an application to write to internal media storage -->
+    <!-- Allows an application to write to internal media storage
+         @hide  -->
     <permission android:name="android.permission.WRITE_MEDIA_STORAGE"
         android:permissionGroup="android.permission-group.STORAGE"
         android:label="@string/permlab_mediaStorageWrite"
diff --git a/core/res/res/anim/animator_fade_in.xml b/core/res/res/anim/animator_fade_in.xml
deleted file mode 100644
index cff98cf..0000000
--- a/core/res/res/anim/animator_fade_in.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:interpolator="@interpolator/accelerate_quad"
-    android:valueFrom="0"
-    android:valueTo="1"
-    android:propertyName="alpha"
-    android:duration="@android:integer/config_mediumAnimTime"
-/>
diff --git a/core/res/res/anim/animator_fade_out.xml b/core/res/res/anim/animator_fade_out.xml
deleted file mode 100644
index 6a3d5ee..0000000
--- a/core/res/res/anim/animator_fade_out.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:interpolator="@interpolator/accelerate_quad"
-    android:valueFrom="1.0"
-    android:valueTo="0.0"
-    android:propertyName="alpha"
-    android:duration="@android:integer/config_mediumAnimTime"
-/>
diff --git a/core/res/res/anim/fragment_close_enter.xml b/core/res/res/anim/fragment_close_enter.xml
deleted file mode 100644
index c0abbc5..0000000
--- a/core/res/res/anim/fragment_close_enter.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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. 
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-	android:zAdjustment="normal">
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_quint"
-        android:valueFrom="0.975" android:valueTo="1.0"
-        android:valueType="floatType"
-        android:propertyName="scaleY"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_quint"
-        android:valueFrom="0.975" android:valueTo="1.0"
-        android:valueType="floatType"
-        android:propertyName="scaleX"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_cubic"
-        android:valueFrom="0.0" android:valueTo="1.0"
-        android:valueType="floatType"
-        android:propertyName="alpha"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_close_exit.xml b/core/res/res/anim/fragment_close_exit.xml
deleted file mode 100644
index 9a5708c..0000000
--- a/core/res/res/anim/fragment_close_exit.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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. 
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-	android:zAdjustment="top">
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_quint"
-        android:valueFrom="1.0" android:valueTo="1.075"
-        android:valueType="floatType"
-        android:propertyName="scaleY"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_quint"
-        android:valueFrom="1.0" android:valueTo="1.075"
-        android:valueType="floatType"
-        android:propertyName="scaleX"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_cubic"
-        android:valueFrom="1.0" android:valueTo="0.0"
-        android:valueType="floatType"
-        android:propertyName="alpha"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_next_enter.xml b/core/res/res/anim/fragment_next_enter.xml
deleted file mode 100644
index 13b15f3..0000000
--- a/core/res/res/anim/fragment_next_enter.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-	android:zAdjustment="top">
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_cubic"
-        android:valueFrom="0"
-        android:valueTo="1"
-        android:valueType="floatType"
-        android:propertyName="alpha"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_next_exit.xml b/core/res/res/anim/fragment_next_exit.xml
deleted file mode 100644
index 503b7ad..0000000
--- a/core/res/res/anim/fragment_next_exit.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-	android:zAdjustment="normal">
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_cubic"
-        android:valueFrom="1"
-        android:valueTo="0"
-        android:valueType="floatType"
-        android:propertyName="alpha"
-        android:duration="@android:integer/config_activityShortDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_open_enter.xml b/core/res/res/anim/fragment_open_enter.xml
deleted file mode 100644
index 6b16cb4..0000000
--- a/core/res/res/anim/fragment_open_enter.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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. 
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android">
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_quint"
-        android:valueFrom="1.125" android:valueTo="1.0"
-        android:valueType="floatType"
-        android:propertyName="scaleY"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_quint"
-        android:valueFrom="1.125" android:valueTo="1.0"
-        android:valueType="floatType"
-        android:propertyName="scaleX"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_cubic"
-        android:valueFrom="0.0" android:valueTo="1.0"
-        android:valueType="floatType"
-        android:propertyName="alpha"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_open_exit.xml b/core/res/res/anim/fragment_open_exit.xml
deleted file mode 100644
index d77ee8e..0000000
--- a/core/res/res/anim/fragment_open_exit.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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. 
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android">
-    <objectAnimator
-        android:interpolator="@interpolator/linear"
-        android:valueFrom="1.0" android:valueTo="0.975"
-        android:valueType="floatType"
-        android:propertyName="scaleY"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-    <objectAnimator
-        android:interpolator="@interpolator/linear"
-        android:valueFrom="1.0" android:valueTo="0.975"
-        android:valueType="floatType"
-        android:propertyName="scaleX"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_cubic"
-        android:valueFrom="1.0" android:valueTo="0.0"
-        android:valueType="floatType"
-        android:propertyName="alpha"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_prev_enter.xml b/core/res/res/anim/fragment_prev_enter.xml
deleted file mode 100644
index 13b15f3..0000000
--- a/core/res/res/anim/fragment_prev_enter.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-	android:zAdjustment="top">
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_cubic"
-        android:valueFrom="0"
-        android:valueTo="1"
-        android:valueType="floatType"
-        android:propertyName="alpha"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_prev_exit.xml b/core/res/res/anim/fragment_prev_exit.xml
deleted file mode 100644
index 503b7ad..0000000
--- a/core/res/res/anim/fragment_prev_exit.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-	android:zAdjustment="normal">
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_cubic"
-        android:valueFrom="1"
-        android:valueTo="0"
-        android:valueType="floatType"
-        android:propertyName="alpha"
-        android:duration="@android:integer/config_activityShortDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/animator/fade_in.xml b/core/res/res/animator/fade_in.xml
index 2a28b4d..cff98cf 100644
--- a/core/res/res/animator/fade_in.xml
+++ b/core/res/res/animator/fade_in.xml
@@ -18,7 +18,7 @@
 -->
 
 <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:interpolator="@anim/accelerate_interpolator"
+    android:interpolator="@interpolator/accelerate_quad"
     android:valueFrom="0"
     android:valueTo="1"
     android:propertyName="alpha"
diff --git a/core/res/res/animator/fade_out.xml b/core/res/res/animator/fade_out.xml
index 4db6591..6a3d5ee 100644
--- a/core/res/res/animator/fade_out.xml
+++ b/core/res/res/animator/fade_out.xml
@@ -18,7 +18,7 @@
 -->
 
 <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:interpolator="@anim/accelerate_interpolator"
+    android:interpolator="@interpolator/accelerate_quad"
     android:valueFrom="1.0"
     android:valueTo="0.0"
     android:propertyName="alpha"
diff --git a/core/res/res/drawable-hdpi/ic_menu_help.png b/core/res/res/drawable-hdpi/ic_menu_help.png
index 4300e86..01a77da 100644
--- a/core/res/res/drawable-hdpi/ic_menu_help.png
+++ b/core/res/res/drawable-hdpi/ic_menu_help.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal.9.png b/core/res/res/drawable-mdpi/btn_default_normal.9.png
index a2d5ccd..7ff74b2 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_disable.9.png b/core/res/res/drawable-mdpi/btn_default_normal_disable.9.png
index edd3a3e..d3e11b5 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_disable.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_disable.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_disable_focused.9.png b/core/res/res/drawable-mdpi/btn_default_normal_disable_focused.9.png
index f506179..843ca7a 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_disable_focused.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_disable_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed.9.png b/core/res/res/drawable-mdpi/btn_default_pressed.9.png
index 033bf89..74fd58b 100644
--- a/core/res/res/drawable-mdpi/btn_default_pressed.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_selected.9.png b/core/res/res/drawable-mdpi/btn_default_selected.9.png
index 1e900bf..415b145 100644
--- a/core/res/res/drawable-mdpi/btn_default_selected.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_normal.9.png b/core/res/res/drawable-mdpi/btn_default_small_normal.9.png
index bcedd5f..5dddd46 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_normal.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_normal_disable.9.png b/core/res/res/drawable-mdpi/btn_default_small_normal_disable.9.png
index ac6260f..6ab5c4a 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_normal_disable.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_normal_disable.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png b/core/res/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
index 4ee1b3f..c65bace 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_pressed.9.png b/core/res/res/drawable-mdpi/btn_default_small_pressed.9.png
index 25e38f4..43e82f9 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_pressed.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_selected.9.png b/core/res/res/drawable-mdpi/btn_default_small_selected.9.png
index cc209c6..7a376a9 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_selected.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_bullet_key_permission.png b/core/res/res/drawable-mdpi/ic_bullet_key_permission.png
index ccb010f..68ad039 100644
--- a/core/res/res/drawable-mdpi/ic_bullet_key_permission.png
+++ b/core/res/res/drawable-mdpi/ic_bullet_key_permission.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_help.png b/core/res/res/drawable-mdpi/ic_menu_help.png
index 7c55dfd..12ca235 100644
--- a/core/res/res/drawable-mdpi/ic_menu_help.png
+++ b/core/res/res/drawable-mdpi/ic_menu_help.png
Binary files differ
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 2e87883..1a6f404 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -91,7 +91,7 @@
     <color name="search_url_text_selected">@android:color/black</color>
     <color name="search_url_text_pressed">@android:color/black</color>
     <color name="search_widget_corpus_item_background">@android:color/lighter_gray</color>
-    
+
     <!-- SlidingTab -->
     <color name="sliding_tab_text_color_active">@android:color/black</color>
     <color name="sliding_tab_text_color_shadow">@android:color/black</color>
@@ -105,7 +105,7 @@
 
     <!-- keyguard clock -->
     <color name="lockscreen_clock_background">#b3ffffff</color>
-    <color name="lockscreen_clock_foreground">#40000000</color>
+    <color name="lockscreen_clock_foreground">#7affffff</color>
     <color name="lockscreen_clock_am_pm">#ff9a9a9a</color>
     <color name="lockscreen_owner_info">#ff9a9a9a</color>
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index c2a848d..e124d9d 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1458,9 +1458,6 @@
        sinusoidal pattern. -->
   <public type="interpolator" name="cycle" />
 
-  <public type="anim" name="animator_fade_in" />
-  <public type="anim" name="animator_fade_out" />
-
   <!-- Acceleration curve matching a cubic ease in function. -->
   <public type="anim" name="accelerate_cubic_interpolator" />
   <!-- Acceleration curve matching a cubic ease out function. -->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 96e60f2..920312b 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -81,14 +81,14 @@
         <item name="wallpaperIntraOpenExitAnimation">@anim/wallpaper_intra_open_exit</item>
         <item name="wallpaperIntraCloseEnterAnimation">@anim/wallpaper_intra_close_enter</item>
         <item name="wallpaperIntraCloseExitAnimation">@anim/wallpaper_intra_close_exit</item>
-        <item name="fragmentOpenEnterAnimation">@anim/fragment_open_enter</item>
-        <item name="fragmentOpenExitAnimation">@anim/fragment_open_exit</item>
-        <item name="fragmentCloseEnterAnimation">@anim/fragment_close_enter</item>
-        <item name="fragmentCloseExitAnimation">@anim/fragment_close_exit</item>
-        <item name="fragmentNextEnterAnimation">@anim/fragment_next_enter</item>
-        <item name="fragmentNextExitAnimation">@anim/fragment_next_exit</item>
-        <item name="fragmentPrevEnterAnimation">@anim/fragment_prev_enter</item>
-        <item name="fragmentPrevExitAnimation">@anim/fragment_prev_exit</item>
+        <item name="fragmentOpenEnterAnimation">@animator/fragment_open_enter</item>
+        <item name="fragmentOpenExitAnimation">@animator/fragment_open_exit</item>
+        <item name="fragmentCloseEnterAnimation">@animator/fragment_close_enter</item>
+        <item name="fragmentCloseExitAnimation">@animator/fragment_close_exit</item>
+        <item name="fragmentNextEnterAnimation">@animator/fragment_next_enter</item>
+        <item name="fragmentNextExitAnimation">@animator/fragment_next_exit</item>
+        <item name="fragmentPrevEnterAnimation">@animator/fragment_prev_enter</item>
+        <item name="fragmentPrevExitAnimation">@animator/fragment_prev_exit</item>
     </style>
 
     <!-- Standard animations for a non-full-screen window or activity. -->
diff --git a/core/tests/coretests/src/android/util/JsonReaderTest.java b/core/tests/coretests/src/android/util/JsonReaderTest.java
index 216a772..b5c2c27 100644
--- a/core/tests/coretests/src/android/util/JsonReaderTest.java
+++ b/core/tests/coretests/src/android/util/JsonReaderTest.java
@@ -16,11 +16,10 @@
 
 package android.util;
 
-import java.util.Arrays;
-import junit.framework.TestCase;
-
 import java.io.IOException;
 import java.io.StringReader;
+import java.util.Arrays;
+import junit.framework.TestCase;
 
 public final class JsonReaderTest extends TestCase {
 
@@ -677,7 +676,7 @@
         try {
             reader.nextString();
             fail();
-        } catch (IOException expected) {
+        } catch (MalformedJsonException expected) {
         }
     }
 
@@ -811,4 +810,50 @@
         reader.nextNull();
         reader.endArray();
     }
+
+    public void testStrictMultipleTopLevelValues() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("[] []"));
+        reader.beginArray();
+        reader.endArray();
+        try {
+            reader.peek();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testLenientMultipleTopLevelValues() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("[] true {}"));
+        reader.setLenient(true);
+        reader.beginArray();
+        reader.endArray();
+        assertEquals(true, reader.nextBoolean());
+        reader.beginObject();
+        reader.endObject();
+        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
+    }
+
+    public void testStrictTopLevelValueType() {
+        JsonReader reader = new JsonReader(new StringReader("true"));
+        try {
+            reader.nextBoolean();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testLenientTopLevelValueType() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("true"));
+        reader.setLenient(true);
+        assertEquals(true, reader.nextBoolean());
+    }
+
+    public void testStrictNonExecutePrefix() {
+        JsonReader reader = new JsonReader(new StringReader(")]}'\n []"));
+        try {
+            reader.beginArray();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
 }
diff --git a/core/tests/coretests/src/android/util/JsonWriterTest.java b/core/tests/coretests/src/android/util/JsonWriterTest.java
index fa84023..b29e2fd 100644
--- a/core/tests/coretests/src/android/util/JsonWriterTest.java
+++ b/core/tests/coretests/src/android/util/JsonWriterTest.java
@@ -16,10 +16,11 @@
 
 package android.util;
 
-import junit.framework.TestCase;
-
 import java.io.IOException;
 import java.io.StringWriter;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import junit.framework.TestCase;
 
 public final class JsonWriterTest extends TestCase {
 
@@ -119,7 +120,7 @@
         JsonWriter jsonWriter = new JsonWriter(stringWriter);
         jsonWriter.beginObject();
         jsonWriter.name("a");
-        jsonWriter.value(null);
+        jsonWriter.value((String) null);
         jsonWriter.endObject();
         assertEquals("{\"a\":null}", stringWriter.toString());
     }
@@ -145,6 +146,27 @@
         }
     }
 
+    public void testNonFiniteBoxedDoubles() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginArray();
+        try {
+            jsonWriter.value(new Double(Double.NaN));
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            jsonWriter.value(new Double(Double.NEGATIVE_INFINITY));
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            jsonWriter.value(new Double(Double.POSITIVE_INFINITY));
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
     public void testDoubles() throws IOException {
         StringWriter stringWriter = new StringWriter();
         JsonWriter jsonWriter = new JsonWriter(stringWriter);
@@ -189,6 +211,22 @@
                 + "9223372036854775807]", stringWriter.toString());
     }
 
+    public void testNumbers() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginArray();
+        jsonWriter.value(new BigInteger("0"));
+        jsonWriter.value(new BigInteger("9223372036854775808"));
+        jsonWriter.value(new BigInteger("-9223372036854775809"));
+        jsonWriter.value(new BigDecimal("3.141592653589793238462643383"));
+        jsonWriter.endArray();
+        jsonWriter.close();
+        assertEquals("[0,"
+                + "9223372036854775808,"
+                + "-9223372036854775809,"
+                + "3.141592653589793238462643383]", stringWriter.toString());
+    }
+
     public void testBooleans() throws IOException {
         StringWriter stringWriter = new StringWriter();
         JsonWriter jsonWriter = new JsonWriter(stringWriter);
diff --git a/data/fonts/AndroidClock.ttf b/data/fonts/AndroidClock.ttf
index 24a7f08..03e36cb 100644
--- a/data/fonts/AndroidClock.ttf
+++ b/data/fonts/AndroidClock.ttf
Binary files differ
diff --git a/data/fonts/AndroidClock_Highlight.ttf b/data/fonts/AndroidClock_Highlight.ttf
index 1e14a8f..8fb31ba 100644
--- a/data/fonts/AndroidClock_Highlight.ttf
+++ b/data/fonts/AndroidClock_Highlight.ttf
Binary files differ
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 66c6d81..184620b 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -85,8 +85,12 @@
 
         @Override
         protected void finalize() throws Throwable {
-            if (mNativeCanvas != 0) {
-                finalizer(mNativeCanvas);
+            try {
+                if (mNativeCanvas != 0) {
+                    finalizer(mNativeCanvas);
+                }
+            } finally {
+                super.finalize();
             }
         }
     }
@@ -137,6 +141,8 @@
      * Returns null.
      * 
      * @deprecated This method is not supported and should not be invoked.
+     * 
+     * @hide
      */
     @Deprecated
     protected GL getGL() {
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 53962e1..7a47c3b 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -53,19 +53,6 @@
     public static final int USAGE_GRAPHICS_CONSTANTS = 0x0008;
 
 
-    public enum CubemapLayout {
-        VERTICAL_FACE_LIST (0),
-        HORIZONTAL_FACE_LIST (1),
-        VERTICAL_CROSS (2),
-        HORIZONTAL_CROSS (3);
-
-        int mID;
-        CubemapLayout(int id) {
-            mID = id;
-        }
-    }
-
-
     public enum MipmapControl {
         MIPMAP_NONE(0),
         MIPMAP_FULL(1),
@@ -416,33 +403,41 @@
                                 USAGE_GRAPHICS_TEXTURE);
     }
 
+    /**
+    * Creates a cubemap allocation from a bitmap containing the
+    * horizontal list of cube faces. Each individual face must be
+    * the same size and power of 2
+    *
+    * @param rs
+    * @param b bitmap with cubemap faces layed out in the following
+    *          format: right, left, top, bottom, front, back
+    * @param mips specifies desired mipmap behaviour for the cubemap
+    * @param usage bitfield specifying how the cubemap is utilized
+    *
+    **/
     static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b,
                                                      MipmapControl mips,
-                                                     CubemapLayout layout,
                                                      int usage) {
         rs.validate();
 
         int height = b.getHeight();
         int width = b.getWidth();
 
-        if (layout != CubemapLayout.VERTICAL_FACE_LIST) {
-            throw new RSIllegalArgumentException("Only vertical face list supported");
-        }
-        if (height % 6 != 0) {
+        if (width % 6 != 0) {
             throw new RSIllegalArgumentException("Cubemap height must be multiple of 6");
         }
-        if (height / 6 != width) {
+        if (width / 6 != height) {
             throw new RSIllegalArgumentException("Only square cobe map faces supported");
         }
-        boolean isPow2 = (width & (width - 1)) == 0;
+        boolean isPow2 = (height & (height - 1)) == 0;
         if (!isPow2) {
             throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
         }
 
         Element e = elementFromBitmap(rs, b);
         Type.Builder tb = new Type.Builder(rs, e);
-        tb.setX(width);
-        tb.setY(width);
+        tb.setX(height);
+        tb.setY(height);
         tb.setFaces(true);
         tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
         Type t = tb.create();
@@ -454,10 +449,9 @@
         return new Allocation(id, rs, t, usage);
     }
 
-    static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b,
-                                                     CubemapLayout layout) {
+    static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b) {
         return createCubemapFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
-                                       layout, USAGE_GRAPHICS_TEXTURE);
+                                       USAGE_GRAPHICS_TEXTURE);
     }
 
     static public Allocation createFromBitmapResource(RenderScript rs,
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index ff92e08..cbc15d8 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -113,8 +113,11 @@
     int mBufferCount;
 
     // mCurrentTexture is the buffer slot index of the buffer that is currently
-    // bound to the OpenGL texture. A value of INVALID_BUFFER_SLOT, indicating
-    // that no buffer is currently bound to the texture.
+    // bound to the OpenGL texture. It is initialized to INVALID_BUFFER_SLOT,
+    // indicating that no buffer slot is currently bound to the texture. Note,
+    // however, that a value of INVALID_BUFFER_SLOT does not necessarily mean
+    // that no buffer is bound to the texture. A call to setBufferCount will
+    // reset mCurrentTexture to INVALID_BUFFER_SLOT.
     int mCurrentTexture;
 
     // mLastQueued is the buffer slot index of the most recently enqueued buffer.
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index b3815c4..4599d70 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -101,6 +101,8 @@
 
     List<sp<AMessage> > mDeferredQueue;
 
+    bool mSentFormat;
+
     status_t allocateBuffersOnPort(OMX_U32 portIndex);
     status_t freeBuffersOnPort(OMX_U32 portIndex);
     status_t freeBuffer(OMX_U32 portIndex, size_t i);
@@ -145,6 +147,8 @@
     void deferMessage(const sp<AMessage> &msg);
     void processDeferredMessages();
 
+    void sendFormatChange();
+
     DISALLOW_EVIL_CONSTRUCTORS(ACodec);
 };
 
diff --git a/include/media/stagefright/foundation/AMessage.h b/include/media/stagefright/foundation/AMessage.h
index 91ec60c..72dc730 100644
--- a/include/media/stagefright/foundation/AMessage.h
+++ b/include/media/stagefright/foundation/AMessage.h
@@ -52,6 +52,10 @@
     void setObject(const char *name, const sp<RefBase> &obj);
     void setMessage(const char *name, const sp<AMessage> &obj);
 
+    void setRect(
+            const char *name,
+            int32_t left, int32_t top, int32_t right, int32_t bottom);
+
     bool findInt32(const char *name, int32_t *value) const;
     bool findInt64(const char *name, int64_t *value) const;
     bool findSize(const char *name, size_t *value) const;
@@ -62,6 +66,10 @@
     bool findObject(const char *name, sp<RefBase> *obj) const;
     bool findMessage(const char *name, sp<AMessage> *obj) const;
 
+    bool findRect(
+            const char *name,
+            int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) const;
+
     void post(int64_t delayUs = 0);
 
     // Performs a deep-copy of "this", contained messages are in turn "dup'ed".
@@ -85,11 +93,16 @@
         kTypeString,
         kTypeObject,
         kTypeMessage,
+        kTypeRect,
     };
 
     uint32_t mWhat;
     ALooper::handler_id mTarget;
 
+    struct Rect {
+        int32_t mLeft, mTop, mRight, mBottom;
+    };
+
     struct Item {
         union {
             int32_t int32Value;
@@ -100,6 +113,7 @@
             void *ptrValue;
             RefBase *refValue;
             AString *stringValue;
+            Rect rectValue;
         } u;
         const char *mName;
         Type mType;
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 9579996..11a48d9 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -15,6 +15,7 @@
  */
 
 #define LOG_TAG "SurfaceTexture"
+//#define LOG_NDEBUG 0
 
 #define GL_GLEXT_PROTOTYPES
 #define EGL_EGLEXT_PROTOTYPES
@@ -36,21 +37,32 @@
 SurfaceTexture::SurfaceTexture(GLuint tex) :
     mBufferCount(MIN_BUFFER_SLOTS), mCurrentTexture(INVALID_BUFFER_SLOT),
     mLastQueued(INVALID_BUFFER_SLOT), mTexName(tex) {
+    LOGV("SurfaceTexture::SurfaceTexture");
+    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
+        mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
+        mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
+        mSlots[i].mOwnedByClient = false;
+    }
 }
 
 SurfaceTexture::~SurfaceTexture() {
+    LOGV("SurfaceTexture::~SurfaceTexture");
     freeAllBuffers();
 }
 
 status_t SurfaceTexture::setBufferCount(int bufferCount) {
+    LOGV("SurfaceTexture::setBufferCount");
     Mutex::Autolock lock(mMutex);
     freeAllBuffers();
     mBufferCount = bufferCount;
+    mCurrentTexture = INVALID_BUFFER_SLOT;
+    mLastQueued = INVALID_BUFFER_SLOT;
     return OK;
 }
 
 sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf,
         uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
+    LOGV("SurfaceTexture::requestBuffer");
     Mutex::Autolock lock(mMutex);
     if (buf < 0 || mBufferCount <= buf) {
         LOGE("requestBuffer: slot index out of range [0, %d]: %d",
@@ -75,6 +87,7 @@
 }
 
 status_t SurfaceTexture::dequeueBuffer(int *buf) {
+    LOGV("SurfaceTexture::dequeueBuffer");
     Mutex::Autolock lock(mMutex);
     int found = INVALID_BUFFER_SLOT;
     for (int i = 0; i < mBufferCount; i++) {
@@ -92,6 +105,7 @@
 }
 
 status_t SurfaceTexture::queueBuffer(int buf) {
+    LOGV("SurfaceTexture::queueBuffer");
     Mutex::Autolock lock(mMutex);
     if (buf < 0 || mBufferCount <= buf) {
         LOGE("queueBuffer: slot index out of range [0, %d]: %d",
@@ -111,6 +125,7 @@
 }
 
 void SurfaceTexture::cancelBuffer(int buf) {
+    LOGV("SurfaceTexture::cancelBuffer");
     Mutex::Autolock lock(mMutex);
     if (buf < 0 || mBufferCount <= buf) {
         LOGE("cancelBuffer: slot index out of range [0, %d]: %d", mBufferCount,
@@ -124,18 +139,21 @@
 }
 
 status_t SurfaceTexture::setCrop(const Rect& reg) {
+    LOGV("SurfaceTexture::setCrop");
     Mutex::Autolock lock(mMutex);
     // XXX: How should we handle crops?
     return OK;
 }
 
 status_t SurfaceTexture::setTransform(uint32_t transform) {
+    LOGV("SurfaceTexture::setTransform");
     Mutex::Autolock lock(mMutex);
     // XXX: How should we handle transforms?
     return OK;
 }
 
 status_t SurfaceTexture::updateTexImage() {
+    LOGV("SurfaceTexture::updateTexImage");
     Mutex::Autolock lock(mMutex);
 
     // We always bind the texture even if we don't update its contents.
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 40dd117..406d09f 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -53,6 +53,10 @@
 
     mDebugLevel = readDebugLevel();
     LOGD("Enabling debug mode %d", mDebugLevel);
+
+#if RENDER_LAYERS_AS_REGIONS
+    LOGD("Layers will be composited as regions");
+#endif
 }
 
 Caches::~Caches() {
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 9613c5f..99bb6f0 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -162,6 +162,11 @@
     GLenum status = GL_NO_ERROR;
     while ((status = glGetError()) != GL_NO_ERROR) {
         LOGD("GL error from OpenGLRenderer: 0x%x", status);
+        switch (status) {
+            case GL_OUT_OF_MEMORY:
+                LOGE("  OpenGLRenderer is out of memory!");
+                break;
+        }
     }
 #endif
 #if DEBUG_MEMORY_USAGE
@@ -599,43 +604,23 @@
         size_t count;
         const android::Rect* rects = layer->region.getArray(&count);
 
-        setupDraw();
-
-        ProgramDescription description;
-        description.hasTexture = true;
-
         const float alpha = layer->alpha / 255.0f;
-        const bool setColor = description.setColor(alpha, alpha, alpha, alpha);
-        chooseBlending(layer->blend || layer->alpha < 255, layer->mode, description, false);
-
-        useProgram(mCaches.programCache.get(description));
-
-        // Texture
-        bindTexture(layer->texture);
-        glUniform1i(mCaches.currentProgram->getUniform("sampler"), 0);
-
-        // Always premultiplied
-        if (setColor) {
-            mCaches.currentProgram->setColor(alpha, alpha, alpha, alpha);
-        }
-
-        // Mesh
-        int texCoordsSlot = mCaches.currentProgram->getAttrib("texCoords");
-        glEnableVertexAttribArray(texCoordsSlot);
-
-        mModelView.loadIdentity();
-        mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform);
-
         const float texX = 1.0f / float(layer->width);
         const float texY = 1.0f / float(layer->height);
 
         TextureVertex* mesh = mCaches.getRegionMesh();
         GLsizei numQuads = 0;
 
-        glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
-                gMeshStride, &mesh[0].position[0]);
-        glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE,
-                gMeshStride, &mesh[0].texture[0]);
+        setupDraw();
+        setupDrawWithTexture();
+        setupDrawColor(alpha, alpha, alpha, alpha);
+        setupDrawBlending(layer->blend || layer->alpha < 255, layer->mode, false);
+        setupDrawProgram();
+        setupDrawDirtyRegionsDisabled();
+        setupDrawPureColorUniforms();
+        setupDrawTexture(layer->texture);
+        setupDrawModelViewIdentity();
+        setupDrawMesh(&mesh[0].position[0], &mesh[0].texture[0]);
 
         for (size_t i = 0; i < count; i++) {
             const android::Rect* r = &rects[i];
@@ -665,7 +650,7 @@
         }
 
         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-        glDisableVertexAttribArray(texCoordsSlot);
+        finishDrawTexture();
 
 #if DEBUG_LAYERS_AS_REGIONS
         uint32_t colors[] = {
@@ -1181,7 +1166,6 @@
 }
 
 void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
-    // TODO: Should do quickReject for each line
     if (mSnapshot->isIgnored()) return;
 
     const bool isAA = paint->isAntiAlias();
@@ -1195,6 +1179,7 @@
     getAlphaAndMode(paint, &alpha, &mode);
 
     int verticesCount = count >> 2;
+    int generatedVerticesCount = 0;
     if (!isHairLine) {
         // TODO: AA needs more vertices
         verticesCount *= 6;
@@ -1241,31 +1226,55 @@
             vec2 p3 = b + n;
             vec2 p4 = b - n;
 
-            // Draw the line as 2 triangles, could be optimized
-            // by using only 4 vertices and the correct indices
-            // Also we should probably used non textured vertices
-            // when line AA is disabled to save on bandwidth
-            TextureVertex::set(vertex++, p1.x, p1.y, 0.0f, 0.0f);
-            TextureVertex::set(vertex++, p2.x, p2.y, 0.0f, 0.0f);
-            TextureVertex::set(vertex++, p3.x, p3.y, 0.0f, 0.0f);
-            TextureVertex::set(vertex++, p1.x, p1.y, 0.0f, 0.0f);
-            TextureVertex::set(vertex++, p3.x, p3.y, 0.0f, 0.0f);
-            TextureVertex::set(vertex++, p4.x, p4.y, 0.0f, 0.0f);
+            const float left = fmin(p1.x, fmin(p2.x, fmin(p3.x, p4.x)));
+            const float right = fmax(p1.x, fmax(p2.x, fmax(p3.x, p4.x)));
+            const float top = fmin(p1.y, fmin(p2.y, fmin(p3.y, p4.y)));
+            const float bottom = fmax(p1.y, fmax(p2.y, fmax(p3.y, p4.y)));
 
-            // TODO: Mark the dirty regions when RENDER_LAYERS_AS_REGIONS is set
+            if (!quickReject(left, top, right, bottom)) {
+                // Draw the line as 2 triangles, could be optimized
+                // by using only 4 vertices and the correct indices
+                // Also we should probably used non textured vertices
+                // when line AA is disabled to save on bandwidth
+                TextureVertex::set(vertex++, p1.x, p1.y, 0.0f, 0.0f);
+                TextureVertex::set(vertex++, p2.x, p2.y, 0.0f, 0.0f);
+                TextureVertex::set(vertex++, p3.x, p3.y, 0.0f, 0.0f);
+                TextureVertex::set(vertex++, p1.x, p1.y, 0.0f, 0.0f);
+                TextureVertex::set(vertex++, p3.x, p3.y, 0.0f, 0.0f);
+                TextureVertex::set(vertex++, p4.x, p4.y, 0.0f, 0.0f);
+
+                generatedVerticesCount += 6;
+
+                dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
+            }
         }
 
-        // GL_LINE does not give the result we want to match Skia
-        glDrawArrays(GL_TRIANGLES, 0, verticesCount);
+        if (generatedVerticesCount > 0) {
+            // GL_LINE does not give the result we want to match Skia
+            glDrawArrays(GL_TRIANGLES, 0, generatedVerticesCount);
+        }
     } else {
         // TODO: Handle the AA case
         for (int i = 0; i < count; i += 4) {
-            TextureVertex::set(vertex++, points[i], points[i + 1], 0.0f, 0.0f);
-            TextureVertex::set(vertex++, points[i + 2], points[i + 3], 0.0f, 0.0f);
+            const float left = fmin(points[i], points[i + 1]);
+            const float right = fmax(points[i], points[i + 1]);
+            const float top = fmin(points[i + 2], points[i + 3]);
+            const float bottom = fmax(points[i + 2], points[i + 3]);
+
+            if (!quickReject(left, top, right, bottom)) {
+                TextureVertex::set(vertex++, points[i], points[i + 1], 0.0f, 0.0f);
+                TextureVertex::set(vertex++, points[i + 2], points[i + 3], 0.0f, 0.0f);
+
+                generatedVerticesCount += 2;
+
+                dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
+            }
         }
 
-        glLineWidth(1.0f);
-        glDrawArrays(GL_LINES, 0, verticesCount);
+        if (generatedVerticesCount > 0) {
+            glLineWidth(1.0f);
+            glDrawArrays(GL_LINES, 0, generatedVerticesCount);
+        }
     }
 }
 
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index c474936..6a0d7ea 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -26,7 +26,7 @@
  */
 
 // If turned on, layers drawn inside FBOs are optimized with regions
-#define RENDER_LAYERS_AS_REGIONS 0
+#define RENDER_LAYERS_AS_REGIONS 1
 
 /**
  * Debug level for app developers.
diff --git a/libs/rs/java/Samples/res/drawable/cubemap_test.png b/libs/rs/java/Samples/res/drawable/cubemap_test.png
index 75ad0a4..baf35d0 100644
--- a/libs/rs/java/Samples/res/drawable/cubemap_test.png
+++ b/libs/rs/java/Samples/res/drawable/cubemap_test.png
Binary files differ
diff --git a/libs/rs/java/Samples/src/com/android/samples/RsBenchRS.java b/libs/rs/java/Samples/src/com/android/samples/RsBenchRS.java
index 5430a13..1afcee3 100644
--- a/libs/rs/java/Samples/src/com/android/samples/RsBenchRS.java
+++ b/libs/rs/java/Samples/src/com/android/samples/RsBenchRS.java
@@ -22,7 +22,6 @@
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.renderscript.*;
-import android.renderscript.Allocation.CubemapLayout;
 import android.renderscript.Allocation.MipmapControl;
 import android.renderscript.Program.TextureType;
 import android.renderscript.ProgramStore.DepthFunc;
@@ -318,8 +317,7 @@
         mTexTransparent = loadTextureARGB(R.drawable.leaf);
         mTexChecker = loadTextureRGB(R.drawable.checker);
         Bitmap b = BitmapFactory.decodeResource(mRes, R.drawable.cubemap_test);
-        mTexCube = Allocation.createCubemapFromBitmap(mRS, b,
-                                                      Allocation.CubemapLayout.VERTICAL_FACE_LIST);
+        mTexCube = Allocation.createCubemapFromBitmap(mRS, b);
 
         mScript.set_gTexTorus(mTexTorus);
         mScript.set_gTexOpaque(mTexOpaque);
diff --git a/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java b/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java
index cac105a..87840a7 100644
--- a/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java
+++ b/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java
@@ -22,7 +22,6 @@
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.renderscript.*;
-import android.renderscript.Allocation.CubemapLayout;
 import android.renderscript.Font.Style;
 import android.renderscript.Program.TextureType;
 import android.renderscript.ProgramStore.DepthFunc;
@@ -308,8 +307,7 @@
         mTexTransparent = loadTextureARGB(R.drawable.leaf);
         mTexChecker = loadTextureRGB(R.drawable.checker);
         Bitmap b = BitmapFactory.decodeResource(mRes, R.drawable.cubemap_test);
-        mTexCube = Allocation.createCubemapFromBitmap(mRS, b,
-                                                      Allocation.CubemapLayout.VERTICAL_FACE_LIST);
+        mTexCube = Allocation.createCubemapFromBitmap(mRS, b);
 
         mScript.set_gTexTorus(mTexTorus);
         mScript.set_gTexOpaque(mTexOpaque);
diff --git a/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java b/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
index a50321e..fc3a065 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
+++ b/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
@@ -66,6 +66,7 @@
 
         unitTests.add(new UT_primitives(this, mRes, mCtx));
         unitTests.add(new UT_rsdebug(this, mRes, mCtx));
+        unitTests.add(new UT_rstime(this, mRes, mCtx));
         unitTests.add(new UT_rstypes(this, mRes, mCtx));
         unitTests.add(new UT_fp_mad(this, mRes, mCtx));
         /*
diff --git a/libs/rs/java/tests/src/com/android/rs/test/UT_rstime.java b/libs/rs/java/tests/src/com/android/rs/test/UT_rstime.java
new file mode 100644
index 0000000..f302e1a
--- /dev/null
+++ b/libs/rs/java/tests/src/com/android/rs/test/UT_rstime.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_rstime extends UnitTest {
+    private Resources mRes;
+
+    protected UT_rstime(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "rsTime", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_rstime s = new ScriptC_rstime(pRS, mRes, R.raw.rstime);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_test_rstime(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/libs/rs/java/tests/src/com/android/rs/test/rstime.rs b/libs/rs/java/tests/src/com/android/rs/test/rstime.rs
new file mode 100644
index 0000000..5e3e078
--- /dev/null
+++ b/libs/rs/java/tests/src/com/android/rs/test/rstime.rs
@@ -0,0 +1,52 @@
+#include "shared.rsh"
+
+static bool basic_test(uint32_t index) {
+    bool failed = false;
+
+    rs_time_t curTime = rsTime(0);
+    rs_tm tm;
+    rsDebug("curTime", curTime);
+
+    rsLocaltime(&tm, &curTime);
+
+    rsDebug("tm.tm_sec", tm.tm_sec);
+    rsDebug("tm.tm_min", tm.tm_min);
+    rsDebug("tm.tm_hour", tm.tm_hour);
+    rsDebug("tm.tm_mday", tm.tm_mday);
+    rsDebug("tm.tm_mon", tm.tm_mon);
+    rsDebug("tm.tm_year", tm.tm_year);
+    rsDebug("tm.tm_wday", tm.tm_wday);
+    rsDebug("tm.tm_yday", tm.tm_yday);
+    rsDebug("tm.tm_isdst", tm.tm_isdst);
+
+    // Test a specific time (only valid for PST localtime)
+    curTime = 1294438893;
+    rsLocaltime(&tm, &curTime);
+
+    _RS_ASSERT(tm.tm_sec == 33);
+    _RS_ASSERT(tm.tm_min == 21);
+    _RS_ASSERT(tm.tm_hour == 14);
+    _RS_ASSERT(tm.tm_mday == 7);
+    _RS_ASSERT(tm.tm_mon == 0);
+    _RS_ASSERT(tm.tm_year == 111);
+    _RS_ASSERT(tm.tm_wday == 5);
+    _RS_ASSERT(tm.tm_yday == 6);
+    _RS_ASSERT(tm.tm_isdst == 0);
+
+    return failed;
+}
+
+void test_rstime(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= basic_test(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+        rsDebug("rstime_test FAILED", -1);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+        rsDebug("rstime_test PASSED", 0);
+    }
+}
+
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index 3608e43..673ade2 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -831,16 +831,21 @@
         return NULL;
     }
 
+    uint32_t faceSize = t->getDimX();
+    uint32_t strideBytes = faceSize * 6 * t->getElementSizeBytes();
+    uint32_t copySize = faceSize * t->getElementSizeBytes();
+
     uint8_t *sourcePtr = (uint8_t*)data;
     for (uint32_t face = 0; face < 6; face ++) {
         Adapter2D faceAdapter(rsc, texAlloc);
         faceAdapter.setFace(face);
 
-        size_t cpySize = t->getDimX() * t->getDimX() * t->getElementSizeBytes();
-        memcpy(faceAdapter.getElement(0, 0), sourcePtr, cpySize);
+        for (uint32_t dI = 0; dI < faceSize; dI ++) {
+            memcpy(faceAdapter.getElement(0, dI), sourcePtr + strideBytes * dI, copySize);
+        }
 
         // Move the data pointer to the next cube face
-        sourcePtr += cpySize;
+        sourcePtr += copySize;
 
         if (mips == RS_ALLOCATION_MIPMAP_FULL) {
             Adapter2D adapt(rsc, texAlloc);
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 6a065b2..c5ee7ee 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -44,6 +44,7 @@
 uint32_t Context::gThreadTLSKeyCount = 0;
 uint32_t Context::gGLContextCount = 0;
 pthread_mutex_t Context::gInitMutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t Context::gLibMutex = PTHREAD_MUTEX_INITIALIZER;
 
 static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
     if (returnVal != EGL_TRUE) {
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index 3c402c4..df275bc 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -75,6 +75,8 @@
     static uint32_t gThreadTLSKeyCount;
     static uint32_t gGLContextCount;
     static pthread_mutex_t gInitMutex;
+    // Library mutex (for providing thread-safe calls from the runtime)
+    static pthread_mutex_t gLibMutex;
 
     struct ScriptTLSStruct {
         Context * mContext;
diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp
index f61b983..0b21669 100644
--- a/libs/rs/rsScriptC_Lib.cpp
+++ b/libs/rs/rsScriptC_Lib.cpp
@@ -100,70 +100,24 @@
 // Time routines
 //////////////////////////////////////////////////////////////////////////////
 
-static int32_t SC_second() {
+static time_t SC_time(time_t *timer) {
     GET_TLS();
-
-    time_t rawtime;
-    time(&rawtime);
-
-    struct tm *timeinfo;
-    timeinfo = localtime(&rawtime);
-    return timeinfo->tm_sec;
+    return time(timer);
 }
 
-static int32_t SC_minute() {
+static tm* SC_localtime(tm *local, time_t *timer) {
     GET_TLS();
+    if (!local) {
+      return NULL;
+    }
 
-    time_t rawtime;
-    time(&rawtime);
-
-    struct tm *timeinfo;
-    timeinfo = localtime(&rawtime);
-    return timeinfo->tm_min;
-}
-
-static int32_t SC_hour() {
-    GET_TLS();
-
-    time_t rawtime;
-    time(&rawtime);
-
-    struct tm *timeinfo;
-    timeinfo = localtime(&rawtime);
-    return timeinfo->tm_hour;
-}
-
-static int32_t SC_day() {
-    GET_TLS();
-
-    time_t rawtime;
-    time(&rawtime);
-
-    struct tm *timeinfo;
-    timeinfo = localtime(&rawtime);
-    return timeinfo->tm_mday;
-}
-
-static int32_t SC_month() {
-    GET_TLS();
-
-    time_t rawtime;
-    time(&rawtime);
-
-    struct tm *timeinfo;
-    timeinfo = localtime(&rawtime);
-    return timeinfo->tm_mon;
-}
-
-static int32_t SC_year() {
-    GET_TLS();
-
-    time_t rawtime;
-    time(&rawtime);
-
-    struct tm *timeinfo;
-    timeinfo = localtime(&rawtime);
-    return timeinfo->tm_year;
+    // The native localtime function is not thread-safe, so we
+    // have to apply locking for proper behavior in RenderScript.
+    pthread_mutex_lock(&rsc->gLibMutex);
+    tm *tmp = localtime(timer);
+    memcpy(local, tmp, sizeof(*tmp));
+    pthread_mutex_unlock(&rsc->gLibMutex);
+    return local;
 }
 
 static int64_t SC_uptimeMillis() {
@@ -498,12 +452,8 @@
     { "_Z6rsFracf", (void *)&SC_frac, true },
 
     // time
-    { "_Z8rsSecondv", (void *)&SC_second, true },
-    { "_Z8rsMinutev", (void *)&SC_minute, true },
-    { "_Z6rsHourv", (void *)&SC_hour, true },
-    { "_Z5rsDayv", (void *)&SC_day, true },
-    { "_Z7rsMonthv", (void *)&SC_month, true },
-    { "_Z6rsYearv", (void *)&SC_year, true },
+    { "_Z6rsTimePi", (void *)&SC_time, true },
+    { "_Z11rsLocaltimeP5rs_tmPKi", (void *)&SC_localtime, true },
     { "_Z14rsUptimeMillisv", (void*)&SC_uptimeMillis, true },
     { "_Z13rsUptimeNanosv", (void*)&SC_uptimeNanos, true },
     { "_Z7rsGetDtv", (void*)&SC_getDt, false },
diff --git a/libs/rs/scriptc/rs_math.rsh b/libs/rs/scriptc/rs_math.rsh
index d059997..a74c0e0 100644
--- a/libs/rs/scriptc/rs_math.rsh
+++ b/libs/rs/scriptc/rs_math.rsh
@@ -118,32 +118,6 @@
 extern float __attribute__((overloadable))
     rsFrac(float);
 
-// time
-extern int32_t __attribute__((overloadable))
-    rsSecond(void);
-extern int32_t __attribute__((overloadable))
-    rsMinute(void);
-extern int32_t __attribute__((overloadable))
-    rsHour(void);
-extern int32_t __attribute__((overloadable))
-    rsDay(void);
-extern int32_t __attribute__((overloadable))
-    rsMonth(void);
-extern int32_t __attribute__((overloadable))
-    rsYear(void);
-
-// Return the current system clock in milliseconds
-extern int64_t __attribute__((overloadable))
-    rsUptimeMillis(void);
-
-// Return the current system clock in nanoseconds
-extern int64_t __attribute__((overloadable))
-    rsUptimeNanos(void);
-
-// Return the time in seconds since function was last called in this script.
-extern float __attribute__((overloadable))
-    rsGetDt(void);
-
 // Send a message back to the client.  Will not block and returns true
 // if the message was sendable and false if the fifo was full.
 // A message ID is required.  Data payload is optional.
diff --git a/libs/rs/scriptc/rs_time.rsh b/libs/rs/scriptc/rs_time.rsh
new file mode 100644
index 0000000..f1abed63
--- /dev/null
+++ b/libs/rs/scriptc/rs_time.rsh
@@ -0,0 +1,36 @@
+#ifndef __RS_TIME_RSH__
+#define __RS_TIME_RSH__
+
+typedef int rs_time_t;
+
+typedef struct {
+    int tm_sec;
+    int tm_min;
+    int tm_hour;
+    int tm_mday;
+    int tm_mon;
+    int tm_year;
+    int tm_wday;
+    int tm_yday;
+    int tm_isdst;
+} rs_tm;
+
+extern rs_time_t __attribute__((overloadable))
+    rsTime(rs_time_t *timer);
+
+extern rs_tm * __attribute__((overloadable))
+    rsLocaltime(rs_tm *local, const rs_time_t *timer);
+
+// Return the current system clock in milliseconds
+extern int64_t __attribute__((overloadable))
+    rsUptimeMillis(void);
+
+// Return the current system clock in nanoseconds
+extern int64_t __attribute__((overloadable))
+    rsUptimeNanos(void);
+
+// Return the time in seconds since function was last called in this script.
+extern float __attribute__((overloadable))
+    rsGetDt(void);
+
+#endif
diff --git a/media/libmediaplayerservice/nuplayer/DecoderWrapper.cpp b/media/libmediaplayerservice/nuplayer/DecoderWrapper.cpp
index 4d4cd8d..802d1fb 100644
--- a/media/libmediaplayerservice/nuplayer/DecoderWrapper.cpp
+++ b/media/libmediaplayerservice/nuplayer/DecoderWrapper.cpp
@@ -309,6 +309,18 @@
 
         realNotify->setInt32("width", width);
         realNotify->setInt32("height", height);
+
+        int32_t cropLeft, cropTop, cropRight, cropBottom;
+        if (!meta->findRect(
+                    kKeyCropRect,
+                    &cropLeft, &cropTop, &cropRight, &cropBottom)) {
+            cropLeft = 0;
+            cropTop = 0;
+            cropRight = width - 1;
+            cropBottom = height - 1;
+        }
+
+        realNotify->setRect("crop", cropLeft, cropTop, cropRight, cropBottom);
     }
 
     notify->post();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index e1b371e..7f534c0 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -271,22 +271,43 @@
 
                 finishFlushIfPossible();
             } else if (what == ACodec::kWhatOutputFormatChanged) {
-                CHECK(audio);
+                if (audio) {
+                    int32_t numChannels;
+                    CHECK(codecRequest->findInt32("channel-count", &numChannels));
 
-                int32_t numChannels;
-                CHECK(codecRequest->findInt32("channel-count", &numChannels));
+                    int32_t sampleRate;
+                    CHECK(codecRequest->findInt32("sample-rate", &sampleRate));
 
-                int32_t sampleRate;
-                CHECK(codecRequest->findInt32("sample-rate", &sampleRate));
+                    LOGV("Audio output format changed to %d Hz, %d channels",
+                         sampleRate, numChannels);
 
-                LOGV("Audio output format changed to %d Hz, %d channels",
-                     sampleRate, numChannels);
+                    mAudioSink->close();
+                    CHECK_EQ(mAudioSink->open(sampleRate, numChannels), (status_t)OK);
+                    mAudioSink->start();
 
-                mAudioSink->close();
-                CHECK_EQ(mAudioSink->open(sampleRate, numChannels), (status_t)OK);
-                mAudioSink->start();
+                    mRenderer->signalAudioSinkChanged();
+                } else {
+                    // video
 
-                mRenderer->signalAudioSinkChanged();
+                    int32_t width, height;
+                    CHECK(codecRequest->findInt32("width", &width));
+                    CHECK(codecRequest->findInt32("height", &height));
+
+                    int32_t cropLeft, cropTop, cropRight, cropBottom;
+                    CHECK(codecRequest->findRect(
+                                "crop",
+                                &cropLeft, &cropTop, &cropRight, &cropBottom));
+
+                    LOGV("Video output format changed to %d x %d "
+                         "(crop: %d, %d, %d, %d)",
+                         width, height,
+                         cropLeft, cropTop, cropRight, cropBottom);
+
+                    notifyListener(
+                            MEDIA_SET_VIDEO_SIZE,
+                            cropRight - cropLeft + 1,
+                            cropBottom - cropTop + 1);
+                }
             } else if (what == ACodec::kWhatShutdownCompleted) {
                 LOGV("%s shutdown completed", audio ? "audio" : "video");
                 if (audio) {
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 39e0c51..dfb4e00 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -299,7 +299,8 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 ACodec::ACodec()
-    : mNode(NULL) {
+    : mNode(NULL),
+      mSentFormat(false) {
     mUninitializedState = new UninitializedState(this);
     mLoadedToIdleState = new LoadedToIdleState(this);
     mIdleToExecutingState = new IdleToExecutingState(this);
@@ -980,6 +981,103 @@
     }
 }
 
+void ACodec::sendFormatChange() {
+    sp<AMessage> notify = mNotify->dup();
+    notify->setInt32("what", kWhatOutputFormatChanged);
+
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+    InitOMXParams(&def);
+    def.nPortIndex = kPortIndexOutput;
+
+    CHECK_EQ(mOMX->getParameter(
+                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
+             (status_t)OK);
+
+    CHECK_EQ((int)def.eDir, (int)OMX_DirOutput);
+
+    switch (def.eDomain) {
+        case OMX_PortDomainVideo:
+        {
+            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
+
+            notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
+            notify->setInt32("width", videoDef->nFrameWidth);
+            notify->setInt32("height", videoDef->nFrameHeight);
+
+            OMX_CONFIG_RECTTYPE rect;
+            InitOMXParams(&rect);
+            rect.nPortIndex = kPortIndexOutput;
+
+            if (mOMX->getConfig(
+                        mNode, OMX_IndexConfigCommonOutputCrop,
+                        &rect, sizeof(rect)) != OK) {
+                rect.nLeft = 0;
+                rect.nTop = 0;
+                rect.nWidth = videoDef->nFrameWidth;
+                rect.nHeight = videoDef->nFrameHeight;
+            }
+
+            CHECK_GE(rect.nLeft, 0);
+            CHECK_GE(rect.nTop, 0);
+            CHECK_GE(rect.nWidth, 0u);
+            CHECK_GE(rect.nHeight, 0u);
+            CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
+            CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
+
+            notify->setRect(
+                    "crop",
+                    rect.nLeft,
+                    rect.nTop,
+                    rect.nLeft + rect.nWidth - 1,
+                    rect.nTop + rect.nHeight - 1);
+
+            if (mNativeWindow != NULL) {
+                android_native_rect_t crop;
+                crop.left = rect.nLeft;
+                crop.top = rect.nTop;
+                crop.right = rect.nLeft + rect.nWidth - 1;
+                crop.bottom = rect.nTop + rect.nHeight - 1;
+
+                CHECK_EQ(0, native_window_set_crop(
+                            mNativeWindow.get(), &crop));
+            }
+            break;
+        }
+
+        case OMX_PortDomainAudio:
+        {
+            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
+            CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM);
+
+            OMX_AUDIO_PARAM_PCMMODETYPE params;
+            InitOMXParams(&params);
+            params.nPortIndex = kPortIndexOutput;
+
+            CHECK_EQ(mOMX->getParameter(
+                        mNode, OMX_IndexParamAudioPcm,
+                        &params, sizeof(params)),
+                     (status_t)OK);
+
+            CHECK(params.nChannels == 1 || params.bInterleaved);
+            CHECK_EQ(params.nBitPerSample, 16u);
+            CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned);
+            CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear);
+
+            notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
+            notify->setInt32("channel-count", params.nChannels);
+            notify->setInt32("sample-rate", params.nSamplingRate);
+            break;
+        }
+
+        default:
+            TRESPASS();
+    }
+
+    notify->post();
+
+    mSentFormat = true;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
@@ -1305,6 +1403,10 @@
                     info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
                 }
             } else {
+                if (!mCodec->mSentFormat) {
+                    mCodec->sendFormatChange();
+                }
+
                 if (mCodec->mNativeWindow == NULL) {
                     info->mData->setRange(rangeOffset, rangeLength);
                 }
@@ -1717,7 +1819,7 @@
         {
             CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
 
-            if (data2 == OMX_IndexParamPortDefinition) {
+            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
                 CHECK_EQ(mCodec->mOMX->sendCommand(
                             mCodec->mNode,
                             OMX_CommandPortDisable, kPortIndexOutput),
@@ -1729,6 +1831,8 @@
                 }
 
                 mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
+            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
+                mCodec->mSentFormat = false;
             } else {
                 LOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
                      mCodec->mComponentName.c_str(), data2);
@@ -1816,6 +1920,8 @@
             } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
                 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
 
+                mCodec->mSentFormat = false;
+
                 LOGV("[%s] Output port now reenabled.",
                         mCodec->mComponentName.c_str());
 
@@ -1869,6 +1975,8 @@
 
 void ACodec::ExecutingToIdleState::stateEntered() {
     LOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
+
+    mCodec->mSentFormat = false;
 }
 
 bool ACodec::ExecutingToIdleState::onOMXEvent(
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index 9677838..31b6ec9 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -347,7 +347,8 @@
 }
 
 void CameraSourceTimeLapse::releaseRecordingFrame(const sp<IMemory>& frame) {
-    if (!mUseStillCameraForTimeLapse) {
+    if (!mUseStillCameraForTimeLapse &&
+        mCamera != NULL) {
         mCamera->releaseRecordingFrame(frame);
     }
 }
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 7750a9d..e516cb4 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -3923,6 +3923,8 @@
 
             if (!mIsEncoder) {
                 OMX_CONFIG_RECTTYPE rect;
+                InitOMXParams(&rect);
+                rect.nPortIndex = kPortIndexOutput;
                 status_t err =
                         mOMX->getConfig(
                             mNode, OMX_IndexConfigCommonOutputCrop,
diff --git a/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp b/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp
index 0f08f6e..38778fb 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp
@@ -132,7 +132,10 @@
     }
 
     MP4DecodingMode actualMode = PVGetDecBitstreamMode(mHandle);
-    CHECK_EQ(mode, actualMode);
+    if (mode != actualMode) {
+        PVCleanUpVideoDecoder(mHandle);
+        return UNKNOWN_ERROR;
+    }
 
     PVSetPostProcType((VideoDecControls *) mHandle, 0);
 
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
index 0e40acc..b592c3f 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -171,6 +171,18 @@
     item->u.refValue = obj.get();
 }
 
+void AMessage::setRect(
+        const char *name,
+        int32_t left, int32_t top, int32_t right, int32_t bottom) {
+    Item *item = allocateItem(name);
+    item->mType = kTypeRect;
+
+    item->u.rectValue.mLeft = left;
+    item->u.rectValue.mTop = top;
+    item->u.rectValue.mRight = right;
+    item->u.rectValue.mBottom = bottom;
+}
+
 bool AMessage::findString(const char *name, AString *value) const {
     const Item *item = findItem(name, kTypeString);
     if (item) {
@@ -198,6 +210,22 @@
     return false;
 }
 
+bool AMessage::findRect(
+        const char *name,
+        int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) const {
+    const Item *item = findItem(name, kTypeRect);
+    if (item == NULL) {
+        return false;
+    }
+
+    *left = item->u.rectValue.mLeft;
+    *top = item->u.rectValue.mTop;
+    *right = item->u.rectValue.mRight;
+    *bottom = item->u.rectValue.mBottom;
+
+    return true;
+}
+
 void AMessage::post(int64_t delayUs) {
     extern ALooperRoster gLooperRoster;
 
diff --git a/opengl/tests/hwc/hwcCommit.cpp b/opengl/tests/hwc/hwcCommit.cpp
index ed74cbe..66ccdae 100644
--- a/opengl/tests/hwc/hwcCommit.cpp
+++ b/opengl/tests/hwc/hwcCommit.cpp
@@ -76,6 +76,7 @@
 #include <cmath>
 #include <cstdlib>
 #include <ctime>
+#include <iomanip>
 #include <istream>
 #include <libgen.h>
 #include <list>
@@ -125,6 +126,7 @@
 const struct hwc_rect defaultDisplayFrame = {0, 0, 100, 100};
 
 // Global Constants
+const uint32_t printFieldWidth = 2;
 const struct searchLimits {
     uint32_t   numOverlays;
     HwcTestDim sourceCrop;
@@ -233,6 +235,8 @@
 static EGLDisplay dpy;
 static EGLSurface surface;
 static EGLint width, height;
+static size_t maxHeadingLen;
+static vector<string> formats;
 
 // Measurements
 struct meas {
@@ -264,6 +268,9 @@
         HwcTestDim vScaleBestDf;
         HwcTestDim vScaleBestSc;
     } sc;
+    vector<uint32_t> overlapBlendNone;
+    vector<uint32_t> overlapBlendPremult;
+    vector<uint32_t> overlapBlendCoverage;
 };
 vector<meas> measurements;
 
@@ -292,9 +299,14 @@
                   const HwcTestDim& dfMin, const HwcTestDim& dfMax,
                   const HwcTestDim& scMin, const HwcTestDim& scMax,
                   HwcTestDim& outBestDf, HwcTestDim& outBestSc);
+uint32_t numOverlapping(uint32_t backgroundFormat, uint32_t foregroundFormat,
+                        uint32_t backgroundBlend, uint32_t foregroundBlend);
 string transformList2str(const list<uint32_t>& transformList);
 string blendList2str(const list<uint32_t>& blendList);
 void init(void);
+void printFormatHeadings(size_t indent);
+void printOverlapLine(size_t indent, const string formatStr,
+                      const vector<uint32_t>& results);
 void printSyntax(const char *cmd);
 
 // Command-line option settings
@@ -332,7 +344,6 @@
     bool    error;
     string  str;
     char cmd[MAXCMD];
-    list<string> formats;
     list<Rectangle> rectList;
 
     testSetLogCatTag(LOG_TAG);
@@ -395,6 +406,13 @@
         }
     }
 
+    // Determine length of longest specified graphic format.
+    // This value is used for output formating
+    for (vector<string>::iterator it = formats.begin();
+         it != formats.end(); ++it) {
+         maxHeadingLen = max(maxHeadingLen, it->length());
+    }
+
     // Stop framework
     rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STOP_FRAMEWORK);
     if (rv >= (signed) sizeof(cmd) - 1) {
@@ -411,7 +429,7 @@
     init();
 
     // For each of the graphic formats
-    for (list<string>::iterator itFormat = formats.begin();
+    for (vector<string>::iterator itFormat = formats.begin();
          itFormat != formats.end(); ++itFormat) {
 
         // Locate hwcTestLib structure that describes this format
@@ -539,8 +557,66 @@
         testPrintI("    VScale Best Source Crop: %s",
                    ((string) measPtr->sc.vScaleBestSc).c_str());
 
+        // Overlap two graphic formats and different blends
+        // Results displayed after all overlap measurments with
+        // current format in the foreground
+        // TODO: make measurments with background blend other than
+        //       none.  All of these measurements are done with a
+        //       background blend of HWC_BLENDING_NONE, with the
+        //       blend type of the foregound being varied.
+        uint32_t foregroundFormat = format->format;
+        for (vector<string>::iterator it = formats.begin();
+             it != formats.end(); ++it) {
+            uint32_t num;
+
+            const struct hwcTestGraphicFormat *backgroundFormatPtr
+                = hwcTestGraphicFormatLookup((*it).c_str());
+            uint32_t backgroundFormat = backgroundFormatPtr->format;
+
+            num = numOverlapping(backgroundFormat, foregroundFormat,
+                                 HWC_BLENDING_NONE, HWC_BLENDING_NONE);
+            measPtr->overlapBlendNone.push_back(num);
+
+            num = numOverlapping(backgroundFormat, foregroundFormat,
+                                 HWC_BLENDING_NONE, HWC_BLENDING_PREMULT);
+            measPtr->overlapBlendPremult.push_back(num);
+
+            num = numOverlapping(backgroundFormat, foregroundFormat,
+                                 HWC_BLENDING_NONE, HWC_BLENDING_COVERAGE);
+            measPtr->overlapBlendCoverage.push_back(num);
+        }
+
     }
 
+    // Display overlap results
+    size_t indent = 2;
+    testPrintI("overlapping blend: none");
+    printFormatHeadings(indent);
+    for (vector<string>::iterator it = formats.begin();
+         it != formats.end(); ++it) {
+        printOverlapLine(indent, *it, measurements[it
+                         - formats.begin()].overlapBlendNone);
+    }
+    testPrintI("");
+
+    testPrintI("overlapping blend: premult");
+    printFormatHeadings(indent);
+    for (vector<string>::iterator it = formats.begin();
+         it != formats.end(); ++it) {
+        printOverlapLine(indent, *it, measurements[it
+                         - formats.begin()].overlapBlendPremult);
+    }
+    testPrintI("");
+
+    testPrintI("overlapping blend: coverage");
+    printFormatHeadings(indent);
+    for (vector<string>::iterator it = formats.begin();
+         it != formats.end(); ++it) {
+        printOverlapLine(indent, *it, measurements[it
+                         - formats.begin()].overlapBlendCoverage);
+    }
+    testPrintI("");
+
     // Start framework
     rv = snprintf(cmd, sizeof(cmd), "%s", CMD_START_FRAMEWORK);
     if (rv >= (signed) sizeof(cmd) - 1) {
@@ -1204,6 +1280,33 @@
     return best;
 }
 
+uint32_t numOverlapping(uint32_t backgroundFormat, uint32_t foregroundFormat,
+                        uint32_t backgroundBlend, uint32_t foregroundBlend)
+{
+    list<Rectangle> rectList;
+
+    Rectangle background(backgroundFormat, startDim, startDim);
+    background.blend = backgroundBlend;
+    rectList.push_back(background);
+
+    // TODO: Handle cases where startDim is so small that adding 5
+    //       causes frames not to overlap.
+    // TODO: Handle cases where startDim is so large that adding 5
+    //       cause a portion or all of the foreground displayFrame
+    //       to be off the display.
+    Rectangle foreground(foregroundFormat, startDim, startDim);
+    foreground.displayFrame.left += 5;
+    foreground.displayFrame.top += 5;
+    foreground.displayFrame.right += 5;
+    foreground.displayFrame.bottom += 5;
+    background.blend = foregroundBlend;
+    rectList.push_back(foreground);
+
+    uint32_t num = numOverlays(rectList);
+
+    return num;
+}
+
 Rectangle::Rectangle(uint32_t graphicFormat, HwcTestDim dfDim,
                      HwcTestDim sDim) :
     format(graphicFormat), transform(defaultTransform),
@@ -1405,6 +1508,45 @@
     hwcTestOpenHwc(&hwcDevice);
 }
 
+void printFormatHeadings(size_t indent)
+{
+    for (size_t row = 0; row <= maxHeadingLen; row++) {
+        ostringstream line;
+        for(vector<string>::iterator it = formats.begin();
+            it != formats.end(); ++it) {
+            if ((maxHeadingLen - row) <= it->length()) {
+                if (row != maxHeadingLen) {
+                    char ch = (*it)[it->length() - (maxHeadingLen - row)];
+                    line << ' ' << setw(printFieldWidth) << ch;
+                } else {
+                    line << ' ' << string(printFieldWidth, '-');
+                }
+            } else {
+               line << ' ' << setw(printFieldWidth) << "";
+            }
+        }
+        testPrintI("%*s%s", indent + maxHeadingLen, "",
+                   line.str().c_str());
+    }
+}
+
+void printOverlapLine(size_t indent, const string formatStr,
+                        const vector<uint32_t>& results)
+{
+    ostringstream line;
+
+    line << setw(indent + maxHeadingLen - formatStr.length()) << "";
+
+    line << formatStr;
+
+    for (vector<uint32_t>::const_iterator it = results.begin();
+         it != results.end(); ++it) {
+        line << ' ' << setw(printFieldWidth) << *it;
+    }
+
+    testPrintI("%s", line.str().c_str());
+}
+
 void printSyntax(const char *cmd)
 {
     testPrintE("  %s [options] [graphicFormat] ...",
diff --git a/opengl/tests/hwc/hwcTestLib.cpp b/opengl/tests/hwc/hwcTestLib.cpp
index a468a92..925405e 100644
--- a/opengl/tests/hwc/hwcTestLib.cpp
+++ b/opengl/tests/hwc/hwcTestLib.cpp
@@ -475,14 +475,14 @@
         testPrintI("      displayFrame: %s",
                    hwcTestRect2str(list->hwLayers[layer].displayFrame).c_str());
         testPrintI("      scaleFactor: [%f, %f]",
-                   (float) (list->hwLayers[layer].displayFrame.right
-                            - list->hwLayers[layer].displayFrame.left)
-                       / (float) (list->hwLayers[layer].sourceCrop.right
-                            - list->hwLayers[layer].sourceCrop.left),
-                   (float) (list->hwLayers[layer].displayFrame.bottom
-                            - list->hwLayers[layer].displayFrame.top)
-                       / (float) (list->hwLayers[layer].sourceCrop.bottom
-                            - list->hwLayers[layer].sourceCrop.top));
+                   (float) (list->hwLayers[layer].sourceCrop.right
+                            - list->hwLayers[layer].sourceCrop.left)
+                       / (float) (list->hwLayers[layer].displayFrame.right
+                            - list->hwLayers[layer].displayFrame.left),
+                   (float) (list->hwLayers[layer].sourceCrop.bottom
+                            - list->hwLayers[layer].sourceCrop.top)
+                       / (float) (list->hwLayers[layer].displayFrame.bottom
+                            - list->hwLayers[layer].displayFrame.top));
     }
 }
 
@@ -494,7 +494,11 @@
  */
 void hwcTestDisplayListPrepareModifiable(hwc_layer_list_t *list)
 {
+    uint32_t numOverlays = 0;
     for (unsigned int layer = 0; layer < list->numHwLayers; layer++) {
+        if (list->hwLayers[layer].compositionType == HWC_OVERLAY) {
+            numOverlays++;
+        }
         testPrintI("    layer %u compositionType: %#x%s%s", layer,
                    list->hwLayers[layer].compositionType,
                    (list->hwLayers[layer].compositionType == HWC_FRAMEBUFFER)
@@ -508,6 +512,7 @@
                    (list->hwLayers[layer].hints & HWC_HINT_CLEAR_FB)
                        ? " CLEAR_FB" : "");
     }
+    testPrintI("    numOverlays: %u", numOverlays);
 }
 
 /*
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 6e2bfdb..f8809d7 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -262,11 +262,8 @@
 
         // Watch for external modifications to the database file,
         // keeping our cache in sync.
-        // It's kinda lame to call mOpenHelper.getReadableDatabase()
-        // during onCreate(), but since ensureAndroidIdIsSet has
-        // already done it above and initialized/upgraded the
-        // database, might as well just use it...
-        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+        db.enableWriteAheadLogging();
         sObserverInstance = new SettingsFileObserver(db.getPath());
         sObserverInstance.startWatching();
         startAsyncCachePopulation();
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index d824f30..d3d1750 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -12,6 +12,7 @@
     <application
         android:persistent="true"
         android:allowClearUserData="false"
+        android:hardwareAccelerated="true"
         android:label="@string/app_label"
         android:icon="@drawable/ic_launcher_settings">
 
diff --git a/packages/SystemUI/res/drawable-nodpi/panel_notification.png b/packages/SystemUI/res/drawable-nodpi/panel_notification.png
index b0d9c18..437deff 100644
--- a/packages/SystemUI/res/drawable-nodpi/panel_notification.png
+++ b/packages/SystemUI/res/drawable-nodpi/panel_notification.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/panel_notification_tiled.xml b/packages/SystemUI/res/drawable/panel_notification_tiled.xml
new file mode 100644
index 0000000..9d41e28
--- /dev/null
+++ b/packages/SystemUI/res/drawable/panel_notification_tiled.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<bitmap
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/panel_notification"
+    android:tileMode="repeat"
+    />
+
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel.xml b/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel.xml
index d3fe2e7..7f84b21 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel.xml
@@ -20,27 +20,35 @@
     xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
     android:layout_height="match_parent"
     android:layout_width="match_parent"
-    android:orientation="vertical"
     android:gravity="right"
-    android:paddingTop="32dp"
     >
 
-    <LinearLayout
+    <View
+        android:id="@+id/scrim"
+        android:background="@drawable/notify_panel_bg_protect"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_alignParentTop="true"
+        android:layout_alignParentRight="true"
+        />
+
+    <RelativeLayout
         android:id="@+id/content_parent"
         android:layout_height="wrap_content"
         android:layout_width="wrap_content"
-        android:animateLayoutChanges="true"
-        android:orientation="vertical"
+        android:layout_alignParentBottom="true"
+        android:layout_alignParentRight="true"
         >
-
-        <com.android.systemui.statusbar.tablet.NotificationTitleArea
+        <RelativeLayout
             android:id="@+id/title_area"
             android:layout_height="160dp"
             android:layout_width="384dp"
             android:layout_marginLeft="24dp"
             android:paddingTop="20dp"
             android:orientation="vertical"
-            android:animateLayoutChanges="true"
+            android:layout_alignParentTop="true"
+            android:layout_alignParentRight="true"
+            android:background="@drawable/panel_notification_tiled"
             >
 
             <com.android.systemui.statusbar.tablet.HoloClock
@@ -154,13 +162,15 @@
                 android:src="@drawable/status_bar_veto"
                 android:baseline="21dp"
                 />
-        </com.android.systemui.statusbar.tablet.NotificationTitleArea>
+        </RelativeLayout>
 
         <LinearLayout
             android:id="@+id/content_frame"
             android:layout_height="wrap_content"
             android:layout_width="408dp"
             android:orientation="vertical"
+            android:layout_below="@id/title_area"
+            android:layout_alignParentRight="true"
             >
             <ScrollView
                 android:id="@+id/notification_scroller"
@@ -191,5 +201,17 @@
                 android:src="@drawable/notify_item_glow_bottom"
                 />
         </LinearLayout>
-    </LinearLayout>
+    </RelativeLayout>
+
+    <View
+        android:id="@+id/glow"
+        android:background="@drawable/notify_glow_back"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignTop="@id/content_parent"
+        android:layout_alignLeft="@id/content_parent"
+        android:layout_marginLeft="100dip"
+        android:layout_marginTop="-100dip"
+        />
+
 </com.android.systemui.statusbar.tablet.NotificationPanel>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
index 7dcf9be..3201d06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.tablet;
 
 import android.animation.Animator;
+import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.content.Context;
@@ -33,11 +34,13 @@
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.FrameLayout;
 import android.widget.TextView;
 
 import com.android.systemui.R;
 
-public class NotificationPanel extends LinearLayout implements StatusBarPanel,
+public class NotificationPanel extends RelativeLayout implements StatusBarPanel,
         View.OnClickListener {
     static final String TAG = "Tablet/NotificationPanel";
     static final boolean DEBUG = false;
@@ -51,12 +54,11 @@
     ViewGroup mContentFrame;
     Rect mContentArea;
     View mSettingsView;
+    View mScrim, mGlow;
     ViewGroup mContentParent;
 
     Choreographer mChoreo = new Choreographer();
     int mStatusBarHeight;
-    Drawable mBgDrawable;
-    Drawable mGlowDrawable;
 
     public NotificationPanel(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
@@ -69,8 +71,6 @@
 
         mStatusBarHeight = res.getDimensionPixelSize(
                 com.android.internal.R.dimen.status_bar_height);
-        mBgDrawable = res.getDrawable(R.drawable.notify_panel_bg_protect);
-        mGlowDrawable = res.getDrawable(R.drawable.notify_glow_back);
     }
 
     @Override
@@ -80,9 +80,13 @@
         setWillNotDraw(false);
 
         mContentParent = (ViewGroup)findViewById(R.id.content_parent);
+        mContentParent.bringToFront();
         mTitleArea = findViewById(R.id.title_area);
         mTitleArea.setOnClickListener(this);
 
+        mScrim = findViewById(R.id.scrim);
+        mGlow = findViewById(R.id.glow);
+
         mSettingsButton = (ImageView)findViewById(R.id.settings_button);
         mNotificationButton = (ImageView)findViewById(R.id.notification_button);
 
@@ -132,21 +136,6 @@
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         super.onLayout(changed, l, t, r, b);
-        // We know that none of our children are GONE, so don't worry about skipping GONE views.
-        final int N = getChildCount();
-        if (N == 0) {
-            return;
-        }
-        final int allocatedBottom = getChildAt(N-1).getBottom();
-        final int shift = b - allocatedBottom - getPaddingBottom();
-        if (shift <= 0) {
-            return;
-        }
-        for (int i=0; i<N; i++) {
-            final View c = getChildAt(i);
-            c.layout(c.getLeft(), c.getTop() + shift, c.getRight(), c.getBottom() + shift);
-        }
-
         mChoreo.setPanelHeight(mContentParent.getHeight());
     }
 
@@ -154,26 +143,6 @@
     public void onSizeChanged(int w, int h, int oldw, int oldh) {
         super.onSizeChanged(w, h, oldw, oldh);
         mContentArea = null;
-        mBgDrawable.setBounds(0, 0, w, h-mStatusBarHeight);
-    }
-
-    @Override
-    public void onDraw(Canvas canvas) {
-        int saveCount;
-        final int w = getWidth();
-        final int h = getHeight();
-
-        super.onDraw(canvas);
-
-        // Background protection
-        mBgDrawable.draw(canvas);
-
-        // The panel glow (behind status bar)
-
-        saveCount = canvas.save();
-        canvas.clipRect(0, 0, w, h-mStatusBarHeight);
-        mGlowDrawable.draw(canvas);
-        canvas.restoreToCount(saveCount);
     }
 
     public void onClick(View v) {
@@ -227,82 +196,82 @@
 
     private class Choreographer implements Animator.AnimatorListener {
         boolean mVisible;
-        int mBgAlpha;
-        ValueAnimator mBgAnim;
         int mPanelHeight;
-        int mPanelBottom;
-        ValueAnimator mPositionAnim;
+        AnimatorSet mContentAnim;
 
         // should group this into a multi-property animation
-        final int OPEN_DURATION = 200;
+        final int OPEN_DURATION = 250;
+
+        // the panel will start to appear this many px from the end
+        final int HYPERSPACE_OFFRAMP = 120;
 
         Choreographer() {
         }
 
-        void createAnimation(boolean visible) {
-            mBgAnim = ObjectAnimator.ofInt(this, "bgAlpha", mBgAlpha, visible ? 255 : 0)
-                    .setDuration(OPEN_DURATION);
-            mBgAnim.addListener(this);
+        void createAnimation(boolean appearing) {
+            Animator bgAnim = ObjectAnimator.ofFloat(mScrim,
+                    "alpha", mScrim.getAlpha(), appearing ? 1 : 0);
 
-            mPositionAnim = ObjectAnimator.ofInt(this, "panelBottom", mPanelBottom,
-                        visible ? mPanelHeight : 0)
-                    .setDuration(OPEN_DURATION);
-        }
+            float start, end;
 
-        void startAnimation(boolean visible) {
-            if (DEBUG) Slog.d(TAG, "startAnimation(visible=" + visible + ")");
-
-            createAnimation(visible);
-            mBgAnim.start();
-            mPositionAnim.start();
-
-            mVisible = visible;
-        }
-
-        void jumpTo(boolean visible) {
-            setBgAlpha(visible ? 255 : 0);
-            setPanelBottom(visible ? mPanelHeight : 0);
-        }
-
-        public void setBgAlpha(int alpha) {
-            mBgAlpha = alpha;
-            mBgDrawable.setAlpha((int)(alpha));
-            invalidate();
-        }
-
-        // 0 is closed, the height of the panel is open
-        public void setPanelBottom(int y) {
-            mPanelBottom = y;
-            int translationY = mPanelHeight - y;
-            mContentParent.setTranslationY(translationY);
-
-            final int glowXOffset = 100;
-            final int glowYOffset = 100;
-            int glowX = mContentParent.getLeft() - glowXOffset;
-            int glowY = mContentParent.getTop() - glowYOffset + translationY;
-            mGlowDrawable.setBounds(glowX, glowY, glowX + mGlowDrawable.getIntrinsicWidth(),
-                    glowY + mGlowDrawable.getIntrinsicHeight());
-
-            float alpha;
-            if (mPanelBottom > glowYOffset) {
-                alpha = 1;
+            // 0: on-screen
+            // height: off-screen
+            float y = mContentParent.getTranslationY();
+            if (appearing) {
+                // we want to go from near-the-top to the top, unless we're half-open in the right
+                // general vicinity
+                start = (y < HYPERSPACE_OFFRAMP)
+                    ? y
+                    : HYPERSPACE_OFFRAMP;
+                end = 0;
             } else {
-                alpha = ((float)mPanelBottom) / glowYOffset;
+                start = y;
+                end = y + HYPERSPACE_OFFRAMP;
             }
-            mContentParent.setAlpha(alpha);
-            mGlowDrawable.setAlpha((int)(255 * alpha));
+            Animator posAnim = ObjectAnimator.ofFloat(mContentParent, "translationY", start, end);
+            posAnim.setInterpolator(appearing 
+                    ? new android.view.animation.DecelerateInterpolator(2.0f)
+                    : new android.view.animation.AccelerateInterpolator(2.0f));
 
-            if (false) {
-                Slog.d(TAG, "mPanelBottom=" + mPanelBottom + " translationY=" + translationY
-                        + " alpha=" + alpha + " glowY=" + glowY);
-            }
+            Animator glowAnim = ObjectAnimator.ofFloat(mGlow, "alpha",
+                    mGlow.getAlpha(), appearing ? 1.0f : 0.0f);
+            glowAnim.setInterpolator(appearing 
+                    ? new android.view.animation.AccelerateInterpolator(1.0f)
+                    : new android.view.animation.DecelerateInterpolator(1.0f));
+
+            mContentAnim = new AnimatorSet();
+            mContentAnim
+                .play(ObjectAnimator.ofFloat(mContentParent, "alpha", mContentParent.getAlpha(),
+                                                                      appearing ? 1.0f : 0.0f))
+                .with(glowAnim)
+                .with(bgAnim)
+                .with(posAnim)
+                ;
+            mContentAnim.setDuration(OPEN_DURATION);
+            mContentAnim.addListener(this);
+        }
+
+        void startAnimation(boolean appearing) {
+            if (DEBUG) Slog.d(TAG, "startAnimation(appearing=" + appearing + ")");
+
+            createAnimation(appearing);
+
+            mContentParent.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            mContentAnim.start();
+
+            mVisible = appearing;
+        }
+
+        void jumpTo(boolean appearing) {
+//            setBgAlpha(appearing ? 255 : 0);
+            mContentParent.setTranslationY(appearing ? 0 : mPanelHeight);
         }
 
         public void setPanelHeight(int h) {
+            if (DEBUG) Slog.d(TAG, "panelHeight=" + h);
             mPanelHeight = h;
-            if (mPanelBottom == 0) {
+            if (mPanelHeight == 0) {
                 // fully closed, no animation necessary
-                setPanelBottom(0);
             } else if (mVisible) {
                 if (DEBUG) {
                     Slog.d(TAG, "panelHeight not zero but trying to open; scheduling an anim to open fully");
@@ -312,17 +281,18 @@
         }
 
         public void onAnimationCancel(Animator animation) {
-            if (DEBUG) Slog.d(TAG, "onAnimationCancel mBgAlpha=" + mBgAlpha);
+            if (DEBUG) Slog.d(TAG, "onAnimationCancel");
             // force this to zero so we close the window
-            mBgAlpha = 0;
+            mVisible = false;
         }
 
         public void onAnimationEnd(Animator animation) {
-            if (DEBUG) Slog.d(TAG, "onAnimationEnd mBgAlpha=" + mBgAlpha);
-            if (mBgAlpha == 0) {
+            if (DEBUG) Slog.d(TAG, "onAnimationEnd");
+            if (! mVisible) {
                 setVisibility(View.GONE);
             }
-            mBgAnim = null;
+            mContentParent.setLayerType(View.LAYER_TYPE_NONE, null);
+            mContentAnim = null;
         }
 
         public void onAnimationRepeat(Animator animation) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationTitleArea.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationTitleArea.java
deleted file mode 100644
index d4413db..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationTitleArea.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.tablet;
-
-import android.content.Context;
-import android.graphics.BitmapFactory;
-import android.graphics.Bitmap;
-import android.graphics.Paint;
-import android.graphics.Canvas;
-import android.util.AttributeSet;
-import android.util.Slog;
-import android.widget.ImageView;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-import android.view.View;
-import android.widget.FrameLayout;
-
-import com.android.systemui.R;
-
-public class NotificationTitleArea extends RelativeLayout {
-    static final String TAG = "NotificationTitleArea";
-
-    View mSettingsButton;
-    View mNotificationButton;
-    View mNotificationScroller;
-    FrameLayout mSettingsFrame;
-    View mSettingsPanel;
-
-    // for drawing the background
-    Bitmap mTexture;
-    Paint mPaint;
-    int mTextureWidth;
-    int mTextureHeight;
-    
-
-    public NotificationTitleArea(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public NotificationTitleArea(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-
-        // for drawing the background
-        mTexture = BitmapFactory.decodeResource(getResources(), R.drawable.panel_notification);
-        mTextureWidth = mTexture.getWidth();
-        mTextureHeight = mTexture.getHeight();
-
-        mPaint = new Paint();
-        mPaint.setDither(false);
-    }
-
-    public void onFinishInflate() {
-        super.onFinishInflate();
-        setWillNotDraw(false);
-    }
-
-    @Override
-    public void onDraw(Canvas canvas) {
-        final Bitmap texture = mTexture;
-        final Paint paint = mPaint;
-
-        final int width = getWidth();
-        final int height = getHeight();
-
-        final int textureWidth = mTextureWidth;
-        final int textureHeight = mTextureHeight;
-
-        int x = 0;
-        int y;
-
-        while (x < width) {
-            y = 0;
-            while (y < height) {
-                canvas.drawBitmap(texture, x, y, paint);
-                y += textureHeight;
-            }
-            x += textureWidth;
-        }
-    }
-}
-
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
index 612427b..53c30fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
@@ -252,7 +252,11 @@
 
     private void refreshApplicationList() {
         mActivityDescriptions = getRecentTasks();
-        updateUiElements(getResources().getConfiguration(), true);
+        if (mActivityDescriptions.size() > 0) {
+            updateUiElements(getResources().getConfiguration(), true);
+        } else {
+            mBar.animateCollapse();
+        }
     }
 
     private Bitmap compositeBitmap(Bitmap background, Bitmap thumbnail) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 9ddb432..cd39d71 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -183,7 +183,7 @@
         mStatusBarView.setIgnoreChildren(0, mNotificationTrigger, mNotificationPanel);
 
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT,
+                720, // ViewGroup.LayoutParams.MATCH_PARENT,
                 ViewGroup.LayoutParams.MATCH_PARENT,
                 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
@@ -196,6 +196,7 @@
         lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
                 | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
         lp.windowAnimations = com.android.internal.R.style.Animation; // == no animation
+//        lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons; // simple fade
 
         WindowManagerImpl.getDefault().addView(mNotificationPanel, lp);
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 2fcd04e..38eed50 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -26,9 +26,11 @@
 import com.android.internal.view.BaseSurfaceHolder;
 import com.android.internal.view.RootViewSurfaceTaker;
 import com.android.internal.view.StandaloneActionMode;
+import com.android.internal.view.menu.ActionMenuView;
 import com.android.internal.view.menu.ContextMenuBuilder;
 import com.android.internal.view.menu.MenuBuilder;
 import com.android.internal.view.menu.MenuDialogHelper;
+import com.android.internal.view.menu.MenuItemImpl;
 import com.android.internal.view.menu.MenuPopupHelper;
 import com.android.internal.view.menu.MenuView;
 import com.android.internal.view.menu.SubMenuBuilder;
@@ -881,12 +883,16 @@
             // The window manager will give us a valid window token
             new MenuDialogHelper(subMenu).show(null);
         } else if (hasFeature(FEATURE_ACTION_BAR)) {
-            mActionButtonPopup = new ActionButtonSubmenu(getContext(), subMenu);
-            mActionButtonPopup.show();
-            Callback cb = getCallback();
-            if (cb != null) {
-                cb.onMenuOpened(FEATURE_ACTION_BAR, subMenu);
-            }
+            mDecor.post(new Runnable() {
+                public void run() {
+                    mActionButtonPopup = new ActionButtonSubmenu(getContext(), subMenu);
+                    mActionButtonPopup.show();
+                    Callback cb = getCallback();
+                    if (cb != null) {
+                        cb.onMenuOpened(FEATURE_ACTION_BAR, subMenu);
+                    }
+                }
+            });
         }
 
         return true;
@@ -3009,6 +3015,20 @@
         public ActionButtonSubmenu(Context context, SubMenuBuilder subMenu) {
             super(context, subMenu);
             mSubMenu = subMenu;
+
+            MenuBuilder parentMenu = subMenu.getRootMenu();
+            MenuItemImpl item = (MenuItemImpl) subMenu.getItem();
+            if (!item.isActionButton()) {
+                // Give a reasonable anchor to nested submenus.
+                ActionMenuView amv = (ActionMenuView) parentMenu.getMenuView(
+                        MenuBuilder.TYPE_ACTION_BUTTON, null);
+
+                View anchor = amv.getOverflowButton();
+                if (anchor == null) {
+                    anchor = amv;
+                }
+                setAnchorView(anchor);
+            }
         }
 
         @Override
diff --git a/services/input/Android.mk b/services/input/Android.mk
index 37804ff..d7b61fc 100644
--- a/services/input/Android.mk
+++ b/services/input/Android.mk
@@ -21,6 +21,7 @@
     InputDispatcher.cpp \
     InputManager.cpp \
     InputReader.cpp \
+    InputWindow.cpp \
     PointerController.cpp
 
 LOCAL_SHARED_LIBRARIES := \
diff --git a/services/input/InputApplication.h b/services/input/InputApplication.h
new file mode 100644
index 0000000..cc80062
--- /dev/null
+++ b/services/input/InputApplication.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef _UI_INPUT_APPLICATION_H
+#define _UI_INPUT_APPLICATION_H
+
+#include <ui/Input.h>
+
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+#include <utils/String8.h>
+
+namespace android {
+
+/*
+ * A handle to an application that can receive input.
+ * Used by the native input dispatcher to indirectly refer to the window manager objects
+ * that describe an application.
+ */
+class InputApplicationHandle : public RefBase {
+protected:
+    InputApplicationHandle() { }
+    virtual ~InputApplicationHandle() { }
+};
+
+
+/*
+ * An input application describes properties of an application that can receive input.
+ */
+struct InputApplication {
+    sp<InputApplicationHandle> inputApplicationHandle;
+    String8 name;
+    nsecs_t dispatchingTimeout;
+};
+
+} // namespace android
+
+#endif // _UI_INPUT_APPLICATION_H
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 89a7751..b5a4bd2 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -72,6 +72,10 @@
 // when an application takes too long to respond and the user has pressed an app switch key.
 const nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec
 
+// Amount of time to allow for an event to be dispatched (measured since its eventTime)
+// before considering it stale and dropping it.
+const nsecs_t STALE_EVENT_TIMEOUT = 10000 * 1000000LL; // 10sec
+
 
 static inline nsecs_t now() {
     return systemTime(SYSTEM_TIME_MONOTONIC);
@@ -151,34 +155,12 @@
 }
 
 
-// --- InputWindow ---
-
-bool InputWindow::touchableAreaContainsPoint(int32_t x, int32_t y) const {
-    return x >= touchableAreaLeft && x <= touchableAreaRight
-            && y >= touchableAreaTop && y <= touchableAreaBottom;
-}
-
-bool InputWindow::frameContainsPoint(int32_t x, int32_t y) const {
-    return x >= frameLeft && x <= frameRight
-            && y >= frameTop && y <= frameBottom;
-}
-
-bool InputWindow::isTrustedOverlay() const {
-    return layoutParamsType == TYPE_INPUT_METHOD
-            || layoutParamsType == TYPE_INPUT_METHOD_DIALOG
-            || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY;
-}
-
-bool InputWindow::supportsSplitTouch() const {
-    return layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH;
-}
-
-
 // --- InputDispatcher ---
 
 InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
     mPolicy(policy),
-    mPendingEvent(NULL), mAppSwitchDueTime(LONG_LONG_MAX),
+    mPendingEvent(NULL), mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
+    mNextUnblockedEvent(NULL),
     mDispatchEnabled(true), mDispatchFrozen(false),
     mFocusedWindow(NULL),
     mFocusedApplication(NULL),
@@ -368,6 +350,7 @@
     }
 
     // Now we have an event to dispatch.
+    // All events are eventually dequeued and processed this way, even if we intend to drop them.
     assert(mPendingEvent != NULL);
     bool done = false;
     DropReason dropReason = DROP_REASON_NOT_DROPPED;
@@ -376,6 +359,11 @@
     } else if (!mDispatchEnabled) {
         dropReason = DROP_REASON_DISABLED;
     }
+
+    if (mNextUnblockedEvent == mPendingEvent) {
+        mNextUnblockedEvent = NULL;
+    }
+
     switch (mPendingEvent->type) {
     case EventEntry::TYPE_CONFIGURATION_CHANGED: {
         ConfigurationChangedEntry* typedEntry =
@@ -395,6 +383,13 @@
                 dropReason = DROP_REASON_APP_SWITCH;
             }
         }
+        if (dropReason == DROP_REASON_NOT_DROPPED
+                && isStaleEventLocked(currentTime, typedEntry)) {
+            dropReason = DROP_REASON_STALE;
+        }
+        if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
+            dropReason = DROP_REASON_BLOCKED;
+        }
         done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout,
                 &dropReason, nextWakeupTime);
         break;
@@ -405,6 +400,13 @@
         if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
             dropReason = DROP_REASON_APP_SWITCH;
         }
+        if (dropReason == DROP_REASON_NOT_DROPPED
+                && isStaleEventLocked(currentTime, typedEntry)) {
+            dropReason = DROP_REASON_STALE;
+        }
+        if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
+            dropReason = DROP_REASON_BLOCKED;
+        }
         done = dispatchMotionLocked(currentTime, typedEntry,
                 &dropReason, nextWakeupTime);
         break;
@@ -431,6 +433,9 @@
 
     switch (entry->type) {
     case EventEntry::TYPE_KEY: {
+        // Optimize app switch latency.
+        // If the application takes too long to catch up then we drop all events preceding
+        // the app switch key.
         KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
         if (isAppSwitchKeyEventLocked(keyEntry)) {
             if (keyEntry->action == AKEY_EVENT_ACTION_DOWN) {
@@ -448,11 +453,63 @@
         }
         break;
     }
+
+    case EventEntry::TYPE_MOTION: {
+        // Optimize case where the current application is unresponsive and the user
+        // decides to touch a window in a different application.
+        // If the application takes too long to catch up then we drop all events preceding
+        // the touch into the other window.
+        MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
+        if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN
+                && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
+                && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY
+                && mInputTargetWaitApplication != NULL) {
+            int32_t x = int32_t(motionEntry->firstSample.pointerCoords[0].x);
+            int32_t y = int32_t(motionEntry->firstSample.pointerCoords[0].y);
+            const InputWindow* touchedWindow = findTouchedWindowAtLocked(x, y);
+            if (touchedWindow
+                    && touchedWindow->inputWindowHandle != NULL
+                    && touchedWindow->inputWindowHandle->getInputApplicationHandle()
+                            != mInputTargetWaitApplication) {
+                // User touched a different application than the one we are waiting on.
+                // Flag the event, and start pruning the input queue.
+                mNextUnblockedEvent = motionEntry;
+                needWake = true;
+            }
+        }
+        break;
+    }
     }
 
     return needWake;
 }
 
+const InputWindow* InputDispatcher::findTouchedWindowAtLocked(int32_t x, int32_t y) {
+    // Traverse windows from front to back to find touched window.
+    size_t numWindows = mWindows.size();
+    for (size_t i = 0; i < numWindows; i++) {
+        const InputWindow* window = & mWindows.editItemAt(i);
+        int32_t flags = window->layoutParamsFlags;
+
+        if (window->visible) {
+            if (!(flags & InputWindow::FLAG_NOT_TOUCHABLE)) {
+                bool isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE
+                        | InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0;
+                if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
+                    // Found window.
+                    return window;
+                }
+            }
+        }
+
+        if (flags & InputWindow::FLAG_SYSTEM_ERROR) {
+            // Error window is on top but not visible, so touch is dropped.
+            return NULL;
+        }
+    }
+    return NULL;
+}
+
 void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropReason) {
     const char* reason;
     switch (dropReason) {
@@ -470,6 +527,16 @@
         LOGI("Dropped event because of pending overdue app switch.");
         reason = "inbound event was dropped because of pending overdue app switch";
         break;
+    case DROP_REASON_BLOCKED:
+        LOGI("Dropped event because the current application is not responding and the user "
+                "has started interating with a different application.");
+        reason = "inbound event was dropped because the current application is not responding "
+                "and the user has started interating with a different application";
+        break;
+    case DROP_REASON_STALE:
+        LOGI("Dropped event because it is stale.");
+        reason = "inbound event was dropped because it is stale";
+        break;
     default:
         assert(false);
         return;
@@ -521,6 +588,10 @@
 #endif
 }
 
+bool InputDispatcher::isStaleEventLocked(nsecs_t currentTime, EventEntry* entry) {
+    return currentTime - entry->eventTime >= STALE_EVENT_TIMEOUT;
+}
+
 bool InputDispatcher::runCommandsLockedInterruptible() {
     if (mCommandQueue.isEmpty()) {
         return false;
@@ -670,7 +741,7 @@
             CommandEntry* commandEntry = postCommandLocked(
                     & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
             if (mFocusedWindow) {
-                commandEntry->inputChannel = mFocusedWindow->inputChannel;
+                commandEntry->inputWindowHandle = mFocusedWindow->inputWindowHandle;
             }
             commandEntry->keyEntry = entry;
             entry->refCount += 1;
@@ -848,6 +919,7 @@
     mCurrentInputTargetsValid = false;
     mCurrentInputTargets.clear();
     mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
+    mInputTargetWaitApplication.clear();
 }
 
 void InputDispatcher::commitTargetsLocked() {
@@ -866,6 +938,7 @@
             mInputTargetWaitStartTime = currentTime;
             mInputTargetWaitTimeoutTime = LONG_LONG_MAX;
             mInputTargetWaitTimeoutExpired = false;
+            mInputTargetWaitApplication.clear();
         }
     } else {
         if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
@@ -880,6 +953,15 @@
             mInputTargetWaitStartTime = currentTime;
             mInputTargetWaitTimeoutTime = currentTime + timeout;
             mInputTargetWaitTimeoutExpired = false;
+            mInputTargetWaitApplication.clear();
+
+            if (window && window->inputWindowHandle != NULL) {
+                mInputTargetWaitApplication =
+                        window->inputWindowHandle->getInputApplicationHandle();
+            }
+            if (mInputTargetWaitApplication == NULL && application) {
+                mInputTargetWaitApplication = application->inputApplicationHandle;
+            }
         }
     }
 
@@ -2624,7 +2706,7 @@
 void InputDispatcher::releaseFocusedApplicationLocked() {
     if (mFocusedApplication) {
         mFocusedApplication = NULL;
-        mFocusedApplicationStorage.handle.clear();
+        mFocusedApplicationStorage.inputApplicationHandle.clear();
     }
 }
 
@@ -2860,7 +2942,8 @@
     }
 }
 
-status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) {
+status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
+        const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
 #if DEBUG_REGISTRATION
     LOGD("channel '%s' ~ registerInputChannel - monitor=%s", inputChannel->getName().string(),
             toString(monitor));
@@ -2875,7 +2958,7 @@
             return BAD_VALUE;
         }
 
-        sp<Connection> connection = new Connection(inputChannel);
+        sp<Connection> connection = new Connection(inputChannel, inputWindowHandle);
         status_t status = connection->initialize();
         if (status) {
             LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
@@ -3002,9 +3085,10 @@
     CommandEntry* commandEntry = postCommandLocked(
             & InputDispatcher::doNotifyANRLockedInterruptible);
     if (application) {
-        commandEntry->inputApplicationHandle = application->handle;
+        commandEntry->inputApplicationHandle = application->inputApplicationHandle;
     }
     if (window) {
+        commandEntry->inputWindowHandle = window->inputWindowHandle;
         commandEntry->inputChannel = window->inputChannel;
     }
 }
@@ -3025,7 +3109,7 @@
     if (connection->status != Connection::STATUS_ZOMBIE) {
         mLock.unlock();
 
-        mPolicy->notifyInputChannelBroken(connection->inputChannel);
+        mPolicy->notifyInputChannelBroken(connection->inputWindowHandle);
 
         mLock.lock();
     }
@@ -3036,7 +3120,7 @@
     mLock.unlock();
 
     nsecs_t newTimeout = mPolicy->notifyANR(
-            commandEntry->inputApplicationHandle, commandEntry->inputChannel);
+            commandEntry->inputApplicationHandle, commandEntry->inputWindowHandle);
 
     mLock.lock();
 
@@ -3052,7 +3136,7 @@
 
     mLock.unlock();
 
-    bool consumed = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputChannel,
+    bool consumed = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
             &event, entry->policyFlags);
 
     mLock.lock();
@@ -3095,7 +3179,7 @@
 
                     mLock.unlock();
 
-                    bool fallback = mPolicy->dispatchUnhandledKey(connection->inputChannel,
+                    bool fallback = mPolicy->dispatchUnhandledKey(connection->inputWindowHandle,
                             &event, keyEntry->policyFlags, &event);
 
                     mLock.lock();
@@ -3604,8 +3688,10 @@
 
 // --- InputDispatcher::Connection ---
 
-InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel) :
-        status(STATUS_NORMAL), inputChannel(inputChannel), inputPublisher(inputChannel),
+InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel,
+        const sp<InputWindowHandle>& inputWindowHandle) :
+        status(STATUS_NORMAL), inputChannel(inputChannel), inputWindowHandle(inputWindowHandle),
+        inputPublisher(inputChannel),
         lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX) {
 }
 
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index c8beab2..11e5117 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -33,6 +33,9 @@
 #include <unistd.h>
 #include <limits.h>
 
+#include "InputWindow.h"
+#include "InputApplication.h"
+
 
 namespace android {
 
@@ -116,137 +119,6 @@
 
 
 /*
- * An input window describes the bounds of a window that can receive input.
- */
-struct InputWindow {
-    // Window flags from WindowManager.LayoutParams
-    enum {
-        FLAG_ALLOW_LOCK_WHILE_SCREEN_ON     = 0x00000001,
-        FLAG_DIM_BEHIND        = 0x00000002,
-        FLAG_BLUR_BEHIND        = 0x00000004,
-        FLAG_NOT_FOCUSABLE      = 0x00000008,
-        FLAG_NOT_TOUCHABLE      = 0x00000010,
-        FLAG_NOT_TOUCH_MODAL    = 0x00000020,
-        FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
-        FLAG_KEEP_SCREEN_ON     = 0x00000080,
-        FLAG_LAYOUT_IN_SCREEN   = 0x00000100,
-        FLAG_LAYOUT_NO_LIMITS   = 0x00000200,
-        FLAG_FULLSCREEN      = 0x00000400,
-        FLAG_FORCE_NOT_FULLSCREEN   = 0x00000800,
-        FLAG_DITHER             = 0x00001000,
-        FLAG_SECURE             = 0x00002000,
-        FLAG_SCALED             = 0x00004000,
-        FLAG_IGNORE_CHEEK_PRESSES    = 0x00008000,
-        FLAG_LAYOUT_INSET_DECOR = 0x00010000,
-        FLAG_ALT_FOCUSABLE_IM = 0x00020000,
-        FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
-        FLAG_SHOW_WHEN_LOCKED = 0x00080000,
-        FLAG_SHOW_WALLPAPER = 0x00100000,
-        FLAG_TURN_SCREEN_ON = 0x00200000,
-        FLAG_DISMISS_KEYGUARD = 0x00400000,
-        FLAG_SPLIT_TOUCH = 0x00800000,
-        FLAG_KEEP_SURFACE_WHILE_ANIMATING = 0x10000000,
-        FLAG_COMPATIBLE_WINDOW = 0x20000000,
-        FLAG_SYSTEM_ERROR = 0x40000000,
-    };
-
-    // Window types from WindowManager.LayoutParams
-    enum {
-        FIRST_APPLICATION_WINDOW = 1,
-        TYPE_BASE_APPLICATION   = 1,
-        TYPE_APPLICATION        = 2,
-        TYPE_APPLICATION_STARTING = 3,
-        LAST_APPLICATION_WINDOW = 99,
-        FIRST_SUB_WINDOW        = 1000,
-        TYPE_APPLICATION_PANEL  = FIRST_SUB_WINDOW,
-        TYPE_APPLICATION_MEDIA  = FIRST_SUB_WINDOW+1,
-        TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2,
-        TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3,
-        TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW+4,
-        LAST_SUB_WINDOW         = 1999,
-        FIRST_SYSTEM_WINDOW     = 2000,
-        TYPE_STATUS_BAR         = FIRST_SYSTEM_WINDOW,
-        TYPE_SEARCH_BAR         = FIRST_SYSTEM_WINDOW+1,
-        TYPE_PHONE              = FIRST_SYSTEM_WINDOW+2,
-        TYPE_SYSTEM_ALERT       = FIRST_SYSTEM_WINDOW+3,
-        TYPE_KEYGUARD           = FIRST_SYSTEM_WINDOW+4,
-        TYPE_TOAST              = FIRST_SYSTEM_WINDOW+5,
-        TYPE_SYSTEM_OVERLAY     = FIRST_SYSTEM_WINDOW+6,
-        TYPE_PRIORITY_PHONE     = FIRST_SYSTEM_WINDOW+7,
-        TYPE_SYSTEM_DIALOG      = FIRST_SYSTEM_WINDOW+8,
-        TYPE_KEYGUARD_DIALOG    = FIRST_SYSTEM_WINDOW+9,
-        TYPE_SYSTEM_ERROR       = FIRST_SYSTEM_WINDOW+10,
-        TYPE_INPUT_METHOD       = FIRST_SYSTEM_WINDOW+11,
-        TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12,
-        TYPE_WALLPAPER          = FIRST_SYSTEM_WINDOW+13,
-        TYPE_STATUS_BAR_SUB_PANEL  = FIRST_SYSTEM_WINDOW+14,
-        TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15,
-        TYPE_DRAG               = FIRST_SYSTEM_WINDOW+16,
-        TYPE_STATUS_BAR_PANEL   = FIRST_SYSTEM_WINDOW+17,
-        LAST_SYSTEM_WINDOW      = 2999,
-    };
-
-    sp<InputChannel> inputChannel;
-    String8 name;
-    int32_t layoutParamsFlags;
-    int32_t layoutParamsType;
-    nsecs_t dispatchingTimeout;
-    int32_t frameLeft;
-    int32_t frameTop;
-    int32_t frameRight;
-    int32_t frameBottom;
-    int32_t visibleFrameLeft;
-    int32_t visibleFrameTop;
-    int32_t visibleFrameRight;
-    int32_t visibleFrameBottom;
-    int32_t touchableAreaLeft;
-    int32_t touchableAreaTop;
-    int32_t touchableAreaRight;
-    int32_t touchableAreaBottom;
-    bool visible;
-    bool canReceiveKeys;
-    bool hasFocus;
-    bool hasWallpaper;
-    bool paused;
-    int32_t layer;
-    int32_t ownerPid;
-    int32_t ownerUid;
-
-    bool touchableAreaContainsPoint(int32_t x, int32_t y) const;
-    bool frameContainsPoint(int32_t x, int32_t y) const;
-
-    /* Returns true if the window is of a trusted type that is allowed to silently
-     * overlay other windows for the purpose of implementing the secure views feature.
-     * Trusted overlays, such as IME windows, can partly obscure other windows without causing
-     * motion events to be delivered to them with AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED.
-     */
-    bool isTrustedOverlay() const;
-
-    bool supportsSplitTouch() const;
-};
-
-
-/*
- * A private handle type used by the input manager to track the window.
- */
-class InputApplicationHandle : public RefBase {
-protected:
-    InputApplicationHandle() { }
-    virtual ~InputApplicationHandle() { }
-};
-
-
-/*
- * An input application describes properties of an application that can receive input.
- */
-struct InputApplication {
-    String8 name;
-    nsecs_t dispatchingTimeout;
-    sp<InputApplicationHandle> handle;
-};
-
-
-/*
  * Input dispatcher policy interface.
  *
  * The input reader policy is used by the input reader to interact with the Window Manager
@@ -267,10 +139,10 @@
     /* Notifies the system that an application is not responding.
      * Returns a new timeout to continue waiting, or 0 to abort dispatch. */
     virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
-            const sp<InputChannel>& inputChannel) = 0;
+            const sp<InputWindowHandle>& inputWindowHandle) = 0;
 
     /* Notifies the system that an input channel is unrecoverably broken. */
-    virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel) = 0;
+    virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) = 0;
 
     /* Gets the key repeat initial timeout or -1 if automatic key repeating is disabled. */
     virtual nsecs_t getKeyRepeatTimeout() = 0;
@@ -303,12 +175,12 @@
     virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) = 0;
 
     /* Allows the policy a chance to intercept a key before dispatching. */
-    virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
+    virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
             const KeyEvent* keyEvent, uint32_t policyFlags) = 0;
 
     /* Allows the policy a chance to perform default processing for an unhandled key.
      * Returns an alternate keycode to redispatch as a fallback, or 0 to give up. */
-    virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
+    virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
             const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) = 0;
 
     /* Notifies the policy about switch events.
@@ -407,7 +279,8 @@
      *
      * These methods may be called on any thread (usually by the input manager).
      */
-    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) = 0;
+    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
+            const sp<InputWindowHandle>& inputWindowHandle, bool monitor) = 0;
     virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;
 };
 
@@ -461,7 +334,8 @@
     virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
             const sp<InputChannel>& toChannel);
 
-    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor);
+    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
+            const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
     virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
 
 private:
@@ -615,6 +489,7 @@
         KeyEntry* keyEntry;
         sp<InputChannel> inputChannel;
         sp<InputApplicationHandle> inputApplicationHandle;
+        sp<InputWindowHandle> inputWindowHandle;
         int32_t userActivityEventType;
         bool handled;
     };
@@ -815,7 +690,8 @@
         };
 
         Status status;
-        sp<InputChannel> inputChannel;
+        sp<InputChannel> inputChannel; // never null
+        sp<InputWindowHandle> inputWindowHandle; // may be null
         InputPublisher inputPublisher;
         InputState inputState;
         Queue<DispatchEntry> outboundQueue;
@@ -823,7 +699,8 @@
         nsecs_t lastEventTime; // the time when the event was originally captured
         nsecs_t lastDispatchTime; // the time when the last event was dispatched
 
-        explicit Connection(const sp<InputChannel>& inputChannel);
+        explicit Connection(const sp<InputChannel>& inputChannel,
+                const sp<InputWindowHandle>& inputWindowHandle);
 
         inline const char* getInputChannelName() const { return inputChannel->getName().string(); }
 
@@ -851,6 +728,8 @@
         DROP_REASON_POLICY = 1,
         DROP_REASON_APP_SWITCH = 2,
         DROP_REASON_DISABLED = 3,
+        DROP_REASON_BLOCKED = 4,
+        DROP_REASON_STALE = 5,
     };
 
     sp<InputDispatcherPolicyInterface> mPolicy;
@@ -884,6 +763,15 @@
     bool isAppSwitchPendingLocked();
     void resetPendingAppSwitchLocked(bool handled);
 
+    // Stale event latency optimization.
+    static bool isStaleEventLocked(nsecs_t currentTime, EventEntry* entry);
+
+    // Blocked event latency optimization.  Drops old events when the user intends
+    // to transfer focus to a new application.
+    EventEntry* mNextUnblockedEvent;
+
+    const InputWindow* findTouchedWindowAtLocked(int32_t x, int32_t y);
+
     // All registered connections mapped by receive pipe file descriptor.
     KeyedVector<int, sp<Connection> > mConnectionsByReceiveFd;
 
@@ -1006,6 +894,7 @@
     nsecs_t mInputTargetWaitStartTime;
     nsecs_t mInputTargetWaitTimeoutTime;
     bool mInputTargetWaitTimeoutExpired;
+    sp<InputApplicationHandle> mInputTargetWaitApplication;
 
     // Finding targets for input events.
     void resetTargetsLocked();
diff --git a/services/input/InputWindow.cpp b/services/input/InputWindow.cpp
new file mode 100644
index 0000000..9ce45f5
--- /dev/null
+++ b/services/input/InputWindow.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#define LOG_TAG "InputWindow"
+
+#include "InputWindow.h"
+
+#include <cutils/log.h>
+
+namespace android {
+
+// --- InputWindow ---
+
+bool InputWindow::touchableAreaContainsPoint(int32_t x, int32_t y) const {
+    return x >= touchableAreaLeft && x <= touchableAreaRight
+            && y >= touchableAreaTop && y <= touchableAreaBottom;
+}
+
+bool InputWindow::frameContainsPoint(int32_t x, int32_t y) const {
+    return x >= frameLeft && x <= frameRight
+            && y >= frameTop && y <= frameBottom;
+}
+
+bool InputWindow::isTrustedOverlay() const {
+    return layoutParamsType == TYPE_INPUT_METHOD
+            || layoutParamsType == TYPE_INPUT_METHOD_DIALOG
+            || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY;
+}
+
+bool InputWindow::supportsSplitTouch() const {
+    return layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH;
+}
+
+} // namespace android
diff --git a/services/input/InputWindow.h b/services/input/InputWindow.h
new file mode 100644
index 0000000..b3d5a65
--- /dev/null
+++ b/services/input/InputWindow.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef _UI_INPUT_WINDOW_H
+#define _UI_INPUT_WINDOW_H
+
+#include <ui/Input.h>
+#include <ui/InputTransport.h>
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+#include <utils/String8.h>
+
+#include "InputApplication.h"
+
+namespace android {
+
+/*
+ * A handle to a window that can receive input.
+ * Used by the native input dispatcher to indirectly refer to the window manager objects
+ * that describe a window.
+ */
+class InputWindowHandle : public RefBase {
+protected:
+    InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle) :
+            mInputApplicationHandle(inputApplicationHandle) { }
+    virtual ~InputWindowHandle() { }
+
+public:
+    inline sp<InputApplicationHandle> getInputApplicationHandle() {
+        return mInputApplicationHandle;
+    }
+
+private:
+    sp<InputApplicationHandle> mInputApplicationHandle;
+};
+
+
+/*
+ * An input window describes the bounds of a window that can receive input.
+ */
+struct InputWindow {
+    // Window flags from WindowManager.LayoutParams
+    enum {
+        FLAG_ALLOW_LOCK_WHILE_SCREEN_ON     = 0x00000001,
+        FLAG_DIM_BEHIND        = 0x00000002,
+        FLAG_BLUR_BEHIND        = 0x00000004,
+        FLAG_NOT_FOCUSABLE      = 0x00000008,
+        FLAG_NOT_TOUCHABLE      = 0x00000010,
+        FLAG_NOT_TOUCH_MODAL    = 0x00000020,
+        FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
+        FLAG_KEEP_SCREEN_ON     = 0x00000080,
+        FLAG_LAYOUT_IN_SCREEN   = 0x00000100,
+        FLAG_LAYOUT_NO_LIMITS   = 0x00000200,
+        FLAG_FULLSCREEN      = 0x00000400,
+        FLAG_FORCE_NOT_FULLSCREEN   = 0x00000800,
+        FLAG_DITHER             = 0x00001000,
+        FLAG_SECURE             = 0x00002000,
+        FLAG_SCALED             = 0x00004000,
+        FLAG_IGNORE_CHEEK_PRESSES    = 0x00008000,
+        FLAG_LAYOUT_INSET_DECOR = 0x00010000,
+        FLAG_ALT_FOCUSABLE_IM = 0x00020000,
+        FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
+        FLAG_SHOW_WHEN_LOCKED = 0x00080000,
+        FLAG_SHOW_WALLPAPER = 0x00100000,
+        FLAG_TURN_SCREEN_ON = 0x00200000,
+        FLAG_DISMISS_KEYGUARD = 0x00400000,
+        FLAG_SPLIT_TOUCH = 0x00800000,
+        FLAG_KEEP_SURFACE_WHILE_ANIMATING = 0x10000000,
+        FLAG_COMPATIBLE_WINDOW = 0x20000000,
+        FLAG_SYSTEM_ERROR = 0x40000000,
+    };
+
+    // Window types from WindowManager.LayoutParams
+    enum {
+        FIRST_APPLICATION_WINDOW = 1,
+        TYPE_BASE_APPLICATION   = 1,
+        TYPE_APPLICATION        = 2,
+        TYPE_APPLICATION_STARTING = 3,
+        LAST_APPLICATION_WINDOW = 99,
+        FIRST_SUB_WINDOW        = 1000,
+        TYPE_APPLICATION_PANEL  = FIRST_SUB_WINDOW,
+        TYPE_APPLICATION_MEDIA  = FIRST_SUB_WINDOW+1,
+        TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2,
+        TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3,
+        TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW+4,
+        LAST_SUB_WINDOW         = 1999,
+        FIRST_SYSTEM_WINDOW     = 2000,
+        TYPE_STATUS_BAR         = FIRST_SYSTEM_WINDOW,
+        TYPE_SEARCH_BAR         = FIRST_SYSTEM_WINDOW+1,
+        TYPE_PHONE              = FIRST_SYSTEM_WINDOW+2,
+        TYPE_SYSTEM_ALERT       = FIRST_SYSTEM_WINDOW+3,
+        TYPE_KEYGUARD           = FIRST_SYSTEM_WINDOW+4,
+        TYPE_TOAST              = FIRST_SYSTEM_WINDOW+5,
+        TYPE_SYSTEM_OVERLAY     = FIRST_SYSTEM_WINDOW+6,
+        TYPE_PRIORITY_PHONE     = FIRST_SYSTEM_WINDOW+7,
+        TYPE_SYSTEM_DIALOG      = FIRST_SYSTEM_WINDOW+8,
+        TYPE_KEYGUARD_DIALOG    = FIRST_SYSTEM_WINDOW+9,
+        TYPE_SYSTEM_ERROR       = FIRST_SYSTEM_WINDOW+10,
+        TYPE_INPUT_METHOD       = FIRST_SYSTEM_WINDOW+11,
+        TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12,
+        TYPE_WALLPAPER          = FIRST_SYSTEM_WINDOW+13,
+        TYPE_STATUS_BAR_SUB_PANEL  = FIRST_SYSTEM_WINDOW+14,
+        TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15,
+        TYPE_DRAG               = FIRST_SYSTEM_WINDOW+16,
+        TYPE_STATUS_BAR_PANEL   = FIRST_SYSTEM_WINDOW+17,
+        LAST_SYSTEM_WINDOW      = 2999,
+    };
+
+    sp<InputWindowHandle> inputWindowHandle;
+    sp<InputChannel> inputChannel;
+    String8 name;
+    int32_t layoutParamsFlags;
+    int32_t layoutParamsType;
+    nsecs_t dispatchingTimeout;
+    int32_t frameLeft;
+    int32_t frameTop;
+    int32_t frameRight;
+    int32_t frameBottom;
+    int32_t visibleFrameLeft;
+    int32_t visibleFrameTop;
+    int32_t visibleFrameRight;
+    int32_t visibleFrameBottom;
+    int32_t touchableAreaLeft;
+    int32_t touchableAreaTop;
+    int32_t touchableAreaRight;
+    int32_t touchableAreaBottom;
+    bool visible;
+    bool canReceiveKeys;
+    bool hasFocus;
+    bool hasWallpaper;
+    bool paused;
+    int32_t layer;
+    int32_t ownerPid;
+    int32_t ownerUid;
+
+    bool touchableAreaContainsPoint(int32_t x, int32_t y) const;
+    bool frameContainsPoint(int32_t x, int32_t y) const;
+
+    /* Returns true if the window is of a trusted type that is allowed to silently
+     * overlay other windows for the purpose of implementing the secure views feature.
+     * Trusted overlays, such as IME windows, can partly obscure other windows without causing
+     * motion events to be delivered to them with AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED.
+     */
+    bool isTrustedOverlay() const;
+
+    bool supportsSplitTouch() const;
+};
+
+} // namespace android
+
+#endif // _UI_INPUT_WINDOW_H
diff --git a/services/input/tests/InputDispatcher_test.cpp b/services/input/tests/InputDispatcher_test.cpp
index b79633a..5ba1867 100644
--- a/services/input/tests/InputDispatcher_test.cpp
+++ b/services/input/tests/InputDispatcher_test.cpp
@@ -36,11 +36,11 @@
     }
 
     virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
-            const sp<InputChannel>& inputChannel) {
+            const sp<InputWindowHandle>& inputWindowHandle) {
         return 0;
     }
 
-    virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
+    virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) {
     }
 
     virtual nsecs_t getKeyRepeatTimeout() {
@@ -61,12 +61,12 @@
     virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
     }
 
-    virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
+    virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
             const KeyEvent* keyEvent, uint32_t policyFlags) {
         return false;
     }
 
-    virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
+    virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
             const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
         return false;
     }
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 9d2c52f..8ec6f53 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -368,7 +368,8 @@
         return 0;
     }
 
-    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) {
+    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
+            const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
         ADD_FAILURE() << "Should never be called by input reader.";
         return 0;
     }
diff --git a/services/java/com/android/server/AccessibilityManagerService.java b/services/java/com/android/server/AccessibilityManagerService.java
index 393beda..63be030 100644
--- a/services/java/com/android/server/AccessibilityManagerService.java
+++ b/services/java/com/android/server/AccessibilityManagerService.java
@@ -532,7 +532,10 @@
 
         for (int i = 0, count = services.size(); i < count; i++) {
             Service service = services.get(i);
-            service.unbind();
+            if (service.unbind()) {
+                i--;
+                count--;
+            }
         }
     }
 
@@ -575,7 +578,6 @@
             Set<ComponentName> enabledServices) {
 
         Map<ComponentName, Service> componentNameToServiceMap = mComponentNameToServiceMap;
-        List<Service> services = mServices;
         boolean isEnabled = mIsEnabled;
 
         for (int i = 0, count = installedServices.size(); i < count; i++) {
@@ -665,23 +667,30 @@
 
         /**
          * Binds to the accessibility service.
+         *
+         * @return True if binding is successful.
          */
-        public void bind() {
+        public boolean bind() {
             if (mService == null) {
-                mContext.bindService(mIntent, this, Context.BIND_AUTO_CREATE);
+                return mContext.bindService(mIntent, this, Context.BIND_AUTO_CREATE);
             }
+            return false;
         }
 
         /**
          * Unbinds form the accessibility service and removes it from the data
          * structures for service management.
+         *
+         * @return True if unbinding is successful.
          */
-        public void unbind() {
+        public boolean unbind() {
             if (mService != null) {
                 mContext.unbindService(this);
                 mComponentNameToServiceMap.remove(mComponentName);
                 mServices.remove(this);
+                return true;
             }
+            return false;
         }
 
         /**
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index ae408fc..22dd804 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -144,6 +144,7 @@
         // update the provider list.
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_PACKAGE_ADDED);
+        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
         filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
         filter.addDataScheme("package");
         mContext.registerReceiver(mBroadcastReceiver, filter);
@@ -643,6 +644,12 @@
     }
 
     boolean addProviderLocked(ResolveInfo ri) {
+        if ((ri.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
+            return false;
+        }
+        if (!ri.activityInfo.isEnabled()) {
+            return false;
+        }
         Provider p = parseProviderInfoXml(new ComponentName(ri.activityInfo.packageName,
                     ri.activityInfo.name), ri);
         if (p != null) {
@@ -1160,6 +1167,7 @@
                 }
             } else {
                 boolean added = false;
+                boolean changed = false;
                 String pkgList[] = null;
                 if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
                     pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
@@ -1178,14 +1186,16 @@
                     }
                     pkgList = new String[] { pkgName };
                     added = Intent.ACTION_PACKAGE_ADDED.equals(action);
+                    changed = Intent.ACTION_PACKAGE_CHANGED.equals(action);
                 }
                 if (pkgList == null || pkgList.length == 0) {
                     return;
                 }
-                if (added) {
+                if (added || changed) {
                     synchronized (mAppWidgetIds) {
                         Bundle extras = intent.getExtras();
-                        if (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false)) {
+                        if (changed || (extras != null &&
+                                    extras.getBoolean(Intent.EXTRA_REPLACING, false))) {
                             for (String pkgName : pkgList) {
                                 // The package was just upgraded
                                 updateProvidersForPackageLocked(pkgName);
diff --git a/services/java/com/android/server/InputApplication.java b/services/java/com/android/server/InputApplication.java
index 38420d4..ae09484 100644
--- a/services/java/com/android/server/InputApplication.java
+++ b/services/java/com/android/server/InputApplication.java
@@ -18,16 +18,19 @@
 
 /**
  * Describes input-related application properties for use by the input dispatcher.
- * 
  * @hide
  */
 public final class InputApplication {
+    // Application handle.
+    public InputApplicationHandle inputApplicationHandle;
+
     // Application name.
     public String name;
-    
+
     // Dispatching timeout.
     public long dispatchingTimeoutNanos;
-    
-    // The application window token.
-    public Object token;
+
+    public void recycle() {
+        inputApplicationHandle = null;
+    }
 }
diff --git a/services/java/com/android/server/InputApplicationHandle.java b/services/java/com/android/server/InputApplicationHandle.java
new file mode 100644
index 0000000..d396d11
--- /dev/null
+++ b/services/java/com/android/server/InputApplicationHandle.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+/**
+ * Functions as a handle for an application that can receive input.
+ * Enables the native input dispatcher to refer indirectly to the window manager's
+ * application window token.
+ * @hide
+ */
+public final class InputApplicationHandle {
+    // Pointer to the native input application handle.
+    // This field is lazily initialized via JNI.
+    @SuppressWarnings("unused")
+    private int ptr;
+
+    // The window manager's application window token.
+    public final WindowManagerService.AppWindowToken appWindowToken;
+
+    private native void nativeDispose();
+
+    public InputApplicationHandle(WindowManagerService.AppWindowToken appWindowToken) {
+        this.appWindowToken = appWindowToken;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        nativeDispose();
+        super.finalize();
+    }
+}
diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java
index 410b8c2..5c2048b 100644
--- a/services/java/com/android/server/InputManager.java
+++ b/services/java/com/android/server/InputManager.java
@@ -77,7 +77,7 @@
     private static native boolean nativeHasKeys(int deviceId, int sourceMask,
             int[] keyCodes, boolean[] keyExists);
     private static native void nativeRegisterInputChannel(InputChannel inputChannel,
-            boolean monitor);
+            InputWindowHandle inputWindowHandle, boolean monitor);
     private static native void nativeUnregisterInputChannel(InputChannel inputChannel);
     private static native int nativeInjectInputEvent(InputEvent event,
             int injectorPid, int injectorUid, int syncMode, int timeoutMillis);
@@ -240,7 +240,7 @@
         }
         
         InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
-        nativeRegisterInputChannel(inputChannels[0], true);
+        nativeRegisterInputChannel(inputChannels[0], null, true);
         inputChannels[0].dispose(); // don't need to retain the Java object reference
         return inputChannels[1];
     }
@@ -248,13 +248,16 @@
     /**
      * Registers an input channel so that it can be used as an input event target.
      * @param inputChannel The input channel to register.
+     * @param inputWindowHandle The handle of the input window associated with the
+     * input channel, or null if none.
      */
-    public void registerInputChannel(InputChannel inputChannel) {
+    public void registerInputChannel(InputChannel inputChannel,
+            InputWindowHandle inputWindowHandle) {
         if (inputChannel == null) {
             throw new IllegalArgumentException("inputChannel must not be null.");
         }
         
-        nativeRegisterInputChannel(inputChannel, false);
+        nativeRegisterInputChannel(inputChannel, inputWindowHandle, false);
     }
     
     /**
@@ -429,13 +432,15 @@
         }
         
         @SuppressWarnings("unused")
-        public void notifyInputChannelBroken(InputChannel inputChannel) {
-            mWindowManagerService.mInputMonitor.notifyInputChannelBroken(inputChannel);
+        public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
+            mWindowManagerService.mInputMonitor.notifyInputChannelBroken(inputWindowHandle);
         }
         
         @SuppressWarnings("unused")
-        public long notifyANR(Object token, InputChannel inputChannel) {
-            return mWindowManagerService.mInputMonitor.notifyANR(token, inputChannel);
+        public long notifyANR(InputApplicationHandle inputApplicationHandle,
+                InputWindowHandle inputWindowHandle) {
+            return mWindowManagerService.mInputMonitor.notifyANR(
+                    inputApplicationHandle, inputWindowHandle);
         }
         
         @SuppressWarnings("unused")
@@ -445,14 +450,14 @@
         }
         
         @SuppressWarnings("unused")
-        public boolean interceptKeyBeforeDispatching(InputChannel focus,
+        public boolean interceptKeyBeforeDispatching(InputWindowHandle focus,
                 KeyEvent event, int policyFlags) {
             return mWindowManagerService.mInputMonitor.interceptKeyBeforeDispatching(
                     focus, event, policyFlags);
         }
         
         @SuppressWarnings("unused")
-        public KeyEvent dispatchUnhandledKey(InputChannel focus,
+        public KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
                 KeyEvent event, int policyFlags) {
             return mWindowManagerService.mInputMonitor.dispatchUnhandledKey(
                     focus, event, policyFlags);
diff --git a/services/java/com/android/server/InputWindow.java b/services/java/com/android/server/InputWindow.java
index befc770..1515290 100644
--- a/services/java/com/android/server/InputWindow.java
+++ b/services/java/com/android/server/InputWindow.java
@@ -20,64 +20,67 @@
 
 /**
  * Describes input-related window properties for use by the input dispatcher.
- * 
  * @hide
  */
 public final class InputWindow {
+    // The window handle.
+    public InputWindowHandle inputWindowHandle;
+
     // The input channel associated with the window.
     public InputChannel inputChannel;
-    
+
     // The window name.
     public String name;
-    
+
     // Window layout params attributes.  (WindowManager.LayoutParams)
     public int layoutParamsFlags;
     public int layoutParamsType;
-    
+
     // Dispatching timeout.
     public long dispatchingTimeoutNanos;
-    
+
     // Window frame area.
     public int frameLeft;
     public int frameTop;
     public int frameRight;
     public int frameBottom;
-    
+
     // Window visible frame area.
     public int visibleFrameLeft;
     public int visibleFrameTop;
     public int visibleFrameRight;
     public int visibleFrameBottom;
-    
+
     // Window touchable area.
     public int touchableAreaLeft;
     public int touchableAreaTop;
     public int touchableAreaRight;
     public int touchableAreaBottom;
-    
+
     // Window is visible.
     public boolean visible;
-    
+
     // Window can receive keys.
     public boolean canReceiveKeys;
-    
+
     // Window has focus.
     public boolean hasFocus;
-    
+
     // Window has wallpaper.  (window is the current wallpaper target)
     public boolean hasWallpaper;
-    
+
     // Input event dispatching is paused.
     public boolean paused;
-    
+
     // Window layer.
     public int layer;
-    
+
     // Id of process and user that owns the window.
     public int ownerPid;
     public int ownerUid;
-    
+
     public void recycle() {
+        inputWindowHandle = null;
         inputChannel = null;
     }
 }
diff --git a/services/java/com/android/server/InputWindowHandle.java b/services/java/com/android/server/InputWindowHandle.java
new file mode 100644
index 0000000..4b92939
--- /dev/null
+++ b/services/java/com/android/server/InputWindowHandle.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.view.WindowManagerPolicy;
+
+/**
+ * Functions as a handle for a window that can receive input.
+ * Enables the native input dispatcher to refer indirectly to the window manager's window state.
+ * @hide
+ */
+public final class InputWindowHandle {
+    // Pointer to the native input window handle.
+    // This field is lazily initialized via JNI.
+    @SuppressWarnings("unused")
+    private int ptr;
+
+    // The input application handle.
+    public final InputApplicationHandle inputApplicationHandle;
+
+    // The window manager's window state.
+    public final WindowManagerPolicy.WindowState windowState;
+
+    private native void nativeDispose();
+
+    public InputWindowHandle(InputApplicationHandle inputApplicationHandle,
+            WindowManagerPolicy.WindowState windowState) {
+        this.inputApplicationHandle = inputApplicationHandle;
+        this.windowState = windowState;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        nativeDispose();
+        super.finalize();
+    }
+}
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 435a2a5..e323b3b 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -7926,6 +7926,14 @@
             copyFrom(orig);
         }
 
+        public void copyFrom(PackageSetting base) {
+            super.copyFrom((PackageSettingBase) base);
+
+            userId = base.userId;
+            sharedUser = base.sharedUser;
+            pkg = base.pkg;
+        }
+
         @Override
         public String toString() {
             return "PackageSetting{"
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index c33d19d..5c823ba 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -536,7 +536,7 @@
                 InputChannel[] channels = InputChannel.openInputChannelPair("drag");
                 mServerChannel = channels[0];
                 mClientChannel = channels[1];
-                mInputManager.registerInputChannel(mServerChannel);
+                mInputManager.registerInputChannel(mServerChannel, null);
                 InputQueue.registerInputChannel(mClientChannel, mDragInputHandler,
                         mH.getLooper().getQueue());
             }
@@ -2311,7 +2311,7 @@
                 win.mInputChannel = inputChannels[0];
                 inputChannels[1].transferToBinderOutParameter(outInputChannel);
                 
-                mInputManager.registerInputChannel(win.mInputChannel);
+                mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
             }
 
             // From now on, no exceptions or errors allowed!
@@ -5711,13 +5711,13 @@
          * 
          * Called by the InputManager.
          */
-        public void notifyInputChannelBroken(InputChannel inputChannel) {
+        public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
+            if (inputWindowHandle == null) {
+                return;
+            }
+
             synchronized (mWindowMap) {
-                WindowState windowState = getWindowStateForInputChannelLocked(inputChannel);
-                if (windowState == null) {
-                    return; // irrelevant
-                }
-                
+                WindowState windowState = (WindowState) inputWindowHandle.windowState;
                 Slog.i(TAG, "WINDOW DIED " + windowState);
                 removeWindowLocked(windowState.mSession, windowState);
             }
@@ -5728,11 +5728,12 @@
          * 
          * Called by the InputManager.
          */
-        public long notifyANR(Object token, InputChannel inputChannel) {
+        public long notifyANR(InputApplicationHandle inputApplicationHandle,
+                InputWindowHandle inputWindowHandle) {
             AppWindowToken appWindowToken = null;
-            if (inputChannel != null) {
+            if (inputWindowHandle != null) {
                 synchronized (mWindowMap) {
-                    WindowState windowState = getWindowStateForInputChannelLocked(inputChannel);
+                    WindowState windowState = (WindowState) inputWindowHandle.windowState;
                     if (windowState != null) {
                         Slog.i(TAG, "Input event dispatching timed out sending to "
                                 + windowState.mAttrs.getTitle());
@@ -5741,8 +5742,8 @@
                 }
             }
             
-            if (appWindowToken == null && token != null) {
-                appWindowToken = (AppWindowToken) token;
+            if (appWindowToken == null && inputApplicationHandle != null) {
+                appWindowToken = inputApplicationHandle.appWindowToken;
                 Slog.i(TAG, "Input event dispatching timed out sending to application "
                         + appWindowToken.stringName);
             }
@@ -5762,24 +5763,6 @@
             }
             return 0; // abort dispatching
         }
-        
-        private WindowState getWindowStateForInputChannel(InputChannel inputChannel) {
-            synchronized (mWindowMap) {
-                return getWindowStateForInputChannelLocked(inputChannel);
-            }
-        }
-        
-        private WindowState getWindowStateForInputChannelLocked(InputChannel inputChannel) {
-            int windowCount = mWindows.size();
-            for (int i = 0; i < windowCount; i++) {
-                WindowState windowState = mWindows.get(i);
-                if (windowState.mInputChannel == inputChannel) {
-                    return windowState;
-                }
-            }
-            
-            return null;
-        }
 
         private void addDragInputWindowLw(InputWindowList windowList) {
             final InputWindow inputWindow = windowList.add();
@@ -5856,6 +5839,7 @@
 
                 // Add a window to our list of input windows.
                 final InputWindow inputWindow = mTempInputWindows.add();
+                inputWindow.inputWindowHandle = child.mInputWindowHandle;
                 inputWindow.inputChannel = child.mInputChannel;
                 inputWindow.name = child.toString();
                 inputWindow.layoutParamsFlags = flags;
@@ -5934,16 +5918,16 @@
         /* Provides an opportunity for the window manager policy to process a key before
          * ordinary dispatch. */
         public boolean interceptKeyBeforeDispatching(
-                InputChannel focus, KeyEvent event, int policyFlags) {
-            WindowState windowState = getWindowStateForInputChannel(focus);
+                InputWindowHandle focus, KeyEvent event, int policyFlags) {
+            WindowState windowState = (WindowState) focus.windowState;
             return mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);
         }
         
         /* Provides an opportunity for the window manager policy to process a key that
          * the application did not handle. */
         public KeyEvent dispatchUnhandledKey(
-                InputChannel focus, KeyEvent event, int policyFlags) {
-            WindowState windowState = getWindowStateForInputChannel(focus);
+                InputWindowHandle focus, KeyEvent event, int policyFlags) {
+            WindowState windowState = (WindowState) focus.windowState;
             return mPolicy.dispatchUnhandledKey(windowState, event, policyFlags);
         }
         
@@ -5973,12 +5957,14 @@
             if (newApp == null) {
                 mInputManager.setFocusedApplication(null);
             } else {
+                mTempInputApplication.inputApplicationHandle = newApp.mInputApplicationHandle;
                 mTempInputApplication.name = newApp.toString();
                 mTempInputApplication.dispatchingTimeoutNanos =
                         newApp.inputDispatchingTimeoutNanos;
-                mTempInputApplication.token = newApp;
-                
+
                 mInputManager.setFocusedApplication(mTempInputApplication);
+
+                mTempInputApplication.recycle();
             }
         }
         
@@ -6823,7 +6809,8 @@
         int mSurfaceLayer;
         float mSurfaceAlpha;
         
-        // Input channel
+        // Input channel and input window handle used by the input dispatcher.
+        InputWindowHandle mInputWindowHandle;
         InputChannel mInputChannel;
         
         // Used to improve performance of toString()
@@ -6915,6 +6902,8 @@
             mLayer = 0;
             mAnimLayer = 0;
             mLastLayer = 0;
+            mInputWindowHandle = new InputWindowHandle(
+                    mAppToken != null ? mAppToken.mInputApplicationHandle : null, this);
         }
 
         void attach() {
@@ -8304,11 +8293,15 @@
         boolean startingMoved;
         boolean firstWindowDrawn;
 
+        // Input application handle used by the input dispatcher.
+        InputApplicationHandle mInputApplicationHandle;
+
         AppWindowToken(IApplicationToken _token) {
             super(_token.asBinder(),
                     WindowManager.LayoutParams.TYPE_APPLICATION, true);
             appWindowToken = this;
             appToken = _token;
+            mInputApplicationHandle = new InputApplicationHandle(this);
         }
 
         public void setAnimation(Animation anim) {
diff --git a/services/jni/Android.mk b/services/jni/Android.mk
index ec85e54..f5a5b4d 100644
--- a/services/jni/Android.mk
+++ b/services/jni/Android.mk
@@ -4,7 +4,11 @@
 LOCAL_SRC_FILES:= \
     com_android_server_AlarmManagerService.cpp \
     com_android_server_BatteryService.cpp \
+    com_android_server_InputApplication.cpp \
+    com_android_server_InputApplicationHandle.cpp \
     com_android_server_InputManager.cpp \
+    com_android_server_InputWindow.cpp \
+    com_android_server_InputWindowHandle.cpp \
     com_android_server_LightsService.cpp \
     com_android_server_PowerManagerService.cpp \
     com_android_server_SystemServer.cpp \
diff --git a/services/jni/com_android_server_InputApplication.cpp b/services/jni/com_android_server_InputApplication.cpp
new file mode 100644
index 0000000..a46a162
--- /dev/null
+++ b/services/jni/com_android_server_InputApplication.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#define LOG_TAG "InputApplication"
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include "com_android_server_InputApplication.h"
+#include "com_android_server_InputApplicationHandle.h"
+
+namespace android {
+
+static struct {
+    jclass clazz;
+
+    jfieldID inputApplicationHandle;
+    jfieldID name;
+    jfieldID dispatchingTimeoutNanos;
+} gInputApplicationClassInfo;
+
+
+// --- Global functions ---
+
+void android_server_InputApplication_toNative(
+        JNIEnv* env, jobject inputApplicationObj, InputApplication* outInputApplication) {
+    jobject inputApplicationHandleObj = env->GetObjectField(inputApplicationObj,
+            gInputApplicationClassInfo.inputApplicationHandle);
+    if (inputApplicationHandleObj) {
+        outInputApplication->inputApplicationHandle =
+                android_server_InputApplicationHandle_getHandle(env, inputApplicationHandleObj);
+        env->DeleteLocalRef(inputApplicationHandleObj);
+    } else {
+        outInputApplication->inputApplicationHandle = NULL;
+    }
+
+    jstring nameObj = jstring(env->GetObjectField(inputApplicationObj,
+            gInputApplicationClassInfo.name));
+    if (nameObj) {
+        const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
+        outInputApplication->name.setTo(nameStr);
+        env->ReleaseStringUTFChars(nameObj, nameStr);
+        env->DeleteLocalRef(nameObj);
+    } else {
+        LOGE("InputApplication.name should not be null.");
+        outInputApplication->name.setTo("unknown");
+    }
+
+    outInputApplication->dispatchingTimeout = env->GetLongField(inputApplicationObj,
+            gInputApplicationClassInfo.dispatchingTimeoutNanos);
+}
+
+
+// --- JNI ---
+
+#define FIND_CLASS(var, className) \
+        var = env->FindClass(className); \
+        LOG_FATAL_IF(! var, "Unable to find class " className); \
+        var = jclass(env->NewGlobalRef(var));
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
+int register_android_server_InputApplication(JNIEnv* env) {
+    FIND_CLASS(gInputApplicationClassInfo.clazz, "com/android/server/InputApplication");
+
+    GET_FIELD_ID(gInputApplicationClassInfo.inputApplicationHandle,
+            gInputApplicationClassInfo.clazz,
+            "inputApplicationHandle", "Lcom/android/server/InputApplicationHandle;");
+
+    GET_FIELD_ID(gInputApplicationClassInfo.name, gInputApplicationClassInfo.clazz,
+            "name", "Ljava/lang/String;");
+
+    GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
+            gInputApplicationClassInfo.clazz,
+            "dispatchingTimeoutNanos", "J");
+    return 0;
+}
+
+} /* namespace android */
diff --git a/services/jni/com_android_server_InputApplication.h b/services/jni/com_android_server_InputApplication.h
new file mode 100644
index 0000000..85fb891
--- /dev/null
+++ b/services/jni/com_android_server_InputApplication.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef _ANDROID_SERVER_INPUT_APPLICATION_H
+#define _ANDROID_SERVER_INPUT_APPLICATION_H
+
+#include <input/InputApplication.h>
+
+#include "JNIHelp.h"
+#include "jni.h"
+
+namespace android {
+
+extern void android_server_InputApplication_toNative(
+        JNIEnv* env, jobject inputApplicationObj, InputApplication* outInputApplication);
+
+} // namespace android
+
+#endif // _ANDROID_SERVER_INPUT_APPLICATION_H
diff --git a/services/jni/com_android_server_InputApplicationHandle.cpp b/services/jni/com_android_server_InputApplicationHandle.cpp
new file mode 100644
index 0000000..ab82635
--- /dev/null
+++ b/services/jni/com_android_server_InputApplicationHandle.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#define LOG_TAG "InputApplicationHandle"
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include <android_runtime/AndroidRuntime.h>
+#include <utils/threads.h>
+
+#include "com_android_server_InputApplicationHandle.h"
+
+namespace android {
+
+static struct {
+    jclass clazz;
+
+    jfieldID ptr;
+} gInputApplicationHandleClassInfo;
+
+static Mutex gHandleMutex;
+
+
+// --- NativeInputApplicationHandle ---
+
+NativeInputApplicationHandle::NativeInputApplicationHandle(jweak objWeak) :
+        mObjWeak(objWeak) {
+}
+
+NativeInputApplicationHandle::~NativeInputApplicationHandle() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->DeleteWeakGlobalRef(mObjWeak);
+}
+
+jobject NativeInputApplicationHandle::getInputApplicationHandleObjLocalRef(JNIEnv* env) {
+    return env->NewLocalRef(mObjWeak);
+}
+
+
+// --- Global functions ---
+
+sp<InputApplicationHandle> android_server_InputApplicationHandle_getHandle(
+        JNIEnv* env, jobject inputApplicationHandleObj) {
+    if (!inputApplicationHandleObj) {
+        return NULL;
+    }
+
+    AutoMutex _l(gHandleMutex);
+
+    int ptr = env->GetIntField(inputApplicationHandleObj, gInputApplicationHandleClassInfo.ptr);
+    NativeInputApplicationHandle* handle;
+    if (ptr) {
+        handle = reinterpret_cast<NativeInputApplicationHandle*>(ptr);
+    } else {
+        jweak objWeak = env->NewWeakGlobalRef(inputApplicationHandleObj);
+        handle = new NativeInputApplicationHandle(objWeak);
+        handle->incStrong(inputApplicationHandleObj);
+        env->SetIntField(inputApplicationHandleObj, gInputApplicationHandleClassInfo.ptr,
+                reinterpret_cast<int>(handle));
+    }
+    return handle;
+}
+
+
+// --- JNI ---
+
+static void android_server_InputApplicationHandle_nativeDispose(JNIEnv* env, jobject obj) {
+    AutoMutex _l(gHandleMutex);
+
+    int ptr = env->GetIntField(obj, gInputApplicationHandleClassInfo.ptr);
+    if (ptr) {
+        env->SetIntField(obj, gInputApplicationHandleClassInfo.ptr, 0);
+
+        NativeInputApplicationHandle* handle = reinterpret_cast<NativeInputApplicationHandle*>(ptr);
+        handle->decStrong(obj);
+    }
+}
+
+
+static JNINativeMethod gInputApplicationHandleMethods[] = {
+    /* name, signature, funcPtr */
+    { "nativeDispose", "()V",
+            (void*) android_server_InputApplicationHandle_nativeDispose },
+};
+
+#define FIND_CLASS(var, className) \
+        var = env->FindClass(className); \
+        LOG_FATAL_IF(! var, "Unable to find class " className); \
+        var = jclass(env->NewGlobalRef(var));
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
+int register_android_server_InputApplicationHandle(JNIEnv* env) {
+    int res = jniRegisterNativeMethods(env, "com/android/server/InputApplicationHandle",
+            gInputApplicationHandleMethods, NELEM(gInputApplicationHandleMethods));
+    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
+
+    FIND_CLASS(gInputApplicationHandleClassInfo.clazz, "com/android/server/InputApplicationHandle");
+
+    GET_FIELD_ID(gInputApplicationHandleClassInfo.ptr, gInputApplicationHandleClassInfo.clazz,
+            "ptr", "I");
+
+    return 0;
+}
+
+} /* namespace android */
diff --git a/services/jni/com_android_server_InputApplicationHandle.h b/services/jni/com_android_server_InputApplicationHandle.h
new file mode 100644
index 0000000..9d18721
--- /dev/null
+++ b/services/jni/com_android_server_InputApplicationHandle.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef _ANDROID_SERVER_INPUT_APPLICATION_HANDLE_H
+#define _ANDROID_SERVER_INPUT_APPLICATION_HANDLE_H
+
+#include <input/InputApplication.h>
+
+#include "JNIHelp.h"
+#include "jni.h"
+
+namespace android {
+
+class NativeInputApplicationHandle : public InputApplicationHandle {
+public:
+    NativeInputApplicationHandle(jweak objWeak);
+    virtual ~NativeInputApplicationHandle();
+
+    jobject getInputApplicationHandleObjLocalRef(JNIEnv* env);
+
+private:
+    jweak mObjWeak;
+};
+
+
+extern sp<InputApplicationHandle> android_server_InputApplicationHandle_getHandle(
+        JNIEnv* env, jobject inputApplicationHandleObj);
+
+} // namespace android
+
+#endif // _ANDROID_SERVER_INPUT_APPLICATION_HANDLE_H
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 5ed63f0..e04e4c3 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -42,11 +42,13 @@
 #include <android/graphics/GraphicsJNI.h>
 
 #include "com_android_server_PowerManagerService.h"
+#include "com_android_server_InputApplication.h"
+#include "com_android_server_InputApplicationHandle.h"
+#include "com_android_server_InputWindow.h"
+#include "com_android_server_InputWindowHandle.h"
 
 namespace android {
 
-// ----------------------------------------------------------------------------
-
 static struct {
     jclass clazz;
 
@@ -68,44 +70,6 @@
 
 static struct {
     jclass clazz;
-
-    jfieldID inputChannel;
-    jfieldID name;
-    jfieldID layoutParamsFlags;
-    jfieldID layoutParamsType;
-    jfieldID dispatchingTimeoutNanos;
-    jfieldID frameLeft;
-    jfieldID frameTop;
-    jfieldID frameRight;
-    jfieldID frameBottom;
-    jfieldID visibleFrameLeft;
-    jfieldID visibleFrameTop;
-    jfieldID visibleFrameRight;
-    jfieldID visibleFrameBottom;
-    jfieldID touchableAreaLeft;
-    jfieldID touchableAreaTop;
-    jfieldID touchableAreaRight;
-    jfieldID touchableAreaBottom;
-    jfieldID visible;
-    jfieldID canReceiveKeys;
-    jfieldID hasFocus;
-    jfieldID hasWallpaper;
-    jfieldID paused;
-    jfieldID layer;
-    jfieldID ownerPid;
-    jfieldID ownerUid;
-} gInputWindowClassInfo;
-
-static struct {
-    jclass clazz;
-
-    jfieldID name;
-    jfieldID dispatchingTimeoutNanos;
-    jfieldID token;
-} gInputApplicationClassInfo;
-
-static struct {
-    jclass clazz;
 } gKeyEventClassInfo;
 
 static struct {
@@ -141,7 +105,29 @@
     jfieldID hotSpotY;
 } gPointerIconClassInfo;
 
-// ----------------------------------------------------------------------------
+
+// --- Global functions ---
+
+static jobject getInputApplicationHandleObjLocalRef(JNIEnv* env,
+        const sp<InputApplicationHandle>& inputApplicationHandle) {
+    if (inputApplicationHandle == NULL) {
+        return NULL;
+    }
+    return static_cast<NativeInputApplicationHandle*>(inputApplicationHandle.get())->
+            getInputApplicationHandleObjLocalRef(env);
+}
+
+static jobject getInputWindowHandleObjLocalRef(JNIEnv* env,
+        const sp<InputWindowHandle>& inputWindowHandle) {
+    if (inputWindowHandle == NULL) {
+        return NULL;
+    }
+    return static_cast<NativeInputWindowHandle*>(inputWindowHandle.get())->
+            getInputWindowHandleObjLocalRef(env);
+}
+
+
+// --- NativeInputManager ---
 
 class NativeInputManager : public virtual RefBase,
     public virtual InputReaderPolicyInterface,
@@ -160,7 +146,7 @@
     void setDisplayOrientation(int32_t displayId, int32_t orientation);
 
     status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
-            jweak inputChannelObjWeak, bool monitor);
+            const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
     status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
 
     void setInputWindows(JNIEnv* env, jobjectArray windowObjArray);
@@ -182,37 +168,22 @@
             uint32_t policyFlags);
     virtual void notifyConfigurationChanged(nsecs_t when);
     virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
-            const sp<InputChannel>& inputChannel);
-    virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel);
+            const sp<InputWindowHandle>& inputWindowHandle);
+    virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle);
     virtual nsecs_t getKeyRepeatTimeout();
     virtual nsecs_t getKeyRepeatDelay();
     virtual int32_t getMaxEventsPerSecond();
     virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags);
     virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
-    virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
+    virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
             const KeyEvent* keyEvent, uint32_t policyFlags);
-    virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
+    virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
             const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent);
     virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType);
     virtual bool checkInjectEventsPermissionNonReentrant(
             int32_t injectorPid, int32_t injectorUid);
 
 private:
-    class ApplicationToken : public InputApplicationHandle {
-        jweak mTokenObjWeak;
-
-    public:
-        ApplicationToken(jweak tokenObjWeak) :
-            mTokenObjWeak(tokenObjWeak) { }
-
-        virtual ~ApplicationToken() {
-            JNIEnv* env = NativeInputManager::jniEnv();
-            env->DeleteWeakGlobalRef(mTokenObjWeak);
-        }
-
-        inline jweak getTokenObj() { return mTokenObjWeak; }
-    };
-
     sp<InputManager> mInputManager;
 
     jobject mCallbacksObj;
@@ -232,19 +203,12 @@
 
         // Pointer controller singleton, created and destroyed as needed.
         wp<PointerController> pointerController;
-
-        // Weak references to all currently registered input channels by connection pointer.
-        KeyedVector<InputChannel*, jweak> inputChannelObjWeakTable;
     } mLocked;
 
     // Power manager interactions.
     bool isScreenOn();
     bool isScreenBright();
 
-    jobject getInputChannelObjLocal(JNIEnv* env, const sp<InputChannel>& inputChannel);
-
-    static bool populateWindow(JNIEnv* env, jobject windowObj, InputWindow& outWindow);
-
     static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
 
     static inline JNIEnv* jniEnv() {
@@ -252,7 +216,7 @@
     }
 };
 
-// ----------------------------------------------------------------------------
+
 
 NativeInputManager::NativeInputManager(jobject callbacksObj) :
     mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1),
@@ -328,88 +292,17 @@
 }
 
 status_t NativeInputManager::registerInputChannel(JNIEnv* env,
-        const sp<InputChannel>& inputChannel, jobject inputChannelObj, bool monitor) {
-    jweak inputChannelObjWeak = env->NewWeakGlobalRef(inputChannelObj);
-    if (! inputChannelObjWeak) {
-        LOGE("Could not create weak reference for input channel.");
-        LOGE_EX(env);
-        return NO_MEMORY;
-    }
-
-    status_t status;
-    {
-        AutoMutex _l(mLock);
-
-        ssize_t index = mLocked.inputChannelObjWeakTable.indexOfKey(inputChannel.get());
-        if (index >= 0) {
-            LOGE("Input channel object '%s' has already been registered",
-                    inputChannel->getName().string());
-            status = INVALID_OPERATION;
-            goto DeleteWeakRef;
-        }
-
-        mLocked.inputChannelObjWeakTable.add(inputChannel.get(), inputChannelObjWeak);
-    }
-
-    status = mInputManager->getDispatcher()->registerInputChannel(inputChannel, monitor);
-    if (! status) {
-        // Success.
-        return OK;
-    }
-
-    // Failed!
-    {
-        AutoMutex _l(mLock);
-        mLocked.inputChannelObjWeakTable.removeItem(inputChannel.get());
-    }
-
-DeleteWeakRef:
-    env->DeleteWeakGlobalRef(inputChannelObjWeak);
-    return status;
+        const sp<InputChannel>& inputChannel,
+        const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
+    return mInputManager->getDispatcher()->registerInputChannel(
+            inputChannel, inputWindowHandle, monitor);
 }
 
 status_t NativeInputManager::unregisterInputChannel(JNIEnv* env,
         const sp<InputChannel>& inputChannel) {
-    jweak inputChannelObjWeak;
-    {
-        AutoMutex _l(mLock);
-
-        ssize_t index = mLocked.inputChannelObjWeakTable.indexOfKey(inputChannel.get());
-        if (index < 0) {
-            LOGE("Input channel object '%s' is not currently registered",
-                    inputChannel->getName().string());
-            return INVALID_OPERATION;
-        }
-
-        inputChannelObjWeak = mLocked.inputChannelObjWeakTable.valueAt(index);
-        mLocked.inputChannelObjWeakTable.removeItemsAt(index);
-    }
-
-    env->DeleteWeakGlobalRef(inputChannelObjWeak);
-
     return mInputManager->getDispatcher()->unregisterInputChannel(inputChannel);
 }
 
-jobject NativeInputManager::getInputChannelObjLocal(JNIEnv* env,
-        const sp<InputChannel>& inputChannel) {
-    InputChannel* inputChannelPtr = inputChannel.get();
-    if (! inputChannelPtr) {
-        return NULL;
-    }
-
-    {
-        AutoMutex _l(mLock);
-
-        ssize_t index = mLocked.inputChannelObjWeakTable.indexOfKey(inputChannelPtr);
-        if (index < 0) {
-            return NULL;
-        }
-
-        jweak inputChannelObjWeak = mLocked.inputChannelObjWeakTable.valueAt(index);
-        return env->NewLocalRef(inputChannelObjWeak);
-    }
-}
-
 bool NativeInputManager::getDisplayInfo(int32_t displayId,
         int32_t* width, int32_t* height, int32_t* orientation) {
     bool result = false;
@@ -549,50 +442,46 @@
 }
 
 nsecs_t NativeInputManager::notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
-        const sp<InputChannel>& inputChannel) {
+        const sp<InputWindowHandle>& inputWindowHandle) {
 #if DEBUG_INPUT_DISPATCHER_POLICY
     LOGD("notifyANR");
 #endif
 
     JNIEnv* env = jniEnv();
 
-    jobject tokenObjLocal;
-    if (inputApplicationHandle.get()) {
-        ApplicationToken* token = static_cast<ApplicationToken*>(inputApplicationHandle.get());
-        jweak tokenObjWeak = token->getTokenObj();
-        tokenObjLocal = env->NewLocalRef(tokenObjWeak);
-    } else {
-        tokenObjLocal = NULL;
-    }
+    jobject inputApplicationHandleObj =
+            getInputApplicationHandleObjLocalRef(env, inputApplicationHandle);
+    jobject inputWindowHandleObj =
+            getInputWindowHandleObjLocalRef(env, inputWindowHandle);
 
-    jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
     jlong newTimeout = env->CallLongMethod(mCallbacksObj,
-                gCallbacksClassInfo.notifyANR, tokenObjLocal, inputChannelObjLocal);
+                gCallbacksClassInfo.notifyANR, inputApplicationHandleObj, inputWindowHandleObj);
     if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
         newTimeout = 0; // abort dispatch
     } else {
         assert(newTimeout >= 0);
     }
 
-    env->DeleteLocalRef(tokenObjLocal);
-    env->DeleteLocalRef(inputChannelObjLocal);
+    env->DeleteLocalRef(inputWindowHandleObj);
+    env->DeleteLocalRef(inputApplicationHandleObj);
     return newTimeout;
 }
 
-void NativeInputManager::notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
+void NativeInputManager::notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) {
 #if DEBUG_INPUT_DISPATCHER_POLICY
-    LOGD("notifyInputChannelBroken - inputChannel='%s'", inputChannel->getName().string());
+    LOGD("notifyInputChannelBroken");
 #endif
 
     JNIEnv* env = jniEnv();
 
-    jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
-    if (inputChannelObjLocal) {
+    jobject inputWindowHandleObj =
+            getInputWindowHandleObjLocalRef(env, inputWindowHandle);
+    if (inputWindowHandleObj) {
         env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelBroken,
-                inputChannelObjLocal);
+                inputWindowHandleObj);
         checkAndClearExceptionFromCallback(env, "notifyInputChannelBroken");
 
-        env->DeleteLocalRef(inputChannelObjLocal);
+        env->DeleteLocalRef(inputWindowHandleObj);
     }
 }
 
@@ -630,160 +519,32 @@
 
     jsize length = env->GetArrayLength(windowObjArray);
     for (jsize i = 0; i < length; i++) {
-        jobject inputTargetObj = env->GetObjectArrayElement(windowObjArray, i);
-        if (! inputTargetObj) {
+        jobject windowObj = env->GetObjectArrayElement(windowObjArray, i);
+        if (! windowObj) {
             break; // found null element indicating end of used portion of the array
         }
 
         windows.push();
         InputWindow& window = windows.editTop();
-        bool valid = populateWindow(env, inputTargetObj, window);
-        if (! valid) {
+        android_server_InputWindow_toNative(env, windowObj, &window);
+        if (window.inputChannel == NULL) {
             windows.pop();
         }
-
-        env->DeleteLocalRef(inputTargetObj);
+        env->DeleteLocalRef(windowObj);
     }
 
     mInputManager->getDispatcher()->setInputWindows(windows);
 }
 
-bool NativeInputManager::populateWindow(JNIEnv* env, jobject windowObj,
-        InputWindow& outWindow) {
-    bool valid = false;
-
-    jobject inputChannelObj = env->GetObjectField(windowObj,
-            gInputWindowClassInfo.inputChannel);
-    if (inputChannelObj) {
-        sp<InputChannel> inputChannel =
-                android_view_InputChannel_getInputChannel(env, inputChannelObj);
-        if (inputChannel != NULL) {
-            jstring name = jstring(env->GetObjectField(windowObj,
-                    gInputWindowClassInfo.name));
-            jint layoutParamsFlags = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.layoutParamsFlags);
-            jint layoutParamsType = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.layoutParamsType);
-            jlong dispatchingTimeoutNanos = env->GetLongField(windowObj,
-                    gInputWindowClassInfo.dispatchingTimeoutNanos);
-            jint frameLeft = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.frameLeft);
-            jint frameTop = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.frameTop);
-            jint frameRight = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.frameRight);
-            jint frameBottom = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.frameBottom);
-            jint visibleFrameLeft = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.visibleFrameLeft);
-            jint visibleFrameTop = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.visibleFrameTop);
-            jint visibleFrameRight = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.visibleFrameRight);
-            jint visibleFrameBottom = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.visibleFrameBottom);
-            jint touchableAreaLeft = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.touchableAreaLeft);
-            jint touchableAreaTop = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.touchableAreaTop);
-            jint touchableAreaRight = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.touchableAreaRight);
-            jint touchableAreaBottom = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.touchableAreaBottom);
-            jboolean visible = env->GetBooleanField(windowObj,
-                    gInputWindowClassInfo.visible);
-            jboolean canReceiveKeys = env->GetBooleanField(windowObj,
-                    gInputWindowClassInfo.canReceiveKeys);
-            jboolean hasFocus = env->GetBooleanField(windowObj,
-                    gInputWindowClassInfo.hasFocus);
-            jboolean hasWallpaper = env->GetBooleanField(windowObj,
-                    gInputWindowClassInfo.hasWallpaper);
-            jboolean paused = env->GetBooleanField(windowObj,
-                    gInputWindowClassInfo.paused);
-            jint layer = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.layer);
-            jint ownerPid = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.ownerPid);
-            jint ownerUid = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.ownerUid);
-
-            const char* nameStr = env->GetStringUTFChars(name, NULL);
-
-            outWindow.inputChannel = inputChannel;
-            outWindow.name.setTo(nameStr);
-            outWindow.layoutParamsFlags = layoutParamsFlags;
-            outWindow.layoutParamsType = layoutParamsType;
-            outWindow.dispatchingTimeout = dispatchingTimeoutNanos;
-            outWindow.frameLeft = frameLeft;
-            outWindow.frameTop = frameTop;
-            outWindow.frameRight = frameRight;
-            outWindow.frameBottom = frameBottom;
-            outWindow.visibleFrameLeft = visibleFrameLeft;
-            outWindow.visibleFrameTop = visibleFrameTop;
-            outWindow.visibleFrameRight = visibleFrameRight;
-            outWindow.visibleFrameBottom = visibleFrameBottom;
-            outWindow.touchableAreaLeft = touchableAreaLeft;
-            outWindow.touchableAreaTop = touchableAreaTop;
-            outWindow.touchableAreaRight = touchableAreaRight;
-            outWindow.touchableAreaBottom = touchableAreaBottom;
-            outWindow.visible = visible;
-            outWindow.canReceiveKeys = canReceiveKeys;
-            outWindow.hasFocus = hasFocus;
-            outWindow.hasWallpaper = hasWallpaper;
-            outWindow.paused = paused;
-            outWindow.layer = layer;
-            outWindow.ownerPid = ownerPid;
-            outWindow.ownerUid = ownerUid;
-
-            env->ReleaseStringUTFChars(name, nameStr);
-            env->DeleteLocalRef(name);
-            valid = true;
-        } else {
-            LOGW("Dropping input target because its input channel is not initialized.");
-        }
-
-        env->DeleteLocalRef(inputChannelObj);
-    } else {
-        LOGW("Dropping input target because the input channel object was null.");
-    }
-    return valid;
-}
-
 void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationObj) {
     if (applicationObj) {
-        jstring nameObj = jstring(env->GetObjectField(applicationObj,
-                gInputApplicationClassInfo.name));
-        jlong dispatchingTimeoutNanos = env->GetLongField(applicationObj,
-                gInputApplicationClassInfo.dispatchingTimeoutNanos);
-        jobject tokenObj = env->GetObjectField(applicationObj,
-                gInputApplicationClassInfo.token);
-        jweak tokenObjWeak = env->NewWeakGlobalRef(tokenObj);
-        if (! tokenObjWeak) {
-            LOGE("Could not create weak reference for application token.");
-            LOGE_EX(env);
-            env->ExceptionClear();
-        }
-        env->DeleteLocalRef(tokenObj);
-
-        String8 name;
-        if (nameObj) {
-            const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
-            name.setTo(nameStr);
-            env->ReleaseStringUTFChars(nameObj, nameStr);
-            env->DeleteLocalRef(nameObj);
-        } else {
-            LOGE("InputApplication.name should not be null.");
-            name.setTo("unknown");
-        }
-
         InputApplication application;
-        application.name = name;
-        application.dispatchingTimeout = dispatchingTimeoutNanos;
-        application.handle = new ApplicationToken(tokenObjWeak);
-        mInputManager->getDispatcher()->setFocusedApplication(& application);
-    } else {
-        mInputManager->getDispatcher()->setFocusedApplication(NULL);
+        android_server_InputApplication_toNative(env, applicationObj, &application);
+        if (application.inputApplicationHandle != NULL) {
+            mInputManager->getDispatcher()->setFocusedApplication(&application);
+        }
     }
+    mInputManager->getDispatcher()->setFocusedApplication(NULL);
 }
 
 void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) {
@@ -875,7 +636,8 @@
     }
 }
 
-bool NativeInputManager::interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
+bool NativeInputManager::interceptKeyBeforeDispatching(
+        const sp<InputWindowHandle>& inputWindowHandle,
         const KeyEvent* keyEvent, uint32_t policyFlags) {
     // Policy:
     // - Ignore untrusted events and pass them along.
@@ -885,13 +647,13 @@
     if (policyFlags & POLICY_FLAG_TRUSTED) {
         JNIEnv* env = jniEnv();
 
-        // Note: inputChannel may be null.
-        jobject inputChannelObj = getInputChannelObjLocal(env, inputChannel);
+        // Note: inputWindowHandle may be null.
+        jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
         jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
         if (keyEventObj) {
             jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
                     gCallbacksClassInfo.interceptKeyBeforeDispatching,
-                    inputChannelObj, keyEventObj, policyFlags);
+                    inputWindowHandleObj, keyEventObj, policyFlags);
             bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
             android_view_KeyEvent_recycle(env, keyEventObj);
             env->DeleteLocalRef(keyEventObj);
@@ -899,12 +661,12 @@
         } else {
             LOGE("Failed to obtain key event object for interceptKeyBeforeDispatching.");
         }
-        env->DeleteLocalRef(inputChannelObj);
+        env->DeleteLocalRef(inputWindowHandleObj);
     }
     return result;
 }
 
-bool NativeInputManager::dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
+bool NativeInputManager::dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
         const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
     // Policy:
     // - Ignore untrusted events and do not perform default handling.
@@ -912,13 +674,13 @@
     if (policyFlags & POLICY_FLAG_TRUSTED) {
         JNIEnv* env = jniEnv();
 
-        // Note: inputChannel may be null.
-        jobject inputChannelObj = getInputChannelObjLocal(env, inputChannel);
+        // Note: inputWindowHandle may be null.
+        jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
         jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
         if (keyEventObj) {
             jobject fallbackKeyEventObj = env->CallObjectMethod(mCallbacksObj,
                     gCallbacksClassInfo.dispatchUnhandledKey,
-                    inputChannelObj, keyEventObj, policyFlags);
+                    inputWindowHandleObj, keyEventObj, policyFlags);
             checkAndClearExceptionFromCallback(env, "dispatchUnhandledKey");
             android_view_KeyEvent_recycle(env, keyEventObj);
             env->DeleteLocalRef(keyEventObj);
@@ -935,7 +697,7 @@
         } else {
             LOGE("Failed to obtain key event object for dispatchUnhandledKey.");
         }
-        env->DeleteLocalRef(inputChannelObj);
+        env->DeleteLocalRef(inputWindowHandleObj);
     }
     return result;
 }
@@ -1079,7 +841,7 @@
 }
 
 static void android_server_InputManager_nativeRegisterInputChannel(JNIEnv* env, jclass clazz,
-        jobject inputChannelObj, jboolean monitor) {
+        jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) {
     if (checkInputManagerUnitialized(env)) {
         return;
     }
@@ -1091,9 +853,11 @@
         return;
     }
 
+    sp<InputWindowHandle> inputWindowHandle =
+            android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);
 
     status_t status = gNativeInputManager->registerInputChannel(
-            env, inputChannel, inputChannelObj, monitor);
+            env, inputChannel, inputWindowHandle, monitor);
     if (status) {
         jniThrowRuntimeException(env, "Failed to register input channel.  "
                 "Check logs for details.");
@@ -1311,7 +1075,8 @@
             (void*) android_server_InputManager_nativeGetSwitchState },
     { "nativeHasKeys", "(II[I[Z)Z",
             (void*) android_server_InputManager_nativeHasKeys },
-    { "nativeRegisterInputChannel", "(Landroid/view/InputChannel;Z)V",
+    { "nativeRegisterInputChannel",
+            "(Landroid/view/InputChannel;Lcom/android/server/InputWindowHandle;Z)V",
             (void*) android_server_InputManager_nativeRegisterInputChannel },
     { "nativeUnregisterInputChannel", "(Landroid/view/InputChannel;)V",
             (void*) android_server_InputManager_nativeUnregisterInputChannel },
@@ -1364,21 +1129,22 @@
             "notifyLidSwitchChanged", "(JZ)V");
 
     GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelBroken, gCallbacksClassInfo.clazz,
-            "notifyInputChannelBroken", "(Landroid/view/InputChannel;)V");
+            "notifyInputChannelBroken", "(Lcom/android/server/InputWindowHandle;)V");
 
     GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz,
-            "notifyANR", "(Ljava/lang/Object;Landroid/view/InputChannel;)J");
+            "notifyANR",
+            "(Lcom/android/server/InputApplicationHandle;Lcom/android/server/InputWindowHandle;)J");
 
     GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
             "interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;IZ)I");
 
     GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz,
             "interceptKeyBeforeDispatching",
-            "(Landroid/view/InputChannel;Landroid/view/KeyEvent;I)Z");
+            "(Lcom/android/server/InputWindowHandle;Landroid/view/KeyEvent;I)Z");
 
     GET_METHOD_ID(gCallbacksClassInfo.dispatchUnhandledKey, gCallbacksClassInfo.clazz,
             "dispatchUnhandledKey",
-            "(Landroid/view/InputChannel;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;");
+            "(Lcom/android/server/InputWindowHandle;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;");
 
     GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz,
             "checkInjectEventsPermission", "(II)Z");
@@ -1401,99 +1167,6 @@
     GET_METHOD_ID(gCallbacksClassInfo.getPointerIcon, gCallbacksClassInfo.clazz,
             "getPointerIcon", "()Lcom/android/server/InputManager$PointerIcon;");
 
-    // InputWindow
-
-    FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow");
-
-    GET_FIELD_ID(gInputWindowClassInfo.inputChannel, gInputWindowClassInfo.clazz,
-            "inputChannel", "Landroid/view/InputChannel;");
-
-    GET_FIELD_ID(gInputWindowClassInfo.name, gInputWindowClassInfo.clazz,
-            "name", "Ljava/lang/String;");
-
-    GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, gInputWindowClassInfo.clazz,
-            "layoutParamsFlags", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, gInputWindowClassInfo.clazz,
-            "layoutParamsType", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, gInputWindowClassInfo.clazz,
-            "dispatchingTimeoutNanos", "J");
-
-    GET_FIELD_ID(gInputWindowClassInfo.frameLeft, gInputWindowClassInfo.clazz,
-            "frameLeft", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
-            "frameTop", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.frameRight, gInputWindowClassInfo.clazz,
-            "frameRight", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.frameBottom, gInputWindowClassInfo.clazz,
-            "frameBottom", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameLeft, gInputWindowClassInfo.clazz,
-            "visibleFrameLeft", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameTop, gInputWindowClassInfo.clazz,
-            "visibleFrameTop", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameRight, gInputWindowClassInfo.clazz,
-            "visibleFrameRight", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameBottom, gInputWindowClassInfo.clazz,
-            "visibleFrameBottom", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
-            "touchableAreaLeft", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.touchableAreaTop, gInputWindowClassInfo.clazz,
-            "touchableAreaTop", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.touchableAreaRight, gInputWindowClassInfo.clazz,
-            "touchableAreaRight", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.touchableAreaBottom, gInputWindowClassInfo.clazz,
-            "touchableAreaBottom", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.visible, gInputWindowClassInfo.clazz,
-            "visible", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.canReceiveKeys, gInputWindowClassInfo.clazz,
-            "canReceiveKeys", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.hasFocus, gInputWindowClassInfo.clazz,
-            "hasFocus", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, gInputWindowClassInfo.clazz,
-            "hasWallpaper", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.paused, gInputWindowClassInfo.clazz,
-            "paused", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.layer, gInputWindowClassInfo.clazz,
-            "layer", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.ownerPid, gInputWindowClassInfo.clazz,
-            "ownerPid", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.ownerUid, gInputWindowClassInfo.clazz,
-            "ownerUid", "I");
-
-    // InputApplication
-
-    FIND_CLASS(gInputApplicationClassInfo.clazz, "com/android/server/InputApplication");
-
-    GET_FIELD_ID(gInputApplicationClassInfo.name, gInputApplicationClassInfo.clazz,
-            "name", "Ljava/lang/String;");
-
-    GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
-            gInputApplicationClassInfo.clazz,
-            "dispatchingTimeoutNanos", "J");
-
-    GET_FIELD_ID(gInputApplicationClassInfo.token, gInputApplicationClassInfo.clazz,
-            "token", "Ljava/lang/Object;");
-
     // KeyEvent
 
     FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent");
diff --git a/services/jni/com_android_server_InputWindow.cpp b/services/jni/com_android_server_InputWindow.cpp
new file mode 100644
index 0000000..a4609a0
--- /dev/null
+++ b/services/jni/com_android_server_InputWindow.cpp
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#define LOG_TAG "InputWindow"
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include <android_view_InputChannel.h>
+#include "com_android_server_InputWindow.h"
+#include "com_android_server_InputWindowHandle.h"
+
+namespace android {
+
+static struct {
+    jclass clazz;
+
+    jfieldID inputWindowHandle;
+    jfieldID inputChannel;
+    jfieldID name;
+    jfieldID layoutParamsFlags;
+    jfieldID layoutParamsType;
+    jfieldID dispatchingTimeoutNanos;
+    jfieldID frameLeft;
+    jfieldID frameTop;
+    jfieldID frameRight;
+    jfieldID frameBottom;
+    jfieldID visibleFrameLeft;
+    jfieldID visibleFrameTop;
+    jfieldID visibleFrameRight;
+    jfieldID visibleFrameBottom;
+    jfieldID touchableAreaLeft;
+    jfieldID touchableAreaTop;
+    jfieldID touchableAreaRight;
+    jfieldID touchableAreaBottom;
+    jfieldID visible;
+    jfieldID canReceiveKeys;
+    jfieldID hasFocus;
+    jfieldID hasWallpaper;
+    jfieldID paused;
+    jfieldID layer;
+    jfieldID ownerPid;
+    jfieldID ownerUid;
+} gInputWindowClassInfo;
+
+
+// --- Global functions ---
+
+void android_server_InputWindow_toNative(
+        JNIEnv* env, jobject inputWindowObj, InputWindow* outInputWindow) {
+    jobject inputWindowHandleObj = env->GetObjectField(inputWindowObj,
+            gInputWindowClassInfo.inputWindowHandle);
+    if (inputWindowHandleObj) {
+        outInputWindow->inputWindowHandle =
+                android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);
+        env->DeleteLocalRef(inputWindowHandleObj);
+    } else {
+        outInputWindow->inputWindowHandle = NULL;
+    }
+
+    jobject inputChannelObj = env->GetObjectField(inputWindowObj,
+            gInputWindowClassInfo.inputChannel);
+    if (inputChannelObj) {
+        outInputWindow->inputChannel =
+                android_view_InputChannel_getInputChannel(env, inputChannelObj);
+        env->DeleteLocalRef(inputChannelObj);
+    } else {
+        outInputWindow->inputChannel = NULL;
+    }
+
+    jstring nameObj = jstring(env->GetObjectField(inputWindowObj,
+            gInputWindowClassInfo.name));
+    if (nameObj) {
+        const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
+        outInputWindow->name.setTo(nameStr);
+        env->ReleaseStringUTFChars(nameObj, nameStr);
+        env->DeleteLocalRef(nameObj);
+    } else {
+        LOGE("InputWindow.name should not be null.");
+        outInputWindow->name.setTo("unknown");
+    }
+
+    outInputWindow->layoutParamsFlags = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.layoutParamsFlags);
+    outInputWindow->layoutParamsType = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.layoutParamsType);
+    outInputWindow->dispatchingTimeout = env->GetLongField(inputWindowObj,
+            gInputWindowClassInfo.dispatchingTimeoutNanos);
+    outInputWindow->frameLeft = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.frameLeft);
+    outInputWindow->frameTop = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.frameTop);
+    outInputWindow->frameRight = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.frameRight);
+    outInputWindow->frameBottom = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.frameBottom);
+    outInputWindow->visibleFrameLeft = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.visibleFrameLeft);
+    outInputWindow->visibleFrameTop = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.visibleFrameTop);
+    outInputWindow->visibleFrameRight = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.visibleFrameRight);
+    outInputWindow->visibleFrameBottom = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.visibleFrameBottom);
+    outInputWindow->touchableAreaLeft = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.touchableAreaLeft);
+    outInputWindow->touchableAreaTop = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.touchableAreaTop);
+    outInputWindow->touchableAreaRight = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.touchableAreaRight);
+    outInputWindow->touchableAreaBottom = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.touchableAreaBottom);
+    outInputWindow->visible = env->GetBooleanField(inputWindowObj,
+            gInputWindowClassInfo.visible);
+    outInputWindow->canReceiveKeys = env->GetBooleanField(inputWindowObj,
+            gInputWindowClassInfo.canReceiveKeys);
+    outInputWindow->hasFocus = env->GetBooleanField(inputWindowObj,
+            gInputWindowClassInfo.hasFocus);
+    outInputWindow->hasWallpaper = env->GetBooleanField(inputWindowObj,
+            gInputWindowClassInfo.hasWallpaper);
+    outInputWindow->paused = env->GetBooleanField(inputWindowObj,
+            gInputWindowClassInfo.paused);
+    outInputWindow->layer = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.layer);
+    outInputWindow->ownerPid = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.ownerPid);
+    outInputWindow->ownerUid = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.ownerUid);
+}
+
+
+// --- JNI ---
+
+#define FIND_CLASS(var, className) \
+        var = env->FindClass(className); \
+        LOG_FATAL_IF(! var, "Unable to find class " className); \
+        var = jclass(env->NewGlobalRef(var));
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
+int register_android_server_InputWindow(JNIEnv* env) {
+    FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow");
+
+    GET_FIELD_ID(gInputWindowClassInfo.inputWindowHandle, gInputWindowClassInfo.clazz,
+            "inputWindowHandle", "Lcom/android/server/InputWindowHandle;");
+
+    GET_FIELD_ID(gInputWindowClassInfo.inputChannel, gInputWindowClassInfo.clazz,
+            "inputChannel", "Landroid/view/InputChannel;");
+
+    GET_FIELD_ID(gInputWindowClassInfo.name, gInputWindowClassInfo.clazz,
+            "name", "Ljava/lang/String;");
+
+    GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, gInputWindowClassInfo.clazz,
+            "layoutParamsFlags", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, gInputWindowClassInfo.clazz,
+            "layoutParamsType", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, gInputWindowClassInfo.clazz,
+            "dispatchingTimeoutNanos", "J");
+
+    GET_FIELD_ID(gInputWindowClassInfo.frameLeft, gInputWindowClassInfo.clazz,
+            "frameLeft", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
+            "frameTop", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.frameRight, gInputWindowClassInfo.clazz,
+            "frameRight", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.frameBottom, gInputWindowClassInfo.clazz,
+            "frameBottom", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameLeft, gInputWindowClassInfo.clazz,
+            "visibleFrameLeft", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameTop, gInputWindowClassInfo.clazz,
+            "visibleFrameTop", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameRight, gInputWindowClassInfo.clazz,
+            "visibleFrameRight", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameBottom, gInputWindowClassInfo.clazz,
+            "visibleFrameBottom", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
+            "touchableAreaLeft", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.touchableAreaTop, gInputWindowClassInfo.clazz,
+            "touchableAreaTop", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.touchableAreaRight, gInputWindowClassInfo.clazz,
+            "touchableAreaRight", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.touchableAreaBottom, gInputWindowClassInfo.clazz,
+            "touchableAreaBottom", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.visible, gInputWindowClassInfo.clazz,
+            "visible", "Z");
+
+    GET_FIELD_ID(gInputWindowClassInfo.canReceiveKeys, gInputWindowClassInfo.clazz,
+            "canReceiveKeys", "Z");
+
+    GET_FIELD_ID(gInputWindowClassInfo.hasFocus, gInputWindowClassInfo.clazz,
+            "hasFocus", "Z");
+
+    GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, gInputWindowClassInfo.clazz,
+            "hasWallpaper", "Z");
+
+    GET_FIELD_ID(gInputWindowClassInfo.paused, gInputWindowClassInfo.clazz,
+            "paused", "Z");
+
+    GET_FIELD_ID(gInputWindowClassInfo.layer, gInputWindowClassInfo.clazz,
+            "layer", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.ownerPid, gInputWindowClassInfo.clazz,
+            "ownerPid", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.ownerUid, gInputWindowClassInfo.clazz,
+            "ownerUid", "I");
+    return 0;
+}
+
+} /* namespace android */
diff --git a/services/jni/com_android_server_InputWindow.h b/services/jni/com_android_server_InputWindow.h
new file mode 100644
index 0000000..eaf7bde
--- /dev/null
+++ b/services/jni/com_android_server_InputWindow.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef _ANDROID_SERVER_INPUT_WINDOW_H
+#define _ANDROID_SERVER_INPUT_WINDOW_H
+
+#include <input/InputWindow.h>
+
+#include "JNIHelp.h"
+#include "jni.h"
+
+namespace android {
+
+extern void android_server_InputWindow_toNative(
+        JNIEnv* env, jobject inputWindowObj, InputWindow* outInputWindow);
+
+} // namespace android
+
+#endif // _ANDROID_SERVER_INPUT_WINDOW_H
diff --git a/services/jni/com_android_server_InputWindowHandle.cpp b/services/jni/com_android_server_InputWindowHandle.cpp
new file mode 100644
index 0000000..4d66212
--- /dev/null
+++ b/services/jni/com_android_server_InputWindowHandle.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#define LOG_TAG "InputWindowHandle"
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include <android_runtime/AndroidRuntime.h>
+#include <utils/threads.h>
+
+#include "com_android_server_InputWindowHandle.h"
+#include "com_android_server_InputApplicationHandle.h"
+
+namespace android {
+
+static struct {
+    jclass clazz;
+
+    jfieldID ptr;
+    jfieldID inputApplicationHandle;
+} gInputWindowHandleClassInfo;
+
+static Mutex gHandleMutex;
+
+
+// --- NativeInputWindowHandle ---
+
+NativeInputWindowHandle::NativeInputWindowHandle(
+        const sp<InputApplicationHandle>& inputApplicationHandle, jweak objWeak) :
+        InputWindowHandle(inputApplicationHandle),
+        mObjWeak(objWeak) {
+}
+
+NativeInputWindowHandle::~NativeInputWindowHandle() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->DeleteWeakGlobalRef(mObjWeak);
+}
+
+jobject NativeInputWindowHandle::getInputWindowHandleObjLocalRef(JNIEnv* env) {
+    return env->NewLocalRef(mObjWeak);
+}
+
+
+// --- Global functions ---
+
+sp<NativeInputWindowHandle> android_server_InputWindowHandle_getHandle(
+        JNIEnv* env, jobject inputWindowHandleObj) {
+    if (!inputWindowHandleObj) {
+        return NULL;
+    }
+
+    AutoMutex _l(gHandleMutex);
+
+    int ptr = env->GetIntField(inputWindowHandleObj, gInputWindowHandleClassInfo.ptr);
+    NativeInputWindowHandle* handle;
+    if (ptr) {
+        handle = reinterpret_cast<NativeInputWindowHandle*>(ptr);
+    } else {
+        jobject inputApplicationHandleObj = env->GetObjectField(inputWindowHandleObj,
+                gInputWindowHandleClassInfo.inputApplicationHandle);
+        sp<InputApplicationHandle> inputApplicationHandle =
+                android_server_InputApplicationHandle_getHandle(env, inputApplicationHandleObj);
+        env->DeleteLocalRef(inputApplicationHandleObj);
+
+        jweak objWeak = env->NewWeakGlobalRef(inputWindowHandleObj);
+        handle = new NativeInputWindowHandle(inputApplicationHandle, objWeak);
+        handle->incStrong(inputWindowHandleObj);
+        env->SetIntField(inputWindowHandleObj, gInputWindowHandleClassInfo.ptr,
+                reinterpret_cast<int>(handle));
+    }
+    return handle;
+}
+
+
+// --- JNI ---
+
+static void android_server_InputWindowHandle_nativeDispose(JNIEnv* env, jobject obj) {
+    AutoMutex _l(gHandleMutex);
+
+    int ptr = env->GetIntField(obj, gInputWindowHandleClassInfo.ptr);
+    if (ptr) {
+        env->SetIntField(obj, gInputWindowHandleClassInfo.ptr, 0);
+
+        NativeInputWindowHandle* handle = reinterpret_cast<NativeInputWindowHandle*>(ptr);
+        handle->decStrong(obj);
+    }
+}
+
+
+static JNINativeMethod gInputWindowHandleMethods[] = {
+    /* name, signature, funcPtr */
+    { "nativeDispose", "()V",
+            (void*) android_server_InputWindowHandle_nativeDispose },
+};
+
+#define FIND_CLASS(var, className) \
+        var = env->FindClass(className); \
+        LOG_FATAL_IF(! var, "Unable to find class " className); \
+        var = jclass(env->NewGlobalRef(var));
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
+int register_android_server_InputWindowHandle(JNIEnv* env) {
+    int res = jniRegisterNativeMethods(env, "com/android/server/InputWindowHandle",
+            gInputWindowHandleMethods, NELEM(gInputWindowHandleMethods));
+    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
+
+    FIND_CLASS(gInputWindowHandleClassInfo.clazz, "com/android/server/InputWindowHandle");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.ptr, gInputWindowHandleClassInfo.clazz,
+            "ptr", "I");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.inputApplicationHandle,
+            gInputWindowHandleClassInfo.clazz,
+            "inputApplicationHandle", "Lcom/android/server/InputApplicationHandle;");
+
+    return 0;
+}
+
+} /* namespace android */
diff --git a/services/jni/com_android_server_InputWindowHandle.h b/services/jni/com_android_server_InputWindowHandle.h
new file mode 100644
index 0000000..43f2a6b
--- /dev/null
+++ b/services/jni/com_android_server_InputWindowHandle.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef _ANDROID_SERVER_INPUT_WINDOW_HANDLE_H
+#define _ANDROID_SERVER_INPUT_WINDOW_HANDLE_H
+
+#include <input/InputWindow.h>
+
+#include "JNIHelp.h"
+#include "jni.h"
+
+namespace android {
+
+class NativeInputWindowHandle : public InputWindowHandle {
+public:
+    NativeInputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
+            jweak objWeak);
+    virtual ~NativeInputWindowHandle();
+
+    jobject getInputWindowHandleObjLocalRef(JNIEnv* env);
+
+private:
+    jweak mObjWeak;
+};
+
+
+extern sp<NativeInputWindowHandle> android_server_InputWindowHandle_getHandle(
+        JNIEnv* env, jobject inputWindowHandleObj);
+
+} // namespace android
+
+#endif // _ANDROID_SERVER_INPUT_WINDOW_HANDLE_H
diff --git a/services/jni/onload.cpp b/services/jni/onload.cpp
index cd4f0a4..bdd6d80 100644
--- a/services/jni/onload.cpp
+++ b/services/jni/onload.cpp
@@ -6,6 +6,10 @@
 namespace android {
 int register_android_server_AlarmManagerService(JNIEnv* env);
 int register_android_server_BatteryService(JNIEnv* env);
+int register_android_server_InputApplication(JNIEnv* env);
+int register_android_server_InputApplicationHandle(JNIEnv* env);
+int register_android_server_InputWindow(JNIEnv* env);
+int register_android_server_InputWindowHandle(JNIEnv* env);
 int register_android_server_InputManager(JNIEnv* env);
 int register_android_server_LightsService(JNIEnv* env);
 int register_android_server_PowerManagerService(JNIEnv* env);
@@ -28,6 +32,10 @@
     LOG_ASSERT(env, "Could not retrieve the env!");
 
     register_android_server_PowerManagerService(env);
+    register_android_server_InputApplication(env);
+    register_android_server_InputApplicationHandle(env);
+    register_android_server_InputWindow(env);
+    register_android_server_InputWindowHandle(env);
     register_android_server_InputManager(env);
     register_android_server_LightsService(env);
     register_android_server_AlarmManagerService(env);
diff --git a/tests/CoreTests/android/core/HeapTest.java b/tests/CoreTests/android/core/HeapTest.java
index 6116f5e..98cb28a 100644
--- a/tests/CoreTests/android/core/HeapTest.java
+++ b/tests/CoreTests/android/core/HeapTest.java
@@ -540,94 +540,4 @@
             objSize = (objSize * 4) / 5;
         }
     }
-
-    // TODO: flaky test
-    //@SmallTest
-    public void testExternalOomeLarge() {
-        /* Just shy of the typical max heap size so that it will actually
-         * try to allocate it instead of short-circuiting.
-         */
-        final int HUGE_SIZE = (16 * 1024 * 1024 - 32);
-
-        assertFalse(VMRuntime.getRuntime().trackExternalAllocation(HUGE_SIZE));
-    }
-
-    /**
-     * "Allocates" external memory in progressively smaller chunks until there's
-     * only roughly 16 bytes left.
-     *
-     * @return the number of bytes allocated
-     */
-    private long allocateMaxExternal() {
-        final VMRuntime runtime = VMRuntime.getRuntime();
-        final int SIXTEEN_MB = (16 * 1024 * 1024);
-        final int MIN_SIZE = 16;
-        long totalAllocated = 0;
-        boolean success;
-
-        success = false;
-        try {
-            /* "Allocate" progressively smaller chunks to "fill up" the entire heap.
-             */
-            int objSize = 1 * 1024 * 1024;
-            while (objSize >= MIN_SIZE) {
-                boolean sawFailure = false;
-                for (int i = 0; i < SIXTEEN_MB / objSize; i++) {
-                    if (runtime.trackExternalAllocation(objSize)) {
-                        totalAllocated += objSize;
-                    } else {
-                        sawFailure = true;
-                        break;
-                    }
-                }
-
-                if (!sawFailure) {
-                    throw new RuntimeException("Test failed: " +
-                            "no failure while filling heap");
-                }
-
-                objSize = (objSize * 4) / 5;
-            }
-            success = true;
-        } finally {
-            if (!success) {
-                runtime.trackExternalFree(totalAllocated);
-                totalAllocated = 0;
-            }
-        }
-        return totalAllocated;
-    }
-
-    public void xxtest00ExternalOomeSmall() {
-        VMRuntime.getRuntime().trackExternalFree(allocateMaxExternal());
-    }
-
-    /**
-     * Allocates as much external memory as possible, then allocates from the heap
-     * until an OOME is caught.
-     *
-     * It's nice to run this test while the real heap is small, hence the '00' in its
-     * name to force it to run before testOomeSmall().
-     */
-    public void xxtest00CombinedOomeSmall() {
-        long totalAllocated = 0;
-        boolean sawEx = false;
-        try {
-            totalAllocated = allocateMaxExternal();
-            LinkedList<Object> list = new LinkedList<Object>();
-            try {
-                while (true) {
-                    list.add((Object)new byte[8192]);
-                }
-                /*NOTREACHED*/
-            } catch (OutOfMemoryError oom) {
-                sawEx = true;
-            }
-        } finally {
-            VMRuntime.getRuntime().trackExternalFree(totalAllocated);
-        }
-        assertTrue(sawEx);
-    }
-
-    //TODO: test external alloc debugging/inspection
 }
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java
index 91e3b84..8ca842e 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java
@@ -23,6 +23,7 @@
 import android.graphics.BitmapShader;
 import android.graphics.Canvas;
 import android.graphics.Paint;
+import android.graphics.drawable.ColorDrawable;
 import android.os.Bundle;
 import android.view.View;
 
@@ -31,7 +32,9 @@
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        getWindow().setBackgroundDrawable(new ColorDrawable(0xffffffff));
         final LinesView view = new LinesView(this);
+        //view.setAlpha(0.80f);
         setContentView(view);
     }
 
@@ -91,8 +94,6 @@
         protected void onDraw(Canvas canvas) {
             super.onDraw(canvas);
 
-            canvas.drawARGB(255, 255, 255, 255);
-
             canvas.save();
             canvas.translate(100.0f, 20.0f);
 
diff --git a/tests/StatusBar/AndroidManifest.xml b/tests/StatusBar/AndroidManifest.xml
index ddb756b..81442bf 100644
--- a/tests/StatusBar/AndroidManifest.xml
+++ b/tests/StatusBar/AndroidManifest.xml
@@ -5,6 +5,7 @@
     <uses-permission android:name="android.permission.STATUS_BAR" />
     <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
     <uses-permission android:name="android.permission.VIBRATE" />
+    <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
 
     <application>
         <activity android:name="StatusBarTest" android:label="_StatusBar">
diff --git a/tests/StatusBar/src/com/android/statusbartest/PowerTest.java b/tests/StatusBar/src/com/android/statusbartest/PowerTest.java
index 92d5bee..31a1cf5a 100644
--- a/tests/StatusBar/src/com/android/statusbartest/PowerTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/PowerTest.java
@@ -26,6 +26,8 @@
 import android.os.IPowerManager;
 import android.widget.ListView;
 import android.content.Intent;
+import android.content.ComponentName;
+import android.content.pm.PackageManager;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.StatusBarManager;
@@ -66,6 +68,24 @@
         return mTests;
     }
     private Test[] mTests = new Test[] {
+        new Test("Enable settings widget") {
+            public void run() {
+                PackageManager pm = getPackageManager();
+                pm.setComponentEnabledSetting(new ComponentName("com.android.settings",
+                            "com.android.settings.widget.SettingsAppWidgetProvider"),
+                        PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
+
+            }
+        },
+        new Test("Disable settings widget") {
+            public void run() {
+                PackageManager pm = getPackageManager();
+                pm.setComponentEnabledSetting(new ComponentName("com.android.settings",
+                            "com.android.settings.widget.SettingsAppWidgetProvider"),
+                        PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0);
+
+            }
+        },
         new Test("Enable proximity") {
             public void run() {
                 mProx.acquire();
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
index c57aef6..096498b 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
@@ -351,7 +351,8 @@
                 If the exception happened on open, bm will be null.
                 If it happened on close, bm is still valid.
             */
-            Bridge.getLog().error(null, e);
+            Bridge.getLog().error(null,
+                    String.format("Error decoding bitmap of id 0x%x", id), e);
         } finally {
             try {
                 if (is != null) is.close();
diff --git a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
index e9fb30a..5524f4f 100644
--- a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
@@ -73,7 +73,7 @@
             oos = new ObjectOutputStream(baos);
             oos.writeObject(chunk);
         } catch (IOException e) {
-            Bridge.getLog().error("Failed to serialize NinePatchChunk.", e);
+            Bridge.getLog().error(null, "Failed to serialize NinePatchChunk.", e);
             return null;
         } finally {
             if (oos != null) {
@@ -196,10 +196,10 @@
                     sChunkCache.put(array, new SoftReference<NinePatchChunk>(chunk));
                 }
             } catch (IOException e) {
-                Bridge.getLog().error("Failed to deserialize NinePatchChunk content.", e);
+                Bridge.getLog().error(null, "Failed to deserialize NinePatchChunk content.", e);
                 return null;
             } catch (ClassNotFoundException e) {
-                Bridge.getLog().error("Failed to deserialize NinePatchChunk class.", e);
+                Bridge.getLog().error(null, "Failed to deserialize NinePatchChunk class.", e);
                 return null;
             } finally {
                 if (ois != null) {
diff --git a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
index bc13b52..33c2aed 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
@@ -135,6 +135,123 @@
 
     // ---- native methods ----
 
+    /*package*/ static boolean isEmpty(Region thisRegion) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return true;
+        }
+
+        return regionDelegate.mArea.isEmpty();
+    }
+
+    /*package*/ static boolean isRect(Region thisRegion) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return true;
+        }
+
+        return regionDelegate.mArea.isRectangular();
+    }
+
+    /*package*/ static boolean isComplex(Region thisRegion) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return true;
+        }
+
+        return regionDelegate.mArea.isSingular() == false;
+    }
+
+    /*package*/ static boolean contains(Region thisRegion, int x, int y) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return false;
+        }
+
+        return regionDelegate.mArea.contains(x, y);
+    }
+
+    /*package*/ static boolean quickContains(Region thisRegion,
+            int left, int top, int right, int bottom) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return false;
+        }
+
+        return regionDelegate.mArea.isRectangular() &&
+                regionDelegate.mArea.contains(left, top, right - left, bottom - top);
+    }
+
+    /*package*/ static boolean quickReject(Region thisRegion,
+            int left, int top, int right, int bottom) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return false;
+        }
+
+        return regionDelegate.mArea.isEmpty() ||
+                regionDelegate.mArea.intersects(left, top, right - left, bottom - top) == false;
+    }
+
+    /*package*/ static boolean quickReject(Region thisRegion, Region rgn) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return false;
+        }
+
+        Region_Delegate targetRegionDelegate = sManager.getDelegate(rgn.mNativeRegion);
+        if (targetRegionDelegate == null) {
+            return false;
+        }
+
+        return regionDelegate.mArea.isEmpty() ||
+                regionDelegate.mArea.getBounds().intersects(
+                        targetRegionDelegate.mArea.getBounds()) == false;
+
+    }
+
+    /*package*/ static void translate(Region thisRegion, int dx, int dy, Region dst) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return;
+        }
+
+        Region_Delegate targetRegionDelegate = sManager.getDelegate(dst.mNativeRegion);
+        if (targetRegionDelegate == null) {
+            return;
+        }
+
+        if (regionDelegate.mArea.isEmpty()) {
+            targetRegionDelegate.mArea = new Area();
+        } else {
+            targetRegionDelegate.mArea = new Area(regionDelegate.mArea);
+            AffineTransform mtx = new AffineTransform();
+            mtx.translate(dx, dy);
+            targetRegionDelegate.mArea.transform(mtx);
+        }
+    }
+
+    /*package*/ static void scale(Region thisRegion, float scale, Region dst) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return;
+        }
+
+        Region_Delegate targetRegionDelegate = sManager.getDelegate(dst.mNativeRegion);
+        if (targetRegionDelegate == null) {
+            return;
+        }
+
+        if (regionDelegate.mArea.isEmpty()) {
+            targetRegionDelegate.mArea = new Area();
+        } else {
+            targetRegionDelegate.mArea = new Area(regionDelegate.mArea);
+            AffineTransform mtx = new AffineTransform();
+            mtx.scale(scale, scale);
+            targetRegionDelegate.mArea.transform(mtx);
+        }
+    }
+
     /*package*/ static int nativeConstructor() {
         Region_Delegate newDelegate = new Region_Delegate();
         return sManager.addDelegate(newDelegate);
diff --git a/tools/layoutlib/bridge/src/com/android/internal/util/XmlUtils_Delegate.java b/tools/layoutlib/bridge/src/com/android/internal/util/XmlUtils_Delegate.java
new file mode 100644
index 0000000..7fa1679
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/internal/util/XmlUtils_Delegate.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link XmlUtils}
+ *
+ * Through the layoutlib_create tool, the original  methods of XmlUtils have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ */
+public class XmlUtils_Delegate {
+    /*package*/ static final int convertValueToInt(CharSequence charSeq, int defaultValue) {
+        if (null == charSeq)
+            return defaultValue;
+
+        String nm = charSeq.toString();
+
+        // This code is copied from the original implementation. The issue is that
+        // The Dalvik libraries are able to handle Integer.parse("XXXXXXXX", 16) where XXXXXXX
+        // is > 80000000 but the Java VM cannot.
+
+        int sign = 1;
+        int index = 0;
+        int len = nm.length();
+        int base = 10;
+
+        if ('-' == nm.charAt(0)) {
+            sign = -1;
+            index++;
+        }
+
+        if ('0' == nm.charAt(index)) {
+            //  Quick check for a zero by itself
+            if (index == (len - 1))
+                return 0;
+
+            char c = nm.charAt(index + 1);
+
+            if ('x' == c || 'X' == c) {
+                index += 2;
+                base = 16;
+            } else {
+                index++;
+                base = 8;
+            }
+        }
+        else if ('#' == nm.charAt(index)) {
+            index++;
+            base = 16;
+        }
+
+        return ((int)Long.parseLong(nm.substring(index), base)) * sign;
+    }
+}
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 e1bf925..0990cef 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -142,16 +142,6 @@
         }
 
         @Override
-        public void error(String tag, Throwable t) {
-            String message = t.getMessage();
-            if (message == null) {
-                message = t.getClass().getName();
-            }
-
-            System.err.println(message);
-        }
-
-        @Override
         public void error(String tag, String message, Throwable throwable) {
             System.err.println(message);
         }
@@ -195,7 +185,8 @@
                 Capability.RENDER,
                 Capability.EMBEDDED_LAYOUT,
                 Capability.VIEW_MANIPULATION,
-                Capability.ANIMATE);
+                Capability.PLAY_ANIMATION,
+                Capability.ANIMATED_VIEW_MANIPULATION);
 
 
         BridgeAssetManager.initSystem();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java
index 791e53b..194687e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java
@@ -48,6 +48,7 @@
 
     public final static String PREFIX_ANDROID = "android:";
 
+    public final static String RES_ANIMATOR = "animator";
     public final static String RES_STYLE = "style";
     public final static String RES_ATTR = "attr";
     public final static String RES_DIMEN = "dimen";
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 7269227..fb79473 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -92,7 +92,7 @@
 
     // cache for TypedArray generated from IStyleResourceValue object
     private Map<int[], Map<Integer, TypedArray>> mTypedArrayCache;
-    private BridgeInflater mInflater;
+    private BridgeInflater mBridgeInflater;
 
     private final IProjectCallback mProjectCallback;
     private BridgeContentResolver mContentResolver;
@@ -160,7 +160,7 @@
     }
 
     public void setBridgeInflater(BridgeInflater inflater) {
-        mInflater = inflater;
+        mBridgeInflater = inflater;
     }
 
     public void addViewKey(View view, Object viewKey) {
@@ -221,7 +221,7 @@
 
     @Override
     public LayoutInflater getLayoutInflater() {
-        return mInflater;
+        return mBridgeInflater;
     }
 
     // ------------ Context methods
@@ -244,7 +244,7 @@
     @Override
     public Object getSystemService(String service) {
         if (LAYOUT_INFLATER_SERVICE.equals(service)) {
-            return mInflater;
+            return mBridgeInflater;
         }
 
         // AutoCompleteTextView and MultiAutoCompleteTextView want a window
@@ -493,12 +493,12 @@
     /**
      * Resolves the value of a resource, if the value references a theme or resource value.
      * <p/>
-     * This method ensures that it returns a {@link IResourceValue} object that does not
+     * This method ensures that it returns a {@link ResourceValue} object that does not
      * reference another resource.
      * If the resource cannot be resolved, it returns <code>null</code>.
      * <p/>
      * If a value that does not need to be resolved is given, the method will return a new
-     * instance of IResourceValue that contains the input value.
+     * instance of {@link ResourceValue} that contains the input value.
      *
      * @param type the type of the resource
      * @param name the name of the attribute containing this value.
@@ -510,11 +510,11 @@
             return null;
         }
 
-        // get the IResourceValue referenced by this value
+        // get the ResourceValue referenced by this value
         ResourceValue resValue = findResValue(value, false /*forceFrameworkOnly*/);
 
         // if resValue is null, but value is not null, this means it was not a reference.
-        // we return the name/value wrapper in a IResourceValue. the isFramework flag doesn't
+        // we return the name/value wrapper in a ResourceValue. the isFramework flag doesn't
         // matter.
         if (resValue == null) {
             return new ResourceValue(type, name, value, false /*isFramework*/);
@@ -525,9 +525,9 @@
     }
 
     /**
-     * Returns the {@link IResourceValue} referenced by the value of <var>value</var>.
+     * Returns the {@link ResourceValue} referenced by the value of <var>value</var>.
      * <p/>
-     * This method ensures that it returns a {@link IResourceValue} object that does not
+     * This method ensures that it returns a {@link ResourceValue} object that does not
      * reference another resource.
      * If the resource cannot be resolved, it returns <code>null</code>.
      * <p/>
@@ -535,7 +535,7 @@
      * value.
      *
      * @param value the value containing the reference to resolve.
-     * @return a {@link IResourceValue} object or <code>null</code>
+     * @return a {@link ResourceValue} object or <code>null</code>
      */
     public ResourceValue resolveResValue(ResourceValue value) {
         if (value == null) {
@@ -547,7 +547,7 @@
             return value;
         }
 
-        // else attempt to find another IResourceValue referenced by this one.
+        // else attempt to find another ResourceValue referenced by this one.
         ResourceValue resolvedValue = findResValue(value.getValue(), value.isFramework());
 
         // if the value did not reference anything, then we simply return the input value
@@ -560,7 +560,7 @@
     }
 
     /**
-     * Searches for, and returns a {@link IResourceValue} by its reference.
+     * Searches for, and returns a {@link ResourceValue} by its reference.
      * <p/>
      * The reference format can be:
      * <pre>@resType/resName</pre>
@@ -577,7 +577,7 @@
      * @param reference the resource reference to search for.
      * @param forceFrameworkOnly if true all references are considered to be toward framework
      *      resource even if the reference does not include the android: prefix.
-     * @return a {@link IResourceValue} or <code>null</code>.
+     * @return a {@link ResourceValue} or <code>null</code>.
      */
     ResourceValue findResValue(String reference, boolean forceFrameworkOnly) {
         if (reference == null) {
@@ -591,7 +591,7 @@
 
             boolean frameworkOnly = false;
 
-            // eleminate the prefix from the string
+            // eliminate the prefix from the string
             if (reference.startsWith(BridgeConstants.PREFIX_ANDROID_THEME_REF)) {
                 frameworkOnly = true;
                 reference = reference.substring(BridgeConstants.PREFIX_ANDROID_THEME_REF.length());
@@ -670,14 +670,14 @@
     }
 
     /**
-     * Searches for, and returns a {@link IResourceValue} by its name, and type.
+     * Searches for, and returns a {@link ResourceValue} by its name, and type.
      * @param resType the type of the resource
      * @param resName  the name of the resource
      * @param frameworkOnly if <code>true</code>, the method does not search in the
      * project resources
      */
     private ResourceValue findResValue(String resType, String resName, boolean frameworkOnly) {
-        // map of IResouceValue for the given type
+        // map of ResouceValue for the given type
         Map<String, ResourceValue> typeMap;
 
         // if allowed, search in the project resources first.
@@ -701,6 +701,13 @@
         }
 
         // didn't find the resource anywhere.
+        // This is normal if the resource is an ID that is generated automatically.
+        // For other resources, we output a warning
+        if ("+id".equals(resType) == false && "+android:id".equals(resType) == false) { //$NON-NLS-1$ //$NON-NLS-2$
+            Bridge.getLog().warning("resources", //$NON-NLS-1$
+                    "Couldn't resolve resource @" +
+                    (frameworkOnly ? "android:" : "") + resType + "/" + resName);
+        }
         return null;
     }
 
@@ -739,11 +746,11 @@
     }
 
     /**
-     * Returns the {@link IResourceValue} matching a given name in a given style. If the
+     * Returns the {@link ResourceValue} matching a given name in a given style. If the
      * item is not directly available in the style, the method looks in its parent style.
      * @param style the style to search in
      * @param itemName the name of the item to search for.
-     * @return the {@link IResourceValue} object or <code>null</code>
+     * @return the {@link ResourceValue} object or <code>null</code>
      */
     public ResourceValue findItemInStyle(StyleResourceValue style, String itemName) {
         ResourceValue item = style.findValue(itemName);
@@ -871,8 +878,8 @@
         return null;
     }
 
-    int getFrameworkIdValue(String idName, int defValue) {
-        Integer value = Bridge.getResourceValue(BridgeConstants.RES_ID, idName);
+    int getFrameworkResourceValue(String resType, String resName, int defValue) {
+        Integer value = Bridge.getResourceValue(resType, resName);
         if (value != null) {
             return value.intValue();
         }
@@ -880,9 +887,9 @@
         return defValue;
     }
 
-    int getProjectIdValue(String idName, int defValue) {
+    int getProjectResourceValue(String resType, String resName, int defValue) {
         if (mProjectCallback != null) {
-            Integer value = mProjectCallback.getResourceValue(BridgeConstants.RES_ID, idName);
+            Integer value = mProjectCallback.getResourceValue(resType, resName);
             if (value != null) {
                 return value.intValue();
             }
@@ -1303,4 +1310,15 @@
     public Context getApplicationContext() {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public void startActivities(Intent[] arg0) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public boolean isRestricted() {
+        return false;
+    }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java
index 1b59621..36aa335 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java
@@ -178,8 +178,10 @@
 
                         return inflate(bridgeParser, root);
                     } catch (Exception e) {
-                        Bridge.getLog().error(null, e);
-                        // return null below.
+                        Bridge.getLog().error(null,
+                                "Failed to parse file " + f.getAbsolutePath(), e);
+
+                        return null;
                     }
                 }
             }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
index 2ea5281..a56800c 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
@@ -43,7 +43,6 @@
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
-import java.io.IOException;
 import java.io.InputStream;
 
 /**
@@ -173,14 +172,13 @@
 
                         return ColorStateList.createFromXml(this,
                                 new BridgeXmlBlockParser(parser, mContext, resValue.isFramework()));
-                    } catch (XmlPullParserException e) {
-                        Bridge.getLog().error(null, e);
-                    } catch (FileNotFoundException e) {
-                        // will not happen, since we pre-check
-                    } catch (IOException e) {
-                        Bridge.getLog().error(null, e);
-                    }
+                    } catch (Exception e) {
+                        // this is an error and not warning since the file existence is checked before
+                        // attempting to parse it.
+                        Bridge.getLog().error(null, "Failed to parse file " + value, e);
 
+                        return null;
+                    }
                 } else {
                     // try to load the color state list from an int
                     try {
@@ -245,7 +243,8 @@
                     return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
                 }
             } catch (XmlPullParserException e) {
-                Bridge.getLog().error(null, e);
+                Bridge.getLog().error(null,
+                        "Failed to configure parser for " + value.getValue(), e);
                 // we'll return null below.
             } catch (FileNotFoundException e) {
                 // this shouldn't happen since we check above.
@@ -279,7 +278,8 @@
                     return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
                 }
             } catch (XmlPullParserException e) {
-                Bridge.getLog().error(null, e);
+                Bridge.getLog().error(null,
+                        "Failed to configure parser for " + value.getValue(), e);
                 // we'll return null below.
             } catch (FileNotFoundException e) {
                 // this shouldn't happen since we check above.
@@ -294,7 +294,6 @@
         return null;
     }
 
-
     @Override
     public TypedArray obtainAttributes(AttributeSet set, int[] attrs) {
         return mContext.obtainStyledAttributes(set, attrs);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
index 6ae7e03..7f11897 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
@@ -43,25 +43,25 @@
  */
 public final class BridgeTypedArray extends TypedArray {
 
-    private BridgeResources mResources;
+    private BridgeResources mBridgeResources;
     private BridgeContext mContext;
-    private ResourceValue[] mData;
+    private ResourceValue[] mResourceData;
     private String[] mNames;
     private final boolean mPlatformFile;
 
     public BridgeTypedArray(BridgeResources resources, BridgeContext context, int len,
             boolean platformFile) {
         super(null, null, null, 0);
-        mResources = resources;
+        mBridgeResources = resources;
         mContext = context;
         mPlatformFile = platformFile;
-        mData = new ResourceValue[len];
+        mResourceData = new ResourceValue[len];
         mNames = new String[len];
     }
 
     /** A bridge-specific method that sets a value in the type array */
     public void bridgeSetValue(int index, String name, ResourceValue value) {
-        mData[index] = value;
+        mResourceData[index] = value;
         mNames[index] = name;
     }
 
@@ -75,7 +75,7 @@
         // fills TypedArray.mIndices which is used to implement getIndexCount/getIndexAt
         // first count the array size
         int count = 0;
-        for (ResourceValue data : mData) {
+        for (ResourceValue data : mResourceData) {
             if (data != null) {
                 count++;
             }
@@ -87,8 +87,8 @@
 
         // fill the array with the indices.
         int index = 1;
-        for (int i = 0 ; i < mData.length ; i++) {
-            if (mData[i] != null) {
+        for (int i = 0 ; i < mResourceData.length ; i++) {
+            if (mResourceData[i] != null) {
                 mIndices[index++] = i;
             }
         }
@@ -99,7 +99,7 @@
      */
     @Override
     public int length() {
-        return mData.length;
+        return mResourceData.length;
     }
 
     /**
@@ -107,7 +107,7 @@
      */
     @Override
     public Resources getResources() {
-        return mResources;
+        return mBridgeResources;
     }
 
     /**
@@ -120,9 +120,9 @@
      */
     @Override
     public CharSequence getText(int index) {
-        if (mData[index] != null) {
+        if (mResourceData[index] != null) {
             // FIXME: handle styled strings!
-            return mData[index].getValue();
+            return mResourceData[index].getValue();
         }
 
         return null;
@@ -138,8 +138,8 @@
      */
     @Override
     public String getString(int index) {
-        if (mData[index] != null) {
-            return mData[index].getValue();
+        if (mResourceData[index] != null) {
+            return mResourceData[index].getValue();
         }
 
         return null;
@@ -155,11 +155,11 @@
      */
     @Override
     public boolean getBoolean(int index, boolean defValue) {
-        if (mData[index] == null) {
+        if (mResourceData[index] == null) {
             return defValue;
         }
 
-        String s = mData[index].getValue();
+        String s = mResourceData[index].getValue();
         if (s != null) {
             return XmlUtils.convertValueToBoolean(s, defValue);
         }
@@ -177,11 +177,11 @@
      */
     @Override
     public int getInt(int index, int defValue) {
-        if (mData[index] == null) {
+        if (mResourceData[index] == null) {
             return defValue;
         }
 
-        String s = mData[index].getValue();
+        String s = mResourceData[index].getValue();
 
         try {
             return (s == null) ? defValue : XmlUtils.convertValueToInt(s, defValue);
@@ -225,11 +225,11 @@
      */
     @Override
     public float getFloat(int index, float defValue) {
-        if (mData[index] == null) {
+        if (mResourceData[index] == null) {
             return defValue;
         }
 
-        String s = mData[index].getValue();
+        String s = mResourceData[index].getValue();
 
         if (s != null) {
             try {
@@ -259,11 +259,11 @@
      */
     @Override
     public int getColor(int index, int defValue) {
-        if (mData[index] == null) {
+        if (mResourceData[index] == null) {
             return defValue;
         }
 
-        String s = mData[index].getValue();
+        String s = mResourceData[index].getValue();
         try {
             return ResourceHelper.getColor(s);
         } catch (NumberFormatException e) {
@@ -288,11 +288,11 @@
      */
     @Override
     public ColorStateList getColorStateList(int index) {
-        if (mData[index] == null) {
+        if (mResourceData[index] == null) {
             return null;
         }
 
-        String value = mData[index].getValue();
+        String value = mResourceData[index].getValue();
 
         if (value == null) {
             return null;
@@ -322,17 +322,18 @@
         } catch (Exception e) {
             // this is an error and not warning since the file existence is checked before
             // attempting to parse it.
-            Bridge.getLog().error(null, e);
+            Bridge.getLog().error(null, "Failed to parse file " + value, e);
 
-            // return null below.
+            return null;
         }
 
         // looks like were unable to resolve the color value.
-        assert false;
         Bridge.getLog().warning(null, String.format(
                 "Unable to resolve color value \"%1$s\" in attribute \"%2$s\"",
                 value, mNames[index]));
 
+        assert false;
+
         return null;
     }
 
@@ -347,11 +348,11 @@
      */
     @Override
     public int getInteger(int index, int defValue) {
-        if (mData[index] == null) {
+        if (mResourceData[index] == null) {
             return defValue;
         }
 
-        String s = mData[index].getValue();
+        String s = mResourceData[index].getValue();
 
         if (s != null) {
             try {
@@ -386,11 +387,11 @@
      */
     @Override
     public float getDimension(int index, float defValue) {
-        if (mData[index] == null) {
+        if (mResourceData[index] == null) {
             return defValue;
         }
 
-        String s = mData[index].getValue();
+        String s = mResourceData[index].getValue();
 
         if (s == null) {
             return defValue;
@@ -402,15 +403,16 @@
         }
 
         if (ResourceHelper.stringToFloat(s, mValue)) {
-            return mValue.getDimension(mResources.mMetrics);
+            return mValue.getDimension(mBridgeResources.mMetrics);
         }
 
         // looks like we were unable to resolve the dimension value
-        assert false;
         Bridge.getLog().warning(null, String.format(
                 "Unable to resolve dimension value \"%1$s\" in attribute \"%2$s\"",
                 s, mNames[index]));
 
+        assert false;
+
         return defValue;
     }
 
@@ -456,11 +458,11 @@
      */
     @Override
     public int getDimensionPixelSize(int index, int defValue) {
-        if (mData[index] == null) {
+        if (mResourceData[index] == null) {
             return defValue;
         }
 
-        String s = mData[index].getValue();
+        String s = mResourceData[index].getValue();
 
         if (s == null) {
             return defValue;
@@ -522,11 +524,11 @@
      */
     @Override
     public float getFraction(int index, int base, int pbase, float defValue) {
-        if (mData[index] == null) {
+        if (mResourceData[index] == null) {
             return defValue;
         }
 
-        String value = mData[index].getValue();
+        String value = mResourceData[index].getValue();
         if (value == null) {
             return defValue;
         }
@@ -536,11 +538,12 @@
         }
 
         // looks like we were unable to resolve the fraction value
-        assert false;
         Bridge.getLog().warning(null, String.format(
                 "Unable to resolve fraction value \"%1$s\" in attribute \"%2$s\"",
                 value, mNames[index]));
 
+        assert false;
+
         return defValue;
     }
 
@@ -560,8 +563,8 @@
      */
     @Override
     public int getResourceId(int index, int defValue) {
-        // get the IResource for this index
-        ResourceValue resValue = mData[index];
+        // get the Resource for this index
+        ResourceValue resValue = mResourceData[index];
 
         // no data, return the default value.
         if (resValue == null) {
@@ -574,19 +577,21 @@
             return mContext.getDynamicIdByStyle((StyleResourceValue)resValue);
         }
 
-        // if the attribute was a reference to an id, and not a declaration of an id (@+id), then
-        // the xml attribute value was "resolved" which leads us to a IResourceValue with
-        // getType() returning "id" and getName() returning the id name
+        // if the attribute was a reference to a resource, and not a declaration of an id (@+id),
+        // then the xml attribute value was "resolved" which leads us to a ResourceValue with a
+        // valid getType() and getName() returning a resource name.
         // (and getValue() returning null!). We need to handle this!
-        if (resValue.getType() != null && resValue.getType().equals(BridgeConstants.RES_ID)) {
+        if (resValue.getType() != null && resValue.getType().startsWith("@+") == false) {
             // if this is a framework id
             if (mPlatformFile || resValue.isFramework()) {
                 // look for idName in the android R classes
-                return mContext.getFrameworkIdValue(resValue.getName(), defValue);
+                return mContext.getFrameworkResourceValue(
+                        resValue.getType(), resValue.getName(), defValue);
             }
 
             // look for idName in the project R class.
-            return mContext.getProjectIdValue(resValue.getName(), defValue);
+            return mContext.getProjectResourceValue(
+                    resValue.getType(), resValue.getName(), defValue);
         }
 
         // else, try to get the value, and resolve it somehow.
@@ -623,11 +628,11 @@
             // if this is a framework id
             if (mPlatformFile || value.startsWith("@android") || value.startsWith("@+android")) {
                 // look for idName in the android R classes
-                return mContext.getFrameworkIdValue(idName, defValue);
+                return mContext.getFrameworkResourceValue(BridgeConstants.RES_ID, idName, defValue);
             }
 
             // look for idName in the project R class.
-            return mContext.getProjectIdValue(idName, defValue);
+            return mContext.getProjectResourceValue(BridgeConstants.RES_ID, idName, defValue);
         }
 
         // not a direct id valid reference? resolve it
@@ -644,9 +649,11 @@
             return idValue.intValue();
         }
 
-        assert false;
         Bridge.getLog().warning(null, String.format(
                 "Unable to resolve id \"%1$s\" for attribute \"%2$s\"", value, mNames[index]));
+
+        assert false;
+
         return defValue;
     }
 
@@ -662,28 +669,29 @@
      */
     @Override
     public Drawable getDrawable(int index) {
-        if (mData[index] == null) {
+        if (mResourceData[index] == null) {
             return null;
         }
 
-        ResourceValue value = mData[index];
+        ResourceValue value = mResourceData[index];
         String stringValue = value.getValue();
         if (stringValue == null || BridgeConstants.REFERENCE_NULL.equals(stringValue)) {
             return null;
         }
 
-        Drawable d = ResourceHelper.getDrawable(value, mContext, mData[index].isFramework());
+        Drawable d = ResourceHelper.getDrawable(value, mContext, mResourceData[index].isFramework());
 
         if (d != null) {
             return d;
         }
 
         // looks like we were unable to resolve the drawable
-        assert false;
         Bridge.getLog().warning(null, String.format(
                 "Unable to resolve drawable \"%1$s\" in attribute \"%2$s\"", stringValue,
                 mNames[index]));
 
+        assert false;
+
         return null;
     }
 
@@ -700,18 +708,18 @@
      */
     @Override
     public CharSequence[] getTextArray(int index) {
-        if (mData[index] == null) {
+        if (mResourceData[index] == null) {
             return null;
         }
 
-        String value = mData[index].getValue();
+        String value = mResourceData[index].getValue();
         if (value != null) {
             return new CharSequence[] { value };
         }
 
         Bridge.getLog().warning(null, String.format(
                 String.format("Unknown value for getTextArray(%d) => %s", //DEBUG
-                index, mData[index].getName())));
+                index, mResourceData[index].getName())));
 
         return null;
     }
@@ -727,11 +735,11 @@
      */
     @Override
     public boolean getValue(int index, TypedValue outValue) {
-        if (mData[index] == null) {
+        if (mResourceData[index] == null) {
             return false;
         }
 
-        String s = mData[index].getValue();
+        String s = mResourceData[index].getValue();
 
         return ResourceHelper.stringToFloat(s, outValue);
     }
@@ -745,7 +753,7 @@
      */
     @Override
     public boolean hasValue(int index) {
-        return mData[index] != null;
+        return mResourceData[index] != null;
     }
 
     /**
@@ -792,6 +800,6 @@
 
     @Override
     public String toString() {
-        return mData.toString();
+        return mResourceData.toString();
     }
  }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/AnimationThread.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/AnimationThread.java
index 125c1e6..033e065 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/AnimationThread.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/AnimationThread.java
@@ -28,7 +28,7 @@
 import android.os.Message;
 import android.os.Handler_Delegate.IHandlerCallback;
 
-import java.util.LinkedList;
+import java.util.PriorityQueue;
 import java.util.Queue;
 
 /**
@@ -45,7 +45,7 @@
  */
 public abstract class AnimationThread extends Thread {
 
-    private static class MessageBundle {
+    private static class MessageBundle implements Comparable<MessageBundle> {
         final Handler mTarget;
         final Message mMessage;
         final long mUptimeMillis;
@@ -55,11 +55,18 @@
             mMessage = message;
             mUptimeMillis = uptimeMillis;
         }
+
+        public int compareTo(MessageBundle bundle) {
+            if (mUptimeMillis < bundle.mUptimeMillis) {
+                return -1;
+            }
+            return 1;
+        }
     }
 
     private final RenderSessionImpl mSession;
 
-    private Queue<MessageBundle> mQueue = new LinkedList<MessageBundle>();
+    private Queue<MessageBundle> mQueue = new PriorityQueue<MessageBundle>();
     private final IAnimationListener mListener;
 
     public AnimationThread(RenderSessionImpl scene, String threadName,
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 025a318..5d5f2a1 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -365,7 +365,7 @@
             }
 
             // log it
-            mParams.getLog().error("Scene inflate failed", t);
+            mParams.getLog().error(null, "Scene inflate failed", t);
 
             return ERROR_INFLATION.createResult(t.getMessage(), t);
         }
@@ -481,7 +481,7 @@
             }
 
             // log it
-            mParams.getLog().error("Scene Render failed", t);
+            mParams.getLog().error(null, "Scene Render failed", t);
 
             return ERROR_UNKNOWN.createResult(t.getMessage(), t);
         }
@@ -505,14 +505,18 @@
         ResourceValue animationResource = null;
         int animationId = 0;
         if (isFrameworkAnimation) {
-            animationResource = mContext.getFrameworkResource("anim", animationName);
+            animationResource = mContext.getFrameworkResource(BridgeConstants.RES_ANIMATOR,
+                    animationName);
             if (animationResource != null) {
-                animationId = Bridge.getResourceValue("anim", animationName);
+                animationId = Bridge.getResourceValue(BridgeConstants.RES_ANIMATOR,
+                        animationName);
             }
         } else {
-            animationResource = mContext.getProjectResource("anim", animationName);
+            animationResource = mContext.getProjectResource(BridgeConstants.RES_ANIMATOR,
+                    animationName);
             if (animationResource != null) {
-                animationId = mContext.getProjectCallback().getResourceValue("anim", animationName);
+                animationId = mContext.getProjectCallback().getResourceValue(
+                        BridgeConstants.RES_ANIMATOR, animationName);
             }
         }
 
@@ -630,7 +634,7 @@
      * @see LayoutScene#moveChild(Object, Object, int, Map, IAnimationListener)
      */
     public Result moveChild(final ViewGroup newParentView, final View childView, final int index,
-            Map<String, String> layoutParamsMap, IAnimationListener listener) {
+            Map<String, String> layoutParamsMap, final IAnimationListener listener) {
         checkLock();
 
         invalidateRenderingSize();
@@ -647,42 +651,73 @@
 
         if (listener != null) {
             final LayoutParams params = layoutParams;
-            new AnimationThread(this, "moveChild", listener) {
 
-                @Override
-                public Result preAnimation() {
-                    // set up the transition for the previous parent.
-                    LayoutTransition removeTransition = new LayoutTransition();
-                    previousParent.setLayoutTransition(removeTransition);
+            // there is no support for animating views across layouts, so in case the new and old
+            // parent views are different we fake the animation through a no animation thread.
+            if (previousParent != newParentView) {
+                new Thread("not animated moveChild") {
+                    @Override
+                    public void run() {
+                        Result result = moveView(previousParent, newParentView, childView, index,
+                                params);
+                        if (result.isSuccess() == false) {
+                            listener.done(result);
+                        }
 
-                    // no fade-out. Because we can't rely on layout transition listeners when
-                    // there is no Animator at all, instead we keep the animator but set its
-                    // duration to 0.
-                    // Note: Cannot user Animation.setDuration() directly. Have to set it
-                    // on the LayoutTransition.
-                    removeTransition.setDuration(LayoutTransition.DISAPPEARING, 0);
+                        // ready to do the work, acquire the scene.
+                        result = acquire(250);
+                        if (result.isSuccess() == false) {
+                            listener.done(result);
+                            return;
+                        }
 
-                    if (previousParent != newParentView) {
-                        // different parent, set a Layout transition on the new parent.
-                        newParentView.setLayoutTransition(new LayoutTransition());
+                        try {
+                            result = render();
+                            if (result.isSuccess()) {
+                                listener.onNewFrame(RenderSessionImpl.this.getSession());
+                            }
+                        } finally {
+                            release();
+                        }
+
+                        listener.done(result);
+                    }
+                }.start();
+            } else {
+                new AnimationThread(this, "moveChild", listener) {
+
+                    @Override
+                    public Result preAnimation() {
+                        // set up the transition for the parent.
+                        LayoutTransition transition = new LayoutTransition();
+                        previousParent.setLayoutTransition(transition);
+
+                        // tweak the animation durations and start delays (to match the duration of
+                        // animation playing just before).
+                        // Note: Cannot user Animation.setDuration() directly. Have to set it
+                        // on the LayoutTransition.
+                        transition.setDuration(LayoutTransition.DISAPPEARING, 100);
+                        // CHANGE_DISAPPEARING plays after DISAPPEARING
+                        transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 100);
+
+                        transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 100);
+
+                        transition.setDuration(LayoutTransition.CHANGE_APPEARING, 100);
+                        // CHANGE_APPEARING plays after CHANGE_APPEARING
+                        transition.setStartDelay(LayoutTransition.APPEARING, 100);
+
+                        transition.setDuration(LayoutTransition.APPEARING, 100);
+
+                        return moveView(previousParent, newParentView, childView, index, params);
                     }
 
-                    // no fade-in. Because we can't rely on layout transition listeners when
-                    // there is no Animator at all, instead we keep the animator but set its
-                    // duration to 0.
-                    // Note: Cannot user Animation.setDuration() directly. Have to set it
-                    // on the LayoutTransition.
-                    newParentView.getLayoutTransition().setDuration(LayoutTransition.APPEARING, 0);
-
-                    return moveView(previousParent, newParentView, childView, index, params);
-                }
-
-                @Override
-                public void postAnimation() {
-                    previousParent.setLayoutTransition(null);
-                    newParentView.setLayoutTransition(null);
-                }
-            }.start();
+                    @Override
+                    public void postAnimation() {
+                        previousParent.setLayoutTransition(null);
+                        newParentView.setLayoutTransition(null);
+                    }
+                }.start();
+            }
 
             // always return success since the real status will come through the listener.
             return SUCCESS.createResult(layoutParams);
@@ -707,7 +742,7 @@
      *
      * @param previousParent the previous parent, still owning the child at the time of the call.
      * @param newParent the new parent
-     * @param view the view to move
+     * @param movedView the view to move
      * @param index the new location in the new parent
      * @param params an option (can be null) {@link LayoutParams} instance.
      *
@@ -715,12 +750,12 @@
      *     {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
      *     adding views.
      */
-    private Result moveView(ViewGroup previousParent, final ViewGroup newParent, View view,
-            final int index, final LayoutParams params) {
+    private Result moveView(ViewGroup previousParent, final ViewGroup newParent,
+            final View movedView, final int index, final LayoutParams params) {
         try {
             // check if there is a transition on the previousParent.
-            LayoutTransition transition = previousParent.getLayoutTransition();
-            if (transition != null) {
+            LayoutTransition previousTransition = previousParent.getLayoutTransition();
+            if (previousTransition != null) {
                 // in this case there is an animation. This means we have to wait for the child's
                 // parent reference to be null'ed out so that we can add it to the new parent.
                 // It is technically removed right before the DISAPPEARING animation is done (if
@@ -730,48 +765,50 @@
                 // parent, we need to wait until the CHANGE_DISAPPEARING animation is done before
                 // adding the child or the child will appear in its new location before the
                 // other children have made room for it.
-                // If the parents are different, then we can add the child to its new parent right
-                // after the DISAPPEARING animation is done.
-
-                final int waitForType = newParent == previousParent ?
-                        LayoutTransition.CHANGE_DISAPPEARING : LayoutTransition.DISAPPEARING;
 
                 // add a listener to the transition to be notified of the actual removal.
-                transition.addTransitionListener(new TransitionListener() {
+                previousTransition.addTransitionListener(new TransitionListener() {
+                    private int mChangeDisappearingCount = 0;
 
                     public void startTransition(LayoutTransition transition, ViewGroup container,
                             View view, int transitionType) {
-                        // don't care.
+                        if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) {
+                            mChangeDisappearingCount++;
+                        }
                     }
 
                     public void endTransition(LayoutTransition transition, ViewGroup container,
                             View view, int transitionType) {
-                        if (transitionType == waitForType) {
+                        if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) {
+                            mChangeDisappearingCount--;
+                        }
+
+                        if (transitionType == LayoutTransition.CHANGE_DISAPPEARING &&
+                                mChangeDisappearingCount == 0) {
                             // add it to the parentView in the correct location
                             if (params != null) {
-                                newParent.addView(view, index, params);
+                                newParent.addView(movedView, index, params);
                             } else {
-                                newParent.addView(view, index);
+                                newParent.addView(movedView, index);
                             }
-
                         }
                     }
                 });
 
                 // remove the view from the current parent.
-                previousParent.removeView(view);
+                previousParent.removeView(movedView);
 
                 // and return since adding the view to the new parent is done in the listener.
                 return SUCCESS.createResult();
             } else {
                 // standard code with no animation. pretty simple.
-                previousParent.removeView(view);
+                previousParent.removeView(movedView);
 
                 // add it to the parentView in the correct location
                 if (params != null) {
-                    newParent.addView(view, index, params);
+                    newParent.addView(movedView, index, params);
                 } else {
-                    newParent.addView(view, index);
+                    newParent.addView(movedView, index);
                 }
 
                 return SUCCESS.createResult();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
index 5427f142..fb52c86 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
@@ -27,7 +27,6 @@
 
 import org.kxml2.io.KXmlParser;
 import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
 
 import android.graphics.Bitmap;
 import android.graphics.Bitmap_Delegate;
@@ -40,7 +39,6 @@
 import android.util.TypedValue;
 
 import java.io.File;
-import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;
 import java.net.MalformedURLException;
@@ -162,7 +160,7 @@
                         // URL is wrong, we'll return null below
                     } catch (IOException e) {
                         // failed to read the file, we'll return null below.
-                        Bridge.getLog().error(null, e);
+                        Bridge.getLog().error(null, "Failed lot load " + file.getAbsolutePath(), e);
                     }
                 }
 
@@ -190,13 +188,14 @@
                     d = Drawable.createFromXml(context.getResources(),
                             new BridgeXmlBlockParser(parser, context, isFramework));
                     return d;
-                } catch (XmlPullParserException e) {
-                    Bridge.getLog().error(null, e);
-                } catch (FileNotFoundException e) {
-                    // will not happen, since we pre-check
-                } catch (IOException e) {
-                    Bridge.getLog().error(null, e);
+                } catch (Exception e) {
+                    // this is an error and not warning since the file existence is checked before
+                    // attempting to parse it.
+                    Bridge.getLog().error(null, "Failed to parse file " + value, e);
                 }
+            } else {
+                Bridge.getLog().error(null,
+                        String.format("File %s does not exist (or is not a file)", stringValue));
             }
 
             return null;
@@ -222,7 +221,7 @@
                     return new BitmapDrawable(context.getResources(), bitmap);
                 } catch (IOException e) {
                     // we'll return null below
-                    Bridge.getLog().error(null, e);
+                    Bridge.getLog().error(null, "Failed lot load " + bmpFile.getAbsolutePath(), e);
                 }
             } else {
                 // attempt to get a color from the value
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 6b589d7..4198006 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -97,6 +97,7 @@
         "android.app.Fragment#instantiate", //(Landroid/content/Context;Ljava/lang/String;Landroid/os/Bundle;)Landroid/app/Fragment;",
         "android.os.Handler#sendMessageAtTime",
         "android.view.View#isInEditMode",
+        "com.android.internal.util.XmlUtils#convertValueToInt"
         // TODO: comment out once DelegateClass is working
         // "android.content.res.Resources$Theme#obtainStyledAttributes",
     };
diff --git a/wifi/java/android/net/wifi/SupplicantStateTracker.java b/wifi/java/android/net/wifi/SupplicantStateTracker.java
index 1a00507..f96a5ae 100644
--- a/wifi/java/android/net/wifi/SupplicantStateTracker.java
+++ b/wifi/java/android/net/wifi/SupplicantStateTracker.java
@@ -192,27 +192,16 @@
         @Override
          public void enter() {
              if (DBG) Log.d(TAG, getName() + "\n");
-             mWifiStateMachine.setNetworkAvailable(false);
          }
-        @Override
-        public void exit() {
-            mWifiStateMachine.setNetworkAvailable(true);
-        }
     }
 
     class InactiveState extends HierarchicalState {
         @Override
          public void enter() {
              if (DBG) Log.d(TAG, getName() + "\n");
-             mWifiStateMachine.setNetworkAvailable(false);
          }
-        @Override
-        public void exit() {
-            mWifiStateMachine.setNetworkAvailable(true);
-        }
     }
 
-
     class DisconnectedState extends HierarchicalState {
         @Override
          public void enter() {
@@ -336,4 +325,4 @@
             if (DBG) Log.d(TAG, getName() + "\n");
         }
     }
-}
\ No newline at end of file
+}
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 10faeda..8718117 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -299,10 +299,8 @@
     static final int CMD_SET_FREQUENCY_BAND               = 90;
 
     /* Commands from/to the SupplicantStateTracker */
-    /* Indicates whether a wifi network is available for connection */
-    static final int CMD_SET_NETWORK_AVAILABLE            = 111;
     /* Reset the supplicant state tracker */
-    static final int CMD_RESET_SUPPLICANT_STATE           = 112;
+    static final int CMD_RESET_SUPPLICANT_STATE           = 111;
 
 
     /* Commands/events reported by WpsStateMachine */
@@ -1451,10 +1449,6 @@
         setWifiEnabled(true);
     }
 
-    void setNetworkAvailable(boolean available) {
-        sendMessage(obtainMessage(CMD_SET_NETWORK_AVAILABLE, available ? 1 : 0, 0));
-    }
-
     /********************************************************
      * HSM states
      *******************************************************/
@@ -1480,9 +1474,6 @@
                 case CMD_ENABLE_RSSI_POLL:
                     mEnableRssiPolling = (message.arg1 == 1);
                     break;
-                case CMD_SET_NETWORK_AVAILABLE:
-                    mNetworkInfo.setIsAvailable(message.arg1 == 1);
-                    break;
                     /* Discard */
                 case CMD_LOAD_DRIVER:
                 case CMD_UNLOAD_DRIVER:
@@ -1873,6 +1864,8 @@
             EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
             /* Initialize for connect mode operation at start */
             mIsScanMode = false;
+            /* Wifi is available as long as we have a connection to supplicant */
+            mNetworkInfo.setIsAvailable(true);
         }
         @Override
         public boolean processMessage(Message message) {
@@ -1886,6 +1879,7 @@
                         Log.e(TAG, "Failed to stop supplicant, issue kill");
                         WifiNative.killSupplicant();
                     }
+                    mNetworkInfo.setIsAvailable(false);
                     handleNetworkDisconnect();
                     setWifiState(WIFI_STATE_DISABLING);
                     sendSupplicantConnectionChangedBroadcast(false);
@@ -1896,6 +1890,7 @@
                     Log.e(TAG, "Connection lost, restart supplicant");
                     WifiNative.killSupplicant();
                     WifiNative.closeSupplicantConnection();
+                    mNetworkInfo.setIsAvailable(false);
                     handleNetworkDisconnect();
                     sendSupplicantConnectionChangedBroadcast(false);
                     mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
@@ -1975,6 +1970,11 @@
             }
             return HANDLED;
         }
+
+        @Override
+        public void exit() {
+            mNetworkInfo.setIsAvailable(false);
+        }
     }
 
     class SupplicantStoppingState extends HierarchicalState {