Merge "Update AndroidClock font for LockScreen and tweak transparency." into honeycomb
diff --git a/api/current.xml b/api/current.xml
index 48240b5..8b0c555 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -1475,7 +1475,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="17432591"
+ value="17432589"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1508,29 +1508,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="17432593"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="animator_fade_in"
- type="int"
- transient="false"
- volatile="false"
- value="17432589"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="animator_fade_out"
- type="int"
- transient="false"
- volatile="false"
- value="17432590"
+ value="17432591"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1585,7 +1563,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="17432592"
+ value="17432590"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1607,7 +1585,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="17432594"
+ value="17432592"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -19985,6 +19963,42 @@
 </parameter>
 </method>
 </class>
+<class name="ArgbEvaluator"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.animation.TypeEvaluator">
+</implements>
+<constructor name="ArgbEvaluator"
+ type="android.animation.ArgbEvaluator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="evaluate"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fraction" type="float">
+</parameter>
+<parameter name="startValue" type="java.lang.Object">
+</parameter>
+<parameter name="endValue" type="java.lang.Object">
+</parameter>
+</method>
+</class>
 <class name="DoubleEvaluator"
  extends="java.lang.Object"
  abstract="false"
@@ -20951,42 +20965,6 @@
 </parameter>
 </method>
 </class>
