Merge "Re-enable fades in ListView."
diff --git a/api/current.xml b/api/current.xml
index cdb6964..2624b64 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -75700,6 +75700,16 @@
  visibility="public"
 >
 </field>
+<field name="inPreferQualityOverSpeed"
+ type="boolean"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="inPreferredConfig"
  type="android.graphics.Bitmap.Config"
  transient="false"
@@ -198453,6 +198463,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_FALLBACK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1024"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_FROM_SYSTEM"
  type="int"
  transient="false"
@@ -198684,6 +198705,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_APP_SWITCH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="187"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_AT"
  type="int"
  transient="false"
@@ -227724,6 +227756,28 @@
 <parameter name="newFocus" type="android.view.View">
 </parameter>
 </method>
+<method name="onPause"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onResume"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="overlayHorizontalScrollbar"
  return="boolean"
  abstract="false"
@@ -239897,6 +239951,325 @@
 </parameter>
 </method>
 </interface>
+<class name="NumberPicker"
+ extends="android.widget.LinearLayout"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="NumberPicker"
+ type="android.widget.NumberPicker"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<constructor name="NumberPicker"
+ type="android.widget.NumberPicker"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<constructor name="NumberPicker"
+ type="android.widget.NumberPicker"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+<parameter name="defStyle" type="int">
+</parameter>
+</constructor>
+<method name="getCurrent"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getRangeEnd"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getRangeStart"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setCurrent"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="current" type="int">
+</parameter>
+</method>
+<method name="setFormatter"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="formatter" type="android.widget.NumberPicker.Formatter">
+</parameter>
+</method>
+<method name="setOnChangeListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="onChangeListener" type="android.widget.NumberPicker.OnChangeListener">
+</parameter>
+</method>
+<method name="setOnLongPressUpdateInterval"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="intervalMillis" type="long">
+</parameter>
+</method>
+<method name="setOnScrollListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="onScrollListener" type="android.widget.NumberPicker.OnScrollListener">
+</parameter>
+</method>
+<method name="setRange"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="start" type="int">
+</parameter>
+<parameter name="end" type="int">
+</parameter>
+</method>
+<method name="setRange"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="start" type="int">
+</parameter>
+<parameter name="end" type="int">
+</parameter>
+<parameter name="displayedValues" type="java.lang.String[]">
+</parameter>
+</method>
+<method name="setRange"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="start" type="int">
+</parameter>
+<parameter name="end" type="int">
+</parameter>
+<parameter name="displayedValues" type="java.lang.String[]">
+</parameter>
+<parameter name="wrapSelectorWheel" type="boolean">
+</parameter>
+</method>
+<method name="setWrapSelectorWheel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="wrapSelector" type="boolean">
+</parameter>
+</method>
+<field name="TWO_DIGIT_FORMATTER"
+ type="android.widget.NumberPicker.Formatter"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="NumberPicker.Formatter"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="toString"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="int">
+</parameter>
+</method>
+</interface>
+<interface name="NumberPicker.OnChangeListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onChange"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="picker" type="android.widget.NumberPicker">
+</parameter>
+<parameter name="oldVal" type="int">
+</parameter>
+<parameter name="newVal" type="int">
+</parameter>
+</method>
+</interface>
+<interface name="NumberPicker.OnScrollListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onScrollStateChange"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.widget.NumberPicker">
+</parameter>
+<parameter name="scrollState" type="int">
+</parameter>
+</method>
+<field name="SCROLL_STATE_FLING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SCROLL_STATE_IDLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SCROLL_STATE_TOUCH_SCROLL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="OverScroller"
  extends="java.lang.Object"
  abstract="false"
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index a0a6b42..d679ef6 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -297,7 +297,7 @@
  *             <p>Followed by either <code>onResume()</code> if the activity
  *             returns back to the front, or <code>onStop()</code> if it becomes
  *             invisible to the user.</td>
