Merge "Fix ThreadedRenderer.setEnabled()"
diff --git a/core/jni/android_util_EventLog.cpp b/core/jni/android_util_EventLog.cpp
index 2593420..8a0eaa2 100644
--- a/core/jni/android_util_EventLog.cpp
+++ b/core/jni/android_util_EventLog.cpp
@@ -177,13 +177,13 @@
             break;
         }
         if (ret < 0) {
-            if (errno == EINTR) {
+            if (ret == -EINTR) {
                 continue;
             }
-            if (errno == EINVAL) {
+            if (ret == -EINVAL) {
                 jniThrowException(env, "java/io/IOException", "Event too short");
-            } else if (errno != EAGAIN) {
-                jniThrowIOException(env, errno);  // Will throw on return
+            } else if (ret != -EAGAIN) {
+                jniThrowIOException(env, -ret);  // Will throw on return
             }
             break;
         }
diff --git a/media/java/android/media/MediaFocusControl.java b/media/java/android/media/MediaFocusControl.java
index f688d81..664c707 100644
--- a/media/java/android/media/MediaFocusControl.java
+++ b/media/java/android/media/MediaFocusControl.java
@@ -471,10 +471,6 @@
                 final FocusRequester exFocusOwner = mFocusStack.pop();
                 exFocusOwner.handleFocusLoss(AudioManager.AUDIOFOCUS_LOSS);
                 exFocusOwner.release();
-                // clear RCD
-                synchronized(mPRStack) {
-                    clearRemoteControlDisplay_syncAfRcs();
-                }
             }
         }
     }
@@ -535,10 +531,6 @@
             if (signal) {
                 // notify the new top of the stack it gained focus
                 notifyTopOfAudioFocusStack();
-                // there's a new top of the stack, let the remote control know
-                synchronized(mPRStack) {
-                    checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
-                }
             }
         } else {
             // focus is abandoned by a client that's not at the top of the stack,
@@ -582,10 +574,6 @@
             // we removed an entry at the top of the stack:
             //  notify the new top of the stack it gained focus.
             notifyTopOfAudioFocusStack();
-            // there's a new top of the stack, let the remote control know
-            synchronized(mPRStack) {
-                checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
-            }
         }
     }
 
@@ -694,10 +682,6 @@
             mFocusStack.push(new FocusRequester(mainStreamType, focusChangeHint, fd, cb,
                     clientId, afdh, callingPackageName, Binder.getCallingUid()));
 
-            // there's a new top of the stack, let the remote control know
-            synchronized(mPRStack) {
-                checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
-            }
         }//synchronized(mAudioFocusLock)
 
         return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
@@ -1237,11 +1221,11 @@
     /**
      * Helper function:
      * Set the new remote control receiver at the top of the RC focus stack.
-     * Called synchronized on mAudioFocusLock, then mPRStack
+     * Called synchronized on mPRStack
      * precondition: mediaIntent != null
      * @return true if mPRStack was changed, false otherwise
      */