-<class name="RGBEvaluator"
- extends="java.lang.Object"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<implements name="android.animation.TypeEvaluator">
-</implements>
-<constructor name="RGBEvaluator"
- type="android.animation.RGBEvaluator"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<method name="evaluate"
- return="java.lang.Object"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="fraction" type="float">
-</parameter>
-<parameter name="startValue" type="java.lang.Object">
-</parameter>
-<parameter name="endValue" type="java.lang.Object">
-</parameter>
-</method>
-</class>
 <interface name="TimeInterpolator"
  abstract="true"
  static="false"
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java
index 6e589e4..bcab66e 100644
--- a/core/java/android/animation/AnimatorInflater.java
+++ b/core/java/android/animation/AnimatorInflater.java
@@ -215,7 +215,7 @@
                 (toType <= TypedValue.TYPE_LAST_COLOR_INT))) {
             // special case for colors: ignore valueType and get ints
             getFloats = false;
-            anim.setEvaluator(new RGBEvaluator());
+            anim.setEvaluator(new ArgbEvaluator());
         }
 
         if (getFloats) {
diff --git a/core/java/android/animation/RGBEvaluator.java b/core/java/android/animation/ArgbEvaluator.java
similarity index 97%
rename from core/java/android/animation/RGBEvaluator.java
rename to core/java/android/animation/ArgbEvaluator.java
index bae0af0..c3875be 100644
--- a/core/java/android/animation/RGBEvaluator.java
+++ b/core/java/android/animation/ArgbEvaluator.java
@@ -20,7 +20,7 @@
  * This evaluator can be used to perform type interpolation between integer
  * values that represent ARGB colors.
  */
-public class RGBEvaluator implements TypeEvaluator {
+public class ArgbEvaluator implements TypeEvaluator {
 
     /**
      * This function returns the calculated in-between value for a color
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index cfecec1..f884473 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -862,7 +862,7 @@
      * of <code>startValue</code> and <code>endValue</code> in the constructor. But if these values
      * are not one of these primitive types, or if different evaluation is desired (such as is
      * necessary with int values that represent colors), a custom evaluator needs to be assigned.
-     * For example, when running an animation on color values, the {@link RGBEvaluator}
+     * For example, when running an animation on color values, the {@link ArgbEvaluator}
      * should be used to get correct RGB color interpolation.
      *
      * <p>If this ValueAnimator has only one set of values being animated between, this evaluator
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 0bce748..2fa2834 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -1377,8 +1377,8 @@
             // to have the most recent value used.
             try {
                 waitUntilReadyToRun();
-                NetworkInfo info = getConnectivityManager().getActiveNetworkInfo();
-                mDataConnectionIsConnected = (info != null) && info.isConnected();
+                NetworkInfo networkInfo = getConnectivityManager().getActiveNetworkInfo();
+                mDataConnectionIsConnected = (networkInfo != null) && networkInfo.isConnected();
                 mSyncManagerWakeLock.acquire();
                 // Always do this first so that we be sure that any periodic syncs that
                 // are ready to run have been converted into pending syncs. This allows the
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 366393c..7c55f7b 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -1073,11 +1073,6 @@
                             }
                         }
                         surfaceChanged = true;
-
-                        if (mAttachInfo.mHardwareRenderer != null) {
-                            // This will bail out early if already initialized
-                            mAttachInfo.mHardwareRenderer.initialize(mHolder);
-                        }
                     }
                     if (surfaceChanged) {
                         mSurfaceHolderCallback.surfaceChanged(mSurfaceHolder,
diff --git a/core/java/android/webkit/FindActionModeCallback.java b/core/java/android/webkit/FindActionModeCallback.java
index 700d313..a322fa3d 100644
--- a/core/java/android/webkit/FindActionModeCallback.java
+++ b/core/java/android/webkit/FindActionModeCallback.java
@@ -34,7 +34,7 @@
 import android.view.inputmethod.InputMethodManager;
 
 class FindActionModeCallback implements ActionMode.Callback, TextWatcher,
-        View.OnLongClickListener {
+        View.OnLongClickListener, View.OnClickListener {
     private View mCustomView;
     private EditText mEditText;
     private TextView mMatches;
@@ -53,6 +53,7 @@
         // Override long click so that select ActionMode is not opened, which
         // would exit find ActionMode.
         mEditText.setOnLongClickListener(this);
+        mEditText.setOnClickListener(this);
         setText("");
         mMatches = (TextView) mCustomView.findViewById(
                 com.android.internal.R.id.matches);
@@ -105,7 +106,17 @@
             throw new AssertionError(
                     "No WebView for FindActionModeCallback::findNext");
         }
+        if (!mMatchesFound) {
+            findAll();
+            return;
+        }
+        if (0 == mNumberOfMatches) {
+            // There are no matches, so moving to the next match will not do
+            // anything.
+            return;
+        }
         mWebView.findNext(next);
+        updateMatchesString();
     }
 
     /*
@@ -158,6 +169,13 @@
     @Override
     public boolean onLongClick(View v) { return true; }
 
+    // OnClickListener implementation
+
+    @Override
+    public void onClick(View v) {
+        findNext(true);
+    }
+
     // ActionMode.Callback implementation
 
     @Override
@@ -193,15 +211,6 @@
                     "No WebView for FindActionModeCallback::onActionItemClicked");
         }
         mInput.hideSoftInputFromWindow(mWebView.getWindowToken(), 0);
-        if (!mMatchesFound) {
-            findAll();
-            return true;
-        }
-        if (0 == mNumberOfMatches) {
-            // There are no matches, so moving to the next match will not do
-            // anything.
-            return true;
-        }
         switch(item.getItemId()) {
             case com.android.internal.R.id.find_prev:
                 findNext(false);
@@ -212,7 +221,6 @@
             default:
                 return false;
         }
-        updateMatchesString();
         return true;
     }
 
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index e8283a6..4a9e441 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2618,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());
@@ -2652,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());
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index c874160..8d5e71a 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -115,8 +115,8 @@
      */
     private int mViewportDensityDpi = -1;
 
-    private int mRestoredScale = 0;
-    private int mRestoredTextWrapScale = 0;
+    private float mRestoredScale = 0;
+    private float mRestoredTextWrapScale = 0;
     private int mRestoredX = 0;
     private int mRestoredY = 0;
 
@@ -2245,8 +2245,8 @@
         }
 
         // reset the scroll position, the restored offset and scales
-        mWebkitScrollX = mWebkitScrollY = mRestoredX = mRestoredY
-                = mRestoredScale = mRestoredTextWrapScale = 0;
+        mWebkitScrollX = mWebkitScrollY = mRestoredX = mRestoredY = 0;
+        mRestoredScale = mRestoredTextWrapScale = 0;
     }
 
     // called by JNI
@@ -2352,9 +2352,9 @@
         mInitialViewState.mMobileSite = (0 == mViewportWidth);
         if (mRestoredScale > 0) {
             mInitialViewState.mIsRestored = true;
-            mInitialViewState.mViewScale = mRestoredScale / 100.0f;
+            mInitialViewState.mViewScale = mRestoredScale;
             if (mRestoredTextWrapScale > 0) {
-                mInitialViewState.mTextWrapScale = mRestoredTextWrapScale / 100.0f;
+                mInitialViewState.mTextWrapScale = mRestoredTextWrapScale;
             } else {
                 mInitialViewState.mTextWrapScale = mInitialViewState.mViewScale;
             }
@@ -2411,7 +2411,7 @@
                 // know the exact scale. If mRestoredScale is non-zero, use it;
                 // otherwise just use mTextWrapScale as the initial scale.
                 data.mScale = mInitialViewState.mViewScale == 0
-                        ? (mRestoredScale > 0 ? mRestoredScale / 100.0f
+                        ? (mRestoredScale > 0 ? mRestoredScale
                                 : mInitialViewState.mTextWrapScale)
                         : mInitialViewState.mViewScale;
                 if (DebugFlags.WEB_VIEW_CORE) {
@@ -2444,7 +2444,7 @@
     }
 
     // called by JNI
-    private void restoreScale(int scale, int textWrapScale) {
+    private void restoreScale(float scale, float textWrapScale) {
         if (mBrowserFrame.firstLayoutDone() == false) {
             mRestoredScale = scale;
             if (mSettings.getUseWideViewPort()) {
diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java
index 7b9def0..e1392ae 100644
--- a/core/java/android/webkit/WebViewDatabase.java
+++ b/core/java/android/webkit/WebViewDatabase.java
@@ -223,6 +223,7 @@
                         null);
             }
         }
+        mDatabase.enableWriteAheadLogging();
 
         // mDatabase should not be null,
         // the only case is RequestAPI test has problem to create db
@@ -233,7 +234,7 @@
         }
 
         if (mDatabase.getVersion() != DATABASE_VERSION) {
-            mDatabase.beginTransaction();
+            mDatabase.beginTransactionNonExclusive();
             try {
                 upgradeDatabase();
                 mDatabase.setTransactionSuccessful();
@@ -261,6 +262,7 @@
                         CACHE_DATABASE_FILE, 0, null);
             }
         }
+        mCacheDatabase.enableWriteAheadLogging();
 
         // mCacheDatabase should not be null,
         // the only case is RequestAPI test has problem to create db
@@ -271,7 +273,7 @@
         }
 
         if (mCacheDatabase.getVersion() != CACHE_DATABASE_VERSION) {
-            mCacheDatabase.beginTransaction();
+            mCacheDatabase.beginTransactionNonExclusive();
             try {
                 upgradeCacheDatabase();
                 bootstrapCacheDatabase();
@@ -648,7 +650,7 @@
                         + "WebViewWorkerThread instead of from "
                         + Thread.currentThread().getName());
             }
-            mCacheDatabase.beginTransaction();
+            mCacheDatabase.beginTransactionNonExclusive();
             return true;
         }
         return false;
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 2fd5bb1..b4a33de 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -150,6 +150,12 @@
     private static float MINIMUM_SCALE_INCREMENT = 0.01f;
 
     /*
+     *  The touch points could be changed even the fingers stop moving.
+     *  We use the following to filter out the zooming jitters.
+     */
+    private static float MINIMUM_SCALE_WITHOUT_JITTER = 0.05f;
+
+    /*
      * The following member variables are only to be used for animating zoom. If
      * mZoomScale is non-zero then we are in the middle of a zoom animation. The
      * other variables are used as a cache (e.g. inverse) or as a way to store
@@ -684,6 +690,10 @@
                 } else {
                     scale = Math.max(scale, mActualScale * 0.8f);
                 }
+                // if the scale change is too small, regard it as jitter and skip it.
+                if (Math.abs(scale - mActualScale) < MINIMUM_SCALE_WITHOUT_JITTER) {
+                    return false;
+                }
                 setZoomCenter(detector.getFocusX(), detector.getFocusY());
                 setZoomScale(scale, false);
                 mWebView.invalidate();
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 7675e0c..a1c286f 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4672,6 +4672,9 @@
                     // don't let it be inserted into the text.
                     if ((event.getFlags() & KeyEvent.FLAG_EDITOR_ACTION) != 0
                             || shouldAdvanceFocusOnEnter()) {
+                        if (mOnClickListener != null) {
+                            return 0;
+                        }
                         return -1;
                     }
                 }
diff --git a/core/res/res/anim/animator_fade_in.xml b/core/res/res/anim/animator_fade_in.xml
deleted file mode 100644
index cff98cf..0000000
--- a/core/res/res/anim/animator_fade_in.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:interpolator="@interpolator/accelerate_quad"
-    android:valueFrom="0"
-    android:valueTo="1"
-    android:propertyName="alpha"
-    android:duration="@android:integer/config_mediumAnimTime"
-/>
diff --git a/core/res/res/anim/animator_fade_out.xml b/core/res/res/anim/animator_fade_out.xml
deleted file mode 100644
index 6a3d5ee..0000000
--- a/core/res/res/anim/animator_fade_out.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:interpolator="@interpolator/accelerate_quad"
-    android:valueFrom="1.0"
-    android:valueTo="0.0"
-    android:propertyName="alpha"
-    android:duration="@android:integer/config_mediumAnimTime"
-/>
diff --git a/core/res/res/anim/fragment_close_enter.xml b/core/res/res/anim/fragment_close_enter.xml
deleted file mode 100644
index c0abbc5..0000000
--- a/core/res/res/anim/fragment_close_enter.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License. 
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-	android:zAdjustment="normal">
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_quint"
-        android:valueFrom="0.975" android:valueTo="1.0"
-        android:valueType="floatType"
-        android:propertyName="scaleY"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_quint"
-        android:valueFrom="0.975" android:valueTo="1.0"
-        android:valueType="floatType"
-        android:propertyName="scaleX"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_cubic"
-        android:valueFrom="0.0" android:valueTo="1.0"
-        android:valueType="floatType"
-        android:propertyName="alpha"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_close_exit.xml b/core/res/res/anim/fragment_close_exit.xml
deleted file mode 100644
index 9a5708c..0000000
--- a/core/res/res/anim/fragment_close_exit.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License. 
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-	android:zAdjustment="top">
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_quint"
-        android:valueFrom="1.0" android:valueTo="1.075"
-        android:valueType="floatType"
-        android:propertyName="scaleY"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_quint"
-        android:valueFrom="1.0" android:valueTo="1.075"
-        android:valueType="floatType"
-        android:propertyName="scaleX"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_cubic"
-        android:valueFrom="1.0" android:valueTo="0.0"
-        android:valueType="floatType"
-        android:propertyName="alpha"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_next_enter.xml b/core/res/res/anim/fragment_next_enter.xml
deleted file mode 100644
index 13b15f3..0000000
--- a/core/res/res/anim/fragment_next_enter.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-	android:zAdjustment="top">
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_cubic"
-        android:valueFrom="0"
-        android:valueTo="1"
-        android:valueType="floatType"
-        android:propertyName="alpha"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_next_exit.xml b/core/res/res/anim/fragment_next_exit.xml
deleted file mode 100644
index 503b7ad..0000000
--- a/core/res/res/anim/fragment_next_exit.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-	android:zAdjustment="normal">
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_cubic"
-        android:valueFrom="1"
-        android:valueTo="0"
-        android:valueType="floatType"
-        android:propertyName="alpha"
-        android:duration="@android:integer/config_activityShortDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_open_enter.xml b/core/res/res/anim/fragment_open_enter.xml
deleted file mode 100644
index 6b16cb4..0000000
--- a/core/res/res/anim/fragment_open_enter.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License. 
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android">
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_quint"
-        android:valueFrom="1.125" android:valueTo="1.0"
-        android:valueType="floatType"
-        android:propertyName="scaleY"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_quint"
-        android:valueFrom="1.125" android:valueTo="1.0"
-        android:valueType="floatType"
-        android:propertyName="scaleX"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_cubic"
-        android:valueFrom="0.0" android:valueTo="1.0"
-        android:valueType="floatType"
-        android:propertyName="alpha"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_open_exit.xml b/core/res/res/anim/fragment_open_exit.xml
deleted file mode 100644
index d77ee8e..0000000
--- a/core/res/res/anim/fragment_open_exit.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License. 
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android">
-    <objectAnimator
-        android:interpolator="@interpolator/linear"
-        android:valueFrom="1.0" android:valueTo="0.975"
-        android:valueType="floatType"
-        android:propertyName="scaleY"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-    <objectAnimator
-        android:interpolator="@interpolator/linear"
-        android:valueFrom="1.0" android:valueTo="0.975"
-        android:valueType="floatType"
-        android:propertyName="scaleX"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_cubic"
-        android:valueFrom="1.0" android:valueTo="0.0"
-        android:valueType="floatType"
-        android:propertyName="alpha"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_prev_enter.xml b/core/res/res/anim/fragment_prev_enter.xml
deleted file mode 100644
index 13b15f3..0000000
--- a/core/res/res/anim/fragment_prev_enter.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-	android:zAdjustment="top">
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_cubic"
-        android:valueFrom="0"
-        android:valueTo="1"
-        android:valueType="floatType"
-        android:propertyName="alpha"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_prev_exit.xml b/core/res/res/anim/fragment_prev_exit.xml
deleted file mode 100644
index 503b7ad..0000000
--- a/core/res/res/anim/fragment_prev_exit.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-	android:zAdjustment="normal">
-    <objectAnimator
-        android:interpolator="@interpolator/decelerate_cubic"
-        android:valueFrom="1"
-        android:valueTo="0"
-        android:valueType="floatType"
-        android:propertyName="alpha"
-        android:duration="@android:integer/config_activityShortDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/animator/fade_in.xml b/core/res/res/animator/fade_in.xml
index 2a28b4d..cff98cf 100644
--- a/core/res/res/animator/fade_in.xml
+++ b/core/res/res/animator/fade_in.xml
@@ -18,7 +18,7 @@
 -->
 
 <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:interpolator="@anim/accelerate_interpolator"
+    android:interpolator="@interpolator/accelerate_quad"
     android:valueFrom="0"
     android:valueTo="1"
     android:propertyName="alpha"
diff --git a/core/res/res/animator/fade_out.xml b/core/res/res/animator/fade_out.xml
index 4db6591..6a3d5ee 100644
--- a/core/res/res/animator/fade_out.xml
+++ b/core/res/res/animator/fade_out.xml
@@ -18,7 +18,7 @@
 -->
 
 <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:interpolator="@anim/accelerate_interpolator"
+    android:interpolator="@interpolator/accelerate_quad"
     android:valueFrom="1.0"
     android:valueTo="0.0"
     android:propertyName="alpha"
diff --git a/core/res/res/drawable-hdpi/ic_menu_help.png b/core/res/res/drawable-hdpi/ic_menu_help.png
index 4300e86..01a77da 100644
--- a/core/res/res/drawable-hdpi/ic_menu_help.png
+++ b/core/res/res/drawable-hdpi/ic_menu_help.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal.9.png b/core/res/res/drawable-mdpi/btn_default_normal.9.png
index a2d5ccd..7ff74b2 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_disable.9.png b/core/res/res/drawable-mdpi/btn_default_normal_disable.9.png
index edd3a3e..d3e11b5 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_disable.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_disable.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_disable_focused.9.png b/core/res/res/drawable-mdpi/btn_default_normal_disable_focused.9.png
index f506179..843ca7a 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_disable_focused.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_disable_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed.9.png b/core/res/res/drawable-mdpi/btn_default_pressed.9.png
index 033bf89..74fd58b 100644
--- a/core/res/res/drawable-mdpi/btn_default_pressed.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_selected.9.png b/core/res/res/drawable-mdpi/btn_default_selected.9.png
index 1e900bf..415b145 100644
--- a/core/res/res/drawable-mdpi/btn_default_selected.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_normal.9.png b/core/res/res/drawable-mdpi/btn_default_small_normal.9.png
index bcedd5f..5dddd46 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_normal.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_normal_disable.9.png b/core/res/res/drawable-mdpi/btn_default_small_normal_disable.9.png
index ac6260f..6ab5c4a 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_normal_disable.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_normal_disable.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png b/core/res/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
index 4ee1b3f..c65bace 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_pressed.9.png b/core/res/res/drawable-mdpi/btn_default_small_pressed.9.png
index 25e38f4..43e82f9 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_pressed.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_selected.9.png b/core/res/res/drawable-mdpi/btn_default_small_selected.9.png
index cc209c6..7a376a9 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_selected.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_bullet_key_permission.png b/core/res/res/drawable-mdpi/ic_bullet_key_permission.png
index ccb010f..68ad039 100644
--- a/core/res/res/drawable-mdpi/ic_bullet_key_permission.png
+++ b/core/res/res/drawable-mdpi/ic_bullet_key_permission.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_help.png b/core/res/res/drawable-mdpi/ic_menu_help.png
index 7c55dfd..12ca235 100644
--- a/core/res/res/drawable-mdpi/ic_menu_help.png
+++ b/core/res/res/drawable-mdpi/ic_menu_help.png
Binary files differ
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index c2a848d..e124d9d 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1458,9 +1458,6 @@
        sinusoidal pattern. -->
   <public type="interpolator" name="cycle" />
 
-  <public type="anim" name="animator_fade_in" />
-  <public type="anim" name="animator_fade_out" />
-
   <!-- Acceleration curve matching a cubic ease in function. -->
   <public type="anim" name="accelerate_cubic_interpolator" />
   <!-- Acceleration curve matching a cubic ease out function. -->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 96e60f2..920312b 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -81,14 +81,14 @@
         <item name="wallpaperIntraOpenExitAnimation">@anim/wallpaper_intra_open_exit</item>
         <item name="wallpaperIntraCloseEnterAnimation">@anim/wallpaper_intra_close_enter</item>
         <item name="wallpaperIntraCloseExitAnimation">@anim/wallpaper_intra_close_exit</item>
-        <item name="fragmentOpenEnterAnimation">@anim/fragment_open_enter</item>
-        <item name="fragmentOpenExitAnimation">@anim/fragment_open_exit</item>
-        <item name="fragmentCloseEnterAnimation">@anim/fragment_close_enter</item>
-        <item name="fragmentCloseExitAnimation">@anim/fragment_close_exit</item>
-        <item name="fragmentNextEnterAnimation">@anim/fragment_next_enter</item>
-        <item name="fragmentNextExitAnimation">@anim/fragment_next_exit</item>
-        <item name="fragmentPrevEnterAnimation">@anim/fragment_prev_enter</item>
-        <item name="fragmentPrevExitAnimation">@anim/fragment_prev_exit</item>
+        <item name="fragmentOpenEnterAnimation">@animator/fragment_open_enter</item>
+        <item name="fragmentOpenExitAnimation">@animator/fragment_open_exit</item>
+        <item name="fragmentCloseEnterAnimation">@animator/fragment_close_enter</item>
+        <item name="fragmentCloseExitAnimation">@animator/fragment_close_exit</item>
+        <item name="fragmentNextEnterAnimation">@animator/fragment_next_enter</item>
+        <item name="fragmentNextExitAnimation">@animator/fragment_next_exit</item>
+        <item name="fragmentPrevEnterAnimation">@animator/fragment_prev_enter</item>
+        <item name="fragmentPrevExitAnimation">@animator/fragment_prev_exit</item>
     </style>
 
     <!-- Standard animations for a non-full-screen window or activity. -->
diff --git a/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/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index 9677838..31b6ec9 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -347,7 +347,8 @@
 }
 
 void CameraSourceTimeLapse::releaseRecordingFrame(const sp<IMemory>& frame) {
-    if (!mUseStillCameraForTimeLapse) {
+    if (!mUseStillCameraForTimeLapse &&
+        mCamera != NULL) {
         mCamera->releaseRecordingFrame(frame);
     }
 }
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 7750a9d..e516cb4 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -3923,6 +3923,8 @@
 
             if (!mIsEncoder) {
                 OMX_CONFIG_RECTTYPE rect;
+                InitOMXParams(&rect);
+                rect.nPortIndex = kPortIndexOutput;
                 status_t err =
                         mOMX->getConfig(
                             mNode, OMX_IndexConfigCommonOutputCrop,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 6e2bfdb..f8809d7 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -262,11 +262,8 @@
 
         // Watch for external modifications to the database file,
         // keeping our cache in sync.
-        // It's kinda lame to call mOpenHelper.getReadableDatabase()
-        // during onCreate(), but since ensureAndroidIdIsSet has
-        // already done it above and initialized/upgraded the
-        // database, might as well just use it...
-        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+        db.enableWriteAheadLogging();
         sObserverInstance = new SettingsFileObserver(db.getPath());
         sObserverInstance.startWatching();
         startAsyncCachePopulation();
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index d824f30..d3d1750 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -12,6 +12,7 @@
     <application
         android:persistent="true"
         android:allowClearUserData="false"
+        android:hardwareAccelerated="true"
         android:label="@string/app_label"
         android:icon="@drawable/ic_launcher_settings">
 
diff --git a/packages/SystemUI/res/drawable-nodpi/panel_notification.png b/packages/SystemUI/res/drawable-nodpi/panel_notification.png
index b0d9c18..437deff 100644
--- a/packages/SystemUI/res/drawable-nodpi/panel_notification.png
+++ b/packages/SystemUI/res/drawable-nodpi/panel_notification.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/panel_notification_tiled.xml b/packages/SystemUI/res/drawable/panel_notification_tiled.xml
new file mode 100644
index 0000000..9d41e28
--- /dev/null
+++ b/packages/SystemUI/res/drawable/panel_notification_tiled.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<bitmap
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/panel_notification"
+    android:tileMode="repeat"
+    />
+
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel.xml b/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel.xml
index d3fe2e7..7f84b214 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel.xml
@@ -20,27 +20,35 @@
     xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
     android:layout_height="match_parent"
     android:layout_width="match_parent"
-    android:orientation="vertical"
     android:gravity="right"
-    android:paddingTop="32dp"
     >
 
-    <LinearLayout
+    <View
+        android:id="@+id/scrim"
+        android:background="@drawable/notify_panel_bg_protect"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_alignParentTop="true"
+        android:layout_alignParentRight="true"
+        />
+
+    <RelativeLayout
         android:id="@+id/content_parent"
         android:layout_height="wrap_content"
         android:layout_width="wrap_content"
-        android:animateLayoutChanges="true"
-        android:orientation="vertical"
+        android:layout_alignParentBottom="true"
+        android:layout_alignParentRight="true"
         >
-
-        <com.android.systemui.statusbar.tablet.NotificationTitleArea
+        <RelativeLayout
             android:id="@+id/title_area"
             android:layout_height="160dp"
             android:layout_width="384dp"
             android:layout_marginLeft="24dp"
             android:paddingTop="20dp"
             android:orientation="vertical"
-            android:animateLayoutChanges="true"
+            android:layout_alignParentTop="true"
+            android:layout_alignParentRight="true"
+            android:background="@drawable/panel_notification_tiled"
             >
 
             <com.android.systemui.statusbar.tablet.HoloClock
@@ -154,13 +162,15 @@
                 android:src="@drawable/status_bar_veto"
                 android:baseline="21dp"
                 />
-        </com.android.systemui.statusbar.tablet.NotificationTitleArea>
+        </RelativeLayout>
 
         <LinearLayout
             android:id="@+id/content_frame"
             android:layout_height="wrap_content"
             android:layout_width="408dp"
             android:orientation="vertical"
+            android:layout_below="@id/title_area"
+            android:layout_alignParentRight="true"
             >
             <ScrollView
                 android:id="@+id/notification_scroller"
@@ -191,5 +201,17 @@
                 android:src="@drawable/notify_item_glow_bottom"
                 />
         </LinearLayout>
-    </LinearLayout>
+    </RelativeLayout>
+
+    <View
+        android:id="@+id/glow"
+        android:background="@drawable/notify_glow_back"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignTop="@id/content_parent"
+        android:layout_alignLeft="@id/content_parent"
+        android:layout_marginLeft="100dip"
+        android:layout_marginTop="-100dip"
+        />
+
 </com.android.systemui.statusbar.tablet.NotificationPanel>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
index 7dcf9be..3201d06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.tablet;
 
 import android.animation.Animator;
+import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.content.Context;
@@ -33,11 +34,13 @@
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.FrameLayout;
 import android.widget.TextView;
 
 import com.android.systemui.R;
 
-public class NotificationPanel extends LinearLayout implements StatusBarPanel,
+public class NotificationPanel extends RelativeLayout implements StatusBarPanel,
         View.OnClickListener {
     static final String TAG = "Tablet/NotificationPanel";
     static final boolean DEBUG = false;
@@ -51,12 +54,11 @@
     ViewGroup mContentFrame;
     Rect mContentArea;
     View mSettingsView;
+    View mScrim, mGlow;
     ViewGroup mContentParent;
 
     Choreographer mChoreo = new Choreographer();
     int mStatusBarHeight;
-    Drawable mBgDrawable;
-    Drawable mGlowDrawable;
 
     public NotificationPanel(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
@@ -69,8 +71,6 @@
 
         mStatusBarHeight = res.getDimensionPixelSize(
                 com.android.internal.R.dimen.status_bar_height);
-        mBgDrawable = res.getDrawable(R.drawable.notify_panel_bg_protect);
-        mGlowDrawable = res.getDrawable(R.drawable.notify_glow_back);
     }
 
     @Override
@@ -80,9 +80,13 @@
         setWillNotDraw(false);
 
         mContentParent = (ViewGroup)findViewById(R.id.content_parent);
+        mContentParent.bringToFront();
         mTitleArea = findViewById(R.id.title_area);
         mTitleArea.setOnClickListener(this);
 
+        mScrim = findViewById(R.id.scrim);
+        mGlow = findViewById(R.id.glow);
+
         mSettingsButton = (ImageView)findViewById(R.id.settings_button);
         mNotificationButton = (ImageView)findViewById(R.id.notification_button);
 
@@ -132,21 +136,6 @@
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         super.onLayout(changed, l, t, r, b);
-        // We know that none of our children are GONE, so don't worry about skipping GONE views.
-        final int N = getChildCount();
-        if (N == 0) {
-            return;
-        }
-        final int allocatedBottom = getChildAt(N-1).getBottom();
-        final int shift = b - allocatedBottom - getPaddingBottom();
-        if (shift <= 0) {
-            return;
-        }
-        for (int i=0; i<N; i++) {
-            final View c = getChildAt(i);
-            c.layout(c.getLeft(), c.getTop() + shift, c.getRight(), c.getBottom() + shift);
-        }
-
         mChoreo.setPanelHeight(mContentParent.getHeight());
     }
 
@@ -154,26 +143,6 @@
     public void onSizeChanged(int w, int h, int oldw, int oldh) {
         super.onSizeChanged(w, h, oldw, oldh);
         mContentArea = null;
-        mBgDrawable.setBounds(0, 0, w, h-mStatusBarHeight);
-    }
-
-    @Override
-    public void onDraw(Canvas canvas) {
-        int saveCount;
-        final int w = getWidth();
-        final int h = getHeight();
-
-        super.onDraw(canvas);
-
-        // Background protection
-        mBgDrawable.draw(canvas);
-
-        // The panel glow (behind status bar)
-
-        saveCount = canvas.save();
-        canvas.clipRect(0, 0, w, h-mStatusBarHeight);
-        mGlowDrawable.draw(canvas);
-        canvas.restoreToCount(saveCount);
     }
 
     public void onClick(View v) {
@@ -227,82 +196,82 @@
 
     private class Choreographer implements Animator.AnimatorListener {
         boolean mVisible;
-        int mBgAlpha;
-        ValueAnimator mBgAnim;
         int mPanelHeight;
-        int mPanelBottom;
-        ValueAnimator mPositionAnim;
+        AnimatorSet mContentAnim;
 
         // should group this into a multi-property animation
-        final int OPEN_DURATION = 200;
+        final int OPEN_DURATION = 250;
+
+        // the panel will start to appear this many px from the end
+        final int HYPERSPACE_OFFRAMP = 120;
 
         Choreographer() {
         }
 
-        void createAnimation(boolean visible) {
-            mBgAnim = ObjectAnimator.ofInt(this, "bgAlpha", mBgAlpha, visible ? 255 : 0)
-                    .setDuration(OPEN_DURATION);
-            mBgAnim.addListener(this);
+        void createAnimation(boolean appearing) {
+            Animator bgAnim = ObjectAnimator.ofFloat(mScrim,
+                    "alpha", mScrim.getAlpha(), appearing ? 1 : 0);
 
-            mPositionAnim = ObjectAnimator.ofInt(this, "panelBottom", mPanelBottom,
-                        visible ? mPanelHeight : 0)
-                    .setDuration(OPEN_DURATION);
-        }
+            float start, end;
 
-        void startAnimation(boolean visible) {
-            if (DEBUG) Slog.d(TAG, "startAnimation(visible=" + visible + ")");
-
-            createAnimation(visible);
-            mBgAnim.start();
-            mPositionAnim.start();
-
-            mVisible = visible;
-        }
-
-        void jumpTo(boolean visible) {
-            setBgAlpha(visible ? 255 : 0);
-            setPanelBottom(visible ? mPanelHeight : 0);
-        }
-
-        public void setBgAlpha(int alpha) {
-            mBgAlpha = alpha;
-            mBgDrawable.setAlpha((int)(alpha));
-            invalidate();
-        }
-
-        // 0 is closed, the height of the panel is open
-        public void setPanelBottom(int y) {
-            mPanelBottom = y;
-            int translationY = mPanelHeight - y;
-            mContentParent.setTranslationY(translationY);
-
-            final int glowXOffset = 100;
-            final int glowYOffset = 100;
-            int glowX = mContentParent.getLeft() - glowXOffset;
-            int glowY = mContentParent.getTop() - glowYOffset + translationY;
-            mGlowDrawable.setBounds(glowX, glowY, glowX + mGlowDrawable.getIntrinsicWidth(),
-                    glowY + mGlowDrawable.getIntrinsicHeight());
-
-            float alpha;
-            if (mPanelBottom > glowYOffset) {
-                alpha = 1;
+            // 0: on-screen
+            // height: off-screen
+            float y = mContentParent.getTranslationY();
+            if (appearing) {
+                // we want to go from near-the-top to the top, unless we're half-open in the right
+                // general vicinity
+                start = (y < HYPERSPACE_OFFRAMP)
+                    ? y
+                    : HYPERSPACE_OFFRAMP;
+                end = 0;
             } else {
-                alpha = ((float)mPanelBottom) / glowYOffset;
+                start = y;
+                end = y + HYPERSPACE_OFFRAMP;
             }
-            mContentParent.setAlpha(alpha);
-            mGlowDrawable.setAlpha((int)(255 * alpha));
+            Animator posAnim = ObjectAnimator.ofFloat(mContentParent, "translationY", start, end);
+            posAnim.setInterpolator(appearing 
+                    ? new android.view.animation.DecelerateInterpolator(2.0f)
+                    : new android.view.animation.AccelerateInterpolator(2.0f));
 
-            if (false) {
-                Slog.d(TAG, "mPanelBottom=" + mPanelBottom + " translationY=" + translationY
-                        + " alpha=" + alpha + " glowY=" + glowY);
-            }
+            Animator glowAnim = ObjectAnimator.ofFloat(mGlow, "alpha",
+                    mGlow.getAlpha(), appearing ? 1.0f : 0.0f);
+            glowAnim.setInterpolator(appearing 
+                    ? new android.view.animation.AccelerateInterpolator(1.0f)
+                    : new android.view.animation.DecelerateInterpolator(1.0f));
+
+            mContentAnim = new AnimatorSet();
+            mContentAnim
+                .play(ObjectAnimator.ofFloat(mContentParent, "alpha", mContentParent.getAlpha(),
+                                                                      appearing ? 1.0f : 0.0f))
+                .with(glowAnim)
+                .with(bgAnim)
+                .with(posAnim)
+                ;
+            mContentAnim.setDuration(OPEN_DURATION);
+            mContentAnim.addListener(this);
+        }
+
+        void startAnimation(boolean appearing) {
+            if (DEBUG) Slog.d(TAG, "startAnimation(appearing=" + appearing + ")");
+
+            createAnimation(appearing);
+
+            mContentParent.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            mContentAnim.start();
+
+            mVisible = appearing;
+        }
+
+        void jumpTo(boolean appearing) {
+//            setBgAlpha(appearing ? 255 : 0);
+            mContentParent.setTranslationY(appearing ? 0 : mPanelHeight);
         }
 
         public void setPanelHeight(int h) {
+            if (DEBUG) Slog.d(TAG, "panelHeight=" + h);
             mPanelHeight = h;
-            if (mPanelBottom == 0) {
+            if (mPanelHeight == 0) {
                 // fully closed, no animation necessary
-                setPanelBottom(0);
             } else if (mVisible) {
                 if (DEBUG) {
                     Slog.d(TAG, "panelHeight not zero but trying to open; scheduling an anim to open fully");
@@ -312,17 +281,18 @@
         }
 
         public void onAnimationCancel(Animator animation) {
-            if (DEBUG) Slog.d(TAG, "onAnimationCancel mBgAlpha=" + mBgAlpha);
+            if (DEBUG) Slog.d(TAG, "onAnimationCancel");
             // force this to zero so we close the window
-            mBgAlpha = 0;
+            mVisible = false;
         }
 
         public void onAnimationEnd(Animator animation) {
-            if (DEBUG) Slog.d(TAG, "onAnimationEnd mBgAlpha=" + mBgAlpha);
-            if (mBgAlpha == 0) {
+            if (DEBUG) Slog.d(TAG, "onAnimationEnd");
+            if (! mVisible) {
                 setVisibility(View.GONE);
             }
-            mBgAnim = null;
+            mContentParent.setLayerType(View.LAYER_TYPE_NONE, null);
+            mContentAnim = null;
         }
 
         public void onAnimationRepeat(Animator animation) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationTitleArea.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationTitleArea.java
deleted file mode 100644
index d4413db..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationTitleArea.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.tablet;
-
-import android.content.Context;
-import android.graphics.BitmapFactory;
-import android.graphics.Bitmap;
-import android.graphics.Paint;
-import android.graphics.Canvas;
-import android.util.AttributeSet;
-import android.util.Slog;
-import android.widget.ImageView;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-import android.view.View;
-import android.widget.FrameLayout;
-
-import com.android.systemui.R;
-
-public class NotificationTitleArea extends RelativeLayout {
-    static final String TAG = "NotificationTitleArea";
-
-    View mSettingsButton;
-    View mNotificationButton;
-    View mNotificationScroller;
-    FrameLayout mSettingsFrame;
-    View mSettingsPanel;
-
-    // for drawing the background
-    Bitmap mTexture;
-    Paint mPaint;
-    int mTextureWidth;
-    int mTextureHeight;
-    
-
-    public NotificationTitleArea(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public NotificationTitleArea(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-
-        // for drawing the background
-        mTexture = BitmapFactory.decodeResource(getResources(), R.drawable.panel_notification);
-        mTextureWidth = mTexture.getWidth();
-        mTextureHeight = mTexture.getHeight();
-
-        mPaint = new Paint();
-        mPaint.setDither(false);
-    }
-
-    public void onFinishInflate() {
-        super.onFinishInflate();
-        setWillNotDraw(false);
-    }
-
-    @Override
-    public void onDraw(Canvas canvas) {
-        final Bitmap texture = mTexture;
-        final Paint paint = mPaint;
-
-        final int width = getWidth();
-        final int height = getHeight();
-
-        final int textureWidth = mTextureWidth;
-        final int textureHeight = mTextureHeight;
-
-        int x = 0;
-        int y;
-
-        while (x < width) {
-            y = 0;
-            while (y < height) {
-                canvas.drawBitmap(texture, x, y, paint);
-                y += textureHeight;
-            }
-            x += textureWidth;
-        }
-    }
-}
-
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
index 612427b..53c30fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
@@ -252,7 +252,11 @@
 
     private void refreshApplicationList() {
         mActivityDescriptions = getRecentTasks();
-        updateUiElements(getResources().getConfiguration(), true);
+        if (mActivityDescriptions.size() > 0) {
+            updateUiElements(getResources().getConfiguration(), true);
+        } else {
+            mBar.animateCollapse();
+        }
     }
 
     private Bitmap compositeBitmap(Bitmap background, Bitmap thumbnail) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 9ddb432..cd39d71 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -183,7 +183,7 @@
         mStatusBarView.setIgnoreChildren(0, mNotificationTrigger, mNotificationPanel);
 
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT,
+                720, // ViewGroup.LayoutParams.MATCH_PARENT,
                 ViewGroup.LayoutParams.MATCH_PARENT,
                 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
@@ -196,6 +196,7 @@
         lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
                 | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
         lp.windowAnimations = com.android.internal.R.style.Animation; // == no animation
+//        lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons; // simple fade
 
         WindowManagerImpl.getDefault().addView(mNotificationPanel, lp);
 
diff --git a/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/InputApplication.java b/services/java/com/android/server/InputApplication.java
index 38420d4..ae09484 100644
--- a/services/java/com/android/server/InputApplication.java
+++ b/services/java/com/android/server/InputApplication.java
@@ -18,16 +18,19 @@
 
 /**
  * Describes input-related application properties for use by the input dispatcher.
- * 
  * @hide
  */
 public final class InputApplication {
+    // Application handle.
+    public InputApplicationHandle inputApplicationHandle;
+
     // Application name.
     public String name;
-    
+
     // Dispatching timeout.
     public long dispatchingTimeoutNanos;
-    
-    // The application window token.
-    public Object token;
+
+    public void recycle() {
+        inputApplicationHandle = null;
+    }
 }
