Merge "Fix 5602985: Show "Emergency calls only" when device has no SIM." into ics-mr1
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 7c03a2f..140222e 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -121,6 +121,10 @@
             runProfile();
         } else if (op.equals("dumpheap")) {
             runDumpHeap();
+        } else if (op.equals("set-debug-app")) {
+            runSetDebugApp();
+        } else if (op.equals("clear-debug-app")) {
+            runClearDebugApp();
         } else if (op.equals("monitor")) {
             runMonitor();
         } else if (op.equals("screen-compat")) {
@@ -666,6 +670,31 @@
         }
     }
 
+    private void runSetDebugApp() throws Exception {
+        boolean wait = false;
+        boolean persistent = false;
+
+        String opt;
+        while ((opt=nextOption()) != null) {
+            if (opt.equals("-w")) {
+                wait = true;
+            } else if (opt.equals("--persistent")) {
+                persistent = true;
+            } else {
+                System.err.println("Error: Unknown option: " + opt);
+                showUsage();
+                return;
+            }
+        }
+
+        String pkg = nextArgRequired();
+        mAm.setDebugApp(pkg, wait, persistent);
+    }
+
+    private void runClearDebugApp() throws Exception {
+        mAm.setDebugApp(null, false, true);
+    }
+
     class MyActivityController extends IActivityController.Stub {
         final String mGdbPort;
 
@@ -1199,6 +1228,8 @@
                 "       am profile [looper] start <PROCESS> <FILE>\n" +
                 "       am profile [looper] stop [<PROCESS>]\n" +
                 "       am dumpheap [flags] <PROCESS> <FILE>\n" +
+                "       am set-debug-app [-w] [--persistent] <PACKAGE>\n" +
+                "       am clear-debug-app\n" +
                 "       am monitor [--gdb <port>]\n" +
                 "       am screen-compat [on|off] <PACKAGE>\n" +
                 "       am display-size [reset|MxN]\n" +
@@ -1240,6 +1271,12 @@
                 "am dumpheap: dump the heap of a process.  Options are:\n" +
                 "    -n: dump native heap instead of managed heap\n" +
                 "\n" +
+                "am set-debug-app: set application <PACKAGE> to debug.  Options are:\n" +
+                "    -w: wait for debugger when application starts\n" +
+                "    --persistent: retain this value\n" +
+                "\n" +
+                "am clear-debug-app: clear the previously set-debug-app.\n" +
+                "\n" +
                 "am monitor: start monitoring for crashes or ANRs.\n" +
                 "    --gdb: start gdbserv on the given port at crash/ANR\n" +
                 "\n" +
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index f9896f7..303f81b 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2734,8 +2734,9 @@
         CharSequence description;
     }
 
-    private class ProviderRefCount {
+    private static final class ProviderRefCount {
         public int count;
+
         ProviderRefCount(int pCount) {
             count = pCount;
         }
@@ -3988,16 +3989,14 @@
             buf.append(": ");
             buf.append(cpi.name);
             Log.i(TAG, buf.toString());
-            IContentProvider cp = installProvider(context, null, cpi, false);
+            IContentProvider cp = installProvider(context, null, cpi,
+                    false /*noisy*/, true /*noReleaseNeeded*/);
             if (cp != null) {
                 IActivityManager.ContentProviderHolder cph =
-                    new IActivityManager.ContentProviderHolder(cpi);
+                        new IActivityManager.ContentProviderHolder(cpi);
                 cph.provider = cp;
+                cph.noReleaseNeeded = true;
                 results.add(cph);
-                // Don't ever unload this provider from the process.
-                synchronized(mProviderMap) {
-                    mProviderRefCountMap.put(cp.asBinder(), new ProviderRefCount(10000));
-                }
             }
         }
 
@@ -4008,26 +4007,22 @@
         }
     }
 
-    private IContentProvider getExistingProvider(Context context, String name) {
-        synchronized(mProviderMap) {
-            final ProviderClientRecord pr = mProviderMap.get(name);
-            if (pr != null) {
-                return pr.mProvider;
-            }
-            return null;
-        }
-    }
-
-    private IContentProvider getProvider(Context context, String name) {
-        IContentProvider existing = getExistingProvider(context, name);
-        if (existing != null) {
-            return existing;
+    public final IContentProvider acquireProvider(Context c, String name) {
+        IContentProvider provider = acquireExistingProvider(c, name);
+        if (provider != null) {
+            return provider;
         }
 
+        // There is a possible race here.  Another thread may try to acquire
+        // the same provider at the same time.  When this happens, we want to ensure
+        // that the first one wins.
+        // Note that we cannot hold the lock while acquiring and installing the
+        // provider since it might take a long time to run and it could also potentially
+        // be re-entrant in the case where the provider is in the same process.
         IActivityManager.ContentProviderHolder holder = null;
         try {
             holder = ActivityManagerNative.getDefault().getContentProvider(
-                getApplicationThread(), name);
+                    getApplicationThread(), name);
         } catch (RemoteException ex) {
         }
         if (holder == null) {
@@ -4035,136 +4030,137 @@
             return null;
         }
 
-        IContentProvider prov = installProvider(context, holder.provider,
-                holder.info, true);
-        //Slog.i(TAG, "noReleaseNeeded=" + holder.noReleaseNeeded);
-        if (holder.noReleaseNeeded || holder.provider == null) {
-            // We are not going to release the provider if it is an external
-            // provider that doesn't care about being released, or if it is
-            // a local provider running in this process.
-            //Slog.i(TAG, "*** NO RELEASE NEEDED");
-            synchronized(mProviderMap) {
-                mProviderRefCountMap.put(prov.asBinder(), new ProviderRefCount(10000));
+        // Install provider will increment the reference count for us, and break
+        // any ties in the race.
+        provider = installProvider(c, holder.provider, holder.info,
+                true /*noisy*/, holder.noReleaseNeeded);
+        if (holder.provider != null && provider != holder.provider) {
+            if (localLOGV) {
+                Slog.v(TAG, "acquireProvider: lost the race, releasing extraneous "
+                        + "reference to the content provider");
+            }
+            try {
+                ActivityManagerNative.getDefault().removeContentProvider(
+                        getApplicationThread(), name);
+            } catch (RemoteException ex) {
             }
         }
-        return prov;
-    }
-
-    public final IContentProvider acquireProvider(Context c, String name) {
-        IContentProvider provider = getProvider(c, name);
-        if(provider == null)
-            return null;
-        IBinder jBinder = provider.asBinder();
-        synchronized(mProviderMap) {
-            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
-            if(prc == null) {
-                mProviderRefCountMap.put(jBinder, new ProviderRefCount(1));
-            } else {
-                prc.count++;
-            } //end else
-        } //end synchronized
         return provider;
     }
 
     public final IContentProvider acquireExistingProvider(Context c, String name) {
-        IContentProvider provider = getExistingProvider(c, name);
-        if(provider == null)
-            return null;
-        IBinder jBinder = provider.asBinder();
-        synchronized(mProviderMap) {
+        synchronized (mProviderMap) {
+            ProviderClientRecord pr = mProviderMap.get(name);
+            if (pr == null) {
+                return null;
+            }
+
+            IContentProvider provider = pr.mProvider;
+            IBinder jBinder = provider.asBinder();
+
+            // Only increment the ref count if we have one.  If we don't then the
+            // provider is not reference counted and never needs to be released.
             ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
-            if(prc == null) {
-                mProviderRefCountMap.put(jBinder, new ProviderRefCount(1));
-            } else {
-                prc.count++;
-            } //end else
-        } //end synchronized
-        return provider;
+            if (prc != null) {
+                prc.count += 1;
+                if (prc.count == 1) {
+                    if (localLOGV) {
+                        Slog.v(TAG, "acquireExistingProvider: "
+                                + "snatched provider from the jaws of death");
+                    }
+                    // Because the provider previously had a reference count of zero,
+                    // it was scheduled to be removed.  Cancel that.
+                    mH.removeMessages(H.REMOVE_PROVIDER, provider);
+                }
+            }
+            return provider;
+        }
     }
 
     public final boolean releaseProvider(IContentProvider provider) {
         if(provider == null) {
             return false;
         }
+
         IBinder jBinder = provider.asBinder();
-        synchronized(mProviderMap) {
+        synchronized (mProviderMap) {
             ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
-            if(prc == null) {
-                if(localLOGV) Slog.v(TAG, "releaseProvider::Weird shouldn't be here");
+            if (prc == null) {
+                // The provider has no ref count, no release is needed.
                 return false;
-            } else {
-                prc.count--;
-                if(prc.count == 0) {
-                    // Schedule the actual remove asynchronously, since we
-                    // don't know the context this will be called in.
-                    // TODO: it would be nice to post a delayed message, so
-                    // if we come back and need the same provider quickly
-                    // we will still have it available.
-                    Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, provider);
-                    mH.sendMessage(msg);
-                } //end if
-            } //end else
-        } //end synchronized
-        return true;
+            }
+
+            if (prc.count == 0) {
+                if (localLOGV) Slog.v(TAG, "releaseProvider: ref count already 0, how?");
+                return false;
+            }
+
+            prc.count -= 1;
+            if (prc.count == 0) {
+                // Schedule the actual remove asynchronously, since we don't know the context
+                // this will be called in.
+                // TODO: it would be nice to post a delayed message, so
+                // if we come back and need the same provider quickly
+                // we will still have it available.
+                Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, provider);
+                mH.sendMessage(msg);
+            }
+            return true;
+        }
     }
 
     final void completeRemoveProvider(IContentProvider provider) {
         IBinder jBinder = provider.asBinder();
-        String name = null;
+        String remoteProviderName = null;
         synchronized(mProviderMap) {
             ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
-            if(prc != null && prc.count == 0) {
-                mProviderRefCountMap.remove(jBinder);
-                //invoke removeProvider to dereference provider
-                name = removeProviderLocked(provider);
+            if (prc == null) {
+                // Either no release is needed (so we shouldn't be here) or the
+                // provider was already released.
+                if (localLOGV) Slog.v(TAG, "completeRemoveProvider: release not needed");
+                return;
+            }
+
+            if (prc.count != 0) {
+                // There was a race!  Some other client managed to acquire
+                // the provider before the removal was completed.
+                // Abort the removal.  We will do it later.
+                if (localLOGV) Slog.v(TAG, "completeRemoveProvider: lost the race, "
+                        + "provider still in use");
+                return;
+            }
+
+            mProviderRefCountMap.remove(jBinder);
+
+            Iterator<ProviderClientRecord> iter = mProviderMap.values().iterator();
+            while (iter.hasNext()) {
+                ProviderClientRecord pr = iter.next();
+                IBinder myBinder = pr.mProvider.asBinder();
+                if (myBinder == jBinder) {
+                    iter.remove();
+                    if (pr.mLocalProvider == null) {
+                        myBinder.unlinkToDeath(pr, 0);
+                        if (remoteProviderName == null) {
+                            remoteProviderName = pr.mName;
+                        }
+                    }
+                }
             }
         }
-        
-        if (name != null) {
+
+        if (remoteProviderName != null) {
             try {
-                if(localLOGV) Slog.v(TAG, "removeProvider::Invoking " +
-                        "ActivityManagerNative.removeContentProvider(" + name);
+                if (localLOGV) {
+                    Slog.v(TAG, "removeProvider: Invoking ActivityManagerNative."
+                            + "removeContentProvider(" + remoteProviderName + ")");
+                }
                 ActivityManagerNative.getDefault().removeContentProvider(
-                        getApplicationThread(), name);
+                        getApplicationThread(), remoteProviderName);
             } catch (RemoteException e) {
                 //do nothing content provider object is dead any way
-            } //end catch
+            }
         }
     }
-    
-    public final String removeProviderLocked(IContentProvider provider) {
-        if (provider == null) {
-            return null;
-        }
-        IBinder providerBinder = provider.asBinder();
-
-        String name = null;
-        
-        // remove the provider from mProviderMap
-        Iterator<ProviderClientRecord> iter = mProviderMap.values().iterator();
-        while (iter.hasNext()) {
-            ProviderClientRecord pr = iter.next();
-            IBinder myBinder = pr.mProvider.asBinder();
-            if (myBinder == providerBinder) {
-                //find if its published by this process itself
-                if(pr.mLocalProvider != null) {
-                    if(localLOGV) Slog.i(TAG, "removeProvider::found local provider returning");
-                    return name;
-                }
-                if(localLOGV) Slog.v(TAG, "removeProvider::Not local provider Unlinking " +
-                        "death recipient");
-                //content provider is in another process
-                myBinder.unlinkToDeath(pr, 0);
-                iter.remove();
-                //invoke remove only once for the very first name seen
-                if(name == null) {
-                    name = pr.mName;
-                }
-            } //end if myBinder
-        }  //end while iter
-        
-        return name;
-    }
 
     final void removeDeadProvider(String name, IContentProvider provider) {
         synchronized(mProviderMap) {
@@ -4179,8 +4175,23 @@
         }
     }
 
+    /**
+     * Installs the provider.
+     *
+     * Providers that are local to the process or that come from the system server
+     * may be installed permanently which is indicated by setting noReleaseNeeded to true.
+     * Other remote providers are reference counted.  The initial reference count
+     * for all reference counted providers is one.  Providers that are not reference
+     * counted do not have a reference count (at all).
+     *
+     * This method detects when a provider has already been installed.  When this happens,
+     * it increments the reference count of the existing provider (if appropriate)
+     * and returns the existing provider.  This can happen due to concurrent
+     * attempts to acquire the same provider.
+     */
     private IContentProvider installProvider(Context context,
-            IContentProvider provider, ProviderInfo info, boolean noisy) {
+            IContentProvider provider, ProviderInfo info,
+            boolean noisy, boolean noReleaseNeeded) {
         ContentProvider localProvider = null;
         if (provider == null) {
             if (noisy) {
@@ -4238,24 +4249,69 @@
         }
 
         synchronized (mProviderMap) {
-            // Cache the pointer for the remote provider.
+            // There is a possibility that this thread raced with another thread to
+            // add the provider.  If we find another thread got there first then we
+            // just get out of the way and return the original provider.
+            IBinder jBinder = provider.asBinder();
             String names[] = PATTERN_SEMICOLON.split(info.authority);
-            for (int i=0; i<names.length; i++) {
-                ProviderClientRecord pr = new ProviderClientRecord(names[i], provider,
-                        localProvider);
-                try {
-                    provider.asBinder().linkToDeath(pr, 0);
+            for (int i = 0; i < names.length; i++) {
+                ProviderClientRecord pr = mProviderMap.get(names[i]);
+                if (pr != null) {
+                    if (localLOGV) {
+                        Slog.v(TAG, "installProvider: lost the race, "
+                                + "using existing named provider");
+                    }
+                    provider = pr.mProvider;
+                } else {
+                    pr = new ProviderClientRecord(names[i], provider, localProvider);
+                    if (localProvider == null) {
+                        try {
+                            jBinder.linkToDeath(pr, 0);
+                        } catch (RemoteException e) {
+                            // Provider already dead.  Bail out of here without making
+                            // any changes to the provider map or other data structures.
+                            return null;
+                        }
+                    }
                     mProviderMap.put(names[i], pr);
-                } catch (RemoteException e) {
-                    return null;
                 }
             }
+
             if (localProvider != null) {
-                mLocalProviders.put(provider.asBinder(),
-                        new ProviderClientRecord(null, provider, localProvider));
+                ProviderClientRecord pr = mLocalProviders.get(jBinder);
+                if (pr != null) {
+                    if (localLOGV) {
+                        Slog.v(TAG, "installProvider: lost the race, "
+                                + "using existing local provider");
+                    }
+                    provider = pr.mProvider;
+                } else {
+                    pr = new ProviderClientRecord(null, provider, localProvider);
+                    mLocalProviders.put(jBinder, pr);
+                }
+            }
+
+            if (!noReleaseNeeded) {
+                ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
+                if (prc != null) {
+                    if (localLOGV) {
+                        Slog.v(TAG, "installProvider: lost the race, incrementing ref count");
+                    }
+                    prc.count += 1;
+                    if (prc.count == 1) {
+                        if (localLOGV) {
+                            Slog.v(TAG, "installProvider: "
+                                    + "snatched provider from the jaws of death");
+                        }
+                        // Because the provider previously had a reference count of zero,
+                        // it was scheduled to be removed.  Cancel that.
+                        mH.removeMessages(H.REMOVE_PROVIDER, provider);
+                    }
+                } else {
+                    mProviderRefCountMap.put(jBinder, new ProviderRefCount(1));
+                }
             }
         }
-
         return provider;
     }
 
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 91398bc..b1c1f30 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -635,6 +635,9 @@
                     //Log.v(TAG, "...app returning after sending offsets!");
                 } catch (RemoteException e) {
                     // Ignore.
+                } catch (IllegalArgumentException e) {
+                    // Since this is being posted, it's possible that this windowToken is no longer
+                    // valid, for example, if setWallpaperOffsets is called just before rotation.
                 }
             }
         });
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 3becec0..c2a757f 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -1111,9 +1111,21 @@
      * Parameters#getMaxNumDetectedFaces()} returns a number larger than 0.
      * If the face detection has started, apps should not call this again.
      *