-    private boolean pushMediaButtonReceiver_syncAfRcs(PendingIntent mediaIntent,
+    private boolean pushMediaButtonReceiver_syncPrs(PendingIntent mediaIntent,
             ComponentName target, IBinder token) {
         // already at top of stack?
         if (!mPRStack.empty() && mPRStack.peek().hasMatchingMediaButtonIntent(mediaIntent)) {
@@ -1285,10 +1269,10 @@
     /**
      * Helper function:
      * Remove the remote control receiver from the RC focus stack.
-     * Called synchronized on mAudioFocusLock, then mPRStack
+     * Called synchronized on mPRStack
      * precondition: pi != null
      */
-    private void removeMediaButtonReceiver_syncAfRcs(PendingIntent pi) {
+    private void removeMediaButtonReceiver_syncPrs(PendingIntent pi) {
         try {
             for (int index = mPRStack.size()-1; index >= 0; index--) {
                 final PlayerRecord prse = mPRStack.elementAt(index);
@@ -1470,7 +1454,7 @@
      * Helper function:
      * Called synchronized on mPRStack
      */
-    private void clearRemoteControlDisplay_syncAfRcs() {
+    private void clearRemoteControlDisplay_syncPrs() {
         synchronized(mCurrentRcLock) {
             mCurrentRcClient = null;
         }
@@ -1480,20 +1464,20 @@
 
     /**
      * Helper function for code readability: only to be called from
-     *    checkUpdateRemoteControlDisplay_syncAfRcs() which checks the preconditions for
+     *    checkUpdateRemoteControlDisplay_syncPrs() which checks the preconditions for
      *    this method.
      * Preconditions:
-     *    - called synchronized mAudioFocusLock then on mPRStack
+     *    - called synchronized on mPRStack
      *    - mPRStack.isEmpty() is false
      */
-    private void updateRemoteControlDisplay_syncAfRcs(int infoChangedFlags) {
+    private void updateRemoteControlDisplay_syncPrs(int infoChangedFlags) {
         PlayerRecord prse = mPRStack.peek();
         int infoFlagsAboutToBeUsed = infoChangedFlags;
         // this is where we enforce opt-in for information display on the remote controls
         //   with the new AudioManager.registerRemoteControlClient() API
         if (prse.getRcc() == null) {
             //Log.w(TAG, "Can't update remote control display with null remote control client");
-            clearRemoteControlDisplay_syncAfRcs();
+            clearRemoteControlDisplay_syncPrs();
             return;
         }
         synchronized(mCurrentRcLock) {
@@ -1511,62 +1495,25 @@
 
     /**
      * Helper function:
-     * Called synchronized on mAudioFocusLock, then mPRStack
+     * Called synchronized on mPRStack
      * Check whether the remote control display should be updated, triggers the update if required
      * @param infoChangedFlags the flags corresponding to the remote control client information
      *     that has changed, if applicable (checking for the update conditions might trigger a
      *     clear, rather than an update event).
      */
-    private void checkUpdateRemoteControlDisplay_syncAfRcs(int infoChangedFlags) {
+    private void checkUpdateRemoteControlDisplay_syncPrs(int infoChangedFlags) {
         // determine whether the remote control display should be refreshed
-        // if either stack is empty, there is a mismatch, so clear the RC display
-        if (mPRStack.isEmpty() || mFocusStack.isEmpty()) {
-            clearRemoteControlDisplay_syncAfRcs();
+        // if the player record stack is empty, there is nothing to display, so clear the RC display
+        if (mPRStack.isEmpty()) {
+            clearRemoteControlDisplay_syncPrs();
             return;
         }
 
-        // determine which entry in the AudioFocus stack to consider, and compare against the
-        // top of the stack for the media button event receivers : simply using the top of the
-        // stack would make the entry disappear from the RemoteControlDisplay in conditions such as
-        // notifications playing during music playback.
-        // Crawl the AudioFocus stack from the top until an entry is found with the following
-        // characteristics:
-        // - focus gain on STREAM_MUSIC stream
-        // - non-transient focus gain on a stream other than music
-        FocusRequester af = null;
-        try {
-            for (int index = mFocusStack.size()-1; index >= 0; index--) {
-                FocusRequester fr = mFocusStack.elementAt(index);
-                if ((fr.getStreamType() == AudioManager.STREAM_MUSIC)
-                        || (fr.getGainRequest() == AudioManager.AUDIOFOCUS_GAIN)) {
-                    af = fr;
-                    break;
-                }
-            }
-        } catch (ArrayIndexOutOfBoundsException e) {
-            Log.e(TAG, "Wrong index accessing audio focus stack when updating RCD: " + e);
-            af = null;
-        }
-        if (af == null) {
-            clearRemoteControlDisplay_syncAfRcs();
-            return;
-        }
-
-        // if the audio focus and RC owners belong to different packages, there is a mismatch, clear
-        if (!af.hasSamePackage(mPRStack.peek().getCallingPackageName())) {
-            clearRemoteControlDisplay_syncAfRcs();
-            return;
-        }
-        // if the audio focus didn't originate from the same Uid as the one in which the remote
-        //   control information will be retrieved, clear
-        if (!af.hasSameUid(mPRStack.peek().getCallingUid())) {
-            clearRemoteControlDisplay_syncAfRcs();
-            return;
-        }
+        // this is where more rules for refresh go
 
         // refresh conditions were verified: update the remote controls
-        // ok to call: synchronized mAudioFocusLock then on mPRStack, mPRStack is not empty
-        updateRemoteControlDisplay_syncAfRcs(infoChangedFlags);
+        // ok to call: synchronized on mPRStack, mPRStack is not empty
+        updateRemoteControlDisplay_syncPrs(infoChangedFlags);
     }
 
     /**
@@ -1582,35 +1529,33 @@
 
     private void onPromoteRcc(int rccId) {
         if (DEBUG_RC) { Log.d(TAG, "Promoting RCC " + rccId); }
-        synchronized(mAudioFocusLock) {
-            synchronized(mPRStack) {
-                // ignore if given RCC ID is already at top of remote control stack
-                if (!mPRStack.isEmpty() && (mPRStack.peek().getRccId() == rccId)) {
-                    return;
-                }
-                int indexToPromote = -1;
-                try {
-                    for (int index = mPRStack.size()-1; index >= 0; index--) {
-                        final PlayerRecord prse = mPRStack.elementAt(index);
-                        if (prse.getRccId() == rccId) {
-                            indexToPromote = index;
-                            break;
-                        }
+        synchronized(mPRStack) {
+            // ignore if given RCC ID is already at top of remote control stack
+            if (!mPRStack.isEmpty() && (mPRStack.peek().getRccId() == rccId)) {
+                return;
+            }
+            int indexToPromote = -1;
+            try {
+                for (int index = mPRStack.size()-1; index >= 0; index--) {
+                    final PlayerRecord prse = mPRStack.elementAt(index);
+                    if (prse.getRccId() == rccId) {
+                        indexToPromote = index;
+                        break;
                     }
-                    if (indexToPromote >= 0) {
-                        if (DEBUG_RC) { Log.d(TAG, "  moving RCC from index " + indexToPromote
-                                + " to " + (mPRStack.size()-1)); }
-                        final PlayerRecord prse = mPRStack.remove(indexToPromote);
-                        mPRStack.push(prse);
-                        // the RC stack changed, reevaluate the display
-                        checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
-                    }
-                } catch (ArrayIndexOutOfBoundsException e) {
-                    // not expected to happen, indicates improper concurrent modification
-                    Log.e(TAG, "Wrong index accessing RC stack, lock error? ", e);
                 }
-            }//synchronized(mPRStack)
-        }//synchronized(mAudioFocusLock)
+                if (indexToPromote >= 0) {
+                    if (DEBUG_RC) { Log.d(TAG, "  moving RCC from index " + indexToPromote
+                            + " to " + (mPRStack.size()-1)); }
+                    final PlayerRecord prse = mPRStack.remove(indexToPromote);
+                    mPRStack.push(prse);
+                    // the RC stack changed, reevaluate the display
+                    checkUpdateRemoteControlDisplay_syncPrs(RC_INFO_ALL);
+                }
+            } catch (ArrayIndexOutOfBoundsException e) {
+                // not expected to happen, indicates improper concurrent modification
+                Log.e(TAG, "Wrong index accessing RC stack, lock error? ", e);
+            }
+        }//synchronized(mPRStack)
     }
 
     /**
@@ -1621,12 +1566,10 @@
             IBinder token) {
         Log.i(TAG, "  Remote Control   registerMediaButtonIntent() for " + mediaIntent);
 
-        synchronized(mAudioFocusLock) {
-            synchronized(mPRStack) {
-                if (pushMediaButtonReceiver_syncAfRcs(mediaIntent, eventReceiver, token)) {
-                    // new RC client, assume every type of information shall be queried
-                    checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
-                }
+        synchronized(mPRStack) {
+            if (pushMediaButtonReceiver_syncPrs(mediaIntent, eventReceiver, token)) {
+                // new RC client, assume every type of information shall be queried
+                checkUpdateRemoteControlDisplay_syncPrs(RC_INFO_ALL);
             }
         }
     }
@@ -1639,14 +1582,12 @@
     {
         Log.i(TAG, "  Remote Control   unregisterMediaButtonIntent() for " + mediaIntent);
 
-        synchronized(mAudioFocusLock) {
-            synchronized(mPRStack) {
-                boolean topOfStackWillChange = isCurrentRcController(mediaIntent);
-                removeMediaButtonReceiver_syncAfRcs(mediaIntent);
-                if (topOfStackWillChange) {
-                    // current RC client will change, assume every type of info needs to be queried
-                    checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
-                }
+        synchronized(mPRStack) {
+            boolean topOfStackWillChange = isCurrentRcController(mediaIntent);
+            removeMediaButtonReceiver_syncPrs(mediaIntent);
+            if (topOfStackWillChange) {
+                // current RC client will change, assume every type of info needs to be queried
+                checkUpdateRemoteControlDisplay_syncPrs(RC_INFO_ALL);
             }
         }
     }
@@ -1697,42 +1638,40 @@
             IRemoteControlClient rcClient, String callingPackageName) {
         if (DEBUG_RC) Log.i(TAG, "Register remote control client rcClient="+rcClient);
         int rccId = RemoteControlClient.RCSE_ID_UNREGISTERED;
-        synchronized(mAudioFocusLock) {
-            synchronized(mPRStack) {
-                // store the new display information
-                try {
-                    for (int index = mPRStack.size()-1; index >= 0; index--) {
-                        final PlayerRecord prse = mPRStack.elementAt(index);
-                        if(prse.hasMatchingMediaButtonIntent(mediaIntent)) {
-                            prse.resetControllerInfoForRcc(rcClient, callingPackageName,
-                                    Binder.getCallingUid());
+        synchronized(mPRStack) {
+            // store the new display information
+            try {
+                for (int index = mPRStack.size()-1; index >= 0; index--) {
+                    final PlayerRecord prse = mPRStack.elementAt(index);
+                    if(prse.hasMatchingMediaButtonIntent(mediaIntent)) {
+                        prse.resetControllerInfoForRcc(rcClient, callingPackageName,
+                                Binder.getCallingUid());
 
-                            if (rcClient == null) {
-                                break;
-                            }
-
-                            rccId = prse.getRccId();
-
-                            // there is a new (non-null) client:
-                            //     give the new client the displays (if any)
-                            if (mRcDisplays.size() > 0) {
-                                plugRemoteControlDisplaysIntoClient_syncRcStack(prse.getRcc());
-                            }
+                        if (rcClient == null) {
                             break;
                         }
-                    }//for
-                } catch (ArrayIndexOutOfBoundsException e) {
-                    // not expected to happen, indicates improper concurrent modification
-                    Log.e(TAG, "Wrong index accessing RC stack, lock error? ", e);
-                }
 
-                // if the eventReceiver is at the top of the stack
-                // then check for potential refresh of the remote controls
-                if (isCurrentRcController(mediaIntent)) {
-                    checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
-                }
-            }//synchronized(mPRStack)
-        }//synchronized(mAudioFocusLock)
+                        rccId = prse.getRccId();
+
+                        // there is a new (non-null) client:
+                        //     give the new client the displays (if any)
+                        if (mRcDisplays.size() > 0) {
+                            plugRemoteControlDisplaysIntoClient_syncPrs(prse.getRcc());
+                        }
+                        break;
+                    }
+                }//for
+            } catch (ArrayIndexOutOfBoundsException e) {
+                // not expected to happen, indicates improper concurrent modification
+                Log.e(TAG, "Wrong index accessing RC stack, lock error? ", e);
+            }
+
+            // if the eventReceiver is at the top of the stack
+            // then check for potential refresh of the remote controls
+            if (isCurrentRcController(mediaIntent)) {
+                checkUpdateRemoteControlDisplay_syncPrs(RC_INFO_ALL);
+            }
+        }//synchronized(mPRStack)
         return rccId;
     }
 
@@ -1743,29 +1682,27 @@
     protected void unregisterRemoteControlClient(PendingIntent mediaIntent,
             IRemoteControlClient rcClient) {
         if (DEBUG_RC) Log.i(TAG, "Unregister remote control client rcClient="+rcClient);
-        synchronized(mAudioFocusLock) {
-            synchronized(mPRStack) {
-                boolean topRccChange = false;
-                try {
-                    for (int index = mPRStack.size()-1; index >= 0; index--) {
-                        final PlayerRecord prse = mPRStack.elementAt(index);
-                        if ((prse.hasMatchingMediaButtonIntent(mediaIntent))
-                                && rcClient.equals(prse.getRcc())) {
-                            // we found the IRemoteControlClient to unregister
-                            prse.resetControllerInfoForNoRcc();
-                            topRccChange = (index == mPRStack.size()-1);
-                            // there can only be one matching RCC in the RC stack, we're done
-                            break;
-                        }
+        synchronized(mPRStack) {
+            boolean topRccChange = false;
+            try {
+                for (int index = mPRStack.size()-1; index >= 0; index--) {
+                    final PlayerRecord prse = mPRStack.elementAt(index);
+                    if ((prse.hasMatchingMediaButtonIntent(mediaIntent))
+                            && rcClient.equals(prse.getRcc())) {
+                        // we found the IRemoteControlClient to unregister
+                        prse.resetControllerInfoForNoRcc();
+                        topRccChange = (index == mPRStack.size()-1);
+                        // there can only be one matching RCC in the RC stack, we're done
+                        break;
                     }
-                } catch (ArrayIndexOutOfBoundsException e) {
-                    // not expected to happen, indicates improper concurrent modification
-                    Log.e(TAG, "Wrong index accessing RC stack, lock error? ", e);
                 }
-                if (topRccChange) {
-                    // no more RCC for the RCD, check for potential refresh of the remote controls
-                    checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
-                }
+            } catch (ArrayIndexOutOfBoundsException e) {
+                // not expected to happen, indicates improper concurrent modification
+                Log.e(TAG, "Wrong index accessing RC stack, lock error? ", e);
+            }
+            if (topRccChange) {
+                // no more RCC for the RCD, check for potential refresh of the remote controls
+                checkUpdateRemoteControlDisplay_syncPrs(RC_INFO_ALL);
             }
         }
     }
@@ -1843,7 +1780,7 @@
      * Plug each registered display into the specified client
      * @param rcc, guaranteed non null
      */
-    private void plugRemoteControlDisplaysIntoClient_syncRcStack(IRemoteControlClient rcc) {
+    private void plugRemoteControlDisplaysIntoClient_syncPrs(IRemoteControlClient rcc) {
         final Iterator<DisplayInfoForServer> displayIterator = mRcDisplays.iterator();
         while (displayIterator.hasNext()) {
             final DisplayInfoForServer di = displayIterator.next();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index dd75921..64c67b1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -43,6 +43,7 @@
     boolean mVisible;
     boolean mTaskLaunched;
 
+    // Broadcast receiver to handle messages from our RecentsService
     BroadcastReceiver mServiceBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -63,6 +64,14 @@
         }
     };
 
+    // Broadcast receiver to handle messages from the system
+    BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            finish();
+        }
+    };
+
     /** Updates the set of recent tasks */
     void updateRecentsTasks() {
         RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
@@ -111,12 +120,6 @@
         RecentsTaskLoader.initialize(this);
         RecentsConfiguration.reinitialize(this);
 
-        // Set the background dim
-        WindowManager.LayoutParams wlp = getWindow().getAttributes();
-        wlp.dimAmount = Constants.Values.Window.BackgroundDim;
-        getWindow().setAttributes(wlp);
-        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
-
         // Create the view hierarchy
         mRecentsView = new RecentsView(this);
         mRecentsView.setCallbacks(this);
@@ -170,12 +173,37 @@
         Console.log(Constants.DebugFlags.App.SystemUIHandshake, "[RecentsActivity|onResume]", "",
                 Console.AnsiRed);
         super.onResume();
+    }
+
+    @Override
+    public void onAttachedToWindow() {
+        Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+                "[RecentsActivity|onAttachedToWindow]", "",
+                Console.AnsiRed);
+        super.onAttachedToWindow();
 
         // Register the broadcast receiver to handle messages from our service
         IntentFilter filter = new IntentFilter();
         filter.addAction(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY);
         filter.addAction(RecentsService.ACTION_FINISH_RECENTS_ACTIVITY);
         registerReceiver(mServiceBroadcastReceiver, filter);
+
+        // Register the broadcast receiver to handle messages when the screen is turned off
+        filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_SCREEN_OFF);
+        registerReceiver(mScreenOffReceiver, filter);
+    }
+
+    @Override
+    public void onDetachedFromWindow() {
+        Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+                "[RecentsActivity|onDetachedFromWindow]", "",
+                Console.AnsiRed);
+        super.onDetachedFromWindow();
+
+        // Unregister any broadcast receivers we have registered
+        unregisterReceiver(mServiceBroadcastReceiver);
+        unregisterReceiver(mScreenOffReceiver);
     }
 
     @Override
@@ -183,9 +211,6 @@
         Console.log(Constants.DebugFlags.App.SystemUIHandshake, "[RecentsActivity|onPause]", "",
                 Console.AnsiRed);
         super.onPause();
-
-        // Unregister any broadcast receivers we have registered
-        unregisterReceiver(mServiceBroadcastReceiver);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 4a0de0b..94a655f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -17,6 +17,7 @@
 package com.android.systemui.recents;
 
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Rect;
 import android.util.DisplayMetrics;
@@ -62,6 +63,12 @@
         DisplayMetrics dm = res.getDisplayMetrics();
         mDisplayMetrics = dm;
 
+        boolean isLandscape = res.getConfiguration().orientation ==
+                Configuration.ORIENTATION_LANDSCAPE;
+        Console.log(Constants.DebugFlags.UI.MeasureAndLayout,
+                "[RecentsConfiguration|orientation]", isLandscape ? "Landscape" : "Portrait",
+                Console.AnsiGreen);
+
         displayRect.set(0, 0, dm.widthPixels, dm.heightPixels);
         animationPxMovementPerSecond =
                 res.getDimensionPixelSize(R.dimen.recents_animation_movement_in_dps_per_second);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index d661f287..754d956 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
@@ -22,7 +22,6 @@
 import android.content.pm.ActivityInfo;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
-import android.graphics.Canvas;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
@@ -213,6 +212,7 @@
                                 Console.log(Constants.DebugFlags.App.TaskDataLoader,
                                         "    [TaskResourceLoader|loadThumbnail]",
                                         thumbnail);
+                                thumbnail.setHasAlpha(false);
                                 loadThumbnail = thumbnail;
                                 mThumbnailCache.put(t.key, thumbnail);
                             } else {
@@ -331,13 +331,9 @@
 
         // Create the default assets
         Bitmap icon = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
+        icon.eraseColor(0x00000000);
         mDefaultThumbnail = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
-        Canvas c = new Canvas();
-        c.setBitmap(icon);
-        c.drawColor(0x00000000);
-        c.setBitmap(mDefaultThumbnail);
-        c.drawColor(0x00000000);
-        c.setBitmap(null);
+        mDefaultThumbnail.eraseColor(0x00000000);
         mDefaultApplicationIcon = new BitmapDrawable(context.getResources(), icon);
         Console.log(Constants.DebugFlags.App.TaskDataLoader,
                 "[RecentsTaskLoader|defaultBitmaps]",
@@ -454,6 +450,7 @@
                             "[RecentsTaskLoader|loadingTaskThumbnail]");
                     task.thumbnail = ssp.getTaskThumbnail(task.key.id);
                     if (task.thumbnail != null) {
+                        task.thumbnail.setHasAlpha(false);
                         mThumbnailCache.put(task.key, task.thumbnail);
                     } else {
                         task.thumbnail = mDefaultThumbnail;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
index efcd948..505238d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
@@ -24,7 +24,6 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
-import android.graphics.Canvas;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 
@@ -52,9 +51,7 @@
         if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
             // Create a dummy icon
             mDummyIcon = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
-            Canvas c = new Canvas(mDummyIcon);
-            c.drawColor(0xFF999999);
-            c.setBitmap(null);
+            mDummyIcon.eraseColor(0xFF999999);
         }
     }
 
@@ -117,9 +114,7 @@
         // If we are mocking, then just return a dummy thumbnail
         if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
             Bitmap thumbnail = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
-            Canvas c = new Canvas(thumbnail);
-            c.drawColor(0xff333333);
-            c.setBitmap(null);
+            thumbnail.eraseColor(0xff333333);
             return thumbnail;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 1ebe231..141d870 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -108,6 +108,7 @@
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         int width = MeasureSpec.getSize(widthMeasureSpec);
+        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
         int height = MeasureSpec.getSize(heightMeasureSpec);
         int heightMode = MeasureSpec.getMode(heightMeasureSpec);
 
@@ -118,6 +119,7 @@
 
         // We measure our stack views sans the status bar.  It will handle the nav bar itself.
         RecentsConfiguration config = RecentsConfiguration.getInstance();
+        int childWidth = width - config.systemInsets.right;
         int childHeight = height - config.systemInsets.top;
 
         // Measure each child
@@ -125,7 +127,7 @@
         for (int i = 0; i < childCount; i++) {
             final View child = getChildAt(i);
             if (child.getVisibility() != GONE) {
-                child.measure(widthMeasureSpec,
+                child.measure(MeasureSpec.makeMeasureSpec(childWidth, widthMode),
                         MeasureSpec.makeMeasureSpec(childHeight, heightMode));
             }
         }
@@ -255,11 +257,11 @@
                             | Intent.FLAG_ACTIVITY_TASK_ON_HOME
                             | Intent.FLAG_ACTIVITY_NEW_TASK);
                     try {
+                        UserHandle taskUser = new UserHandle(task.userId);
                         if (opts != null) {
-                            getContext().startActivityAsUser(i, opts.toBundle(),
-                                    new UserHandle(task.userId));
+                            getContext().startActivityAsUser(i, opts.toBundle(), taskUser);
                         } else {
-                            getContext().startActivityAsUser(i, new UserHandle(task.userId));
+                            getContext().startActivityAsUser(i, taskUser);
                         }
                     } catch (ActivityNotFoundException anfe) {
                         Console.logError(getContext(), "Could not start Activity");
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index fa06764..c9a491e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -524,8 +524,8 @@
                 (Constants.Values.TaskStackView.StackPeekHeightPct * mStackRect.height()));
         int size = Math.min(minHeight, Math.min(mStackRect.width(), mStackRect.height()));
         int centerX = mStackRect.centerX();
-        mTaskRect.set(centerX - size / 2, mStackRectSansPeek.top,
-                centerX + size / 2, mStackRectSansPeek.top + size);
+        mTaskRect.set(mStackRect.left, mStackRectSansPeek.top,
+                mStackRect.right, mStackRectSansPeek.top + size);
 
         // Update the scroll bounds
         updateMinMaxScroll(false);