diff --git a/services/java/com/android/server/InputApplicationHandle.java b/services/java/com/android/server/InputApplicationHandle.java
new file mode 100644
index 0000000..d396d11
--- /dev/null
+++ b/services/java/com/android/server/InputApplicationHandle.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+/**
+ * Functions as a handle for an application that can receive input.
+ * Enables the native input dispatcher to refer indirectly to the window manager's
+ * application window token.
+ * @hide
+ */
+public final class InputApplicationHandle {
+    // Pointer to the native input application handle.
+    // This field is lazily initialized via JNI.
+    @SuppressWarnings("unused")
+    private int ptr;
+
+    // The window manager's application window token.
+    public final WindowManagerService.AppWindowToken appWindowToken;
+
+    private native void nativeDispose();
+
+    public InputApplicationHandle(WindowManagerService.AppWindowToken appWindowToken) {
+        this.appWindowToken = appWindowToken;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        nativeDispose();
+        super.finalize();
+    }
+}
diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java
index 410b8c2..5c2048b 100644
--- a/services/java/com/android/server/InputManager.java
+++ b/services/java/com/android/server/InputManager.java
@@ -77,7 +77,7 @@
     private static native boolean nativeHasKeys(int deviceId, int sourceMask,
             int[] keyCodes, boolean[] keyExists);
     private static native void nativeRegisterInputChannel(InputChannel inputChannel,
-            boolean monitor);
+            InputWindowHandle inputWindowHandle, boolean monitor);
     private static native void nativeUnregisterInputChannel(InputChannel inputChannel);
     private static native int nativeInjectInputEvent(InputEvent event,
             int injectorPid, int injectorUid, int syncMode, int timeoutMillis);
@@ -240,7 +240,7 @@
         }
         
         InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
-        nativeRegisterInputChannel(inputChannels[0], true);
+        nativeRegisterInputChannel(inputChannels[0], null, true);
         inputChannels[0].dispose(); // don't need to retain the Java object reference
         return inputChannels[1];
     }
@@ -248,13 +248,16 @@
     /**
      * Registers an input channel so that it can be used as an input event target.
      * @param inputChannel The input channel to register.
+     * @param inputWindowHandle The handle of the input window associated with the
+     * input channel, or null if none.
      */
-    public void registerInputChannel(InputChannel inputChannel) {
+    public void registerInputChannel(InputChannel inputChannel,
+            InputWindowHandle inputWindowHandle) {
         if (inputChannel == null) {
             throw new IllegalArgumentException("inputChannel must not be null.");
         }
         
-        nativeRegisterInputChannel(inputChannel, false);
+        nativeRegisterInputChannel(inputChannel, inputWindowHandle, false);
     }
     
     /**
@@ -429,13 +432,15 @@
         }
         
         @SuppressWarnings("unused")
-        public void notifyInputChannelBroken(InputChannel inputChannel) {
-            mWindowManagerService.mInputMonitor.notifyInputChannelBroken(inputChannel);
+        public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
+            mWindowManagerService.mInputMonitor.notifyInputChannelBroken(inputWindowHandle);
         }
         
         @SuppressWarnings("unused")
-        public long notifyANR(Object token, InputChannel inputChannel) {
-            return mWindowManagerService.mInputMonitor.notifyANR(token, inputChannel);
+        public long notifyANR(InputApplicationHandle inputApplicationHandle,
+                InputWindowHandle inputWindowHandle) {
+            return mWindowManagerService.mInputMonitor.notifyANR(
+                    inputApplicationHandle, inputWindowHandle);
         }
         
         @SuppressWarnings("unused")
@@ -445,14 +450,14 @@
         }
         
         @SuppressWarnings("unused")
-        public boolean interceptKeyBeforeDispatching(InputChannel focus,
+        public boolean interceptKeyBeforeDispatching(InputWindowHandle focus,
                 KeyEvent event, int policyFlags) {
             return mWindowManagerService.mInputMonitor.interceptKeyBeforeDispatching(
                     focus, event, policyFlags);
         }
         
         @SuppressWarnings("unused")
-        public KeyEvent dispatchUnhandledKey(InputChannel focus,
+        public KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
                 KeyEvent event, int policyFlags) {
             return mWindowManagerService.mInputMonitor.dispatchUnhandledKey(
                     focus, event, policyFlags);
diff --git a/services/java/com/android/server/InputWindow.java b/services/java/com/android/server/InputWindow.java
index befc770..1515290 100644
--- a/services/java/com/android/server/InputWindow.java
+++ b/services/java/com/android/server/InputWindow.java
@@ -20,64 +20,67 @@
 
 /**
  * Describes input-related window properties for use by the input dispatcher.
- * 
  * @hide
  */
 public final class InputWindow {
+    // The window handle.
+    public InputWindowHandle inputWindowHandle;
+
     // The input channel associated with the window.
     public InputChannel inputChannel;
-    
+
     // The window name.
     public String name;
-    
+
     // Window layout params attributes.  (WindowManager.LayoutParams)
     public int layoutParamsFlags;
     public int layoutParamsType;
-    
+
     // Dispatching timeout.
     public long dispatchingTimeoutNanos;
-    
+
     // Window frame area.
     public int frameLeft;
     public int frameTop;
     public int frameRight;
     public int frameBottom;
-    
+
     // Window visible frame area.
     public int visibleFrameLeft;
     public int visibleFrameTop;
     public int visibleFrameRight;
     public int visibleFrameBottom;
-    
+
     // Window touchable area.
     public int touchableAreaLeft;
     public int touchableAreaTop;
     public int touchableAreaRight;
     public int touchableAreaBottom;
-    
+
     // Window is visible.
     public boolean visible;
-    
+
     // Window can receive keys.
     public boolean canReceiveKeys;
-    
+
     // Window has focus.
     public boolean hasFocus;
-    
+
     // Window has wallpaper.  (window is the current wallpaper target)
     public boolean hasWallpaper;
-    
+
     // Input event dispatching is paused.
     public boolean paused;
-    
+
     // Window layer.
     public int layer;
-    
+
     // Id of process and user that owns the window.
     public int ownerPid;
     public int ownerUid;
-    
+
     public void recycle() {
+        inputWindowHandle = null;
         inputChannel = null;
     }
 }
diff --git a/services/java/com/android/server/InputWindowHandle.java b/services/java/com/android/server/InputWindowHandle.java
new file mode 100644
index 0000000..4b92939
--- /dev/null
+++ b/services/java/com/android/server/InputWindowHandle.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.view.WindowManagerPolicy;
+
+/**
+ * Functions as a handle for a window that can receive input.
+ * Enables the native input dispatcher to refer indirectly to the window manager's window state.
+ * @hide
+ */
+public final class InputWindowHandle {
+    // Pointer to the native input window handle.
+    // This field is lazily initialized via JNI.
+    @SuppressWarnings("unused")
+    private int ptr;
+
+    // The input application handle.
+    public final InputApplicationHandle inputApplicationHandle;
+
+    // The window manager's window state.
+    public final WindowManagerPolicy.WindowState windowState;
+
+    private native void nativeDispose();
+
+    public InputWindowHandle(InputApplicationHandle inputApplicationHandle,
+            WindowManagerPolicy.WindowState windowState) {
+        this.inputApplicationHandle = inputApplicationHandle;
+        this.windowState = windowState;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        nativeDispose();
+        super.finalize();
+    }
+}
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 435a2a5..e323b3b 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -7926,6 +7926,14 @@
             copyFrom(orig);
         }
 