-     * When the face detection is running, {@link Parameters#setWhiteBalance(String)},
+     * <p>When the face detection is running, {@link Parameters#setWhiteBalance(String)},
      * {@link Parameters#setFocusAreas(List)}, and {@link Parameters#setMeteringAreas(List)}
-     * have no effect.
+     * have no effect. The camera uses the detected faces to do auto-white balance,
+     * auto exposure, and autofocus.
+     *
+     * <p>If the apps call {@link #autoFocus(AutoFocusCallback)}, the camera
+     * will stop sending face callbacks. The last face callback indicates the
+     * areas used to do autofocus. After focus completes, face detection will
+     * resume sending face callbacks. If the apps call {@link
+     * #cancelAutoFocus()}, the face callbacks will also resume.</p>
+     *
+     * <p>After calling {@link #takePicture(Camera.ShutterCallback, Camera.PictureCallback,
+     * Camera.PictureCallback)} or {@link #stopPreview()}, and then resuming
+     * preview with {@link #startPreview()}, the apps should call this method
+     * again to resume face detection.</p>
      *
      * @throws IllegalArgumentException if the face detection is unsupported.
      * @throws RuntimeException if the method fails or the face detection is
@@ -1163,14 +1175,31 @@
          * camera field of view, and (1000, 1000) represents the bottom-right of
          * the field of view. For example, suppose the size of the viewfinder UI
          * is 800x480. The rect passed from the driver is (-1000, -1000, 0, 0).
-         * The corresponding viewfinder rect should be (0, 0, 400, 240). The
-         * width and height of the rect will not be 0 or negative. The
-         * coordinates can be smaller than -1000 or bigger than 1000. But at
-         * least one vertex will be within (-1000, -1000) and (1000, 1000).
+         * The corresponding viewfinder rect should be (0, 0, 400, 240). It is
+         * guaranteed left < right and top < bottom. The coordinates can be
+         * smaller than -1000 or bigger than 1000. But at least one vertex will
+         * be within (-1000, -1000) and (1000, 1000).
          *
          * <p>The direction is relative to the sensor orientation, that is, what
          * the sensor sees. The direction is not affected by the rotation or
-         * mirroring of {@link #setDisplayOrientation(int)}.</p>
+         * mirroring of {@link #setDisplayOrientation(int)}. The face bounding
+         * rectangle does not provide any information about face orientation.</p>
+         *
+         * <p>Here is the matrix to convert driver coordinates to View coordinates
+         * in pixels.</p>
+         * <pre>
+         * Matrix matrix = new Matrix();
+         * CameraInfo info = CameraHolder.instance().getCameraInfo()[cameraId];
+         * // Need mirror for front camera.
+         * boolean mirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT);
+         * matrix.setScale(mirror ? -1 : 1, 1);
+         * // This is the value for android.hardware.Camera.setDisplayOrientation.
+         * matrix.postRotate(displayOrientation);
+         * // Camera driver coordinates range from (-1000, -1000) to (1000, 1000).
+         * // UI coordinates range from (0, 0) to (width, height).
+         * matrix.postScale(view.getWidth() / 2000f, view.getHeight() / 2000f);
+         * matrix.postTranslate(view.getWidth() / 2f, view.getHeight() / 2f);
+         * </pre>
          *
          * @see #startFaceDetection()
          */
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 821b6df..83acef8 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -187,6 +187,16 @@
     public static final String DEFERRED_SNIPPETING_QUERY = "deferred_snippeting_query";
 
     /**
+     * A boolean parameter for {@link CommonDataKinds.Phone#CONTENT_URI},
+     * {@link CommonDataKinds.Email#CONTENT_URI}, and
+     * {@link CommonDataKinds.StructuredPostal#CONTENT_URI}.
+     * This enables a content provider to remove duplicate entries in results.
+     *
+     * @hide
+     */
+    public static final String REMOVE_DUPLICATE_ENTRIES = "remove_duplicate_entries";
+
+    /**
      * <p>
      * API for obtaining a pre-authorized version of a URI that normally requires special
      * permission (beyond READ_CONTACTS) to read.  The caller obtaining the pre-authorized URI
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 7249497..ec2f55b 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -3097,10 +3097,7 @@
         // Special-case layer scrolling so that we do not trigger normal scroll
         // updating.
         if (mTouchMode == TOUCH_DRAG_LAYER_MODE) {
-            nativeScrollLayer(mScrollingLayer, scrollX, scrollY);
-            mScrollingLayerRect.left = scrollX;
-            mScrollingLayerRect.top = scrollY;
-            invalidate();
+            scrollLayerTo(scrollX, scrollY);
             return;
         }
         mInOverScrollMode = false;
@@ -3603,9 +3600,7 @@
                     mScrollY = y;
                 } else {
                     // Update the layer position instead of WebView.
-                    nativeScrollLayer(mScrollingLayer, x, y);
-                    mScrollingLayerRect.left = x;
-                    mScrollingLayerRect.top = y;
+                    scrollLayerTo(x, y);
                 }
                 abortAnimation();
                 nativeSetIsScrolling(false);
@@ -3624,6 +3619,17 @@
         }
     }
 
+    private void scrollLayerTo(int x, int y) {
+        if (x == mScrollingLayerRect.left && y == mScrollingLayerRect.top) {
+            return;
+        }
+        nativeScrollLayer(mScrollingLayer, x, y);
+        mScrollingLayerRect.left = x;
+        mScrollingLayerRect.top = y;
+        onScrollChanged(mScrollX, mScrollY, mScrollX, mScrollY);
+        invalidate();
+    }
+
     private static int computeDuration(int dx, int dy) {
         int distance = Math.max(Math.abs(dx), Math.abs(dy));
         int duration = distance * 1000 / STD_SPEED;
@@ -8309,12 +8315,8 @@
                     if (mScrollingLayer == 0) {
                         pinScrollBy(mAutoScrollX, mAutoScrollY, true, 0);
                     } else {
-                        mScrollingLayerRect.left += mAutoScrollX;
-                        mScrollingLayerRect.top += mAutoScrollY;
-                        nativeScrollLayer(mScrollingLayer,
-                                mScrollingLayerRect.left,
-                                mScrollingLayerRect.top);
-                        invalidate();
+                        scrollLayerTo(mScrollingLayerRect.left + mAutoScrollX,
+                                mScrollingLayerRect.top + mAutoScrollY);
                     }
                     sendEmptyMessageDelayed(
                             SCROLL_SELECT_TEXT, SELECT_SCROLL_INTERVAL);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index b106cc5..f422f60 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -131,7 +131,6 @@
 import android.view.inputmethod.ExtractedTextRequest;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.InputMethodSubtype;
 import android.view.textservice.SpellCheckerSubtype;
 import android.view.textservice.TextServicesManager;
 import android.widget.AdapterView.OnItemClickListener;
@@ -5342,7 +5341,6 @@
 
         switch (keyCode) {
             case KeyEvent.KEYCODE_ENTER:
-                mEnterKeyIsDown = true;
                 if (event.hasNoModifiers()) {
                     // When mInputContentType is set, we know that we are
                     // running in a "modern" cupcake environment, so don't need
@@ -5374,7 +5372,6 @@
                 break;
                 
             case KeyEvent.KEYCODE_DPAD_CENTER:
-                mDPadCenterIsDown = true;
                 if (event.hasNoModifiers()) {
                     if (shouldAdvanceFocusOnEnter()) {
                         return 0;
@@ -5488,7 +5485,6 @@
 
         switch (keyCode) {
             case KeyEvent.KEYCODE_DPAD_CENTER:
-                mDPadCenterIsDown = false;
                 if (event.hasNoModifiers()) {
                     /*
                      * If there is a click listener, just call through to
@@ -5513,7 +5509,6 @@
                 return super.onKeyUp(keyCode, event);
 
             case KeyEvent.KEYCODE_ENTER:
-                mEnterKeyIsDown = false;
                 if (event.hasNoModifiers()) {
                     if (mInputContentType != null
                             && mInputContentType.onEditorActionListener != null
@@ -8972,17 +8967,9 @@
     }
 
     private long getLastTouchOffsets() {
-        int minOffset, maxOffset;
-
-        if (mContextMenuTriggeredByKey) {
-            minOffset = getSelectionStart();
-            maxOffset = getSelectionEnd();
-        } else {
-            SelectionModifierCursorController selectionController = getSelectionController();
-            minOffset = selectionController.getMinTouchOffset();
-            maxOffset = selectionController.getMaxTouchOffset();
-        }
-
+        SelectionModifierCursorController selectionController = getSelectionController();
+        final int minOffset = selectionController.getMinTouchOffset();
+        final int maxOffset = selectionController.getMaxTouchOffset();
         return packRangeInLong(minOffset, maxOffset);
     }
 
@@ -9075,12 +9062,6 @@
     private static final int ID_COPY = android.R.id.copy;
     private static final int ID_PASTE = android.R.id.paste;
 
-    private class MenuHandler implements MenuItem.OnMenuItemClickListener {
-        public boolean onMenuItemClick(MenuItem item) {
-            return onTextContextMenuItem(item.getItemId());
-        }
-    }
-
     /**
      * Called when a context menu option for the text view is selected.  Currently
      * this will be one of {@link android.R.id#selectAll}, {@link android.R.id#cut},
@@ -11480,12 +11461,6 @@
     private boolean                 mSelectionControllerEnabled;
     private boolean                 mInBatchEditControllers;
 
-    // These are needed to desambiguate a long click. If the long click comes from ones of these, we
-    // select from the current cursor position. Otherwise, select from long pressed position.
-    private boolean                 mDPadCenterIsDown = false;
-    private boolean                 mEnterKeyIsDown = false;
-    private boolean                 mContextMenuTriggeredByKey = false;
-
     private boolean                 mSelectAllOnFocus = false;
 
     private int                     mGravity = Gravity.TOP | Gravity.START;
diff --git a/core/java/com/android/internal/widget/DigitalClock.java b/core/java/com/android/internal/widget/DigitalClock.java
index 6f24eba..daefc9a 100644
--- a/core/java/com/android/internal/widget/DigitalClock.java
+++ b/core/java/com/android/internal/widget/DigitalClock.java
@@ -106,7 +106,8 @@
         private String mAmString, mPmString;
 
         AmPm(View parent, Typeface tf) {
-            mAmPmTextView = (TextView) parent.findViewById(R.id.am_pm);
+            // No longer used, uncomment if we decide to use AM/PM indicator again
+            // mAmPmTextView = (TextView) parent.findViewById(R.id.am_pm);
             if (mAmPmTextView != null && tf != null) {
                 mAmPmTextView.setTypeface(tf);
             }
diff --git a/core/res/res/drawable-hdpi/transportcontrol_bg.9.png b/core/res/res/drawable-hdpi/transportcontrol_bg.9.png
new file mode 100644
index 0000000..ebd6f8a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/transportcontrol_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/transportcontrol_bg.9.png b/core/res/res/drawable-mdpi/transportcontrol_bg.9.png
new file mode 100644
index 0000000..d5a339f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/transportcontrol_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/transportcontrol_bg.9.png b/core/res/res/drawable-xhdpi/transportcontrol_bg.9.png
new file mode 100644
index 0000000..b690a2a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/transportcontrol_bg.9.png
Binary files differ
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml b/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
index b58f081..f972843 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
@@ -17,45 +17,69 @@
 */
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical">
+    android:layout_height="match_parent">
 
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="0dip"
-        android:layout_weight="1"
-    />
-
+    <!-- left side: status and music -->
     <RelativeLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content">
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:layout_width="0dip"
+        android:gravity="center">
 
-        <!-- left side: status -->
-        <include layout="@layout/keyguard_screen_status_land"
-            android:layout_width="wrap_content"
+        <RelativeLayout android:id="@+id/transport_bg_protect"
+            android:layout_width="512dip"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="102dip"
-            android:paddingTop="50dip"
-            android:layout_centerVertical="true"
-            android:layout_alignParentLeft="true"/>
+            android:layout_marginBottom="24dip">
 
-        <!-- right side: password -->
+            <!-- Music transport control underneath -->
+            <include android:id="@+id/transport"
+                layout="@layout/keyguard_transport_control"
+                android:layout_row="0"
+                android:layout_column="0"
+                android:layout_rowSpan="3"
+                android:layout_columnSpan="1"
+                android:layout_gravity="fill"
+                android:layout_width="match_parent"
+                android:layout_height="512dip"
+                />
+
+            <!-- Status -->
+            <include layout="@layout/keyguard_screen_status_land"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="50dip"
+                android:layout_marginTop="50dip"
+                android:layout_marginBottom="50dip"
+                android:layout_marginRight="64dip"
+                android:layout_alignParentTop="true"
+                android:layout_alignParentLeft="true"/>
+
+        </RelativeLayout>
+
+    </RelativeLayout>
+
+    <!-- right side: password -->
+    <LinearLayout
+        android:layout_width="0dip"
+        android:layout_weight="1"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:gravity="center">
+
         <LinearLayout
-            android:layout_width="330dip"
-            android:layout_height="wrap_content"
             android:orientation="vertical"
-            android:layout_alignParentRight="true"
-            android:layout_centerVertical="true"
-            android:layout_marginRight="155dip">
-
+            android:layout_width="330dip"
+            android:layout_height="wrap_content">
 
             <LinearLayout
                 android:orientation="horizontal"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_gravity="center_vertical"
+                android:layout_gravity="center"
                 android:background="@drawable/lockscreen_password_field_dark">
 
                 <EditText android:id="@+id/passwordEntry"
@@ -88,6 +112,7 @@
                     android:visibility="gone"
                     />
 
+                <!-- The IME switcher button is only shown in ASCII password mode (not PIN) -->
                 <ImageView android:id="@+id/switch_ime_button"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
@@ -103,33 +128,29 @@
 
             <!-- Numeric keyboard -->
             <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
-                android:layout_width="330dip"
+                android:layout_width="match_parent"
                 android:layout_height="330dip"
                 android:background="#40000000"
                 android:layout_marginTop="5dip"
                 android:keyBackground="@drawable/btn_keyboard_key_ics"
                 android:visibility="gone"
             />
+
+            <!-- Emergency call button. Generally not used on tablet devices. -->
+            <Button
+                android:id="@+id/emergencyCallButton"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_horizontal"
+                android:drawableLeft="@drawable/ic_emergency"
+                android:drawablePadding="8dip"
+                android:text="@string/lockscreen_emergency_call"
+                android:visibility="gone"
+                style="@style/Widget.Button.Transparent"
+            />
+
         </LinearLayout>
 
-    </RelativeLayout>
-
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="0dip"
-        android:layout_weight="1"
-    />
-
-    <!-- emergency call button NOT CURRENTLY USED -->
-    <Button
-        android:id="@+id/emergencyCallButton"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:drawableLeft="@drawable/ic_emergency"
-        android:drawablePadding="8dip"
-        android:text="@string/lockscreen_emergency_call"
-        android:visibility="gone"
-        style="@style/Widget.Button.Transparent"
-    />
+    </LinearLayout>
 
 </LinearLayout>
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml b/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
index cadb5f8..8b65b22 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
@@ -16,23 +16,48 @@
 ** limitations under the License.
 */
 -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical">
+    android:layout_height="match_parent">
 
-    <!-- top: status -->
+    <!-- top: status and emergency/forgot pattern buttons -->
     <RelativeLayout
-            android:layout_width="match_parent"
-            android:layout_height="0dip"
-            android:layout_weight="1">
-        <include layout="@layout/keyguard_screen_status_port"
-            android:layout_width="wrap_content"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:layout_width="match_parent"
+        android:gravity="center">
+
+        <RelativeLayout android:id="@+id/transport_bg_protect"
+            android:layout_width="512dip"
             android:layout_height="wrap_content"
-            android:layout_marginTop="134dip"
-            android:layout_marginLeft="266dip"
-            android:layout_alignParentTop="true"
-            android:layout_alignParentLeft="true"/>
+            android:gravity="center">
+
+            <!-- Music transport control -->
+            <include android:id="@+id/transport"
+                layout="@layout/keyguard_transport_control"
+                android:layout_row="0"
+                android:layout_column="0"
+                android:layout_rowSpan="3"
+                android:layout_columnSpan="1"
+                android:layout_gravity="fill"
+                android:layout_width="match_parent"
+                android:layout_height="512dip"
+                />
+
+            <include layout="@layout/keyguard_screen_status_port"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="50dip"
+                android:layout_marginTop="50dip"
+                android:layout_marginBottom="100dip"
+                android:layout_marginRight="64dip"
+                android:layout_alignParentTop="true"
+                android:layout_alignParentLeft="true"/>
+
+        </RelativeLayout>
+
     </RelativeLayout>
 
     <!-- bottom: password -->
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml b/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml
index 3a7c1e1..4fafc3c 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml
@@ -23,15 +23,14 @@
         android:orientation="vertical"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:gravity="left"
-        >
+        android:gravity="right">
 
     <TextView
         android:id="@+id/carrier"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="17sp"
+        android:textSize="16sp"
         android:drawablePadding="4dip"
         android:layout_marginTop="32dip"
         android:singleLine="true"
@@ -72,19 +71,6 @@
             android:layout_marginBottom="6dip"
             />
 
-        <TextView android:id="@+id/am_pm"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_toRightOf="@id/timeDisplayBackground"
-            android:layout_alignBaseline="@id/timeDisplayBackground"
-            android:singleLine="true"
-            android:ellipsize="none"
-            android:textSize="30sp"
-            android:layout_marginLeft="8dip"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textColor="@color/lockscreen_clock_am_pm"
-            />
-
     </com.android.internal.widget.DigitalClock>
 
     <LinearLayout
@@ -99,15 +85,16 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textSize="17sp"/>
+            android:textSize="16sp"/>
 
         <TextView
             android:id="@+id/alarm_status"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="30dip"
+            android:layout_marginLeft="16dip"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textSize="17sp"/>
+            android:drawablePadding="4dip"
+            android:textSize="16sp"/>
 
     </LinearLayout>
 
@@ -117,7 +104,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginTop="10dip"
-        android:textSize="17sp"
+        android:textSize="16sp"
         android:textAppearance="?android:attr/textAppearanceMedium"
         />
 
@@ -127,7 +114,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="17sp"
+        android:textSize="16sp"
         android:layout_marginTop="20dip"
         android:singleLine="false"
         android:textColor="@color/lockscreen_owner_info"
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml b/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml
index c02341e..dfab3e3 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml
@@ -23,9 +23,8 @@
         android:orientation="vertical"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="140dip"
         android:layout_marginTop="20dip"
-        android:gravity="left"
+        android:gravity="right"
         >
 
     <TextView
@@ -33,7 +32,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="17sp"
+        android:textSize="16sp"
         android:drawablePadding="4dip"
         android:layout_marginTop="32dip"
         android:singleLine="true"
@@ -73,19 +72,6 @@
             android:layout_alignTop="@id/timeDisplayBackground"
             />
 
-        <TextView android:id="@+id/am_pm"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_toRightOf="@id/timeDisplayBackground"
-            android:layout_alignBaseline="@id/timeDisplayBackground"
-            android:singleLine="true"
-            android:ellipsize="none"
-            android:textSize="30sp"
-            android:layout_marginLeft="8dip"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textColor="@color/lockscreen_clock_am_pm"
-            />
-
     </com.android.internal.widget.DigitalClock>
 
     <LinearLayout
@@ -100,15 +86,16 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textSize="17sp"/>
+            android:textSize="16sp"/>
 
         <TextView
             android:id="@+id/alarm_status"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="30dip"
+            android:layout_marginLeft="16dip"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textSize="17sp"/>
+            android:drawablePadding="4dip"
+            android:textSize="16sp"/>
 
     </LinearLayout>
 
@@ -117,7 +104,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginTop="10dip"
-        android:textSize="17sp"
+        android:textSize="16sp"
         android:textAppearance="?android:attr/textAppearanceMedium"
         />
 
@@ -128,7 +115,7 @@
         android:layout_height="wrap_content"
         android:layout_marginTop="20dip"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="17sp"
+        android:textSize="16sp"
         android:singleLine="false"
         android:visibility="invisible"
         android:textColor="@color/lockscreen_owner_info"
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml
index 23b2fcb..73dadb4 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml
@@ -30,15 +30,40 @@
 
     <!-- top: status -->
     <RelativeLayout
-        android:layout_width="match_parent"
         android:layout_height="0dip"
         android:layout_weight="1"
-        android:orientation="vertical">
-        <include layout="@layout/keyguard_screen_status_port"
-            android:layout_width="wrap_content"
+        android:layout_width="match_parent"
+        android:gravity="center">
+
+        <RelativeLayout android:id="@+id/transport_bg_protect"
+            android:layout_width="512dip"
             android:layout_height="wrap_content"
-            android:layout_marginTop="134dip"
-            android:layout_marginLeft="266dip"/>
+            android:gravity="center">
+
+            <!-- Music transport control -->
+            <include android:id="@+id/transport"
+                layout="@layout/keyguard_transport_control"
+                android:layout_row="0"
+                android:layout_column="0"
+                android:layout_rowSpan="3"
+                android:layout_columnSpan="1"
+                android:layout_gravity="fill"
+                android:layout_width="match_parent"
+                android:layout_height="512dip"
+                />
+
+            <include layout="@layout/keyguard_screen_status_port"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="50dip"
+                android:layout_marginTop="50dip"
+                android:layout_marginBottom="100dip"
+                android:layout_marginRight="64dip"
+                android:layout_alignParentTop="true"
+                android:layout_alignParentLeft="true"/>
+
+        </RelativeLayout>
+
     </RelativeLayout>
 
     <LinearLayout
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml
index 66223f2..10b1ace 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml
@@ -27,19 +27,40 @@
     android:orientation="horizontal"
     android:id="@+id/root">
 
-    <!-- left side: status -->
+    <!-- left side: status and music -->
     <RelativeLayout
         android:layout_height="match_parent"
         android:layout_weight="1"
-        android:layout_width="0dip">
+        android:layout_width="0dip"
+        android:gravity="center">
 
-        <include layout="@layout/keyguard_screen_status_land"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginLeft="102dip"
-            android:layout_marginTop="320dip"
-            android:layout_alignParentTop="true"
-            android:layout_alignParentLeft="true"/>
+        <RelativeLayout android:id="@+id/transport_bg_protect"
+            android:layout_width="512dip"
+            android:layout_height="wrap_content">
+
+            <!-- Music transport control underneath -->
+            <include android:id="@+id/transport"
+                layout="@layout/keyguard_transport_control"
+                android:layout_row="0"
+                android:layout_column="0"
+                android:layout_rowSpan="3"
+                android:layout_columnSpan="1"
+                android:layout_gravity="fill"
+                android:layout_width="match_parent"
+                android:layout_height="512dip"
+                />
+
+            <include layout="@layout/keyguard_screen_status_land"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="50dip"
+                android:layout_marginTop="50dip"
+                android:layout_marginBottom="82dip"
+                android:layout_marginRight="64dip"
+                android:layout_alignParentTop="true"
+                android:layout_alignParentLeft="true"/>
+
+        </RelativeLayout>
 
     </RelativeLayout>
 
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml b/core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml
index 7ac41b5..70d18cc 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml
@@ -27,19 +27,41 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-    <!-- left side: status  -->
+    <!-- left side: status and music -->
     <RelativeLayout
         android:layout_height="match_parent"
         android:layout_weight="1"
-        android:layout_width="0dip">
+        android:layout_width="0dip"
+        android:gravity="center">
 
-        <include layout="@layout/keyguard_screen_status_land"
-            android:layout_width="wrap_content"
+        <RelativeLayout android:id="@+id/transport_bg_protect"
+            android:layout_width="512dip"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="102dip"
-            android:layout_marginTop="320dip"
-            android:layout_alignParentTop="true"
-            android:layout_alignParentLeft="true"/>
+            android:layout_marginBottom="24dip">
+
+            <!-- Music transport control underneath -->
+            <include android:id="@+id/transport"
+                layout="@layout/keyguard_transport_control"
+                android:layout_row="0"
+                android:layout_column="0"
+                android:layout_rowSpan="3"
+                android:layout_columnSpan="1"
+                android:layout_gravity="fill"
+                android:layout_width="match_parent"
+                android:layout_height="512dip"
+                />
+
+            <include layout="@layout/keyguard_screen_status_land"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="50dip"
+                android:layout_marginTop="50dip"
+                android:layout_marginBottom="50dip"
+                android:layout_marginRight="64dip"
+                android:layout_alignParentTop="true"
+                android:layout_alignParentLeft="true"/>
+
+        </RelativeLayout>
 
     </RelativeLayout>
 
@@ -58,22 +80,23 @@
 
         <!-- Emergency and forgot pattern buttons. -->
         <LinearLayout
+            android:orientation="horizontal"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_below="@id/lockPattern"
             android:layout_alignLeft="@id/lockPattern"
             android:layout_alignRight="@id/lockPattern"
             android:layout_marginTop="28dip"
-            android:layout_marginLeft="28dip"
-            android:layout_marginRight="28dip"
-            android:orientation="horizontal">
+            android:gravity="center"
+            style="?android:attr/buttonBarStyle"
+            android:weightSum="2">
 
             <Button android:id="@+id/forgotPatternButton"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center"
-                style="@style/Widget.Button.Transparent"
-                android:drawableLeft="@drawable/ic_emergency"
+                style="?android:attr/buttonBarButtonStyle"
+                android:drawableLeft="@drawable/lockscreen_forgot_password_button"
                 android:drawablePadding="8dip"
                 android:text="@string/lockscreen_forgot_pattern_button_text"
                 android:visibility="gone"
@@ -83,7 +106,7 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center"
-                style="@style/Widget.Button.Transparent"
+                style="?android:attr/buttonBarButtonStyle"
                 android:drawableLeft="@drawable/ic_emergency"
                 android:drawablePadding="8dip"
                 android:text="@string/lockscreen_emergency_call"
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml b/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml
index 1f6058f..7a623ce 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml
@@ -23,32 +23,72 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-    <!-- top: status and emergency/forgot pattern buttons -->
-    <LinearLayout
+    <!-- top: status -->
+    <RelativeLayout
         android:layout_height="0dip"
         android:layout_weight="1"
         android:layout_width="match_parent"
-        android:orientation="vertical">
+        android:gravity="center">
 
-        <include layout="@layout/keyguard_screen_status_port"
-            android:layout_width="wrap_content"
+        <RelativeLayout android:id="@+id/transport_bg_protect"
+            android:layout_width="512dip"
             android:layout_height="wrap_content"
-            android:layout_marginTop="134dip"
-            android:layout_marginLeft="266dip"/>
+            android:gravity="center">
+
+            <!-- Music transport control -->
+            <include android:id="@+id/transport"
+                layout="@layout/keyguard_transport_control"
+                android:layout_row="0"
+                android:layout_column="0"
+                android:layout_rowSpan="3"
+                android:layout_columnSpan="1"
+                android:layout_gravity="fill"
+                android:layout_width="match_parent"
+                android:layout_height="512dip"
+                />
+
+            <include layout="@layout/keyguard_screen_status_land"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="50dip"
+                android:layout_marginTop="50dip"
+                android:layout_marginBottom="100dip"
+                android:layout_marginRight="64dip"
+                android:layout_alignParentTop="true"
+                android:layout_alignParentLeft="true"/>
+
+        </RelativeLayout>
+
+    </RelativeLayout>
+
+    <!-- bottom: lock pattern, emergency dialer and forgot pattern button -->
+    <LinearLayout
+        android:layout_weight="1"
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:orientation="vertical"
+        android:gravity="center">
+
+        <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
+            android:layout_width="354dip"
+            android:layout_height="354dip"
+            android:layout_marginTop="50dip"/>
 
         <!-- Emergency and forgot pattern buttons. -->
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="horizontal"
-            android:gravity="center_horizontal">
+            style="?android:attr/buttonBarStyle"
+            android:gravity="center"
+            android:weightSum="2">
 
             <Button android:id="@+id/forgotPatternButton"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center"
-                style="@style/Widget.Button.Transparent"
-                android:drawableLeft="@drawable/ic_emergency"
+                style="?android:attr/buttonBarButtonStyle"
+                android:drawableLeft="@drawable/lockscreen_forgot_password_button"
                 android:drawablePadding="8dip"
                 android:text="@string/lockscreen_forgot_pattern_button_text"
                 android:visibility="gone"
@@ -58,7 +98,7 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center"
-                style="@style/Widget.Button.Transparent"
+                style="?android:attr/buttonBarButtonStyle"
                 android:drawableLeft="@drawable/ic_emergency"
                 android:drawablePadding="8dip"
                 android:text="@string/lockscreen_emergency_call"
@@ -69,19 +109,5 @@
 
     </LinearLayout>
 
-    <!-- right side: lock pattern -->
-    <LinearLayout
-        android:layout_weight="1"
-        android:layout_width="match_parent"
-        android:layout_height="0dip"
-        android:gravity="center"
-        >
-        <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
-            android:layout_width="354dip"
-            android:layout_height="354dip"
-            android:layout_marginTop="50dip"
-          />
-    </LinearLayout>
-
 </com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
 
diff --git a/core/res/res/layout-sw600dp/keyguard_transport_control.xml b/core/res/res/layout-sw600dp/keyguard_transport_control.xml
new file mode 100644
index 0000000..86b103e
--- /dev/null
+++ b/core/res/res/layout-sw600dp/keyguard_transport_control.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- *** Note *** This should mirror the file in layout/ with the exception of the background set
+     here for adding a drop shadow on tablets. -->
+
+<com.android.internal.widget.TransportControlView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/transport_controls"
+    android:background="@drawable/transportcontrol_bg">
+
+    <!-- FrameLayout used as scrim to show between album art and buttons -->
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:foreground="@drawable/ic_lockscreen_player_background">
+        <!-- We use ImageView for its cropping features, otherwise could be android:background -->
+        <ImageView
+            android:id="@+id/albumart"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_gravity="fill"
+            android:scaleType="centerCrop"
+            android:adjustViewBounds="false"
+        />
+    </FrameLayout>
+
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="bottom">
+        <TextView
+            android:id="@+id/title"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="8dip"
+            android:layout_marginLeft="16dip"
+            android:layout_marginRight="16dip"
+            android:gravity="center_horizontal"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+        />
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:layout_marginTop="5dip">
+            <FrameLayout
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="1">
+                <ImageView
+                    android:id="@+id/btn_prev"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    android:src="@drawable/ic_media_previous"
+                    android:clickable="true"
+                    android:background="?android:attr/selectableItemBackground"
+                    android:padding="10dip"
+                    android:contentDescription="@string/lockscreen_transport_prev_description"/>
+            </FrameLayout>
+            <FrameLayout
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="1">
+                <ImageView
+                    android:id="@+id/btn_play"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    android:clickable="true"
+                    android:src="@drawable/ic_media_play"
+                    android:background="?android:attr/selectableItemBackground"
+                    android:padding="10dip"
+                    android:contentDescription="@string/lockscreen_transport_play_description"/>
+            </FrameLayout>
+            <FrameLayout
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="1">
+                <ImageView
+                    android:id="@+id/btn_next"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    android:clickable="true"
+                    android:src="@drawable/ic_media_next"
+                    android:background="?android:attr/selectableItemBackground"
+                    android:padding="10dip"
+                    android:contentDescription="@string/lockscreen_transport_next_description"/>
+            </FrameLayout>
+        </LinearLayout>
+    </LinearLayout>
+
+</com.android.internal.widget.TransportControlView>
diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml
index 2392618..b0f1bc5 100644
--- a/core/res/res/layout/screen_action_bar.xml
+++ b/core/res/res/layout/screen_action_bar.xml
@@ -19,6 +19,8 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
     android:orientation="vertical"
     android:fitsSystemWindows="true">
     <com.android.internal.widget.ActionBarContainer android:id="@+id/action_bar_container"
diff --git a/core/res/res/layout/screen_action_bar_overlay.xml b/core/res/res/layout/screen_action_bar_overlay.xml
index 19b861c..2a8c7c3 100644
--- a/core/res/res/layout/screen_action_bar_overlay.xml
+++ b/core/res/res/layout/screen_action_bar_overlay.xml
@@ -19,38 +19,45 @@
 the Action Bar enabled overlaying application content.
 -->
 
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
     android:fitsSystemWindows="true">
     <FrameLayout android:id="@android:id/content"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
-    <com.android.internal.widget.ActionBarContainer android:id="@+id/action_bar_container"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        style="?android:attr/actionBarStyle"
-        android:gravity="top">
-        <com.android.internal.widget.ActionBarView
-            android:id="@+id/action_bar"
+    <LinearLayout android:layout_width="match_parent"
+                  android:layout_height="wrap_content"
+                  android:layout_gravity="top">
+        <com.android.internal.widget.ActionBarContainer android:id="@+id/action_bar_container"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            style="?android:attr/actionBarStyle" />
-        <com.android.internal.widget.ActionBarContextView
-            android:id="@+id/action_context_bar"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:visibility="gone"
-            style="?android:attr/actionModeStyle" />
-    </com.android.internal.widget.ActionBarContainer>
-    <ImageView android:src="?android:attr/windowContentOverlay"
-               android:scaleType="fitXY"
-               android:layout_width="match_parent"
-               android:layout_height="wrap_content"
-               android:layout_below="@id/action_bar_container" />
+            android:layout_alignParentTop="true"
+            style="?android:attr/actionBarStyle"
+            android:gravity="top">
+            <com.android.internal.widget.ActionBarView
+                android:id="@+id/action_bar"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                style="?android:attr/actionBarStyle" />
+            <com.android.internal.widget.ActionBarContextView
+                android:id="@+id/action_context_bar"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:visibility="gone"
+                style="?android:attr/actionModeStyle" />
+        </com.android.internal.widget.ActionBarContainer>
+        <ImageView android:src="?android:attr/windowContentOverlay"
+                   android:scaleType="fitXY"
+                   android:layout_width="match_parent"
+                   android:layout_height="wrap_content"
+                   android:layout_below="@id/action_bar_container" />
+    </LinearLayout>
     <com.android.internal.widget.ActionBarContainer android:id="@+id/split_action_bar"
                   android:layout_width="match_parent"
                   android:layout_height="wrap_content"
-                  android:layout_alignParentBottom="true"
+                  android:layout_gravity="bottom"
                   style="?android:attr/actionBarSplitStyle"
                   android:visibility="gone"
                   android:gravity="center"/>
-</RelativeLayout>
+</FrameLayout>
diff --git a/core/res/res/layout/screen_simple.xml b/core/res/res/layout/screen_simple.xml
index 87c29f6..c1914e7 100644
--- a/core/res/res/layout/screen_simple.xml
+++ b/core/res/res/layout/screen_simple.xml
@@ -22,6 +22,8 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
     android:fitsSystemWindows="true"
     android:orientation="vertical">
     <ViewStub android:id="@+id/action_mode_bar_stub"
diff --git a/core/res/res/layout/screen_simple_overlay_action_mode.xml b/core/res/res/layout/screen_simple_overlay_action_mode.xml
index eb093e7..c790d10 100644
--- a/core/res/res/layout/screen_simple_overlay_action_mode.xml
+++ b/core/res/res/layout/screen_simple_overlay_action_mode.xml
@@ -21,6 +21,8 @@
 -->
 
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
     android:fitsSystemWindows="true">
     <FrameLayout
          android:id="@android:id/content"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 4eb47cd..c488116 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -171,7 +171,7 @@
     <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Kry toegang tot beskikbare rekeninge."</string>
     <string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Hardewarekontroles"</string>
     <string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"Direkte toegang tot hardeware op die selfoon."</string>
-    <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"foonoproepe"</string>
+    <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"Foonoproepe"</string>
     <string name="permgroupdesc_phoneCalls" msgid="7489701620446183770">"Monitor, neem op, en verwerk foonoproepe."</string>
     <string name="permgrouplab_systemTools" msgid="4652191644082714048">"Stelselhulpmiddels"</string>
     <string name="permgroupdesc_systemTools" msgid="8162102602190734305">"Laervlak-toegang en -beheer van die stelsel."</string>
@@ -991,8 +991,8 @@
     <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Kon nie jou SD-kaart vir USB-massaberging gebruik nie."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB gekoppel"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Kies om lêers na/van jou rekenaar te kopieer."</string>
-    <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Skakel USB-geheue af"</string>
-    <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Kies om USB-geheue af te skakel."</string>
+    <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Skakel USB-berging af"</string>
+    <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Kies om USB-berging af te skakel."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB-berging in gebruik"</string>
     <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Voordat jy USB-berging afskakel, maak seker dat jy jou Android se USB-berging van jou rekenaar ontheg (\"uitgestoot\") het."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Voordat jy die USB-berging afskakel, maak seker dat jy jou Android se SD-kaart uit die rekenaar ontheg (uitgeskiet) het."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 97ad227..27d0be3 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -159,7 +159,7 @@
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Tjenester, der koster dig penge"</string>
     <string name="permgroupdesc_costMoney" msgid="8193824940620517189">"Tillader, at en applikation kan gøre ting, som kan koste penge."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Dine beskeder"</string>
-    <string name="permgroupdesc_messages" msgid="7045736972019211994">"Læs og skriv dine sms-, e-mail- og andre beskeder."</string>
+    <string name="permgroupdesc_messages" msgid="7045736972019211994">"Læs og skriv dine sms-, e-mail og andre beskeder."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Dine personlige oplysninger"</string>
     <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Få direkte adgang til dine kontakter og din kalender, der er gemt på tabletcomputeren."</string>
     <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Få direkte adgang til dine kontakter og din kalender, der er gemt på telefonen."</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index a5caabf..aa38493 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1024,7 +1024,7 @@
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Verificando errores"</string>
     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Almacenamiento USB en blanco"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Tarjeta SD vacía"</string>
-    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Almacenamiento USB en blanco o sistema de archivos no compatible."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Almacenamiento USB vacío o sistema de archivos no compatible"</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Tarjeta SD en blanco o el sistema de archivos no es compatible."</string>
     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Almacenamiento USB dañado"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Tarjeta SD dañada"</string>
@@ -1032,7 +1032,7 @@
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Tarjeta SD dañada. Es posible que debas reformatearla."</string>
     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Almacenamiento USB extraído inesperadamente"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Almacenamiento USB extraído de forma imprevista"</string>
-    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Desmontar el almacenamiento USB antes de extraerlo para evitar la pérdida de datos."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Desactivar el almacenamiento USB antes de extraerlo para evitar la pérdida de datos."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Desmontar la tarjeta SD antes de extraerla para evitar la pérdida de datos."</string>
     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Es seguro extraer el almacenamiento USB"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Es seguro extraer la tarjeta SD"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 250415c..fd248e5 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -137,7 +137,7 @@
     <string name="turn_off_radio" msgid="8198784949987062346">"כבה אלחוטי"</string>
     <string name="screen_lock" msgid="799094655496098153">"נעילת מסך"</string>
     <string name="power_off" msgid="4266614107412865048">"כיבוי"</string>
-    <string name="shutdown_progress" msgid="2281079257329981203">"מבצע כיבוי..."</string>
+    <string name="shutdown_progress" msgid="2281079257329981203">"מכבה..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"הטבלט שלך יכבה."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"הטלפון שלך יכובה."</string>
     <string name="shutdown_confirm_question" msgid="6656441286856415014">"האם ברצונך לבצע כיבוי?"</string>
@@ -740,7 +740,7 @@
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"כתוב את ההיסטוריה והסימניות של הדפדפן"</string>
     <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"מאפשר ליישום לשנות את ההיסטוריה או את הסימניות של הדפדפן המאוחסנות בטבלט. יישומים זדוניים עלולים להשתמש ביכולת זו כדי למחוק או לשנות את הנתונים בדפדפן."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"מאפשר ליישום לשנות את ההיסטוריה או הסימניות של הדפדפן המאוחסנות בטלפון. יישומים זדוניים עלולים להשתמש ביכולת זו כדי למחוק או לשנות את נתוני הדפדפן."</string>
-    <string name="permlab_setAlarm" msgid="5924401328803615165">"הגדר התראה בשעון המעורר"</string>
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"הגדר צלצול בשעון המעורר"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"מאפשר ליישום להגדיר התראה ביישום מותקן של שעון מעורר. ייתכן שיישומי שעון מעורר מסוימים לא יישמו תכונה זו."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"הוסף דואר קולי"</string>
     <string name="permdesc_addVoicemail" msgid="4828507394878206682">"מאפשר ליישום להוסיף הודעות לתיבת הדואר הנכנס של הדואר הקולי."</string>
@@ -895,8 +895,8 @@
     <string name="chooseUsbActivity" msgid="7892597146032121735">"בחר יישום עבור מכשיר ה-USB"</string>
     <string name="noApplications" msgid="1691104391758345586">"אין יישומים שיכולים לבצע פעולה זו."</string>
     <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"למרבה הצער, <xliff:g id="APPLICATION">%1$s</xliff:g> הפסיק לפעול."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"למרבה הצער, התהליך <xliff:g id="PROCESS">%1$s</xliff:g> הופסק."</string>
+    <string name="aerr_application" msgid="932628488013092776">"לצערנו ה<xliff:g id="APPLICATION">%1$s</xliff:g> הפסיק לפעול."</string>
+    <string name="aerr_process" msgid="4507058997035697579">"לצערנו, התהליך <xliff:g id="PROCESS">%1$s</xliff:g> הופסק."</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
     <string name="anr_activity_application" msgid="8339738283149696827">"<xliff:g id="APPLICATION">%2$s</xliff:g> אינו מגיב."\n\n" האם ברצונך לסגור אותו?"</string>
     <string name="anr_activity_process" msgid="7018289416670457797">"פעילות <xliff:g id="ACTIVITY">%1$s</xliff:g> אינה מגיבה."\n\n"האם ברצונך לסגור אותה?"</string>
@@ -940,8 +940,8 @@
     <string name="volume_icon_description_incall" msgid="8890073218154543397">"עוצמת קול של שיחות"</string>
     <string name="volume_icon_description_media" msgid="4217311719665194215">"עוצמת קול של מדיה"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"עוצמת קול של התראות"</string>
-    <string name="ringtone_default" msgid="3789758980357696936">"רינגטון המוגדר כברירת מחדל"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"רינגטון המוגדר כברירת מחדל (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <string name="ringtone_default" msgid="3789758980357696936">"רינגטון ברירת מחדל"</string>
+    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"רינגטון ברירת מחדל (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
     <string name="ringtone_silent" msgid="4440324407807468713">"שקט"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"רינגטונים"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"רינגטון לא ידוע"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 6aac520..ee098d5 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -223,7 +223,7 @@
     <string name="permlab_forceStopPackages" msgid="1447830113260156236">"다른 애플리케이션 강제 종료"</string>
     <string name="permdesc_forceStopPackages" msgid="7263036616161367402">"애플리케이션이 다른 애플리케이션을 강제로 종료할 수 있도록 합니다."</string>
     <string name="permlab_forceBack" msgid="1804196839880393631">"강제로 애플리케이션 닫기"</string>
-    <string name="permdesc_forceBack" msgid="6534109744159919013">"애플리케이션이 포그라운드에 있는 활동을 강제로 닫고 되돌아갈 수 있도록 합니다. 일반 애플리케이션에는 절대로 필요하지 않습니다."</string>
+    <string name="permdesc_forceBack" msgid="6534109744159919013">"애플리케이션이 포그라운드에 있는 작업을 강제로 닫고 되돌아갈 수 있도록 합니다. 일반 애플리케이션에는 절대로 필요하지 않습니다."</string>
     <string name="permlab_dump" msgid="1681799862438954752">"시스템 내부 상태 검색"</string>
     <string name="permdesc_dump" msgid="2198776174276275220">"애플리케이션이 시스템의 내부 상태를 검색할 수 있도록 합니다. 단, 악성 애플리케이션이 이 기능을 이용하여 일반적으로 필요하지 않은 다양한 개인정보와 보안정보를 검색할 수 있습니다."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"화면 콘텐츠 검색"</string>
@@ -446,7 +446,7 @@
     <string name="permdesc_useCredentials" msgid="7416570544619546974">"애플리케이션이 인증 토큰을 요청하도록 합니다."</string>
     <string name="permlab_accessNetworkState" msgid="6865575199464405769">"네트워크 상태 보기"</string>
     <string name="permdesc_accessNetworkState" msgid="558721128707712766">"애플리케이션이 모든 네트워크의 상태를 볼 수 있도록 합니다."</string>
-    <string name="permlab_createNetworkSockets" msgid="9121633680349549585">"인터넷에 최대한 액세스"</string>
+    <string name="permlab_createNetworkSockets" msgid="9121633680349549585">"인터넷 액세스"</string>
     <string name="permdesc_createNetworkSockets" msgid="4593339106921772192">"애플리케이션이 네트워크 소켓을 만들 수 있도록 합니다."</string>
     <string name="permlab_writeApnSettings" msgid="505660159675751896">"네트워크 설정 및 트래픽 차단/변경"</string>
     <string name="permdesc_writeApnSettings" msgid="2369786339323021771">"애플리케이션이 모든 네트워크 트래픽을 가로채고 검사하거나 네트워크 설정을 변경하도록 허용합니다. 예를 들어 프록시나 APN의 포트를 변경할 수 있습니다. 악성 애플리케이션이 사용자 모르게 네트워크 패킷을 모니터링하고 리디렉션하며 수정할 수도 있습니다."</string>
@@ -899,7 +899,7 @@
     <string name="aerr_process" msgid="4507058997035697579">"<xliff:g id="PROCESS">%1$s</xliff:g> 프로세스가 중지되었습니다."</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
     <string name="anr_activity_application" msgid="8339738283149696827">"<xliff:g id="APPLICATION">%2$s</xliff:g>이(가) 응답하지 않습니다."\n\n"닫으시겠습니까?"</string>
-    <string name="anr_activity_process" msgid="7018289416670457797">"<xliff:g id="ACTIVITY">%1$s</xliff:g> 활동이 응답하지 않습니다."\n\n"닫으시겠습니까?"</string>
+    <string name="anr_activity_process" msgid="7018289416670457797">"<xliff:g id="ACTIVITY">%1$s</xliff:g>이(가) 응답하지 않습니다."\n\n"닫으시겠습니까?"</string>
     <string name="anr_application_process" msgid="7208175830253210526">"<xliff:g id="APPLICATION">%1$s</xliff:g>이(가) 응답하지 않습니다. 닫으시겠습니까?"</string>
     <string name="anr_process" msgid="306819947562555821">"<xliff:g id="PROCESS">%1$s</xliff:g> 프로세스가 응답하지 않습니다."\n\n"닫으시겠습니까?"</string>
     <string name="force_close" msgid="8346072094521265605">"확인"</string>
@@ -1208,7 +1208,7 @@
     <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 지문:"</string>
     <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 지문:"</string>
     <string name="activity_chooser_view_see_all" msgid="180268188117163072">"전체 보기..."</string>
-    <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"활동 선택"</string>
+    <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"작업 선택"</string>
     <string name="share_action_provider_share_with" msgid="1791316789651185229">"공유 대상..."</string>
     <string name="status_bar_device_locked" msgid="3092703448690669768">"기기가 잠겼습니다."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index d66c2d4..44f4d10 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -348,7 +348,7 @@
     <string name="permlab_accessFineLocation" msgid="8116127007541369477">"точное местоположение (GPS)"</string>
     <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Получать доступ к источникам точного местоположения, таким как GPS, когда это возможно. Вредоносные приложения могут использовать это разрешение для определения вашего местоположения и расходовать ресурс батареи."</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Получать доступ к источникам точного местоположения, таким как GPS, если возможно. Вредоносные приложения могут использовать это разрешение для определения вашего местоположения и расходовать ресурс батареи."</string>
-    <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"отслеживать местоположение по сигналам сети"</string>
+    <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"примерное местоположение по координатам сети"</string>
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Получать доступ к источникам данных о местоположении, таким как база данных сотовой сети, для определения приблизительного местоположения планшетного ПК, когда это возможно. Вредоносные приложения могут использовать это разрешение для определения вашего приблизительного местоположения."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Получать доступ к источникам данных о местоположении, таким как база данных сотовой сети, для определения приблизительного местоположения телефона, если возможно. Вредоносные приложения могут использовать эту возможность для определения вашего приблизительного местоположения."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"получать доступ к SurfaceFlinger"</string>
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index 5b488c0..921bcf4 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -43,7 +43,7 @@
     <dimen name="action_bar_subtitle_bottom_margin">9dip</dimen>
 
     <!-- Size of clock font in LockScreen. -->
-    <dimen name="keyguard_pattern_unlock_clock_font_size">98sp</dimen>
+    <dimen name="keyguard_pattern_unlock_clock_font_size">112sp</dimen>
 
     <!-- Size of lockscreen outerring on unsecure unlock LockScreen -->
     <dimen name="keyguard_lockscreen_outerring_diameter">364dp</dimen>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index e88de76..05da503 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -136,7 +136,7 @@
     <string name="turn_on_radio" msgid="3912793092339962371">"Vula okungenantambo"</string>
     <string name="turn_off_radio" msgid="8198784949987062346">"Vala okungenantambo"</string>
     <string name="screen_lock" msgid="799094655496098153">"Ukuvala isikrini"</string>
-    <string name="power_off" msgid="4266614107412865048">"Amandla avaliwe"</string>
+    <string name="power_off" msgid="4266614107412865048">"Vala amandla"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Ivala shaqa..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Ithebhulethi yakho izocima."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Ifoni yakho izocima."</string>
@@ -146,7 +146,7 @@
     <string name="global_actions" product="tablet" msgid="408477140088053665">"Okukhethwa konke kwethebhulethi"</string>
     <string name="global_actions" product="default" msgid="2406416831541615258">"Okukhethwa kukho kwefoni"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Ukuvala isikrini"</string>
-    <string name="global_action_power_off" msgid="4471879440839879722">"Amandla avaliwe"</string>
+    <string name="global_action_power_off" msgid="4471879440839879722">"Vala amandla"</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Imodi ethulile"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Umsindo UVALIWE"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Umsindo UVULIWE"</string>
@@ -838,7 +838,7 @@
     <item quantity="one" msgid="2178576254385739855">"Kusasa"</item>
     <item quantity="other" msgid="2973062968038355991">"ezinsukwini ezing-<xliff:g id="COUNT">%d</xliff:g>"</item>
   </plurals>
-    <string name="preposition_for_date" msgid="9093949757757445117">"Ngomhla ka <xliff:g id="DATE">%s</xliff:g>"</string>
+    <string name="preposition_for_date" msgid="9093949757757445117">"ngo-<xliff:g id="DATE">%s</xliff:g>"</string>
     <string name="preposition_for_time" msgid="5506831244263083793">"e-<xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="preposition_for_year" msgid="5040395640711867177">"phakathi- <xliff:g id="YEAR">%s</xliff:g>"</string>
     <string name="day" msgid="8144195776058119424">"usuku"</string>
@@ -886,7 +886,7 @@
     <string name="no" msgid="5141531044935541497">"Khansela"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"Ukunaka"</string>
     <string name="loading" msgid="1760724998928255250">"Iyalayisha..."</string>
-    <string name="capital_on" msgid="1544682755514494298">"Ngomhla ka"</string>
+    <string name="capital_on" msgid="1544682755514494298">"VULIWE"</string>
     <string name="capital_off" msgid="6815870386972805832">"VALIWE"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Qedela isenzo usebenzisa"</string>
     <string name="alwaysUse" msgid="4583018368000610438">"Sebenzisa ngokuzenzakalelayo kulesenzo."</string>
@@ -1146,7 +1146,7 @@
     <string name="checkbox_not_checked" msgid="5174639551134444056">"akuhloliwe"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"Okukhethiwe"</string>
     <string name="radiobutton_not_selected" msgid="2908760184307722393">"akukhethiwe"</string>
-    <string name="switch_on" msgid="551417728476977311">"Ngomhla ka-"</string>
+    <string name="switch_on" msgid="551417728476977311">"vuliwe"</string>
     <string name="switch_off" msgid="7249798614327155088">"valiwe"</string>
     <string name="togglebutton_pressed" msgid="4180411746647422233">"kucindezelwe."</string>
     <string name="togglebutton_not_pressed" msgid="4495147725636134425">"akucindezelwe."</string>
diff --git a/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java b/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java
index 0cc883f..a781472 100644
--- a/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java
+++ b/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java
@@ -90,7 +90,26 @@
      */
     @LargeTest
     public void testWifiDownload() throws Exception {
-        assertTrue(setDeviceWifiAndAirplaneMode(mSsid));
+        assertTrue("Could not connect to wifi!", setDeviceWifiAndAirplaneMode(mSsid));
+        downloadFile();
+    }
+
+    /**
+     * Ensure that downloading on mobile reports reasonable stats.
+     */
+    @LargeTest
+    public void testMobileDownload() throws Exception {
+        // As part of the setup we disconnected from wifi; make sure we are connected to mobile and
+        // that we have data.
+        assertTrue("Do not have mobile data!", hasMobileData());
+        downloadFile();
+    }
+
+    /**
+     * Helper method that downloads a file using http connection from a test server and reports the
+     * data usage stats to instrumentation out.
+     */
+    protected void downloadFile() throws Exception {
         NetworkStats pre_test_stats = fetchDataFromProc(mUid);
         String ts = Long.toString(System.currentTimeMillis());
 
@@ -120,11 +139,28 @@
     }
 
     /**
-     * Ensure that downloading on wifi reports reasonable stats.
+     * Ensure that uploading on wifi reports reasonable stats.
      */
     @LargeTest
     public void testWifiUpload() throws Exception {
         assertTrue(setDeviceWifiAndAirplaneMode(mSsid));
+        uploadFile();
+    }
+
+    /**
+     *  Ensure that uploading on wifi reports reasonable stats.
+     */
+    @LargeTest
+    public void testMobileUpload() throws Exception {
+        assertTrue(hasMobileData());
+        uploadFile();
+    }
+
+    /**
+     * Helper method that downloads a test file to upload. The stats reported to instrumentation out
+     * only include upload stats.
+     */
+    protected void uploadFile() throws Exception {
         // Download a file from the server.
         String ts = Long.toString(System.currentTimeMillis());
         String targetUrl = BandwidthTestUtil.buildDownloadUrl(
@@ -156,12 +192,30 @@
     }
 
     /**
-     * We want to make sure that if we use the Download Manager to download stuff,
+     * We want to make sure that if we use wifi and the  Download Manager to download stuff,
      * accounting still goes to the app making the call and that the numbers still make sense.
      */
     @LargeTest
     public void testWifiDownloadWithDownloadManager() throws Exception {
         assertTrue(setDeviceWifiAndAirplaneMode(mSsid));
+        downloadFileUsingDownloadManager();
+    }
+
+    /**
+     * We want to make sure that if we use mobile data and the Download Manager to download stuff,
+     * accounting still goes to the app making the call and that the numbers still make sense.
+     */
+    @LargeTest
+    public void testMobileDownloadWithDownloadManager() throws Exception {
+        assertTrue(hasMobileData());
+        downloadFileUsingDownloadManager();
+    }
+
+    /**
+     * Helper method that downloads a file from a test server using the download manager and reports
+     * the stats to instrumentation out.
+     */
+    protected void downloadFileUsingDownloadManager() throws Exception {
         // If we are using the download manager, then the data that is written to /proc/uid_stat/
         // is accounted against download manager's uid, since it uses pre-ICS API.
         int downloadManagerUid = mConnectionUtil.downloadManagerUid();
@@ -195,6 +249,7 @@
 
     /**
      * Fetch network data from /proc/uid_stat/uid
+     *
      * @return populated {@link NetworkStats}
      */
     public NetworkStats fetchDataFromProc(int uid) {
@@ -210,7 +265,8 @@
     }
 
     /**
-     * Turn on Airplane mode and connect to the wifi
+     * Turn on Airplane mode and connect to the wifi.
+     *
      * @param ssid of the wifi to connect to
      * @return true if we successfully connected to a given network.
      */
@@ -219,12 +275,25 @@
         assertTrue(mConnectionUtil.connectToWifi(ssid));
         assertTrue(mConnectionUtil.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
                 ConnectionUtil.LONG_TIMEOUT));
-        return mConnectionUtil.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                ConnectionUtil.LONG_TIMEOUT);
+        assertTrue(mConnectionUtil.waitForNetworkState(ConnectivityManager.TYPE_WIFI,
+                State.CONNECTED, ConnectionUtil.LONG_TIMEOUT));
+        return mConnectionUtil.hasData();
+    }
+
+    /**
+     * Helper method to make sure we are connected to mobile data.
+     *
+     * @return true if we successfully connect to mobile data.
+     */
+    public boolean hasMobileData() {
+        assertTrue("Not connected to mobile", mConnectionUtil.isConnectedToMobile());
+        assertFalse("Still connected to wifi.", mConnectionUtil.isConnectedToWifi());
+        return mConnectionUtil.hasData();
     }
 
     /**
      * Output the {@link NetworkStats} to Instrumentation out.
+     *
      * @param label to attach to this given stats.
      * @param stats {@link NetworkStats} to add.
      * @param results {@link Bundle} to be added to.
@@ -281,4 +350,4 @@
         }
         return true;
     }
-}
\ No newline at end of file
+}
diff --git a/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java b/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java
index d663aad..a5e5ab0e 100644
--- a/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java
+++ b/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java
@@ -44,6 +44,8 @@
 import com.android.bandwidthtest.NetworkState.StateTransitionDirection;
 import com.android.internal.util.AsyncChannel;
 
+import java.io.IOException;
+import java.net.UnknownHostException;
 import java.util.List;
 
 /*
@@ -257,14 +259,14 @@
         mConnectivityState[networkType].recordState(networkState);
     }
 
-   /**
-    * Set the state transition criteria
-    *
-    * @param networkType
-    * @param initState
-    * @param transitionDir
-    * @param targetState
-    */
+    /**
+     * Set the state transition criteria
+     *
+     * @param networkType
+     * @param initState
+     * @param transitionDir
+     * @param targetState
+     */
     public void setStateTransitionCriteria(int networkType, State initState,
             StateTransitionDirection transitionDir, State targetState) {
         mConnectivityState[networkType].setStateTransitionCriteria(
@@ -495,7 +497,8 @@
      * @return true if connected to a mobile network, false otherwise.
      */
     public boolean isConnectedToMobile() {
-        return (mNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE);
+        NetworkInfo networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
+        return networkInfo.isConnected();
     }
 
     /**
@@ -503,10 +506,10 @@
      * @return true if connected to wifi, false otherwise.
      */
     public boolean isConnectedToWifi() {
-        return (mNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI);
+        NetworkInfo networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+        return networkInfo.isConnected();
     }
 
-
     /**
      * Associate the device to given SSID
      * If the device is already associated with a WiFi, disconnect and forget it,
@@ -681,4 +684,30 @@
         }
         Log.v(LOG_TAG, "onDestroy, inst=" + Integer.toHexString(hashCode()));
     }
+
+    /**
+     * Helper method used to test data connectivity by pinging a series of popular sites.
+     * @return true if device has data connectivity, false otherwise.
+     */
+    public boolean hasData() {
+        String[] hostList = {"www.google.com", "www.yahoo.com",
+                "www.bing.com", "www.facebook.com", "www.ask.com"};
+        try {
+            for (int i = 0; i < hostList.length; ++i) {
+                String host = hostList[i];
+                Process p = Runtime.getRuntime().exec("ping -c 10 -w 100 " + host);
+                int status = p.waitFor();
+                if (status == 0) {
+                    return true;
+                }
+            }
+        } catch (UnknownHostException e) {
+            Log.e(LOG_TAG, "Ping test Failed: Unknown Host");
+        } catch (IOException e) {
+            Log.e(LOG_TAG, "Ping test Failed: IOException");
+        } catch (InterruptedException e) {
+            Log.e(LOG_TAG, "Ping test Failed: InterruptedException");
+        }
+        return false;
+    }
 }
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
index e1db073..1df763a 100644
--- a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
+++ b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
@@ -256,6 +256,10 @@
         stats.recordData(TEST_START, TEST_START + DAY_IN_MILLIS, 24L, 24L);
         assertEquals(24, stats.size());
 
+        // try removing invalid data; should be no change
+        stats.removeBucketsBefore(0 - DAY_IN_MILLIS);
+        assertEquals(24, stats.size());
+
         // try removing far before buckets; should be no change
         stats.removeBucketsBefore(TEST_START - YEAR_IN_MILLIS);
         assertEquals(24, stats.size());
diff --git a/include/media/MediaProfiles.h b/include/media/MediaProfiles.h
index eab7648..250f267 100644
--- a/include/media/MediaProfiles.h
+++ b/include/media/MediaProfiles.h
@@ -48,15 +48,21 @@
 };
 
 /**
- *Set CIF as default maximum import and export resolution of video editor.
- *The maximum import and export resolutions are platform specific,
- *which should be defined in media_profiles.xml.
+ * Set CIF as default maximum import and export resolution of video editor.
+ * The maximum import and export resolutions are platform specific,
+ * which should be defined in media_profiles.xml.
+ * Set default maximum prefetch YUV frames to 6, which means video editor can
+ * queue up to 6 YUV frames in the video encoder source.
+ * This value is used to limit the amount of memory used by video editor
+ * engine when the encoder consumes YUV frames at a lower speed
+ * than video editor engine produces.
  */
 enum videoeditor_capability {
     VIDEOEDITOR_DEFAULT_MAX_INPUT_FRAME_WIDTH = 352,
     VIDEOEDITOR_DEFUALT_MAX_INPUT_FRAME_HEIGHT = 288,
     VIDEOEDITOR_DEFAULT_MAX_OUTPUT_FRAME_WIDTH = 352,
     VIDEOEDITOR_DEFUALT_MAX_OUTPUT_FRAME_HEIGHT = 288,
+    VIDEOEDITOR_DEFAULT_MAX_PREFETCH_YUV_FRAMES = 6
 };
 
 enum video_decoder {
@@ -138,6 +144,8 @@
      * videoeditor.input.height.max - max input video frame height
      * videoeditor.output.width.max - max output video frame width
      * videoeditor.output.height.max - max output video frame height
+     * maxPrefetchYUVFrames - max prefetch YUV frames in video editor engine. This value is used
+     * to limit the memory consumption.
      */
     int getVideoEditorCapParamByName(const char *name) const;
 
@@ -357,11 +365,12 @@
     };
     struct VideoEditorCap {
         VideoEditorCap(int inFrameWidth, int inFrameHeight,
-            int outFrameWidth, int outFrameHeight)
+            int outFrameWidth, int outFrameHeight, int frames)
             : mMaxInputFrameWidth(inFrameWidth),
               mMaxInputFrameHeight(inFrameHeight),
               mMaxOutputFrameWidth(outFrameWidth),
-              mMaxOutputFrameHeight(outFrameHeight) {}
+              mMaxOutputFrameHeight(outFrameHeight),
+              mMaxPrefetchYUVFrames(frames) {}
 
         ~VideoEditorCap() {}
 
@@ -369,6 +378,7 @@
         int mMaxInputFrameHeight;
         int mMaxOutputFrameWidth;
         int mMaxOutputFrameHeight;
+        int mMaxPrefetchYUVFrames;
     };
 
     int getCamcorderProfileIndex(int cameraId, camcorder_quality quality) const;
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index ed319f5..9767568 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -32,6 +32,10 @@
 
 LOCAL_MODULE:= libgui
 
+ifeq ($(TARGET_BOARD_PLATFORM), tegra)
+	LOCAL_CFLAGS += -DALLOW_DEQUEUE_CURRENT_BUFFER
+endif
+
 include $(BUILD_SHARED_LIBRARY)
 
 ifeq (,$(ONE_SHOT_MAKEFILE))
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 6f84206..374f3c5 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -36,8 +36,12 @@
 #include <utils/Log.h>
 #include <utils/String8.h>
 
-
-#define ALLOW_DEQUEUE_CURRENT_BUFFER    false
+#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER
+#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER    true
+#warning "ALLOW_DEQUEUE_CURRENT_BUFFER enabled"
+#else
+#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER    false
+#endif
 
 // Macros for including the SurfaceTexture name in log messages
 #define ST_LOGV(x, ...) LOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
@@ -323,7 +327,7 @@
             LOGW_IF((state == BufferSlot::FREE) && (mCurrentTexture==i),
                     "dequeueBuffer: buffer %d is both FREE and current!", i);
 
-            if (ALLOW_DEQUEUE_CURRENT_BUFFER) {
+            if (FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER) {
                 if (state == BufferSlot::FREE || i == mCurrentTexture) {
                     foundSync = i;
                     if (i != mCurrentTexture) {
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index a8daab0..a2b80c2 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -3062,6 +3062,7 @@
             if ((mRcClientDeathHandler != null) && (mRcClientDeathHandler.mCb != null)) {
                 try {
                     mRcClientDeathHandler.mCb.unlinkToDeath(mRcClientDeathHandler, 0);
+                    mRcClientDeathHandler = null;
                 } catch (java.util.NoSuchElementException e) {
                     // not much we can do here
                     Log.e(TAG, "Encountered " + e + " in unlinkToRcClientDeath()");
@@ -3069,6 +3070,12 @@
                 }
             }
         }
+
+        @Override
+        protected void finalize() throws Throwable {
+            unlinkToRcClientDeath();// unlink exception handled inside method
+            super.finalize();
+        }
     }
 
     /**
@@ -3115,6 +3122,7 @@
                     if (packageName.equalsIgnoreCase(rcse.mReceiverComponent.getPackageName())) {
                         // a stack entry is from the package being removed, remove it from the stack
                         stackIterator.remove();
+                        rcse.unlinkToRcClientDeath();
                     }
                 }
                 if (mRCStack.empty()) {
@@ -3195,6 +3203,7 @@
             RemoteControlStackEntry rcse = (RemoteControlStackEntry)stackIterator.next();
             if(rcse.mMediaIntent.equals(pi)) {
                 stackIterator.remove();
+                rcse.unlinkToRcClientDeath();
                 break;
             }
         }
@@ -3456,7 +3465,7 @@
                         rcse.mCallingPackageName = callingPackageName;
                         rcse.mCallingUid = Binder.getCallingUid();
                         if (rcClient == null) {
-                            rcse.mRcClientDeathHandler = null;
+                            // here rcse.mRcClientDeathHandler is null;
                             break;
                         }
 
@@ -3512,7 +3521,6 @@
                         rcse.unlinkToRcClientDeath();
                         // reset the client-related fields
                         rcse.mRcClient = null;
-                        rcse.mRcClientDeathHandler = null;
                         rcse.mCallingPackageName = null;
                     }
                 }
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index ad55ff8..6096b72 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -404,11 +404,12 @@
     CHECK(!strcmp("maxInputFrameWidth", atts[0]) &&
           !strcmp("maxInputFrameHeight", atts[2])  &&
           !strcmp("maxOutputFrameWidth", atts[4]) &&
-          !strcmp("maxOutputFrameHeight", atts[6]));
+          !strcmp("maxOutputFrameHeight", atts[6]) &&
+          !strcmp("maxPrefetchYUVFrames", atts[8]));
 
     MediaProfiles::VideoEditorCap *pVideoEditorCap =
         new MediaProfiles::VideoEditorCap(atoi(atts[1]), atoi(atts[3]),
-                atoi(atts[5]), atoi(atts[7]));
+                atoi(atts[5]), atoi(atts[7]), atoi(atts[9]));
 
     logVideoEditorCap(*pVideoEditorCap);
     profiles->mVideoEditorCap = pVideoEditorCap;
@@ -850,7 +851,8 @@
                 VIDEOEDITOR_DEFAULT_MAX_INPUT_FRAME_WIDTH,
                 VIDEOEDITOR_DEFUALT_MAX_INPUT_FRAME_HEIGHT,
                 VIDEOEDITOR_DEFAULT_MAX_OUTPUT_FRAME_WIDTH,
-                VIDEOEDITOR_DEFUALT_MAX_OUTPUT_FRAME_HEIGHT);
+                VIDEOEDITOR_DEFUALT_MAX_OUTPUT_FRAME_HEIGHT,
+                VIDEOEDITOR_DEFAULT_MAX_PREFETCH_YUV_FRAMES);
 }
 /*static*/ void
 MediaProfiles::createDefaultExportVideoProfiles(MediaProfiles *profiles)
@@ -1019,6 +1021,8 @@
         return mVideoEditorCap->mMaxOutputFrameWidth;
     if (!strcmp("videoeditor.output.height.max", name))
         return mVideoEditorCap->mMaxOutputFrameHeight;
+    if (!strcmp("maxPrefetchYUVFrames", name))
+        return mVideoEditorCap->mMaxPrefetchYUVFrames;
 
     LOGE("The given video editor param name %s is not found", name);
     return -1;
diff --git a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
index 62213de..9c87c22 100644
--- a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
+++ b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
@@ -16,6 +16,8 @@
 
 package com.android.nfc_extras;
 
+import java.util.HashMap;
+
 import android.content.Context;
 import android.nfc.INfcAdapterExtras;
 import android.nfc.NfcAdapter;
@@ -57,20 +59,22 @@
     // protected by NfcAdapterExtras.class, and final after first construction,
     // except for attemptDeadServiceRecovery() when NFC crashes - we accept a
     // best effort recovery
-    private static NfcAdapter sAdapter;
     private static INfcAdapterExtras sService;
     private static final CardEmulationRoute ROUTE_OFF =
             new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null);
 
+    // contents protected by NfcAdapterExtras.class
+    private static final HashMap<NfcAdapter, NfcAdapterExtras> sNfcExtras = new HashMap();
+
     private final NfcExecutionEnvironment mEmbeddedEe;
     private final CardEmulationRoute mRouteOnWhenScreenOn;
 
-    final Context mContext;
+    private final NfcAdapter mAdapter;
     final String mPackageName;
 
     /** get service handles */
-    private static void initService() {
-        final INfcAdapterExtras service = sAdapter.getNfcAdapterExtrasInterface();
+    private static void initService(NfcAdapter adapter) {
+        final INfcAdapterExtras service = adapter.getNfcAdapterExtrasInterface();
         if (service != null) {
             // Leave stale rather than receive a null value.
             sService = service;
@@ -95,23 +99,20 @@
 
         synchronized (NfcAdapterExtras.class) {
             if (sService == null) {
-                try {
-                    sAdapter = adapter;
-                    initService();
-                } finally {
-                    if (sService == null) {
-                        sAdapter = null;
-                    }
-                }
+                initService(adapter);
             }
+            NfcAdapterExtras extras = sNfcExtras.get(adapter);
+            if (extras == null) {
+                extras = new NfcAdapterExtras(adapter);
+                sNfcExtras.put(adapter,  extras);
+            }
+            return extras;
         }
-
-        return new NfcAdapterExtras(context);
     }
 
-    private NfcAdapterExtras(Context context) {
-        mContext = context.getApplicationContext();
-        mPackageName = context.getPackageName();
+    private NfcAdapterExtras(NfcAdapter adapter) {
+        mAdapter = adapter;
+        mPackageName = adapter.getContext().getPackageName();
         mEmbeddedEe = new NfcExecutionEnvironment(this);
         mRouteOnWhenScreenOn = new CardEmulationRoute(CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON,
                 mEmbeddedEe);
@@ -160,8 +161,8 @@
      */
     void attemptDeadServiceRecovery(Exception e) {
         Log.e(TAG, "NFC Adapter Extras dead - attempting to recover");
-        sAdapter.attemptDeadServiceRecovery(e);
-        initService();
+        mAdapter.attemptDeadServiceRecovery(e);
+        initService(mAdapter);
     }
 
     INfcAdapterExtras getService() {
diff --git a/nfc-extras/tests/Android.mk b/nfc-extras/tests/Android.mk
new file mode 100644
index 0000000..3eca76d
--- /dev/null
+++ b/nfc-extras/tests/Android.mk
@@ -0,0 +1,32 @@
+# Copyright 2011, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_JAVA_LIBRARIES := \
+    android.test.runner \
+    com.android.nfc_extras
+
+# Include all test java files.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := NfcExtrasTests
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/nfc-extras/tests/AndroidManifest.xml b/nfc-extras/tests/AndroidManifest.xml
new file mode 100644
index 0000000..0cc6653
--- /dev/null
+++ b/nfc-extras/tests/AndroidManifest.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.nfc_extras.tests">
+
+    <!-- We add an application tag here just so that we can indicate that
+         this package needs to link against the android.test library,
+         which is needed when building test cases. -->
+    <application>
+        <uses-library android:name="android.test.runner" />
+        <uses-library android:name="com.android.nfc_extras" />
+    </application>
+
+    <uses-permission android:name="android.permission.NFC"/>
+
+    <!--
+    Run all tests with
+    adb shell am instrument -w com.android.nfc_extras.tests/android.test.InstrumentationTestRunner
+    -->
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+                     android:targetPackage="com.android.nfc_extras.tests"
+                     android:label="Tests for NFC Extras library"/>
+
+</manifest>
diff --git a/nfc-extras/tests/src/com/android/nfc_extras/BasicNfcEeTest.java b/nfc-extras/tests/src/com/android/nfc_extras/BasicNfcEeTest.java
new file mode 100644
index 0000000..e1025aa
--- /dev/null
+++ b/nfc-extras/tests/src/com/android/nfc_extras/BasicNfcEeTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.nfc_extras;
+
+import android.content.Context;
+import android.nfc.NfcAdapter;
+import android.test.InstrumentationTestCase;
+import android.util.Log;
+
+import com.android.nfc_extras.NfcAdapterExtras;
+import com.android.nfc_extras.NfcAdapterExtras.CardEmulationRoute;
+import com.android.nfc_extras.NfcExecutionEnvironment;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+public class BasicNfcEeTest extends InstrumentationTestCase {
+    private Context mContext;
+    private NfcAdapterExtras mAdapterExtras;
+    private NfcExecutionEnvironment mEe;
+
+    public static final byte[] SELECT_CARD_MANAGER_COMMAND = new byte[] {
+        (byte)0x00, (byte)0xA4, (byte)0x04, (byte)0x00,  // command
+        (byte)0x08,  // data length
+        (byte)0xA0, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x03, (byte)0x00, (byte)0x00,
+        (byte)0x00,  // card manager AID
+        (byte)0x00  // trailer
+    };
+
+    public static final byte[] SELECT_CARD_MANAGER_RESPONSE = new byte[] {
+        (byte)0x90, (byte)0x00,
+    };
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mContext = getInstrumentation().getContext();
+        mAdapterExtras = NfcAdapterExtras.get(NfcAdapter.getDefaultAdapter(mContext));
+        mEe = mAdapterExtras.getEmbeddedExecutionEnvironment();
+    }
+
+    public void testSendCardManagerApdu() throws IOException {
+        mEe.open();
+
+        try {
+            byte[] out = mEe.transceive(SELECT_CARD_MANAGER_COMMAND);
+            assertTrue(out.length >= SELECT_CARD_MANAGER_RESPONSE.length);
+            byte[] trailing = Arrays.copyOfRange(out,
+                    out.length - SELECT_CARD_MANAGER_RESPONSE.length,
+                    out.length);
+            assertByteArrayEquals(SELECT_CARD_MANAGER_RESPONSE, trailing);
+
+        } finally {
+            mEe.close();
+        }
+
+    }
+
+    public void testSendCardManagerApduMultiple() throws IOException {
+        for (int i=0; i<10; i++) {
+            try {
+            mEe.open();
+
+            try {
+                byte[] out = mEe.transceive(SELECT_CARD_MANAGER_COMMAND);
+                byte[] trailing = Arrays.copyOfRange(out,
+                        out.length - SELECT_CARD_MANAGER_RESPONSE.length,
+                        out.length);
+
+            } finally {
+                try {Thread.sleep(1000);} catch (InterruptedException e) {}
+                mEe.close();
+            }
+            } catch (IOException e) {}
+        }
+
+        testSendCardManagerApdu();
+
+    }
+
+    public void testEnableEe() {
+        mAdapterExtras.setCardEmulationRoute(
+                new CardEmulationRoute(CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON, mEe));
+        CardEmulationRoute newRoute = mAdapterExtras.getCardEmulationRoute();
+        assertEquals(CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON, newRoute.route);
+        assertEquals(mEe, newRoute.nfcEe);
+    }
+
+    public void testDisableEe() {
+        mAdapterExtras.setCardEmulationRoute(
+                new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null));
+        CardEmulationRoute newRoute = mAdapterExtras.getCardEmulationRoute();
+        assertEquals(CardEmulationRoute.ROUTE_OFF, newRoute.route);
+        assertNull(newRoute.nfcEe);
+    }
+
+    private static void assertByteArrayEquals(byte[] b1, byte[] b2) {
+        assertEquals(b1.length, b2.length);
+        for (int i = 0; i < b1.length; i++) {
+            assertEquals(b1[i], b2[i]);
+        }
+    }
+}
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index 8e8e26c..c926670 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -261,14 +261,14 @@
  */
 #ifndef EGL_ANDROID_blob_cache
 #define EGL_ANDROID_blob_cache 1
-typedef khronos_ssize_t EGLsizei;
-typedef void (*EGLSetBlobFunc) (const void* key, EGLsizei keySize, const void* value, EGLsizei valueSize);
-typedef EGLsizei (*EGLGetBlobFunc) (const void* key, EGLsizei keySize, void* value, EGLsizei valueSize);
+typedef khronos_ssize_t EGLsizeiANDROID;
+typedef void (*EGLSetBlobFuncANDROID) (const void* key, EGLsizeiANDROID keySize, const void* value, EGLsizeiANDROID valueSize);
+typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void* key, EGLsizeiANDROID keySize, void* value, EGLsizeiANDROID valueSize);
 #ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncs(EGLDisplay dpy, EGLSetBlobFunc set, EGLGetBlobFunc get);
+EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncsANDROID(EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
 #endif /* EGL_EGLEXT_PROTOTYPES */
-typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSPROC) (EGLDisplay dpy,
-        EGLSetBlobFunc set, EGLGetBlobFunc get);
+typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSANDROIDPROC) (EGLDisplay dpy,
+        EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
 #endif
 
 #ifdef __cplusplus
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 1e43195..6ad06af 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -212,16 +212,20 @@
 
 EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image)
 {
-    ImageRef _i(image);
-    if (!_i.get())
-        return EGL_NO_IMAGE_KHR;
-
     EGLContext context = egl_tls_t::getContext();
     if (context == EGL_NO_CONTEXT || image == EGL_NO_IMAGE_KHR)
         return EGL_NO_IMAGE_KHR;
 
     egl_context_t const * const c = get_context(context);
-    if (c == NULL) // this should never happen
+    if (c == NULL) // this should never happen, by construction
+        return EGL_NO_IMAGE_KHR;
+
+    egl_display_t* display = egl_display_t::get(c->dpy);
+    if (display == NULL) // this should never happen, by construction
+        return EGL_NO_IMAGE_KHR;
+
+    ImageRef _i(display, image);
+    if (!_i.get())
         return EGL_NO_IMAGE_KHR;
 
     // here we don't validate the context because if it's been marked for
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 60ac34b..095f10c 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -451,7 +451,7 @@
     egl_display_t const * const dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
-    SurfaceRef _s(surface);
+    SurfaceRef _s(dp, surface);
     if (!_s.get())
         return setError(EGL_BAD_SURFACE, EGL_FALSE);
 
@@ -472,7 +472,7 @@
     egl_display_t const * const dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
-    SurfaceRef _s(surface);
+    SurfaceRef _s(dp, surface);
     if (!_s.get())
         return setError(EGL_BAD_SURFACE, EGL_FALSE);
 
@@ -541,7 +541,7 @@
     if (!dp)
         return EGL_FALSE;
 
-    ContextRef _c(ctx);
+    ContextRef _c(dp, ctx);
     if (!_c.get())
         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
     
@@ -592,9 +592,9 @@
     }
 
     // get a reference to the object passed in
-    ContextRef _c(ctx);
-    SurfaceRef _d(draw);
-    SurfaceRef _r(read);
+    ContextRef _c(dp, ctx);
+    SurfaceRef _d(dp, draw);
+    SurfaceRef _r(dp, read);
 
     // validate the context (if not EGL_NO_CONTEXT)
     if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
@@ -696,7 +696,7 @@
     egl_display_t const * const dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
-    ContextRef _c(ctx);
+    ContextRef _c(dp, ctx);
     if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
 
     egl_context_t * const c = get_context(ctx);
@@ -860,7 +860,7 @@
 
     // The EGL_ANDROID_blob_cache extension should not be exposed to
     // applications.  It is used internally by the Android EGL layer.
-    if (!strcmp(procname, "eglSetBlobCacheFuncs")) {
+    if (!strcmp(procname, "eglSetBlobCacheFuncsANDROID")) {
         return NULL;
     }
 
@@ -944,7 +944,7 @@
     egl_display_t const * const dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
-    SurfaceRef _s(draw);
+    SurfaceRef _s(dp, draw);
     if (!_s.get())
         return setError(EGL_BAD_SURFACE, EGL_FALSE);
 
@@ -960,7 +960,7 @@
     egl_display_t const * const dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
-    SurfaceRef _s(surface);
+    SurfaceRef _s(dp, surface);
     if (!_s.get())
         return setError(EGL_BAD_SURFACE, EGL_FALSE);
 
@@ -1002,7 +1002,7 @@
     egl_display_t const * const dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
-    SurfaceRef _s(surface);
+    SurfaceRef _s(dp, surface);
     if (!_s.get())
         return setError(EGL_BAD_SURFACE, EGL_FALSE);
 
@@ -1022,7 +1022,7 @@
     egl_display_t const * const dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
-    SurfaceRef _s(surface);
+    SurfaceRef _s(dp, surface);
     if (!_s.get())
         return setError(EGL_BAD_SURFACE, EGL_FALSE);
 
@@ -1042,7 +1042,7 @@
     egl_display_t const * const dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
-    SurfaceRef _s(surface);
+    SurfaceRef _s(dp, surface);
     if (!_s.get())
         return setError(EGL_BAD_SURFACE, EGL_FALSE);
 
@@ -1201,7 +1201,7 @@
     egl_display_t const * const dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
-    SurfaceRef _s(surface);
+    SurfaceRef _s(dp, surface);
     if (!_s.get())
         return setError(EGL_BAD_SURFACE, EGL_FALSE);
 
@@ -1220,7 +1220,7 @@
     egl_display_t const * const dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
-    SurfaceRef _s(surface);
+    SurfaceRef _s(dp, surface);
     if (!_s.get())
         return setError(EGL_BAD_SURFACE, EGL_FALSE);
 
@@ -1241,7 +1241,7 @@
     if (!dp) return EGL_NO_IMAGE_KHR;
 
     if (ctx != EGL_NO_CONTEXT) {
-        ContextRef _c(ctx);
+        ContextRef _c(dp, ctx);
         if (!_c.get())
             return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
         egl_context_t * const c = get_context(ctx);
@@ -1310,7 +1310,7 @@
     egl_display_t const * const dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
-    ImageRef _i(img);
+    ImageRef _i(dp, img);
     if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
 
     egl_image_t* image = get_image(img);
@@ -1349,7 +1349,7 @@
     if (!dp) return EGL_NO_SYNC_KHR;
 
     EGLContext ctx = eglGetCurrentContext();
-    ContextRef _c(ctx);
+    ContextRef _c(dp, ctx);
     if (!_c.get())
         return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR);
 
@@ -1372,12 +1372,12 @@
     egl_display_t const * const dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
-    SyncRef _s(sync);
+    SyncRef _s(dp, sync);
     if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
     egl_sync_t* syncObject = get_sync(sync);
 
     EGLContext ctx = syncObject->context;
-    ContextRef _c(ctx);
+    ContextRef _c(dp, ctx);
     if (!_c.get())
         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
 
@@ -1399,12 +1399,12 @@
     egl_display_t const * const dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
-    SyncRef _s(sync);
+    SyncRef _s(dp, sync);
     if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
     egl_sync_t* syncObject = get_sync(sync);
 
     EGLContext ctx = syncObject->context;
-    ContextRef _c(ctx);
+    ContextRef _c(dp, ctx);
     if (!_c.get())
         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
 
@@ -1424,13 +1424,13 @@
     egl_display_t const * const dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
-    SyncRef _s(sync);
+    SyncRef _s(dp, sync);
     if (!_s.get())
         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
 
     egl_sync_t* syncObject = get_sync(sync);
     EGLContext ctx = syncObject->context;
-    ContextRef _c(ctx);
+    ContextRef _c(dp, ctx);
     if (!_c.get())
         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
 
@@ -1455,7 +1455,7 @@
     egl_display_t const * const dp = validate_display(dpy);
     if (!dp) return EGL_FALSE;
 
-    SurfaceRef _s(draw);
+    SurfaceRef _s(dp, draw);
     if (!_s.get())
         return setError(EGL_BAD_SURFACE, EGL_FALSE);
 
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index 522421b..13a4929 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -46,13 +46,13 @@
 //
 // Callback functions passed to EGL.
 //
-static void setBlob(const void* key, EGLsizei keySize, const void* value,
-        EGLsizei valueSize) {
+static void setBlob(const void* key, EGLsizeiANDROID keySize,
+        const void* value, EGLsizeiANDROID valueSize) {
     egl_cache_t::get()->setBlob(key, keySize, value, valueSize);
 }
 
-static EGLsizei getBlob(const void* key, EGLsizei keySize, void* value,
-        EGLsizei valueSize) {
+static EGLsizeiANDROID getBlob(const void* key, EGLsizeiANDROID keySize,
+        void* value, EGLsizeiANDROID valueSize) {
     return egl_cache_t::get()->getBlob(key, keySize, value, valueSize);
 }
 
@@ -87,22 +87,23 @@
                     !strcmp(" " BC_EXT_STR, exts + extsLen - (bcExtLen+1));
             bool inMiddle = strstr(" " BC_EXT_STR " ", exts);
             if (equal || atStart || atEnd || inMiddle) {
-                PFNEGLSETBLOBCACHEFUNCSPROC eglSetBlobCacheFuncs;
-                eglSetBlobCacheFuncs =
-                        reinterpret_cast<PFNEGLSETBLOBCACHEFUNCSPROC>(
-                            cnx->egl.eglGetProcAddress("eglSetBlobCacheFuncs"));
-                if (eglSetBlobCacheFuncs == NULL) {
+                PFNEGLSETBLOBCACHEFUNCSANDROIDPROC eglSetBlobCacheFuncsANDROID;
+                eglSetBlobCacheFuncsANDROID =
+                        reinterpret_cast<PFNEGLSETBLOBCACHEFUNCSANDROIDPROC>(
+                            cnx->egl.eglGetProcAddress(
+                                    "eglSetBlobCacheFuncsANDROID"));
+                if (eglSetBlobCacheFuncsANDROID == NULL) {
                     LOGE("EGL_ANDROID_blob_cache advertised by display %d, "
-                            "but unable to get eglSetBlobCacheFuncs", i);
+                            "but unable to get eglSetBlobCacheFuncsANDROID", i);
                     continue;
                 }
 
-                eglSetBlobCacheFuncs(display->disp[i].dpy, android::setBlob,
-                        android::getBlob);
+                eglSetBlobCacheFuncsANDROID(display->disp[i].dpy,
+                        android::setBlob, android::getBlob);
                 EGLint err = cnx->egl.eglGetError();
                 if (err != EGL_SUCCESS) {
-                    LOGE("eglSetBlobCacheFuncs resulted in an error: %#x",
-                            err);
+                    LOGE("eglSetBlobCacheFuncsANDROID resulted in an error: "
+                            "%#x", err);
                 }
             }
         }
@@ -119,8 +120,8 @@
     mInitialized = false;
 }
 
-void egl_cache_t::setBlob(const void* key, EGLsizei keySize, const void* value,
-        EGLsizei valueSize) {
+void egl_cache_t::setBlob(const void* key, EGLsizeiANDROID keySize,
+        const void* value, EGLsizeiANDROID valueSize) {
     Mutex::Autolock lock(mMutex);
 
     if (keySize < 0 || valueSize < 0) {
@@ -158,8 +159,8 @@
     }
 }
 
-EGLsizei egl_cache_t::getBlob(const void* key, EGLsizei keySize, void* value,
-        EGLsizei valueSize) {
+EGLsizeiANDROID egl_cache_t::getBlob(const void* key, EGLsizeiANDROID keySize,
+        void* value, EGLsizeiANDROID valueSize) {
     Mutex::Autolock lock(mMutex);
 
     if (keySize < 0 || valueSize < 0) {
@@ -323,7 +324,8 @@
             return;
         }
 
-        status_t err = mBlobCache->unflatten(buf + headerSize, cacheSize, NULL, 0);
+        status_t err = mBlobCache->unflatten(buf + headerSize, cacheSize, NULL,
+                0);
         if (err != OK) {
             LOGE("error reading cache contents: %s (%d)", strerror(-err),
                     -err);
diff --git a/opengl/libs/EGL/egl_cache.h b/opengl/libs/EGL/egl_cache.h
index 4389623..8760009 100644
--- a/opengl/libs/EGL/egl_cache.h
+++ b/opengl/libs/EGL/egl_cache.h
@@ -52,14 +52,14 @@
     // setBlob attempts to insert a new key/value blob pair into the cache.
     // This will be called by the hardware vendor's EGL implementation via the
     // EGL_ANDROID_blob_cache extension.
-    void setBlob(const void* key, EGLsizei keySize, const void* value,
-        EGLsizei valueSize);
+    void setBlob(const void* key, EGLsizeiANDROID keySize, const void* value,
+        EGLsizeiANDROID valueSize);
 
     // getBlob attempts to retrieve the value blob associated with a given key
     // blob from cache.  This will be called by the hardware vendor's EGL
     // implementation via the EGL_ANDROID_blob_cache extension.
-    EGLsizei getBlob(const void* key, EGLsizei keySize, void* value,
-        EGLsizei valueSize);
+    EGLsizeiANDROID getBlob(const void* key, EGLsizeiANDROID keySize,
+        void* value, EGLsizeiANDROID valueSize);
 
     // setCacheFilename sets the name of the file that should be used to store
     // cache contents from one program invocation to another.
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 558ca77..2935832 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -62,11 +62,13 @@
     objects.remove(object);
 }
 
-bool egl_display_t::getObject(egl_object_t* object) {
+bool egl_display_t::getObject(egl_object_t* object) const {
     Mutex::Autolock _l(lock);
     if (objects.indexOf(object) >= 0) {
-        object->incRef();
-        return true;
+        if (object->getDisplay() == this) {
+            object->incRef();
+            return true;
+        }
     }
     return false;
 }
diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h
index e0a367d..94077be 100644
--- a/opengl/libs/EGL/egl_display.h
+++ b/opengl/libs/EGL/egl_display.h
@@ -81,7 +81,7 @@
     // remove object from this display's list
     void removeObject(egl_object_t* object);
     // add reference to this object. returns true if this is a valid object.
-    bool getObject(egl_object_t* object);
+    bool getObject(egl_object_t* object) const;
 
 
     static egl_display_t* get(EGLDisplay dpy);
@@ -119,9 +119,9 @@
     egl_config_t*   configs;
 
 private:
-    uint32_t        refs;
-    Mutex           lock;
-    SortedVector<egl_object_t*> objects;
+            uint32_t                    refs;
+    mutable Mutex                       lock;
+            SortedVector<egl_object_t*> objects;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp
index dbf9a01..20cdc7e 100644
--- a/opengl/libs/EGL/egl_object.cpp
+++ b/opengl/libs/EGL/egl_object.cpp
@@ -55,10 +55,10 @@
     }
 }
 
-bool egl_object_t::get() {
+bool egl_object_t::get(egl_display_t const* display, egl_object_t* object) {
     // used by LocalRef, this does an incRef() atomically with
     // checking that the object is valid.
-    return display->getObject(this);
+    return display->getObject(object);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h
index 46f7139..df1b261 100644
--- a/opengl/libs/EGL/egl_object.h
+++ b/opengl/libs/EGL/egl_object.h
@@ -52,10 +52,11 @@
 
     inline int32_t incRef() { return android_atomic_inc(&count); }
     inline int32_t decRef() { return android_atomic_dec(&count); }
+    inline egl_display_t* getDisplay() const { return display; }
 
 private:
     void terminate();
-    bool get();
+    static bool get(egl_display_t const* display, egl_object_t* object);
 
 public:
     template <typename N, typename T>
@@ -66,9 +67,9 @@
     public:
         ~LocalRef();
         explicit LocalRef(egl_object_t* rhs);
-        explicit LocalRef(T o) : ref(0) {
+        explicit LocalRef(egl_display_t const* display, T o) : ref(0) {
             egl_object_t* native = reinterpret_cast<N*>(o);
-            if (o && native->get()) {
+            if (o && egl_object_t::get(display, native)) {
                 ref = native;
             }
         }
diff --git a/opengl/specs/EGL_ANDROID_blob_cache.txt b/opengl/specs/EGL_ANDROID_blob_cache.txt
index 55dc900..61f45d3 100644
--- a/opengl/specs/EGL_ANDROID_blob_cache.txt
+++ b/opengl/specs/EGL_ANDROID_blob_cache.txt
@@ -63,33 +63,33 @@
 New Types
 
     /*
-     * EGLsizei is a signed integer type for representing the size of a memory
-     * buffer.
+     * EGLsizeiANDROID is a signed integer type for representing the size of a
+     * memory buffer.
      */
     #include <khrplatform.h>
-    typedef khronos_ssize_t EGLsizei;
+    typedef khronos_ssize_t EGLsizeiANDROID;
 
     /*
      * EGLSetBlobFunc is a pointer to an application-provided function that a
      * client API implementation may use to insert a key/value pair into the
      * cache.
      */
-    typedef void (*EGLSetBlobFunc) (const void* key, EGLsizei keySize,
-        const void* value, EGLsizei valueSize)
+    typedef void (*EGLSetBlobFuncANDROID) (const void* key,
+        EGLsizeiANDROID keySize, const void* value, EGLsizeiANDROID valueSize)
 
     /*
      * EGLGetBlobFunc is a pointer to an application-provided function that a
      * client API implementation may use to retrieve a cached value from the
      * cache.
      */
-    typedef EGLsizei (*EGLGetBlobFunc) (const void* key, EGLsizei keySize,
-        void* value, EGLsizei valueSize)
+    typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void* key,
+        EGLsizeiANDROID keySize, void* value, EGLsizeiANDROID valueSize)
 
 New Procedures and Functions
 
-    void eglSetBlobCacheFuncs(EGLDisplay dpy,
-                              EGLSetBlobFunc set,
-                              EGLGetBlobFunc get);
+    void eglSetBlobCacheFuncsANDROID(EGLDisplay dpy,
+                                     EGLSetBlobFunc set,
+                                     EGLGetBlobFunc get);
 
 New Tokens
 
@@ -107,8 +107,8 @@
     function pointers through which the client APIs can request data be cached
     and retrieved.  The command
 
-        void eglSetBlobCacheFuncs(EGLDisplay dpy,
-            EGLSetBlobFunc set, EGLGetBlobFunc get);
+        void eglSetBlobCacheFuncsANDROID(EGLDisplay dpy,
+            EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
 
     sets the callback function pointers that client APIs associated with
     display <dpy> can use to interact with caching functionality provided by
@@ -120,17 +120,17 @@
 
     Cache functions may only be specified once during the lifetime of an
     EGLDisplay.  The <set> and <get> functions may be called at any time and
-    from any thread from the time at which eglSetBlobCacheFuncs is called until
-    the time that the last resource associated with <dpy> is deleted and <dpy>
-    itself is terminated.  Concurrent calls to these functions from different
-    threads is also allowed.
+    from any thread from the time at which eglSetBlobCacheFuncsANDROID is
+    called until the time that the last resource associated with <dpy> is
+    deleted and <dpy> itself is terminated.  Concurrent calls to these
+    functions from different threads is also allowed.
 
-    If eglSetBlobCacheFuncs generates an error then all client APIs must behave
-    as though eglSetBlobCacheFuncs was not called for the display <dpy>.  If
-    <set> or <get> is NULL then an EGL_BAD_PARAMETER error is generated.  If a
-    successful eglSetBlobCacheFuncs call was already made for <dpy> and the
-    display has not since been terminated then an EGL_BAD_PARAMETER error is
-    generated.
+    If eglSetBlobCacheFuncsANDROID generates an error then all client APIs must
+    behave as though eglSetBlobCacheFuncsANDROID was not called for the display
+    <dpy>.  If <set> or <get> is NULL then an EGL_BAD_PARAMETER error is
+    generated.  If a successful eglSetBlobCacheFuncsANDROID call was already
+    made for <dpy> and the display has not since been terminated then an
+    EGL_BAD_PARAMETER error is generated.
 
     3.9.1 Cache Operations
 
@@ -138,8 +138,8 @@
     key, a client API implementation can call the application-provided callback
     function
 
-        void (*set) (const void* key, EGLsizei keySize, const void* value,
-            EGLsizei valueSize)
+        void (*set) (const void* key, EGLsizeiANDROID keySize,
+            const void* value, EGLsizeiANDROID valueSize)
 
     <key> and <value> are pointers to the beginning of the key and value,
     respectively, that are to be inserted.  <keySize> and <valueSize> specify
@@ -157,8 +157,8 @@
     client API implementation can call the application-provided callback
     function
 
-        EGLsizei (*get) (const void* key, EGLsizei keySize, void* value,
-            EGLsizei valueSize)
+        EGLsizeiANDROID (*get) (const void* key, EGLsizeiANDROID keySize,
+            void* value, EGLsizeiANDROID valueSize)
 
     <key> is a pointer to the beginning of the key.  <keySize> specifies the
     size in bytes of the binary key pointed to by <key>.  If the cache contains
diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
index 3ee9e77..180f022 100644
--- a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
@@ -33,39 +33,29 @@
         android:clipToPadding="false"
         android:clipChildren="false">
 
-        <LinearLayout android:id="@+id/recents_glow"
+        <com.android.systemui.recent.RecentsHorizontalScrollView android:id="@+id/recents_container"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
-            android:layout_gravity="bottom|right"
+            android:layout_marginRight="@dimen/status_bar_recents_right_glow_margin"
+            android:divider="@null"
+            android:stackFromBottom="true"
+            android:fadingEdge="horizontal"
+            android:scrollbars="none"
+            android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length"
+            android:layout_gravity="bottom|left"
             android:orientation="horizontal"
             android:clipToPadding="false"
-            android:clipChildren="false"
-            >
-            <com.android.systemui.recent.RecentsHorizontalScrollView android:id="@+id/recents_container"
+            android:clipChildren="false">
+
+            <LinearLayout android:id="@+id/recents_linear_layout"
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
-                android:layout_marginRight="@dimen/status_bar_recents_right_glow_margin"
-                android:divider="@null"
-                android:stackFromBottom="true"
-                android:fadingEdge="horizontal"
-                android:scrollbars="none"
-                android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length"
-                android:layout_gravity="bottom|left"
                 android:orientation="horizontal"
                 android:clipToPadding="false"
                 android:clipChildren="false">
+            </LinearLayout>
 
-                <LinearLayout android:id="@+id/recents_linear_layout"
-                    android:layout_width="wrap_content"
-                    android:layout_height="match_parent"
-                    android:orientation="horizontal"
-                    android:clipToPadding="false"
-                    android:clipChildren="false">
-                </LinearLayout>
-
-            </com.android.systemui.recent.RecentsHorizontalScrollView>
-
-        </LinearLayout>
+        </com.android.systemui.recent.RecentsHorizontalScrollView>
 
     </FrameLayout>
 
diff --git a/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml
index d040544..e6a077a 100644
--- a/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml
@@ -31,39 +31,29 @@
         android:layout_height="match_parent"
         android:layout_alignParentBottom="true">
 
-        <LinearLayout android:id="@+id/recents_glow"
+        <com.android.systemui.recent.RecentsVerticalScrollView
+            android:id="@+id/recents_container"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_gravity="bottom"
-            android:orientation="horizontal"
-            android:clipChildren="false"
-            android:layout_marginTop="@*android:dimen/status_bar_height">
+            android:layout_marginRight="0dp"
+            android:divider="@null"
+            android:stackFromBottom="true"
+            android:fadingEdge="vertical"
+            android:scrollbars="none"
+            android:fadingEdgeLength="@*android:dimen/status_bar_height"
+            android:layout_gravity="bottom|left"
+            android:clipToPadding="false"
+            android:clipChildren="false">
 
-            <com.android.systemui.recent.RecentsVerticalScrollView
-                android:id="@+id/recents_container"
+            <LinearLayout android:id="@+id/recents_linear_layout"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginRight="0dp"
-                android:divider="@null"
-                android:stackFromBottom="true"
-                android:fadingEdge="vertical"
-                android:scrollbars="none"
-                android:fadingEdgeLength="@*android:dimen/status_bar_height"
-                android:layout_gravity="bottom|left"
+                android:orientation="vertical"
                 android:clipToPadding="false"
                 android:clipChildren="false">
+            </LinearLayout>
 
-                <LinearLayout android:id="@+id/recents_linear_layout"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:orientation="vertical"
-                    android:clipToPadding="false"
-                    android:clipChildren="false">
-                </LinearLayout>
-
-            </com.android.systemui.recent.RecentsVerticalScrollView>
-
-        </LinearLayout>
+        </com.android.systemui.recent.RecentsVerticalScrollView>
 
     </FrameLayout>
 
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_no_recent_apps.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_no_recent_apps.xml
new file mode 100644
index 0000000..bc89281
--- /dev/null
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_no_recent_apps.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent"
+    >
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="20dp"
+        android:textColor="@android:color/holo_blue_light"
+        android:text="@string/status_bar_no_recent_apps"
+        android:gravity="left"
+        android:layout_gravity="bottom|left"
+    />
+</FrameLayout>
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml
index 18a31f7..cb26db00 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml
@@ -23,31 +23,6 @@
     android:layout_height="wrap_content"
     android:layout_width="wrap_content">
 
-    <FrameLayout android:id="@+id/app_thumbnail"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_alignParentLeft="true"
-        android:layout_alignParentTop="true"
-        android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin"
-        android:scaleType="center"
-        android:background="@drawable/recents_thumbnail_bg"
-        android:foreground="@drawable/recents_thumbnail_fg"
-        android:visibility="invisible">
-        <ImageView android:id="@+id/app_thumbnail_image"
-            android:layout_width="@dimen/status_bar_recents_thumbnail_width"
-            android:layout_height="@dimen/status_bar_recents_thumbnail_height"
-        />
-        <ImageView android:id="@+id/app_icon"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginLeft="@dimen/status_bar_recents_app_icon_left_margin"
-            android:layout_marginTop="@dimen/status_bar_recents_app_icon_top_margin"
-            android:maxWidth="@dimen/status_bar_recents_app_icon_max_width"
-            android:maxHeight="@dimen/status_bar_recents_app_icon_max_height"
-            android:adjustViewBounds="true"
-        />
-    </FrameLayout>
-
     <TextView android:id="@+id/app_label"
         android:layout_width="@dimen/status_bar_recents_app_label_width"
         android:layout_height="wrap_content"
@@ -64,6 +39,35 @@
         android:textColor="@color/status_bar_recents_app_label_color"
     />
 
+    <FrameLayout android:id="@+id/app_thumbnail"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_toRightOf="@id/app_label"
+        android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin"
+        android:scaleType="center"
+        android:background="@drawable/recents_thumbnail_bg"
+        android:foreground="@drawable/recents_thumbnail_fg"
+        android:visibility="invisible">
+        <ImageView android:id="@+id/app_thumbnail_image"
+            android:layout_width="@dimen/status_bar_recents_thumbnail_width"
+            android:layout_height="@dimen/status_bar_recents_thumbnail_height"
+        />
+    </FrameLayout>
+
+
+    <ImageView android:id="@+id/app_icon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_toRightOf="@id/app_label"
+        android:layout_marginLeft="@dimen/status_bar_recents_app_icon_left_margin"
+        android:layout_marginTop="@dimen/status_bar_recents_app_icon_top_margin"
+        android:maxWidth="@dimen/status_bar_recents_app_icon_max_width"
+        android:maxHeight="@dimen/status_bar_recents_app_icon_max_height"
+        android:scaleType="centerInside"
+        android:adjustViewBounds="true"
+    />
+
+
     <View android:id="@+id/recents_callout_line"
         android:layout_width="@dimen/status_bar_recents_app_label_width"
         android:layout_height="1dip"
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml
index 5dd101e..111f9a4 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_panel.xml
@@ -36,40 +36,36 @@
         android:clipToPadding="false"
         android:clipChildren="false">
 
-        <LinearLayout android:id="@+id/recents_glow"
+        <com.android.systemui.recent.RecentsVerticalScrollView android:id="@+id/recents_container"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginBottom="-49dip"
-            android:layout_gravity="bottom"
-            android:background="@drawable/recents_blue_glow"
-            android:orientation="horizontal"
+            android:layout_marginRight="@dimen/status_bar_recents_right_glow_margin"
+            android:divider="@null"
+            android:stackFromBottom="true"
+            android:fadingEdge="vertical"
+            android:scrollbars="none"
+            android:fadingEdgeLength="20dip"
+            android:layout_gravity="bottom|left"
             android:clipToPadding="false"
-            android:clipChildren="false"
-            >
-            <com.android.systemui.recent.RecentsVerticalScrollView android:id="@+id/recents_container"
+            android:clipChildren="false">
+
+            <LinearLayout android:id="@+id/recents_linear_layout"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginRight="@dimen/status_bar_recents_right_glow_margin"
-                android:divider="@null"
-                android:stackFromBottom="true"
-                android:fadingEdge="vertical"
-                android:scrollbars="none"
-                android:fadingEdgeLength="20dip"
-                android:layout_gravity="bottom|left"
+                android:orientation="vertical"
                 android:clipToPadding="false"
                 android:clipChildren="false">
+            </LinearLayout>
 
-                <LinearLayout android:id="@+id/recents_linear_layout"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:orientation="vertical"
-                    android:clipToPadding="false"
-                    android:clipChildren="false">
-                </LinearLayout>
+        </com.android.systemui.recent.RecentsVerticalScrollView>
 
-            </com.android.systemui.recent.RecentsVerticalScrollView>
-
-        </LinearLayout>
+        <include layout="@layout/status_bar_no_recent_apps"
+            android:id="@+id/recents_no_apps"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_marginLeft="58dip"
+            android:layout_marginBottom="36dip"
+            android:visibility="invisible" />
 
     </FrameLayout>
 
@@ -82,4 +78,5 @@
         android:contentDescription="@string/status_bar_accessibility_dismiss_recents"
     />
 
+
 </com.android.systemui.recent.RecentsPanelView>
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index af2c93c..b1aaade 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -31,21 +31,35 @@
     <LinearLayout android:id="@+id/icons"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:orientation="horizontal">
-            
-        <com.android.systemui.statusbar.phone.IconMerger android:id="@+id/notificationIcons"
+        android:paddingLeft="6dip"
+        android:paddingRight="6dip"
+        android:orientation="horizontal"
+        >
+
+        <LinearLayout
             android:layout_width="0dip"
-            android:layout_weight="1"
             android:layout_height="match_parent"
-            android:layout_alignParentLeft="true"
-            android:paddingLeft="6dip"
-            android:gravity="center_vertical"
-            android:orientation="horizontal"/>  
-            
+            android:layout_weight="1"
+            android:orientation="horizontal"
+            >
+            <com.android.systemui.statusbar.StatusBarIconView android:id="@+id/moreIcon"
+                android:layout_width="@dimen/status_bar_icon_size"
+                android:layout_height="match_parent"
+                android:src="@drawable/stat_notify_more"
+                android:visibility="gone"
+                />
+
+            <com.android.systemui.statusbar.phone.IconMerger android:id="@+id/notificationIcons"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_alignParentLeft="true"
+                android:gravity="center_vertical"
+                android:orientation="horizontal"/>  
+        </LinearLayout>
+
         <LinearLayout android:id="@+id/statusIcons"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
-            android:layout_alignParentRight="true"
             android:gravity="center_vertical"
             android:orientation="horizontal"/>    
 
@@ -53,7 +67,7 @@
             android:id="@+id/signal_battery_cluster"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
-            android:layout_marginRight="6dp"
+            android:paddingLeft="2dp"
             android:orientation="horizontal"
             android:gravity="center"
             >
@@ -66,7 +80,7 @@
                 android:id="@+id/battery"
                 android:layout_height="wrap_content"
                 android:layout_width="wrap_content"
-                android:paddingLeft="6dip"
+                android:paddingLeft="4dip"
                 />
         </LinearLayout>
 
@@ -76,7 +90,7 @@
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
             android:singleLine="true"
-            android:paddingRight="6dip"
+            android:paddingLeft="6dip"
             android:gravity="center_vertical|left"
             />
     </LinearLayout>
diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml
index 3e2ec59..24185a4f 100644
--- a/packages/SystemUI/res/values-sw600dp/config.xml
+++ b/packages/SystemUI/res/values-sw600dp/config.xml
@@ -18,8 +18,11 @@
 -->
 
 <resources>
-
     <!-- Whether we're using the tablet-optimized recents interface (we use this
      value at runtime for some things) -->
     <bool name="config_recents_interface_for_tablets">true</bool>
+
+    <!-- Whether recents thumbnails should stretch in both x and y to fill their
+     ImageView -->
+    <bool name="config_recents_thumbnail_image_fits_to_xy">true</bool>
 </resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index fe9245d..f522285 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -31,15 +31,15 @@
 
     <!-- Recent Applications parameters -->
     <!-- How far the thumbnail for a recent app appears from left edge -->
-    <dimen name="status_bar_recents_thumbnail_left_margin">121dp</dimen>
+    <dimen name="status_bar_recents_thumbnail_left_margin">28dp</dimen>
     <!-- Upper width limit for application icon -->
     <dimen name="status_bar_recents_app_icon_max_width">64dp</dimen>
     <!-- Upper height limit for application icon -->
     <dimen name="status_bar_recents_app_icon_max_height">64dp</dimen>
 
     <!-- Size of application icon -->
-    <dimen name="status_bar_recents_thumbnail_width">245dp</dimen>
-    <dimen name="status_bar_recents_thumbnail_height">144dp</dimen>
+    <dimen name="status_bar_recents_thumbnail_width">208dp</dimen>
+    <dimen name="status_bar_recents_thumbnail_height">130dp</dimen>
 
     <!-- Width of recents panel -->
     <dimen name="status_bar_recents_width">600dp</dimen>
@@ -59,8 +59,8 @@
     <dimen name="status_bar_recents_right_glow_margin">100dip</dimen>
 
     <!-- Where to place the app icon over the thumbnail -->
-    <dimen name="status_bar_recents_app_icon_left_margin">13dp</dimen>
-    <dimen name="status_bar_recents_app_icon_top_margin">13dp</dimen>
+    <dimen name="status_bar_recents_app_icon_left_margin">0dp</dimen>
+    <dimen name="status_bar_recents_app_icon_top_margin">8dp</dimen>
 
     <!-- size at which Notification icons will be drawn in the status bar -->
     <dimen name="status_bar_icon_drawing_size">24dip</dimen>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 1fe4ebb..1f22507 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -25,6 +25,10 @@
      value at runtime for some things) -->
     <bool name="config_recents_interface_for_tablets">false</bool>
 
+    <!-- Whether recents thumbnails should stretch in both x and y to fill their
+     ImageView -->
+    <bool name="config_recents_thumbnail_image_fits_to_xy">false</bool>
+
     <!-- Control whether status bar should distinguish HSPA data icon form UMTS
     data icon on devices -->
     <bool name="config_hspa_data_distinguishable">false</bool>
diff --git a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
index 886a14d..ad38a11 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
@@ -120,8 +120,13 @@
 
         createAnimation(appearing);
 
-        mContentView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
-        mContentView.buildLayer();
+        // isHardwareAccelerated() checks if we're attached to a window and if that
+        // window is HW accelerated-- we were sometimes not attached to a window
+        // and buildLayer was throwing an IllegalStateException
+        if (mContentView.isHardwareAccelerated()) {
+            mContentView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            mContentView.buildLayer();
+        }
         mContentAnim.start();
 
         mVisible = appearing;
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index 6b8b65e..8bfd711 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -16,14 +16,13 @@
 
 package com.android.systemui.recent;
 
-import java.util.ArrayList;
-
 import android.animation.Animator;
 import android.animation.LayoutTransition;
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Matrix;
 import android.graphics.Shader.TileMode;
@@ -42,15 +41,15 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.AnimationUtils;
 import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
 import android.widget.BaseAdapter;
 import android.widget.HorizontalScrollView;
 import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
 import android.widget.PopupMenu;
 import android.widget.RelativeLayout;
 import android.widget.ScrollView;
 import android.widget.TextView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.ImageView.ScaleType;
 
 import com.android.systemui.R;
 import com.android.systemui.statusbar.StatusBar;
@@ -58,6 +57,8 @@
 import com.android.systemui.statusbar.tablet.StatusBarPanel;
 import com.android.systemui.statusbar.tablet.TabletStatusBar;
 
+import java.util.ArrayList;
+
 public class RecentsPanelView extends RelativeLayout implements OnItemClickListener, RecentsCallback,
         StatusBarPanel, Animator.AnimatorListener, View.OnTouchListener {
     static final String TAG = "RecentsPanelView";
@@ -65,7 +66,6 @@
     private Context mContext;
     private StatusBar mBar;
     private View mRecentsScrim;
-    private View mRecentsGlowView;
     private View mRecentsNoApps;
     private ViewGroup mRecentsContainer;
 
@@ -79,6 +79,7 @@
     private boolean mRecentTasksDirty = true;
     private TaskDescriptionAdapter mListAdapter;
     private int mThumbnailWidth;
+    private boolean mFitThumbnailToXY;
 
     public void setRecentTasksLoader(RecentTasksLoader loader) {
         mRecentTasksLoader = loader;
@@ -174,9 +175,8 @@
         // use mRecentsContainer's exact bounds to determine horizontal position
         final int l = mRecentsContainer.getLeft();
         final int r = mRecentsContainer.getRight();
-        // use surrounding mRecentsGlowView's position in parent determine vertical bounds
-        final int t = mRecentsGlowView.getTop();
-        final int b = mRecentsGlowView.getBottom();
+        final int t = mRecentsContainer.getTop();
+        final int b = mRecentsContainer.getBottom();
         return x >= l && x < r && y >= t && y < b;
     }
 
@@ -194,7 +194,7 @@
             // if there are no apps, either bring up a "No recent apps" message, or just
             // quit early
             boolean noApps = (mRecentTaskDescriptions.size() == 0);
-            if (mRecentsNoApps != null) { // doesn't exist on large devices
+            if (mRecentsNoApps != null) {
                 mRecentsNoApps.setVisibility(noApps ? View.VISIBLE : View.INVISIBLE);
             } else {
                 if (noApps) {
@@ -325,8 +325,9 @@
     }
 
     public void updateValuesFromResources() {
-        mThumbnailWidth =
-            (int) mContext.getResources().getDimension(R.dimen.status_bar_recents_thumbnail_width);
+        final Resources res = mContext.getResources();
+        mThumbnailWidth = Math.round(res.getDimension(R.dimen.status_bar_recents_thumbnail_width));
+        mFitThumbnailToXY = res.getBoolean(R.bool.config_recents_thumbnail_image_fits_to_xy);
     }
 
     @Override
@@ -351,10 +352,9 @@
         }
 
 
-        mRecentsGlowView = findViewById(R.id.recents_glow);
         mRecentsScrim = findViewById(R.id.recents_bg_protect);
         mRecentsNoApps = findViewById(R.id.recents_no_apps);
-        mChoreo = new Choreographer(this, mRecentsScrim, mRecentsGlowView, mRecentsNoApps, this);
+        mChoreo = new Choreographer(this, mRecentsScrim, mRecentsContainer, mRecentsNoApps, this);
         mRecentsDismissButton = findViewById(R.id.recents_dismiss_button);
         if (mRecentsDismissButton != null) {
             mRecentsDismissButton.setOnClickListener(new OnClickListener() {
@@ -409,11 +409,15 @@
             if (h.thumbnailViewImageBitmap == null ||
                 h.thumbnailViewImageBitmap.getWidth() != thumbnail.getWidth() ||
                 h.thumbnailViewImageBitmap.getHeight() != thumbnail.getHeight()) {
-                Matrix scaleMatrix = new Matrix();
-                float scale = mThumbnailWidth / (float) thumbnail.getWidth();
-                scaleMatrix.setScale(scale, scale);
-                h.thumbnailViewImage.setScaleType(ScaleType.MATRIX);
-                h.thumbnailViewImage.setImageMatrix(scaleMatrix);
+                if (mFitThumbnailToXY) {
+                    h.thumbnailViewImage.setScaleType(ScaleType.FIT_XY);
+                } else {
+                    Matrix scaleMatrix = new Matrix();
+                    float scale = mThumbnailWidth / (float) thumbnail.getWidth();
+                    scaleMatrix.setScale(scale, scale);
+                    h.thumbnailViewImage.setScaleType(ScaleType.MATRIX);
+                    h.thumbnailViewImage.setImageMatrix(scaleMatrix);
+                }
             }
             if (show && h.thumbnailView.getVisibility() != View.VISIBLE) {
                 if (anim) {
@@ -444,7 +448,7 @@
                             // only fade in the thumbnail if recents is already visible-- we
                             // show it immediately otherwise
                             boolean animateShow = mShowing &&
-                                mRecentsGlowView.getAlpha() > ViewConfiguration.ALPHA_THRESHOLD;
+                                mRecentsContainer.getAlpha() > ViewConfiguration.ALPHA_THRESHOLD;
                             updateThumbnail(h, ad.getThumbnail(), true, animateShow);
                         }
                     }
@@ -516,7 +520,6 @@
         final int items = mRecentTaskDescriptions.size();
 
         mRecentsContainer.setVisibility(items > 0 ? View.VISIBLE : View.GONE);
-        mRecentsGlowView.setVisibility(items > 0 ? View.VISIBLE : View.GONE);
 
         // Set description for accessibility
         int numRecentApps = mRecentTaskDescriptions.size();
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index c259c28..ad37603 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -49,8 +49,6 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
-import android.view.animation.AccelerateInterpolator;
-import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
@@ -131,8 +129,8 @@
         // Show the intermediate notification
         mTickerAddSpace = !mTickerAddSpace;
         mNotificationId = nId;
+        mNotificationManager = nManager;
         mNotificationBuilder = new Notification.Builder(context)
-            .setLargeIcon(croppedIcon)
             .setTicker(r.getString(R.string.screenshot_saving_ticker)
                     + (mTickerAddSpace ? " " : ""))
             .setContentTitle(r.getString(R.string.screenshot_saving_title))
@@ -141,9 +139,12 @@
             .setWhen(System.currentTimeMillis());
         Notification n = mNotificationBuilder.getNotification();
         n.flags |= Notification.FLAG_NO_CLEAR;
-
-        mNotificationManager = nManager;
         mNotificationManager.notify(nId, n);
+
+        // On the tablet, the large icon makes the notification appear as if it is clickable (and
+        // on small devices, the large icon is not shown) so defer showing the large icon until
+        // we compose the final post-save notification below.
+        mNotificationBuilder.setLargeIcon(croppedIcon);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 6997837..8228df5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -25,6 +25,7 @@
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.text.TextUtils;
+import android.util.AttributeSet;
 import android.util.Slog;
 import android.util.Log;
 import android.view.ViewDebug;
@@ -75,6 +76,18 @@
         setScaleType(ImageView.ScaleType.CENTER);
     }
 
+    public StatusBarIconView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        final Resources res = context.getResources();
+        final int outerBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_size);
+        final int imageBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_drawing_size);
+        final float scale = (float)imageBounds / (float)outerBounds;
+        setScaleX(scale);
+        setScaleY(scale);
+        final float alpha = res.getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1);
+        setAlpha(alpha);
+    }
+
     private static boolean streq(String a, String b) {
         if (a == b) {
             return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java
index 20215bd..0640282 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java
@@ -30,113 +30,59 @@
 
 public class IconMerger extends LinearLayout {
     private static final String TAG = "IconMerger";
+    private static final boolean DEBUG = false;
 
     private int mIconSize;
-    private StatusBarIconView mMoreView;
-    private StatusBarIcon mMoreIcon = new StatusBarIcon(null, R.drawable.stat_notify_more, 0, 0,
-            null);
+    private View mMoreView;
 
     public IconMerger(Context context, AttributeSet attrs) {
         super(context, attrs);
 
         mIconSize = context.getResources().getDimensionPixelSize(
-                com.android.internal.R.dimen.status_bar_icon_size);
+                R.dimen.status_bar_icon_size);
 
-        mMoreView = new StatusBarIconView(context, "more", null);
-        mMoreView.set(mMoreIcon);
-        super.addView(mMoreView, 0, new LinearLayout.LayoutParams(mIconSize, mIconSize));
+        if (DEBUG) {
+            setBackgroundColor(0x800099FF);
+        }
     }
 
-    public void addView(StatusBarIconView v, int index, LinearLayout.LayoutParams p) {
-        super.addView(v, index+1, p);
+    public void setOverflowIndicator(View v) {
+        mMoreView = v;
     }
 
-    public void addView(StatusBarIconView v, int index) {
-        super.addView(v, index+1, new LinearLayout.LayoutParams(mIconSize, mIconSize));
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        // we need to constrain this to an integral multiple of our children
+        int width = getMeasuredWidth();
+        setMeasuredDimension(width - (width % mIconSize), getMeasuredHeight());
     }
 
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         super.onLayout(changed, l, t, r, b);
+        checkOverflow(r - l);
+    }
 
-        final int maxWidth = r - l;
+    private void checkOverflow(int width) {
+        if (mMoreView == null) return;
+
         final int N = getChildCount();
-        int i;
-
-        // get the rightmost one, and see if we even need to do anything
-        int fitRight = -1;
-        for (i=N-1; i>=0; i--) {
-            final View child = getChildAt(i);
-            if (child.getVisibility() != GONE) {
-                fitRight = child.getRight();
-                break;
-            }
+        int visibleChildren = 0;
+        for (int i=0; i<N; i++) {
+            if (getChildAt(i).getVisibility() != GONE) visibleChildren++;
         }
-
-        // find the first visible one that isn't the more icon
-        final StatusBarIconView moreView = mMoreView;
-        int fitLeft = -1;
-        int startIndex = -1;
-        for (i=0; i<N; i++) {
-            final View child = getChildAt(i);
-            if (child == moreView) {
-                startIndex = i+1;
-            }
-            else if (child.getVisibility() != GONE) {
-                fitLeft = child.getLeft();
-                break;
-            }
-        }
-
-        if (moreView == null || startIndex < 0) {
-            return;
-            /*
-            throw new RuntimeException("Status Bar / IconMerger moreView == " + moreView
-                    + " startIndex=" + startIndex);
-            */
-        }
-        
-        // if it fits without the more icon, then hide the more icon and update fitLeft
-        // so everything gets pushed left
-        int adjust = 0;
-        if (fitRight - fitLeft <= maxWidth) {
-            adjust = fitLeft - moreView.getLeft();
-            fitLeft -= adjust;
-            fitRight -= adjust;
-            moreView.layout(0, moreView.getTop(), 0, moreView.getBottom());
-        }
-        int extra = fitRight - r;
-        int shift = -1;
-
-        int breakingPoint = fitLeft + extra + adjust;
-        int number = 0;
-        for (i=startIndex; i<N; i++) {
-            final StatusBarIconView child = (StatusBarIconView)getChildAt(i);
-            if (child.getVisibility() != GONE) {
-                int childLeft = child.getLeft();
-                int childRight = child.getRight();
-                if (childLeft < breakingPoint) {
-                    // hide this one
-                    child.layout(0, child.getTop(), 0, child.getBottom());
-                    int n = child.getStatusBarIcon().number;
-                    if (n == 0) {
-                        number += 1;
-                    } else if (n > 0) {
-                        number += n;
-                    }
-                } else {
-                    // decide how much to shift by
-                    if (shift < 0) {
-                        shift = childLeft - fitLeft;
-                    }
-                    // shift this left by shift
-                    child.layout(childLeft-shift, child.getTop(),
-                                    childRight-shift, child.getBottom());
+        final boolean overflowShown = (mMoreView.getVisibility() == View.VISIBLE);
+        // let's assume we have one more slot if the more icon is already showing
+        if (overflowShown) visibleChildren --;
+        final boolean moreRequired = visibleChildren * mIconSize > width;
+        if (moreRequired != overflowShown) {
+            post(new Runnable() {
+                @Override
+                public void run() {
+                    mMoreView.setVisibility(moreRequired ? View.VISIBLE : View.GONE);
                 }
-            }
+            });
         }
-
-        mMoreIcon.number = number;
-        mMoreView.set(mMoreIcon);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 51fb262..b0554d0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -149,6 +149,7 @@
     // icons
     LinearLayout mIcons;
     IconMerger mNotificationIcons;
+    View mMoreIcon;
     LinearLayout mStatusIcons;
 
     // expanded notifications
@@ -307,6 +308,8 @@
         mPixelFormat = PixelFormat.OPAQUE;
         mStatusIcons = (LinearLayout)sb.findViewById(R.id.statusIcons);
         mNotificationIcons = (IconMerger)sb.findViewById(R.id.notificationIcons);
+        mMoreIcon = sb.findViewById(R.id.moreIcon);
+        mNotificationIcons.setOverflowIndicator(mMoreIcon);
         mIcons = (LinearLayout)sb.findViewById(R.id.icons);
         mTickerView = sb.findViewById(R.id.ticker);
 
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index 0f21bdb..dd3b75d 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -244,8 +244,14 @@
             // TODO: examine all widgets to derive clock status
             mUpdateMonitor.reportClockVisible(false);
 
-            // TODO: We should disable the wallpaper instead
-            setBackgroundColor(0xff000000);
+            // If there's not a bg protection view containing the transport, then show a black
+            // background. Otherwise, allow the normal background to show.
+            if (findViewById(R.id.transport_bg_protect) == null) {
+                // TODO: We should disable the wallpaper instead
+                setBackgroundColor(0xff000000);
+            } else {
+                resetBackground();
+            }
         }
 
         public void requestHide(View view) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 921f331..b4dd07b 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -3097,7 +3097,7 @@
                 sensorRotation = lastRotation;
             }
 
-            int preferredRotation = -1;
+            final int preferredRotation;
             if (mHdmiPlugged) {
                 // Ignore sensor when plugged into HDMI.
                 preferredRotation = mHdmiRotation;
@@ -3146,28 +3146,39 @@
             } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
                 // Apply rotation lock.
                 preferredRotation = mUserRotation;
+            } else {
+                // No overriding preference.
+                // We will do exactly what the application asked us to do.
+                preferredRotation = -1;
             }
 
-            // TODO: Sometimes, we might want to override the application-requested
-            //       orientation, such as when HDMI is plugged in or when docked.
-            //       We can do that by modifying the appropriate cases above to return
-            //       the preferred orientation directly instead of continuing on down here.
-
             switch (orientation) {
                 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
-                    // Always return portrait if orientation set to portrait.
+                    // Return portrait unless overridden.
+                    if (isAnyPortrait(preferredRotation)) {
+                        return preferredRotation;
+                    }
                     return mPortraitRotation;
 
                 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
-                    // Always return landscape if orientation set to landscape.
+                    // Return landscape unless overridden.
+                    if (isLandscapeOrSeascape(preferredRotation)) {
+                        return preferredRotation;
+                    }
                     return mLandscapeRotation;
 
                 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
-                    // Always return portrait if orientation set to portrait.
+                    // Return reverse portrait unless overridden.
+                    if (isAnyPortrait(preferredRotation)) {
+                        return preferredRotation;
+                    }
                     return mUpsideDownRotation;
 
                 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
-                    // Always return seascape if orientation set to reverse landscape.
+                    // Return seascape unless overridden.
+                    if (isLandscapeOrSeascape(preferredRotation)) {
+                        return preferredRotation;
+                    }
                     return mSeascapeRotation;
 
                 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index cd63090..b6f1184 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1248,15 +1248,23 @@
                         PrintWriter pw = new PrintWriter(sw);
                         StringWriter catSw = new StringWriter();
                         PrintWriter catPw = new PrintWriter(catSw);
-                        dumpApplicationMemoryUsage(null, pw, "  ", new String[] { }, true, catPw);
+                        String[] emptyArgs = new String[] { };
+                        StringBuilder tag = new StringBuilder(128);
+                        dumpProcessesLocked(null, catPw, emptyArgs, 0, false);
+                        catPw.println();
+                        dumpServicesLocked(null, catPw, emptyArgs, 0, false, false);
+                        catPw.println();
+                        dumpActivitiesLocked(null, catPw, emptyArgs, 0, false, false);
+                        catPw.println();
+                        tag.append("Low on memory -- ");
+                        dumpApplicationMemoryUsage(null, pw, "  ", emptyArgs, true, catPw, tag);
                         String memUsage = sw.toString();
                         dropBuilder.append('\n');
                         dropBuilder.append(memUsage);
                         dropBuilder.append(catSw.toString());
                         logBuilder.append(memUsage);
-                        addErrorToDropBox("watchdog", null, "system_server", null,
-                                null, "Low on memory -- no more background processes",
-                                dropBuilder.toString(), null, null);
+                        addErrorToDropBox("lowmem", null, "system_server", null,
+                                null, tag.toString(), dropBuilder.toString(), null, null);
                         Slog.i(TAG, logBuilder.toString());
                         synchronized (ActivityManagerService.this) {
                             long now = SystemClock.uptimeMillis();
@@ -1409,7 +1417,8 @@
                 return;
             }
 
-            mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, "  ", args, false, null);
+            mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, "  ", args,
+                    false, null, null);
         }
     }
 
@@ -1479,6 +1488,7 @@
 
         mConfiguration.setToDefaults();
         mConfiguration.locale = Locale.getDefault();
+        mConfigurationSeq = mConfiguration.seq = 1;
         mProcessStats.init();
         
         mCompatModePackages = new CompatModePackages(this, systemDir);
@@ -2436,7 +2446,7 @@
                     r.mayFreezeScreenLocked(r.app) ? r.appToken : null);
             if (config != null) {
                 r.frozenBeforeDestroy = true;
-                if (!updateConfigurationLocked(config, r, false)) {
+                if (!updateConfigurationLocked(config, r, false, false)) {
                     mMainStack.resumeTopActivityLocked(null);
                 }
             }
@@ -3797,7 +3807,7 @@
                     app.instrumentationClass, profileFile, profileFd, profileAutoStop,
                     app.instrumentationArguments, app.instrumentationWatcher, testMode, 
                     isRestrictedBackupMode || !normalMode, app.persistent,
-                    mConfiguration, app.compat, getCommonServicesLocked(),
+                    new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
                     mCoreSettingsObserver.getCoreSettingsLocked());
             updateLruProcessLocked(app, false, true);
             app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
@@ -6707,8 +6717,7 @@
             mAlwaysFinishActivities = alwaysFinishActivities;
             // This happens before any activities are started, so we can
             // change mConfiguration in-place.
-            mConfiguration.updateFrom(configuration);
-            mConfigurationSeq = mConfiguration.seq = 1;
+            updateConfigurationLocked(configuration, null, false, true);
             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
         }
     }
@@ -8789,6 +8798,20 @@
                         TimeUtils.formatDuration(r.createTime, nowReal, pw);
                         pw.print(" started="); pw.print(r.startRequested);
                         pw.print(" connections="); pw.println(r.connections.size());
+                    if (r.connections.size() > 0) {
+                        pw.println("    Connections:");
+                        for (ArrayList<ConnectionRecord> clist : r.connections.values()) {
+                            for (int i=0; i<clist.size(); i++) {
+                                ConnectionRecord conn = clist.get(i);
+                                pw.print("      ");
+                                pw.print(conn.binding.intent.intent.getIntent().toShortString(
+                                        false, false, false));
+                                pw.print(" -> ");
+                                ProcessRecord proc = conn.binding.client;
+                                pw.println(proc != null ? proc.toShortString() : "null");
+                            }
+                        }
+                    }
                 }
                 if (dumpClient && r.app != null && r.app.thread != null) {
                     pw.println("    Client:");
@@ -8908,18 +8931,21 @@
                     continue;
                 }
                 pw.print("  * "); pw.print(cls); pw.print(" (");
-                        pw.print(comp.flattenToShortString()); pw.print(")");
+                        pw.print(comp.flattenToShortString()); pw.println(")");
                 if (dumpAll) {
-                    pw.println();
                     r.dump(pw, "      ");
                 } else {
-                    pw.print("  * "); pw.print(e.getKey().flattenToShortString());
                     if (r.proc != null) {
-                        pw.println(":");
                         pw.print("      "); pw.println(r.proc);
                     } else {
                         pw.println();
                     }
+                    if (r.clients.size() > 0) {
+                        pw.println("      Clients:");
+                        for (ProcessRecord cproc : r.clients) {
+                            pw.print("        - "); pw.println(cproc);
+                        }
+                    }
                 }
             }
             needSep = true;
@@ -8937,8 +8963,8 @@
                     if (!matcher.match(r, r.name)) {
                         continue;
                     }
-                    pw.print("  "); pw.print(e.getKey()); pw.print(": ");
-                            pw.println(r);
+                    pw.print("  "); pw.print(e.getKey()); pw.println(":");
+                    pw.print("    "); pw.println(r);
                 }
                 needSep = true;
             }
@@ -9322,16 +9348,20 @@
 
     final static class MemItem {
         final String label;
+        final String shortLabel;
         final long pss;
+        final int id;
         ArrayList<MemItem> subitems;
 
-        public MemItem(String _label, long _pss) {
+        public MemItem(String _label, String _shortLabel, long _pss, int _id) {
             label = _label;
+            shortLabel = _shortLabel;
             pss = _pss;
+            id = _id;
         }
     }
 
-    final void dumpMemItems(PrintWriter pw, String prefix, ArrayList<MemItem> items,
+    static final void dumpMemItems(PrintWriter pw, String prefix, ArrayList<MemItem> items,
             boolean sort) {
         if (sort) {
             Collections.sort(items, new Comparator<MemItem>() {
@@ -9349,16 +9379,56 @@
 
         for (int i=0; i<items.size(); i++) {
             MemItem mi = items.get(i);
-            pw.print(prefix); pw.printf("%7d Kb: ", mi.pss); pw.println(mi.label);
+            pw.print(prefix); pw.printf("%7d kB: ", mi.pss); pw.println(mi.label);
             if (mi.subitems != null) {
                 dumpMemItems(pw, prefix + "           ", mi.subitems, true);
             }
         }
     }
 
+    // These are in KB.
+    static final long[] DUMP_MEM_BUCKETS = new long[] {
+        5*1024, 7*1024, 10*1024, 15*1024, 20*1024, 30*1024, 40*1024, 80*1024,
+        120*1024, 160*1024, 200*1024,
+        250*1024, 300*1024, 350*1024, 400*1024, 500*1024, 600*1024, 800*1024,
+        1*1024*1024, 2*1024*1024, 5*1024*1024, 10*1024*1024, 20*1024*1024
+    };
+
+    static final void appendMemBucket(StringBuilder out, long memKB, String label) {
+        int start = label.lastIndexOf('.');
+        if (start >= 0) start++;
+        else start = 0;
+        int end = label.length();
+        for (int i=0; i<DUMP_MEM_BUCKETS.length; i++) {
+            if (DUMP_MEM_BUCKETS[i] >= memKB) {
+                long bucket = DUMP_MEM_BUCKETS[i]/1024;
+                out.append(bucket);
+                out.append("MB ");
+                out.append(label, start, end);
+                return;
+            }
+        }
+        out.append(memKB/1024);
+        out.append("MB ");
+        out.append(label, start, end);
+    }
+
+    static final int[] DUMP_MEM_OOM_ADJ = new int[] {
+            ProcessList.SYSTEM_ADJ, ProcessList.PERSISTENT_PROC_ADJ, ProcessList.FOREGROUND_APP_ADJ,
+            ProcessList.VISIBLE_APP_ADJ, ProcessList.PERCEPTIBLE_APP_ADJ, ProcessList.HEAVY_WEIGHT_APP_ADJ,
+            ProcessList.BACKUP_APP_ADJ, ProcessList.SERVICE_ADJ, ProcessList.HOME_APP_ADJ,
+            ProcessList.PREVIOUS_APP_ADJ, ProcessList.SERVICE_B_ADJ, ProcessList.HIDDEN_APP_MAX_ADJ
+    };
+    static final String[] DUMP_MEM_OOM_LABEL = new String[] {
+            "System", "Persistent", "Foreground",
+            "Visible", "Perceptible", "Heavy Weight",
+            "Backup", "A Services", "Home", "Previous",
+            "B Services", "Background"
+    };
+
     final void dumpApplicationMemoryUsage(FileDescriptor fd,
             PrintWriter pw, String prefix, String[] args, boolean brief,
-            PrintWriter categoryPw) {
+            PrintWriter categoryPw, StringBuilder outTag) {
         boolean dumpAll = false;
         boolean oomOnly = false;
         
@@ -9414,20 +9484,9 @@
         long nativePss=0, dalvikPss=0, otherPss=0;
         long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
 
-        final int[] oomAdj = new int[] {
-            ProcessList.SYSTEM_ADJ, ProcessList.PERSISTENT_PROC_ADJ, ProcessList.FOREGROUND_APP_ADJ,
-            ProcessList.VISIBLE_APP_ADJ, ProcessList.PERCEPTIBLE_APP_ADJ, ProcessList.HEAVY_WEIGHT_APP_ADJ,
-            ProcessList.BACKUP_APP_ADJ, ProcessList.SERVICE_ADJ, ProcessList.HOME_APP_ADJ,
-            ProcessList.PREVIOUS_APP_ADJ, ProcessList.SERVICE_B_ADJ, ProcessList.HIDDEN_APP_MAX_ADJ
-        };
-        final String[] oomLabel = new String[] {
-                "System", "Persistent", "Foreground",
-                "Visible", "Perceptible", "Heavy Weight",
-                "Backup", "A Services", "Home", "Previous",
-                "B Services", "Background"
-        };
-        long oomPss[] = new long[oomLabel.length];
-        ArrayList<MemItem>[] oomProcs = (ArrayList<MemItem>[])new ArrayList[oomLabel.length];
+        long oomPss[] = new long[DUMP_MEM_OOM_LABEL.length];
+        ArrayList<MemItem>[] oomProcs = (ArrayList<MemItem>[])
+                new ArrayList[DUMP_MEM_OOM_LABEL.length];
 
         long totalPss = 0;
 
@@ -9457,7 +9516,7 @@
                     long myTotalPss = mi.getTotalPss();
                     totalPss += myTotalPss;
                     MemItem pssItem = new MemItem(r.processName + " (pid " + r.pid + ")",
-                            myTotalPss);
+                            r.processName, myTotalPss, 0);
                     procMems.add(pssItem);
 
                     nativePss += mi.nativePss;
@@ -9470,7 +9529,8 @@
                     }
 
                     for (int oomIndex=0; oomIndex<oomPss.length; oomIndex++) {
-                        if (r.setAdj <= oomAdj[oomIndex] || oomIndex == (oomPss.length-1)) {
+                        if (r.setAdj <= DUMP_MEM_OOM_ADJ[oomIndex]
+                                || oomIndex == (oomPss.length-1)) {
                             oomPss[oomIndex] += myTotalPss;
                             if (oomProcs[oomIndex] == null) {
                                 oomProcs[oomIndex] = new ArrayList<MemItem>();
@@ -9486,22 +9546,47 @@
         if (!isCheckinRequest && procs.size() > 1) {
             ArrayList<MemItem> catMems = new ArrayList<MemItem>();
 
-            catMems.add(new MemItem("Native", nativePss));
-            catMems.add(new MemItem("Dalvik", dalvikPss));
-            catMems.add(new MemItem("Unknown", otherPss));
+            catMems.add(new MemItem("Native", "Native", nativePss, -1));
+            catMems.add(new MemItem("Dalvik", "Dalvik", dalvikPss, -2));
+            catMems.add(new MemItem("Unknown", "Unknown", otherPss, -3));
             for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
-                catMems.add(new MemItem(Debug.MemoryInfo.getOtherLabel(j), miscPss[j]));
+                String label = Debug.MemoryInfo.getOtherLabel(j);
+                catMems.add(new MemItem(label, label, miscPss[j], j));
             }
 
             ArrayList<MemItem> oomMems = new ArrayList<MemItem>();
             for (int j=0; j<oomPss.length; j++) {
                 if (oomPss[j] != 0) {
-                    MemItem item = new MemItem(oomLabel[j], oomPss[j]);
+                    String label = DUMP_MEM_OOM_LABEL[j];
+                    MemItem item = new MemItem(label, label, oomPss[j],
+                            DUMP_MEM_OOM_ADJ[j]);
                     item.subitems = oomProcs[j];
                     oomMems.add(item);
                 }
             }
 
+            if (outTag != null) {
+                appendMemBucket(outTag, totalPss, "total");
+                for (int i=0; i<oomMems.size(); i++) {
+                    MemItem miCat = oomMems.get(i);
+                    if (miCat.subitems == null || miCat.subitems.size() < 1) {
+                        continue;
+                    }
+                    if (miCat.id < ProcessList.SERVICE_ADJ
+                            || miCat.id == ProcessList.HOME_APP_ADJ
+                            || miCat.id == ProcessList.PREVIOUS_APP_ADJ) {
+                        outTag.append(" / ");
+                        for (int j=0; j<miCat.subitems.size(); j++) {
+                            MemItem mi = miCat.subitems.get(j);
+                            if (j > 0) {
+                                outTag.append(" ");
+                            }
+                            appendMemBucket(outTag, mi.pss, mi.shortLabel);
+                        }
+                    }
+                }
+            }
+
             if (!brief && !oomOnly) {
                 pw.println();
                 pw.println("Total PSS by process:");
@@ -9517,7 +9602,7 @@
                 dumpMemItems(out, "  ", catMems, true);
             }
             pw.println();
-            pw.print("Total PSS: "); pw.print(totalPss); pw.println(" Kb");
+            pw.print("Total PSS: "); pw.print(totalPss); pw.println(" kB");
         }
     }
 
@@ -12934,7 +13019,7 @@
 
         synchronized(this) {
             final long origId = Binder.clearCallingIdentity();
-            updateConfigurationLocked(values, null, true);
+            updateConfigurationLocked(values, null, true, false);
             Binder.restoreCallingIdentity(origId);
         }
     }
@@ -12957,7 +13042,7 @@
             if (values != null) {
                 Settings.System.clearConfiguration(values);
             }
-            updateConfigurationLocked(values, null, false);
+            updateConfigurationLocked(values, null, false, false);
             Binder.restoreCallingIdentity(origId);
         }
     }
@@ -12971,7 +13056,7 @@
      * @param persistent TODO
      */
     public boolean updateConfigurationLocked(Configuration values,
-            ActivityRecord starting, boolean persistent) {
+            ActivityRecord starting, boolean persistent, boolean initLocale) {
         int changes = 0;
         
         boolean kept = true;
@@ -12986,7 +13071,7 @@
                 
                 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
 
-                if (values.locale != null) {
+                if (values.locale != null && !initLocale) {
                     saveLocaleLocked(values.locale, 
                                      !values.locale.equals(mConfiguration.locale),
                                      values.userSetLocale);
@@ -12999,10 +13084,12 @@
                 newConfig.seq = mConfigurationSeq;
                 mConfiguration = newConfig;
                 Slog.i(TAG, "Config changed: " + newConfig);
-                
+
+                final Configuration configCopy = new Configuration(mConfiguration);
+
                 AttributeCache ac = AttributeCache.instance();
                 if (ac != null) {
-                    ac.updateConfiguration(mConfiguration);
+                    ac.updateConfiguration(configCopy);
                 }
 
                 // Make sure all resources in our process are updated
@@ -13012,11 +13099,11 @@
                 // boot, where the first config change needs to guarantee
                 // all resources have that config before following boot
                 // code is executed.
-                mSystemThread.applyConfigurationToResources(newConfig);
+                mSystemThread.applyConfigurationToResources(configCopy);
 
                 if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
                     Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
-                    msg.obj = new Configuration(mConfiguration);
+                    msg.obj = new Configuration(configCopy);
                     mHandler.sendMessage(msg);
                 }
         
@@ -13026,7 +13113,7 @@
                         if (app.thread != null) {
                             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
                                     + app.processName + " new config " + mConfiguration);
-                            app.thread.scheduleConfigurationChanged(mConfiguration);
+                            app.thread.scheduleConfigurationChanged(configCopy);
                         }
                     } catch (Exception e) {
                     }
@@ -13965,7 +14052,6 @@
         // application processes based on their current state.
         int i = mLruProcesses.size();
         int curHiddenAdj = ProcessList.HIDDEN_APP_MIN_ADJ;
-        int numBg = 0;
         while (i > 0) {
             i--;
             ProcessRecord app = mLruProcesses.get(i);
@@ -13989,12 +14075,7 @@
                                 app.processName, app.setAdj, "too many background");
                         app.killedBackground = true;
                         Process.killProcessQuiet(app.pid);
-                    } else {
-                        numBg++;
                     }
-                } else if (app.curAdj >= ProcessList.HOME_APP_ADJ
-                        && app.curAdj != ProcessList.SERVICE_B_ADJ) {
-                    numBg++;
                 }
             }
         }
@@ -14009,12 +14090,18 @@
         // memory they want.
         if (numHidden <= (ProcessList.MAX_HIDDEN_APPS/2)) {
             final int N = mLruProcesses.size();
-            factor = numBg/3;
+            factor = numHidden/3;
+            int minFactor = 2;
+            if (mHomeProcess != null) minFactor++;
+            if (mPreviousProcess != null) minFactor++;
+            if (factor < minFactor) factor = minFactor;
             step = 0;
             int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
             for (i=0; i<N; i++) {
                 ProcessRecord app = mLruProcesses.get(i);
-                if (app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ && !app.killedBackground) {
+                if (app.curAdj >= ProcessList.HOME_APP_ADJ
+                        && app.curAdj != ProcessList.SERVICE_B_ADJ
+                        && !app.killedBackground) {
                     if (app.trimMemoryLevel < curLevel && app.thread != null) {
                         try {
                             app.thread.scheduleTrimMemory(curLevel);
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index c892cb1..c7ce3c3 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -528,7 +528,7 @@
             Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(
                     mService.mConfiguration,
                     r.mayFreezeScreenLocked(app) ? r.appToken : null);
-            mService.updateConfigurationLocked(config, r, false);
+            mService.updateConfigurationLocked(config, r, false, false);
         }
 
         r.app = app;
@@ -590,7 +590,8 @@
                 }
             }
             app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
-                    System.identityHashCode(r), r.info, mService.mConfiguration,
+                    System.identityHashCode(r), r.info,
+                    new Configuration(mService.mConfiguration),
                     r.compat, r.icicle, results, newIntents, !andResume,
                     mService.isNextTransitionForward(), profileFile, profileFd,
                     profileAutoStop);
@@ -1460,7 +1461,7 @@
                     if (config != null) {
                         next.frozenBeforeDestroy = true;
                     }
-                    updated = mService.updateConfigurationLocked(config, next, false);
+                    updated = mService.updateConfigurationLocked(config, next, false, false);
                 }
             }
             if (!updated) {
@@ -2917,7 +2918,7 @@
                 mConfigWillChange = false;
                 if (DEBUG_CONFIGURATION) Slog.v(TAG,
                         "Updating to new configuration after starting activity.");
-                mService.updateConfigurationLocked(config, null, false);
+                mService.updateConfigurationLocked(config, null, false, false);
             }
             
             Binder.restoreCallingIdentity(origId);
@@ -4190,7 +4191,7 @@
             if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
             r.forceNewConfig = false;
             r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents,
-                    changes, !andResume, mService.mConfiguration);
+                    changes, !andResume, new Configuration(mService.mConfiguration));
             // Note: don't need to call pauseIfSleepingLocked() here, because
             // the caller will only pass in 'andResume' if this activity is
             // currently resumed, which implies we aren't sleeping.
diff --git a/services/java/com/android/server/am/ContentProviderRecord.java b/services/java/com/android/server/am/ContentProviderRecord.java
index 9c55597..38355537 100644
--- a/services/java/com/android/server/am/ContentProviderRecord.java
+++ b/services/java/com/android/server/am/ContentProviderRecord.java
@@ -73,12 +73,15 @@
                     pw.print("multiprocess="); pw.print(info.multiprocess);
                     pw.print(" initOrder="); pw.println(info.initOrder);
         }
-        if (clients.size() > 0) {
-            pw.print(prefix); pw.print("clients="); pw.println(clients);
-        }
         if (externals != 0) {
             pw.print(prefix); pw.print("externals="); pw.println(externals);
         }
+        if (clients.size() > 0) {
+            pw.print(prefix); pw.println("Clients:");
+            for (ProcessRecord cproc : clients) {
+                pw.print(prefix); pw.print("  - "); pw.println(cproc.toShortString());
+            }
+        }
     }
 
     public String toString() {
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index 6365525..28cb983 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -1243,7 +1243,8 @@
 
         // trim any history beyond max
         if (mTime.hasCache()) {
-            final long currentTime = mTime.currentTimeMillis();
+            final long currentTime = Math.min(
+                    System.currentTimeMillis(), mTime.currentTimeMillis());
             final long maxHistory = mSettings.getNetworkMaxHistory();
             for (NetworkStatsHistory history : input.values()) {
                 history.removeBucketsBefore(currentTime - maxHistory);
@@ -1287,7 +1288,8 @@
 
         // trim any history beyond max
         if (mTime.hasCache()) {
-            final long currentTime = mTime.currentTimeMillis();
+            final long currentTime = Math.min(
+                    System.currentTimeMillis(), mTime.currentTimeMillis());
             final long maxUidHistory = mSettings.getUidMaxHistory();
             final long maxTagHistory = mSettings.getTagMaxHistory();
             for (UidStatsKey key : mUidStats.keySet()) {
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 50321b3..ebb13d5 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -5090,10 +5090,22 @@
 
             // Constrain thumbnail to smaller of screen width or height. Assumes aspect
             // of thumbnail is the same as the screen (in landscape) or square.
+            float targetWidthScale = width / (float) fw;
+            float targetHeightScale = height / (float) fh;
             if (dw <= dh) {
-                scale = width / (float) fw; // portrait
+                scale = targetWidthScale;
+                // If aspect of thumbnail is the same as the screen (in landscape),
+                // select the slightly larger value so we fill the entire bitmap
+                if (targetHeightScale > scale && (int) (targetHeightScale * fw) == width) {
+                    scale = targetHeightScale;
+                }
             } else {
-                scale = height / (float) fh; // landscape
+                scale = targetHeightScale;
+                // If aspect of thumbnail is the same as the screen (in landscape),
+                // select the slightly larger value so we fill the entire bitmap
+                if (targetWidthScale > scale && (int) (targetWidthScale * fh) == height) {
+                    scale = targetWidthScale;
+                }
             }
 
             // The screen shot will contain the entire screen.
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 368595f..0618374 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -80,7 +80,6 @@
 import org.easymock.Capture;
 import org.easymock.EasyMock;
 import org.easymock.IAnswer;
-import org.easymock.IExpectationSetters;
 
 import java.io.File;
 import java.util.LinkedHashSet;
@@ -537,6 +536,7 @@
                 .addIfaceValues(TEST_IFACE, 256L, 2L, 256L, 2L);
         expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
                 .andReturn(stats).atLeastOnce();
+        expectPolicyDataEnable(TYPE_WIFI, true);
 
         // TODO: consider making strongly ordered mock
         expectRemoveInterfaceQuota(TEST_IFACE);
@@ -580,7 +580,7 @@
         NetworkState[] state = null;
         NetworkStats stats = null;
         Future<Void> future;
-        Capture<String> tag;
+        Future<String> tagFuture;
 
         final long TIME_FEB_15 = 1171497600000L;
         final long TIME_MAR_10 = 1173484800000L;
@@ -598,6 +598,7 @@
             expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
             expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
                     .andReturn(stats).atLeastOnce();
+            expectPolicyDataEnable(TYPE_WIFI, true);
 
             expectClearNotifications();
             future = expectMeteredIfacesChanged();
@@ -620,6 +621,7 @@
             expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
             expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
                     .andReturn(stats).atLeastOnce();
+            expectPolicyDataEnable(TYPE_WIFI, true);
 
             expectRemoveInterfaceQuota(TEST_IFACE);
             expectSetInterfaceQuota(TEST_IFACE, 2 * MB_IN_BYTES);
@@ -642,14 +644,15 @@
             expectCurrentTime();
             expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
                     .andReturn(stats).atLeastOnce();
+            expectPolicyDataEnable(TYPE_WIFI, true);
 
             expectForceUpdate();
             expectClearNotifications();
-            tag = expectEnqueueNotification();
+            tagFuture = expectEnqueueNotification();
 
             replay();
             mNetworkObserver.limitReached(null, TEST_IFACE);
-            assertNotificationType(TYPE_WARNING, tag.getValue());
+            assertNotificationType(TYPE_WARNING, tagFuture.get());
             verifyAndReset();
         }
 
@@ -662,15 +665,15 @@
             expectCurrentTime();
             expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
                     .andReturn(stats).atLeastOnce();
-            expectPolicyDataEnable(TYPE_WIFI, false).atLeastOnce();
+            expectPolicyDataEnable(TYPE_WIFI, false);
 
             expectForceUpdate();
             expectClearNotifications();
-            tag = expectEnqueueNotification();
+            tagFuture = expectEnqueueNotification();
 
             replay();
             mNetworkObserver.limitReached(null, TEST_IFACE);
-            assertNotificationType(TYPE_LIMIT, tag.getValue());
+            assertNotificationType(TYPE_LIMIT, tagFuture.get());
             verifyAndReset();
         }
 
@@ -682,21 +685,20 @@
             expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
             expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
                     .andReturn(stats).atLeastOnce();
-            expectPolicyDataEnable(TYPE_WIFI, true).atLeastOnce();
+            expectPolicyDataEnable(TYPE_WIFI, true);
 
             // snoozed interface still has high quota so background data is
             // still restricted.
             expectRemoveInterfaceQuota(TEST_IFACE);
             expectSetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
+            expectMeteredIfacesChanged(TEST_IFACE);
 
             expectClearNotifications();
-            tag = expectEnqueueNotification();
-            future = expectMeteredIfacesChanged(TEST_IFACE);
+            tagFuture = expectEnqueueNotification();
 
             replay();
             mService.snoozePolicy(sTemplateWifi);
-            future.get();
-            assertNotificationType(TYPE_LIMIT_SNOOZED, tag.getValue());
+            assertNotificationType(TYPE_LIMIT_SNOOZED, tagFuture.get());
             verifyAndReset();
         }
     }
@@ -737,9 +739,9 @@
         expectLastCall().anyTimes();
     }
 
-    private Capture<String> expectEnqueueNotification() throws Exception {
-        final Capture<String> tag = new Capture<String>();
-        mNotifManager.enqueueNotificationWithTag(isA(String.class), capture(tag), anyInt(),
+    private Future<String> expectEnqueueNotification() throws Exception {
+        final FutureCapture<String> tag = new FutureCapture<String>();
+        mNotifManager.enqueueNotificationWithTag(isA(String.class), capture(tag.capture), anyInt(),
                 isA(Notification.class), isA(int[].class));
         return tag;
     }
@@ -789,22 +791,25 @@
         return future;
     }
 
-    private <T> IExpectationSetters<T> expectPolicyDataEnable(int type, boolean enabled)
-            throws Exception {
+    private Future<Void> expectPolicyDataEnable(int type, boolean enabled) throws Exception {
+        final FutureAnswer future = new FutureAnswer();
         mConnManager.setPolicyDataEnable(type, enabled);
-        return expectLastCall();
+        expectLastCall().andAnswer(future);
+        return future;
     }
 
-    private static class FutureAnswer extends AbstractFuture<Void> implements IAnswer<Void> {
+    private static class TestAbstractFuture<T> extends AbstractFuture<T> {
         @Override
-        public Void get() throws InterruptedException, ExecutionException {
+        public T get() throws InterruptedException, ExecutionException {
             try {
                 return get(5, TimeUnit.SECONDS);
             } catch (TimeoutException e) {
                 throw new RuntimeException(e);
             }
         }
+    }
 
+    private static class FutureAnswer extends TestAbstractFuture<Void> implements IAnswer<Void> {
         @Override
         public Void answer() {
             set(null);
@@ -812,6 +817,16 @@
         }
     }
 
+    private static class FutureCapture<T> extends TestAbstractFuture<T> {
+        public Capture<T> capture = new Capture<T>() {
+            @Override
+            public void setValue(T value) {
+                super.setValue(value);
+                set(value);
+            }
+        };
+    }
+
     private static class IdleFuture extends AbstractFuture<Void> implements IdleHandler {
         @Override
         public Void get() throws InterruptedException, ExecutionException {