Merge "Change local names for greater clarity." 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 7302fd6..f80701b 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"
@@ -19996,6 +19985,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 +20987,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 +58398,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 +78255,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"
@@ -140839,6 +140828,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"
@@ -166366,8 +166366,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>
@@ -166385,8 +166383,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"
@@ -166646,39 +166642,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"
@@ -258070,7 +258033,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="arg0" type="T">
+<parameter name="t" type="T">
 </parameter>
 </method>
 </interface>
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/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/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/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/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 f98ad74..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());
@@ -5329,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");
             }
@@ -5347,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
@@ -5612,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;
@@ -5884,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) {
@@ -7263,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)
@@ -8088,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..c874160 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;
@@ -830,6 +831,7 @@
         Point[] mPoints;
         int mMetaState;
         boolean mReprocess;
+        MotionEvent mMotionEvent;
     }
 
     static class GeolocationPermissionsData {
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/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/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/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/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/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/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/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/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/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/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/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/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/com/android/layoutlib/bridge/android/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
index 886ef2a..4fb280d 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
@@ -328,11 +328,12 @@
         }
 
         // 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;
     }
 
@@ -406,11 +407,12 @@
         }
 
         // 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;
     }
 
@@ -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;
     }
 
@@ -644,9 +647,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;
     }
 
@@ -679,11 +684,12 @@
         }
 
         // 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;
     }