+        public void copyFrom(PackageSetting base) {
+            super.copyFrom((PackageSettingBase) base);
+
+            userId = base.userId;
+            sharedUser = base.sharedUser;
+            pkg = base.pkg;
+        }
+
         @Override
         public String toString() {
             return "PackageSetting{"
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index c33d19d..5c823ba 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -536,7 +536,7 @@
                 InputChannel[] channels = InputChannel.openInputChannelPair("drag");
                 mServerChannel = channels[0];
                 mClientChannel = channels[1];
-                mInputManager.registerInputChannel(mServerChannel);
+                mInputManager.registerInputChannel(mServerChannel, null);
                 InputQueue.registerInputChannel(mClientChannel, mDragInputHandler,
                         mH.getLooper().getQueue());
             }
@@ -2311,7 +2311,7 @@
                 win.mInputChannel = inputChannels[0];
                 inputChannels[1].transferToBinderOutParameter(outInputChannel);
                 
-                mInputManager.registerInputChannel(win.mInputChannel);
+                mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
             }
 
             // From now on, no exceptions or errors allowed!
@@ -5711,13 +5711,13 @@
          * 
          * Called by the InputManager.
          */
-        public void notifyInputChannelBroken(InputChannel inputChannel) {
+        public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
+            if (inputWindowHandle == null) {
+                return;
+            }
+
             synchronized (mWindowMap) {
-                WindowState windowState = getWindowStateForInputChannelLocked(inputChannel);
-                if (windowState == null) {
-                    return; // irrelevant
-                }
-                
+                WindowState windowState = (WindowState) inputWindowHandle.windowState;
                 Slog.i(TAG, "WINDOW DIED " + windowState);
                 removeWindowLocked(windowState.mSession, windowState);
             }
@@ -5728,11 +5728,12 @@
          * 
          * Called by the InputManager.
          */
-        public long notifyANR(Object token, InputChannel inputChannel) {
+        public long notifyANR(InputApplicationHandle inputApplicationHandle,
+                InputWindowHandle inputWindowHandle) {
             AppWindowToken appWindowToken = null;
-            if (inputChannel != null) {
+            if (inputWindowHandle != null) {
                 synchronized (mWindowMap) {
-                    WindowState windowState = getWindowStateForInputChannelLocked(inputChannel);
+                    WindowState windowState = (WindowState) inputWindowHandle.windowState;
                     if (windowState != null) {
                         Slog.i(TAG, "Input event dispatching timed out sending to "
                                 + windowState.mAttrs.getTitle());
@@ -5741,8 +5742,8 @@
                 }
             }
             
-            if (appWindowToken == null && token != null) {
-                appWindowToken = (AppWindowToken) token;
+            if (appWindowToken == null && inputApplicationHandle != null) {
+                appWindowToken = inputApplicationHandle.appWindowToken;
                 Slog.i(TAG, "Input event dispatching timed out sending to application "
                         + appWindowToken.stringName);
             }
@@ -5762,24 +5763,6 @@
             }
             return 0; // abort dispatching
         }
-        
-        private WindowState getWindowStateForInputChannel(InputChannel inputChannel) {
-            synchronized (mWindowMap) {
-                return getWindowStateForInputChannelLocked(inputChannel);
-            }
-        }
-        
-        private WindowState getWindowStateForInputChannelLocked(InputChannel inputChannel) {
-            int windowCount = mWindows.size();
-            for (int i = 0; i < windowCount; i++) {
-                WindowState windowState = mWindows.get(i);
-                if (windowState.mInputChannel == inputChannel) {
-                    return windowState;
-                }
-            }
-            
-            return null;
-        }
 
         private void addDragInputWindowLw(InputWindowList windowList) {
             final InputWindow inputWindow = windowList.add();
@@ -5856,6 +5839,7 @@
 
                 // Add a window to our list of input windows.
                 final InputWindow inputWindow = mTempInputWindows.add();
+                inputWindow.inputWindowHandle = child.mInputWindowHandle;
                 inputWindow.inputChannel = child.mInputChannel;
                 inputWindow.name = child.toString();
                 inputWindow.layoutParamsFlags = flags;
@@ -5934,16 +5918,16 @@
         /* Provides an opportunity for the window manager policy to process a key before
          * ordinary dispatch. */
         public boolean interceptKeyBeforeDispatching(
-                InputChannel focus, KeyEvent event, int policyFlags) {
-            WindowState windowState = getWindowStateForInputChannel(focus);
+                InputWindowHandle focus, KeyEvent event, int policyFlags) {
+            WindowState windowState = (WindowState) focus.windowState;
             return mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);
         }
         
         /* Provides an opportunity for the window manager policy to process a key that
          * the application did not handle. */
         public KeyEvent dispatchUnhandledKey(
-                InputChannel focus, KeyEvent event, int policyFlags) {
-            WindowState windowState = getWindowStateForInputChannel(focus);
+                InputWindowHandle focus, KeyEvent event, int policyFlags) {
+            WindowState windowState = (WindowState) focus.windowState;
             return mPolicy.dispatchUnhandledKey(windowState, event, policyFlags);
         }
         
@@ -5973,12 +5957,14 @@
             if (newApp == null) {
                 mInputManager.setFocusedApplication(null);
             } else {
+                mTempInputApplication.inputApplicationHandle = newApp.mInputApplicationHandle;
                 mTempInputApplication.name = newApp.toString();
                 mTempInputApplication.dispatchingTimeoutNanos =
                         newApp.inputDispatchingTimeoutNanos;
-                mTempInputApplication.token = newApp;
-                
+
                 mInputManager.setFocusedApplication(mTempInputApplication);
+
+                mTempInputApplication.recycle();
             }
         }
         
@@ -6823,7 +6809,8 @@
         int mSurfaceLayer;
         float mSurfaceAlpha;
         
-        // Input channel
+        // Input channel and input window handle used by the input dispatcher.
+        InputWindowHandle mInputWindowHandle;
         InputChannel mInputChannel;
         
         // Used to improve performance of toString()
@@ -6915,6 +6902,8 @@
             mLayer = 0;
             mAnimLayer = 0;
             mLastLayer = 0;
+            mInputWindowHandle = new InputWindowHandle(
+                    mAppToken != null ? mAppToken.mInputApplicationHandle : null, this);
         }
 
         void attach() {
@@ -8304,11 +8293,15 @@
         boolean startingMoved;
         boolean firstWindowDrawn;
 
+        // Input application handle used by the input dispatcher.
+        InputApplicationHandle mInputApplicationHandle;
+
         AppWindowToken(IApplicationToken _token) {
             super(_token.asBinder(),
                     WindowManager.LayoutParams.TYPE_APPLICATION, true);
             appWindowToken = this;
             appToken = _token;
+            mInputApplicationHandle = new InputApplicationHandle(this);
         }
 
         public void setAnimation(Animation anim) {
diff --git a/services/jni/Android.mk b/services/jni/Android.mk
index ec85e54..f5a5b4d 100644
--- a/services/jni/Android.mk
+++ b/services/jni/Android.mk
@@ -4,7 +4,11 @@
 LOCAL_SRC_FILES:= \
     com_android_server_AlarmManagerService.cpp \
     com_android_server_BatteryService.cpp \
+    com_android_server_InputApplication.cpp \
+    com_android_server_InputApplicationHandle.cpp \
     com_android_server_InputManager.cpp \
+    com_android_server_InputWindow.cpp \
+    com_android_server_InputWindowHandle.cpp \
     com_android_server_LightsService.cpp \
     com_android_server_PowerManagerService.cpp \
     com_android_server_SystemServer.cpp \
diff --git a/services/jni/com_android_server_InputApplication.cpp b/services/jni/com_android_server_InputApplication.cpp
new file mode 100644
index 0000000..a46a162
--- /dev/null
+++ b/services/jni/com_android_server_InputApplication.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "InputApplication"
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include "com_android_server_InputApplication.h"
+#include "com_android_server_InputApplicationHandle.h"
+
+namespace android {
+
+static struct {
+    jclass clazz;
+
+    jfieldID inputApplicationHandle;
+    jfieldID name;
+    jfieldID dispatchingTimeoutNanos;
+} gInputApplicationClassInfo;
+
+
+// --- Global functions ---
+
+void android_server_InputApplication_toNative(
+        JNIEnv* env, jobject inputApplicationObj, InputApplication* outInputApplication) {
+    jobject inputApplicationHandleObj = env->GetObjectField(inputApplicationObj,
+            gInputApplicationClassInfo.inputApplicationHandle);
+    if (inputApplicationHandleObj) {
+        outInputApplication->inputApplicationHandle =
+                android_server_InputApplicationHandle_getHandle(env, inputApplicationHandleObj);
+        env->DeleteLocalRef(inputApplicationHandleObj);
+    } else {
+        outInputApplication->inputApplicationHandle = NULL;
+    }
+
+    jstring nameObj = jstring(env->GetObjectField(inputApplicationObj,
+            gInputApplicationClassInfo.name));
+    if (nameObj) {
+        const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
+        outInputApplication->name.setTo(nameStr);
+        env->ReleaseStringUTFChars(nameObj, nameStr);
+        env->DeleteLocalRef(nameObj);
+    } else {
+        LOGE("InputApplication.name should not be null.");
+        outInputApplication->name.setTo("unknown");
+    }
+
+    outInputApplication->dispatchingTimeout = env->GetLongField(inputApplicationObj,
+            gInputApplicationClassInfo.dispatchingTimeoutNanos);
+}
+
+
+// --- JNI ---
+
+#define FIND_CLASS(var, className) \
+        var = env->FindClass(className); \
+        LOG_FATAL_IF(! var, "Unable to find class " className); \
+        var = jclass(env->NewGlobalRef(var));
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
+int register_android_server_InputApplication(JNIEnv* env) {
+    FIND_CLASS(gInputApplicationClassInfo.clazz, "com/android/server/InputApplication");
+
+    GET_FIELD_ID(gInputApplicationClassInfo.inputApplicationHandle,
+            gInputApplicationClassInfo.clazz,
+            "inputApplicationHandle", "Lcom/android/server/InputApplicationHandle;");
+
+    GET_FIELD_ID(gInputApplicationClassInfo.name, gInputApplicationClassInfo.clazz,
+            "name", "Ljava/lang/String;");
+
+    GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
+            gInputApplicationClassInfo.clazz,
+            "dispatchingTimeoutNanos", "J");
+    return 0;
+}
+
+} /* namespace android */
diff --git a/services/jni/com_android_server_InputApplication.h b/services/jni/com_android_server_InputApplication.h
new file mode 100644
index 0000000..85fb891
--- /dev/null
+++ b/services/jni/com_android_server_InputApplication.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _ANDROID_SERVER_INPUT_APPLICATION_H
+#define _ANDROID_SERVER_INPUT_APPLICATION_H
+
+#include <input/InputApplication.h>
+
+#include "JNIHelp.h"
+#include "jni.h"
+
+namespace android {
+
+extern void android_server_InputApplication_toNative(
+        JNIEnv* env, jobject inputApplicationObj, InputApplication* outInputApplication);
+
+} // namespace android
+
+#endif // _ANDROID_SERVER_INPUT_APPLICATION_H
diff --git a/services/jni/com_android_server_InputApplicationHandle.cpp b/services/jni/com_android_server_InputApplicationHandle.cpp
new file mode 100644
index 0000000..ab82635
--- /dev/null
+++ b/services/jni/com_android_server_InputApplicationHandle.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "InputApplicationHandle"
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include <android_runtime/AndroidRuntime.h>
+#include <utils/threads.h>
+
+#include "com_android_server_InputApplicationHandle.h"
+
+namespace android {
+
+static struct {
+    jclass clazz;
+
+    jfieldID ptr;
+} gInputApplicationHandleClassInfo;
+
+static Mutex gHandleMutex;
+
+
+// --- NativeInputApplicationHandle ---
+
+NativeInputApplicationHandle::NativeInputApplicationHandle(jweak objWeak) :
+        mObjWeak(objWeak) {
+}
+
+NativeInputApplicationHandle::~NativeInputApplicationHandle() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->DeleteWeakGlobalRef(mObjWeak);
+}
+
+jobject NativeInputApplicationHandle::getInputApplicationHandleObjLocalRef(JNIEnv* env) {
+    return env->NewLocalRef(mObjWeak);
+}
+
+
+// --- Global functions ---
+
+sp<InputApplicationHandle> android_server_InputApplicationHandle_getHandle(
+        JNIEnv* env, jobject inputApplicationHandleObj) {
+    if (!inputApplicationHandleObj) {
+        return NULL;
+    }
+
+    AutoMutex _l(gHandleMutex);
+
+    int ptr = env->GetIntField(inputApplicationHandleObj, gInputApplicationHandleClassInfo.ptr);
+    NativeInputApplicationHandle* handle;
+    if (ptr) {
+        handle = reinterpret_cast<NativeInputApplicationHandle*>(ptr);
+    } else {
+        jweak objWeak = env->NewWeakGlobalRef(inputApplicationHandleObj);
+        handle = new NativeInputApplicationHandle(objWeak);
+        handle->incStrong(inputApplicationHandleObj);
+        env->SetIntField(inputApplicationHandleObj, gInputApplicationHandleClassInfo.ptr,
+                reinterpret_cast<int>(handle));
+    }
+    return handle;
+}
+
+
+// --- JNI ---
+
+static void android_server_InputApplicationHandle_nativeDispose(JNIEnv* env, jobject obj) {
+    AutoMutex _l(gHandleMutex);
+
+    int ptr = env->GetIntField(obj, gInputApplicationHandleClassInfo.ptr);
+    if (ptr) {
+        env->SetIntField(obj, gInputApplicationHandleClassInfo.ptr, 0);
+
+        NativeInputApplicationHandle* handle = reinterpret_cast<NativeInputApplicationHandle*>(ptr);
+        handle->decStrong(obj);
+    }
+}
+
+
+static JNINativeMethod gInputApplicationHandleMethods[] = {
+    /* name, signature, funcPtr */
+    { "nativeDispose", "()V",
+            (void*) android_server_InputApplicationHandle_nativeDispose },
+};
+
+#define FIND_CLASS(var, className) \
+        var = env->FindClass(className); \
+        LOG_FATAL_IF(! var, "Unable to find class " className); \
+        var = jclass(env->NewGlobalRef(var));
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
+int register_android_server_InputApplicationHandle(JNIEnv* env) {
+    int res = jniRegisterNativeMethods(env, "com/android/server/InputApplicationHandle",
+            gInputApplicationHandleMethods, NELEM(gInputApplicationHandleMethods));
+    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
+
+    FIND_CLASS(gInputApplicationHandleClassInfo.clazz, "com/android/server/InputApplicationHandle");
+
+    GET_FIELD_ID(gInputApplicationHandleClassInfo.ptr, gInputApplicationHandleClassInfo.clazz,
+            "ptr", "I");
+
+    return 0;
+}
+
+} /* namespace android */
diff --git a/services/jni/com_android_server_InputApplicationHandle.h b/services/jni/com_android_server_InputApplicationHandle.h
new file mode 100644
index 0000000..9d18721
--- /dev/null
+++ b/services/jni/com_android_server_InputApplicationHandle.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _ANDROID_SERVER_INPUT_APPLICATION_HANDLE_H
+#define _ANDROID_SERVER_INPUT_APPLICATION_HANDLE_H
+
+#include <input/InputApplication.h>
+
+#include "JNIHelp.h"
+#include "jni.h"
+
+namespace android {
+
+class NativeInputApplicationHandle : public InputApplicationHandle {
+public:
+    NativeInputApplicationHandle(jweak objWeak);
+    virtual ~NativeInputApplicationHandle();
+
+    jobject getInputApplicationHandleObjLocalRef(JNIEnv* env);
+
+private:
+    jweak mObjWeak;
+};
+
+
+extern sp<InputApplicationHandle> android_server_InputApplicationHandle_getHandle(
+        JNIEnv* env, jobject inputApplicationHandleObj);
+
+} // namespace android
+
+#endif // _ANDROID_SERVER_INPUT_APPLICATION_HANDLE_H
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 5ed63f0..e04e4c3 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -42,11 +42,13 @@
 #include <android/graphics/GraphicsJNI.h>
 
 #include "com_android_server_PowerManagerService.h"
+#include "com_android_server_InputApplication.h"
+#include "com_android_server_InputApplicationHandle.h"
+#include "com_android_server_InputWindow.h"
+#include "com_android_server_InputWindowHandle.h"
 
 namespace android {
 
-// ----------------------------------------------------------------------------
-
 static struct {
     jclass clazz;
 
@@ -68,44 +70,6 @@
 
 static struct {
     jclass clazz;
-
-    jfieldID inputChannel;
-    jfieldID name;
-    jfieldID layoutParamsFlags;
-    jfieldID layoutParamsType;
-    jfieldID dispatchingTimeoutNanos;
-    jfieldID frameLeft;
-    jfieldID frameTop;
-    jfieldID frameRight;
-    jfieldID frameBottom;
-    jfieldID visibleFrameLeft;
-    jfieldID visibleFrameTop;
-    jfieldID visibleFrameRight;
-    jfieldID visibleFrameBottom;
-    jfieldID touchableAreaLeft;
-    jfieldID touchableAreaTop;
-    jfieldID touchableAreaRight;
-    jfieldID touchableAreaBottom;
-    jfieldID visible;
-    jfieldID canReceiveKeys;
-    jfieldID hasFocus;
-    jfieldID hasWallpaper;
-    jfieldID paused;
-    jfieldID layer;
-    jfieldID ownerPid;
-    jfieldID ownerUid;
-} gInputWindowClassInfo;
-
-static struct {
-    jclass clazz;
-
-    jfieldID name;
-    jfieldID dispatchingTimeoutNanos;
-    jfieldID token;
-} gInputApplicationClassInfo;
-
-static struct {
-    jclass clazz;
 } gKeyEventClassInfo;
 
 static struct {
@@ -141,7 +105,29 @@
     jfieldID hotSpotY;
 } gPointerIconClassInfo;
 
-// ----------------------------------------------------------------------------
+
+// --- Global functions ---
+
+static jobject getInputApplicationHandleObjLocalRef(JNIEnv* env,
+        const sp<InputApplicationHandle>& inputApplicationHandle) {
+    if (inputApplicationHandle == NULL) {
+        return NULL;
+    }
+    return static_cast<NativeInputApplicationHandle*>(inputApplicationHandle.get())->
+            getInputApplicationHandleObjLocalRef(env);
+}
+
+static jobject getInputWindowHandleObjLocalRef(JNIEnv* env,
+        const sp<InputWindowHandle>& inputWindowHandle) {
+    if (inputWindowHandle == NULL) {
+        return NULL;
+    }
+    return static_cast<NativeInputWindowHandle*>(inputWindowHandle.get())->
+            getInputWindowHandleObjLocalRef(env);
+}
+
+
+// --- NativeInputManager ---
 
 class NativeInputManager : public virtual RefBase,
     public virtual InputReaderPolicyInterface,
@@ -160,7 +146,7 @@
     void setDisplayOrientation(int32_t displayId, int32_t orientation);
 
     status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
-            jweak inputChannelObjWeak, bool monitor);
+            const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
     status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
 
     void setInputWindows(JNIEnv* env, jobjectArray windowObjArray);
@@ -182,37 +168,22 @@
             uint32_t policyFlags);
     virtual void notifyConfigurationChanged(nsecs_t when);
     virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
-            const sp<InputChannel>& inputChannel);
-    virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel);
+            const sp<InputWindowHandle>& inputWindowHandle);
+    virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle);
     virtual nsecs_t getKeyRepeatTimeout();
     virtual nsecs_t getKeyRepeatDelay();
     virtual int32_t getMaxEventsPerSecond();
     virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags);
     virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