- *         <td align="center"><font color="#800000"><strong>Yes</strong></font></td>
+ *         <td align="center"><font color="#800000"><strong>Pre-{@link android.os.Build.VERSION_CODES#HONEYCOMB}</strong></font></td>
  *         <td align="center"><code>onResume()</code> or<br>
  *                 <code>onStop()</code></td>
  *     </tr>
@@ -347,6 +347,14 @@
  * because the later is not part of the lifecycle callbacks, so will not
  * be called in every situation as described in its documentation.</p>
  *
+ * <p class="note">Be aware that these semantics will change slightly between
+ * applications targeting platforms starting with {@link android.os.Build.VERSION_CODES#HONEYCOMB}
+ * vs. those targeting prior platforms.  Starting with Honeycomb, an application
+ * is not in the killable state until its {@link #onStop} has returned.  This
+ * impacts when {@link #onSaveInstanceState(Bundle)} may be called (it may be
+ * safely called after {@link #onPause()} and allows and application to safely
+ * wait until {@link #onStop()} to save persistent state.</p>
+ *
  * <p>For those methods that are not marked as being killable, the activity's
  * process will not be killed by the system starting from the time the method
  * is called and continuing after it returns.  Thus an activity is in the killable
@@ -489,7 +497,7 @@
  * paused.  Note this implies
  * that the user pressing BACK from your activity does <em>not</em>
  * mean "cancel" -- it means to leave the activity with its current contents
- * saved away.  Cancelling edits in an activity must be provided through
+ * saved away.  Canceling edits in an activity must be provided through
  * some other mechanism, such as an explicit "revert" or "undo" option.</p>
  *
  * <p>See the {@linkplain android.content.ContentProvider content package} for
@@ -1255,11 +1263,8 @@
      * can use the given <var>canvas</var>, which is configured to draw into the
      * bitmap, for rendering if desired.
      * 
-     * <p>The default implementation renders the Screen's current view
-     * hierarchy into the canvas to generate a thumbnail.
-     * 
-     * <p>If you return false, the bitmap will be filled with a default
-     * thumbnail.
+     * <p>The default implementation returns fails and does not draw a thumbnail;
+     * this will result in the platform creating its own thumbnail if needed.
      * 
      * @param outBitmap The bitmap to contain the thumbnail.
      * @param canvas Can be used to render into the bitmap.
@@ -1272,40 +1277,7 @@
      * @see #onPause
      */
     public boolean onCreateThumbnail(Bitmap outBitmap, Canvas canvas) {
-        if (mDecor == null) {
-            return false;
-        }
-
-        int paddingLeft = 0;
-        int paddingRight = 0;
-        int paddingTop = 0;
-        int paddingBottom = 0;
-
-        // Find System window and use padding so we ignore space reserved for decorations
-        // like the status bar and such.
-        final FrameLayout top = (FrameLayout) mDecor;
-        for (int i = 0; i < top.getChildCount(); i++) {
-            View child = top.getChildAt(i);
-            if (child.isFitsSystemWindowsFlagSet()) {
-                paddingLeft = child.getPaddingLeft();
-                paddingRight = child.getPaddingRight();
-                paddingTop = child.getPaddingTop();
-                paddingBottom = child.getPaddingBottom();
-                break;
-            }
-        }
-        
-        final int visibleWidth = mDecor.getWidth() - paddingLeft - paddingRight;
-        final int visibleHeight = mDecor.getHeight() - paddingTop - paddingBottom;
-
-        canvas.save();
-        canvas.scale( (float) outBitmap.getWidth() / visibleWidth,
-                (float) outBitmap.getHeight() / visibleHeight);
-        canvas.translate(-paddingLeft, -paddingTop);
-        mDecor.draw(canvas);
-        canvas.restore();
-
-        return true;
+        return false;
     }
 
     /**
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index f3cc4ee..34788a5 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -359,8 +359,7 @@
         case ACTIVITY_PAUSED_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder token = data.readStrongBinder();
-            Bundle map = data.readBundle();
-            activityPaused(token, map);
+            activityPaused(token);
             reply.writeNoException();
             return true;
         }
@@ -368,10 +367,11 @@
         case ACTIVITY_STOPPED_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder token = data.readStrongBinder();
+            Bundle map = data.readBundle();
             Bitmap thumbnail = data.readInt() != 0
                 ? Bitmap.CREATOR.createFromParcel(data) : null;
             CharSequence description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(data);
-            activityStopped(token, thumbnail, description);
+            activityStopped(token, map, thumbnail, description);
             reply.writeNoException();
             return true;
         }
@@ -1688,25 +1688,25 @@
         data.recycle();
         reply.recycle();
     }
-    public void activityPaused(IBinder token, Bundle state) throws RemoteException
+    public void activityPaused(IBinder token) throws RemoteException
+    {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(token);
+        mRemote.transact(ACTIVITY_PAUSED_TRANSACTION, data, reply, 0);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
+    public void activityStopped(IBinder token, Bundle state,
+            Bitmap thumbnail, CharSequence description) throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(token);
         data.writeBundle(state);
-        mRemote.transact(ACTIVITY_PAUSED_TRANSACTION, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-    public void activityStopped(IBinder token,
-                                Bitmap thumbnail, CharSequence description) throws RemoteException
-    {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeStrongBinder(token);
         if (thumbnail != null) {
             data.writeInt(1);
             thumbnail.writeToParcel(data, 0);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index a8f08c2..45500bc 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -239,6 +239,14 @@
             nextIdle = null;
         }
 
+        public boolean isPreHoneycomb() {
+            if (activity != null) {
+                return activity.getApplicationInfo().targetSdkVersion
+                        < android.os.Build.VERSION_CODES.HONEYCOMB;
+            }
+            return false;
+        }
+
         public String toString() {
             ComponentName componentName = intent.getComponent();
             return "ActivityRecord{"
@@ -2299,39 +2307,42 @@
 
     private int mThumbnailWidth = -1;
     private int mThumbnailHeight = -1;
+    private Bitmap mAvailThumbnailBitmap = null;
+    private Canvas mThumbnailCanvas = null;
 
     private final Bitmap createThumbnailBitmap(ActivityClientRecord r) {
-        Bitmap thumbnail = null;
+        Bitmap thumbnail = mAvailThumbnailBitmap;
         try {
-            int w = mThumbnailWidth;
-            int h;
-            if (w < 0) {
-                Resources res = r.activity.getResources();
-                mThumbnailHeight = h =
-                    res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
+            if (thumbnail == null) {
+                int w = mThumbnailWidth;
+                int h;
+                if (w < 0) {
+                    Resources res = r.activity.getResources();
+                    mThumbnailHeight = h =
+                        res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
 
-                mThumbnailWidth = w =
-                    res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
-            } else {
-                h = mThumbnailHeight;
+                    mThumbnailWidth = w =
+                        res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
+                } else {
+                    h = mThumbnailHeight;
+                }
+
+                // On platforms where we don't want thumbnails, set dims to (0,0)
+                if ((w > 0) && (h > 0)) {
+                    thumbnail = Bitmap.createBitmap(w, h, THUMBNAIL_FORMAT);
+                    thumbnail.eraseColor(0);
+                }
             }
 
-            // On platforms where we don't want thumbnails, set dims to (0,0)
-            if ((w > 0) && (h > 0)) {
-                View topView = r.activity.getWindow().getDecorView();
+            Canvas cv = mThumbnailCanvas;
+            if (cv == null) {
+                mThumbnailCanvas = cv = new Canvas();
+            }
 
-                // Maximize bitmap by capturing in native aspect.
-                if (topView.getWidth() >= topView.getHeight()) {
-                    thumbnail = Bitmap.createBitmap(w, h, THUMBNAIL_FORMAT);
-                } else {
-                    thumbnail = Bitmap.createBitmap(h, w, THUMBNAIL_FORMAT);
-                }
-
-                thumbnail.eraseColor(0);
-                Canvas cv = new Canvas(thumbnail);
-                if (!r.activity.onCreateThumbnail(thumbnail, cv)) {
-                    thumbnail = null;
-                }
+            cv.setBitmap(thumbnail);
+            if (!r.activity.onCreateThumbnail(thumbnail, cv)) {
+                mAvailThumbnailBitmap = thumbnail;
+                thumbnail = null;
             }
 
         } catch (Exception e) {
@@ -2357,14 +2368,14 @@
             }
 
             r.activity.mConfigChangeFlags |= configChanges;
-            Bundle state = performPauseActivity(token, finished, true);
+            performPauseActivity(token, finished, r.isPreHoneycomb());
 
             // Make sure any pending writes are now committed.
             QueuedWork.waitToFinish();
             
             // Tell the activity manager we have paused.
             try {
-                ActivityManagerNative.getDefault().activityPaused(token, state);
+                ActivityManagerNative.getDefault().activityPaused(token);
             } catch (RemoteException ex) {
             }
         }
@@ -2404,6 +2415,8 @@
                 state = new Bundle();
                 mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
                 r.state = state;
+            } else {
+                r.state = null;
             }
             // Now we are idle.
             r.activity.mCalled = false;
@@ -2430,9 +2443,9 @@
         return state;
     }
 
-    final void performStopActivity(IBinder token) {
+    final void performStopActivity(IBinder token, boolean saveState) {
         ActivityClientRecord r = mActivities.get(token);
-        performStopActivityInner(r, null, false);
+        performStopActivityInner(r, null, false, saveState);
     }
 
     private static class StopInfo {
@@ -2447,9 +2460,18 @@
         }
     }
 
+    /**
+     * Core implementation of stopping an activity.  Note this is a little
+     * tricky because the server's meaning of stop is slightly different
+     * than our client -- for the server, stop means to save state and give
+     * it the result when it is done, but the window may still be visible.
+     * For the client, we want to call onStop()/onStart() to indicate when
+     * the activity's UI visibillity changes.
+     */
     private final void performStopActivityInner(ActivityClientRecord r,
-            StopInfo info, boolean keepShown) {
+            StopInfo info, boolean keepShown, boolean saveState) {
         if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
+        Bundle state = null;
         if (r != null) {
             if (!keepShown && r.stopped) {
                 if (r.activity.mFinished) {
@@ -2479,6 +2501,17 @@
                 }
             }
 
+            // Next have the activity save its current state and managed dialogs...
+            if (!r.activity.mFinished && saveState) {
+                if (r.state == null) {
+                    state = new Bundle();
+                    mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
+                    r.state = state;
+                } else {
+                    state = r.state;
+                }
+            }
+
             if (!keepShown) {
                 try {
                     // Now we are idle.
@@ -2530,7 +2563,7 @@
         r.activity.mConfigChangeFlags |= configChanges;
 
         StopInfo info = new StopInfo();
-        performStopActivityInner(r, info, show);
+        performStopActivityInner(r, info, show, true);
 
         if (localLOGV) Slog.v(
             TAG, "Finishing stop of " + r + ": show=" + show
@@ -2541,7 +2574,7 @@
         // Tell activity manager we have been stopped.
         try {
             ActivityManagerNative.getDefault().activityStopped(
-                r.token, info.thumbnail, info.description);
+                r.token, r.state, info.thumbnail, info.description);
         } catch (RemoteException ex) {
         }
     }
@@ -2557,7 +2590,7 @@
     private final void handleWindowVisibility(IBinder token, boolean show) {
         ActivityClientRecord r = mActivities.get(token);
         if (!show && !r.stopped) {
-            performStopActivityInner(r, null, show);
+            performStopActivityInner(r, null, show, false);
         } else if (show && r.stopped) {
             // If we are getting ready to gc after going to the background, well
             // we are back active so skip it.
@@ -2651,9 +2684,6 @@
             if (finishing) {
                 r.activity.mFinished = true;
             }
-            if (getNonConfigInstance) {
-                r.activity.mChangingConfigurations = true;
-            }
             if (!r.paused) {
                 try {
                     r.activity.mCalled = false;
@@ -2924,9 +2954,11 @@
         r.onlyLocalRequest = tmp.onlyLocalRequest;
         Intent currentIntent = r.activity.mIntent;
 
+        r.activity.mChangingConfigurations = true;
+
         Bundle savedState = null;
         if (!r.paused) {
-            savedState = performPauseActivity(r.token, false, true);
+            savedState = performPauseActivity(r.token, false, r.isPreHoneycomb());
         }
 
         handleDestroyActivity(r.token, false, configChanges, true);
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index dc18083..abffbdb 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -119,10 +119,10 @@
     public void attachApplication(IApplicationThread app) throws RemoteException;
     /* oneway */
     public void activityIdle(IBinder token, Configuration config) throws RemoteException;
-    public void activityPaused(IBinder token, Bundle state) throws RemoteException;
+    public void activityPaused(IBinder token) throws RemoteException;
     /* oneway */
-    public void activityStopped(IBinder token,
-                                Bitmap thumbnail, CharSequence description) throws RemoteException;
+    public void activityStopped(IBinder token, Bundle state,
+            Bitmap thumbnail, CharSequence description) throws RemoteException;
     /* oneway */
     public void activityDestroyed(IBinder token) throws RemoteException;
     public String getCallingPackage(IBinder token) throws RemoteException;
diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java
index 524de6f..5da04f1 100644
--- a/core/java/android/app/LocalActivityManager.java
+++ b/core/java/android/app/LocalActivityManager.java
@@ -176,7 +176,7 @@
                 }
                 if (desiredState == CREATED) {
                     if (localLOGV) Log.v(TAG, r.id + ": stopping");
-                    mActivityThread.performStopActivity(r);
+                    mActivityThread.performStopActivity(r, false);
                     r.curState = CREATED;
                 }
                 return;
@@ -191,7 +191,7 @@
                     if (localLOGV) Log.v(TAG, r.id + ": pausing");
                     performPause(r, mFinishing);
                     if (localLOGV) Log.v(TAG, r.id + ": stopping");
-                    mActivityThread.performStopActivity(r);
+                    mActivityThread.performStopActivity(r, false);
                     r.curState = CREATED;
                 }
                 return;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index b27f4cf..7ca6270 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -145,7 +145,7 @@
      * tied to the lifetime of the process rather than the current component.
      *
      * <p>Consider for example how this interacts with
-     * {@ #registerReceiver(BroadcastReceiver, IntentFilter)}:
+     * {@link #registerReceiver(BroadcastReceiver, IntentFilter)}:
      * <ul>
      * <li> <p>If used from an Activity context, the receiver is being registered
      * within that activity.  This means that you are expected to unregister
diff --git a/core/java/android/nfc/INfcTag.aidl b/core/java/android/nfc/INfcTag.aidl
index ad3c1bb..f5c79e7 100644
--- a/core/java/android/nfc/INfcTag.aidl
+++ b/core/java/android/nfc/INfcTag.aidl
@@ -37,4 +37,5 @@
     int write(int nativeHandle, in NdefMessage msg);
     int makeReadOnly(int nativeHandle);
     int getModeHint(int nativeHandle);
-}
\ No newline at end of file
+    int formatNdef(int nativeHandle, in byte[] key);
+}
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
index ad05496..36de915 100644
--- a/core/java/android/nfc/Tag.java
+++ b/core/java/android/nfc/Tag.java
@@ -21,6 +21,7 @@
 import android.nfc.technology.MifareUltralight;
 import android.nfc.technology.NfcV;
 import android.nfc.technology.Ndef;
+import android.nfc.technology.NdefFormatable;
 import android.nfc.technology.NfcA;
 import android.nfc.technology.NfcB;
 import android.nfc.technology.NfcF;
@@ -154,13 +155,12 @@
                 case TagTechnology.NFC_V: {
                     return new NfcV(adapter, this, extras);
                 }
-                case TagTechnology.MIFARE_CLASSIC_NDEF:
-                case TagTechnology.TYPE_1:
-                case TagTechnology.TYPE_2:
-                case TagTechnology.TYPE_3:
-                case TagTechnology.TYPE_4: {
+                case TagTechnology.NDEF: {
                     return new Ndef(adapter, this, tech, extras);
                 }
+                case TagTechnology.NDEF_FORMATABLE: {
+                    return new NdefFormatable(adapter, this, tech, extras);
+                }
                 case TagTechnology.NFC_F: {
                     return new NfcF(adapter, this, extras);
                 }
diff --git a/core/java/android/nfc/technology/Ndef.java b/core/java/android/nfc/technology/Ndef.java
index 22460cf..c856646 100644
--- a/core/java/android/nfc/technology/Ndef.java
+++ b/core/java/android/nfc/technology/Ndef.java
@@ -44,12 +44,25 @@
     public static final int NDEF_MODE_WRITE_MANY = 4;
     public static final int NDEF_MODE_UNKNOWN = 5;
 
+    /** @hide */
+    public static final String EXTRA_NDEF_MSG = "ndefmsg";
+
+    /** @hide */
+    public static final String EXTRA_NDEF_MAXLENGTH = "ndefmaxlength";
+
+    private final int maxNdefSize;
+
     /**
      * Internal constructor, to be used by NfcAdapter
      * @hide
      */
     public Ndef(NfcAdapter adapter, Tag tag, int tech, Bundle extras) throws RemoteException {
         super(adapter, tag, tech);
+        if (extras != null) {
+            maxNdefSize = extras.getInt(EXTRA_NDEF_MAXLENGTH);
+        } else {
+            maxNdefSize = 0;  //TODO: throw exception
+        }
     }
 
     /**
@@ -92,7 +105,7 @@
      * Get maximum NDEF message size in bytes
      */
     public int getSize() {
-        throw new UnsupportedOperationException();
+        return maxNdefSize;
     }
 
     /**
diff --git a/core/java/android/nfc/technology/NdefFormatable.java b/core/java/android/nfc/technology/NdefFormatable.java
index 7c4f9ab..3ed37a5 100644
--- a/core/java/android/nfc/technology/NdefFormatable.java
+++ b/core/java/android/nfc/technology/NdefFormatable.java
@@ -56,7 +56,37 @@
      * Formats a tag as NDEF, if possible. You may supply a first
      * NdefMessage to be written on the tag.
      */
-    public void format(NdefMessage firstMessage) throws IOException {
-      throw new UnsupportedOperationException();
+    public void format(NdefMessage firstMessage) throws IOException, FormatException {
+        try {
+            byte[] DEFAULT_KEY = {(byte)0xFF,(byte)0xFF,(byte)0xFF,
+                                  (byte)0xFF,(byte)0xFF,(byte)0xFF};
+            int serviceHandle = mTag.getServiceHandle();
+            int errorCode = mTagService.formatNdef(serviceHandle, DEFAULT_KEY);
+            switch (errorCode) {
+                case ErrorCodes.SUCCESS:
+                    break;
+                case ErrorCodes.ERROR_IO:
+                    throw new IOException();
+                case ErrorCodes.ERROR_INVALID_PARAM:
+                    throw new FormatException();
+                default:
+                    // Should not happen
+                    throw new IOException();
+            }
+            errorCode = mTagService.write(serviceHandle, firstMessage);
+            switch (errorCode) {
+                case ErrorCodes.SUCCESS:
+                    break;
+                case ErrorCodes.ERROR_IO:
+                    throw new IOException();
+                case ErrorCodes.ERROR_INVALID_PARAM:
+                    throw new FormatException();
+                default:
+                    // Should not happen
+                    throw new IOException();
+            }
+        } catch (RemoteException e) {
+            attemptDeadServiceRecovery(e);
+        }
     }
 }
diff --git a/core/java/android/nfc/technology/TagTechnology.java b/core/java/android/nfc/technology/TagTechnology.java
index 9dfb297..4704f2b 100644
--- a/core/java/android/nfc/technology/TagTechnology.java
+++ b/core/java/android/nfc/technology/TagTechnology.java
@@ -49,22 +49,7 @@
     /**
      * This object is an instance of {@link Ndef}
      */
-    public static final int TYPE_1 = 101;
-
-    /**
-     * This object is an instance of {@link Ndef}
-     */
-    public static final int TYPE_2 = 102;
-
-    /**
-     * This object is an instance of {@link Ndef}
-     */
-    public static final int TYPE_3 = 103;
-
-    /**
-     * This object is an instance of {@link Ndef}
-     */
-    public static final int TYPE_4 = 104;
+    public static final int NDEF = 101;
 
     /**
      * This object is an instance of {@link NdefFormatable}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index b4c6a2923..6e50e97 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -200,6 +200,8 @@
          * <ul>
          * <li> The default theme for applications is now dark holographic:
          *      {@link android.R.style#Theme_Holo}.
+         * <li> The activity lifecycle has changed slightly as per
+         * {@link android.app.Activity}.
          * </ul>
          */
         public static final int HONEYCOMB = CUR_DEVELOPMENT;
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index beda099..0d6966f 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -21,6 +21,7 @@
 import com.android.internal.view.IInputMethodClient;
 
 import android.content.res.Configuration;
+import android.graphics.Bitmap;
 import android.view.IApplicationToken;
 import android.view.IOnKeyguardExitResult;
 import android.view.IRotationWatcher;
@@ -182,4 +183,9 @@
 	 * @hide
 	 */
 	void thawRotation();
+
+	/**
+	 * Create a screenshot of the applications currently displayed.
+	 */
+	Bitmap screenshotApplications(int maxWidth, int maxHeight);
 }
diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java
index 97bd8dd..5c4abd5 100644
--- a/core/java/android/view/KeyCharacterMap.java
+++ b/core/java/android/view/KeyCharacterMap.java
@@ -144,6 +144,8 @@
     private static native void nativeDispose(int ptr);
 
     private static native char nativeGetCharacter(int ptr, int keyCode, int metaState);
+    private static native boolean nativeGetFallbackAction(int ptr, int keyCode, int metaState,
+            FallbackAction outFallbackAction);
     private static native char nativeGetNumber(int ptr, int keyCode);
     private static native char nativeGetMatch(int ptr, int keyCode, char[] chars, int metaState);
     private static native char nativeGetDisplayLabel(int ptr, int keyCode);
@@ -206,14 +208,9 @@
      * @return The associated character or combining accent, or 0 if none.
      */
     public int get(int keyCode, int metaState) {
-        if ((metaState & MetaKeyKeyListener.META_CAP_LOCKED) != 0) {
-            metaState |= KeyEvent.META_CAPS_LOCK_ON;
-        }
-        if ((metaState & MetaKeyKeyListener.META_ALT_LOCKED) != 0) {
-            metaState |= KeyEvent.META_ALT_ON;
-        }
-
+        metaState = applyLockedModifiers(metaState);
         char ch = nativeGetCharacter(mPtr, keyCode, metaState);
+
         int map = COMBINING.get(ch);
         if (map != 0) {
             return map;
@@ -223,6 +220,34 @@
     }
 
     /**
+     * Gets the fallback action to perform if the application does not
+     * handle the specified key.
+     * <p>
+     * When an application does not handle a particular key, the system may
+     * translate the key to an alternate fallback key (specified in the
+     * fallback action) and dispatch it to the application.
+     * The event containing the fallback key is flagged
+     * with {@link KeyEvent#FLAG_FALLBACK}.
+     * </p>
+     *
+     * @param keyCode The key code.
+     * @param metaState The meta key modifier state.
+     * @param outFallbackAction The fallback action object to populate.
+     * @return True if a fallback action was found, false otherwise.
+     *
+     * @hide
+     */
+    public boolean getFallbackAction(int keyCode, int metaState,
+            FallbackAction outFallbackAction) {
+        if (outFallbackAction == null) {
+            throw new IllegalArgumentException("fallbackAction must not be null");
+        }
+
+        metaState = applyLockedModifiers(metaState);
+        return nativeGetFallbackAction(mPtr, keyCode, metaState, outFallbackAction);
+    }
+
+    /**
      * Gets the number or symbol associated with the key.
      * <p>
      * The character value is returned, not the numeric value.
@@ -277,6 +302,8 @@
         if (chars == null) {
             throw new IllegalArgumentException("chars must not be null.");
         }
+
+        metaState = applyLockedModifiers(metaState);
         return nativeGetMatch(mPtr, keyCode, chars, metaState);
     }
 
@@ -509,6 +536,16 @@
         return ret;
     }
 
+    private static int applyLockedModifiers(int metaState) {
+        if ((metaState & MetaKeyKeyListener.META_CAP_LOCKED) != 0) {
+            metaState |= KeyEvent.META_CAPS_LOCK_ON;
+        }
+        if ((metaState & MetaKeyKeyListener.META_ALT_LOCKED) != 0) {
+            metaState |= KeyEvent.META_ALT_ON;
+        }
+        return metaState;
+    }
+
     /**
      * Maps Unicode combining diacritical to display-form dead key
      * (display character shifted left 16 bits).
@@ -670,4 +707,14 @@
             super(msg);
         }
     }
+
+    /**
+     * Specifies a substitute key code and meta state as a fallback action
+     * for an unhandled key.
+     * @hide
+     */
+    public static final class FallbackAction {
+        public int keyCode;
+        public int metaState;
+    }
 }
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 03407a3..43b77e6 100755
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -529,15 +529,17 @@
     /** Key code constant: Blue "programmable" key.
      * On TV remotes, acts as a contextual/programmable key. */
     public static final int KEYCODE_PROG_BLUE       = 186;
+    /** Key code constant: App switch key.
+     * Should bring up the application switcher dialog. */
+    public static final int KEYCODE_APP_SWITCH      = 187;
 
-    private static final int LAST_KEYCODE           = KEYCODE_PROG_BLUE;
+    private static final int LAST_KEYCODE           = KEYCODE_APP_SWITCH;
 
     // NOTE: If you add a new keycode here you must also add it to:
     //  isSystem()
     //  native/include/android/keycodes.h
     //  frameworks/base/include/ui/KeycodeLabels.h
     //  external/webkit/WebKit/android/plugins/ANPKeyCodes.h
-    //  tools/puppet_master/PuppetMaster/nav_keys.py
     //  frameworks/base/core/res/res/values/attrs.xml
     //  emulator?
     //
@@ -737,6 +739,7 @@
         "KEYCODE_PROG_GREEN",
         "KEYCODE_PROG_YELLOW",
         "KEYCODE_PROG_BLUE",
+        "KEYCODE_APP_SWITCH",
     };
 
     // Symbolic names of all metakeys in bit order from least significant to most significant.
@@ -1056,7 +1059,17 @@
      * the tracking to be canceled.
      */
     public static final int FLAG_TRACKING = 0x200;
-    
+
+    /**
+     * Set when a key event has been synthesized to implement default behavior
+     * for an event that the application did not handle.
+     * Fallback key events are generated by unhandled trackball motions
+     * (to emulate a directional keypad) and by certain unhandled key presses
+     * that are declared in the key map (such as special function numeric keypad
+     * keys when numlock is off).
+     */
+    public static final int FLAG_FALLBACK = 0x400;
+
     /**
      * Private control to determine when an app is tracking a key sequence.
      * @hide
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 1f5bb5d..ad96686 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -556,7 +556,7 @@
  * improve the security of views that provide access to sensitive functionality.
  * </p><p>
  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured} or set the
- * andoird:filterTouchesWhenObscured attribute to true.  When enabled, the framework
+ * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
  * will discard touches that are received whenever the view's window is obscured by
  * another visible window.  As a result, the view will not receive touches whenever a
  * toast, dialog or other window appears above the view's window.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 7b81b8f..a9aa8f9 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -4213,7 +4213,7 @@
         boolean noneOfTheChildrenAreTransparent = true;
         for (int i = 0; i < count; i++) {
             final View child = children[i];
-            if ((child.mViewFlags & VISIBILITY_MASK) != GONE || child.getAnimation() != null) {
+            if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {
                 if (!child.gatherTransparentRegion(region)) {
                     noneOfTheChildrenAreTransparent = false;
                 }
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 53cff91..9bda637 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -2310,21 +2310,23 @@
         }
 
         final int action = event.getAction();
-        final int metastate = event.getMetaState();
+        final int metaState = event.getMetaState();
         switch (action) {
             case MotionEvent.ACTION_DOWN:
                 x.reset(2);
                 y.reset(2);
                 deliverKeyEvent(new KeyEvent(curTime, curTime,
-                        KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER,
-                        0, metastate), false);
+                        KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER, 0, metaState,
+                        KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
+                        InputDevice.SOURCE_KEYBOARD), false);
                 break;
             case MotionEvent.ACTION_UP:
                 x.reset(2);
                 y.reset(2);
                 deliverKeyEvent(new KeyEvent(curTime, curTime,
-                        KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER,
-                        0, metastate), false);
+                        KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER, 0, metaState,
+                        KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
+                        InputDevice.SOURCE_KEYBOARD), false);
                 break;
         }
 
@@ -2374,9 +2376,11 @@
                 if (DEBUG_TRACKBALL) Log.v("foo", "Delivering fake DPAD: "
                         + keycode);
                 movement--;
+                int repeatCount = accelMovement - movement;
                 deliverKeyEvent(new KeyEvent(curTime, curTime,
-                        KeyEvent.ACTION_MULTIPLE, keycode,
-                        accelMovement-movement, metastate), false);
+                        KeyEvent.ACTION_MULTIPLE, keycode, repeatCount, metaState,
+                        KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
+                        InputDevice.SOURCE_KEYBOARD), false);
             }
             while (movement > 0) {
                 if (DEBUG_TRACKBALL) Log.v("foo", "Delivering fake DPAD: "
@@ -2384,10 +2388,14 @@
                 movement--;
                 curTime = SystemClock.uptimeMillis();
                 deliverKeyEvent(new KeyEvent(curTime, curTime,
-                        KeyEvent.ACTION_DOWN, keycode, 0, event.getMetaState()), false);
+                        KeyEvent.ACTION_DOWN, keycode, 0, metaState,
+                        KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
+                        InputDevice.SOURCE_KEYBOARD), false);
                 deliverKeyEvent(new KeyEvent(curTime, curTime,
-                        KeyEvent.ACTION_UP, keycode, 0, metastate), false);
-            }
+                        KeyEvent.ACTION_UP, keycode, 0, metaState,
+                        KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FALLBACK,
+                        InputDevice.SOURCE_KEYBOARD), false);
+                }
             mLastTrackballTime = curTime;
         }
 
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index af36d80..3479bf5 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -587,9 +587,10 @@
      *            event will normally go.
      * @param event The key event.
      * @param policyFlags The policy flags associated with the key.
-     * @return Returns true if the policy consumed the event.
+     * @return Returns an alternate key event to redispatch as a fallback, or null to give up.
+     * The caller is responsible for recycling the key event.
      */
-    public boolean dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags);
+    public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags);
 
     /**
      * Called when layout of the windows is about to start.
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index bf8f7db..c6cf918 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -322,8 +322,19 @@
         }
     }
 
+    private class InnerScrollChangedListener implements ViewTreeObserver.OnScrollChangedListener {
+        public void onScrollChanged() {
+            if (isShown()) {
+                setGLRectViewport();
+            }
+        }
+    }
+
     // The listener to capture global layout change event.
-    private InnerGlobalLayoutListener mListener = null;
+    private InnerGlobalLayoutListener mGlobalLayoutListener = null;
+
+    // The listener to capture scroll event.
+    private InnerScrollChangedListener mScrollChangedListener = null;
 
     // if AUTO_REDRAW_HACK is true, then the CALL key will toggle redrawing
     // the screen all-the-time. Good for profiling our drawing code
@@ -937,28 +948,28 @@
      * @param context A Context object used to access application assets.
      * @param attrs An AttributeSet passed to our parent.
      * @param defStyle The default style resource ID.
-     * @param javascriptInterfaces is a Map of interface names, as keys, and
+     * @param javaScriptInterfaces is a Map of interface names, as keys, and
      * object implementing those interfaces, as values.
      * @hide pending API council approval.
      */
     protected WebView(Context context, AttributeSet attrs, int defStyle,
-            Map<String, Object> javascriptInterfaces, boolean privateBrowsing) {
+            Map<String, Object> javaScriptInterfaces, boolean privateBrowsing) {
         super(context, attrs, defStyle);
 
         // Used by the chrome stack to find application paths
         JniUtil.setContext(context);
 
         if (AccessibilityManager.getInstance(context).isEnabled()) {
-            if (javascriptInterfaces == null) {
-                javascriptInterfaces = new HashMap<String, Object>();
+            if (javaScriptInterfaces == null) {
+                javaScriptInterfaces = new HashMap<String, Object>();
             }
-            exposeAccessibilityJavaScriptApi(javascriptInterfaces);
+            exposeAccessibilityJavaScriptApi(javaScriptInterfaces);
         }
 
         mCallbackProxy = new CallbackProxy(context, this);
         mViewManager = new ViewManager(this);
         L10nUtils.loadStrings(context);
-        mWebViewCore = new WebViewCore(context, this, mCallbackProxy, javascriptInterfaces);
+        mWebViewCore = new WebViewCore(context, this, mCallbackProxy, javaScriptInterfaces);
         mDatabase = WebViewDatabase.getInstance(context);
         mScroller = new OverScroller(context, null, 0, 0, false); //TODO Use OverScroller's flywheel
         mZoomManager = new ZoomManager(this, mCallbackProxy);
@@ -1105,10 +1116,10 @@
      * interfaces map provided by the WebView client. In case of conflicting
      * alias with the one of the accessibility API the user specified one wins.
      *
-     * @param javascriptInterfaces A map with interfaces to be exposed to JavaScript.
+     * @param javaScriptInterfaces A map with interfaces to be exposed to JavaScript.
      */
-    private void exposeAccessibilityJavaScriptApi(Map<String, Object> javascriptInterfaces) {
-        if (javascriptInterfaces.containsKey(ALIAS_ACCESSIBILITY_JS_INTERFACE)) {
+    private void exposeAccessibilityJavaScriptApi(Map<String, Object> javaScriptInterfaces) {
+        if (javaScriptInterfaces.containsKey(ALIAS_ACCESSIBILITY_JS_INTERFACE)) {
             Log.w(LOGTAG, "JavaScript interface mapped to \"" + ALIAS_ACCESSIBILITY_JS_INTERFACE
                     + "\" overrides the accessibility API JavaScript interface. No accessibility"
                     + "API will be exposed to JavaScript!");
@@ -1116,7 +1127,7 @@
         }
 
         // expose the TTS for now ...
-        javascriptInterfaces.put(ALIAS_ACCESSIBILITY_JS_INTERFACE,
+        javaScriptInterfaces.put(ALIAS_ACCESSIBILITY_JS_INTERFACE,
                 new TextToSpeech(getContext(), null));
     }
 
@@ -1394,7 +1405,7 @@
             mPrivateHandler.removeCallbacksAndMessages(null);
             mCallbackProxy.removeCallbacksAndMessages(null);
             // Wake up the WebCore thread just in case it is waiting for a
-            // javascript dialog.
+            // JavaScript dialog.
             synchronized (mCallbackProxy) {
                 mCallbackProxy.notify();
             }
@@ -1433,7 +1444,7 @@
 
     /**
      * Inform WebView of the network state. This is used to set
-     * the javascript property window.navigator.isOnline and
+     * the JavaScript property window.navigator.isOnline and
      * generates the online/offline event as specified in HTML5, sec. 5.7.7
      * @param networkUp boolean indicating if network is available
      */
@@ -2100,9 +2111,9 @@
 
     /**
      * Return a HitTestResult based on the current cursor node. If a HTML::a tag
-     * is found and the anchor has a non-javascript url, the HitTestResult type
+     * is found and the anchor has a non-JavaScript url, the HitTestResult type
      * is set to SRC_ANCHOR_TYPE and the url is set in the "extra" field. If the
-     * anchor does not have a url or if it is a javascript url, the type will
+     * anchor does not have a url or if it is a JavaScript url, the type will
      * be UNKNOWN_TYPE and the url has to be retrieved through
      * {@link #requestFocusNodeHref} asynchronously. If a HTML::img tag is
      * found, the HitTestResult type is set to IMAGE_TYPE and the url is set in
@@ -2757,7 +2768,7 @@
     }
 
     /**
-     * Pause all layout, parsing, and javascript timers for all webviews. This
+     * Pause all layout, parsing, and JavaScript timers for all webviews. This
      * is a global requests, not restricted to just this webview. This can be
      * useful if the application has been paused.
      */
@@ -2766,7 +2777,7 @@
     }
 
     /**
-     * Resume all layout, parsing, and javascript timers for all webviews.
+     * Resume all layout, parsing, and JavaScript timers for all webviews.
      * This will resume dispatching all timers.
      */
     public void resumeTimers() {
@@ -2774,13 +2785,12 @@
     }
 
     /**
-     * Call this to pause any extra processing associated with this view and
-     * its associated DOM/plugins/javascript/etc. For example, if the view is
-     * taken offscreen, this could be called to reduce unnecessary CPU and/or
-     * network traffic. When the view is again "active", call onResume().
+     * Call this to pause any extra processing associated with this WebView and
+     * its associated DOM, plugins, JavaScript etc. For example, if the WebView
+     * is taken offscreen, this could be called to reduce unnecessary CPU or
+     * network traffic. When the WebView is again "active", call onResume().
      *
-     * Note that this differs from pauseTimers(), which affects all views/DOMs
-     * @hide
+     * Note that this differs from pauseTimers(), which affects all WebViews.
      */
     public void onPause() {
         if (!mIsPaused) {
@@ -2790,8 +2800,7 @@
     }
 
     /**
-     * Call this to balanace a previous call to onPause()
-     * @hide
+     * Call this to resume a WebView after a previous call to onPause().
      */
     public void onResume() {
         if (mIsPaused) {
@@ -3443,7 +3452,7 @@
 
     /**
      * Set the chrome handler. This is an implementation of WebChromeClient for
-     * use in handling Javascript dialogs, favicons, titles, and the progress.
+     * use in handling JavaScript dialogs, favicons, titles, and the progress.
      * This will replace the current handler.
      * @param client An implementation of WebChromeClient.
      */
@@ -3506,8 +3515,8 @@
     }
 
     /**
-     * Use this function to bind an object to Javascript so that the
-     * methods can be accessed from Javascript.
+     * Use this function to bind an object to JavaScript so that the
+     * methods can be accessed from JavaScript.
      * <p><strong>IMPORTANT:</strong>
      * <ul>
      * <li> Using addJavascriptInterface() allows JavaScript to control your
@@ -3521,7 +3530,7 @@
      * <li> The Java object that is bound runs in another thread and not in
      * the thread that it was constructed in.</li>
      * </ul></p>
-     * @param obj The class instance to bind to Javascript, null instances are
+     * @param obj The class instance to bind to JavaScript, null instances are
      *            ignored.
      * @param interfaceName The name to used to expose the instance in
      *                      JavaScript.
@@ -4748,9 +4757,15 @@
         super.onAttachedToWindow();
         if (hasWindowFocus()) setActive(true);
         final ViewTreeObserver treeObserver = getViewTreeObserver();
-        if (treeObserver != null && mListener == null) {
-            mListener = new InnerGlobalLayoutListener();
-            treeObserver.addOnGlobalLayoutListener(mListener);
+        if (treeObserver != null) {
+            if (mGlobalLayoutListener == null) {
+                mGlobalLayoutListener = new InnerGlobalLayoutListener();
+                treeObserver.addOnGlobalLayoutListener(mGlobalLayoutListener);
+            }
+            if (mScrollChangedListener == null) {
+                mScrollChangedListener = new InnerScrollChangedListener();
+                treeObserver.addOnScrollChangedListener(mScrollChangedListener);
+            }
         }
     }
 
@@ -4761,9 +4776,15 @@
         if (hasWindowFocus()) setActive(false);
 
         final ViewTreeObserver treeObserver = getViewTreeObserver();
-        if (treeObserver != null && mListener != null) {
-            treeObserver.removeGlobalOnLayoutListener(mListener);
-            mListener = null;
+        if (treeObserver != null) {
+            if (mGlobalLayoutListener != null) {
+                treeObserver.removeGlobalOnLayoutListener(mGlobalLayoutListener);
+                mGlobalLayoutListener = null;
+            }
+            if (mScrollChangedListener != null) {
+                treeObserver.removeOnScrollChangedListener(mScrollChangedListener);
+                mScrollChangedListener = null;
+            }
         }
 
         super.onDetachedFromWindow();
@@ -6744,7 +6765,7 @@
                         mSentAutoScrollMessage = false;
                         break;
                     }
-                    scrollBy(mAutoScrollX, mAutoScrollY);
+                    pinScrollBy(mAutoScrollX, mAutoScrollY, true, 0);
                     sendEmptyMessageDelayed(
                             SCROLL_SELECT_TEXT, SELECT_SCROLL_INTERVAL);
                     break;
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 261992b..4e5bc6e 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -28,7 +28,7 @@
 import android.util.AttributeSet;
 import android.util.SparseArray;
 import android.view.LayoutInflater;
-import android.widget.NumberPicker.OnChangedListener;
+import android.widget.NumberPicker.OnChangeListener;
 
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
@@ -97,8 +97,8 @@
                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         inflater.inflate(R.layout.date_picker, this, true);
 
-        OnChangedListener onChangeListener = new OnChangedListener() {
-            public void onChanged(NumberPicker picker, int oldVal, int newVal) {
+        OnChangeListener onChangeListener = new OnChangeListener() {
+            public void onChange(NumberPicker picker, int oldVal, int newVal) {
                 notifyDateChanged();
                 updateMiniMonth();
             }
@@ -107,18 +107,18 @@
         // day
         mDayPicker = (NumberPicker) findViewById(R.id.day);
         mDayPicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
-        mDayPicker.setSpeed(100);
+        mDayPicker.setOnLongPressUpdateInterval(100);
         mDayPicker.setOnChangeListener(onChangeListener);
 
         // month
         mMonthPicker = (NumberPicker) findViewById(R.id.month);
         mMonthPicker.setRange(0, mNumberOfMonths - 1, getShortMonths());
-        mMonthPicker.setSpeed(200);
+        mMonthPicker.setOnLongPressUpdateInterval(200);
         mMonthPicker.setOnChangeListener(onChangeListener);
 
         // year
         mYearPicker = (NumberPicker) findViewById(R.id.year);
-        mYearPicker.setSpeed(100);
+        mYearPicker.setOnLongPressUpdateInterval(100);
         mYearPicker.setOnChangeListener(onChangeListener);
         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DatePicker);
         int mStartYear = a.getInt(R.styleable.DatePicker_startYear, DEFAULT_START_YEAR);
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index bdd2e2c..805bc08 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -50,10 +50,18 @@
 import android.view.inputmethod.InputMethodManager;
 
 /**
- * A view for selecting a number For a dialog using this view, see
- * {@link android.app.TimePickerDialog}.
- *
- * @hide
+ * A widget that enables the user to select a number form a predefined range.
+ * The widget presents an input filed and up and down buttons for selecting the
+ * current value. Pressing/long pressing the up and down buttons increments and
+ * decrements the current value respectively. Touching the input filed shows a
+ * scroll wheel, tapping on which while shown and not moving allows direct edit
+ * of the current value. Sliding motions up or down hide the buttons and the
+ * input filed, show the scroll wheel, and rotate the latter. Flinging is
+ * also supported. The widget enables mapping from positions to strings such
+ * that instead the position index the corresponding string is displayed.
+ * <p>
+ * For an example of using this widget, see {@link android.widget.TimePicker}.
+ * </p>
  */
 @Widget
 public class NumberPicker extends LinearLayout {
@@ -166,7 +174,7 @@
     /**
      * Listener to be notified upon current value change.
      */
-    private OnChangedListener mOnChangedListener;
+    private OnChangeListener mOnChangeListener;
 
     /**
      * Listener to be notified upon scroll state change.
@@ -181,7 +189,7 @@
     /**
      * The speed for updating the value form long press.
      */
-    private long mLongPressUpdateSpeed = 300;
+    private long mLongPressUpdateInterval = 300;
 
     /**
      * Cache for the string representation of selector indices.
@@ -320,13 +328,15 @@
     /**
      * The callback interface used to indicate the number value has changed.
      */
-    public interface OnChangedListener {
+    public interface OnChangeListener {
         /**
+         * Called upon a change of the current value.
+         *
          * @param picker The NumberPicker associated with this listener.
          * @param oldVal The previous value.
          * @param newVal The new value.
          */
-        void onChanged(NumberPicker picker, int oldVal, int newVal);
+        void onChange(NumberPicker picker, int oldVal, int newVal);
     }
 
     /**
@@ -356,18 +366,34 @@
          * @param scrollState The current scroll state. One of {@link #SCROLL_STATE_IDLE},
          * {@link #SCROLL_STATE_TOUCH_SCROLL} or {@link #SCROLL_STATE_IDLE}.
          */
-        public void onScrollStateChanged(NumberPicker view, int scrollState);
+        public void onScrollStateChange(NumberPicker view, int scrollState);
     }
 
     /**
-     * Interface used to format the number into a string for presentation
+     * Interface used to format the number into a string for presentation.
      */
     public interface Formatter {
-        String toString(int value);
+
+        /**
+         * Formats a string representation of the current index.
+         *
+         * @param value The currently selected value.
+         * @return A formatted string representation.
+         */
+        public String toString(int value);
     }
 
     /**
-     * Create a new number picker
+     * Create a new number picker.
+     *
+     * @param context The application environment.
+     */
+    public NumberPicker(Context context) {
+        this(context, null);
+    }
+
+    /**
+     * Create a new number picker.
      *
      * @param context The application environment.
      * @param attrs A collection of attributes.
@@ -735,17 +761,22 @@
         }
     }
 
-    /**
-     * Set the callback that indicates the number has been adjusted by the user.
-     *
-     * @param onChangeListener the callback, should not be null.
-     */
-    public void setOnChangeListener(OnChangedListener onChangeListener) {
-        mOnChangedListener = onChangeListener;
+    @Override
+    public int getSolidColor() {
+        return mSolidColor;
     }
 
     /**
-     * Set the callback that in notified for scroll state changes.
+     * Sets the listener to be notified on change of the current value.
+     *
+     * @param onChangeListener The listener.
+     */
+    public void setOnChangeListener(OnChangeListener onChangeListener) {
+        mOnChangeListener = onChangeListener;
+    }
+
+    /**
+     * Set listener to be notified for scroll state changes.
      *
      * @param onScrollListener the callback, should not be null.
      */
@@ -754,10 +785,16 @@
     }
 
     /**
-     * Set the formatter that will be used to format the number for presentation
+     * Set the formatter to be used for formatting the current value.
+     * <p>
+     * Note: If you have provided alternative values for the selected positons
+     *       this formatter is never invoked.
+     * </p>
      *
      * @param formatter the formatter object. If formatter is null,
-     *            String.valueOf() will be used
+     *            String.valueOf() will be used.
+     *
+     * @see #setRange(int, int, String[])
      */
     public void setFormatter(Formatter formatter) {
         mFormatter = formatter;
@@ -777,11 +814,11 @@
     /**
      * Set the range of numbers allowed for the number picker. The current value
      * will be automatically set to the start. Also provide a mapping for values
-     * used to display to the user.
+     * used to display to the user instead of the numbers in the range.
      *
-     * @param start the start of the range (inclusive)
-     * @param end the end of the range (inclusive)
-     * @param displayedValues the values displayed to the user.
+     * @param start The start of the range (inclusive).
+     * @param end The end of the range (inclusive).
+     * @param displayedValues The values displayed to the user.
      */
     public void setRange(int start, int end, String[] displayedValues) {
         boolean wrapSelector = (end - start) >= mSelectorIndices.length;
@@ -792,12 +829,20 @@
      * Set the range of numbers allowed for the number picker. The current value
      * will be automatically set to the start. Also provide a mapping for values
      * used to display to the user.
+     * <p>
+     * Note: The <code>wrapSelectorWheel</code> argument is ignored if the range
+     * (difference between <code>start</code> and <code>end</code>) us less than
+     * five since this is the number of values shown by the selector wheel.
+     * </p>
      *
      * @param start the start of the range (inclusive)
      * @param end the end of the range (inclusive)
      * @param displayedValues the values displayed to the user.
+     * @param wrapSelectorWheel Whether to wrap the selector wheel.
+     *
+     * @see #setWrapSelectorWheel(boolean)
      */
-    public void setRange(int start, int end, String[] displayedValues, boolean wrapSelector) {
+    public void setRange(int start, int end, String[] displayedValues, boolean wrapSelectorWheel) {
         if (start < 0 || end < 0) {
             throw new IllegalArgumentException("start and end must be > 0");
         }
@@ -807,7 +852,7 @@
         mEnd = end;
         mCurrent = start;
 
-        setWrapSelector(wrapSelector);
+        setWrapSelectorWheel(wrapSelectorWheel);
         updateInputTextView();
 
         if (displayedValues != null) {
@@ -826,8 +871,9 @@
      * Set the current value for the number picker.
      *
      * @param current the current value the start of the range (inclusive)
+     *
      * @throws IllegalArgumentException when current is not within the range of
-     *             of the number picker
+     *             of the number picker.
      */
     public void setCurrent(int current) {
         if (current < mStart || current > mEnd) {
@@ -839,12 +885,14 @@
     }
 
     /**
-     * Sets whether the selector shown during flinging/scrolling should wrap
-     * around the beginning and end values.
+     * Sets whether the selector wheel shown during flinging/scrolling should wrap
+     * around the beginning and end values. By default if the range is more than
+     * five (the number of items shown on the selector wheel) the selector wheel
+     * wrapping is enabled.
      *
      * @param wrapSelector Whether to wrap.
      */
-    public void setWrapSelector(boolean wrapSelector) {
+    public void setWrapSelectorWheel(boolean wrapSelector) {
         if (wrapSelector && (mEnd - mStart) < mSelectorIndices.length) {
             throw new IllegalStateException("Range less than selector items count.");
         }
@@ -856,18 +904,18 @@
     }
 
     /**
-     * Sets the speed at which the numbers will scroll when the +/- buttons are
-     * longpressed
+     * Sets the speed at which the numbers be incremented and decremented when
+     * the up and down buttons are long pressed respectively.
      *
-     * @param speed The speed (in milliseconds) at which the numbers will scroll
-     *            default 300ms
+     * @param intervalMillis The speed (in milliseconds) at which the numbers
+     *            will be incremented and decremented (default 300ms).
      */
-    public void setSpeed(long speed) {
-        mLongPressUpdateSpeed = speed;
+    public void setOnLongPressUpdateInterval(long intervalMillis) {
+        mLongPressUpdateInterval = intervalMillis;
     }
 
     /**
-     * Returns the current value of the NumberPicker
+     * Returns the current value of the NumberPicker.
      *
      * @return the current value.
      */
@@ -875,9 +923,22 @@
         return mCurrent;
     }
 
-    @Override
-    public int getSolidColor() {
-        return mSolidColor;
+    /**
+     * Returns the range lower value of the NumberPicker.
+     *
+     * @return The lower number of the range.
+     */
+    public int getRangeStart() {
+        return mStart;
+    }
+
+    /**
+     * Returns the range end value of the NumberPicker.
+     *
+     * @return The upper number of the range.
+     */
+    public int getRangeEnd() {
+        return mEnd;
     }
 
     @Override
@@ -950,24 +1011,6 @@
     }
 
     /**
-     * Returns the upper value of the range of the NumberPicker
-     *
-     * @return the uppper number of the range.
-     */
-    protected int getEndRange() {
-        return mEnd;
-    }
-
-    /**
-     * Returns the lower value of the range of the NumberPicker
-     *
-     * @return the lower number of the range.
-     */
-    protected int getBeginRange() {
-        return mStart;
-    }
-
-    /**
      * Sets the current value of this NumberPicker, and sets mPrevious to the
      * previous value. If current is greater than mEnd less than mStart, the
      * value of mCurrent is wrapped around. Subclasses can override this to
@@ -1038,7 +1081,7 @@
     private void tryNotifyScrollListener(int scrollState) {
         if (mOnScrollListener != null && mScrollState != scrollState) {
             mScrollState = scrollState;
-            mOnScrollListener.onScrollStateChanged(this, scrollState);
+            mOnScrollListener.onScrollStateChange(this, scrollState);
         }
     }
 
@@ -1238,8 +1281,8 @@
      * NumberPicker.
      */
     private void notifyChange(int previous, int current) {
-        if (mOnChangedListener != null) {
-            mOnChangedListener.onChanged(this, previous, mCurrent);
+        if (mOnChangeListener != null) {
+            mOnChangeListener.onChange(this, previous, mCurrent);
         }
     }
 
@@ -1439,7 +1482,7 @@
 
         public void run() {
             changeCurrent(mCurrent + mUpdateStep);
-            postDelayed(this, mLongPressUpdateSpeed);
+            postDelayed(this, mLongPressUpdateInterval);
         }
     }
 }
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index e66eb8d..203b637 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -25,7 +25,7 @@
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.widget.NumberPicker.OnChangedListener;
+import android.widget.NumberPicker.OnChangeListener;
 
 import java.text.DateFormatSymbols;
 import java.util.Calendar;
@@ -110,8 +110,8 @@
 
         // hour
         mHourPicker = (NumberPicker) findViewById(R.id.hour);
-        mHourPicker.setOnChangeListener(new NumberPicker.OnChangedListener() {
-            public void onChanged(NumberPicker spinner, int oldVal, int newVal) {
+        mHourPicker.setOnChangeListener(new NumberPicker.OnChangeListener() {
+            public void onChange(NumberPicker spinner, int oldVal, int newVal) {
                 mCurrentHour = newVal;
                 if (!mIs24HourView) {
                     // adjust from [1-12] to [0-11] internally, with the times
@@ -135,10 +135,10 @@
         // digits of minute
         mMinutePicker = (NumberPicker) findViewById(R.id.minute);
         mMinutePicker.setRange(0, 59);
-        mMinutePicker.setSpeed(100);
+        mMinutePicker.setOnLongPressUpdateInterval(100);
         mMinutePicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
-        mMinutePicker.setOnChangeListener(new NumberPicker.OnChangedListener() {
-            public void onChanged(NumberPicker spinner, int oldVal, int newVal) {
+        mMinutePicker.setOnChangeListener(new NumberPicker.OnChangeListener() {
+            public void onChange(NumberPicker spinner, int oldVal, int newVal) {
                 mCurrentMinute = newVal;
                 onTimeChanged();
             }
@@ -146,8 +146,8 @@
 
         // am/pm
         mAmPmPicker = (NumberPicker) findViewById(R.id.amPm);
-        mAmPmPicker.setOnChangeListener(new OnChangedListener() {
-            public void onChanged(NumberPicker picker, int oldVal, int newVal) {
+        mAmPmPicker.setOnChangeListener(new OnChangeListener() {
+            public void onChange(NumberPicker picker, int oldVal, int newVal) {
                 picker.requestFocus();
                 if (mIsAm) {
                     // Currently AM switching to PM
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index ce7ab84..3e19811 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -23,9 +23,9 @@
 import com.android.internal.widget.ActionBarView;
 
 import android.animation.Animator;
-import android.animation.ObjectAnimator;
 import android.animation.Animator.AnimatorListener;
 import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
 import android.app.ActionBar;
 import android.app.Activity;
 import android.app.Dialog;
@@ -40,10 +40,10 @@
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.Window;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 import android.widget.SpinnerAdapter;
-import android.widget.ViewAnimator;
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
@@ -67,6 +67,7 @@
     private ActionBarView mActionView;
     private ActionBarContextView mUpperContextView;
     private LinearLayout mLowerContextView;
+    private View mContentView;
 
     private ArrayList<TabImpl> mTabs = new ArrayList<TabImpl>();
 
@@ -88,7 +89,7 @@
 
     final Handler mHandler = new Handler();
 
-    private Animator mCurrentAnimation;
+    private Animator mCurrentAnim;
 
     final AnimatorListener[] mAfterAnimation = new AnimatorListener[] {
             new AnimatorListener() { // NORMAL_VIEW
@@ -101,7 +102,7 @@
                     if (mLowerContextView != null) {
                         mLowerContextView.removeAllViews();
                     }
-                    mCurrentAnimation = null;
+                    mCurrentAnim = null;
                     hideAllExcept(NORMAL_VIEW);
                 }
 
@@ -120,7 +121,7 @@
 
                 @Override
                 public void onAnimationEnd(Animator animation) {
-                    mCurrentAnimation = null;
+                    mCurrentAnim = null;
                     hideAllExcept(CONTEXT_VIEW);
                 }
 
@@ -134,9 +135,56 @@
             }
     };
 
+    final AnimatorListener mHideListener = new AnimatorListener() {
+        @Override
+        public void onAnimationStart(Animator animation) {
+        }
+
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            if (mContentView != null) {
+                mContentView.setTranslationY(0);
+            }
+            mContainerView.setVisibility(View.GONE);
+            mCurrentAnim = null;
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animation) {
+        }
+
+        @Override
+        public void onAnimationRepeat(Animator animation) {
+        }
+    };
+
+    final AnimatorListener mShowListener = new AnimatorListener() {
+        @Override
+        public void onAnimationStart(Animator animation) {
+        }
+
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            mCurrentAnim = null;
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animation) {
+        }
+
+        @Override
+        public void onAnimationRepeat(Animator animation) {
+        }
+    };
+
     public ActionBarImpl(Activity activity) {
         mActivity = activity;
-        init(activity.getWindow().getDecorView());
+        Window window = activity.getWindow();
+        View decor = window.getDecorView();
+        init(decor);
+        if (!mActivity.getWindow().hasFeature(Window.FEATURE_ACTION_BAR_OVERLAY)) {
+            mContentView = decor.findViewById(android.R.id.content);
+        }
     }
 
     public ActionBarImpl(Dialog dialog) {
@@ -444,14 +492,45 @@
 
     @Override
     public void show() {
-        // TODO animate!
+        if (mCurrentAnim != null) {
+            mCurrentAnim.end();
+        }
+        if (mContainerView.getVisibility() == View.VISIBLE) {
+            return;
+        }
         mContainerView.setVisibility(View.VISIBLE);
+        mContainerView.setAlpha(0);
+        mContainerView.setTranslationY(-mContainerView.getHeight());
+        AnimatorSet anim = new AnimatorSet();
+        AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mContainerView, "translationY", 0))
+            .with(ObjectAnimator.ofFloat(mContainerView, "alpha", 1));
+        if (mContentView != null) {
+            b.with(ObjectAnimator.ofFloat(mContentView, "translationY", -mContainerView.getHeight(), 0));
+        }
+        anim.addListener(mShowListener);
+        mCurrentAnim = anim;
+        anim.start();
     }
 
     @Override
     public void hide() {
-        // TODO animate!
-        mContainerView.setVisibility(View.GONE);
+        if (mCurrentAnim != null) {
+            mCurrentAnim.end();
+        }
+        if (mContainerView.getVisibility() == View.GONE) {
+            return;
+        }
+        mContainerView.setAlpha(1);
+        AnimatorSet anim = new AnimatorSet();
+        AnimatorSet.Builder b = anim.play(
+                ObjectAnimator.ofFloat(mContainerView, "translationY", -mContainerView.getHeight()))
+            .with(ObjectAnimator.ofFloat(mContainerView, "alpha", 0));
+        if (mContentView != null) {
+            b.with(ObjectAnimator.ofFloat(mContentView, "translationY", 0, -mContainerView.getHeight()));
+        }
+        anim.addListener(mHideListener);
+        mCurrentAnim = anim;
+        anim.start();
     }
 
     public boolean isShowing() {
@@ -459,10 +538,7 @@
     }
 
     private long animateTo(int viewIndex) {
-        // Don't wait for the current animation to finish.
-        if (mCurrentAnimation != null) {
-            mCurrentAnimation.end();
-        }
+        show();
 
         AnimatorSet set = new AnimatorSet();
 
@@ -492,7 +568,7 @@
 
         set.addListener(mAfterAnimation[viewIndex]);
 
-        mCurrentAnimation = set;
+        mCurrentAnim = set;
         set.start();
         return set.getDuration();
     }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 630830d..145feb5 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -3090,13 +3090,18 @@
                 }
             }
 
-            void readExcessivePowerFromParcelLocked(Parcel in) {
+            boolean readExcessivePowerFromParcelLocked(Parcel in) {
                 final int N = in.readInt();
                 if (N == 0) {
                     mExcessivePower = null;
-                    return;
+                    return true;
                 }
 
+                if (N > 10000) {
+                    Slog.w(TAG, "File corrupt: too many excessive power entries " + N);
+                    return false;
+                }
+                
                 mExcessivePower = new ArrayList<ExcessivePower>();
                 for (int i=0; i<N; i++) {
                     ExcessivePower ew = new ExcessivePower();
@@ -3105,6 +3110,7 @@
                     ew.usedTime = in.readLong();
                     mExcessivePower.add(ew);
                 }
+                return true;
             }
 
             void writeToParcelLocked(Parcel out) {
@@ -4700,7 +4706,7 @@
             }
 
             int NW = in.readInt();
-            if (NW > 10000) {
+            if (NW > 100) {
                 Slog.w(TAG, "File corrupt: too many wake locks " + NW);
                 return;
             }
@@ -4718,7 +4724,7 @@
             }
 
             int NP = in.readInt();
-            if (NP > 10000) {
+            if (NP > 1000) {
                 Slog.w(TAG, "File corrupt: too many sensors " + NP);
                 return;
             }
@@ -4731,7 +4737,7 @@
             }
 
             NP = in.readInt();
-            if (NP > 10000) {
+            if (NP > 1000) {
                 Slog.w(TAG, "File corrupt: too many processes " + NP);
                 return;
             }
@@ -4742,6 +4748,10 @@
                 p.mSystemTime = p.mLoadedSystemTime = in.readLong();
                 p.mStarts = p.mLoadedStarts = in.readInt();
                 int NSB = in.readInt();
+                if (NSB > 100) {
+                    Slog.w(TAG, "File corrupt: too many speed bins " + NSB);
+                    return;
+                }
                 p.mSpeedBins = new SamplingCounter[NSB];
                 for (int i=0; i<NSB; i++) {
                     if (in.readInt() != 0) {
@@ -4749,7 +4759,9 @@
                         p.mSpeedBins[i].readSummaryFromParcelLocked(in);
                     }
                 }
-                p.readExcessivePowerFromParcelLocked(in);
+                if (!p.readExcessivePowerFromParcelLocked(in)) {
+                    return;
+                }
             }
 
             NP = in.readInt();
@@ -4762,6 +4774,10 @@
                 Uid.Pkg p = u.getPackageStatsLocked(pkgName);
                 p.mWakeups = p.mLoadedWakeups = in.readInt();
                 final int NS = in.readInt();
+                if (NS > 1000) {
+                    Slog.w(TAG, "File corrupt: too many services " + NS);
+                    return;
+                }
                 for (int is = 0; is < NS; is++) {
                     String servName = in.readString();
                     Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 848bf9e..dea53bf 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -557,8 +557,6 @@
 
     public static void main(String argv[]) {
         try {
-            VMRuntime.getRuntime().setMinimumHeapSize(5 * 1024 * 1024);
-
             // Start profiling the zygote initialization.
             SamplingProfilerIntegration.start();
 
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index bcd7bae..8eeed3d 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -51,11 +51,11 @@
 	android_view_InputChannel.cpp \
 	android_view_InputQueue.cpp \
 	android_view_KeyEvent.cpp \
+	android_view_KeyCharacterMap.cpp \
 	android_view_GLES20Canvas.cpp \
 	android_view_MotionEvent.cpp \
 	android_text_AndroidCharacter.cpp \
 	android_text_AndroidBidi.cpp \
-	android_text_KeyCharacterMap.cpp \
 	android_os_Debug.cpp \
 	android_os_FileUtils.cpp \
 	android_os_MemoryFile.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index e50233e..07505a5 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -353,33 +353,12 @@
  */
 jclass AndroidRuntime::findClass(JNIEnv* env, const char* className)
 {
-    char* convName = NULL;
-
     if (env->ExceptionCheck()) {
-        LOGE("ERROR: exception pending on entry to findClass()\n");
+        LOGE("ERROR: exception pending on entry to findClass()");
         return NULL;
     }
 
     /*
-     * JNI FindClass uses class names with slashes, but ClassLoader.loadClass
-     * uses the dotted "binary name" format.  We don't need to convert the
-     * name with the new approach.
-     */
-#if 0
-    /* (convName only created if necessary -- use className) */
-    for (char* cp = const_cast<char*>(className); *cp != '\0'; cp++) {
-        if (*cp == '.') {
-            if (convName == NULL) {
-                convName = strdup(className);
-                cp = convName + (cp-className);
-                className = convName;
-            }
-            *cp = '/';
-        }
-    }
-#endif
-
-    /*
      * This is a little awkward because the JNI FindClass call uses the
      * class loader associated with the native method we're executing in.
      * Because this native method is part of a "boot" class, JNI doesn't
@@ -394,7 +373,6 @@
      * have to do things the hard way.
      */
     jclass cls = NULL;
-    //cls = env->FindClass(className);
 
     jclass javaLangClassLoader;
     jmethodID getSystemClassLoader, loadClass;
@@ -416,24 +394,21 @@
     /* create an object for the class name string; alloc could fail */
     strClassName = env->NewStringUTF(className);
     if (env->ExceptionCheck()) {
-        LOGE("ERROR: unable to convert '%s' to string\n", className);
-        goto bail;
+        LOGE("ERROR: unable to convert '%s' to string", className);
+        return NULL;
     }
-    LOGV("system class loader is %p, loading %p (%s)\n",
+    LOGV("system class loader is %p, loading %p (%s)",
         systemClassLoader, strClassName, className);
 
     /* try to find the named class */
     cls = (jclass) env->CallObjectMethod(systemClassLoader, loadClass,
                         strClassName);
     if (env->ExceptionCheck()) {
-        LOGE("ERROR: unable to load class '%s' from %p\n",
+        LOGE("ERROR: unable to load class '%s' from %p",
             className, systemClassLoader);
-        cls = NULL;
-        goto bail;
+        return NULL;
     }
 
-bail:
-    free(convName);
     return cls;
 }
 
@@ -576,6 +551,7 @@
     char dexoptFlagsBuf[PROPERTY_VALUE_MAX];
     char enableAssertBuf[sizeof("-ea:")-1 + PROPERTY_VALUE_MAX];
     char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX];
+    char heapstartsizeOptsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
     char heapsizeOptsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
     char extraOptsBuf[PROPERTY_VALUE_MAX];
     char* stackTraceFile = NULL;
@@ -650,9 +626,16 @@
     mOptions.add(opt);
     //options[curOpt++].optionString = "-verbose:class";
 
+    /*
+     * The default starting and maximum size of the heap.  Larger
+     * values should be specified in a product property override.
+     */
+    strcpy(heapstartsizeOptsBuf, "-Xms");
+    property_get("dalvik.vm.heapstartsize", heapstartsizeOptsBuf+4, "4m");
+    opt.optionString = heapstartsizeOptsBuf;
+    mOptions.add(opt);
     strcpy(heapsizeOptsBuf, "-Xmx");
     property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");
-    //LOGI("Heap size: %s", heapsizeOptsBuf);
     opt.optionString = heapsizeOptsBuf;
     mOptions.add(opt);
 
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index e72e2b6f..b9c93b8 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -322,12 +322,12 @@
 }
 
 static ssize_t getFDSize(int fd) {
-    off_t curr = ::lseek(fd, 0, SEEK_CUR);
+    off64_t curr = ::lseek64(fd, 0, SEEK_CUR);
     if (curr < 0) {
         return 0;
     }
     size_t size = ::lseek(fd, 0, SEEK_END);
-    ::lseek(fd, curr, SEEK_SET);
+    ::lseek64(fd, curr, SEEK_SET);
     return size;
 }
 
@@ -374,8 +374,8 @@
  */
 static SkStream* copyAssetToStream(Asset* asset) {
     // if we could "ref/reopen" the asset, we may not need to copy it here
-    off_t size = asset->seek(0, SEEK_SET);
-    if ((off_t)-1 == size) {
+    off64_t size = asset->seek(0, SEEK_SET);
+    if ((off64_t)-1 == size) {
         SkDebugf("---- copyAsset: asset rewind failed\n");
         return NULL;
     }
@@ -388,7 +388,7 @@
 
     SkStream* stream = new SkMemoryStream(size);
     void* data = const_cast<void*>(stream->getMemoryBase());
-    off_t len = asset->read(data, size);
+    off64_t len = asset->read(data, size);
     if (len != size) {
         SkDebugf("---- copyAsset: asset->read(%d) returned %d\n", size, len);
         delete stream;
diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp
index 1fe72e6..53a5c0a 100644
--- a/core/jni/android/graphics/Typeface.cpp
+++ b/core/jni/android/graphics/Typeface.cpp
@@ -72,8 +72,8 @@
 
 	virtual bool rewind()
     {
-        off_t pos = fAsset->seek(0, SEEK_SET);
-        return pos != (off_t)-1;
+        off64_t pos = fAsset->seek(0, SEEK_SET);
+        return pos != (off64_t)-1;
     }
     
 	virtual size_t read(void* buffer, size_t size)
@@ -88,10 +88,10 @@
             // asset->seek returns new total offset
             // we want to return amount that was skipped
             
-            off_t oldOffset = fAsset->seek(0, SEEK_CUR);
+            off64_t oldOffset = fAsset->seek(0, SEEK_CUR);
             if (-1 == oldOffset)
                 return 0;
-            off_t newOffset = fAsset->seek(size, SEEK_CUR);
+            off64_t newOffset = fAsset->seek(size, SEEK_CUR);
             if (-1 == newOffset)
                 return 0;
             
diff --git a/core/jni/android/graphics/Utils.cpp b/core/jni/android/graphics/Utils.cpp
index b6ead19..cf6977e 100644
--- a/core/jni/android/graphics/Utils.cpp
+++ b/core/jni/android/graphics/Utils.cpp
@@ -20,8 +20,8 @@
 using namespace android;
 
 bool AssetStreamAdaptor::rewind() {
-    off_t pos = fAsset->seek(0, SEEK_SET);
-    if (pos == (off_t)-1) {
+    off64_t pos = fAsset->seek(0, SEEK_SET);
+    if (pos == (off64_t)-1) {
         SkDebugf("----- fAsset->seek(rewind) failed\n");
         return false;
     }
@@ -38,12 +38,12 @@
         // asset->seek returns new total offset
         // we want to return amount that was skipped
 
-        off_t oldOffset = fAsset->seek(0, SEEK_CUR);
+        off64_t oldOffset = fAsset->seek(0, SEEK_CUR);
         if (-1 == oldOffset) {
             SkDebugf("---- fAsset->seek(oldOffset) failed\n");
             return 0;
         }
-        off_t newOffset = fAsset->seek(size, SEEK_CUR);
+        off64_t newOffset = fAsset->seek(size, SEEK_CUR);
         if (-1 == newOffset) {
             SkDebugf("---- fAsset->seek(%d) failed\n", size);
             return 0;
diff --git a/core/jni/android/graphics/Utils.h b/core/jni/android/graphics/Utils.h
index 2de41a1..9a7a697 100644
--- a/core/jni/android/graphics/Utils.h
+++ b/core/jni/android/graphics/Utils.h
@@ -51,7 +51,7 @@
     }
 private:
     int     fFD;
-    off_t   fCurr;
+    off64_t   fCurr;
 };
 
 jobject nullObjectReturn(const char msg[]);
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 2528db1..619a293 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -149,7 +149,7 @@
 
 static jobject returnParcelFileDescriptor(JNIEnv* env, Asset* a, jlongArray outOffsets)
 {
-    off_t startOffset, length;
+    off64_t startOffset, length;
     int fd = a->openFileDescriptor(&startOffset, &length);
     delete a;
     
diff --git a/core/jni/android_text_KeyCharacterMap.cpp b/core/jni/android_view_KeyCharacterMap.cpp
similarity index 78%
rename from core/jni/android_text_KeyCharacterMap.cpp
rename to core/jni/android_view_KeyCharacterMap.cpp
index a7e62c1..bfeec4f 100644
--- a/core/jni/android_text_KeyCharacterMap.cpp
+++ b/core/jni/android_view_KeyCharacterMap.cpp
@@ -29,6 +29,14 @@
     jclass clazz;
 } gKeyEventClassInfo;
 
+static struct {
+    jclass clazz;
+
+    jfieldID keyCode;
+    jfieldID metaState;
+} gFallbackActionClassInfo;
+
+
 static jint nativeLoad(JNIEnv *env, jobject clazz, jint deviceId) {
     KeyCharacterMap* map;
     status_t status = KeyCharacterMap::loadByDeviceId(deviceId, &map);
@@ -54,6 +62,21 @@
     return map->getCharacter(keyCode, metaState);
 }
 
+static jboolean nativeGetFallbackAction(JNIEnv *env, jobject clazz, jint ptr, jint keyCode,
+        jint metaState, jobject fallbackActionObj) {
+    KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr);
+    KeyCharacterMap::FallbackAction fallbackAction;
+
+    bool result = map->getFallbackAction(keyCode, metaState, &fallbackAction);
+    if (result) {
+        env->SetIntField(fallbackActionObj, gFallbackActionClassInfo.keyCode,
+                fallbackAction.keyCode);
+        env->SetIntField(fallbackActionObj, gFallbackActionClassInfo.metaState,
+                fallbackAction.metaState);
+    }
+    return result;
+}
+
 static jchar nativeGetNumber(JNIEnv *env, jobject clazz, jint ptr, jint keyCode) {
     KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr);
     return map->getNumber(keyCode);
@@ -126,6 +149,8 @@
             (void*)nativeDispose },
     { "nativeGetCharacter", "(III)C",
             (void*)nativeGetCharacter },
+    { "nativeGetFallbackAction", "(IIILandroid/view/KeyCharacterMap$FallbackAction;)Z",
+            (void*)nativeGetFallbackAction },
     { "nativeGetNumber", "(II)C",
             (void*)nativeGetNumber },
     { "nativeGetMatch", "(II[CI)C",
@@ -143,10 +168,22 @@
         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_text_KeyCharacterMap(JNIEnv* env)
 {
     FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent");
 
+    FIND_CLASS(gFallbackActionClassInfo.clazz, "android/view/KeyCharacterMap$FallbackAction");
+
+    GET_FIELD_ID(gFallbackActionClassInfo.keyCode, gFallbackActionClassInfo.clazz,
+            "keyCode", "I");
+
+    GET_FIELD_ID(gFallbackActionClassInfo.metaState, gFallbackActionClassInfo.clazz,
+            "metaState", "I");
+
     return AndroidRuntime::registerNativeMethods(env,
             "android/view/KeyCharacterMap", g_methods, NELEM(g_methods));
 }
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 81191ff..4bd91b3 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1267,6 +1267,7 @@
         <enum name="KEYCODE_PROG_GREEN" value="184" />
         <enum name="KEYCODE_PROG_YELLOW" value="185" />
         <enum name="KEYCODE_PROG_BLUE" value="186" />
+        <enum name="KEYCODE_APP_SWITCH" value="187" />
     </attr>
 
     <!-- ***************************************************************** -->
diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
index 29dee34..6da38a7 100644
--- a/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
+++ b/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
@@ -113,7 +113,7 @@
         protected void setFiredFlag(int flag) {
             synchronized (this) {
                 mFiredFlags |= flag;
-                if (mFiredFlags == mExpectedFlags) {
+                if ((mFiredFlags & mExpectedFlags) == mExpectedFlags) {
                     mCompletedTime = System.currentTimeMillis();
                 }
             }
diff --git a/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java b/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java
index 9c9d9fe..955f5e8 100644
--- a/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java
+++ b/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java
@@ -45,7 +45,7 @@
     private static final long TIMEOUT_WAIT_FOR_SELECTION_STRING = 1000;
 
     /** The timeout to wait for accessibility and the mock service to be enabled. */
-    private static final long TIMEOUT_ENABLE_ACCESSIBILITY_AND_MOCK_SERVICE = 500;
+    private static final long TIMEOUT_ENABLE_ACCESSIBILITY_AND_MOCK_SERVICE = 1000;
 
     /** The count of tests to detect when to shut down the service. */
     private static final int TEST_CASE_COUNT = 8;
diff --git a/data/keyboards/Generic.kcm b/data/keyboards/Generic.kcm
index 24b485d..14d7c80 100644
--- a/data/keyboards/Generic.kcm
+++ b/data/keyboards/Generic.kcm
@@ -42,7 +42,9 @@
     label:                              'C'
     base:                               'c'
     shift, capslock:                    'C'
-    ctrl, alt, meta:                    none
+    alt:                                '\u00e7'
+    shift+alt:                          '\u00c7'
+    ctrl, meta:                         none
 }
 
 key D {
@@ -56,7 +58,8 @@
     label:                              'E'
     base:                               'e'
     shift, capslock:                    'E'
-    ctrl, alt, meta:                    none
+    alt:                                '\u0301'
+    ctrl, meta:                         none
 }
 
 key F {
@@ -84,7 +87,8 @@
     label:                              'I'
     base:                               'i'
     shift, capslock:                    'I'
-    ctrl, alt, meta:                    none
+    alt:                                '\u0302'
+    ctrl, meta:                         none
 }
 
 key J {
@@ -119,7 +123,8 @@
     label:                              'N'
     base:                               'n'
     shift, capslock:                    'N'
-    ctrl, alt, meta:                    none
+    alt:                                '\u0303'
+    ctrl, meta:                         none
 }
 
 key O {
@@ -154,7 +159,8 @@
     label:                              'S'
     base:                               's'
     shift, capslock:                    'S'
-    ctrl, alt, meta:                    none
+    alt:                                '\u00df'
+    ctrl, meta:                         none
 }
 
 key T {
@@ -168,7 +174,8 @@
     label:                              'U'
     base:                               'u'
     shift, capslock:                    'U'
-    ctrl, alt, meta:                    none
+    alt:                                '\u0308'
+    ctrl, meta:                         none
 }
 
 key V {
@@ -253,6 +260,7 @@
     base:                               '6'
     shift:                              '^'
     ctrl, alt, meta:                    none
+    alt+shift:                          '\u0302'
 }
 
 key 7 {
@@ -279,7 +287,8 @@
 key SPACE {
     label:                              ' '
     base:                               ' '
-    ctrl, alt, meta:                    none
+    ctrl, alt:                          none
+    meta:                               fallback SEARCH
 }
 
 key ENTER {
@@ -291,7 +300,8 @@
 key TAB {
     label:                              '\t'
     base:                               '\t'
-    ctrl, alt, meta:                    none
+    ctrl, alt:                          none
+    meta:                               fallback APP_SWITCH
 }
 
 key COMMA {
@@ -319,7 +329,9 @@
     label, number:                      '`'
     base:                               '`'
     shift:                              '~'
-    ctrl, alt, meta:                    none
+    alt:                                '\u0300'
+    alt+shift:                          '\u0303'
+    ctrl, meta:                         none
 }
 
 key MINUS {
@@ -525,3 +537,11 @@
     label, number:                      '+'
     base:                               '+'
 }
+
+### Non-printing keys ###
+
+key ESCAPE {
+    base:                               fallback BACK
+    meta:                               fallback HOME
+    alt:                                fallback MENU
+}
diff --git a/data/keyboards/Vendor_05ac_Product_0239.kl b/data/keyboards/Vendor_05ac_Product_0239.kl
index 5234d58..6bd3753 100644
--- a/data/keyboards/Vendor_05ac_Product_0239.kl
+++ b/data/keyboards/Vendor_05ac_Product_0239.kl
@@ -104,7 +104,7 @@
 key 113   VOLUME_MUTE
 key 114   VOLUME_DOWN
 key 115   VOLUME_UP
-# key 120  switch applications
+key 120   APP_SWITCH
 key 125   META_LEFT
 key 126   META_RIGHT
 key 161   MEDIA_EJECT
diff --git a/data/keyboards/Vendor_22b8_Product_093d.kl b/data/keyboards/Vendor_22b8_Product_093d.kl
index 87b3c32..2749c5b 100644
--- a/data/keyboards/Vendor_22b8_Product_093d.kl
+++ b/data/keyboards/Vendor_22b8_Product_093d.kl
@@ -12,6 +12,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+#
+# Motorola Bluetooth Wireless Keyboard.
+#
+
 key 1     BACK
 key 2     1
 key 3     2
diff --git a/data/keyboards/Virtual.kcm b/data/keyboards/Virtual.kcm
index 8d3c7ac..0ce4a68 100644
--- a/data/keyboards/Virtual.kcm
+++ b/data/keyboards/Virtual.kcm
@@ -39,7 +39,9 @@
     label:                              'C'
     base:                               'c'
     shift, capslock:                    'C'
-    ctrl, alt, meta:                    none
+    alt:                                '\u00e7'
+    shift+alt:                          '\u00c7'
+    ctrl, meta:                         none
 }
 
 key D {
@@ -53,7 +55,8 @@
     label:                              'E'
     base:                               'e'
     shift, capslock:                    'E'
-    ctrl, alt, meta:                    none
+    alt:                                '\u0301'
+    ctrl, meta:                         none
 }
 
 key F {
@@ -81,7 +84,8 @@
     label:                              'I'
     base:                               'i'
     shift, capslock:                    'I'
-    ctrl, alt, meta:                    none
+    alt:                                '\u0302'
+    ctrl, meta:                         none
 }
 
 key J {
@@ -116,7 +120,8 @@
     label:                              'N'
     base:                               'n'
     shift, capslock:                    'N'
-    ctrl, alt, meta:                    none
+    alt:                                '\u0303'
+    ctrl, meta:                         none
 }
 
 key O {
@@ -151,7 +156,8 @@
     label:                              'S'
     base:                               's'
     shift, capslock:                    'S'
-    ctrl, alt, meta:                    none
+    alt:                                '\u00df'
+    ctrl, meta:                         none
 }
 
 key T {
@@ -165,7 +171,8 @@
     label:                              'U'
     base:                               'u'
     shift, capslock:                    'U'
-    ctrl, alt, meta:                    none
+    alt:                                '\u0308'
+    ctrl, meta:                         none
 }
 
 key V {
@@ -250,6 +257,7 @@
     base:                               '6'
     shift:                              '^'
     ctrl, alt, meta:                    none
+    alt+shift:                          '\u0302'
 }
 
 key 7 {
@@ -276,7 +284,8 @@
 key SPACE {
     label:                              ' '
     base:                               ' '
-    ctrl, alt, meta:                    none
+    ctrl, alt:                          none
+    meta:                               fallback SEARCH
 }
 
 key ENTER {
@@ -288,7 +297,8 @@
 key TAB {
     label:                              '\t'
     base:                               '\t'
-    ctrl, alt, meta:                    none
+    ctrl, alt:                          none
+    meta:                               fallback APP_SWITCH
 }
 
 key COMMA {
@@ -316,7 +326,9 @@
     label, number:                      '`'
     base:                               '`'
     shift:                              '~'
-    ctrl, alt, meta:                    none
+    alt:                                '\u0300'
+    alt+shift:                          '\u0303'
+    ctrl, meta:                         none
 }
 
 key MINUS {
@@ -522,3 +534,11 @@
     label, number:                      '+'
     base:                               '+'
 }
+
+### Non-printing keys ###
+
+key ESCAPE {
+    base:                               fallback BACK
+    meta:                               fallback HOME
+    alt:                                fallback MENU
+}
diff --git a/data/sounds/AudioPackage6.mk b/data/sounds/AudioPackage6.mk
new file mode 100755
index 0000000..bceaba8
--- /dev/null
+++ b/data/sounds/AudioPackage6.mk
@@ -0,0 +1,108 @@
+#
+# Audio Package 6 - Trygon/Stingray
+# 
+# Include this file in a product makefile to include these audio files
+#
+# 
+
+LOCAL_PATH:= frameworks/base/data/sounds
+
+PRODUCT_COPY_FILES += \
+	$(LOCAL_PATH)/Alarm_Buzzer.ogg:system/media/audio/alarms/Alarm_Buzzer.ogg \
+	$(LOCAL_PATH)/Alarm_Beep_01.ogg:system/media/audio/alarms/Alarm_Beep_01.ogg \
+	$(LOCAL_PATH)/Alarm_Beep_02.ogg:system/media/audio/alarms/Alarm_Beep_02.ogg \
+	$(LOCAL_PATH)/Alarm_Classic.ogg:system/media/audio/alarms/Alarm_Classic.ogg \
+	$(LOCAL_PATH)/Alarm_Beep_03.ogg:system/media/audio/alarms/Alarm_Beep_03.ogg \
+	$(LOCAL_PATH)/effects/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg \
+	$(LOCAL_PATH)/effects/KeypressStandard.ogg:system/media/audio/ui/KeypressStandard.ogg \
+	$(LOCAL_PATH)/effects/KeypressSpacebar.ogg:system/media/audio/ui/KeypressSpacebar.ogg \
+	$(LOCAL_PATH)/effects/KeypressDelete.ogg:system/media/audio/ui/KeypressDelete.ogg \
+	$(LOCAL_PATH)/effects/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \
+	$(LOCAL_PATH)/effects/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+	$(LOCAL_PATH)/effects/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
+	$(LOCAL_PATH)/effects/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
+	$(LOCAL_PATH)/effects/Dock.ogg:system/media/audio/ui/Dock.ogg \
+	$(LOCAL_PATH)/effects/Undock.ogg:system/media/audio/ui/Undock.ogg \
+	$(LOCAL_PATH)/effects/Lock.ogg:system/media/audio/ui/Lock.ogg \
+	$(LOCAL_PATH)/effects/Unlock.ogg:system/media/audio/ui/Unlock.ogg \
+	$(LOCAL_PATH)/notifications/Aldebaran.ogg:system/media/audio/notifications/Aldebaran.ogg \
+	$(LOCAL_PATH)/notifications/Altair.ogg:system/media/audio/notifications/Altair.ogg \
+	$(LOCAL_PATH)/notifications/Antares.ogg:system/media/audio/notifications/Antares.ogg \
+	$(LOCAL_PATH)/notifications/arcturus.ogg:system/media/audio/notifications/arcturus.ogg \
+	$(LOCAL_PATH)/notifications/Betelgeuse.ogg:system/media/audio/notifications/Betelgeuse.ogg \
+	$(LOCAL_PATH)/notifications/Canopus.ogg:system/media/audio/notifications/Canopus.ogg \
+	$(LOCAL_PATH)/notifications/Capella.ogg:system/media/audio/notifications/Capella.ogg \
+	$(LOCAL_PATH)/notifications/Castor.ogg:system/media/audio/notifications/Castor.ogg \
+	$(LOCAL_PATH)/notifications/CetiAlpha.ogg:system/media/audio/notifications/CetiAlpha.ogg \
+	$(LOCAL_PATH)/notifications/Deneb.ogg:system/media/audio/notifications/Deneb.ogg \
+	$(LOCAL_PATH)/notifications/Electra.ogg:system/media/audio/notifications/Electra.ogg \
+	$(LOCAL_PATH)/notifications/Fomalhaut.ogg:system/media/audio/notifications/Fomalhaut.ogg \
+	$(LOCAL_PATH)/notifications/Merope.ogg:system/media/audio/notifications/Merope.ogg \
+	$(LOCAL_PATH)/notifications/Polaris.ogg:system/media/audio/notifications/Polaris.ogg \
+	$(LOCAL_PATH)/notifications/Pollux.ogg:system/media/audio/notifications/Pollux.ogg \
+	$(LOCAL_PATH)/notifications/Procyon.ogg:system/media/audio/notifications/Procyon.ogg \
+	$(LOCAL_PATH)/notifications/regulus.ogg:system/media/audio/notifications/regulus.ogg \
+	$(LOCAL_PATH)/notifications/sirius.ogg:system/media/audio/notifications/sirius.ogg \
+	$(LOCAL_PATH)/notifications/Sirrah.ogg:system/media/audio/notifications/Sirrah.ogg \
+	$(LOCAL_PATH)/notifications/vega.ogg:system/media/audio/notifications/vega.ogg \
+	$(LOCAL_PATH)/ringtones/ANDROMEDA.ogg:system/media/audio/ringtones/ANDROMEDA.ogg \
+	$(LOCAL_PATH)/ringtones/Aquila.ogg:system/media/audio/ringtones/Aquila.ogg \
+	$(LOCAL_PATH)/ringtones/ArgoNavis.ogg:system/media/audio/ringtones/ArgoNavis.ogg \
+	$(LOCAL_PATH)/ringtones/BOOTES.ogg:system/media/audio/ringtones/BOOTES.ogg \
+	$(LOCAL_PATH)/ringtones/CANISMAJOR.ogg:system/media/audio/ringtones/CANISMAJOR.ogg \
+	$(LOCAL_PATH)/ringtones/Carina.ogg:system/media/audio/ringtones/Carina.ogg \
+	$(LOCAL_PATH)/ringtones/CASSIOPEIA.ogg:system/media/audio/ringtones/CASSIOPEIA.ogg \
+	$(LOCAL_PATH)/ringtones/Centaurus.ogg:system/media/audio/ringtones/Centaurus.ogg \
+	$(LOCAL_PATH)/ringtones/Cygnus.ogg:system/media/audio/ringtones/Cygnus.ogg \
+	$(LOCAL_PATH)/ringtones/Draco.ogg:system/media/audio/ringtones/Draco.ogg \
+	$(LOCAL_PATH)/ringtones/Eridani.ogg:system/media/audio/ringtones/Eridani.ogg \
+	$(LOCAL_PATH)/ringtones/hydra.ogg:system/media/audio/ringtones/hydra.ogg \
+	$(LOCAL_PATH)/ringtones/Lyra.ogg:system/media/audio/ringtones/Lyra.ogg \
+	$(LOCAL_PATH)/ringtones/Machina.ogg:system/media/audio/ringtones/Machina.ogg \
+	$(LOCAL_PATH)/ringtones/Orion.ogg:system/media/audio/ringtones/Orion.ogg \
+	$(LOCAL_PATH)/ringtones/Pegasus.ogg:system/media/audio/ringtones/Pegasus.ogg \
+	$(LOCAL_PATH)/ringtones/PERSEUS.ogg:system/media/audio/ringtones/PERSEUS.ogg \
+	$(LOCAL_PATH)/ringtones/Pyxis.ogg:system/media/audio/ringtones/Pyxis.ogg \
+	$(LOCAL_PATH)/ringtones/Rigel.ogg:system/media/audio/ringtones/Rigel.ogg \
+	$(LOCAL_PATH)/ringtones/Scarabaeus.ogg:system/media/audio/ringtones/Scarabaeus.ogg \
+	$(LOCAL_PATH)/ringtones/Sceptrum.ogg:system/media/audio/ringtones/Sceptrum.ogg \
+	$(LOCAL_PATH)/ringtones/Solarium.ogg:system/media/audio/ringtones/Solarium.ogg \
+	$(LOCAL_PATH)/ringtones/Testudo.ogg:system/media/audio/ringtones/Testudo.ogg \
+	$(LOCAL_PATH)/ringtones/URSAMINOR.ogg:system/media/audio/ringtones/URSAMINOR.ogg \
+	$(LOCAL_PATH)/ringtones/Vespa.ogg:system/media/audio/ringtones/Vespa.ogg \
+	$(LOCAL_PATH)/notifications/alert01.ogg:system/media/audio/notifications/alert01.ogg \
+	$(LOCAL_PATH)/notifications/alert02.ogg:system/media/audio/notifications/alert02.ogg \
+	$(LOCAL_PATH)/notifications/alert03.ogg:system/media/audio/notifications/alert03.ogg \
+	$(LOCAL_PATH)/notifications/alert04.ogg:system/media/audio/notifications/alert04.ogg \
+	$(LOCAL_PATH)/notifications/alert05.ogg:system/media/audio/notifications/alert05.ogg \
+	$(LOCAL_PATH)/notifications/alert06.ogg:system/media/audio/notifications/alert06.ogg \
+	$(LOCAL_PATH)/notifications/alert07.ogg:system/media/audio/notifications/alert07.ogg \
+	$(LOCAL_PATH)/notifications/alert08.ogg:system/media/audio/notifications/alert08.ogg \
+	$(LOCAL_PATH)/notifications/alert09.ogg:system/media/audio/notifications/alert09.ogg \
+	$(LOCAL_PATH)/notifications/alert10.ogg:system/media/audio/notifications/alert10.ogg \
+	$(LOCAL_PATH)/notifications/alert11.ogg:system/media/audio/notifications/alert11.ogg \
+	$(LOCAL_PATH)/notifications/alert12.ogg:system/media/audio/notifications/alert12.ogg \
+	$(LOCAL_PATH)/notifications/alert13.ogg:system/media/audio/notifications/alert13.ogg \
+	$(LOCAL_PATH)/notifications/alert14.ogg:system/media/audio/notifications/alert14.ogg \
+	$(LOCAL_PATH)/notifications/alert15.ogg:system/media/audio/notifications/alert15.ogg \
+	$(LOCAL_PATH)/ringtones/ringtone18.ogg:system/media/audio/ringtones/ringtone18.ogg \
+	$(LOCAL_PATH)/ringtones/ringtone19.ogg:system/media/audio/ringtones/ringtone19.ogg \
+	$(LOCAL_PATH)/ringtones/ringtone20.ogg:system/media/audio/ringtones/ringtone20.ogg \
+	$(LOCAL_PATH)/ringtones/ringtone21.ogg:system/media/audio/ringtones/ringtone21.ogg \
+	$(LOCAL_PATH)/ringtones/ringtone22.ogg:system/media/audio/ringtones/ringtone22.ogg \
+	$(LOCAL_PATH)/ringtones/ringtone23.ogg:system/media/audio/ringtones/ringtone23.ogg \
+	$(LOCAL_PATH)/ringtones/ringtone24.ogg:system/media/audio/ringtones/ringtone24.ogg \
+	$(LOCAL_PATH)/ringtones/ringtone25.ogg:system/media/audio/ringtones/ringtone25.ogg \
+	$(LOCAL_PATH)/ringtones/ringtone26.ogg:system/media/audio/ringtones/ringtone26.ogg \
+	$(LOCAL_PATH)/ringtones/ringtone27.ogg:system/media/audio/ringtones/ringtone27.ogg \
+	$(LOCAL_PATH)/ringtones/ringtone28.ogg:system/media/audio/ringtones/ringtone28.ogg \
+	$(LOCAL_PATH)/ringtones/ringtone29.ogg:system/media/audio/ringtones/ringtone29.ogg \
+	$(LOCAL_PATH)/ringtones/ringtone30.ogg:system/media/audio/ringtones/ringtone30.ogg \
+	$(LOCAL_PATH)/ringtones/ringtone31.ogg:system/media/audio/ringtones/ringtone31.ogg \
+	$(LOCAL_PATH)/ringtones/ringtone32.ogg:system/media/audio/ringtones/ringtone32.ogg \
+	$(LOCAL_PATH)/ringtones/ringtone33.ogg:system/media/audio/ringtones/ringtone33.ogg \
+	$(LOCAL_PATH)/ringtones/ringtone34.ogg:system/media/audio/ringtones/ringtone34.ogg \
+	$(LOCAL_PATH)/ringtones/ringtone35.ogg:system/media/audio/ringtones/ringtone35.ogg \
+	$(LOCAL_PATH)/ringtones/ringtone36.ogg:system/media/audio/ringtones/ringtone36.ogg \
+	$(LOCAL_PATH)/ringtones/ringtone37.ogg:system/media/audio/ringtones/ringtone37.ogg \
+	$(LOCAL_PATH)/ringtones/ringtone38.ogg:system/media/audio/ringtones/ringtone38.ogg
diff --git a/data/sounds/notifications/alert01.ogg b/data/sounds/notifications/alert01.ogg
old mode 100644
new mode 100755
index 310424a..4b900b0
--- a/data/sounds/notifications/alert01.ogg
+++ b/data/sounds/notifications/alert01.ogg
Binary files differ
diff --git a/data/sounds/notifications/alert02.ogg b/data/sounds/notifications/alert02.ogg
old mode 100644
new mode 100755
index 6c6d5c7..469ea6a
--- a/data/sounds/notifications/alert02.ogg
+++ b/data/sounds/notifications/alert02.ogg
Binary files differ
diff --git a/data/sounds/notifications/alert03.ogg b/data/sounds/notifications/alert03.ogg
old mode 100644
new mode 100755
index cd8811f..58f418b
--- a/data/sounds/notifications/alert03.ogg
+++ b/data/sounds/notifications/alert03.ogg
Binary files differ
diff --git a/data/sounds/notifications/alert04.ogg b/data/sounds/notifications/alert04.ogg
old mode 100644
new mode 100755
index 3cdb0b1..4730d6d
--- a/data/sounds/notifications/alert04.ogg
+++ b/data/sounds/notifications/alert04.ogg
Binary files differ
diff --git a/data/sounds/notifications/alert05.ogg b/data/sounds/notifications/alert05.ogg
old mode 100644
new mode 100755
index 2022cc3..663da31
--- a/data/sounds/notifications/alert05.ogg
+++ b/data/sounds/notifications/alert05.ogg
Binary files differ
diff --git a/data/sounds/notifications/alert06.ogg b/data/sounds/notifications/alert06.ogg
old mode 100644
new mode 100755
index 8da9420..2861b84
--- a/data/sounds/notifications/alert06.ogg
+++ b/data/sounds/notifications/alert06.ogg
Binary files differ
diff --git a/data/sounds/notifications/alert07.ogg b/data/sounds/notifications/alert07.ogg
index 1bb6370..6fe905d 100644
--- a/data/sounds/notifications/alert07.ogg
+++ b/data/sounds/notifications/alert07.ogg
Binary files differ
diff --git a/data/sounds/notifications/alert08.ogg b/data/sounds/notifications/alert08.ogg
index 7ebd4aa..ee30c26 100644
--- a/data/sounds/notifications/alert08.ogg
+++ b/data/sounds/notifications/alert08.ogg
Binary files differ
diff --git a/data/sounds/notifications/alert09.ogg b/data/sounds/notifications/alert09.ogg
index dcf9c2b..86b2f2e 100644
--- a/data/sounds/notifications/alert09.ogg
+++ b/data/sounds/notifications/alert09.ogg
Binary files differ
diff --git a/data/sounds/notifications/alert10.ogg b/data/sounds/notifications/alert10.ogg
index 9960ad7..1d93143 100644
--- a/data/sounds/notifications/alert10.ogg
+++ b/data/sounds/notifications/alert10.ogg
Binary files differ
diff --git a/data/sounds/notifications/alert11.ogg b/data/sounds/notifications/alert11.ogg
index 0b907e1..c7327db 100644
--- a/data/sounds/notifications/alert11.ogg
+++ b/data/sounds/notifications/alert11.ogg
Binary files differ
diff --git a/data/sounds/notifications/alert12.ogg b/data/sounds/notifications/alert12.ogg
index 2ebadec..352a049 100644
--- a/data/sounds/notifications/alert12.ogg
+++ b/data/sounds/notifications/alert12.ogg
Binary files differ
diff --git a/data/sounds/notifications/alert13.ogg b/data/sounds/notifications/alert13.ogg
index 6acc2df..0987360 100644
--- a/data/sounds/notifications/alert13.ogg
+++ b/data/sounds/notifications/alert13.ogg
Binary files differ
diff --git a/data/sounds/notifications/alert14.ogg b/data/sounds/notifications/alert14.ogg
index a34a1f0..6e49307 100644
--- a/data/sounds/notifications/alert14.ogg
+++ b/data/sounds/notifications/alert14.ogg
Binary files differ
diff --git a/data/sounds/notifications/alert15.ogg b/data/sounds/notifications/alert15.ogg
index 108aa45..b140427 100644
--- a/data/sounds/notifications/alert15.ogg
+++ b/data/sounds/notifications/alert15.ogg
Binary files differ
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 8450c3a..66f8f70 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -210,7 +210,6 @@
          * expense of the decoding speed. Currently the field only affects JPEG
          * decode, in the case of which a more accurate, but slightly slower,
          * IDCT method will be used instead.
-         * @hide
          */
         public boolean inPreferQualityOverSpeed;
 
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 0aba347..d37c22d 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -121,10 +121,16 @@
         kOutputBuffersAreUnreadable           = 8192,
     };
 
+    enum BufferStatus {
+        OWNED_BY_US,
+        OWNED_BY_COMPONENT,
+        OWNED_BY_NATIVE_WINDOW,
+        OWNED_BY_CLIENT,
+    };
+
     struct BufferInfo {
         IOMX::buffer_id mBuffer;
-        bool mOwnedByComponent;
-        bool mOwnedByNativeWindow;
+        BufferStatus mStatus;
         sp<IMemory> mMem;
         size_t mSize;
         void *mData;
@@ -248,9 +254,9 @@
 
     status_t freeBuffer(OMX_U32 portIndex, size_t bufIndex);
 
-    void drainInputBuffer(IOMX::buffer_id buffer);
+    bool drainInputBuffer(IOMX::buffer_id buffer);
     void fillOutputBuffer(IOMX::buffer_id buffer);
-    void drainInputBuffer(BufferInfo *info);
+    bool drainInputBuffer(BufferInfo *info);
     void fillOutputBuffer(BufferInfo *info);
 
     void drainInputBuffers();
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index c446633..aa65d93 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -91,12 +91,15 @@
     status_t lock(uint32_t usage, const Rect& rect, void** vaddr);
     status_t lock(GGLSurface* surface, uint32_t usage);
     status_t unlock();
-    
+
     android_native_buffer_t* getNativeBuffer() const;
     
     void setIndex(int index);
     int getIndex() const;
 
+    // for debugging
+    static void dumpAllocationsToSystemLog();
+
 private:
     virtual ~GraphicBuffer();
 
diff --git a/include/ui/GraphicBufferAllocator.h b/include/ui/GraphicBufferAllocator.h
index 54b8236..dffa788 100644
--- a/include/ui/GraphicBufferAllocator.h
+++ b/include/ui/GraphicBufferAllocator.h
@@ -68,6 +68,7 @@
     status_t free(buffer_handle_t handle);
 
     void dump(String8& res) const;
+    static void dumpToSystemLog();
 
 private:
     struct alloc_rec_t {
diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h
index b621680..7305601 100644
--- a/include/ui/InputDispatcher.h
+++ b/include/ui/InputDispatcher.h
@@ -306,9 +306,10 @@
     virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
             const KeyEvent* keyEvent, uint32_t policyFlags) = 0;
 
-    /* Allows the policy a chance to perform default processing for an unhandled key. */
+    /* 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,
-            const KeyEvent* keyEvent, uint32_t policyFlags) = 0;
+            const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) = 0;
 
     /* Notifies the policy about switch events.
      */
@@ -735,6 +736,7 @@
             CANCEL_ALL_EVENTS = 0,
             CANCEL_POINTER_EVENTS = 1,
             CANCEL_NON_POINTER_EVENTS = 2,
+            CANCEL_FALLBACK_EVENTS = 3,
         };
 
         InputState();
@@ -771,6 +773,7 @@
             int32_t source;
             int32_t keyCode;
             int32_t scanCode;
+            int32_t flags;
             nsecs_t downTime;
         };
 
@@ -790,7 +793,10 @@
         Vector<KeyMemento> mKeyMementos;
         Vector<MotionMemento> mMotionMementos;
 
-        static bool shouldCancelEvent(int32_t eventSource, CancelationOptions options);
+        static bool shouldCancelKey(const KeyMemento& memento,
+                CancelationOptions options);
+        static bool shouldCancelMotion(const MotionMemento& memento,
+                CancelationOptions options);
     };
 
     /* Manages the dispatch state associated with a single input channel. */
diff --git a/include/ui/InputReader.h b/include/ui/InputReader.h
index 8ec5421..b466ff1 100644
--- a/include/ui/InputReader.h
+++ b/include/ui/InputReader.h
@@ -402,7 +402,6 @@
     } mLocked;
 
     void initializeLocked();
-    void initializeLedStateLocked(LockedState::LedState& ledState, int32_t led);
 
     void configureParameters();
     void dumpParameters(String8& dump);
@@ -414,6 +413,8 @@
 
     ssize_t findKeyDownLocked(int32_t scanCode);
 
+    void resetLedStateLocked();
+    void initializeLedStateLocked(LockedState::LedState& ledState, int32_t led);
     void updateLedStateLocked(bool reset);
     void updateLedStateForModifierLocked(LockedState::LedState& ledState, int32_t led,
             int32_t modifier, bool reset);
diff --git a/include/ui/InputTransport.h b/include/ui/InputTransport.h
index 7efb6cc..119db81 100644
--- a/include/ui/InputTransport.h
+++ b/include/ui/InputTransport.h
@@ -256,7 +256,7 @@
      * Returns WOULD_BLOCK if there is no signal present.
      * Other errors probably indicate that the channel is broken.
      */
-    status_t receiveFinishedSignal(bool& outHandled);
+    status_t receiveFinishedSignal(bool* outHandled);
 
 private:
     sp<InputChannel> mChannel;
diff --git a/include/ui/KeyCharacterMap.h b/include/ui/KeyCharacterMap.h
index a1ccb37..10a3810 100644
--- a/include/ui/KeyCharacterMap.h
+++ b/include/ui/KeyCharacterMap.h
@@ -44,6 +44,12 @@
         KEYBOARD_TYPE_SPECIAL_FUNCTION = 5,
     };
 
+    // Substitute key code and meta state for fallback action.
+    struct FallbackAction {
+        int32_t keyCode;
+        int32_t metaState;
+    };
+
     ~KeyCharacterMap();
 
     static status_t load(const String8& filename, KeyCharacterMap** outMap);
@@ -67,6 +73,13 @@
      */
     char16_t getCharacter(int32_t keyCode, int32_t metaState) const;
 
+    /* Gets the fallback action to use by default if the application does not
+     * handle the specified key.
+     * Returns true if an action was available, false if none.
+     */
+    bool getFallbackAction(int32_t keyCode, int32_t metaState,
+            FallbackAction* outFallbackAction) const;
+
     /* Gets the first matching Unicode character that can be generated by the key,
      * preferring the one with the specified meta key modifiers.
      * Returns 0 if no matching character is generated.
@@ -155,6 +168,10 @@
 
     KeyCharacterMap();
 
+    bool getKey(int32_t keyCode, const Key** outKey) const;
+    bool getKeyBehavior(int32_t keyCode, int32_t metaState,
+            const Key** outKey, const Behavior** outBehavior) const;
+
     bool findKey(char16_t ch, int32_t* outKeyCode, int32_t* outMetaState) const;
 
     static void addKey(Vector<KeyEvent>& outEvents,
diff --git a/include/ui/KeycodeLabels.h b/include/ui/KeycodeLabels.h
index be7db1f..9b1a897 100755
--- a/include/ui/KeycodeLabels.h
+++ b/include/ui/KeycodeLabels.h
@@ -211,6 +211,7 @@
     { "PROG_GREEN", 184 },
     { "PROG_YELLOW", 185 },
     { "PROG_BLUE", 186 },
+    { "APP_SWITCH", 187 },
 
     // NOTE: If you add a new keycode here you must also add it to several other files.
     //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/include/utils/Asset.h b/include/utils/Asset.h
index 2a09095..1fe0e06 100644
--- a/include/utils/Asset.h
+++ b/include/utils/Asset.h
@@ -23,9 +23,11 @@
 
 #include <stdio.h>
 #include <sys/types.h>
-#include "FileMap.h"
-#include "String8.h"
-#include "Errors.h"
+
+#include <utils/Compat.h>
+#include <utils/Errors.h>
+#include <utils/FileMap.h>
+#include <utils/String8.h>
 
 namespace android {
 
@@ -69,10 +71,10 @@
 
     /*
      * Seek to the specified offset.  "whence" uses the same values as
-     * lseek/fseek.  Returns the new position on success, or (off_t) -1
+     * lseek/fseek.  Returns the new position on success, or (off64_t) -1
      * on failure.
      */
-    virtual off_t seek(off_t offset, int whence) = 0;
+    virtual off64_t seek(off64_t offset, int whence) = 0;
 
     /*
      * Close the asset, freeing all associated resources.
@@ -87,26 +89,26 @@
     /*
      * Get the total amount of data that can be read.
      */
-    virtual off_t getLength(void) const = 0;
+    virtual off64_t getLength(void) const = 0;
 
     /*
      * Get the total amount of data that can be read from the current position.
      */
-    virtual off_t getRemainingLength(void) const = 0;
+    virtual off64_t getRemainingLength(void) const = 0;
 
     /*
      * Open a new file descriptor that can be used to read this asset.
      * Returns -1 if you can not use the file descriptor (for example if the
      * asset is compressed).
      */
-    virtual int openFileDescriptor(off_t* outStart, off_t* outLength) const = 0;
-    
+    virtual int openFileDescriptor(off64_t* outStart, off64_t* outLength) const = 0;
+
     /*
      * Return whether this asset's buffer is allocated in RAM (not mmapped).
      * Note: not virtual so it is safe to call even when being destroyed.
      */
     virtual bool isAllocated(void) const { return false; }
-    
+
     /*
      * Get a string identifying the asset's source.  This might be a full
      * path, it might be a colon-separated list of identifiers.
@@ -120,7 +122,7 @@
     Asset(void);        // constructor; only invoked indirectly
 
     /* handle common seek() housekeeping */
-    off_t handleSeek(off_t offset, int whence, off_t curPosn, off_t maxPosn);
+    off64_t handleSeek(off64_t offset, int whence, off64_t curPosn, off64_t maxPosn);
 
     /* set the asset source string */
     void setAssetSource(const String8& path) { mAssetSource = path; }
@@ -153,7 +155,7 @@
      *
      * The asset takes ownership of the file descriptor.
      */
-    static Asset* createFromFileSegment(int fd, off_t offset, size_t length,
+    static Asset* createFromFileSegment(int fd, off64_t offset, size_t length,
         AccessMode mode);
 
     /*
@@ -166,7 +168,7 @@
      * This may not verify the validity of the compressed data until first
      * use.
      */
-    static Asset* createFromCompressedData(int fd, off_t offset,
+    static Asset* createFromCompressedData(int fd, off64_t offset,
         int compressionMethod, size_t compressedLength,
         size_t uncompressedLength, AccessMode mode);
 #endif
@@ -221,7 +223,7 @@
      *
      * On success, the object takes ownership of "fd".
      */
-    status_t openChunk(const char* fileName, int fd, off_t offset, size_t length);
+    status_t openChunk(const char* fileName, int fd, off64_t offset, size_t length);
 
     /*
      * Use a memory-mapped region.
@@ -234,18 +236,18 @@
      * Standard Asset interfaces.
      */
     virtual ssize_t read(void* buf, size_t count);
-    virtual off_t seek(off_t offset, int whence);
+    virtual off64_t seek(off64_t offset, int whence);
     virtual void close(void);
     virtual const void* getBuffer(bool wordAligned);
-    virtual off_t getLength(void) const { return mLength; }
-    virtual off_t getRemainingLength(void) const { return mLength-mOffset; }
-    virtual int openFileDescriptor(off_t* outStart, off_t* outLength) const;
+    virtual off64_t getLength(void) const { return mLength; }
+    virtual off64_t getRemainingLength(void) const { return mLength-mOffset; }
+    virtual int openFileDescriptor(off64_t* outStart, off64_t* outLength) const;
     virtual bool isAllocated(void) const { return mBuf != NULL; }
 
 private:
-    off_t       mStart;         // absolute file offset of start of chunk
-    off_t       mLength;        // length of the chunk
-    off_t       mOffset;        // current local offset, 0 == mStart
+    off64_t     mStart;         // absolute file offset of start of chunk
+    off64_t     mLength;        // length of the chunk
+    off64_t     mOffset;        // current local offset, 0 == mStart
     FILE*       mFp;            // for read/seek
     char*       mFileName;      // for opening
 
@@ -276,7 +278,7 @@
      *
      * On success, the object takes ownership of "fd".
      */
-    status_t openChunk(int fd, off_t offset, int compressionMethod,
+    status_t openChunk(int fd, off64_t offset, int compressionMethod,
         size_t uncompressedLen, size_t compressedLen);
 
     /*
@@ -291,19 +293,19 @@
      * Standard Asset interfaces.
      */
     virtual ssize_t read(void* buf, size_t count);
-    virtual off_t seek(off_t offset, int whence);
+    virtual off64_t seek(off64_t offset, int whence);
     virtual void close(void);
     virtual const void* getBuffer(bool wordAligned);
-    virtual off_t getLength(void) const { return mUncompressedLen; }
-    virtual off_t getRemainingLength(void) const { return mUncompressedLen-mOffset; }
-    virtual int openFileDescriptor(off_t* outStart, off_t* outLength) const { return -1; }
+    virtual off64_t getLength(void) const { return mUncompressedLen; }
+    virtual off64_t getRemainingLength(void) const { return mUncompressedLen-mOffset; }
+    virtual int openFileDescriptor(off64_t* outStart, off64_t* outLength) const { return -1; }
     virtual bool isAllocated(void) const { return mBuf != NULL; }
 
 private:
-    off_t       mStart;         // offset to start of compressed data
-    off_t       mCompressedLen; // length of the compressed data
-    off_t       mUncompressedLen; // length of the uncompressed data
-    off_t       mOffset;        // current offset, 0 == start of uncomp data
+    off64_t     mStart;         // offset to start of compressed data
+    off64_t     mCompressedLen; // length of the compressed data
+    off64_t     mUncompressedLen; // length of the uncompressed data
+    off64_t     mOffset;        // current offset, 0 == start of uncomp data
 
     FileMap*    mMap;           // for memory-mapped input
     int         mFd;            // for file input
diff --git a/include/utils/Compat.h b/include/utils/Compat.h
new file mode 100644
index 0000000..1819266
--- /dev/null
+++ b/include/utils/Compat.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LIB_UTILS_COMPAT_H
+#define __LIB_UTILS_COMPAT_H
+
+#include <unistd.h>
+
+/* Compatibility definitions for non-Linux (i.e., BSD-based) hosts. */
+#ifndef HAVE_OFF64_T
+#if _FILE_OFFSET_BITS < 64
+#error "_FILE_OFFSET_BITS < 64; large files are not supported on this platform"
+#endif /* _FILE_OFFSET_BITS < 64 */
+
+typedef off_t off64_t;
+
+static inline off64_t lseek64(int fd, off64_t offset, int whence) {
+    return lseek(fd, offset, whence);
+}
+
+#ifdef HAVE_PREAD
+static inline ssize_t pread64(int fd, void* buf, size_t nbytes, off64_t offset) {
+    return pread(fd, buf, nbytes, offset);
+}
+#endif
+
+#endif /* !HAVE_OFF64_T */
+
+#endif /* __LIB_UTILS_COMPAT_H */
diff --git a/include/utils/FileMap.h b/include/utils/FileMap.h
index 8dfd3be..dfe6d51 100644
--- a/include/utils/FileMap.h
+++ b/include/utils/FileMap.h
@@ -22,6 +22,8 @@
 
 #include <sys/types.h>
 
+#include <utils/Compat.h>
+
 #ifdef HAVE_WIN32_FILEMAP
 #include <windows.h>
 #endif
@@ -55,7 +57,7 @@
      * Returns "false" on failure.
      */
     bool create(const char* origFileName, int fd,
-                off_t offset, size_t length, bool readOnly);
+                off64_t offset, size_t length, bool readOnly);
 
     /*
      * Return the name of the file this map came from, if known.
@@ -75,7 +77,7 @@
     /*
      * Get the data offset used to create this map.
      */
-    off_t getDataOffset(void) const { return mDataOffset; }
+    off64_t getDataOffset(void) const { return mDataOffset; }
 
     /*
      * Get a "copy" of the object.
@@ -118,7 +120,7 @@
     char*       mFileName;      // original file name, if known
     void*       mBasePtr;       // base of mmap area; page aligned
     size_t      mBaseLength;    // length, measured from "mBasePtr"
-    off_t       mDataOffset;    // offset used when map was created
+    off64_t     mDataOffset;    // offset used when map was created
     void*       mDataPtr;       // start of requested data, offset from base
     size_t      mDataLength;    // length, measured from "mDataPtr"
 #ifdef HAVE_WIN32_FILEMAP
diff --git a/include/utils/StreamingZipInflater.h b/include/utils/StreamingZipInflater.h
index 16867d8..3ace5d5 100644
--- a/include/utils/StreamingZipInflater.h
+++ b/include/utils/StreamingZipInflater.h
@@ -21,6 +21,8 @@
 #include <inttypes.h>
 #include <zlib.h>
 
+#include <utils/Compat.h>
+
 namespace android {
 
 class StreamingZipInflater {
@@ -29,7 +31,7 @@
     static const size_t OUTPUT_CHUNK_SIZE = 64 * 1024;
 
     // Flavor that pages in the compressed data from a fd
-    StreamingZipInflater(int fd, off_t compDataStart, size_t uncompSize, size_t compSize);
+    StreamingZipInflater(int fd, off64_t compDataStart, size_t uncompSize, size_t compSize);
 
     // Flavor that gets the compressed data from an in-memory buffer
     StreamingZipInflater(class FileMap* dataMap, size_t uncompSize);
@@ -43,7 +45,7 @@
     // seeking backwards requires uncompressing fom the beginning, so is very
     // expensive.  seeking forwards only requires uncompressing from the current
     // position to the destination.
-    off_t seekAbsolute(off_t absoluteInputPosition);
+    off64_t seekAbsolute(off64_t absoluteInputPosition);
 
 private:
     void initInflateState();
@@ -51,7 +53,7 @@
 
     // where to find the uncompressed data
     int mFd;
-    off_t mInFileStart;         // where the compressed data lives in the file
+    off64_t mInFileStart;         // where the compressed data lives in the file
     class FileMap* mDataMap;
 
     z_stream mInflateState;
@@ -63,7 +65,7 @@
     size_t mOutTotalSize;       // total uncompressed size of the blob
 
     // current output state bookkeeping
-    off_t mOutCurPosition;      // current position in total offset
+    off64_t mOutCurPosition;      // current position in total offset
     size_t mOutLastDecoded;     // last decoded byte + 1 in mOutbuf
     size_t mOutDeliverable;     // next undelivered byte of decoded output in mOutBuf
 
diff --git a/include/utils/ZipFileCRO.h b/include/utils/ZipFileCRO.h
index e38bf66..3e42a95 100644
--- a/include/utils/ZipFileCRO.h
+++ b/include/utils/ZipFileCRO.h
@@ -24,6 +24,8 @@
 #include <stdlib.h>
 #include <unistd.h>
 
+#include <utils/Compat.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -48,7 +50,7 @@
 
 extern bool ZipFileCRO_getEntryInfo(ZipFileCRO zip, ZipEntryCRO entry,
         int* pMethod, size_t* pUncompLen,
-        size_t* pCompLen, off_t* pOffset, long* pModWhen, long* pCrc32);
+        size_t* pCompLen, off64_t* pOffset, long* pModWhen, long* pCrc32);
 
 extern bool ZipFileCRO_uncompressEntry(ZipFileCRO zip, ZipEntryCRO entry, int fd);
 
diff --git a/include/utils/ZipFileRO.h b/include/utils/ZipFileRO.h
index 3c1f3ca..3a99979 100644
--- a/include/utils/ZipFileRO.h
+++ b/include/utils/ZipFileRO.h
@@ -30,6 +30,7 @@
 #ifndef __LIBS_ZIPFILERO_H
 #define __LIBS_ZIPFILERO_H
 
+#include <utils/Compat.h>
 #include <utils/Errors.h>
 #include <utils/FileMap.h>
 #include <utils/threads.h>
@@ -128,7 +129,7 @@
      * appears to be bad.
      */
     bool getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen,
-        size_t* pCompLen, off_t* pOffset, long* pModWhen, long* pCrc32) const;
+        size_t* pCompLen, off64_t* pOffset, long* pModWhen, long* pCrc32) const;
 
     /*
      * Create a new FileMap object that maps a subset of the archive.  For
@@ -231,7 +232,7 @@
     int         mNumEntries;
 
     /* CD directory offset in the Zip archive */
-    off_t       mDirectoryOffset;
+    off64_t     mDirectoryOffset;
 
     /*
      * We know how many entries are in the Zip archive, so we have a
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 436e064..97312a6 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -114,6 +114,11 @@
     return mInitCheck;
 }
 
+void GraphicBuffer::dumpAllocationsToSystemLog()
+{
+    GraphicBufferAllocator::dumpToSystemLog();
+}
+
 android_native_buffer_t* GraphicBuffer::getNativeBuffer() const
 {
     return static_cast<android_native_buffer_t*>(
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index d51664d..fa46ab7 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -73,6 +73,13 @@
     result.append(buffer);
 }
 
+void GraphicBufferAllocator::dumpToSystemLog()
+{
+    String8 s;
+    GraphicBufferAllocator::getInstance().dump(s);
+    LOGD("%s", s.string());
+}
+
 status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format,
         int usage, buffer_handle_t* handle, int32_t* stride)
 {
@@ -104,10 +111,6 @@
         rec.usage = usage;
         rec.size = h * stride[0] * bytesPerPixel(format);
         list.add(*handle, rec);
-    } else {
-        String8 s;
-        dump(s);
-        LOGD("%s", s.string());
     }
 
     return err;
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index f1223f1..1f6a920 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -1884,7 +1884,7 @@
         }
 
         bool handled = false;
-        status_t status = connection->inputPublisher.receiveFinishedSignal(handled);
+        status_t status = connection->inputPublisher.receiveFinishedSignal(&handled);
         if (status) {
             LOGE("channel '%s' ~ Failed to receive finished signal.  status=%d",
                     connection->getInputChannelName(), status);
@@ -3039,21 +3039,57 @@
     sp<Connection> connection = commandEntry->connection;
     bool handled = commandEntry->handled;
 
-    if (!handled && !connection->outboundQueue.isEmpty()) {
+    if (!connection->outboundQueue.isEmpty()) {
         DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
         if (dispatchEntry->inProgress
                 && dispatchEntry->hasForegroundTarget()
                 && dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
             KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
-            KeyEvent event;
-            initializeKeyEvent(&event, keyEntry);
+            if (!(keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK)) {
+                if (handled) {
+                    // If the application handled a non-fallback key, then immediately
+                    // cancel all fallback keys previously dispatched to the application.
+                    // This behavior will prevent chording with fallback keys (so they cannot
+                    // be used as modifiers) but it will ensure that fallback keys do not
+                    // get stuck.  This takes care of the case where the application does not handle
+                    // the original DOWN so we generate a fallback DOWN but it does handle
+                    // the original UP in which case we would not generate the fallback UP.
+                    synthesizeCancelationEventsForConnectionLocked(connection,
+                            InputState::CANCEL_FALLBACK_EVENTS,
+                            "Application handled a non-fallback event.");
+                } else {
+                    // If the application did not handle a non-fallback key, then ask
+                    // the policy what to do with it.  We might generate a fallback key
+                    // event here.
+                    KeyEvent event;
+                    initializeKeyEvent(&event, keyEntry);
 
-            mLock.unlock();
+                    mLock.unlock();
 
-            mPolicy->dispatchUnhandledKey(connection->inputChannel,
-                    &event, keyEntry->policyFlags);
+                    bool fallback = mPolicy->dispatchUnhandledKey(connection->inputChannel,
+                            &event, keyEntry->policyFlags, &event);
 
-            mLock.lock();
+                    mLock.lock();
+
+                    if (fallback) {
+                        // Restart the dispatch cycle using the fallback key.
+                        keyEntry->eventTime = event.getEventTime();
+                        keyEntry->deviceId = event.getDeviceId();
+                        keyEntry->source = event.getSource();
+                        keyEntry->flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK;
+                        keyEntry->keyCode = event.getKeyCode();
+                        keyEntry->scanCode = event.getScanCode();
+                        keyEntry->metaState = event.getMetaState();
+                        keyEntry->repeatCount = event.getRepeatCount();
+                        keyEntry->downTime = event.getDownTime();
+                        keyEntry->syntheticRepeat = false;
+
+                        dispatchEntry->inProgress = false;
+                        startDispatchCycleLocked(now(), connection);
+                        return;
+                    }
+                }
+            }
         }
     }
 
@@ -3371,6 +3407,7 @@
         memento.source = entry->source;
         memento.keyCode = entry->keyCode;
         memento.scanCode = entry->scanCode;
+        memento.flags = entry->flags;
         memento.downTime = entry->downTime;
         return CONSISTENT;
     }
@@ -3453,10 +3490,10 @@
         CancelationOptions options) {
     for (size_t i = 0; i < mKeyMementos.size(); ) {
         const KeyMemento& memento = mKeyMementos.itemAt(i);
-        if (shouldCancelEvent(memento.source, options)) {
+        if (shouldCancelKey(memento, options)) {
             outEvents.push(allocator->obtainKeyEntry(currentTime,
                     memento.deviceId, memento.source, 0,
-                    AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_CANCELED,
+                    AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED,
                     memento.keyCode, memento.scanCode, 0, 0, memento.downTime));
             mKeyMementos.removeAt(i);
         } else {
@@ -3466,7 +3503,7 @@
 
     for (size_t i = 0; i < mMotionMementos.size(); ) {
         const MotionMemento& memento = mMotionMementos.itemAt(i);
-        if (shouldCancelEvent(memento.source, options)) {
+        if (shouldCancelMotion(memento, options)) {
             outEvents.push(allocator->obtainMotionEntry(currentTime,
                     memento.deviceId, memento.source, 0,
                     AMOTION_EVENT_ACTION_CANCEL, 0, 0, 0,
@@ -3502,15 +3539,30 @@
     }
 }
 
-bool InputDispatcher::InputState::shouldCancelEvent(int32_t eventSource,
+bool InputDispatcher::InputState::shouldCancelKey(const KeyMemento& memento,
         CancelationOptions options) {
     switch (options) {
-    case CANCEL_POINTER_EVENTS:
-        return eventSource & AINPUT_SOURCE_CLASS_POINTER;
+    case CANCEL_ALL_EVENTS:
     case CANCEL_NON_POINTER_EVENTS:
-        return !(eventSource & AINPUT_SOURCE_CLASS_POINTER);
-    default:
         return true;
+    case CANCEL_FALLBACK_EVENTS:
+        return memento.flags & AKEY_EVENT_FLAG_FALLBACK;
+    default:
+        return false;
+    }
+}
+
+bool InputDispatcher::InputState::shouldCancelMotion(const MotionMemento& memento,
+        CancelationOptions options) {
+    switch (options) {
+    case CANCEL_ALL_EVENTS:
+        return true;
+    case CANCEL_POINTER_EVENTS:
+        return memento.source & AINPUT_SOURCE_CLASS_POINTER;
+    case CANCEL_NON_POINTER_EVENTS:
+        return !(memento.source & AINPUT_SOURCE_CLASS_POINTER);
+    default:
+        return false;
     }
 }
 
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
index 9cc96ad..51ed09f 100644
--- a/libs/ui/InputReader.cpp
+++ b/libs/ui/InputReader.cpp
@@ -745,17 +745,6 @@
 void KeyboardInputMapper::initializeLocked() {
     mLocked.metaState = AMETA_NONE;
     mLocked.downTime = 0;
-
-    initializeLedStateLocked(mLocked.capsLockLedState, LED_CAPSL);
-    initializeLedStateLocked(mLocked.numLockLedState, LED_NUML);
-    initializeLedStateLocked(mLocked.scrollLockLedState, LED_SCROLLL);
-
-    updateLedStateLocked(true);
-}
-
-void KeyboardInputMapper::initializeLedStateLocked(LockedState::LedState& ledState, int32_t led) {
-    ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
-    ledState.on = false;
 }
 
 uint32_t KeyboardInputMapper::getSources() {
@@ -786,6 +775,12 @@
 
     // Configure basic parameters.
     configureParameters();
+
+    // Reset LEDs.
+    {
+        AutoMutex _l(mLock);
+        resetLedStateLocked();
+    }
 }
 
 void KeyboardInputMapper::configureParameters() {
@@ -813,6 +808,7 @@
             // Synthesize key up event on reset if keys are currently down.
             if (mLocked.keyDowns.isEmpty()) {
                 initializeLocked();
+                resetLedStateLocked();
                 break; // done
             }
 
@@ -953,6 +949,19 @@
     } // release lock
 }
 
+void KeyboardInputMapper::resetLedStateLocked() {
+    initializeLedStateLocked(mLocked.capsLockLedState, LED_CAPSL);
+    initializeLedStateLocked(mLocked.numLockLedState, LED_NUML);
+    initializeLedStateLocked(mLocked.scrollLockLedState, LED_SCROLLL);
+
+    updateLedStateLocked(true);
+}
+
+void KeyboardInputMapper::initializeLedStateLocked(LockedState::LedState& ledState, int32_t led) {
+    ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
+    ledState.on = false;
+}
+
 void KeyboardInputMapper::updateLedStateLocked(bool reset) {
     updateLedStateForModifierLocked(mLocked.capsLockLedState, LED_CAPSL,
             AMETA_CAPS_LOCK_ON, reset);
@@ -966,7 +975,7 @@
         int32_t led, int32_t modifier, bool reset) {
     if (ledState.avail) {
         bool desiredState = (mLocked.metaState & modifier) != 0;
-        if (ledState.on != desiredState) {
+        if (reset || ledState.on != desiredState) {
             getEventHub()->setLedState(getDeviceId(), led, desiredState);
             ledState.on = desiredState;
         }
diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp
index 1885691..83d9556 100644
--- a/libs/ui/InputTransport.cpp
+++ b/libs/ui/InputTransport.cpp
@@ -501,7 +501,7 @@
     return mChannel->sendSignal(INPUT_SIGNAL_DISPATCH);
 }
 
-status_t InputPublisher::receiveFinishedSignal(bool& outHandled) {
+status_t InputPublisher::receiveFinishedSignal(bool* outHandled) {
 #if DEBUG_TRANSPORT_ACTIONS
     LOGD("channel '%s' publisher ~ receiveFinishedSignal",
             mChannel->getName().string());
@@ -510,13 +510,13 @@
     char signal;
     status_t result = mChannel->receiveSignal(& signal);
     if (result) {
-        outHandled = false;
+        *outHandled = false;
         return result;
     }
     if (signal == INPUT_SIGNAL_FINISHED_HANDLED) {
-        outHandled = true;
+        *outHandled = true;
     } else if (signal == INPUT_SIGNAL_FINISHED_UNHANDLED) {
-        outHandled = false;
+        *outHandled = false;
     } else {
         LOGE("channel '%s' publisher ~ Received unexpected signal '%c' from consumer",
                 mChannel->getName().string(), signal);
diff --git a/libs/ui/KeyCharacterMap.cpp b/libs/ui/KeyCharacterMap.cpp
index e689c4b..9bfa8f6 100644
--- a/libs/ui/KeyCharacterMap.cpp
+++ b/libs/ui/KeyCharacterMap.cpp
@@ -141,9 +141,8 @@
 
 char16_t KeyCharacterMap::getDisplayLabel(int32_t keyCode) const {
     char16_t result = 0;
-    ssize_t index = mKeys.indexOfKey(keyCode);
-    if (index >= 0) {
-        const Key* key = mKeys.valueAt(index);
+    const Key* key;
+    if (getKey(keyCode, &key)) {
         result = key->label;
     }
 #if DEBUG_MAPPING
@@ -154,9 +153,8 @@
 
 char16_t KeyCharacterMap::getNumber(int32_t keyCode) const {
     char16_t result = 0;
-    ssize_t index = mKeys.indexOfKey(keyCode);
-    if (index >= 0) {
-        const Key* key = mKeys.valueAt(index);
+    const Key* key;
+    if (getKey(keyCode, &key)) {
         result = key->number;
     }
 #if DEBUG_MAPPING
@@ -167,15 +165,10 @@
 
 char16_t KeyCharacterMap::getCharacter(int32_t keyCode, int32_t metaState) const {
     char16_t result = 0;
-    ssize_t index = mKeys.indexOfKey(keyCode);
-    if (index >= 0) {
-        const Key* key = mKeys.valueAt(index);
-        for (const Behavior* behavior = key->firstBehavior; behavior; behavior = behavior->next) {
-            if ((behavior->metaState & metaState) == behavior->metaState) {
-                result = behavior->character;
-                break;
-            }
-        }
+    const Key* key;
+    const Behavior* behavior;
+    if (getKeyBehavior(keyCode, metaState, &key, &behavior)) {
+        result = behavior->character;
     }
 #if DEBUG_MAPPING
     LOGD("getCharacter: keyCode=%d, metaState=0x%08x ~ Result %d.", keyCode, metaState, result);
@@ -183,13 +176,33 @@
     return result;
 }
 
+bool KeyCharacterMap::getFallbackAction(int32_t keyCode, int32_t metaState,
+        FallbackAction* outFallbackAction) const {
+    outFallbackAction->keyCode = 0;
+    outFallbackAction->metaState = 0;
+
+    bool result = false;
+    const Key* key;
+    const Behavior* behavior;
+    if (getKeyBehavior(keyCode, metaState, &key, &behavior)) {
+        outFallbackAction->keyCode = behavior->fallbackKeyCode;
+        outFallbackAction->metaState = metaState & ~behavior->metaState;
+        result = true;
+    }
+#if DEBUG_MAPPING
+    LOGD("getFallbackKeyCode: keyCode=%d, metaState=0x%08x ~ Result %s, "
+            "fallback keyCode=%d, fallback metaState=0x%08x.",
+            keyCode, metaState, result ? "true" : "false",
+            outFallbackAction->keyCode, outFallbackAction->metaState);
+#endif
+    return result;
+}
+
 char16_t KeyCharacterMap::getMatch(int32_t keyCode, const char16_t* chars, size_t numChars,
         int32_t metaState) const {
     char16_t result = 0;
-    ssize_t index = mKeys.indexOfKey(keyCode);
-    if (index >= 0) {
-        const Key* key = mKeys.valueAt(index);
-
+    const Key* key;
+    if (getKey(keyCode, &key)) {
         // Try to find the most general behavior that maps to this character.
         // For example, the base key behavior will usually be last in the list.
         // However, if we find a perfect meta state match for one behavior then use that one.
@@ -238,7 +251,7 @@
     }
 #if DEBUG_MAPPING
     LOGD("getEvents: deviceId=%d, chars=[%s] ~ Generated %d events.",
-            deviceId, toString(chars, numChars).string(), outEvents.size());
+            deviceId, toString(chars, numChars).string(), int32_t(outEvents.size()));
     for (size_t i = 0; i < outEvents.size(); i++) {
         LOGD("  Key: keyCode=%d, metaState=0x%08x, %s.",
                 outEvents[i].getKeyCode(), outEvents[i].getMetaState(),
@@ -248,6 +261,32 @@
     return true;
 }
 
+bool KeyCharacterMap::getKey(int32_t keyCode, const Key** outKey) const {
+    ssize_t index = mKeys.indexOfKey(keyCode);
+    if (index >= 0) {
+        *outKey = mKeys.valueAt(index);
+        return true;
+    }
+    return false;
+}
+
+bool KeyCharacterMap::getKeyBehavior(int32_t keyCode, int32_t metaState,
+        const Key** outKey, const Behavior** outBehavior) const {
+    const Key* key;
+    if (getKey(keyCode, &key)) {
+        const Behavior* behavior = key->firstBehavior;
+        while (behavior) {
+            if ((behavior->metaState & metaState) == behavior->metaState) {
+                *outKey = key;
+                *outBehavior = behavior;
+                return true;
+            }
+            behavior = behavior->next;
+        }
+    }
+    return false;
+}
+
 bool KeyCharacterMap::findKey(char16_t ch, int32_t* outKeyCode, int32_t* outMetaState) const {
     if (!ch) {
         return false;
diff --git a/libs/ui/tests/InputDispatcher_test.cpp b/libs/ui/tests/InputDispatcher_test.cpp
index 68f9037..7e17c57 100644
--- a/libs/ui/tests/InputDispatcher_test.cpp
+++ b/libs/ui/tests/InputDispatcher_test.cpp
@@ -66,7 +66,7 @@
     }
 
     virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
-            const KeyEvent* keyEvent, uint32_t policyFlags) {
+            const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
         return false;
     }
 
diff --git a/libs/ui/tests/InputPublisherAndConsumer_test.cpp b/libs/ui/tests/InputPublisherAndConsumer_test.cpp
index c6eac25..903fcaf 100644
--- a/libs/ui/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/ui/tests/InputPublisherAndConsumer_test.cpp
@@ -123,7 +123,7 @@
             << "consumer sendFinishedSignal should return OK";
 
     bool handled = false;
-    status = mPublisher->receiveFinishedSignal(handled);
+    status = mPublisher->receiveFinishedSignal(&handled);
     ASSERT_EQ(OK, status)
             << "publisher receiveFinishedSignal should return OK";
     ASSERT_TRUE(handled)
@@ -287,7 +287,7 @@
             << "consumer sendFinishedSignal should return OK";
 
     bool handled = true;
-    status = mPublisher->receiveFinishedSignal(handled);
+    status = mPublisher->receiveFinishedSignal(&handled);
     ASSERT_EQ(OK, status)
             << "publisher receiveFinishedSignal should return OK";
     ASSERT_FALSE(handled)
diff --git a/libs/ui/tests/InputReader_test.cpp b/libs/ui/tests/InputReader_test.cpp
index d6c2cbd..97cbc25 100644
--- a/libs/ui/tests/InputReader_test.cpp
+++ b/libs/ui/tests/InputReader_test.cpp
@@ -1137,6 +1137,7 @@
         mFakeDispatcher = new FakeInputDispatcher();
         mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeDispatcher);
 
+        mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
         mDevice = new InputDevice(mFakeContext, DEVICE_ID, String8(DEVICE_NAME));
     }
 
@@ -1753,7 +1754,7 @@
     process(mapper, ARBITRARY_TIME, DEVICE_ID,
             EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 1, 0);
     process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 1, 0);
+            EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 0, 0);
     ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
     ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
     ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
@@ -2225,19 +2226,19 @@
 }
 
 
-TEST_F(SingleTouchInputMapperTest, GetSources_WhenDisplayTypeIsTouchPad_ReturnsTouchPad) {
+TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchPad_ReturnsTouchPad) {
     SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
     prepareAxes(POSITION);
-    addConfigurationProperty("touch.displayType", "touchPad");
+    addConfigurationProperty("touch.deviceType", "touchPad");
     addMapperAndConfigure(mapper);
 
     ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper->getSources());
 }
 
-TEST_F(SingleTouchInputMapperTest, GetSources_WhenDisplayTypeIsTouchScreen_ReturnsTouchScreen) {
+TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchScreen_ReturnsTouchScreen) {
     SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
     prepareAxes(POSITION);
-    addConfigurationProperty("touch.displayType", "touchScreen");
+    addConfigurationProperty("touch.deviceType", "touchScreen");
     addMapperAndConfigure(mapper);
 
     ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper->getSources());
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
index 8bd833b..e8d40ba 100644
--- a/libs/utils/Android.mk
+++ b/libs/utils/Android.mk
@@ -70,11 +70,6 @@
 endif
 endif
 
-ifeq ($(HOST_OS),darwin)
-# MacOS doesn't have lseek64. However, off_t is 64-bit anyway.
-LOCAL_CFLAGS += -DOFF_T_IS_64_BIT
-endif
-
 include $(BUILD_HOST_STATIC_LIBRARY)
 
 
diff --git a/libs/utils/Asset.cpp b/libs/utils/Asset.cpp
index cef7db4..a18294b 100644
--- a/libs/utils/Asset.cpp
+++ b/libs/utils/Asset.cpp
@@ -35,6 +35,9 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <assert.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 
 using namespace android;
 
@@ -62,7 +65,7 @@
         if (cur->isAllocated()) {
             res.append("    ");
             res.append(cur->getAssetSource());
-            off_t size = (cur->getLength()+512)/1024;
+            off64_t size = (cur->getLength()+512)/1024;
             char buf[64];
             sprintf(buf, ": %dK\n", (int)size);
             res.append(buf);
@@ -119,7 +122,7 @@
 {
     _FileAsset* pAsset;
     status_t result;
-    off_t length;
+    off64_t length;
     int fd;
 
     fd = open(fileName, O_RDONLY | O_BINARY);
@@ -132,12 +135,26 @@
      * always open things read-only it doesn't really matter, so there's
      * no value in incurring the extra overhead of an fstat() call.
      */
-    length = lseek(fd, 0, SEEK_END);
+    // TODO(kroot): replace this with fstat despite the plea above.
+#if 1
+    length = lseek64(fd, 0, SEEK_END);
     if (length < 0) {
         ::close(fd);
         return NULL;
     }
-    (void) lseek(fd, 0, SEEK_SET);
+    (void) lseek64(fd, 0, SEEK_SET);
+#else
+    struct stat st;
+    if (fstat(fd, &st) < 0) {
+        ::close(fd);
+        return NULL;
+    }
+
+    if (!S_ISREG(st.st_mode)) {
+        ::close(fd);
+        return NULL;
+    }
+#endif
 
     pAsset = new _FileAsset;
     result = pAsset->openChunk(fileName, fd, 0, length);
@@ -162,7 +179,7 @@
 {
     _CompressedAsset* pAsset;
     status_t result;
-    off_t fileLen;
+    off64_t fileLen;
     bool scanResult;
     long offset;
     int method;
@@ -215,7 +232,7 @@
 /*
  * Create a new Asset from part of an open file.
  */
-/*static*/ Asset* Asset::createFromFileSegment(int fd, off_t offset,
+/*static*/ Asset* Asset::createFromFileSegment(int fd, off64_t offset,
     size_t length, AccessMode mode)
 {
     _FileAsset* pAsset;
@@ -233,7 +250,7 @@
 /*
  * Create a new Asset from compressed data in an open file.
  */
-/*static*/ Asset* Asset::createFromCompressedData(int fd, off_t offset,
+/*static*/ Asset* Asset::createFromCompressedData(int fd, off64_t offset,
     int compressionMethod, size_t uncompressedLen, size_t compressedLen,
     AccessMode mode)
 {
@@ -295,9 +312,9 @@
  *
  * Returns the new chunk offset, or -1 if the seek is illegal.
  */
-off_t Asset::handleSeek(off_t offset, int whence, off_t curPosn, off_t maxPosn)
+off64_t Asset::handleSeek(off64_t offset, int whence, off64_t curPosn, off64_t maxPosn)
 {
-    off_t newOffset;
+    off64_t newOffset;
 
     switch (whence) {
     case SEEK_SET:
@@ -311,15 +328,15 @@
         break;
     default:
         LOGW("unexpected whence %d\n", whence);
-        // this was happening due to an off_t size mismatch
+        // this was happening due to an off64_t size mismatch
         assert(false);
-        return (off_t) -1;
+        return (off64_t) -1;
     }
 
     if (newOffset < 0 || newOffset > maxPosn) {
         LOGW("seek out of range: want %ld, end=%ld\n",
             (long) newOffset, (long) maxPosn);
-        return (off_t) -1;
+        return (off64_t) -1;
     }
 
     return newOffset;
@@ -353,7 +370,7 @@
  *
  * Zero-length chunks are allowed.
  */
-status_t _FileAsset::openChunk(const char* fileName, int fd, off_t offset, size_t length)
+status_t _FileAsset::openChunk(const char* fileName, int fd, off64_t offset, size_t length)
 {
     assert(mFp == NULL);    // no reopen
     assert(mMap == NULL);
@@ -363,15 +380,15 @@
     /*
      * Seek to end to get file length.
      */
-    off_t fileLength;
-    fileLength = lseek(fd, 0, SEEK_END);
-    if (fileLength == (off_t) -1) {
+    off64_t fileLength;
+    fileLength = lseek64(fd, 0, SEEK_END);
+    if (fileLength == (off64_t) -1) {
         // probably a bad file descriptor
         LOGD("failed lseek (errno=%d)\n", errno);
         return UNKNOWN_ERROR;
     }
 
-    if ((off_t) (offset + length) > fileLength) {
+    if ((off64_t) (offset + length) > fileLength) {
         LOGD("start (%ld) + len (%ld) > end (%ld)\n",
             (long) offset, (long) length, (long) fileLength);
         return BAD_INDEX;
@@ -482,21 +499,21 @@
 /*
  * Seek to a new position.
  */
-off_t _FileAsset::seek(off_t offset, int whence)
+off64_t _FileAsset::seek(off64_t offset, int whence)
 {
-    off_t newPosn;
-    long actualOffset;
+    off64_t newPosn;
+    off64_t actualOffset;
 
     // compute new position within chunk
     newPosn = handleSeek(offset, whence, mOffset, mLength);
-    if (newPosn == (off_t) -1)
+    if (newPosn == (off64_t) -1)
         return newPosn;
 
-    actualOffset = (long) (mStart + newPosn);
+    actualOffset = mStart + newPosn;
 
     if (mFp != NULL) {
         if (fseek(mFp, (long) actualOffset, SEEK_SET) != 0)
-            return (off_t) -1;
+            return (off64_t) -1;
     }
 
     mOffset = actualOffset - mStart;
@@ -603,7 +620,7 @@
     }
 }
 
-int _FileAsset::openFileDescriptor(off_t* outStart, off_t* outLength) const
+int _FileAsset::openFileDescriptor(off64_t* outStart, off64_t* outLength) const
 {
     if (mMap != NULL) {
         const char* fname = mMap->getFileName();
@@ -678,7 +695,7 @@
  * This currently just sets up some values and returns.  On the first
  * read, we expand the entire file into a buffer and return data from it.
  */
-status_t _CompressedAsset::openChunk(int fd, off_t offset,
+status_t _CompressedAsset::openChunk(int fd, off64_t offset,
     int compressionMethod, size_t uncompressedLen, size_t compressedLen)
 {
     assert(mFd < 0);        // no re-open
@@ -782,13 +799,13 @@
  * expensive, because it requires plowing through a bunch of compressed
  * data.
  */
-off_t _CompressedAsset::seek(off_t offset, int whence)
+off64_t _CompressedAsset::seek(off64_t offset, int whence)
 {
-    off_t newPosn;
+    off64_t newPosn;
 
     // compute new position within chunk
     newPosn = handleSeek(offset, whence, mOffset, mUncompressedLen);
-    if (newPosn == (off_t) -1)
+    if (newPosn == (off64_t) -1)
         return newPosn;
 
     if (mZipInflater) {
diff --git a/libs/utils/FileMap.cpp b/libs/utils/FileMap.cpp
index f1f8bda..c220a90 100644
--- a/libs/utils/FileMap.cpp
+++ b/libs/utils/FileMap.cpp
@@ -88,11 +88,12 @@
  *
  * Returns "false" on failure.
  */
-bool FileMap::create(const char* origFileName, int fd, off_t offset, size_t length, bool readOnly)
+bool FileMap::create(const char* origFileName, int fd, off64_t offset, size_t length,
+        bool readOnly)
 {
 #ifdef HAVE_WIN32_FILEMAP
     int     adjust;
-    off_t   adjOffset;
+    off64_t adjOffset;
     size_t  adjLength;
 
     if (mPageSize == -1) {
@@ -131,7 +132,7 @@
 #endif
 #ifdef HAVE_POSIX_FILEMAP
     int     prot, flags, adjust;
-    off_t   adjOffset;
+    off64_t adjOffset;
     size_t  adjLength;
 
     void* ptr;
diff --git a/libs/utils/ObbFile.cpp b/libs/utils/ObbFile.cpp
index 2c3724c..2907b56 100644
--- a/libs/utils/ObbFile.cpp
+++ b/libs/utils/ObbFile.cpp
@@ -22,6 +22,8 @@
 #include <unistd.h>
 
 #define LOG_TAG "ObbFile"
+
+#include <utils/Compat.h>
 #include <utils/Log.h>
 #include <utils/ObbFile.h>
 
@@ -67,17 +69,6 @@
     _rc; })
 #endif
 
-/*
- * Work around situations where off_t is 64-bit and use off64_t in
- * situations where it's 32-bit.
- */
-#ifdef OFF_T_IS_64_BIT
-#define my_lseek64 lseek
-typedef off_t my_off64_t;
-#else
-#define my_lseek64 lseek64
-typedef off64_t my_off64_t;
-#endif
 
 namespace android {
 
@@ -125,7 +116,7 @@
 
 bool ObbFile::parseObbFile(int fd)
 {
-    my_off64_t fileLength = my_lseek64(fd, 0, SEEK_END);
+    off64_t fileLength = lseek64(fd, 0, SEEK_END);
 
     if (fileLength < kFooterMinSize) {
         if (fileLength < 0) {
@@ -140,7 +131,7 @@
     size_t footerSize;
 
     {
-        my_lseek64(fd, fileLength - kFooterTagSize, SEEK_SET);
+        lseek64(fd, fileLength - kFooterTagSize, SEEK_SET);
 
         char *footer = new char[kFooterTagSize];
         actual = TEMP_FAILURE_RETRY(read(fd, footer, kFooterTagSize));
@@ -171,8 +162,8 @@
         }
     }
 
-    my_off64_t fileOffset = fileLength - footerSize - kFooterTagSize;
-    if (my_lseek64(fd, fileOffset, SEEK_SET) != fileOffset) {
+    off64_t fileOffset = fileLength - footerSize - kFooterTagSize;
+    if (lseek64(fd, fileOffset, SEEK_SET) != fileOffset) {
         LOGW("seek %lld failed: %s\n", fileOffset, strerror(errno));
         return false;
     }
@@ -211,10 +202,10 @@
 
     memcpy(&mSalt, (unsigned char*)scanBuf + kSaltOffset, sizeof(mSalt));
 
-    uint32_t packageNameLen = get4LE((unsigned char*)scanBuf + kPackageNameLenOffset);
-    if (packageNameLen <= 0
+    size_t packageNameLen = get4LE((unsigned char*)scanBuf + kPackageNameLenOffset);
+    if (packageNameLen == 0
             || packageNameLen > (footerSize - kPackageNameOffset)) {
-        LOGW("bad ObbFile package name length (0x%04x; 0x%04x possible)\n",
+        LOGW("bad ObbFile package name length (0x%04zx; 0x%04zx possible)\n",
                 packageNameLen, footerSize - kPackageNameOffset);
         free(scanBuf);
         return false;
@@ -257,7 +248,7 @@
         return false;
     }
 
-    my_lseek64(fd, 0, SEEK_END);
+    lseek64(fd, 0, SEEK_END);
 
     if (mPackageName.size() == 0 || mVersion == -1) {
         LOGW("tried to write uninitialized ObbFile data\n");
diff --git a/libs/utils/StreamingZipInflater.cpp b/libs/utils/StreamingZipInflater.cpp
index 1f62ac5..5a162cc 100644
--- a/libs/utils/StreamingZipInflater.cpp
+++ b/libs/utils/StreamingZipInflater.cpp
@@ -31,7 +31,7 @@
 /*
  * Streaming access to compressed asset data in an open fd
  */
-StreamingZipInflater::StreamingZipInflater(int fd, off_t compDataStart,
+StreamingZipInflater::StreamingZipInflater(int fd, off64_t compDataStart,
         size_t uncompSize, size_t compSize) {
     mFd = fd;
     mDataMap = NULL;
@@ -210,7 +210,7 @@
 // seeking backwards requires uncompressing fom the beginning, so is very
 // expensive.  seeking forwards only requires uncompressing from the current
 // position to the destination.
-off_t StreamingZipInflater::seekAbsolute(off_t absoluteInputPosition) {
+off64_t StreamingZipInflater::seekAbsolute(off64_t absoluteInputPosition) {
     if (absoluteInputPosition < mOutCurPosition) {
         // rewind and reprocess the data from the beginning
         if (!mStreamNeedsInit) {
diff --git a/libs/utils/ZipFileCRO.cpp b/libs/utils/ZipFileCRO.cpp
index 16b219ca..55dfd9f 100644
--- a/libs/utils/ZipFileCRO.cpp
+++ b/libs/utils/ZipFileCRO.cpp
@@ -40,7 +40,7 @@
 
 bool ZipFileCRO_getEntryInfo(ZipFileCRO zipToken, ZipEntryRO entryToken,
         int* pMethod, size_t* pUncompLen,
-        size_t* pCompLen, off_t* pOffset, long* pModWhen, long* pCrc32) {
+        size_t* pCompLen, off64_t* pOffset, long* pModWhen, long* pCrc32) {
     ZipFileRO* zip = (ZipFileRO*)zipToken;
     ZipEntryRO entry = (ZipEntryRO)entryToken;
     return zip->getEntryInfo(entry, pMethod, pUncompLen, pCompLen, pOffset,
diff --git a/libs/utils/ZipFileRO.cpp b/libs/utils/ZipFileRO.cpp
index 4261196..b18c383 100644
--- a/libs/utils/ZipFileRO.cpp
+++ b/libs/utils/ZipFileRO.cpp
@@ -146,7 +146,7 @@
         return NAME_NOT_FOUND;
     }
 
-    mFileLength = lseek(fd, 0, SEEK_END);
+    mFileLength = lseek64(fd, 0, SEEK_END);
     if (mFileLength < kEOCDLen) {
         TEMP_FAILURE_RETRY(close(fd));
         return UNKNOWN_ERROR;
@@ -202,7 +202,7 @@
     /*
      * Make sure this is a Zip archive.
      */
-    if (lseek(mFd, 0, SEEK_SET) != 0) {
+    if (lseek64(mFd, 0, SEEK_SET) != 0) {
         LOGW("seek to start failed: %s", strerror(errno));
         free(scanBuf);
         return false;
@@ -240,9 +240,9 @@
      *
      * We start by pulling in the last part of the file.
      */
-    off_t searchStart = mFileLength - readAmount;
+    off64_t searchStart = mFileLength - readAmount;
 
-    if (lseek(mFd, searchStart, SEEK_SET) != searchStart) {
+    if (lseek64(mFd, searchStart, SEEK_SET) != searchStart) {
         LOGW("seek %ld failed: %s\n",  (long) searchStart, strerror(errno));
         free(scanBuf);
         return false;
@@ -274,7 +274,7 @@
         return false;
     }
 
-    off_t eocdOffset = searchStart + i;
+    off64_t eocdOffset = searchStart + i;
     const unsigned char* eocdPtr = scanBuf + i;
 
     assert(eocdOffset < mFileLength);
@@ -473,7 +473,7 @@
  * appear to be bogus.
  */
 bool ZipFileRO::getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen,
-    size_t* pCompLen, off_t* pOffset, long* pModWhen, long* pCrc32) const
+    size_t* pCompLen, off64_t* pOffset, long* pModWhen, long* pCrc32) const
 {
     bool ret = false;
 
@@ -489,7 +489,7 @@
      * so we can just subtract back from that.
      */
     const unsigned char* ptr = (const unsigned char*) hashEntry.name;
-    off_t cdOffset = mDirectoryOffset;
+    off64_t cdOffset = mDirectoryOffset;
 
     ptr -= kCDELen;
 
@@ -536,12 +536,12 @@
 #ifdef HAVE_PREAD
         /*
          * This file descriptor might be from zygote's preloaded assets,
-         * so we need to do an pread() instead of a lseek() + read() to
+         * so we need to do an pread64() instead of a lseek64() + read() to
          * guarantee atomicity across the processes with the shared file
          * descriptors.
          */
         ssize_t actual =
-                TEMP_FAILURE_RETRY(pread(mFd, lfhBuf, sizeof(lfhBuf), localHdrOffset));
+                TEMP_FAILURE_RETRY(pread64(mFd, lfhBuf, sizeof(lfhBuf), localHdrOffset));
 
         if (actual != sizeof(lfhBuf)) {
             LOGW("failed reading lfh from offset %ld\n", localHdrOffset);
@@ -556,17 +556,17 @@
         }
 #else /* HAVE_PREAD */
         /*
-         * For hosts don't have pread() we cannot guarantee atomic reads from
+         * For hosts don't have pread64() we cannot guarantee atomic reads from
          * an offset in a file. Android should never run on those platforms.
          * File descriptors inherited from a fork() share file offsets and
          * there would be nothing to protect from two different processes
-         * calling lseek() concurrently.
+         * calling lseek64() concurrently.
          */
 
         {
             AutoMutex _l(mFdLock);
 
-            if (lseek(mFd, localHdrOffset, SEEK_SET) != localHdrOffset) {
+            if (lseek64(mFd, localHdrOffset, SEEK_SET) != localHdrOffset) {
                 LOGW("failed seeking to lfh at offset %ld\n", localHdrOffset);
                 return false;
             }
@@ -579,7 +579,7 @@
             }
 
             if (get4LE(lfhBuf) != kLFHSignature) {
-                off_t actualOffset = lseek(mFd, 0, SEEK_CUR);
+                off64_t actualOffset = lseek64(mFd, 0, SEEK_CUR);
                 LOGW("didn't find signature at start of lfh; wanted: offset=%ld data=0x%08x; "
                         "got: offset=" ZD " data=0x%08lx\n",
                         localHdrOffset, kLFHSignature, (ZD_TYPE) actualOffset, get4LE(lfhBuf));
@@ -588,7 +588,7 @@
         }
 #endif /* HAVE_PREAD */
 
-        off_t dataOffset = localHdrOffset + kLFHLen
+        off64_t dataOffset = localHdrOffset + kLFHLen
             + get2LE(lfhBuf + kLFHNameLen) + get2LE(lfhBuf + kLFHExtraLen);
         if (dataOffset >= cdOffset) {
             LOGW("bad data offset %ld in zip\n", (long) dataOffset);
@@ -596,14 +596,14 @@
         }
 
         /* check lengths */
-        if ((off_t)(dataOffset + compLen) > cdOffset) {
+        if ((off64_t)(dataOffset + compLen) > cdOffset) {
             LOGW("bad compressed length in zip (%ld + " ZD " > %ld)\n",
                 (long) dataOffset, (ZD_TYPE) compLen, (long) cdOffset);
             return false;
         }
 
         if (method == kCompressStored &&
-            (off_t)(dataOffset + uncompLen) > cdOffset)
+            (off64_t)(dataOffset + uncompLen) > cdOffset)
         {
             LOGE("ERROR: bad uncompressed length in zip (%ld + " ZD " > %ld)\n",
                 (long) dataOffset, (ZD_TYPE) uncompLen, (long) cdOffset);
@@ -649,7 +649,7 @@
 
     FileMap* newMap;
     size_t compLen;
-    off_t offset;
+    off64_t offset;
 
     if (!getEntryInfo(entry, NULL, NULL, &compLen, &offset, NULL, NULL))
         return NULL;
@@ -679,7 +679,7 @@
 
     int method;
     size_t uncompLen, compLen;
-    off_t offset;
+    off64_t offset;
     const unsigned char* ptr;
 
     getEntryInfo(entry, &method, &uncompLen, &compLen, &offset, NULL, NULL);
@@ -739,7 +739,7 @@
 
     int method;
     size_t uncompLen, compLen;
-    off_t offset;
+    off64_t offset;
     const unsigned char* ptr;
 
     getEntryInfo(entry, &method, &uncompLen, &compLen, &offset, NULL, NULL);
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index cfcc2ba..2836005 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -264,6 +264,17 @@
     // Bluetooth headset device
     private BluetoothDevice mBluetoothHeadsetDevice;
 
+    // Indicate if SCO audio connection is currently active and if the initiator is
+    // audio service (internal) or bluetooth headset (external)
+    private int mScoAudioState;
+    // SCO audio state is not active
+    private static final int SCO_STATE_INACTIVE = 0;
+    // SCO audio state is active or starting due to a local request to start a virtual call
+    private static final int SCO_STATE_ACTIVE_INTERNAL = 1;
+    // SCO audio state is active due to an action in BT handsfree (either voice recognition or
+    // in call audio)
+    private static final int SCO_STATE_ACTIVE_EXTERNAL = 2;
+
     ///////////////////////////////////////////////////////////////////////////
     // Construction
     ///////////////////////////////////////////////////////////////////////////
@@ -315,6 +326,7 @@
         intentFilter.addAction(Intent.ACTION_USB_ANLG_HEADSET_PLUG);
         intentFilter.addAction(Intent.ACTION_USB_DGTL_HEADSET_PLUG);
         intentFilter.addAction(Intent.ACTION_HDMI_AUDIO_PLUG);
+        intentFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
         context.registerReceiver(mReceiver, intentFilter);
 
         // Register for media button intent broadcasts.
@@ -692,6 +704,19 @@
                         if (AudioService.this.mMode != mode) {
                             if (AudioSystem.setPhoneState(mode) == AudioSystem.AUDIO_STATUS_OK) {
                                 AudioService.this.mMode = mode;
+                                if (mode != AudioSystem.MODE_NORMAL) {
+                                    synchronized(mScoClients) {
+                                        checkScoAudioState();
+                                        if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL) {
+                                            mBluetoothHeadset.stopVoiceRecognition(
+                                                    mBluetoothHeadsetDevice);
+                                            mBluetoothHeadset.stopVirtualVoiceCall(
+                                                    mBluetoothHeadsetDevice);
+                                        } else {
+                                            clearAllScoClients(mCb, true);
+                                        }
+                                    }
+                                }
                             }
                         }
                     }
@@ -761,8 +786,18 @@
                         hdlr.setMode(mode);
                     }
 
+                    // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
+                    // SCO connections not started by the application changing the mode
                     if (mode != AudioSystem.MODE_NORMAL) {
-                        clearAllScoClients();
+                        synchronized(mScoClients) {
+                            checkScoAudioState();
+                            if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL) {
+                                mBluetoothHeadset.stopVoiceRecognition(mBluetoothHeadsetDevice);
+                                mBluetoothHeadset.stopVirtualVoiceCall(mBluetoothHeadsetDevice);
+                            } else {
+                                clearAllScoClients(cb, true);
+                            }
+                        }
                     }
                 }
             }
@@ -1077,18 +1112,39 @@
         }
 
         private void requestScoState(int state) {
+            if (mBluetoothHeadset == null) {
+                return;
+            }
+
+            checkScoAudioState();
+
             if (totalCount() == 0 &&
-                mBluetoothHeadsetDevice != null &&
-                AudioService.this.mMode == AudioSystem.MODE_NORMAL) {
-                if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
-                    mBluetoothHeadset.startVoiceRecognition(mBluetoothHeadsetDevice);
-                } else {
-                    mBluetoothHeadset.stopVoiceRecognition(mBluetoothHeadsetDevice);
+                mBluetoothHeadsetDevice != null) {
+                // Accept SCO audio activation only in NORMAL audio mode or if the mode is
+                // currently controlled by the same client.
+                if ((AudioService.this.mMode == AudioSystem.MODE_NORMAL ||
+                        mSetModeDeathHandlers.get(0).getBinder() == mCb) &&
+                        state == BluetoothHeadset.STATE_AUDIO_CONNECTED &&
+                        mScoAudioState == SCO_STATE_INACTIVE) {
+                    mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
+                    mBluetoothHeadset.startVirtualVoiceCall(mBluetoothHeadsetDevice);
+                } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED &&
+                        mScoAudioState == SCO_STATE_ACTIVE_INTERNAL){
+                    mBluetoothHeadset.stopVirtualVoiceCall(mBluetoothHeadsetDevice);
                 }
             }
         }
     }
 
+    private void checkScoAudioState() {
+        if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null &&
+                mScoAudioState != SCO_STATE_ACTIVE_INTERNAL &&
+                mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice)
+                != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
+            mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
+        }
+    }
+
     public ScoClient getScoClient(IBinder cb) {
         synchronized(mScoClients) {
             ScoClient client;
@@ -1104,11 +1160,12 @@
         }
     }
 
-    public void clearAllScoClients() {
+    public void clearAllScoClients(IBinder exceptBinder, boolean stopSco) {
         synchronized(mScoClients) {
             int size = mScoClients.size();
             for (int i = 0; i < size; i++) {
-                mScoClients.get(i).clearCount(false);
+                if (mScoClients.get(i).getBinder() != exceptBinder)
+                    mScoClients.get(i).clearCount(stopSco);
             }
         }
     }
@@ -1116,22 +1173,27 @@
     private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
         new BluetoothProfile.ServiceListener() {
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            mBluetoothHeadset = (BluetoothHeadset) proxy;
-            List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices();
-            if (deviceList.size() > 0) {
-                mBluetoothHeadsetDevice = deviceList.get(0);
-            } else {
-                mBluetoothHeadsetDevice = null;
+            synchronized (mScoClients) {
+                mBluetoothHeadset = (BluetoothHeadset) proxy;
+                List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices();
+                if (deviceList.size() > 0) {
+                    mBluetoothHeadsetDevice = deviceList.get(0);
+                } else {
+                    mBluetoothHeadsetDevice = null;
+                }
             }
         }
         public void onServiceDisconnected(int profile) {
-            if (mBluetoothHeadset != null) {
-                List<BluetoothDevice> devices = mBluetoothHeadset.getConnectedDevices();
-                if (devices.size() == 0) {
-                    mBluetoothHeadsetDevice = null;
-                    clearAllScoClients();
+            synchronized (mScoClients) {
+                if (mBluetoothHeadset != null) {
+                    List<BluetoothDevice> devices = mBluetoothHeadset.getConnectedDevices();
+                    if (devices.size() == 0) {
+                        mBluetoothHeadsetDevice = null;
+                        clearAllScoClients(null, false);
+                        mScoAudioState = SCO_STATE_INACTIVE;
+                    }
+                    mBluetoothHeadset = null;
                 }
-                mBluetoothHeadset = null;
             }
         }
     };
@@ -1892,19 +1954,22 @@
                 boolean isConnected = (mConnectedDevices.containsKey(device) &&
                                        mConnectedDevices.get(device).equals(address));
 
-                if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
-                    AudioSystem.setDeviceConnectionState(device,
-                                                         AudioSystem.DEVICE_STATE_UNAVAILABLE,
-                                                         address);
-                    mConnectedDevices.remove(device);
-                    mBluetoothHeadsetDevice = null;
-                    clearAllScoClients();
-                } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
-                    AudioSystem.setDeviceConnectionState(device,
-                                                         AudioSystem.DEVICE_STATE_AVAILABLE,
-                                                         address);
-                    mConnectedDevices.put(new Integer(device), address);
-                    mBluetoothHeadsetDevice = btDevice;
+                synchronized (mScoClients) {
+                    if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
+                        AudioSystem.setDeviceConnectionState(device,
+                                                             AudioSystem.DEVICE_STATE_UNAVAILABLE,
+                                                             address);
+                        mConnectedDevices.remove(device);
+                        mBluetoothHeadsetDevice = null;
+                        clearAllScoClients(null, false);
+                        mScoAudioState = SCO_STATE_INACTIVE;
+                    } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
+                        AudioSystem.setDeviceConnectionState(device,
+                                                             AudioSystem.DEVICE_STATE_AVAILABLE,
+                                                             address);
+                        mConnectedDevices.put(new Integer(device), address);
+                        mBluetoothHeadsetDevice = btDevice;
+                    }
                 }
             } else if (action.equals(Intent.ACTION_HEADSET_PLUG)) {
                 int state = intent.getIntExtra("state", 0);
@@ -1965,31 +2030,44 @@
                     mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET), "");
                 }
             } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
-                int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
+                boolean broadcast = false;
+                int audioState = AudioManager.SCO_AUDIO_STATE_ERROR;
                 synchronized (mScoClients) {
-                    if (!mScoClients.isEmpty()) {
-                        switch (state) {
-                        case BluetoothHeadset.STATE_AUDIO_CONNECTED:
-                            state = AudioManager.SCO_AUDIO_STATE_CONNECTED;
-                            break;
-                        case BluetoothHeadset.STATE_AUDIO_DISCONNECTED:
-                            state = AudioManager.SCO_AUDIO_STATE_DISCONNECTED;
-                            break;
-                        case BluetoothHeadset.STATE_AUDIO_CONNECTING:
-                            // Todo(): Handle this, ignore for now as a public
-                            // API will break.
-                            break;
-                        default:
-                            state = AudioManager.SCO_AUDIO_STATE_ERROR;
-                            break;
+                    int btState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
+                    if (!mScoClients.isEmpty() && mScoAudioState == SCO_STATE_ACTIVE_INTERNAL) {
+                        broadcast = true;
+                    }
+                    switch (btState) {
+                    case BluetoothHeadset.STATE_AUDIO_CONNECTED:
+                        audioState = AudioManager.SCO_AUDIO_STATE_CONNECTED;
+                        if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL) {
+                            mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
                         }
-                        if (state != AudioManager.SCO_AUDIO_STATE_ERROR) {
-                            Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
-                            newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, state);
-                            mContext.sendStickyBroadcast(newIntent);
+                        break;
+                    case BluetoothHeadset.STATE_AUDIO_DISCONNECTED:
+                        audioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED;
+                        mScoAudioState = SCO_STATE_INACTIVE;
+                        break;
+                    case BluetoothHeadset.STATE_AUDIO_CONNECTING:
+                        if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL) {
+                            mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
                         }
+                    default:
+                        // do not broadcast CONNECTING or invalid state
+                        broadcast = false;
+                        break;
                     }
                 }
+                if (broadcast) {
+                    Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
+                    newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, audioState);
+                    mContext.sendStickyBroadcast(newIntent);
+                }
+            } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
+                Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
+                newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,
+                        AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
+                mContext.sendStickyBroadcast(newIntent);
             }
         }
     }
diff --git a/media/java/android/media/MtpDatabase.java b/media/java/android/media/MtpDatabase.java
index 139a6ea..6056a0f 100644
--- a/media/java/android/media/MtpDatabase.java
+++ b/media/java/android/media/MtpDatabase.java
@@ -31,6 +31,8 @@
 import android.provider.MediaStore.Images;
 import android.provider.MediaStore.MediaColumns;
 import android.util.Log;
+import android.view.Display;
+import android.view.WindowManager;
 
 import java.io.File;
 import java.util.HashMap;
@@ -460,6 +462,7 @@
         return new int[] {
             MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER,
             MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,
+            MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE,
         };
     }
 
@@ -592,9 +595,21 @@
                         c.close();
                     }
                 }
-        }
 
-        return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
+            case MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE:
+                // use screen size as max image size
+                Display display = ((WindowManager)mContext.getSystemService(
+                        Context.WINDOW_SERVICE)).getDefaultDisplay();
+                int width = display.getWidth();
+                int height = display.getHeight();
+                String imageSize = Integer.toString(width) + "x" +  Integer.toString(height);
+                imageSize.getChars(0, imageSize.length(), outStringValue, 0);
+                outStringValue[imageSize.length()] = 0;
+                return MtpConstants.RESPONSE_OK;
+
+            default:
+                return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
+        }
     }
 
     private int setDeviceProperty(int property, long intValue, String stringValue) {
diff --git a/media/jni/android_media_MtpDatabase.cpp b/media/jni/android_media_MtpDatabase.cpp
index 1909e6a..9bb93fd 100644
--- a/media/jni/android_media_MtpDatabase.cpp
+++ b/media/jni/android_media_MtpDatabase.cpp
@@ -860,8 +860,9 @@
 };
 
 static const PropertyTableEntry   kDevicePropertyTable[] = {
-    {   MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER,     MTP_TYPE_STR },
-    {   MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,        MTP_TYPE_STR },
+    {   MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER,    MTP_TYPE_STR },
+    {   MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,       MTP_TYPE_STR },
+    {   MTP_DEVICE_PROPERTY_IMAGE_SIZE,                 MTP_TYPE_STR },
 };
 
 bool MyMtpDatabase::getObjectPropertyInfo(MtpObjectProperty property, int& type) {
@@ -932,6 +933,9 @@
     MtpProperty* result = NULL;
     switch (property) {
         case MTP_PROPERTY_OBJECT_FORMAT:
+            // use format as default value
+            result = new MtpProperty(property, MTP_TYPE_UINT16, false, format);
+            break;
         case MTP_PROPERTY_PROTECTION_STATUS:
         case MTP_PROPERTY_TRACK:
             result = new MtpProperty(property, MTP_TYPE_UINT16);
@@ -973,31 +977,35 @@
 }
 
 MtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
     MtpProperty* result = NULL;
+    bool writable = false;
+
     switch (property) {
         case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
         case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
-        {
-            // writeable string properties
-            result = new MtpProperty(property, MTP_TYPE_STR, true);
+            writable = true;
+            // fall through
+        case MTP_DEVICE_PROPERTY_IMAGE_SIZE:
+            result = new MtpProperty(property, MTP_TYPE_STR, writable);
 
-            // set current value
-            JNIEnv* env = AndroidRuntime::getJNIEnv();
+            // get current value
             jint ret = env->CallIntMethod(mDatabase, method_getDeviceProperty,
                         (jint)property, mLongBuffer, mStringBuffer);
             if (ret == MTP_RESPONSE_OK) {
                 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
                 result->setCurrentValue(str);
+                // for read-only properties it is safe to assume current value is default value
+                if (!writable)
+                    result->setDefaultValue(str);
                 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
             } else {
                 LOGE("unable to read device property, response: %04X", ret);
             }
-
-            checkAndClearExceptionFromCallback(env, __FUNCTION__);
             break;
-        }
     }
 
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
     return result;
 }
 
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 3108e4e..4bf922f 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1650,8 +1650,7 @@
         }
 
         info.mBuffer = buffer;
-        info.mOwnedByComponent = false;
-        info.mOwnedByNativeWindow = false;
+        info.mStatus = OWNED_BY_US;
         info.mMem = mem;
         info.mMediaBuffer = NULL;
 
@@ -1759,8 +1758,7 @@
         info.mData = NULL;
         info.mSize = def.nBufferSize;
         info.mBuffer = bufferId;
-        info.mOwnedByComponent = false;
-        info.mOwnedByNativeWindow = false;
+        info.mStatus = OWNED_BY_US;
         info.mMem = NULL;
         info.mMediaBuffer = new MediaBuffer(graphicBuffer);
         info.mMediaBuffer->setObserver(this);
@@ -1794,7 +1792,7 @@
 }
 
 status_t OMXCodec::cancelBufferToNativeWindow(BufferInfo *info) {
-    CHECK(!info->mOwnedByNativeWindow);
+    CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
     CODEC_LOGV("Calling cancelBuffer on buffer %p", info->mBuffer);
     int err = mNativeWindow->cancelBuffer(
         mNativeWindow.get(), info->mMediaBuffer->graphicBuffer().get());
@@ -1804,7 +1802,7 @@
       setState(ERROR);
       return err;
     }
-    info->mOwnedByNativeWindow = true;
+    info->mStatus = OWNED_BY_NATIVE_WINDOW;
     return OK;
 }
 
@@ -1839,8 +1837,8 @@
     }
 
     // The native window no longer owns the buffer.
-    CHECK(bufInfo->mOwnedByNativeWindow);
-    bufInfo->mOwnedByNativeWindow = false;
+    CHECK_EQ((int)bufInfo->mStatus, (int)OWNED_BY_NATIVE_WINDOW);
+    bufInfo->mStatus = OWNED_BY_US;
 
     return bufInfo;
 }
@@ -1871,13 +1869,13 @@
             }
 
             CHECK(i < buffers->size());
-            if (!(*buffers)[i].mOwnedByComponent) {
+            if ((*buffers)[i].mStatus != OWNED_BY_COMPONENT) {
                 LOGW("We already own input buffer %p, yet received "
                      "an EMPTY_BUFFER_DONE.", buffer);
             }
 
             BufferInfo* info = &buffers->editItemAt(i);
-            info->mOwnedByComponent = false;
+            info->mStatus = OWNED_BY_US;
 
             // Buffer could not be released until empty buffer done is called.
             if (info->mMediaBuffer != NULL) {
@@ -1926,12 +1924,12 @@
             CHECK(i < buffers->size());
             BufferInfo *info = &buffers->editItemAt(i);
 
-            if (!info->mOwnedByComponent) {
+            if (info->mStatus != OWNED_BY_COMPONENT) {
                 LOGW("We already own output buffer %p, yet received "
                      "a FILL_BUFFER_DONE.", buffer);
             }
 
-            info->mOwnedByComponent = false;
+            info->mStatus = OWNED_BY_US;
 
             if (mPortStatus[kPortIndexOutput] == DISABLING) {
                 CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
@@ -2400,7 +2398,7 @@
 size_t OMXCodec::countBuffersWeOwn(const Vector<BufferInfo> &buffers) {
     size_t n = 0;
     for (size_t i = 0; i < buffers.size(); ++i) {
-        if (!buffers[i].mOwnedByComponent) {
+        if (buffers[i].mStatus != OWNED_BY_COMPONENT) {
             ++n;
         }
     }
@@ -2417,11 +2415,12 @@
     for (size_t i = buffers->size(); i-- > 0;) {
         BufferInfo *info = &buffers->editItemAt(i);
 
-        if (onlyThoseWeOwn && info->mOwnedByComponent) {
+        if (onlyThoseWeOwn && info->mStatus == OWNED_BY_COMPONENT) {
             continue;
         }
 
-        CHECK_EQ((int)info->mOwnedByComponent, (int)false);
+        CHECK(info->mStatus == OWNED_BY_US
+                || info->mStatus == OWNED_BY_NATIVE_WINDOW);
 
         CODEC_LOGV("freeing buffer %p on port %ld", info->mBuffer, portIndex);
 
@@ -2454,7 +2453,7 @@
 
         // Cancel the buffer if it belongs to an ANativeWindow.
         sp<GraphicBuffer> graphicBuffer = info->mMediaBuffer->graphicBuffer();
-        if (!info->mOwnedByNativeWindow && graphicBuffer != 0) {
+        if (info->mStatus == OWNED_BY_US && graphicBuffer != 0) {
             err = cancelBufferToNativeWindow(info);
         }
 
@@ -2559,7 +2558,7 @@
     Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
     for (size_t i = 0; i < buffers->size(); ++i) {
         BufferInfo *info = &buffers->editItemAt(i);
-        if (!info->mOwnedByNativeWindow) {
+        if (info->mStatus == OWNED_BY_US) {
             fillOutputBuffer(&buffers->editItemAt(i));
         }
     }
@@ -2570,15 +2569,17 @@
 
     Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
     for (size_t i = 0; i < buffers->size(); ++i) {
-        drainInputBuffer(&buffers->editItemAt(i));
+        if (!drainInputBuffer(&buffers->editItemAt(i))) {
+            break;
+        }
     }
 }
 
-void OMXCodec::drainInputBuffer(BufferInfo *info) {
-    CHECK_EQ((int)info->mOwnedByComponent, (int)false);
+bool OMXCodec::drainInputBuffer(BufferInfo *info) {
+    CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
 
     if (mSignalledEOS) {
-        return;
+        return false;
     }
 
     if (mCodecSpecificDataIndex < mCodecSpecificData.size()) {
@@ -2614,14 +2615,14 @@
                 0);
         CHECK_EQ(err, (status_t)OK);
 
-        info->mOwnedByComponent = true;
+        info->mStatus = OWNED_BY_COMPONENT;
 
         ++mCodecSpecificDataIndex;
-        return;
+        return true;
     }
 
     if (mPaused) {
-        return;
+        return false;
     }
 
     status_t err;
@@ -2631,6 +2632,7 @@
 
     size_t offset = 0;
     int32_t n = 0;
+
     for (;;) {
         MediaBuffer *srcBuffer;
         MediaSource::ReadOptions options;
@@ -2689,7 +2691,7 @@
                 srcBuffer = NULL;
 
                 setState(ERROR);
-                return;
+                return false;
             }
 
             mLeftOverBuffer = srcBuffer;
@@ -2699,9 +2701,15 @@
         bool releaseBuffer = true;
         if (mIsEncoder && (mQuirks & kAvoidMemcopyInputRecordingFrames)) {
             CHECK(mOMXLivesLocally && offset == 0);
-            OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *) info->mBuffer;
+
+            OMX_BUFFERHEADERTYPE *header =
+                (OMX_BUFFERHEADERTYPE *)info->mBuffer;
+
             CHECK(header->pBuffer == info->mData);
-            header->pBuffer = (OMX_U8 *) srcBuffer->data() + srcBuffer->range_offset();
+
+            header->pBuffer =
+                (OMX_U8 *)srcBuffer->data() + srcBuffer->range_offset();
+
             releaseBuffer = false;
             info->mMediaBuffer = srcBuffer;
         } else {
@@ -2710,7 +2718,8 @@
                 info->mMediaBuffer = srcBuffer;
             }
             memcpy((uint8_t *)info->mData + offset,
-                    (const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(),
+                    (const uint8_t *)srcBuffer->data()
+                        + srcBuffer->range_offset(),
                     srcBuffer->range_length());
         }
 
@@ -2766,10 +2775,10 @@
 
     if (err != OK) {
         setState(ERROR);
-        return;
+        return false;
     }
 
-    info->mOwnedByComponent = true;
+    info->mStatus = OWNED_BY_COMPONENT;
 
     // This component does not ever signal the EOS flag on output buffers,
     // Thanks for nothing.
@@ -2777,10 +2786,12 @@
         mNoMoreOutputData = true;
         mBufferFilled.signal();
     }
+
+    return true;
 }
 
 void OMXCodec::fillOutputBuffer(BufferInfo *info) {
-    CHECK_EQ((int)info->mOwnedByComponent, (int)false);
+    CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
 
     if (mNoMoreOutputData) {
         CODEC_LOGV("There is no more output data available, not "
@@ -2793,7 +2804,6 @@
         if (graphicBuffer != 0) {
             // When using a native buffer we need to lock the buffer before
             // giving it to OMX.
-            CHECK(!info->mOwnedByNativeWindow);
             CODEC_LOGV("Calling lockBuffer on %p", info->mBuffer);
             int err = mNativeWindow->lockBuffer(mNativeWindow.get(),
                     graphicBuffer.get());
@@ -2816,19 +2826,20 @@
         return;
     }
 
-    info->mOwnedByComponent = true;
+    info->mStatus = OWNED_BY_COMPONENT;
 }
 
-void OMXCodec::drainInputBuffer(IOMX::buffer_id buffer) {
+bool OMXCodec::drainInputBuffer(IOMX::buffer_id buffer) {
     Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
     for (size_t i = 0; i < buffers->size(); ++i) {
         if ((*buffers)[i].mBuffer == buffer) {
-            drainInputBuffer(&buffers->editItemAt(i));
-            return;
+            return drainInputBuffer(&buffers->editItemAt(i));
         }
     }
 
     CHECK(!"should not be here.");
+
+    return false;
 }
 
 void OMXCodec::fillOutputBuffer(IOMX::buffer_id buffer) {
@@ -3374,6 +3385,9 @@
     mFilledBuffers.erase(mFilledBuffers.begin());
 
     BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
+    CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
+    info->mStatus = OWNED_BY_CLIENT;
+
     info->mMediaBuffer->add_ref();
     *buffer = info->mMediaBuffer;
 
@@ -3389,6 +3403,10 @@
 
         if (info->mMediaBuffer == buffer) {
             CHECK_EQ((int)mPortStatus[kPortIndexOutput], (int)ENABLED);
+            CHECK_EQ((int)info->mStatus, (int)OWNED_BY_CLIENT);
+
+            info->mStatus = OWNED_BY_US;
+
             if (buffer->graphicBuffer() == 0) {
                 fillOutputBuffer(info);
             } else {
@@ -3402,10 +3420,10 @@
                     if (err < 0) {
                         return;
                     }
-                } else {
-                    info->mOwnedByNativeWindow = true;
                 }
 
+                info->mStatus = OWNED_BY_NATIVE_WINDOW;
+
                 // Dequeue the next buffer from the native window.
                 BufferInfo *nextBufInfo = dequeueBufferFromNativeWindow();
                 if (nextBufInfo == 0) {
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index c28de93..ee3eefc 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -144,7 +144,10 @@
             static_cast<MediaSource::ReadOptions::SeekMode>(seekMode);
 
     int64_t thumbNailTime;
-    if (frameTimeUs < 0 && trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)) {
+    if (frameTimeUs < 0) {
+        if (!trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)) {
+            thumbNailTime = 0;
+        }
         options.setSeekTo(thumbNailTime, mode);
     } else {
         thumbNailTime = -1;
diff --git a/media/mtp/Android.mk b/media/mtp/Android.mk
index b7e1a2a..e285847 100644
--- a/media/mtp/Android.mk
+++ b/media/mtp/Android.mk
@@ -47,3 +47,32 @@
 
 endif
 
+ifeq ($(HOST_OS),linux)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=                                       \
+                  MtpClient.cpp                         \
+                  MtpDataPacket.cpp                     \
+                  MtpDebug.cpp                          \
+                  MtpDevice.cpp                         \
+                  MtpEventPacket.cpp                    \
+                  MtpDeviceInfo.cpp                     \
+                  MtpObjectInfo.cpp                     \
+                  MtpPacket.cpp                         \
+                  MtpProperty.cpp                       \
+                  MtpRequestPacket.cpp                  \
+                  MtpResponsePacket.cpp                 \
+                  MtpStorageInfo.cpp                    \
+                  MtpStringBuffer.cpp                   \
+                  MtpStorage.cpp                        \
+                  MtpUtils.cpp                          \
+                  PtpCursor.cpp                         \
+
+LOCAL_MODULE:= libmtp
+
+LOCAL_CFLAGS := -DMTP_HOST
+
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+endif
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index 416ebfe..8ad39dc 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -63,17 +63,13 @@
     openSession();
     mDeviceInfo = getDeviceInfo();
     if (mDeviceInfo) {
-        mDeviceInfo->print();
-
         if (mDeviceInfo->mDeviceProperties) {
             int count = mDeviceInfo->mDeviceProperties->size();
             for (int i = 0; i < count; i++) {
                 MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i];
                 MtpProperty* property = getDevicePropDesc(propCode);
-                if (property) {
-                    property->print();
+                if (property)
                     mDeviceProperties.push(property);
-                }
             }
         }
     }
@@ -87,6 +83,45 @@
     }
 }
 
+void MtpDevice::print() {
+    if (mDeviceInfo) {
+        mDeviceInfo->print();
+
+        if (mDeviceInfo->mDeviceProperties) {
+            LOGI("***** DEVICE PROPERTIES *****\n");
+            int count = mDeviceInfo->mDeviceProperties->size();
+            for (int i = 0; i < count; i++) {
+                MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i];
+                MtpProperty* property = getDevicePropDesc(propCode);
+                if (property) {
+                    property->print();
+                }
+            }
+        }
+    }
+
+    if (mDeviceInfo->mPlaybackFormats) {
+            LOGI("***** OBJECT PROPERTIES *****\n");
+        int count = mDeviceInfo->mPlaybackFormats->size();
+        for (int i = 0; i < count; i++) {
+            MtpObjectFormat format = (*mDeviceInfo->mPlaybackFormats)[i];
+            LOGI("*** FORMAT: %s\n", MtpDebug::getFormatCodeName(format));
+            MtpObjectPropertyList* props = getObjectPropsSupported(format);
+            if (props) {
+                for (int j = 0; j < props->size(); j++) {
+                    MtpObjectProperty prop = (*props)[j];
+                    MtpProperty* property = getObjectPropDesc(prop, format);
+                    if (property)
+                        property->print();
+                    else
+                        LOGE("could not fetch property: %s",
+                                MtpDebug::getObjectPropCodeName(prop));
+                }
+            }
+        }
+    }
+}
+
 const char* MtpDevice::getDeviceName() {
     if (mDevice)
         return usb_device_get_name(mDevice);
@@ -330,6 +365,23 @@
         return -1;
 }
 
+MtpObjectPropertyList* MtpDevice::getObjectPropsSupported(MtpObjectFormat format) {
+    Mutex::Autolock autoLock(mMutex);
+
+    mRequest.reset();
+    mRequest.setParameter(1, format);
+    if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED))
+        return NULL;
+    if (!readData())
+        return NULL;
+    MtpResponseCode ret = readResponse();
+    if (ret == MTP_RESPONSE_OK) {
+        return mData.getAUInt16();
+    }
+    return NULL;
+
+}
+
 MtpProperty* MtpDevice::getDevicePropDesc(MtpDeviceProperty code) {
     Mutex::Autolock autoLock(mMutex);
 
@@ -348,6 +400,25 @@
     return NULL;
 }
 
+MtpProperty* MtpDevice::getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format) {
+    Mutex::Autolock autoLock(mMutex);
+
+    mRequest.reset();
+    mRequest.setParameter(1, code);
+    mRequest.setParameter(2, format);
+    if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROP_DESC))
+        return NULL;
+    if (!readData())
+        return NULL;
+    MtpResponseCode ret = readResponse();
+    if (ret == MTP_RESPONSE_OK) {
+        MtpProperty* property = new MtpProperty;
+        property->read(mData);
+        return property;
+    }
+    return NULL;
+}
+
 // reads the object's data and writes it to the specified file path
 bool MtpDevice::readObject(MtpObjectHandle handle, const char* destPath, int group, int perm) {
     LOGD("readObject: %s", destPath);
diff --git a/media/mtp/MtpDevice.h b/media/mtp/MtpDevice.h
index 21c85d5..6ffbd24 100644
--- a/media/mtp/MtpDevice.h
+++ b/media/mtp/MtpDevice.h
@@ -67,6 +67,7 @@
 
     void                    initialize();
     void                    close();
+    void                    print();
     const char*             getDeviceName();
 
     bool                    openSession();
@@ -85,7 +86,10 @@
     MtpObjectHandle         getParent(MtpObjectHandle handle);
     MtpObjectHandle         getStorageID(MtpObjectHandle handle);
 
+    MtpObjectPropertyList*  getObjectPropsSupported(MtpObjectFormat format);
+
     MtpProperty*            getDevicePropDesc(MtpDeviceProperty code);
+    MtpProperty*            getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format);
 
     bool                   readObject(MtpObjectHandle handle, const char* destPath, int group,
                                     int perm);
diff --git a/media/mtp/MtpProperty.cpp b/media/mtp/MtpProperty.cpp
index 4356a6f..b095ce1 100644
--- a/media/mtp/MtpProperty.cpp
+++ b/media/mtp/MtpProperty.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "MtpProperty"
 
 #include "MtpDataPacket.h"
+#include "MtpDebug.h"
 #include "MtpProperty.h"
 #include "MtpStringBuffer.h"
 #include "MtpUtils.h"
@@ -121,9 +122,8 @@
 }
 
 void MtpProperty::read(MtpDataPacket& packet) {
-    bool deviceProp = isDeviceProperty();
-
     mCode = packet.getUInt16();
+    bool deviceProp = isDeviceProperty();
     mType = packet.getUInt16();
     mWriteable = (packet.getUInt8() == 1);
     switch (mType) {
@@ -317,9 +317,93 @@
 }
 
 void MtpProperty::print() {
-    LOGV("MtpProperty %04X\n", mCode);
-    LOGV("    type %04X\n", mType);
-    LOGV("    writeable %s\n", (mWriteable ? "true" : "false"));
+    MtpString buffer;
+    bool deviceProp = isDeviceProperty();
+    if (deviceProp)
+        LOGI("    %s (%04X)", MtpDebug::getDevicePropCodeName(mCode), mCode);
+    else
+        LOGI("    %s (%04X)", MtpDebug::getObjectPropCodeName(mCode), mCode);
+    LOGI("    type %04X", mType);
+    LOGI("    writeable %s", (mWriteable ? "true" : "false"));
+    buffer = "    default value: ";
+    print(mDefaultValue, buffer);
+    LOGI("%s", (const char *)buffer);
+    if (deviceProp) {
+        buffer = "    current value: ";
+        print(mCurrentValue, buffer);
+        LOGI("%s", (const char *)buffer);
+    }
+    switch (mFormFlag) {
+        case kFormNone:
+            break;
+        case kFormRange:
+            buffer = "    Range (";
+            print(mMinimumValue, buffer);
+            buffer += ", ";
+            print(mMaximumValue, buffer);
+            buffer += ", ";
+            print(mStepSize, buffer);
+            LOGI("%s", (const char *)buffer);
+            break;
+        case kFormEnum:
+            buffer = "    Enum { ";
+            for (int i = 0; i < mEnumLength; i++) {
+                print(mEnumValues[i], buffer);
+                buffer += " ";
+            }
+            buffer += "}";
+            LOGI("%s", (const char *)buffer);
+            break;
+        case kFormDateTime:
+            LOGI("    DateTime\n");
+            break;
+        default:
+            LOGI("    form %d\n", mFormFlag);
+            break;
+    }
+}
+
+void MtpProperty::print(MtpPropertyValue& value, MtpString& buffer) {
+    switch (mType) {
+        case MTP_TYPE_INT8:
+            buffer.appendFormat("%d", value.u.i8);
+            break;
+        case MTP_TYPE_UINT8:
+            buffer.appendFormat("%d", value.u.u8);
+            break;
+        case MTP_TYPE_INT16:
+            buffer.appendFormat("%d", value.u.i16);
+            break;
+        case MTP_TYPE_UINT16:
+            buffer.appendFormat("%d", value.u.u16);
+            break;
+        case MTP_TYPE_INT32:
+            buffer.appendFormat("%d", value.u.i32);
+            break;
+        case MTP_TYPE_UINT32:
+            buffer.appendFormat("%d", value.u.u32);
+            break;
+        case MTP_TYPE_INT64:
+            buffer.appendFormat("%lld", value.u.i64);
+            break;
+        case MTP_TYPE_UINT64:
+            buffer.appendFormat("%lld", value.u.u64);
+            break;
+        case MTP_TYPE_INT128:
+            buffer.appendFormat("%08X%08X%08X%08X", value.u.i128[0], value.u.i128[1],
+                    value.u.i128[2], value.u.i128[3]);
+            break;
+        case MTP_TYPE_UINT128:
+            buffer.appendFormat("%08X%08X%08X%08X", value.u.u128[0], value.u.u128[1],
+                    value.u.u128[2], value.u.u128[3]);
+            break;
+        case MTP_TYPE_STR:
+            buffer.appendFormat("%s", value.str);
+            break;
+        default:
+            LOGE("unsupported type for MtpProperty::print\n");
+            break;
+    }
 }
 
 void MtpProperty::readValue(MtpDataPacket& packet, MtpPropertyValue& value) {
diff --git a/media/mtp/MtpProperty.h b/media/mtp/MtpProperty.h
index f783a87..06ca56e 100644
--- a/media/mtp/MtpProperty.h
+++ b/media/mtp/MtpProperty.h
@@ -94,6 +94,7 @@
     void                setFormDateTime();
 
     void                print();
+    void                print(MtpPropertyValue& value, MtpString& buffer);
 
     inline bool         isDeviceProperty() const {
                             return (   ((mCode & 0xF000) == 0x5000)
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index de6cbac..5c1e02a 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -423,7 +423,7 @@
     if (!mSessionOpen)
         return MTP_RESPONSE_SESSION_NOT_OPEN;
     MtpObjectFormat format = mRequest.getParameter(1);
-    MtpDevicePropertyList* properties = mDatabase->getSupportedObjectProperties(format);
+    MtpObjectPropertyList* properties = mDatabase->getSupportedObjectProperties(format);
     mData.putAUInt16(properties);
     delete properties;
     return MTP_RESPONSE_OK;
diff --git a/native/android/asset_manager.cpp b/native/android/asset_manager.cpp
index 3f7c1b6..33f088d 100644
--- a/native/android/asset_manager.cpp
+++ b/native/android/asset_manager.cpp
@@ -201,7 +201,7 @@
 
 int AAsset_openFileDescriptor(AAsset* asset, off_t* outStart, off_t* outLength)
 {
-    return asset->mAsset->openFileDescriptor(outStart, outLength);
+    return asset->mAsset->openFileDescriptor((off64_t*)outStart, (off64_t*)outLength);
 }
 
 int AAsset_isAllocated(AAsset* asset)
diff --git a/native/include/android/input.h b/native/include/android/input.h
index 861ec8b..e196686 100644
--- a/native/include/android/input.h
+++ b/native/include/android/input.h
@@ -215,7 +215,15 @@
      * tracked from its initial down.  That is, somebody requested that tracking
      * started on the key down and a long press has not caused
      * the tracking to be canceled. */
-    AKEY_EVENT_FLAG_TRACKING = 0x200
+    AKEY_EVENT_FLAG_TRACKING = 0x200,
+
+    /* Set when a key event has been synthesized to implement default behavior
+     * for an event that the application did not handle.
+     * Fallback key events are generated by unhandled trackball motions
+     * (to emulate a directional keypad) and by certain unhandled key presses
+     * that are declared in the key map (such as special function numeric keypad
+     * keys when numlock is off). */
+    AKEY_EVENT_FLAG_FALLBACK = 0x400,
 };
 
 /*
diff --git a/native/include/android/keycodes.h b/native/include/android/keycodes.h
index 5f33ad5..b026a0c 100644
--- a/native/include/android/keycodes.h
+++ b/native/include/android/keycodes.h
@@ -230,6 +230,7 @@
     AKEYCODE_PROG_GREEN      = 184,
     AKEYCODE_PROG_YELLOW     = 185,
     AKEYCODE_PROG_BLUE       = 186,
+    AKEYCODE_APP_SWITCH      = 187,
 
     // NOTE: If you add a new keycode here you must also add it to several other files.
     //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/opengl/tests/gl2_java/AndroidManifest.xml b/opengl/tests/gl2_java/AndroidManifest.xml
index 585b63f1..8bb6840 100644
--- a/opengl/tests/gl2_java/AndroidManifest.xml
+++ b/opengl/tests/gl2_java/AndroidManifest.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, 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.
-*/
+<!-- Copyright (C) 2009 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.
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/gl2_java/res/values/strings.xml b/opengl/tests/gl2_java/res/values/strings.xml
index d718b1d..06bd23c 100644
--- a/opengl/tests/gl2_java/res/values/strings.xml
+++ b/opengl/tests/gl2_java/res/values/strings.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tests/gl2_jni/AndroidManifest.xml b/opengl/tests/gl2_jni/AndroidManifest.xml
index a72a6a5..1827e5f 100644
--- a/opengl/tests/gl2_jni/AndroidManifest.xml
+++ b/opengl/tests/gl2_jni/AndroidManifest.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, 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.
-*/
+<!-- Copyright (C) 2009 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.
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/gl2_jni/res/values/strings.xml b/opengl/tests/gl2_jni/res/values/strings.xml
index e3f7331..a29c74b 100644
--- a/opengl/tests/gl2_jni/res/values/strings.xml
+++ b/opengl/tests/gl2_jni/res/values/strings.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tests/gl_jni/AndroidManifest.xml b/opengl/tests/gl_jni/AndroidManifest.xml
index 64bd6bf..5d0ec96 100644
--- a/opengl/tests/gl_jni/AndroidManifest.xml
+++ b/opengl/tests/gl_jni/AndroidManifest.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, 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.
-*/
+<!-- Copyright (C) 2009 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.
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/gl_jni/res/values/strings.xml b/opengl/tests/gl_jni/res/values/strings.xml
index 880f5c9..aee9fa0 100644
--- a/opengl/tests/gl_jni/res/values/strings.xml
+++ b/opengl/tests/gl_jni/res/values/strings.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tests/gl_perfapp/AndroidManifest.xml b/opengl/tests/gl_perfapp/AndroidManifest.xml
index 305d95f..ee4bd98 100644
--- a/opengl/tests/gl_perfapp/AndroidManifest.xml
+++ b/opengl/tests/gl_perfapp/AndroidManifest.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, 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.
-*/
+<!-- Copyright (C) 2009 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.
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/gl_perfapp/res/values/strings.xml b/opengl/tests/gl_perfapp/res/values/strings.xml
index dc21075..52cd961 100644
--- a/opengl/tests/gl_perfapp/res/values/strings.xml
+++ b/opengl/tests/gl_perfapp/res/values/strings.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tests/gldual/AndroidManifest.xml b/opengl/tests/gldual/AndroidManifest.xml
index 06f4c4d..a36f4f7 100644
--- a/opengl/tests/gldual/AndroidManifest.xml
+++ b/opengl/tests/gldual/AndroidManifest.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, 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.
-*/
+<!-- Copyright (C) 2009 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.
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/gldual/res/values/strings.xml b/opengl/tests/gldual/res/values/strings.xml
index 4267dff..b1f535d 100644
--- a/opengl/tests/gldual/res/values/strings.xml
+++ b/opengl/tests/gldual/res/values/strings.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tests/testFramerate/AndroidManifest.xml b/opengl/tests/testFramerate/AndroidManifest.xml
index e04342c..85617f4 100644
--- a/opengl/tests/testFramerate/AndroidManifest.xml
+++ b/opengl/tests/testFramerate/AndroidManifest.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, 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.
-*/
+<!-- Copyright (C) 2009 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.
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/testFramerate/res/values/strings.xml b/opengl/tests/testFramerate/res/values/strings.xml
index e6b3088..baadf0e 100644
--- a/opengl/tests/testFramerate/res/values/strings.xml
+++ b/opengl/tests/testFramerate/res/values/strings.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tests/testLatency/AndroidManifest.xml b/opengl/tests/testLatency/AndroidManifest.xml
index 741266e..59f2643 100644
--- a/opengl/tests/testLatency/AndroidManifest.xml
+++ b/opengl/tests/testLatency/AndroidManifest.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, 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.
-*/
+<!-- Copyright (C) 2009 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.
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/testLatency/res/values/strings.xml b/opengl/tests/testLatency/res/values/strings.xml
index 0309991..d80b77c 100644
--- a/opengl/tests/testLatency/res/values/strings.xml
+++ b/opengl/tests/testLatency/res/values/strings.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tests/testPauseResume/AndroidManifest.xml b/opengl/tests/testPauseResume/AndroidManifest.xml
index 3e8e7e7..1879bc3 100644
--- a/opengl/tests/testPauseResume/AndroidManifest.xml
+++ b/opengl/tests/testPauseResume/AndroidManifest.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, 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.
-*/
+<!-- Copyright (C) 2009 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.
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/testPauseResume/res/values/strings.xml b/opengl/tests/testPauseResume/res/values/strings.xml
index 208fe15..b4c98fe2 100644
--- a/opengl/tests/testPauseResume/res/values/strings.xml
+++ b/opengl/tests/testPauseResume/res/values/strings.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tests/testViewport/AndroidManifest.xml b/opengl/tests/testViewport/AndroidManifest.xml
index 90a9d2d..ba178bb 100644
--- a/opengl/tests/testViewport/AndroidManifest.xml
+++ b/opengl/tests/testViewport/AndroidManifest.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, 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.
-*/
+<!-- Copyright (C) 2009 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.
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/testViewport/res/values/strings.xml b/opengl/tests/testViewport/res/values/strings.xml
index f4b8bbb..c037a7c 100644
--- a/opengl/tests/testViewport/res/values/strings.xml
+++ b/opengl/tests/testViewport/res/values/strings.xml
@@ -1,21 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
 -->
 
 <!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tools/glgen/stubs/gles11/glGetString.java b/opengl/tools/glgen/stubs/gles11/glGetString.java
index d44a6dd..b02a0d1 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetString.java
+++ b/opengl/tools/glgen/stubs/gles11/glGetString.java
@@ -1,21 +1,21 @@
-/*

- * Copyright (C) 2009 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.

- */

-

-    // C function const GLubyte * glGetString ( GLenum name )

-

-    public static native String glGetString(

-        int name

-    );

+/*
+ * Copyright (C) 2009 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.
+ */
+
+    // C function const GLubyte * glGetString ( GLenum name )
+
+    public static native String glGetString(
+        int name
+    );
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar.xml b/packages/SystemUI/res/layout-xlarge/status_bar.xml
index f074e98..4ca8084 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar.xml
@@ -264,5 +264,17 @@
                 android:visibility="gone"
                 />
         </RelativeLayout>
+
+        <!-- fake space bar zone -->
+        <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/fake_space_bar"
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            android:paddingLeft="8dip"
+            android:paddingRight="8dip"
+            android:layout_toRightOf="@+id/navigationArea"
+            android:layout_toLeftOf="@+id/notificationArea"
+            android:visibility="gone"
+            systemui:keyCode="62"
+            />
     </RelativeLayout>
 </com.android.systemui.statusbar.tablet.TabletStatusBarView>
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 f561d04..90cf3dc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -40,11 +40,14 @@
 import android.os.IBinder;
 import android.os.Message;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.text.TextUtils;
 import android.util.Slog;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 import android.view.Gravity;
+import android.view.IWindowManager;
+import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
@@ -84,6 +87,9 @@
     public static final int MSG_SHOW_SHADOWS = 1031;
     public static final int MSG_RESTORE_SHADOWS = 1032;
 
+    // Fitts' Law assistance for LatinIME; TODO: replace with a more general approach
+    private static final boolean FAKE_SPACE_BAR = true;
+
     private static final int MAX_IMAGE_LEVEL = 10000;
     private static final boolean USE_2D_RECENTS = true;
 
@@ -93,6 +99,8 @@
 
     H mHandler = new H();
 
+    IWindowManager mWindowManager;
+
     // tracking all current notifications
     private NotificationData mNotns = new NotificationData();
 
@@ -134,6 +142,9 @@
 
     TabletTicker mTicker;
 
+    View mFakeSpaceBar;
+    KeyEvent mSpaceBarKeyEvent = null;
+
     // for disabling the status bar
     int mDisabled = 0;
 
@@ -252,6 +263,9 @@
     protected View makeStatusBarView() {
         final Context context = mContext;
         final Resources res = context.getResources();
+        
+        mWindowManager = IWindowManager.Stub.asInterface(
+                ServiceManager.getService(Context.WINDOW_SERVICE));
 
         mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
 
@@ -304,6 +318,9 @@
         // The bar contents buttons
         mInputMethodSwitchButton = (InputMethodButton) sb.findViewById(R.id.imeSwitchButton);
 
+        // for redirecting errant bar taps to the IME
+        mFakeSpaceBar = sb.findViewById(R.id.fake_space_bar);
+
         // "shadows" of the status bar features, for lights-out mode
         mBackShadow = sb.findViewById(R.id.back_shadow);
         mHomeShadow = sb.findViewById(R.id.home_shadow);
@@ -698,6 +715,9 @@
         mInputMethodSwitchButton.setIMEButtonVisible(token, visible);
         mBackButton.setImageResource(
                 visible ? R.drawable.ic_sysbar_back_ime : R.drawable.ic_sysbar_back);
+        if (FAKE_SPACE_BAR) {
+            mFakeSpaceBar.setVisibility(visible ? View.VISIBLE : View.GONE);
+        }
     }
 
     private boolean isImmersive() {
@@ -739,6 +759,14 @@
         }
     }
 
+    private void sendKey(KeyEvent key) {
+        try {
+            if (DEBUG) Slog.d(TAG, "injecting key event: " + key);
+            mWindowManager.injectInputEventNoWait(key);
+        } catch (RemoteException ex) {
+        }
+    }
+
     private View.OnClickListener mOnClickListener = new View.OnClickListener() {
         public void onClick(View v) {
             if (v == mNotificationTrigger) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index c3112d88..e61dd6c 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -133,6 +133,7 @@
     static final boolean DEBUG = false;
     static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
     static final boolean DEBUG_LAYOUT = false;
+    static final boolean DEBUG_FALLBACK = false;
     static final boolean SHOW_STARTING_ANIMATIONS = true;
     static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
 
@@ -315,8 +316,8 @@
     Intent mHomeIntent;
     Intent mCarDockIntent;
     Intent mDeskDockIntent;
-    boolean mSearchKeyPressed;
-    boolean mConsumeSearchKeyUp;
+    int mShortcutKeyPressed = -1;
+    boolean mConsumeShortcutKeyUp;
     boolean mShowMenuKey = false; // track FLAG_NEEDS_MENU_KEY on frontmost window
 
     // support for activating the lock screen while the screen is on
@@ -345,6 +346,8 @@
     ShortcutManager mShortcutManager;
     PowerManager.WakeLock mBroadcastWakeLock;
 
+    final KeyCharacterMap.FallbackAction mFallbackAction = new KeyCharacterMap.FallbackAction();
+
     class SettingsObserver extends ContentObserver {
         SettingsObserver(Handler handler) {
             super(handler);
@@ -1228,56 +1231,44 @@
                     + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed);
         }
 
-        // Clear a pending HOME longpress if the user releases Home
-        // TODO: This could probably be inside the next bit of logic, but that code
-        // turned out to be a bit fragile so I'm doing it here explicitly, for now.
-        if ((keyCode == KeyEvent.KEYCODE_HOME) && !down) {
-            mHandler.removeCallbacks(mHomeLongPress);
-        }
-
-        // If the HOME button is currently being held, then we do special
-        // chording with it.
-        if (mHomePressed) {
-            
-            // If we have released the home key, and didn't do anything else
-            // while it was pressed, then it is time to go home!
-            if (keyCode == KeyEvent.KEYCODE_HOME) {
-                if (!down) {
-                    mHomePressed = false;
-                    
-                    if (!canceled) {
-                        // If an incoming call is ringing, HOME is totally disabled.
-                        // (The user is already on the InCallScreen at this point,
-                        // and his ONLY options are to answer or reject the call.)
-                        boolean incomingRinging = false;
-                        try {
-                            ITelephony telephonyService = getTelephonyService();
-                            if (telephonyService != null) {
-                                incomingRinging = telephonyService.isRinging();
-                            }
-                        } catch (RemoteException ex) {
-                            Log.w(TAG, "RemoteException from getPhoneInterface()", ex);
-                        }
-        
-                        if (incomingRinging) {
-                            Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
-                        } else {
-                            launchHomeFromHotKey();
-                        }
-                    } else {
-                        Log.i(TAG, "Ignoring HOME; event canceled.");
-                    }
-                }
-            }
-            
-            return true;
-        }
-        
         // First we always handle the home key here, so applications
         // can never break it, although if keyguard is on, we do let
         // it handle it, because that gives us the correct 5 second
         // timeout.
         if (keyCode == KeyEvent.KEYCODE_HOME) {
+            // Clear a pending HOME longpress if the user releases Home
+            if (!down) {
+                mHandler.removeCallbacks(mHomeLongPress);
+            }
+
+            // If we have released the home key, and didn't do anything else
+            // while it was pressed, then it is time to go home!
+            if (mHomePressed && !down) {
+                mHomePressed = false;
+                if (!canceled) {
+                    // If an incoming call is ringing, HOME is totally disabled.
+                    // (The user is already on the InCallScreen at this point,
+                    // and his ONLY options are to answer or reject the call.)
+                    boolean incomingRinging = false;
+                    try {
+                        ITelephony telephonyService = getTelephonyService();
+                        if (telephonyService != null) {
+                            incomingRinging = telephonyService.isRinging();
+                        }
+                    } catch (RemoteException ex) {
+                        Log.w(TAG, "RemoteException from getPhoneInterface()", ex);
+                    }
+
+                    if (incomingRinging) {
+                        Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
+                    } else {
+                        launchHomeFromHotKey();
+                    }
+                } else {
+                    Log.i(TAG, "Ignoring HOME; event canceled.");
+                }
+                return true;
+            }
 
             // If a system window has focus, then it doesn't make sense
             // right now to interact with applications.
@@ -1334,21 +1325,28 @@
         } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
             if (down) {
                 if (repeatCount == 0) {
-                    mSearchKeyPressed = true;
+                    mShortcutKeyPressed = keyCode;
+                    mConsumeShortcutKeyUp = false;
                 }
-            } else {
-                mSearchKeyPressed = false;
+            } else if (keyCode == mShortcutKeyPressed) {
+                mShortcutKeyPressed = -1;
                 
-                if (mConsumeSearchKeyUp) {
+                if (mConsumeShortcutKeyUp) {
                     // Consume the up-event
-                    mConsumeSearchKeyUp = false;
+                    mConsumeShortcutKeyUp = false;
                     return true;
                 }
             }
+        } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
+            if (!down) {
+                showRecentAppsDialog();
+            }
+            return true;
         }
         
-        // Shortcuts are invoked through Search+key, so intercept those here
-        if (mSearchKeyPressed) {
+        // Shortcuts are invoked through Search+key or Meta+key, so intercept those here
+        if ((mShortcutKeyPressed != -1 && !mConsumeShortcutKeyUp)
+                || (metaState & KeyEvent.META_META_ON) != 0) {
             if (down && repeatCount == 0 && !keyguardOn) {
                 Intent shortcutIntent = mShortcutManager.getIntent(event);
                 if (shortcutIntent != null) {
@@ -1359,7 +1357,9 @@
                      * We launched an app, so the up-event of the search key
                      * should be consumed
                      */
-                    mConsumeSearchKeyUp = true;
+                    if (mShortcutKeyPressed != -1) {
+                        mConsumeShortcutKeyUp = true;
+                    }
                     return true;
                 }
             }
@@ -1370,8 +1370,8 @@
 
     /** {@inheritDoc} */
     @Override
-    public boolean dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
-        if (false) {
+    public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
+        if (DEBUG_FALLBACK) {
             Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
                     + ", flags=" + event.getFlags()
                     + ", keyCode=" + event.getKeyCode()
@@ -1380,7 +1380,42 @@
                     + ", repeatCount=" + event.getRepeatCount()
                     + ", policyFlags=" + policyFlags);
         }
-        return false;
+
+        if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
+            final KeyCharacterMap kcm = event.getKeyCharacterMap();
+            boolean fallback = kcm.getFallbackAction(event.getKeyCode(), event.getMetaState(),
+                    mFallbackAction);
+
+            if (fallback) {
+                if (DEBUG_FALLBACK) {
+                    Slog.d(TAG, "Fallback: keyCode=" + mFallbackAction.keyCode
+                            + " metaState=" + Integer.toHexString(mFallbackAction.metaState));
+                }
+
+                int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
+                KeyEvent fallbackEvent = KeyEvent.obtain(
+                        event.getDownTime(), event.getEventTime(),
+                        event.getAction(), mFallbackAction.keyCode,
+                        event.getRepeatCount(), mFallbackAction.metaState,
+                        event.getDeviceId(), event.getScanCode(),
+                        flags, event.getSource(), null);
+                int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags, true);
+                if ((actions & ACTION_PASS_TO_USER) != 0) {
+                    if (!interceptKeyBeforeDispatching(win, fallbackEvent, policyFlags)) {
+                        if (DEBUG_FALLBACK) {
+                            Slog.d(TAG, "Performing fallback.");
+                        }
+                        return fallbackEvent;
+                    }
+                }
+                fallbackEvent.recycle();
+            }
+        }
+
+        if (DEBUG_FALLBACK) {
+            Slog.d(TAG, "No fallback.");
+        }
+        return null;
     }
 
     /**
diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java
index 8634eec..4c499cd 100644
--- a/services/java/com/android/server/InputManager.java
+++ b/services/java/com/android/server/InputManager.java
@@ -402,7 +402,7 @@
         }
         
         @SuppressWarnings("unused")
-        public boolean dispatchUnhandledKey(InputChannel focus,
+        public KeyEvent dispatchUnhandledKey(InputChannel focus,
                 KeyEvent event, int policyFlags) {
             return mWindowManagerService.mInputMonitor.dispatchUnhandledKey(
                     focus, event, policyFlags);
diff --git a/services/java/com/android/server/ScreenRotationAnimation.java b/services/java/com/android/server/ScreenRotationAnimation.java
index a95a6c7..ced7c7b 100644
--- a/services/java/com/android/server/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/ScreenRotationAnimation.java
@@ -152,6 +152,27 @@
         }
     }
 
+    public static void createRotationMatrix(int rotation, int width, int height,
+            Matrix outMatrix) {
+        switch (rotation) {
+            case Surface.ROTATION_0:
+                outMatrix.reset();
+                break;
+            case Surface.ROTATION_90:
+                outMatrix.setRotate(90, 0, 0);
+                outMatrix.postTranslate(height, 0);
+                break;
+            case Surface.ROTATION_180:
+                outMatrix.setRotate(180, 0, 0);
+                outMatrix.postTranslate(width, height);
+                break;
+            case Surface.ROTATION_270:
+                outMatrix.setRotate(270, 0, 0);
+                outMatrix.postTranslate(0, width);
+                break;
+        }
+    }
+
     // Must be called while in a transaction.
     public void setRotation(int rotation) {
         mCurRotation = rotation;
@@ -160,23 +181,7 @@
         // to the snapshot to make it stay in the same original position
         // with the current screen rotation.
         int delta = deltaRotation(rotation, mSnapshotRotation);
-        switch (delta) {
-            case Surface.ROTATION_0:
-                mSnapshotInitialMatrix.reset();
-                break;
-            case Surface.ROTATION_90:
-                mSnapshotInitialMatrix.setRotate(90, 0, 0);
-                mSnapshotInitialMatrix.postTranslate(mHeight, 0);
-                break;
-            case Surface.ROTATION_180:
-                mSnapshotInitialMatrix.setRotate(180, 0, 0);
-                mSnapshotInitialMatrix.postTranslate(mWidth, mHeight);
-                break;
-            case Surface.ROTATION_270:
-                mSnapshotInitialMatrix.setRotate(270, 0, 0);
-                mSnapshotInitialMatrix.postTranslate(0, mWidth);
-                break;
-        }
+        createRotationMatrix(delta, mWidth, mHeight, mSnapshotInitialMatrix);
 
         if (DEBUG) Slog.v(TAG, "**** ROTATION: " + delta);
         setSnapshotTransform(mSnapshotInitialMatrix, 1.0f);
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 2d88b2f..7a2c0c6 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -60,6 +60,7 @@
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
 import android.graphics.Paint;
@@ -4922,6 +4923,90 @@
         SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
     }
 
+    public Bitmap screenshotApplications(int maxWidth, int maxHeight) {
+        if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
+                "screenshotApplications()")) {
+            throw new SecurityException("Requires READ_FRAME_BUFFER permission");
+        }
+
+        Bitmap rawss;
+
+        final Rect frame = new Rect();
+
+        float scale;
+        int sw, sh, dw, dh;
+        int rot;
+
+        synchronized(mWindowMap) {
+            long ident = Binder.clearCallingIdentity();
+
+            int aboveAppLayer = mPolicy.windowTypeToLayerLw(
+                    WindowManager.LayoutParams.TYPE_APPLICATION) * TYPE_LAYER_MULTIPLIER
+                    + TYPE_LAYER_OFFSET;
+            aboveAppLayer += TYPE_LAYER_MULTIPLIER;
+
+            // Figure out the part of the screen that is actually the app.
+            for (int i=0; i<mWindows.size(); i++) {
+                WindowState ws = mWindows.get(i);
+                if (ws.mSurface == null) {
+                    continue;
+                }
+                if (ws.mLayer >= aboveAppLayer) {
+                    break;
+                }
+                final Rect wf = ws.mFrame;
+                final Rect cr = ws.mContentInsets;
+                int left = wf.left + cr.left;
+                int top = wf.top + cr.top;
+                int right = wf.right - cr.right;
+                int bottom = wf.bottom - cr.bottom;
+                frame.union(left, top, right, bottom);
+            }
+            Binder.restoreCallingIdentity(ident);
+
+            if (frame.isEmpty()) {
+                return null;
+            }
+
+            // The screenshot API does not apply the current screen rotation.
+            rot = mDisplay.getRotation();
+            int fw = frame.width();
+            int fh = frame.height();
+
+            // First try reducing to fit in x dimension.
+            scale = maxWidth/(float)fw;
+            sw = maxWidth;
+            sh = (int)(fh*scale);
+            if (sh > maxHeight) {
+                // y dimension became too long; constrain by that.
+                scale = maxHeight/(float)fh;
+                sw = (int)(fw*scale);
+                sh = maxHeight;
+            }
+
+            // The screen shot will contain the entire screen.
+            dw = (int)(mDisplay.getWidth()*scale);
+            dh = (int)(mDisplay.getHeight()*scale);
+            if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
+                int tmp = dw;
+                dw = dh;
+                dh = tmp;
+                rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
+            }
+            rawss = Surface.screenshot(dw, dh);
+        }
+
+        Bitmap bm = Bitmap.createBitmap(sw, sh, rawss.getConfig());
+        Matrix matrix = new Matrix();
+        ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix);
+        matrix.postTranslate(-(int)(frame.left*scale), -(int)(frame.top*scale));
+        Canvas canvas = new Canvas(bm);
+        canvas.drawBitmap(rawss, matrix, null);
+
+        rawss.recycle();
+        return bm;
+    }
+
     public void freezeRotation() {
         if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
                 "setRotation()")) {
@@ -5844,7 +5929,7 @@
         
         /* Provides an opportunity for the window manager policy to process a key that
          * the application did not handle. */
-        public boolean dispatchUnhandledKey(
+        public KeyEvent dispatchUnhandledKey(
                 InputChannel focus, KeyEvent event, int policyFlags) {
             WindowState windowState = getWindowStateForInputChannel(focus);
             return mPolicy.dispatchUnhandledKey(windowState, event, policyFlags);
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 1a10cff..1bfdcae 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -3780,22 +3780,22 @@
         }
     }
     
-    public final void activityPaused(IBinder token, Bundle icicle) {
+    public final void activityPaused(IBinder token) {
+        final long origId = Binder.clearCallingIdentity();
+        mMainStack.activityPaused(token, false);
+        Binder.restoreCallingIdentity(origId);
+    }
+
+    public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
+            CharSequence description) {
+        if (localLOGV) Slog.v(
+            TAG, "Activity stopped: token=" + token);
+
         // Refuse possible leaked file descriptors
         if (icicle != null && icicle.hasFileDescriptors()) {
             throw new IllegalArgumentException("File descriptors passed in Bundle");
         }
 
-        final long origId = Binder.clearCallingIdentity();
-        mMainStack.activityPaused(token, icicle, false);
-        Binder.restoreCallingIdentity(origId);
-    }
-
-    public final void activityStopped(IBinder token, Bitmap thumbnail,
-            CharSequence description) {
-        if (localLOGV) Slog.v(
-            TAG, "Activity stopped: token=" + token);
-
         ActivityRecord r = null;
 
         final long origId = Binder.clearCallingIdentity();
@@ -3804,7 +3804,11 @@
             int index = mMainStack.indexOfTokenLocked(token);
             if (index >= 0) {
                 r = (ActivityRecord)mMainStack.mHistory.get(index);
-                r.thumbnail = thumbnail;
+                r.icicle = icicle;
+                r.haveState = true;
+                if (thumbnail != null) {
+                    r.thumbnail = thumbnail;
+                }
                 r.description = description;
                 r.stopped = true;
                 r.state = ActivityState.STOPPED;
@@ -4822,6 +4826,10 @@
                 throw new SecurityException(msg);
             }
 
+            final boolean canReadFb = checkCallingPermission(
+                    android.Manifest.permission.READ_FRAME_BUFFER)
+                    == PackageManager.PERMISSION_GRANTED;
+
             int pos = mMainStack.mHistory.size()-1;
             ActivityRecord next =
                 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
@@ -4866,7 +4874,13 @@
                     ci.id = curTask.taskId;
                     ci.baseActivity = r.intent.getComponent();
                     ci.topActivity = top.intent.getComponent();
-                    ci.thumbnail = top.thumbnail;
+                    if (canReadFb) {
+                        if (top.thumbnail != null) {
+                            ci.thumbnail = top.thumbnail;
+                        } else if (top.state == ActivityState.RESUMED) {
+                            ci.thumbnail = top.stack.screenshotActivities();
+                        }
+                    }
                     ci.description = topDescription;
                     ci.numActivities = numActivities;
                     ci.numRunning = numRunning;
@@ -11806,7 +11820,7 @@
         } else if (app == mHeavyWeightProcess) {
             // We don't want to kill the current heavy-weight process.
             adj = HEAVY_WEIGHT_APP_ADJ;
-            schedGroup = Process.THREAD_GROUP_DEFAULT;
+            schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
             app.adjType = "heavy";
         } else if (app == mHomeProcess) {
             // This process is hosting what we currently consider to be the
@@ -11822,13 +11836,19 @@
             app.adjType = "bg-activities";
             N = app.activities.size();
             for (int j=0; j<N; j++) {
-                if (app.activities.get(j).visible) {
+                ActivityRecord r = app.activities.get(j);
+                if (r.visible) {
                     // This app has a visible activity!
                     app.hidden = false;
                     adj = VISIBLE_APP_ADJ;
                     schedGroup = Process.THREAD_GROUP_DEFAULT;
                     app.adjType = "visible";
                     break;
+                } else if (r.state == ActivityState.PAUSING
+                        || r.state == ActivityState.PAUSED
+                        || r.state == ActivityState.STOPPING) {
+                    adj = PERCEPTIBLE_APP_ADJ;
+                    app.adjType = "stopping";
                 }
             }
         } else {
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index b4ea036..aa4cd66 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -46,6 +46,8 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
@@ -237,6 +239,9 @@
     
     long mInitialStartTime = 0;
     
+    int mThumbnailWidth = -1;
+    int mThumbnailHeight = -1;
+
     static final int PAUSE_TIMEOUT_MSG = 9;
     static final int IDLE_TIMEOUT_MSG = 10;
     static final int IDLE_NOW_MSG = 11;
@@ -256,7 +261,7 @@
                     // We don't at this point know if the activity is fullscreen,
                     // so we need to be conservative and assume it isn't.
                     Slog.w(TAG, "Activity pause timeout for " + token);
-                    activityPaused(token, null, true);
+                    activityPaused(token, true);
                 } break;
                 case IDLE_TIMEOUT_MSG: {
                     if (mService.mDidDexOpt) {
@@ -564,8 +569,6 @@
             // As part of the process of launching, ActivityThread also performs
             // a resume.
             r.state = ActivityState.RESUMED;
-            r.icicle = null;
-            r.haveState = false;
             r.stopped = false;
             mResumedActivity = r;
             r.task.touchActiveTime();
@@ -580,6 +583,9 @@
             r.stopped = true;
         }
 
+        r.icicle = null;
+        r.haveState = false;
+
         // Launch the new version setup screen if needed.  We do this -after-
         // launching the initial activity (that is, home), so that it can have
         // a chance to initialize itself while in the background, making the
@@ -644,6 +650,23 @@
         }
     }
     
+    public final Bitmap screenshotActivities() {
+        Resources res = mService.mContext.getResources();
+        int w = mThumbnailWidth;
+        int h = mThumbnailHeight;
+        if (w < 0) {
+            mThumbnailWidth = w =
+                res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
+            mThumbnailHeight = h =
+                res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
+        }
+
+        if (w > 0) {
+            return mService.mWindowManager.screenshotApplications(w, h);
+        }
+        return null;
+    }
+
     private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
         if (mPausingActivity != null) {
             RuntimeException e = new RuntimeException();
@@ -663,6 +686,7 @@
         mLastPausedActivity = prev;
         prev.state = ActivityState.PAUSING;
         prev.task.touchActiveTime();
+        prev.thumbnail = screenshotActivities();
 
         mService.updateCpuStats();
         
@@ -726,10 +750,9 @@
         }
     }
     
-    final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
+    final void activityPaused(IBinder token, boolean timeout) {
         if (DEBUG_PAUSE) Slog.v(
-            TAG, "Activity paused: token=" + token + ", icicle=" + icicle
-            + ", timeout=" + timeout);
+            TAG, "Activity paused: token=" + token + ", timeout=" + timeout);
 
         ActivityRecord r = null;
 
@@ -737,10 +760,6 @@
             int index = indexOfTokenLocked(token);
             if (index >= 0) {
                 r = (ActivityRecord)mHistory.get(index);
-                if (!timeout) {
-                    r.icicle = icicle;
-                    r.haveState = true;
-                }
                 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
                 if (mPausingActivity == r) {
                     r.state = ActivityState.PAUSED;
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 1996dd0..9156249 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -183,7 +183,7 @@
     virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
             const KeyEvent* keyEvent, uint32_t policyFlags);
     virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
-            const KeyEvent* keyEvent, uint32_t policyFlags);
+            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);
@@ -813,7 +813,7 @@
     // - Ignore untrusted events and pass them along.
     // - Filter normal events and trusted injected events through the window manager policy to
     //   handle the HOME key and the like.
-    bool result;
+    bool result = false;
     if (policyFlags & POLICY_FLAG_TRUSTED) {
         JNIEnv* env = jniEnv();
 
@@ -830,21 +830,17 @@
             result = consumed && !error;
         } else {
             LOGE("Failed to obtain key event object for interceptKeyBeforeDispatching.");
-            result = false;
         }
-
         env->DeleteLocalRef(inputChannelObj);
-    } else {
-        result = false;
     }
     return result;
 }
 
 bool NativeInputManager::dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
-        const KeyEvent* keyEvent, uint32_t policyFlags) {
+        const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
     // Policy:
     // - Ignore untrusted events and do not perform default handling.
-    bool result;
+    bool result = false;
     if (policyFlags & POLICY_FLAG_TRUSTED) {
         JNIEnv* env = jniEnv();
 
@@ -852,21 +848,26 @@
         jobject inputChannelObj = getInputChannelObjLocal(env, inputChannel);
         jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
         if (keyEventObj) {
-            jboolean handled = env->CallBooleanMethod(mCallbacksObj,
+            jobject fallbackKeyEventObj = env->CallObjectMethod(mCallbacksObj,
                     gCallbacksClassInfo.dispatchUnhandledKey,
                     inputChannelObj, keyEventObj, policyFlags);
-            bool error = checkAndClearExceptionFromCallback(env, "dispatchUnhandledKey");
+            checkAndClearExceptionFromCallback(env, "dispatchUnhandledKey");
             android_view_KeyEvent_recycle(env, keyEventObj);
             env->DeleteLocalRef(keyEventObj);
-            result = handled && !error;
+
+            if (fallbackKeyEventObj) {
+                // Note: outFallbackKeyEvent may be the same object as keyEvent.
+                if (!android_view_KeyEvent_toNative(env, fallbackKeyEventObj,
+                        outFallbackKeyEvent)) {
+                    result = true;
+                }
+                android_view_KeyEvent_recycle(env, fallbackKeyEventObj);
+                env->DeleteLocalRef(fallbackKeyEventObj);
+            }
         } else {
             LOGE("Failed to obtain key event object for dispatchUnhandledKey.");
-            result = false;
         }
-
         env->DeleteLocalRef(inputChannelObj);
-    } else {
-        result = false;
     }
     return result;
 }
@@ -1307,7 +1308,8 @@
             "(Landroid/view/InputChannel;Landroid/view/KeyEvent;I)Z");
 
     GET_METHOD_ID(gCallbacksClassInfo.dispatchUnhandledKey, gCallbacksClassInfo.clazz,
-            "dispatchUnhandledKey", "(Landroid/view/InputChannel;Landroid/view/KeyEvent;I)Z");
+            "dispatchUnhandledKey",
+            "(Landroid/view/InputChannel;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;");
 
     GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz,
             "checkInjectEventsPermission", "(II)Z");
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 145618e..fe4379d 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -58,7 +58,7 @@
         mSecure(false),
         mTextureManager(),
         mBufferManager(mTextureManager),
-        mWidth(0), mHeight(0), mFixedSize(false)
+        mWidth(0), mHeight(0), mNeedsScaling(false), mFixedSize(false)
 {
 }
 
@@ -274,13 +274,10 @@
 
 void Layer::drawForSreenShot() const
 {
-    bool currentFixedSize = mFixedSize;
-    bool currentBlending = mNeedsBlending;
-    const_cast<Layer*>(this)->mFixedSize = false;
-    const_cast<Layer*>(this)->mFixedSize = true;
+    const bool currentFiltering = mNeedsFiltering;
+    const_cast<Layer*>(this)->mNeedsFiltering = true;
     LayerBase::drawForSreenShot();
-    const_cast<Layer*>(this)->mFixedSize = currentFixedSize;
-    const_cast<Layer*>(this)->mNeedsBlending = currentBlending;
+    const_cast<Layer*>(this)->mNeedsFiltering = currentFiltering;
 }
 
 void Layer::onDraw(const Region& clip) const
@@ -318,11 +315,10 @@
 bool Layer::needsFiltering() const
 {
     if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
-        // NOTE: there is a race here, because mFixedSize is updated in a
-        // binder transaction. however, it doesn't really matter since it is
-        // evaluated each time we draw. To be perfectly correct, this flag
-        // would have to be associated with a buffer.
-        if (mFixedSize)
+        // if our buffer is not the same size than ourselves,
+        // we need filtering.
+        Mutex::Autolock _l(mLock);
+        if (mNeedsScaling)
             return true;
     }
     return LayerBase::needsFiltering();
@@ -396,6 +392,7 @@
             mReqHeight = reqHeight;
             mReqFormat = reqFormat;
             mFixedSize = fixedSize;
+            mNeedsScaling = mWidth != mReqWidth || mHeight != mReqHeight;
 
             lcblk->reallocateAllExcept(index);
         }
@@ -409,6 +406,7 @@
     err = buffer->initCheck();
 
     if (err || buffer->handle == 0) {
+        GraphicBuffer::dumpAllocationsToSystemLog();
         LOGE_IF(err || buffer->handle == 0,
                 "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d failed (%s)",
                 this, index, w, h, strerror(-err));
@@ -518,6 +516,7 @@
     Mutex::Autolock _l(mLock);
     mWidth = w;
     mHeight = h;
+    mNeedsScaling = mWidth != mReqWidth || mHeight != mReqHeight;
 }
 
 bool Layer::isFixedSize() const {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 07434cf..30021d3 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -233,6 +233,7 @@
     uint32_t mReqWidth;
     uint32_t mReqHeight;
     uint32_t mReqFormat;
+    bool mNeedsScaling;
     bool mFixedSize;
 };
 
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index df6aa51..28b02c9 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -216,14 +216,10 @@
         flags |= eVisibleRegion;
         this->contentDirty = true;
 
-        mNeedsFiltering = false;
-        if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
-            // we may use linear filtering, if the matrix scales us
-            const uint8_t type = temp.transform.getType();
-            if (!temp.transform.preserveRects() || (type >= Transform::SCALE)) {
-                mNeedsFiltering = true;
-            }
-        }
+        // we may use linear filtering, if the matrix scales us
+        const uint8_t type = temp.transform.getType();
+        mNeedsFiltering = (!temp.transform.preserveRects() ||
+                (type >= Transform::SCALE));
     }
 
     // Commit the transaction
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index bdee05b..135b3a6 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -37,6 +37,7 @@
 
 #include <hardware/hwcomposer.h>
 
+#include "DisplayHardware/DisplayHardware.h"
 #include "Transform.h"
 
 namespace android {
@@ -191,7 +192,9 @@
     /**
      * needsLinearFiltering - true if this surface needs filtering
      */
-    virtual bool needsFiltering() const { return mNeedsFiltering; }
+    virtual bool needsFiltering() const {
+        return (!(mFlags & DisplayHardware::SLOW_CONFIG)) && mNeedsFiltering;
+    }
 
     /**
      * isSecure - true if this surface is secure, that is if it prevents
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 893ae88..ad2a887 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1497,7 +1497,7 @@
             // searches through the comma-separated list for a match,
             // return true if one is found.
             for (String emergencyNum : numbers.split(",")) {
-                if (emergencyNum.equals(number)) {
+                if (number.startsWith(emergencyNum)) {
                     return true;
                 }
             }
@@ -1506,7 +1506,7 @@
         }
 
         //no ecclist system property, so use our own list.
-        return (number.equals("112") || number.equals("911"));
+        return (number.startsWith("112") || number.startsWith("911"));
     }
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 8accfd1..4911644 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -29,6 +29,7 @@
 import com.android.internal.telephony.cdma.sms.CdmaSmsSubaddress;
 import com.android.internal.telephony.cdma.sms.SmsEnvelope;
 import com.android.internal.telephony.cdma.sms.UserData;
+import com.android.internal.util.BitwiseInputStream;
 import com.android.internal.util.HexDump;
 
 import java.io.BufferedOutputStream;
@@ -68,6 +69,16 @@
     static final String LOG_TAG = "CDMA";
     static private final String LOGGABLE_TAG = "CDMA:SMS";
 
+    private final static byte TELESERVICE_IDENTIFIER                    = 0x00;
+    private final static byte SERVICE_CATEGORY                          = 0x01;
+    private final static byte ORIGINATING_ADDRESS                       = 0x02;
+    private final static byte ORIGINATING_SUB_ADDRESS                   = 0x03;
+    private final static byte DESTINATION_ADDRESS                       = 0x04;
+    private final static byte DESTINATION_SUB_ADDRESS                   = 0x05;
+    private final static byte BEARER_REPLY_OPTION                       = 0x06;
+    private final static byte CAUSE_CODES                               = 0x07;
+    private final static byte BEARER_DATA                               = 0x08;
+
     /**
      *  Status of a previously submitted SMS.
      *  This field applies to SMS Delivery Acknowledge messages. 0 indicates success;
@@ -263,6 +274,7 @@
             System.arraycopy(data, 2, pdu, 0, size);
             // the message has to be parsed before it can be displayed
             // see gsm.SmsMessage
+            msg.parsePduFromEfRecord(pdu);
             return msg;
         } catch (RuntimeException ex) {
             Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
@@ -535,6 +547,143 @@
     }
 
     /**
+     * Decodes 3GPP2 sms stored in CSIM/RUIM cards As per 3GPP2 C.S0015-0
+     */
+    private void parsePduFromEfRecord(byte[] pdu) {
+        ByteArrayInputStream bais = new ByteArrayInputStream(pdu);
+        DataInputStream dis = new DataInputStream(bais);
+        SmsEnvelope env = new SmsEnvelope();
+        CdmaSmsAddress addr = new CdmaSmsAddress();
+        CdmaSmsSubaddress subAddr = new CdmaSmsSubaddress();
+
+        try {
+            env.messageType = dis.readByte();
+
+            while (dis.available() > 0) {
+                int parameterId = dis.readByte();
+                int parameterLen = dis.readByte();
+                byte[] parameterData = new byte[parameterLen];
+
+                switch (parameterId) {
+                    case TELESERVICE_IDENTIFIER:
+                        /*
+                         * 16 bit parameter that identifies which upper layer
+                         * service access point is sending or should receive
+                         * this message
+                         */
+                        env.teleService = dis.readUnsignedShort();
+                        Log.i(LOG_TAG, "teleservice = " + env.teleService);
+                        break;
+                    case SERVICE_CATEGORY:
+                        /*
+                         * 16 bit parameter that identifies type of service as
+                         * in 3GPP2 C.S0015-0 Table 3.4.3.2-1
+                         */
+                        env.serviceCategory = dis.readUnsignedShort();
+                        break;
+                    case ORIGINATING_ADDRESS:
+                    case DESTINATION_ADDRESS:
+                        dis.read(parameterData, 0, parameterLen);
+                        BitwiseInputStream addrBis = new BitwiseInputStream(parameterData);
+                        addr.digitMode = addrBis.read(1);
+                        addr.numberMode = addrBis.read(1);
+                        int numberType = 0;
+                        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
+                            numberType = addrBis.read(3);
+                            addr.ton = numberType;
+
+                            if (addr.numberMode == CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK)
+                                addr.numberPlan = addrBis.read(4);
+                        }
+
+                        addr.numberOfDigits = addrBis.read(8);
+
+                        byte[] data = new byte[addr.numberOfDigits];
+                        byte b = 0x00;
+
+                        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF) {
+                            /* As per 3GPP2 C.S0005-0 Table 2.7.1.3.2.4-4 */
+                            for (int index = 0; index < addr.numberOfDigits; index++) {
+                                b = (byte) (0xF & addrBis.read(4));
+                                // convert the value if it is 4-bit DTMF to 8
+                                // bit
+                                data[index] = convertDtmfToAscii(b);
+                            }
+                        } else if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
+                            if (addr.numberMode == CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK) {
+                                for (int index = 0; index < addr.numberOfDigits; index++) {
+                                    b = (byte) (0xFF & addrBis.read(8));
+                                    data[index] = b;
+                                }
+
+                            } else if (addr.numberMode == CdmaSmsAddress.NUMBER_MODE_DATA_NETWORK) {
+                                if (numberType == 2)
+                                    Log.e(LOG_TAG, "TODO: Originating Addr is email id");
+                                else
+                                    Log.e(LOG_TAG,
+                                          "TODO: Originating Addr is data network address");
+                            } else {
+                                Log.e(LOG_TAG, "Originating Addr is of incorrect type");
+                            }
+                        } else {
+                            Log.e(LOG_TAG, "Incorrect Digit mode");
+                        }
+                        addr.origBytes = data;
+                        Log.i(LOG_TAG, "Originating Addr=" + addr.toString());
+                        break;
+                    case ORIGINATING_SUB_ADDRESS:
+                    case DESTINATION_SUB_ADDRESS:
+                        dis.read(parameterData, 0, parameterLen);
+                        BitwiseInputStream subAddrBis = new BitwiseInputStream(parameterData);
+                        subAddr.type = subAddrBis.read(3);
+                        subAddr.odd = subAddrBis.readByteArray(1)[0];
+                        int subAddrLen = subAddrBis.read(8);
+                        byte[] subdata = new byte[subAddrLen];
+                        for (int index = 0; index < subAddrLen; index++) {
+                            b = (byte) (0xFF & subAddrBis.read(4));
+                            // convert the value if it is 4-bit DTMF to 8 bit
+                            subdata[index] = convertDtmfToAscii(b);
+                        }
+                        subAddr.origBytes = subdata;
+                        break;
+                    case BEARER_REPLY_OPTION:
+                        dis.read(parameterData, 0, parameterLen);
+                        BitwiseInputStream replyOptBis = new BitwiseInputStream(parameterData);
+                        env.bearerReply = replyOptBis.read(6);
+                        break;
+                    case CAUSE_CODES:
+                        dis.read(parameterData, 0, parameterLen);
+                        BitwiseInputStream ccBis = new BitwiseInputStream(parameterData);
+                        env.replySeqNo = ccBis.readByteArray(6)[0];
+                        env.errorClass = ccBis.readByteArray(2)[0];
+                        if (env.errorClass != 0x00)
+                            env.causeCode = ccBis.readByteArray(8)[0];
+                        break;
+                    case BEARER_DATA:
+                        dis.read(parameterData, 0, parameterLen);
+                        env.bearerData = parameterData;
+                        break;
+                    default:
+                        throw new Exception("unsupported parameterId (" + parameterId + ")");
+                }
+            }
+            bais.close();
+            dis.close();
+        } catch (Exception ex) {
+            Log.e(LOG_TAG, "parsePduFromEfRecord: conversion from pdu to SmsMessage failed" + ex);
+        }
+
+        // link the filled objects to this SMS
+        originatingAddress = addr;
+        env.origAddress = addr;
+        env.origSubaddress = subAddr;
+        mEnvelope = env;
+        mPdu = pdu;
+
+        parseSms();
+    }
+
+    /**
      * Parses a SMS message from its BearerData stream. (mobile-terminated only)
      */
     protected void parseSms() {
diff --git a/tests/DumpRenderTree/AndroidManifest.xml b/tests/DumpRenderTree/AndroidManifest.xml
index 86b3f06..dc44b25 100644
--- a/tests/DumpRenderTree/AndroidManifest.xml
+++ b/tests/DumpRenderTree/AndroidManifest.xml
@@ -27,7 +27,7 @@
         </activity>
         <activity android:name="TestShellActivity"
           android:launchMode="singleTop"
-          android:hardwareAccelerated="false"
+          android:hardwareAccelerated="true"
           android:screenOrientation="portrait"
           android:theme="@android:style/Theme.Light"/>
         <activity android:name="ReliabilityTestActivity" android:screenOrientation="portrait"
diff --git a/tools/aapt/Package.cpp b/tools/aapt/Package.cpp
index faae89b..ab71f34 100644
--- a/tools/aapt/Package.cpp
+++ b/tools/aapt/Package.cpp
@@ -461,7 +461,7 @@
         ZipFile jar;
         err = jar.open(jars[i], ZipFile::kOpenReadOnly);
         if (err != 0) {
-            fprintf(stderr, "ERROR: unable to open '%s' as a zip file: %zd\n",
+            fprintf(stderr, "ERROR: unable to open '%s' as a zip file: %d\n",
                 jars[i], err);
             return err;
         }
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 7b74506..4614d6f 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -542,11 +542,11 @@
                         DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > baseFiles =
                                 baseGroup->getFiles();
                         for (size_t i=0; i < baseFiles.size(); i++) {
-                            printf("baseFile %d has flavor %s\n", i,
+                            printf("baseFile %zd has flavor %s\n", i,
                                     baseFiles.keyAt(i).toString().string());
                         }
                         for (size_t i=0; i < overlayFiles.size(); i++) {
-                            printf("overlayFile %d has flavor %s\n", i,
+                            printf("overlayFile %zd has flavor %s\n", i,
                                     overlayFiles.keyAt(i).toString().string());
                         }
                     }
@@ -560,7 +560,7 @@
                                 keyAt(overlayGroupIndex));
                         if(baseFileIndex < UNKNOWN_ERROR) {
                             if (bundle->getVerbose()) {
-                                printf("found a match (%d) for overlay file %s, for flavor %s\n",
+                                printf("found a match (%zd) for overlay file %s, for flavor %s\n",
                                         baseFileIndex,
                                         overlayGroup->getLeaf().string(),
                                         overlayFiles.keyAt(overlayGroupIndex).toString().string());
diff --git a/tools/aapt/StringPool.cpp b/tools/aapt/StringPool.cpp
index e28bdff..d067d59 100644
--- a/tools/aapt/StringPool.cpp
+++ b/tools/aapt/StringPool.cpp
@@ -30,7 +30,7 @@
             str = String8(pool->stringAt(s, &len)).string();
         }
 
-        printf("String #%d: %s\n", s, str);
+        printf("String #%zd: %s\n", s, str);
     }
 }