-    virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
+    virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
             const KeyEvent* keyEvent, uint32_t policyFlags);
-    virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
+    virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
             const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent);
     virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType);
     virtual bool checkInjectEventsPermissionNonReentrant(
             int32_t injectorPid, int32_t injectorUid);
 
 private:
-    class ApplicationToken : public InputApplicationHandle {
-        jweak mTokenObjWeak;
-
-    public:
-        ApplicationToken(jweak tokenObjWeak) :
-            mTokenObjWeak(tokenObjWeak) { }
-
-        virtual ~ApplicationToken() {
-            JNIEnv* env = NativeInputManager::jniEnv();
-            env->DeleteWeakGlobalRef(mTokenObjWeak);
-        }
-
-        inline jweak getTokenObj() { return mTokenObjWeak; }
-    };
-
     sp<InputManager> mInputManager;
 
     jobject mCallbacksObj;
@@ -232,19 +203,12 @@
 
         // Pointer controller singleton, created and destroyed as needed.
         wp<PointerController> pointerController;
-
-        // Weak references to all currently registered input channels by connection pointer.
-        KeyedVector<InputChannel*, jweak> inputChannelObjWeakTable;
     } mLocked;
 
     // Power manager interactions.
     bool isScreenOn();
     bool isScreenBright();
 
-    jobject getInputChannelObjLocal(JNIEnv* env, const sp<InputChannel>& inputChannel);
-
-    static bool populateWindow(JNIEnv* env, jobject windowObj, InputWindow& outWindow);
-
     static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
 
     static inline JNIEnv* jniEnv() {
@@ -252,7 +216,7 @@
     }
 };
 
-// ----------------------------------------------------------------------------
+
 
 NativeInputManager::NativeInputManager(jobject callbacksObj) :
     mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1),
@@ -328,88 +292,17 @@
 }
 
 status_t NativeInputManager::registerInputChannel(JNIEnv* env,
-        const sp<InputChannel>& inputChannel, jobject inputChannelObj, bool monitor) {
-    jweak inputChannelObjWeak = env->NewWeakGlobalRef(inputChannelObj);
-    if (! inputChannelObjWeak) {
-        LOGE("Could not create weak reference for input channel.");
-        LOGE_EX(env);
-        return NO_MEMORY;
-    }
-
-    status_t status;
-    {
-        AutoMutex _l(mLock);
-
-        ssize_t index = mLocked.inputChannelObjWeakTable.indexOfKey(inputChannel.get());
-        if (index >= 0) {
-            LOGE("Input channel object '%s' has already been registered",
-                    inputChannel->getName().string());
-            status = INVALID_OPERATION;
-            goto DeleteWeakRef;
-        }
-
-        mLocked.inputChannelObjWeakTable.add(inputChannel.get(), inputChannelObjWeak);
-    }
-
-    status = mInputManager->getDispatcher()->registerInputChannel(inputChannel, monitor);
-    if (! status) {
-        // Success.
-        return OK;
-    }
-
-    // Failed!
-    {
-        AutoMutex _l(mLock);
-        mLocked.inputChannelObjWeakTable.removeItem(inputChannel.get());
-    }
-
-DeleteWeakRef:
-    env->DeleteWeakGlobalRef(inputChannelObjWeak);
-    return status;
+        const sp<InputChannel>& inputChannel,
+        const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
+    return mInputManager->getDispatcher()->registerInputChannel(
+            inputChannel, inputWindowHandle, monitor);
 }
 
 status_t NativeInputManager::unregisterInputChannel(JNIEnv* env,
         const sp<InputChannel>& inputChannel) {
-    jweak inputChannelObjWeak;
-    {
-        AutoMutex _l(mLock);
-
-        ssize_t index = mLocked.inputChannelObjWeakTable.indexOfKey(inputChannel.get());
-        if (index < 0) {
-            LOGE("Input channel object '%s' is not currently registered",
-                    inputChannel->getName().string());
-            return INVALID_OPERATION;
-        }
-
-        inputChannelObjWeak = mLocked.inputChannelObjWeakTable.valueAt(index);
-        mLocked.inputChannelObjWeakTable.removeItemsAt(index);
-    }
-
-    env->DeleteWeakGlobalRef(inputChannelObjWeak);
-
     return mInputManager->getDispatcher()->unregisterInputChannel(inputChannel);
 }
 
-jobject NativeInputManager::getInputChannelObjLocal(JNIEnv* env,
-        const sp<InputChannel>& inputChannel) {
-    InputChannel* inputChannelPtr = inputChannel.get();
-    if (! inputChannelPtr) {
-        return NULL;
-    }
-
-    {
-        AutoMutex _l(mLock);
-
-        ssize_t index = mLocked.inputChannelObjWeakTable.indexOfKey(inputChannelPtr);
-        if (index < 0) {
-            return NULL;
-        }
-
-        jweak inputChannelObjWeak = mLocked.inputChannelObjWeakTable.valueAt(index);
-        return env->NewLocalRef(inputChannelObjWeak);
-    }
-}
-
 bool NativeInputManager::getDisplayInfo(int32_t displayId,
         int32_t* width, int32_t* height, int32_t* orientation) {
     bool result = false;
@@ -549,50 +442,46 @@
 }
 
 nsecs_t NativeInputManager::notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
-        const sp<InputChannel>& inputChannel) {
+        const sp<InputWindowHandle>& inputWindowHandle) {
 #if DEBUG_INPUT_DISPATCHER_POLICY
     LOGD("notifyANR");
 #endif
 
     JNIEnv* env = jniEnv();
 
-    jobject tokenObjLocal;
-    if (inputApplicationHandle.get()) {
-        ApplicationToken* token = static_cast<ApplicationToken*>(inputApplicationHandle.get());
-        jweak tokenObjWeak = token->getTokenObj();
-        tokenObjLocal = env->NewLocalRef(tokenObjWeak);
-    } else {
-        tokenObjLocal = NULL;
-    }
+    jobject inputApplicationHandleObj =
+            getInputApplicationHandleObjLocalRef(env, inputApplicationHandle);
+    jobject inputWindowHandleObj =
+            getInputWindowHandleObjLocalRef(env, inputWindowHandle);
 
-    jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
     jlong newTimeout = env->CallLongMethod(mCallbacksObj,
-                gCallbacksClassInfo.notifyANR, tokenObjLocal, inputChannelObjLocal);
+                gCallbacksClassInfo.notifyANR, inputApplicationHandleObj, inputWindowHandleObj);
     if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
         newTimeout = 0; // abort dispatch
     } else {
         assert(newTimeout >= 0);
     }
 
-    env->DeleteLocalRef(tokenObjLocal);
-    env->DeleteLocalRef(inputChannelObjLocal);
+    env->DeleteLocalRef(inputWindowHandleObj);
+    env->DeleteLocalRef(inputApplicationHandleObj);
     return newTimeout;
 }
 
-void NativeInputManager::notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
+void NativeInputManager::notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) {
 #if DEBUG_INPUT_DISPATCHER_POLICY
-    LOGD("notifyInputChannelBroken - inputChannel='%s'", inputChannel->getName().string());
+    LOGD("notifyInputChannelBroken");
 #endif
 
     JNIEnv* env = jniEnv();
 
-    jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
-    if (inputChannelObjLocal) {
+    jobject inputWindowHandleObj =
+            getInputWindowHandleObjLocalRef(env, inputWindowHandle);
+    if (inputWindowHandleObj) {
         env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelBroken,
-                inputChannelObjLocal);
+                inputWindowHandleObj);
         checkAndClearExceptionFromCallback(env, "notifyInputChannelBroken");
 
-        env->DeleteLocalRef(inputChannelObjLocal);
+        env->DeleteLocalRef(inputWindowHandleObj);
     }
 }
 
@@ -630,160 +519,32 @@
 
     jsize length = env->GetArrayLength(windowObjArray);
     for (jsize i = 0; i < length; i++) {
-        jobject inputTargetObj = env->GetObjectArrayElement(windowObjArray, i);
-        if (! inputTargetObj) {
+        jobject windowObj = env->GetObjectArrayElement(windowObjArray, i);
+        if (! windowObj) {
             break; // found null element indicating end of used portion of the array
         }
 
         windows.push();
         InputWindow& window = windows.editTop();
-        bool valid = populateWindow(env, inputTargetObj, window);
-        if (! valid) {
+        android_server_InputWindow_toNative(env, windowObj, &window);
+        if (window.inputChannel == NULL) {
             windows.pop();
         }
-
-        env->DeleteLocalRef(inputTargetObj);
+        env->DeleteLocalRef(windowObj);
     }
 
     mInputManager->getDispatcher()->setInputWindows(windows);
 }
 
-bool NativeInputManager::populateWindow(JNIEnv* env, jobject windowObj,
-        InputWindow& outWindow) {
-    bool valid = false;
-
-    jobject inputChannelObj = env->GetObjectField(windowObj,
-            gInputWindowClassInfo.inputChannel);
-    if (inputChannelObj) {
-        sp<InputChannel> inputChannel =
-                android_view_InputChannel_getInputChannel(env, inputChannelObj);
-        if (inputChannel != NULL) {
-            jstring name = jstring(env->GetObjectField(windowObj,
-                    gInputWindowClassInfo.name));
-            jint layoutParamsFlags = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.layoutParamsFlags);
-            jint layoutParamsType = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.layoutParamsType);
-            jlong dispatchingTimeoutNanos = env->GetLongField(windowObj,
-                    gInputWindowClassInfo.dispatchingTimeoutNanos);
-            jint frameLeft = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.frameLeft);
-            jint frameTop = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.frameTop);
-            jint frameRight = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.frameRight);
-            jint frameBottom = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.frameBottom);
-            jint visibleFrameLeft = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.visibleFrameLeft);
-            jint visibleFrameTop = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.visibleFrameTop);
-            jint visibleFrameRight = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.visibleFrameRight);
-            jint visibleFrameBottom = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.visibleFrameBottom);
-            jint touchableAreaLeft = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.touchableAreaLeft);
-            jint touchableAreaTop = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.touchableAreaTop);
-            jint touchableAreaRight = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.touchableAreaRight);
-            jint touchableAreaBottom = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.touchableAreaBottom);
-            jboolean visible = env->GetBooleanField(windowObj,
-                    gInputWindowClassInfo.visible);
-            jboolean canReceiveKeys = env->GetBooleanField(windowObj,
-                    gInputWindowClassInfo.canReceiveKeys);
-            jboolean hasFocus = env->GetBooleanField(windowObj,
-                    gInputWindowClassInfo.hasFocus);
-            jboolean hasWallpaper = env->GetBooleanField(windowObj,
-                    gInputWindowClassInfo.hasWallpaper);
-            jboolean paused = env->GetBooleanField(windowObj,
-                    gInputWindowClassInfo.paused);
-            jint layer = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.layer);
-            jint ownerPid = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.ownerPid);
-            jint ownerUid = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.ownerUid);
-
-            const char* nameStr = env->GetStringUTFChars(name, NULL);
-
-            outWindow.inputChannel = inputChannel;
-            outWindow.name.setTo(nameStr);
-            outWindow.layoutParamsFlags = layoutParamsFlags;
-            outWindow.layoutParamsType = layoutParamsType;
-            outWindow.dispatchingTimeout = dispatchingTimeoutNanos;
-            outWindow.frameLeft = frameLeft;
-            outWindow.frameTop = frameTop;
-            outWindow.frameRight = frameRight;
-            outWindow.frameBottom = frameBottom;
-            outWindow.visibleFrameLeft = visibleFrameLeft;
-            outWindow.visibleFrameTop = visibleFrameTop;
-            outWindow.visibleFrameRight = visibleFrameRight;
-            outWindow.visibleFrameBottom = visibleFrameBottom;
-            outWindow.touchableAreaLeft = touchableAreaLeft;
-            outWindow.touchableAreaTop = touchableAreaTop;
-            outWindow.touchableAreaRight = touchableAreaRight;
-            outWindow.touchableAreaBottom = touchableAreaBottom;
-            outWindow.visible = visible;
-            outWindow.canReceiveKeys = canReceiveKeys;
-            outWindow.hasFocus = hasFocus;
-            outWindow.hasWallpaper = hasWallpaper;
-            outWindow.paused = paused;
-            outWindow.layer = layer;
-            outWindow.ownerPid = ownerPid;
-            outWindow.ownerUid = ownerUid;
-
-            env->ReleaseStringUTFChars(name, nameStr);
-            env->DeleteLocalRef(name);
-            valid = true;
-        } else {
-            LOGW("Dropping input target because its input channel is not initialized.");
-        }
-
-        env->DeleteLocalRef(inputChannelObj);
-    } else {
-        LOGW("Dropping input target because the input channel object was null.");
-    }
-    return valid;
-}
-
 void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationObj) {
     if (applicationObj) {
-        jstring nameObj = jstring(env->GetObjectField(applicationObj,
-                gInputApplicationClassInfo.name));
-        jlong dispatchingTimeoutNanos = env->GetLongField(applicationObj,
-                gInputApplicationClassInfo.dispatchingTimeoutNanos);
-        jobject tokenObj = env->GetObjectField(applicationObj,
-                gInputApplicationClassInfo.token);
-        jweak tokenObjWeak = env->NewWeakGlobalRef(tokenObj);
-        if (! tokenObjWeak) {
-            LOGE("Could not create weak reference for application token.");
-            LOGE_EX(env);
-            env->ExceptionClear();
-        }
-        env->DeleteLocalRef(tokenObj);
-
-        String8 name;
-        if (nameObj) {
-            const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
-            name.setTo(nameStr);
-            env->ReleaseStringUTFChars(nameObj, nameStr);
-            env->DeleteLocalRef(nameObj);
-        } else {
-            LOGE("InputApplication.name should not be null.");
-            name.setTo("unknown");
-        }
-
         InputApplication application;
-        application.name = name;
-        application.dispatchingTimeout = dispatchingTimeoutNanos;
-        application.handle = new ApplicationToken(tokenObjWeak);
-        mInputManager->getDispatcher()->setFocusedApplication(& application);
-    } else {
-        mInputManager->getDispatcher()->setFocusedApplication(NULL);
+        android_server_InputApplication_toNative(env, applicationObj, &application);
+        if (application.inputApplicationHandle != NULL) {
+            mInputManager->getDispatcher()->setFocusedApplication(&application);
+        }
     }
+    mInputManager->getDispatcher()->setFocusedApplication(NULL);
 }
 
 void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) {
@@ -875,7 +636,8 @@
     }
 }
 
-bool NativeInputManager::interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
+bool NativeInputManager::interceptKeyBeforeDispatching(
+        const sp<InputWindowHandle>& inputWindowHandle,
         const KeyEvent* keyEvent, uint32_t policyFlags) {
     // Policy:
     // - Ignore untrusted events and pass them along.
@@ -885,13 +647,13 @@
     if (policyFlags & POLICY_FLAG_TRUSTED) {
         JNIEnv* env = jniEnv();
 
-        // Note: inputChannel may be null.
-        jobject inputChannelObj = getInputChannelObjLocal(env, inputChannel);
+        // Note: inputWindowHandle may be null.
+        jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
         jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
         if (keyEventObj) {
             jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
                     gCallbacksClassInfo.interceptKeyBeforeDispatching,
-                    inputChannelObj, keyEventObj, policyFlags);
+                    inputWindowHandleObj, keyEventObj, policyFlags);
             bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
             android_view_KeyEvent_recycle(env, keyEventObj);
             env->DeleteLocalRef(keyEventObj);
@@ -899,12 +661,12 @@
         } else {
             LOGE("Failed to obtain key event object for interceptKeyBeforeDispatching.");
         }
-        env->DeleteLocalRef(inputChannelObj);
+        env->DeleteLocalRef(inputWindowHandleObj);
     }
     return result;
 }
 
-bool NativeInputManager::dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
+bool NativeInputManager::dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
         const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
     // Policy:
     // - Ignore untrusted events and do not perform default handling.
@@ -912,13 +674,13 @@
     if (policyFlags & POLICY_FLAG_TRUSTED) {
         JNIEnv* env = jniEnv();
 
-        // Note: inputChannel may be null.
-        jobject inputChannelObj = getInputChannelObjLocal(env, inputChannel);
+        // Note: inputWindowHandle may be null.
+        jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
         jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
         if (keyEventObj) {
             jobject fallbackKeyEventObj = env->CallObjectMethod(mCallbacksObj,
                     gCallbacksClassInfo.dispatchUnhandledKey,
-                    inputChannelObj, keyEventObj, policyFlags);
+                    inputWindowHandleObj, keyEventObj, policyFlags);
             checkAndClearExceptionFromCallback(env, "dispatchUnhandledKey");
             android_view_KeyEvent_recycle(env, keyEventObj);
             env->DeleteLocalRef(keyEventObj);
@@ -935,7 +697,7 @@
         } else {
             LOGE("Failed to obtain key event object for dispatchUnhandledKey.");
         }
-        env->DeleteLocalRef(inputChannelObj);
+        env->DeleteLocalRef(inputWindowHandleObj);
     }
     return result;
 }
@@ -1079,7 +841,7 @@
 }
 
 static void android_server_InputManager_nativeRegisterInputChannel(JNIEnv* env, jclass clazz,
-        jobject inputChannelObj, jboolean monitor) {
+        jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) {
     if (checkInputManagerUnitialized(env)) {
         return;
     }
@@ -1091,9 +853,11 @@
         return;
     }
 
+    sp<InputWindowHandle> inputWindowHandle =
+            android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);
 
     status_t status = gNativeInputManager->registerInputChannel(
-            env, inputChannel, inputChannelObj, monitor);
+            env, inputChannel, inputWindowHandle, monitor);
     if (status) {
         jniThrowRuntimeException(env, "Failed to register input channel.  "
                 "Check logs for details.");
@@ -1311,7 +1075,8 @@
             (void*) android_server_InputManager_nativeGetSwitchState },
     { "nativeHasKeys", "(II[I[Z)Z",
             (void*) android_server_InputManager_nativeHasKeys },
-    { "nativeRegisterInputChannel", "(Landroid/view/InputChannel;Z)V",
+    { "nativeRegisterInputChannel",
+            "(Landroid/view/InputChannel;Lcom/android/server/InputWindowHandle;Z)V",
             (void*) android_server_InputManager_nativeRegisterInputChannel },
     { "nativeUnregisterInputChannel", "(Landroid/view/InputChannel;)V",
             (void*) android_server_InputManager_nativeUnregisterInputChannel },
@@ -1364,21 +1129,22 @@
             "notifyLidSwitchChanged", "(JZ)V");
 
     GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelBroken, gCallbacksClassInfo.clazz,
-            "notifyInputChannelBroken", "(Landroid/view/InputChannel;)V");
+            "notifyInputChannelBroken", "(Lcom/android/server/InputWindowHandle;)V");
 
     GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz,
-            "notifyANR", "(Ljava/lang/Object;Landroid/view/InputChannel;)J");
+            "notifyANR",
+            "(Lcom/android/server/InputApplicationHandle;Lcom/android/server/InputWindowHandle;)J");
 
     GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
             "interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;IZ)I");
 
     GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz,
             "interceptKeyBeforeDispatching",
-            "(Landroid/view/InputChannel;Landroid/view/KeyEvent;I)Z");
+            "(Lcom/android/server/InputWindowHandle;Landroid/view/KeyEvent;I)Z");
 
     GET_METHOD_ID(gCallbacksClassInfo.dispatchUnhandledKey, gCallbacksClassInfo.clazz,
             "dispatchUnhandledKey",
-            "(Landroid/view/InputChannel;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;");
+            "(Lcom/android/server/InputWindowHandle;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;");
 
     GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz,
             "checkInjectEventsPermission", "(II)Z");
@@ -1401,99 +1167,6 @@
     GET_METHOD_ID(gCallbacksClassInfo.getPointerIcon, gCallbacksClassInfo.clazz,
             "getPointerIcon", "()Lcom/android/server/InputManager$PointerIcon;");
 
-    // InputWindow
-
-    FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow");
-
-    GET_FIELD_ID(gInputWindowClassInfo.inputChannel, gInputWindowClassInfo.clazz,
-            "inputChannel", "Landroid/view/InputChannel;");
-
-    GET_FIELD_ID(gInputWindowClassInfo.name, gInputWindowClassInfo.clazz,
-            "name", "Ljava/lang/String;");
-
-    GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, gInputWindowClassInfo.clazz,
-            "layoutParamsFlags", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, gInputWindowClassInfo.clazz,
-            "layoutParamsType", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, gInputWindowClassInfo.clazz,
-            "dispatchingTimeoutNanos", "J");
-
-    GET_FIELD_ID(gInputWindowClassInfo.frameLeft, gInputWindowClassInfo.clazz,
-            "frameLeft", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
-            "frameTop", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.frameRight, gInputWindowClassInfo.clazz,
-            "frameRight", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.frameBottom, gInputWindowClassInfo.clazz,
-            "frameBottom", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameLeft, gInputWindowClassInfo.clazz,
-            "visibleFrameLeft", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameTop, gInputWindowClassInfo.clazz,
-            "visibleFrameTop", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameRight, gInputWindowClassInfo.clazz,
-            "visibleFrameRight", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameBottom, gInputWindowClassInfo.clazz,
-            "visibleFrameBottom", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
-            "touchableAreaLeft", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.touchableAreaTop, gInputWindowClassInfo.clazz,
-            "touchableAreaTop", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.touchableAreaRight, gInputWindowClassInfo.clazz,
-            "touchableAreaRight", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.touchableAreaBottom, gInputWindowClassInfo.clazz,
-            "touchableAreaBottom", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.visible, gInputWindowClassInfo.clazz,
-            "visible", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.canReceiveKeys, gInputWindowClassInfo.clazz,
-            "canReceiveKeys", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.hasFocus, gInputWindowClassInfo.clazz,
-            "hasFocus", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, gInputWindowClassInfo.clazz,
-            "hasWallpaper", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.paused, gInputWindowClassInfo.clazz,
-            "paused", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.layer, gInputWindowClassInfo.clazz,
-            "layer", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.ownerPid, gInputWindowClassInfo.clazz,
-            "ownerPid", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.ownerUid, gInputWindowClassInfo.clazz,
-            "ownerUid", "I");
-
-    // InputApplication
-
-    FIND_CLASS(gInputApplicationClassInfo.clazz, "com/android/server/InputApplication");
-
-    GET_FIELD_ID(gInputApplicationClassInfo.name, gInputApplicationClassInfo.clazz,
-            "name", "Ljava/lang/String;");
-
-    GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
-            gInputApplicationClassInfo.clazz,
-            "dispatchingTimeoutNanos", "J");
-
-    GET_FIELD_ID(gInputApplicationClassInfo.token, gInputApplicationClassInfo.clazz,
-            "token", "Ljava/lang/Object;");
-
     // KeyEvent
 
     FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent");
diff --git a/services/jni/com_android_server_InputWindow.cpp b/services/jni/com_android_server_InputWindow.cpp
new file mode 100644
index 0000000..a4609a0
--- /dev/null
+++ b/services/jni/com_android_server_InputWindow.cpp
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "InputWindow"
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include <android_view_InputChannel.h>
+#include "com_android_server_InputWindow.h"
+#include "com_android_server_InputWindowHandle.h"
+
+namespace android {
+
+static struct {
+    jclass clazz;
+
+    jfieldID inputWindowHandle;
+    jfieldID inputChannel;
+    jfieldID name;
+    jfieldID layoutParamsFlags;
+    jfieldID layoutParamsType;
+    jfieldID dispatchingTimeoutNanos;
+    jfieldID frameLeft;
+    jfieldID frameTop;
+    jfieldID frameRight;
+    jfieldID frameBottom;
+    jfieldID visibleFrameLeft;
+    jfieldID visibleFrameTop;
+    jfieldID visibleFrameRight;
+    jfieldID visibleFrameBottom;
+    jfieldID touchableAreaLeft;
+    jfieldID touchableAreaTop;
+    jfieldID touchableAreaRight;
+    jfieldID touchableAreaBottom;
+    jfieldID visible;
+    jfieldID canReceiveKeys;
+    jfieldID hasFocus;
+    jfieldID hasWallpaper;
+    jfieldID paused;
+    jfieldID layer;
+    jfieldID ownerPid;
+    jfieldID ownerUid;
+} gInputWindowClassInfo;
+
+
+// --- Global functions ---
+
+void android_server_InputWindow_toNative(
+        JNIEnv* env, jobject inputWindowObj, InputWindow* outInputWindow) {
+    jobject inputWindowHandleObj = env->GetObjectField(inputWindowObj,
+            gInputWindowClassInfo.inputWindowHandle);
+    if (inputWindowHandleObj) {
+        outInputWindow->inputWindowHandle =
+                android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);
+        env->DeleteLocalRef(inputWindowHandleObj);
+    } else {
+        outInputWindow->inputWindowHandle = NULL;
+    }
+
+    jobject inputChannelObj = env->GetObjectField(inputWindowObj,
+            gInputWindowClassInfo.inputChannel);
+    if (inputChannelObj) {
+        outInputWindow->inputChannel =
+                android_view_InputChannel_getInputChannel(env, inputChannelObj);
+        env->DeleteLocalRef(inputChannelObj);
+    } else {
+        outInputWindow->inputChannel = NULL;
+    }
+
+    jstring nameObj = jstring(env->GetObjectField(inputWindowObj,
+            gInputWindowClassInfo.name));
+    if (nameObj) {
+        const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
+        outInputWindow->name.setTo(nameStr);
+        env->ReleaseStringUTFChars(nameObj, nameStr);
+        env->DeleteLocalRef(nameObj);
+    } else {
+        LOGE("InputWindow.name should not be null.");
+        outInputWindow->name.setTo("unknown");
+    }
+
+    outInputWindow->layoutParamsFlags = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.layoutParamsFlags);
+    outInputWindow->layoutParamsType = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.layoutParamsType);
+    outInputWindow->dispatchingTimeout = env->GetLongField(inputWindowObj,
+            gInputWindowClassInfo.dispatchingTimeoutNanos);
+    outInputWindow->frameLeft = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.frameLeft);
+    outInputWindow->frameTop = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.frameTop);
+    outInputWindow->frameRight = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.frameRight);
+    outInputWindow->frameBottom = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.frameBottom);
+    outInputWindow->visibleFrameLeft = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.visibleFrameLeft);
+    outInputWindow->visibleFrameTop = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.visibleFrameTop);
+    outInputWindow->visibleFrameRight = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.visibleFrameRight);
+    outInputWindow->visibleFrameBottom = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.visibleFrameBottom);
+    outInputWindow->touchableAreaLeft = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.touchableAreaLeft);
+    outInputWindow->touchableAreaTop = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.touchableAreaTop);
+    outInputWindow->touchableAreaRight = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.touchableAreaRight);
+    outInputWindow->touchableAreaBottom = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.touchableAreaBottom);
+    outInputWindow->visible = env->GetBooleanField(inputWindowObj,
+            gInputWindowClassInfo.visible);
+    outInputWindow->canReceiveKeys = env->GetBooleanField(inputWindowObj,
+            gInputWindowClassInfo.canReceiveKeys);
+    outInputWindow->hasFocus = env->GetBooleanField(inputWindowObj,
+            gInputWindowClassInfo.hasFocus);
+    outInputWindow->hasWallpaper = env->GetBooleanField(inputWindowObj,
+            gInputWindowClassInfo.hasWallpaper);
+    outInputWindow->paused = env->GetBooleanField(inputWindowObj,
+            gInputWindowClassInfo.paused);
+    outInputWindow->layer = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.layer);
+    outInputWindow->ownerPid = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.ownerPid);
+    outInputWindow->ownerUid = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.ownerUid);
+}
+
+
+// --- JNI ---
+
+#define FIND_CLASS(var, className) \
+        var = env->FindClass(className); \
+        LOG_FATAL_IF(! var, "Unable to find class " className); \
+        var = jclass(env->NewGlobalRef(var));
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
+int register_android_server_InputWindow(JNIEnv* env) {
+    FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow");
+
+    GET_FIELD_ID(gInputWindowClassInfo.inputWindowHandle, gInputWindowClassInfo.clazz,
+            "inputWindowHandle", "Lcom/android/server/InputWindowHandle;");
+
+    GET_FIELD_ID(gInputWindowClassInfo.inputChannel, gInputWindowClassInfo.clazz,
+            "inputChannel", "Landroid/view/InputChannel;");
+
+    GET_FIELD_ID(gInputWindowClassInfo.name, gInputWindowClassInfo.clazz,
+            "name", "Ljava/lang/String;");
+
+    GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, gInputWindowClassInfo.clazz,
+            "layoutParamsFlags", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, gInputWindowClassInfo.clazz,
+            "layoutParamsType", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, gInputWindowClassInfo.clazz,
+            "dispatchingTimeoutNanos", "J");
+
+    GET_FIELD_ID(gInputWindowClassInfo.frameLeft, gInputWindowClassInfo.clazz,
+            "frameLeft", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
+            "frameTop", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.frameRight, gInputWindowClassInfo.clazz,
+            "frameRight", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.frameBottom, gInputWindowClassInfo.clazz,
+            "frameBottom", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameLeft, gInputWindowClassInfo.clazz,
+            "visibleFrameLeft", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameTop, gInputWindowClassInfo.clazz,
+            "visibleFrameTop", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameRight, gInputWindowClassInfo.clazz,
+            "visibleFrameRight", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameBottom, gInputWindowClassInfo.clazz,
+            "visibleFrameBottom", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
+            "touchableAreaLeft", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.touchableAreaTop, gInputWindowClassInfo.clazz,
+            "touchableAreaTop", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.touchableAreaRight, gInputWindowClassInfo.clazz,
+            "touchableAreaRight", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.touchableAreaBottom, gInputWindowClassInfo.clazz,
+            "touchableAreaBottom", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.visible, gInputWindowClassInfo.clazz,
+            "visible", "Z");
+
+    GET_FIELD_ID(gInputWindowClassInfo.canReceiveKeys, gInputWindowClassInfo.clazz,
+            "canReceiveKeys", "Z");
+
+    GET_FIELD_ID(gInputWindowClassInfo.hasFocus, gInputWindowClassInfo.clazz,
+            "hasFocus", "Z");
+
+    GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, gInputWindowClassInfo.clazz,
+            "hasWallpaper", "Z");
+
+    GET_FIELD_ID(gInputWindowClassInfo.paused, gInputWindowClassInfo.clazz,
+            "paused", "Z");
+
+    GET_FIELD_ID(gInputWindowClassInfo.layer, gInputWindowClassInfo.clazz,
+            "layer", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.ownerPid, gInputWindowClassInfo.clazz,
+            "ownerPid", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.ownerUid, gInputWindowClassInfo.clazz,
+            "ownerUid", "I");
+    return 0;
+}
+
+} /* namespace android */
diff --git a/services/jni/com_android_server_InputWindow.h b/services/jni/com_android_server_InputWindow.h
new file mode 100644
index 0000000..eaf7bde
--- /dev/null
+++ b/services/jni/com_android_server_InputWindow.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _ANDROID_SERVER_INPUT_WINDOW_H
+#define _ANDROID_SERVER_INPUT_WINDOW_H
+
+#include <input/InputWindow.h>
+
+#include "JNIHelp.h"
+#include "jni.h"
+
+namespace android {
+
+extern void android_server_InputWindow_toNative(
+        JNIEnv* env, jobject inputWindowObj, InputWindow* outInputWindow);
+
+} // namespace android
+
+#endif // _ANDROID_SERVER_INPUT_WINDOW_H
diff --git a/services/jni/com_android_server_InputWindowHandle.cpp b/services/jni/com_android_server_InputWindowHandle.cpp
new file mode 100644
index 0000000..4d66212
--- /dev/null
+++ b/services/jni/com_android_server_InputWindowHandle.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "InputWindowHandle"
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include <android_runtime/AndroidRuntime.h>
+#include <utils/threads.h>
+
+#include "com_android_server_InputWindowHandle.h"
+#include "com_android_server_InputApplicationHandle.h"
+
+namespace android {
+
+static struct {
+    jclass clazz;
+
+    jfieldID ptr;
+    jfieldID inputApplicationHandle;
+} gInputWindowHandleClassInfo;
+
+static Mutex gHandleMutex;
+
+
+// --- NativeInputWindowHandle ---
+
+NativeInputWindowHandle::NativeInputWindowHandle(
+        const sp<InputApplicationHandle>& inputApplicationHandle, jweak objWeak) :
+        InputWindowHandle(inputApplicationHandle),
+        mObjWeak(objWeak) {
+}
+
+NativeInputWindowHandle::~NativeInputWindowHandle() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->DeleteWeakGlobalRef(mObjWeak);
+}
+
+jobject NativeInputWindowHandle::getInputWindowHandleObjLocalRef(JNIEnv* env) {
+    return env->NewLocalRef(mObjWeak);
+}
+
+
+// --- Global functions ---
+
+sp<NativeInputWindowHandle> android_server_InputWindowHandle_getHandle(
+        JNIEnv* env, jobject inputWindowHandleObj) {
+    if (!inputWindowHandleObj) {
+        return NULL;
+    }
+
+    AutoMutex _l(gHandleMutex);
+
+    int ptr = env->GetIntField(inputWindowHandleObj, gInputWindowHandleClassInfo.ptr);
+    NativeInputWindowHandle* handle;
+    if (ptr) {
+        handle = reinterpret_cast<NativeInputWindowHandle*>(ptr);
+    } else {
+        jobject inputApplicationHandleObj = env->GetObjectField(inputWindowHandleObj,
+                gInputWindowHandleClassInfo.inputApplicationHandle);
+        sp<InputApplicationHandle> inputApplicationHandle =
+                android_server_InputApplicationHandle_getHandle(env, inputApplicationHandleObj);
+        env->DeleteLocalRef(inputApplicationHandleObj);
+
+        jweak objWeak = env->NewWeakGlobalRef(inputWindowHandleObj);
+        handle = new NativeInputWindowHandle(inputApplicationHandle, objWeak);
+        handle->incStrong(inputWindowHandleObj);
+        env->SetIntField(inputWindowHandleObj, gInputWindowHandleClassInfo.ptr,
+                reinterpret_cast<int>(handle));
+    }
+    return handle;
+}
+
+
+// --- JNI ---
+
+static void android_server_InputWindowHandle_nativeDispose(JNIEnv* env, jobject obj) {
+    AutoMutex _l(gHandleMutex);
+
+    int ptr = env->GetIntField(obj, gInputWindowHandleClassInfo.ptr);
+    if (ptr) {
+        env->SetIntField(obj, gInputWindowHandleClassInfo.ptr, 0);
+
+        NativeInputWindowHandle* handle = reinterpret_cast<NativeInputWindowHandle*>(ptr);
+        handle->decStrong(obj);
+    }
+}
+
+
+static JNINativeMethod gInputWindowHandleMethods[] = {
+    /* name, signature, funcPtr */
+    { "nativeDispose", "()V",
+            (void*) android_server_InputWindowHandle_nativeDispose },
+};
+
+#define FIND_CLASS(var, className) \
+        var = env->FindClass(className); \
+        LOG_FATAL_IF(! var, "Unable to find class " className); \
+        var = jclass(env->NewGlobalRef(var));
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
+int register_android_server_InputWindowHandle(JNIEnv* env) {
+    int res = jniRegisterNativeMethods(env, "com/android/server/InputWindowHandle",
+            gInputWindowHandleMethods, NELEM(gInputWindowHandleMethods));
+    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
+
+    FIND_CLASS(gInputWindowHandleClassInfo.clazz, "com/android/server/InputWindowHandle");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.ptr, gInputWindowHandleClassInfo.clazz,
+            "ptr", "I");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.inputApplicationHandle,
+            gInputWindowHandleClassInfo.clazz,
+            "inputApplicationHandle", "Lcom/android/server/InputApplicationHandle;");
+
+    return 0;
+}
+
+} /* namespace android */
diff --git a/services/jni/com_android_server_InputWindowHandle.h b/services/jni/com_android_server_InputWindowHandle.h
new file mode 100644
index 0000000..43f2a6b
--- /dev/null
+++ b/services/jni/com_android_server_InputWindowHandle.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _ANDROID_SERVER_INPUT_WINDOW_HANDLE_H
+#define _ANDROID_SERVER_INPUT_WINDOW_HANDLE_H
+
+#include <input/InputWindow.h>
+
+#include "JNIHelp.h"
+#include "jni.h"
+
+namespace android {
+
+class NativeInputWindowHandle : public InputWindowHandle {
+public:
+    NativeInputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
+            jweak objWeak);
+    virtual ~NativeInputWindowHandle();
+
+    jobject getInputWindowHandleObjLocalRef(JNIEnv* env);
+
+private:
+    jweak mObjWeak;
+};
+
+
+extern sp<NativeInputWindowHandle> android_server_InputWindowHandle_getHandle(
+        JNIEnv* env, jobject inputWindowHandleObj);
+
+} // namespace android
+
+#endif // _ANDROID_SERVER_INPUT_WINDOW_HANDLE_H
diff --git a/services/jni/onload.cpp b/services/jni/onload.cpp
index cd4f0a4..bdd6d80 100644
--- a/services/jni/onload.cpp
+++ b/services/jni/onload.cpp
@@ -6,6 +6,10 @@
 namespace android {
 int register_android_server_AlarmManagerService(JNIEnv* env);
 int register_android_server_BatteryService(JNIEnv* env);
+int register_android_server_InputApplication(JNIEnv* env);
+int register_android_server_InputApplicationHandle(JNIEnv* env);
+int register_android_server_InputWindow(JNIEnv* env);
+int register_android_server_InputWindowHandle(JNIEnv* env);
 int register_android_server_InputManager(JNIEnv* env);
 int register_android_server_LightsService(JNIEnv* env);
 int register_android_server_PowerManagerService(JNIEnv* env);
@@ -28,6 +32,10 @@
     LOG_ASSERT(env, "Could not retrieve the env!");
 
     register_android_server_PowerManagerService(env);
+    register_android_server_InputApplication(env);
+    register_android_server_InputApplicationHandle(env);
+    register_android_server_InputWindow(env);
+    register_android_server_InputWindowHandle(env);
     register_android_server_InputManager(env);
     register_android_server_LightsService(env);
     register_android_server_AlarmManagerService(env);
diff --git a/tests/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/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
index c57aef6..096498b 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
@@ -351,7 +351,8 @@
                 If the exception happened on open, bm will be null.
                 If it happened on close, bm is still valid.
             */
-            Bridge.getLog().error(null, e);
+            Bridge.getLog().error(null,
+                    String.format("Error decoding bitmap of id 0x%x", id), e);
         } finally {
             try {
                 if (is != null) is.close();
diff --git a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
index e9fb30a2..5524f4f 100644
--- a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
@@ -73,7 +73,7 @@
             oos = new ObjectOutputStream(baos);
             oos.writeObject(chunk);
         } catch (IOException e) {
-            Bridge.getLog().error("Failed to serialize NinePatchChunk.", e);
+            Bridge.getLog().error(null, "Failed to serialize NinePatchChunk.", e);
             return null;
         } finally {
             if (oos != null) {
@@ -196,10 +196,10 @@
                     sChunkCache.put(array, new SoftReference<NinePatchChunk>(chunk));
                 }
             } catch (IOException e) {
-                Bridge.getLog().error("Failed to deserialize NinePatchChunk content.", e);
+                Bridge.getLog().error(null, "Failed to deserialize NinePatchChunk content.", e);
                 return null;
             } catch (ClassNotFoundException e) {
-                Bridge.getLog().error("Failed to deserialize NinePatchChunk class.", e);
+                Bridge.getLog().error(null, "Failed to deserialize NinePatchChunk class.", e);
                 return null;
             } finally {
                 if (ois != null) {
diff --git a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
index bc13b52..33c2aed 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
@@ -135,6 +135,123 @@
 
     // ---- native methods ----
 
+    /*package*/ static boolean isEmpty(Region thisRegion) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return true;
+        }
+
+        return regionDelegate.mArea.isEmpty();
+    }
+
+    /*package*/ static boolean isRect(Region thisRegion) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return true;
+        }
+
+        return regionDelegate.mArea.isRectangular();
+    }
+
+    /*package*/ static boolean isComplex(Region thisRegion) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return true;
+        }
+
+        return regionDelegate.mArea.isSingular() == false;
+    }
+
+    /*package*/ static boolean contains(Region thisRegion, int x, int y) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return false;
+        }
+
+        return regionDelegate.mArea.contains(x, y);
+    }
+
+    /*package*/ static boolean quickContains(Region thisRegion,
+            int left, int top, int right, int bottom) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return false;
+        }
+
+        return regionDelegate.mArea.isRectangular() &&
+                regionDelegate.mArea.contains(left, top, right - left, bottom - top);
+    }
+
+    /*package*/ static boolean quickReject(Region thisRegion,
+            int left, int top, int right, int bottom) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return false;
+        }
+
+        return regionDelegate.mArea.isEmpty() ||
+                regionDelegate.mArea.intersects(left, top, right - left, bottom - top) == false;
+    }
+
+    /*package*/ static boolean quickReject(Region thisRegion, Region rgn) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return false;
+        }
+
+        Region_Delegate targetRegionDelegate = sManager.getDelegate(rgn.mNativeRegion);
+        if (targetRegionDelegate == null) {
+            return false;
+        }
+
+        return regionDelegate.mArea.isEmpty() ||
+                regionDelegate.mArea.getBounds().intersects(
+                        targetRegionDelegate.mArea.getBounds()) == false;
+
+    }
+
+    /*package*/ static void translate(Region thisRegion, int dx, int dy, Region dst) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return;
+        }
+
+        Region_Delegate targetRegionDelegate = sManager.getDelegate(dst.mNativeRegion);
+        if (targetRegionDelegate == null) {
+            return;
+        }
+
+        if (regionDelegate.mArea.isEmpty()) {
+            targetRegionDelegate.mArea = new Area();
+        } else {
+            targetRegionDelegate.mArea = new Area(regionDelegate.mArea);
+            AffineTransform mtx = new AffineTransform();
+            mtx.translate(dx, dy);
+            targetRegionDelegate.mArea.transform(mtx);
+        }
+    }
+
+    /*package*/ static void scale(Region thisRegion, float scale, Region dst) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return;
+        }
+
+        Region_Delegate targetRegionDelegate = sManager.getDelegate(dst.mNativeRegion);
+        if (targetRegionDelegate == null) {
+            return;
+        }
+
+        if (regionDelegate.mArea.isEmpty()) {
+            targetRegionDelegate.mArea = new Area();
+        } else {
+            targetRegionDelegate.mArea = new Area(regionDelegate.mArea);
+            AffineTransform mtx = new AffineTransform();
+            mtx.scale(scale, scale);
+            targetRegionDelegate.mArea.transform(mtx);
+        }
+    }
+
     /*package*/ static int nativeConstructor() {
         Region_Delegate newDelegate = new Region_Delegate();
         return sManager.addDelegate(newDelegate);
diff --git a/tools/layoutlib/bridge/src/com/android/internal/util/XmlUtils_Delegate.java b/tools/layoutlib/bridge/src/com/android/internal/util/XmlUtils_Delegate.java
new file mode 100644
index 0000000..7fa1679
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/internal/util/XmlUtils_Delegate.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link XmlUtils}
+ *
+ * Through the layoutlib_create tool, the original  methods of XmlUtils have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ */
+public class XmlUtils_Delegate {
+    /*package*/ static final int convertValueToInt(CharSequence charSeq, int defaultValue) {
+        if (null == charSeq)
+            return defaultValue;
+
+        String nm = charSeq.toString();
+
+        // This code is copied from the original implementation. The issue is that
+        // The Dalvik libraries are able to handle Integer.parse("XXXXXXXX", 16) where XXXXXXX
+        // is > 80000000 but the Java VM cannot.
+
+        int sign = 1;
+        int index = 0;
+        int len = nm.length();
+        int base = 10;
+
+        if ('-' == nm.charAt(0)) {
+            sign = -1;
+            index++;
+        }
+
+        if ('0' == nm.charAt(index)) {
+            //  Quick check for a zero by itself
+            if (index == (len - 1))
+                return 0;
+
+            char c = nm.charAt(index + 1);
+
+            if ('x' == c || 'X' == c) {
+                index += 2;
+                base = 16;
+            } else {
+                index++;
+                base = 8;
+            }
+        }
+        else if ('#' == nm.charAt(index)) {
+            index++;
+            base = 16;
+        }
+
+        return ((int)Long.parseLong(nm.substring(index), base)) * sign;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index c042327..0990cef 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -142,16 +142,6 @@
         }
 
         @Override
-        public void error(String tag, Throwable t) {
-            String message = t.getMessage();
-            if (message == null) {
-                message = t.getClass().getName();
-            }
-
-            System.err.println(message);
-        }
-
-        @Override
         public void error(String tag, String message, Throwable throwable) {
             System.err.println(message);
         }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java
index 791e53b..194687e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java
@@ -48,6 +48,7 @@
 
     public final static String PREFIX_ANDROID = "android:";
 
+    public final static String RES_ANIMATOR = "animator";
     public final static String RES_STYLE = "style";
     public final static String RES_ATTR = "attr";
     public final static String RES_DIMEN = "dimen";
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index b0eea4c..fb79473 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -493,12 +493,12 @@
     /**
      * Resolves the value of a resource, if the value references a theme or resource value.
      * <p/>
-     * This method ensures that it returns a {@link IResourceValue} object that does not
+     * This method ensures that it returns a {@link ResourceValue} object that does not
      * reference another resource.
      * If the resource cannot be resolved, it returns <code>null</code>.
      * <p/>
      * If a value that does not need to be resolved is given, the method will return a new
-     * instance of IResourceValue that contains the input value.
+     * instance of {@link ResourceValue} that contains the input value.
      *
      * @param type the type of the resource
      * @param name the name of the attribute containing this value.
@@ -510,11 +510,11 @@
             return null;
         }
 
-        // get the IResourceValue referenced by this value
+        // get the ResourceValue referenced by this value
         ResourceValue resValue = findResValue(value, false /*forceFrameworkOnly*/);
 
         // if resValue is null, but value is not null, this means it was not a reference.
-        // we return the name/value wrapper in a IResourceValue. the isFramework flag doesn't
+        // we return the name/value wrapper in a ResourceValue. the isFramework flag doesn't
         // matter.
         if (resValue == null) {
             return new ResourceValue(type, name, value, false /*isFramework*/);
@@ -525,9 +525,9 @@
     }
 
     /**
-     * Returns the {@link IResourceValue} referenced by the value of <var>value</var>.
+     * Returns the {@link ResourceValue} referenced by the value of <var>value</var>.
      * <p/>
-     * This method ensures that it returns a {@link IResourceValue} object that does not
+     * This method ensures that it returns a {@link ResourceValue} object that does not
      * reference another resource.
      * If the resource cannot be resolved, it returns <code>null</code>.
      * <p/>
@@ -535,7 +535,7 @@
      * value.
      *
      * @param value the value containing the reference to resolve.
-     * @return a {@link IResourceValue} object or <code>null</code>
+     * @return a {@link ResourceValue} object or <code>null</code>
      */
     public ResourceValue resolveResValue(ResourceValue value) {
         if (value == null) {
@@ -547,7 +547,7 @@
             return value;
         }
 
-        // else attempt to find another IResourceValue referenced by this one.
+        // else attempt to find another ResourceValue referenced by this one.
         ResourceValue resolvedValue = findResValue(value.getValue(), value.isFramework());
 
         // if the value did not reference anything, then we simply return the input value
@@ -560,7 +560,7 @@
     }
 
     /**
-     * Searches for, and returns a {@link IResourceValue} by its reference.
+     * Searches for, and returns a {@link ResourceValue} by its reference.
      * <p/>
      * The reference format can be:
      * <pre>@resType/resName</pre>
@@ -577,7 +577,7 @@
      * @param reference the resource reference to search for.
      * @param forceFrameworkOnly if true all references are considered to be toward framework
      *      resource even if the reference does not include the android: prefix.
-     * @return a {@link IResourceValue} or <code>null</code>.
+     * @return a {@link ResourceValue} or <code>null</code>.
      */
     ResourceValue findResValue(String reference, boolean forceFrameworkOnly) {
         if (reference == null) {
@@ -670,7 +670,7 @@
     }
 
     /**
-     * Searches for, and returns a {@link IResourceValue} by its name, and type.
+     * Searches for, and returns a {@link ResourceValue} by its name, and type.
      * @param resType the type of the resource
      * @param resName  the name of the resource
      * @param frameworkOnly if <code>true</code>, the method does not search in the
@@ -746,11 +746,11 @@
     }
 
     /**
-     * Returns the {@link IResourceValue} matching a given name in a given style. If the
+     * Returns the {@link ResourceValue} matching a given name in a given style. If the
      * item is not directly available in the style, the method looks in its parent style.
      * @param style the style to search in
      * @param itemName the name of the item to search for.
-     * @return the {@link IResourceValue} object or <code>null</code>
+     * @return the {@link ResourceValue} object or <code>null</code>
      */
     public ResourceValue findItemInStyle(StyleResourceValue style, String itemName) {
         ResourceValue item = style.findValue(itemName);
@@ -878,8 +878,8 @@
         return null;
     }
 
-    int getFrameworkIdValue(String idName, int defValue) {
-        Integer value = Bridge.getResourceValue(BridgeConstants.RES_ID, idName);
+    int getFrameworkResourceValue(String resType, String resName, int defValue) {
+        Integer value = Bridge.getResourceValue(resType, resName);
         if (value != null) {
             return value.intValue();
         }
@@ -887,9 +887,9 @@
         return defValue;
     }
 
-    int getProjectIdValue(String idName, int defValue) {
+    int getProjectResourceValue(String resType, String resName, int defValue) {
         if (mProjectCallback != null) {
-            Integer value = mProjectCallback.getResourceValue(BridgeConstants.RES_ID, idName);
+            Integer value = mProjectCallback.getResourceValue(resType, resName);
             if (value != null) {
                 return value.intValue();
             }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java
index 1b59621..36aa335 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java
@@ -178,8 +178,10 @@
 
                         return inflate(bridgeParser, root);
                     } catch (Exception e) {
-                        Bridge.getLog().error(null, e);
-                        // return null below.
+                        Bridge.getLog().error(null,
+                                "Failed to parse file " + f.getAbsolutePath(), e);
+
+                        return null;
                     }
                 }
             }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
index 2ea5281..a56800c 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
@@ -43,7 +43,6 @@
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
-import java.io.IOException;
 import java.io.InputStream;
 
 /**
@@ -173,14 +172,13 @@
 
                         return ColorStateList.createFromXml(this,
                                 new BridgeXmlBlockParser(parser, mContext, resValue.isFramework()));
-                    } catch (XmlPullParserException e) {
-                        Bridge.getLog().error(null, e);
-                    } catch (FileNotFoundException e) {
-                        // will not happen, since we pre-check
-                    } catch (IOException e) {
-                        Bridge.getLog().error(null, e);
-                    }
+                    } catch (Exception e) {
+                        // this is an error and not warning since the file existence is checked before
+                        // attempting to parse it.
+                        Bridge.getLog().error(null, "Failed to parse file " + value, e);
 
+                        return null;
+                    }
                 } else {
                     // try to load the color state list from an int
                     try {
@@ -245,7 +243,8 @@
                     return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
                 }
             } catch (XmlPullParserException e) {
-                Bridge.getLog().error(null, e);
+                Bridge.getLog().error(null,
+                        "Failed to configure parser for " + value.getValue(), e);
                 // we'll return null below.
             } catch (FileNotFoundException e) {
                 // this shouldn't happen since we check above.
@@ -279,7 +278,8 @@
                     return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
                 }
             } catch (XmlPullParserException e) {
-                Bridge.getLog().error(null, e);
+                Bridge.getLog().error(null,
+                        "Failed to configure parser for " + value.getValue(), e);
                 // we'll return null below.
             } catch (FileNotFoundException e) {
                 // this shouldn't happen since we check above.
@@ -294,7 +294,6 @@
         return null;
     }
 
-
     @Override
     public TypedArray obtainAttributes(AttributeSet set, int[] attrs) {
         return mContext.obtainStyledAttributes(set, attrs);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
index 4fb280d..7f11897 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
@@ -322,9 +322,9 @@
         } catch (Exception e) {
             // this is an error and not warning since the file existence is checked before
             // attempting to parse it.
-            Bridge.getLog().error(null, e);
+            Bridge.getLog().error(null, "Failed to parse file " + value, e);
 
-            // return null below.
+            return null;
         }
 
         // looks like were unable to resolve the color value.
@@ -577,19 +577,21 @@
             return mContext.getDynamicIdByStyle((StyleResourceValue)resValue);
         }
 
-        // if the attribute was a reference to an id, and not a declaration of an id (@+id), then
-        // the xml attribute value was "resolved" which leads us to a ResourceValue with
-        // getType() returning "id" and getName() returning the id name
+        // if the attribute was a reference to a resource, and not a declaration of an id (@+id),
+        // then the xml attribute value was "resolved" which leads us to a ResourceValue with a
+        // valid getType() and getName() returning a resource name.
         // (and getValue() returning null!). We need to handle this!
-        if (resValue.getType() != null && resValue.getType().equals(BridgeConstants.RES_ID)) {
+        if (resValue.getType() != null && resValue.getType().startsWith("@+") == false) {
             // if this is a framework id
             if (mPlatformFile || resValue.isFramework()) {
                 // look for idName in the android R classes
-                return mContext.getFrameworkIdValue(resValue.getName(), defValue);
+                return mContext.getFrameworkResourceValue(
+                        resValue.getType(), resValue.getName(), defValue);
             }
 
             // look for idName in the project R class.
-            return mContext.getProjectIdValue(resValue.getName(), defValue);
+            return mContext.getProjectResourceValue(
+                    resValue.getType(), resValue.getName(), defValue);
         }
 
         // else, try to get the value, and resolve it somehow.
@@ -626,11 +628,11 @@
             // if this is a framework id
             if (mPlatformFile || value.startsWith("@android") || value.startsWith("@+android")) {
                 // look for idName in the android R classes
-                return mContext.getFrameworkIdValue(idName, defValue);
+                return mContext.getFrameworkResourceValue(BridgeConstants.RES_ID, idName, defValue);
             }
 
             // look for idName in the project R class.
-            return mContext.getProjectIdValue(idName, defValue);
+            return mContext.getProjectResourceValue(BridgeConstants.RES_ID, idName, defValue);
         }
 
         // not a direct id valid reference? resolve it
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 55a5bc0..5d5f2a1 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -365,7 +365,7 @@
             }
 
             // log it
-            mParams.getLog().error("Scene inflate failed", t);
+            mParams.getLog().error(null, "Scene inflate failed", t);
 
             return ERROR_INFLATION.createResult(t.getMessage(), t);
         }
@@ -481,7 +481,7 @@
             }
 
             // log it
-            mParams.getLog().error("Scene Render failed", t);
+            mParams.getLog().error(null, "Scene Render failed", t);
 
             return ERROR_UNKNOWN.createResult(t.getMessage(), t);
         }
@@ -505,14 +505,18 @@
         ResourceValue animationResource = null;
         int animationId = 0;
         if (isFrameworkAnimation) {
-            animationResource = mContext.getFrameworkResource("anim", animationName);
+            animationResource = mContext.getFrameworkResource(BridgeConstants.RES_ANIMATOR,
+                    animationName);
             if (animationResource != null) {
-                animationId = Bridge.getResourceValue("anim", animationName);
+                animationId = Bridge.getResourceValue(BridgeConstants.RES_ANIMATOR,
+                        animationName);
             }
         } else {
-            animationResource = mContext.getProjectResource("anim", animationName);
+            animationResource = mContext.getProjectResource(BridgeConstants.RES_ANIMATOR,
+                    animationName);
             if (animationResource != null) {
-                animationId = mContext.getProjectCallback().getResourceValue("anim", animationName);
+                animationId = mContext.getProjectCallback().getResourceValue(
+                        BridgeConstants.RES_ANIMATOR, animationName);
             }
         }
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
index 5427f142..fb52c86 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
@@ -27,7 +27,6 @@
 
 import org.kxml2.io.KXmlParser;
 import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
 
 import android.graphics.Bitmap;
 import android.graphics.Bitmap_Delegate;
@@ -40,7 +39,6 @@
 import android.util.TypedValue;
 
 import java.io.File;
-import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;
 import java.net.MalformedURLException;
@@ -162,7 +160,7 @@
                         // URL is wrong, we'll return null below
                     } catch (IOException e) {
                         // failed to read the file, we'll return null below.
-                        Bridge.getLog().error(null, e);
+                        Bridge.getLog().error(null, "Failed lot load " + file.getAbsolutePath(), e);
                     }
                 }
 
@@ -190,13 +188,14 @@
                     d = Drawable.createFromXml(context.getResources(),
                             new BridgeXmlBlockParser(parser, context, isFramework));
                     return d;
-                } catch (XmlPullParserException e) {
-                    Bridge.getLog().error(null, e);
-                } catch (FileNotFoundException e) {
-                    // will not happen, since we pre-check
-                } catch (IOException e) {
-                    Bridge.getLog().error(null, e);
+                } catch (Exception e) {
+                    // this is an error and not warning since the file existence is checked before
+                    // attempting to parse it.
+                    Bridge.getLog().error(null, "Failed to parse file " + value, e);
                 }
+            } else {
+                Bridge.getLog().error(null,
+                        String.format("File %s does not exist (or is not a file)", stringValue));
             }
 
             return null;
@@ -222,7 +221,7 @@
                     return new BitmapDrawable(context.getResources(), bitmap);
                 } catch (IOException e) {
                     // we'll return null below
-                    Bridge.getLog().error(null, e);
+                    Bridge.getLog().error(null, "Failed lot load " + bmpFile.getAbsolutePath(), e);
                 }
             } else {
                 // attempt to get a color from the value
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 6b589d7..4198006 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -97,6 +97,7 @@
         "android.app.Fragment#instantiate", //(Landroid/content/Context;Ljava/lang/String;Landroid/os/Bundle;)Landroid/app/Fragment;",
         "android.os.Handler#sendMessageAtTime",
         "android.view.View#isInEditMode",
+        "com.android.internal.util.XmlUtils#convertValueToInt"
         // TODO: comment out once DelegateClass is working
         // "android.content.res.Resources$Theme#obtainStyledAttributes",
     };