Merge "Have R classes generate their own reference rewrite logic" into lmp-dev
diff --git a/api/current.txt b/api/current.txt
index 82a2d8b8..ffdd9f7 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -785,8 +785,8 @@
     field public static final int largeScreens = 16843398; // 0x1010286
     field public static final int largestWidthLimitDp = 16843622; // 0x1010366
     field public static final int launchMode = 16842781; // 0x101001d
-    field public static final int launchTaskBehindBackgroundAnimation = 16843921; // 0x1010491
     field public static final int launchTaskBehindSourceAnimation = 16843922; // 0x1010492
+    field public static final int launchTaskBehindTargetAnimation = 16843921; // 0x1010491
     field public static final int layerType = 16843604; // 0x1010354
     field public static final int layout = 16842994; // 0x10100f2
     field public static final int layoutAnimation = 16842988; // 0x10100ec
@@ -1349,6 +1349,7 @@
     field public static final int transitionGroup = 16843803; // 0x101041b
     field public static final int transitionName = 16843802; // 0x101041a
     field public static final int transitionOrdering = 16843744; // 0x10103e0
+    field public static final int transitionVisibilityMode = 16843900; // 0x101047c
     field public static final int translateX = 16843866; // 0x101045a
     field public static final int translateY = 16843867; // 0x101045b
     field public static final int translationX = 16843554; // 0x1010322
@@ -1385,7 +1386,6 @@
     field public static final int viewportHeight = 16843805; // 0x101041d
     field public static final int viewportWidth = 16843804; // 0x101041c
     field public static final int visibility = 16842972; // 0x10100dc
-    field public static final int visibilityMode = 16843900; // 0x101047c
     field public static final int visible = 16843156; // 0x1010194
     field public static final int vmSafeMode = 16843448; // 0x10102b8
     field public static final int voiceIcon = 16843908; // 0x1010484
@@ -3773,10 +3773,11 @@
 
   public class ActivityOptions {
     method public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int);
-    method public static android.app.ActivityOptions makeLaunchTaskBehindAnimation();
+    method public static deprecated android.app.ActivityOptions makeLaunchTaskBehindAnimation();
     method public static android.app.ActivityOptions makeScaleUpAnimation(android.view.View, int, int, int, int);
     method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.app.Activity, android.view.View, java.lang.String);
     method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.app.Activity, android.util.Pair<android.view.View, java.lang.String>...);
+    method public static android.app.ActivityOptions makeTaskLaunchBehind();
     method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int);
     method public android.os.Bundle toBundle();
     method public void update(android.app.ActivityOptions);
@@ -5510,8 +5511,8 @@
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM = "android.app.extra.DEVICE_ADMIN_PACKAGE_CHECKSUM";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
-    field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.DEVICE_ADMIN_PACKAGE_NAME";
-    field public static final java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.MANAGED_PROFILE_EMAIL_ADDRESS";
+    field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.deviceAdminPackageName";
+    field public static final java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.ManagedProfileEmailAddress";
     field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.LOCALE";
     field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.LOCAL_TIME";
     field public static final java.lang.String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.TIME_ZONE";
@@ -7353,7 +7354,6 @@
     field public static final java.lang.String NFC_SERVICE = "nfc";
     field public static final java.lang.String NOTIFICATION_SERVICE = "notification";
     field public static final java.lang.String NSD_SERVICE = "servicediscovery";
-    field public static final java.lang.String PHONE_SERVICE = "phone_service";
     field public static final java.lang.String POWER_SERVICE = "power";
     field public static final java.lang.String PRINT_SERVICE = "print";
     field public static final java.lang.String RESTRICTIONS_SERVICE = "restrictions";
@@ -8902,6 +8902,7 @@
     field public static final java.lang.String FEATURE_SENSOR_COMPASS = "android.hardware.sensor.compass";
     field public static final java.lang.String FEATURE_SENSOR_GYROSCOPE = "android.hardware.sensor.gyroscope";
     field public static final java.lang.String FEATURE_SENSOR_HEART_RATE = "android.hardware.sensor.heartrate";
+    field public static final java.lang.String FEATURE_SENSOR_HEART_RATE_ECG = "android.hardware.sensor.heartrate.ecg";
     field public static final java.lang.String FEATURE_SENSOR_LIGHT = "android.hardware.sensor.light";
     field public static final java.lang.String FEATURE_SENSOR_PROXIMITY = "android.hardware.sensor.proximity";
     field public static final java.lang.String FEATURE_SENSOR_RELATIVE_HUMIDITY = "android.hardware.sensor.relative_humidity";
@@ -22768,17 +22769,6 @@
 
 }
 
-package android.phone {
-
-  public final class PhoneManager {
-    method public void cancelMissedCallsNotification();
-    method public boolean handlePinMmi(java.lang.String);
-    method public boolean isInAPhoneCall();
-    method public void showCallScreen(boolean);
-  }
-
-}
-
 package android.preference {
 
   public class CheckBoxPreference extends android.preference.TwoStatePreference {
@@ -27330,6 +27320,7 @@
     method public final void cancelNotification(java.lang.String);
     method public final void cancelNotifications(java.lang.String[]);
     method public android.service.notification.StatusBarNotification[] getActiveNotifications();
+    method public android.service.notification.StatusBarNotification[] getActiveNotifications(java.lang.String[]);
     method public final int getCurrentListenerHints();
     method public android.service.notification.NotificationListenerService.RankingMap getCurrentRanking();
     method public android.os.IBinder onBind(android.content.Intent);
@@ -28606,6 +28597,7 @@
   public abstract class ConnectionService extends android.app.Service {
     ctor public ConnectionService();
     method public final void addConference(android.telecomm.Conference);
+    method public final void conferenceRemoteConnections(android.telecomm.RemoteConnection, android.telecomm.RemoteConnection);
     method public final android.telecomm.RemoteConnection createRemoteIncomingConnection(android.telecomm.PhoneAccountHandle, android.telecomm.ConnectionRequest);
     method public final android.telecomm.RemoteConnection createRemoteOutgoingConnection(android.telecomm.PhoneAccountHandle, android.telecomm.ConnectionRequest);
     method public final java.util.Collection<android.telecomm.Connection> getAllConnections();
@@ -28615,6 +28607,7 @@
     method public void onConnectionRemoved(android.telecomm.Connection);
     method public android.telecomm.Connection onCreateIncomingConnection(android.telecomm.PhoneAccountHandle, android.telecomm.ConnectionRequest);
     method public android.telecomm.Connection onCreateOutgoingConnection(android.telecomm.PhoneAccountHandle, android.telecomm.ConnectionRequest);
+    method public void onRemoteConferenceAdded(android.telecomm.RemoteConference);
     field public static final java.lang.String SERVICE_INTERFACE = "android.telecomm.ConnectionService";
   }
 
@@ -28691,6 +28684,30 @@
     field public static final int UNKNOWN = 3; // 0x3
   }
 
+  public final class RemoteConference {
+    method public final void addListener(android.telecomm.RemoteConference.Listener);
+    method public void disconnect();
+    method public final int getCallCapabilities();
+    method public final java.util.List<android.telecomm.RemoteConnection> getConnections();
+    method public int getDisconnectCause();
+    method public java.lang.String getDisconnectMessage();
+    method public final int getState();
+    method public void hold();
+    method public final void removeListener(android.telecomm.RemoteConference.Listener);
+    method public void separate(android.telecomm.RemoteConnection);
+    method public void unhold();
+  }
+
+  public static abstract class RemoteConference.Listener {
+    ctor public RemoteConference.Listener();
+    method public void onCapabilitiesChanged(android.telecomm.RemoteConference, int);
+    method public void onConnectionAdded(android.telecomm.RemoteConference, android.telecomm.RemoteConnection);
+    method public void onConnectionRemoved(android.telecomm.RemoteConference, android.telecomm.RemoteConnection);
+    method public void onDestroyed(android.telecomm.RemoteConference);
+    method public void onDisconnected(android.telecomm.RemoteConference, int, java.lang.String);
+    method public void onStateChanged(android.telecomm.RemoteConference, int, int);
+  }
+
   public final class RemoteConnection {
     method public void abort();
     method public void addListener(android.telecomm.RemoteConnection.Listener);
@@ -28701,6 +28718,8 @@
     method public java.lang.String getCallerDisplayName();
     method public int getCallerDisplayNamePresentation();
     method public java.util.List<android.telecomm.RemoteConnection> getChildren();
+    method public android.telecomm.RemoteConference getConference();
+    method public java.util.List<android.telecomm.RemoteConnection> getConferenceableConnections();
     method public int getDisconnectCauseCode();
     method public java.lang.String getDisconnectCauseMessage();
     method public int getFailureCode();
@@ -28727,6 +28746,7 @@
     method public void onCallCapabilitiesChanged(android.telecomm.RemoteConnection, int);
     method public void onCallerDisplayNameChanged(android.telecomm.RemoteConnection, java.lang.String, int);
     method public void onChildrenChanged(android.telecomm.RemoteConnection, java.util.List<android.telecomm.RemoteConnection>);
+    method public void onConferenceChanged(android.telecomm.RemoteConnection, android.telecomm.RemoteConference);
     method public void onConferenceableConnectionsChanged(android.telecomm.RemoteConnection, java.util.List<android.telecomm.RemoteConnection>);
     method public void onDestroyed(android.telecomm.RemoteConnection);
     method public void onDisconnected(android.telecomm.RemoteConnection, int, java.lang.String);
@@ -28758,12 +28778,16 @@
 
   public class TelecommManager {
     method public void addNewIncomingCall(android.telecomm.PhoneAccountHandle, android.os.Bundle);
+    method public void cancelMissedCallsNotification();
     method public void clearAccounts(java.lang.String);
     method public android.telecomm.PhoneAccountHandle getDefaultOutgoingPhoneAccount();
     method public java.util.List<android.telecomm.PhoneAccountHandle> getEnabledPhoneAccounts();
     method public android.telecomm.PhoneAccount getPhoneAccount(android.telecomm.PhoneAccountHandle);
+    method public boolean handleMmi(java.lang.String);
     method public boolean hasMultipleEnabledAccounts();
+    method public boolean isInCall();
     method public void registerPhoneAccount(android.telecomm.PhoneAccount);
+    method public void showInCallScreen(boolean);
     method public void unregisterPhoneAccount(android.telecomm.PhoneAccountHandle);
     field public static final java.lang.String ACTION_CONNECTION_SERVICE_CONFIGURE = "android.intent.action.CONNECTION_SERVICE_CONFIGURE";
     field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecomm.intent.action.SHOW_CALL_SETTINGS";
@@ -28986,10 +29010,10 @@
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
     field public static int INVALID_CHANNEL;
-    field public static int MISSING_RESOURCE;
-    field public static int NO_ERROR;
-    field public static int NO_SUCH_ELEMENT;
-    field public static int UNKNOWN_ERROR;
+    field public static int STATUS_MISSING_RESOURCE;
+    field public static int STATUS_NO_ERROR;
+    field public static int STATUS_NO_SUCH_ELEMENT;
+    field public static int STATUS_UNKNOWN_ERROR;
   }
 
   public class MessagingConfigurationManager {
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index b86621f..2173647 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -796,6 +796,12 @@
     public static final int RECENT_INCLUDE_PROFILES = 0x0004;
 
     /**
+     * Ignores all tasks that are on the home stack.
+     * @hide
+     */
+    public static final int RECENT_IGNORE_HOME_STACK_TASKS = 0x0008;
+
+    /**
      * <p></p>Return a list of the tasks that the user has recently launched, with
      * the most recent being first and older ones after in order.
      *
@@ -985,7 +991,7 @@
         ArrayList<AppTask> tasks = new ArrayList<AppTask>();
         List<IAppTask> appTasks;
         try {
-            appTasks = ActivityManagerNative.getDefault().getAppTasks();
+            appTasks = ActivityManagerNative.getDefault().getAppTasks(mContext.getPackageName());
         } catch (RemoteException e) {
             // System dead, we will be dead too soon!
             return null;
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 5b81cc3..82af99b 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -554,7 +554,8 @@
 
         case GET_APP_TASKS_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
-            List<IAppTask> list = getAppTasks();
+            String callingPackage = data.readString();
+            List<IAppTask> list = getAppTasks(callingPackage);
             reply.writeNoException();
             int N = list != null ? list.size() : -1;
             reply.writeInt(N);
@@ -2880,10 +2881,11 @@
         reply.recycle();
         return res;
     }
-    public List<IAppTask> getAppTasks() throws RemoteException {
+    public List<IAppTask> getAppTasks(String callingPackage) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeString(callingPackage);
         mRemote.transact(GET_APP_TASKS_TRANSACTION, data, reply, 0);
         reply.readException();
         ArrayList<IAppTask> list = null;
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 4c02314..9dd4605 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -128,6 +128,10 @@
     public static final int ANIM_DEFAULT = 6;
     /** @hide */
     public static final int ANIM_LAUNCH_TASK_BEHIND = 7;
+    /** @hide */
+    public static final int ANIM_THUMBNAIL_ASPECT_SCALE_UP = 8;
+    /** @hide */
+    public static final int ANIM_THUMBNAIL_ASPECT_SCALE_DOWN = 9;
 
     private String mPackageName;
     private int mAnimationType = ANIM_NONE;
@@ -338,6 +342,67 @@
     }
 
     /**
+     * Create an ActivityOptions specifying an animation where the new activity
+     * window and a thumbnail is aspect-scaled to a new location.
+     *
+     * @param source The View that this thumbnail is animating from.  This
+     * defines the coordinate space for <var>startX</var> and <var>startY</var>.
+     * @param thumbnail The bitmap that will be shown as the initial thumbnail
+     * of the animation.
+     * @param startX The x starting location of the bitmap, relative to <var>source</var>.
+     * @param startY The y starting location of the bitmap, relative to <var>source</var>.
+     * @param listener Optional OnAnimationStartedListener to find out when the
+     * requested animation has started running.  If for some reason the animation
+     * is not executed, the callback will happen immediately.
+     * @return Returns a new ActivityOptions object that you can use to
+     * supply these options as the options Bundle when starting an activity.
+     * @hide
+     */
+    public static ActivityOptions makeThumbnailAspectScaleUpAnimation(View source,
+            Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
+        return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY, listener,
+                true);
+    }
+
+    /**
+     * Create an ActivityOptions specifying an animation where the new activity
+     * window and a thumbnail is aspect-scaled to a new location.
+     *
+     * @param source The View that this thumbnail is animating to.  This
+     * defines the coordinate space for <var>startX</var> and <var>startY</var>.
+     * @param thumbnail The bitmap that will be shown as the final thumbnail
+     * of the animation.
+     * @param startX The x end location of the bitmap, relative to <var>source</var>.
+     * @param startY The y end location of the bitmap, relative to <var>source</var>.
+     * @param listener Optional OnAnimationStartedListener to find out when the
+     * requested animation has started running.  If for some reason the animation
+     * is not executed, the callback will happen immediately.
+     * @return Returns a new ActivityOptions object that you can use to
+     * supply these options as the options Bundle when starting an activity.
+     * @hide
+     */
+    public static ActivityOptions makeThumbnailAspectScaleDownAnimation(View source,
+            Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
+        return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY, listener,
+                false);
+    }
+
+    private static ActivityOptions makeAspectScaledThumbnailAnimation(View source, Bitmap thumbnail,
+            int startX, int startY, OnAnimationStartedListener listener, boolean scaleUp) {
+        ActivityOptions opts = new ActivityOptions();
+        opts.mPackageName = source.getContext().getPackageName();
+        opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_ASPECT_SCALE_UP :
+                ANIM_THUMBNAIL_ASPECT_SCALE_DOWN;
+        opts.mThumbnail = thumbnail;
+        int[] pts = new int[2];
+        source.getLocationOnScreen(pts);
+        opts.mStartX = pts[0] + startX;
+        opts.mStartY = pts[1] + startY;
+        opts.setOnAnimationStartedListener(source.getHandler(), listener);
+        return opts;
+    }
+
+    /**
      * Create an ActivityOptions to transition between Activities using cross-Activity scene
      * animations. This method carries the position of one shared element to the started Activity.
      * The position of <code>sharedElement</code> will be used as the epicenter for the
@@ -444,12 +509,17 @@
      * android.R.styleable#AndroidManifestActivity_launchMode launchMode} values of
      * <code>singleInstance</code> or <code>singleTask</code>.
      */
-    public static ActivityOptions makeLaunchTaskBehindAnimation() {
+    public static ActivityOptions makeTaskLaunchBehind() {
         final ActivityOptions opts = new ActivityOptions();
         opts.mAnimationType = ANIM_LAUNCH_TASK_BEHIND;
         return opts;
     }
 
+    @Deprecated
+    public static ActivityOptions makeLaunchTaskBehindAnimation() {
+        return makeTaskLaunchBehind();
+    }
+
     /** @hide */
     public boolean getLaunchTaskBehind() {
         return mAnimationType == ANIM_LAUNCH_TASK_BEHIND;
@@ -479,7 +549,9 @@
 
             case ANIM_THUMBNAIL_SCALE_UP:
             case ANIM_THUMBNAIL_SCALE_DOWN:
-                mThumbnail = (Bitmap)opts.getParcelable(KEY_ANIM_THUMBNAIL);
+            case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
+            case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
+                mThumbnail = (Bitmap) opts.getParcelable(KEY_ANIM_THUMBNAIL);
                 mStartX = opts.getInt(KEY_ANIM_START_X, 0);
                 mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
                 mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
@@ -630,6 +702,8 @@
                 break;
             case ANIM_THUMBNAIL_SCALE_UP:
             case ANIM_THUMBNAIL_SCALE_DOWN:
+            case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
+            case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
                 mThumbnail = otherOptions.mThumbnail;
                 mStartX = otherOptions.mStartX;
                 mStartY = otherOptions.mStartY;
@@ -686,6 +760,8 @@
                 break;
             case ANIM_THUMBNAIL_SCALE_UP:
             case ANIM_THUMBNAIL_SCALE_DOWN:
+            case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
+            case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
                 b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
                 b.putInt(KEY_ANIM_START_X, mStartX);
                 b.putInt(KEY_ANIM_START_Y, mStartY);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index da343ac..884b046 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -122,7 +122,6 @@
 import android.os.UserManager;
 import android.os.storage.IMountService;
 import android.os.storage.StorageManager;
-import android.phone.PhoneManager;
 import android.print.IPrintManager;
 import android.print.PrintManager;
 import android.service.fingerprint.IFingerprintService;
@@ -570,11 +569,6 @@
                     return new TelecommManager(ctx.getOuterContext());
                 }});
 
-        registerService(PHONE_SERVICE, new ServiceFetcher() {
-                public Object createService(ContextImpl ctx) {
-                    return new PhoneManager(ctx.getOuterContext());
-                }});
-
         registerService(UI_MODE_SERVICE, new ServiceFetcher() {
                 public Object createService(ContextImpl ctx) {
                     return new UiModeManager();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 1664408..69e1710 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -119,7 +119,7 @@
     public void activityDestroyed(IBinder token) throws RemoteException;
     public String getCallingPackage(IBinder token) throws RemoteException;
     public ComponentName getCallingActivity(IBinder token) throws RemoteException;
-    public List<IAppTask> getAppTasks() throws RemoteException;
+    public List<IAppTask> getAppTasks(String callingPackage) throws RemoteException;
     public int addAppTask(IBinder activityToken, Intent intent,
             ActivityManager.TaskDescription description, Bitmap thumbnail) throws RemoteException;
     public Point getAppTaskThumbnailSize() throws RemoteException;
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 2b97c6b..07e9a94 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -58,7 +58,7 @@
     void cancelNotificationFromListener(in INotificationListener token, String pkg, String tag, int id);
     void cancelNotificationsFromListener(in INotificationListener token, in String[] keys);
 
-    ParceledListSlice getActiveNotificationsFromListener(in INotificationListener token);
+    ParceledListSlice getActiveNotificationsFromListener(in INotificationListener token, in String[] keys);
     void requestHintsFromListener(in INotificationListener token, int hints);
     int getHintsFromListener(in INotificationListener token);
 
@@ -71,4 +71,4 @@
     oneway void setZenModeCondition(in Condition condition);
     oneway void setAutomaticZenModeConditions(in Uri[] conditionIds);
     Condition[] getAutomaticZenModeConditions();
-}
\ No newline at end of file
+}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 41bbb87..b17309f 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -126,7 +126,7 @@
      * message containing an Nfc record with MIME type {@link #MIME_TYPE_PROVISIONING_NFC}.
      */
     public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME
-        = "android.app.extra.DEVICE_ADMIN_PACKAGE_NAME";
+        = "android.app.extra.deviceAdminPackageName";
 
     /**
      * A String extra holding the default name of the profile that is created during managed profile
@@ -149,7 +149,7 @@
      * It is usually used to avoid that the user has to enter their email address twice.
      */
     public static final String EXTRA_PROVISIONING_EMAIL_ADDRESS
-        = "android.app.extra.MANAGED_PROFILE_EMAIL_ADDRESS";
+        = "android.app.extra.ManagedProfileEmailAddress";
 
     /**
      * A String extra holding the time zone {@link android.app.AlarmManager} that the device
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index a13a928..ebb1f77 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2203,8 +2203,6 @@
      * @see android.media.MediaRouter
      * @see #TELEPHONY_SERVICE
      * @see android.telephony.TelephonyManager
-     * @see #PHONE_SERVICE
-     * @see android.phone.PhoneManager
      * @see #INPUT_METHOD_SERVICE
      * @see android.view.inputmethod.InputMethodManager
      * @see #UI_MODE_SERVICE
@@ -2558,16 +2556,6 @@
 
     /**
      * Use with {@link #getSystemService} to retrieve a
-     * {@link android.phone.PhoneManager} to manage phone-related features
-     * of the device.
-     *
-     * @see #getSystemService
-     * @see android.phone.PhoneManager
-     */
-    public static final String PHONE_SERVICE = "phone_service";  // "phone" used by telephony.
-
-    /**
-     * Use with {@link #getSystemService} to retrieve a
      * {@link android.text.ClipboardManager} for accessing and modifying
      * the contents of the global clipboard.
      *
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 56b7164..5492775 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1217,6 +1217,14 @@
 
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
+     * {@link #hasSystemFeature}: The heart rate sensor on this device is an Electrocargiogram.
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_SENSOR_HEART_RATE_ECG =
+            "android.hardware.sensor.heartrate.ecg";
+
+    /**
+     * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device includes a relative humidity sensor.
      */
     @SdkConstant(SdkConstantType.FEATURE)
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index d19418b..e63fd07 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -533,6 +533,18 @@
     public static final int DENSITY_DPI_UNDEFINED = 0;
 
     /**
+     * Value for {@link #densityDpi} for resources that scale to any density (vector drawables).
+     * {@hide}
+     */
+    public static final int DENSITY_DPI_ANY = 0xfffe;
+
+    /**
+     * Value for {@link #densityDpi} for resources that are not meant to be scaled.
+     * {@hide}
+     */
+    public static final int DENSITY_DPI_NONE = 0xffff;
+
+    /**
      * The target screen density being rendered to,
      * corresponding to
      * <a href="{@docRoot}guide/topics/resources/providing-resources.html#DensityQualifier">density</a>
@@ -1453,7 +1465,7 @@
         }
 
         switch (config.densityDpi) {
-            case 0:
+            case DENSITY_DPI_UNDEFINED:
                 break;
             case 120:
                 parts.add("ldpi");
@@ -1476,6 +1488,11 @@
             case 640:
                 parts.add("xxxhdpi");
                 break;
+            case DENSITY_DPI_ANY:
+                parts.add("anydpi");
+                break;
+            case DENSITY_DPI_NONE:
+                parts.add("nodpi");
             default:
                 parts.add(config.densityDpi + "dpi");
                 break;
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index 3c61e39..4b5ced9 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -48,6 +48,12 @@
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_OSD_MESSAGE = "android.hardware.hdmi.action.OSD_MESSAGE";
 
+    // --- Messages for ACTION_OSD_MESSAGE ---
+    /**
+     * Message that ARC enabled device is connected to invalid port (non-ARC port).
+     */
+    public static final int OSD_MESSAGE_ARC_CONNECTED_INVALID_PORT = 1;
+
     /**
      * Used as an extra field in the intent {@link #ACTION_OSD_MESSAGE}. Contains the ID of
      * the message to display on screen.
diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java
index 99bccd0..b023b0b 100644
--- a/core/java/android/net/VpnService.java
+++ b/core/java/android/net/VpnService.java
@@ -523,7 +523,8 @@
          *
          * If this method is called at least once, only applications added through this method (and
          * no others) are allowed access. Else (if this method is never called), all applications
-         * are allowed by default.
+         * are allowed by default.  If some applications are added, other, un-added applications
+         * will use networking as if the VPN wasn't running.
          *
          * A {@link Builder} may have only a set of allowed applications OR a set of disallowed
          * ones, but not both. Calling this method after {@link #addDisallowedApplication} has
@@ -548,7 +549,7 @@
          * Adds an application that's denied access to the VPN connection.
          *
          * By default, all applications are allowed access, except for those denied through this
-         * method.
+         * method.  Denied applications will use networking as if the VPN wasn't running.
          *
          * A {@link Builder} may have only a set of allowed applications OR a set of disallowed
          * ones, but not both. Calling this method after {@link #addAllowedApplication} has already
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 119f7f6..4651d7e 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -307,10 +307,22 @@
      * @return An array of active notifications, sorted in natural order.
      */
     public StatusBarNotification[] getActiveNotifications() {
+        return getActiveNotifications(null);
+    }
+
+    /**
+     * Request one or more notifications by key. Useful if you have been keeping track of
+     * notifications but didn't want to retain the bits, and now need to go back and extract
+     * more data out of those notifications.
+     *
+     * @return An array of notifications corresponding to the requested keys, in the
+     * same order as the key list.
+     */
+    public StatusBarNotification[] getActiveNotifications(String[] keys) {
         if (!isBound()) return null;
         try {
             ParceledListSlice<StatusBarNotification> parceledList =
-                    getNotificationInterface().getActiveNotificationsFromListener(mWrapper);
+                    getNotificationInterface().getActiveNotificationsFromListener(mWrapper, keys);
             List<StatusBarNotification> list = parceledList.getList();
 
             int N = list.size();
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index 81c69d1..0b02552 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -84,7 +84,7 @@
     public Visibility(Context context, AttributeSet attrs) {
         super(context, attrs);
         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.VisibilityTransition);
-        int mode = a.getInt(R.styleable.VisibilityTransition_visibilityMode, 0);
+        int mode = a.getInt(R.styleable.VisibilityTransition_transitionVisibilityMode, 0);
         a.recycle();
         if (mode != 0) {
             setMode(mode);
@@ -97,7 +97,7 @@
      *
      * @param mode The behavior supported by this transition, a combination of
      *             {@link #MODE_IN} and {@link #MODE_OUT}.
-     * @attr ref android.R.styleable#VisibilityTransition_visibilityMode
+     * @attr ref android.R.styleable#VisibilityTransition_transitionVisibilityMode
      */
     public void setMode(int mode) {
         if ((mode & ~(MODE_IN | MODE_OUT)) != 0) {
@@ -111,7 +111,7 @@
      *
      * Returns whether appearing and/or disappearing Views are supported. A combination of
      *         {@link #MODE_IN} and {@link #MODE_OUT}.
-     * @attr ref android.R.styleable#VisibilityTransition_visibilityMode
+     * @attr ref android.R.styleable#VisibilityTransition_transitionVisibilityMode
      */
     public int getMode() {
         return mMode;
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index a410aa9..ceea9f8 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -179,6 +179,18 @@
     private static native void nSetHighContrastText(long renderer, boolean highContrastText);
 
     @Override
+    public void insertReorderBarrier() {
+        nInsertReorderBarrier(mRenderer, true);
+    }
+
+    @Override
+    public void insertInorderBarrier() {
+        nInsertReorderBarrier(mRenderer, false);
+    }
+
+    private static native void nInsertReorderBarrier(long renderer, boolean enableReorder);
+
+    @Override
     public int onPreDraw(Rect dirty) {
         if (dirty != null) {
             return nPrepareDirty(mRenderer, dirty.left, dirty.top, dirty.right, dirty.bottom,
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 7deb9c8..5d6d998 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -93,6 +93,8 @@
             int startHeight);
     void overridePendingAppTransitionThumb(in Bitmap srcThumb, int startX, int startY,
             IRemoteCallback startedCallback, boolean scaleUp);
+    void overridePendingAppTransitionAspectScaledThumb(in Bitmap srcThumb, int startX,
+            int startY, IRemoteCallback startedCallback, boolean scaleUp);
     void executeAppTransition();
     void setAppStartingWindow(IBinder token, String pkg, int theme,
             in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 19dd583..854e6be 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3072,7 +3072,7 @@
         boolean more = false;
         final long drawingTime = getDrawingTime();
 
-
+        if (usingRenderNodeProperties) canvas.insertReorderBarrier();
         // Only use the preordered list if not HW accelerated, since the HW pipeline will do the
         // draw reordering internally
         final ArrayList<View> preorderedList = usingRenderNodeProperties
@@ -3099,6 +3099,7 @@
                 more |= drawChild(canvas, child, drawingTime);
             }
         }
+        if (usingRenderNodeProperties) canvas.insertInorderBarrier();
 
         if (debugDraw()) {
             onDebugDraw(canvas);
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index 0b15eb6..818efaa 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -156,6 +156,12 @@
 
     private boolean mCollapsible;
 
+    private final Runnable mShowOverflowMenuRunnable = new Runnable() {
+        @Override public void run() {
+            showOverflowMenu();
+        }
+    };
+
     public Toolbar(Context context) {
         this(context, null);
     }
@@ -404,6 +410,7 @@
             ensureLogoView();
             if (mLogoView.getParent() == null) {
                 addSystemView(mLogoView);
+                updateChildVisibilityForExpandedActionView(mLogoView);
             }
         } else if (mLogoView != null && mLogoView.getParent() != null) {
             removeView(mLogoView);
@@ -545,6 +552,7 @@
             }
             if (mTitleTextView.getParent() == null) {
                 addSystemView(mTitleTextView);
+                updateChildVisibilityForExpandedActionView(mTitleTextView);
             }
         } else if (mTitleTextView != null && mTitleTextView.getParent() != null) {
             removeView(mTitleTextView);
@@ -598,6 +606,7 @@
             }
             if (mSubtitleTextView.getParent() == null) {
                 addSystemView(mSubtitleTextView);
+                updateChildVisibilityForExpandedActionView(mSubtitleTextView);
             }
         } else if (mSubtitleTextView != null && mSubtitleTextView.getParent() != null) {
             removeView(mSubtitleTextView);
@@ -728,6 +737,7 @@
             ensureNavButtonView();
             if (mNavButtonView.getParent() == null) {
                 addSystemView(mNavButtonView);
+                updateChildVisibilityForExpandedActionView(mNavButtonView);
             }
         } else if (mNavButtonView != null && mNavButtonView.getParent() != null) {
             removeView(mNavButtonView);
@@ -979,6 +989,13 @@
     @Override
     protected Parcelable onSaveInstanceState() {
         SavedState state = new SavedState(super.onSaveInstanceState());
+
+        if (mExpandedMenuPresenter != null && mExpandedMenuPresenter.mCurrentExpandedItem != null) {
+            state.expandedMenuItemId = mExpandedMenuPresenter.mCurrentExpandedItem.getItemId();
+        }
+
+        state.isOverflowOpen = isOverflowMenuShowing();
+
         return state;
     }
 
@@ -986,6 +1003,29 @@
     protected void onRestoreInstanceState(Parcelable state) {
         final SavedState ss = (SavedState) state;
         super.onRestoreInstanceState(ss.getSuperState());
+
+        final Menu menu = mMenuView != null ? mMenuView.peekMenu() : null;
+        if (ss.expandedMenuItemId != 0 && mExpandedMenuPresenter != null && menu != null) {
+            final MenuItem item = menu.findItem(ss.expandedMenuItemId);
+            if (item != null) {
+                item.expandActionView();
+            }
+        }
+
+        if (ss.isOverflowOpen) {
+            postShowOverflowMenu();
+        }
+    }
+
+    private void postShowOverflowMenu() {
+        removeCallbacks(mShowOverflowMenuRunnable);
+        post(mShowOverflowMenuRunnable);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        removeCallbacks(mShowOverflowMenuRunnable);
     }
 
     /**
@@ -1591,6 +1631,13 @@
         }
     }
 
+    private void updateChildVisibilityForExpandedActionView(View child) {
+        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+        if (lp.mViewType != LayoutParams.EXPANDED && child != mMenuView) {
+            child.setVisibility(mExpandedActionView != null ? GONE : VISIBLE);
+        }
+    }
+
     /**
      * Force the toolbar to collapse to zero-height during measurement if
      * it could be considered "empty" (no visible elements with nonzero measured size)
@@ -1673,8 +1720,13 @@
     }
 
     static class SavedState extends BaseSavedState {
+        public int expandedMenuItemId;
+        public boolean isOverflowOpen;
+
         public SavedState(Parcel source) {
             super(source);
+            expandedMenuItemId = source.readInt();
+            isOverflowOpen = source.readInt() != 0;
         }
 
         public SavedState(Parcelable superState) {
@@ -1684,6 +1736,8 @@
         @Override
         public void writeToParcel(Parcel out, int flags) {
             super.writeToParcel(out, flags);
+            out.writeInt(expandedMenuItemId);
+            out.writeInt(isOverflowOpen ? 1 : 0);
         }
 
         public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index b06edc5..71cf391 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -34,8 +34,8 @@
 import android.os.UserHandle;
 import android.os.storage.IMountService;
 import android.os.storage.StorageManager;
-import android.phone.PhoneManager;
 import android.provider.Settings;
+import android.telecomm.TelecommManager;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.IWindowManager;
@@ -1440,7 +1440,7 @@
         }
 
         int textId;
-        if (getPhoneManager().isInAPhoneCall()) {
+        if (getTelecommManager().isInCall()) {
             // show "return to call" text and show phone icon
             textId = R.string.lockscreen_return_to_call;
             int phoneCallIcon = showIcon ? R.drawable.stat_sys_phone_call : 0;
@@ -1458,11 +1458,11 @@
      * on various lockscreens.
      */
     public void resumeCall() {
-        getPhoneManager().showCallScreen(false);
+        getTelecommManager().showInCallScreen(false);
     }
 
-    private PhoneManager getPhoneManager() {
-        return (PhoneManager) mContext.getSystemService(Context.PHONE_SERVICE);
+    private TelecommManager getTelecommManager() {
+        return (TelecommManager) mContext.getSystemService(Context.TELECOMM_SERVICE);
     }
 
     private void finishBiometricWeak() {
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index e02aa5e..6146fff 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -66,6 +66,7 @@
         } else {
             shader->resetLocalMatrix();
         }
+        shader->setGenerationID(shader->getGenerationID() + 1);
     }
 }
 
diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
index a728455..31c7b9f 100644
--- a/core/jni/android_hardware_camera2_DngCreator.cpp
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -653,6 +653,119 @@
     return OK;
 }
 
+/**
+ * Write CFA pattern for given CFA enum into cfaOut.  cfaOut must have length >= 4.
+ * Returns OK on success, or a negative error code if the CFA enum was invalid.
+ */
+static status_t convertCFA(uint8_t cfaEnum, /*out*/uint8_t* cfaOut) {
+    camera_metadata_enum_android_sensor_info_color_filter_arrangement_t cfa =
+            static_cast<camera_metadata_enum_android_sensor_info_color_filter_arrangement_t>(
+            cfaEnum);
+    switch(cfa) {
+        case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB: {
+            cfaOut[0] = 0;
+            cfaOut[1] = 1;
+            cfaOut[2] = 1;
+            cfaOut[3] = 2;
+            break;
+        }
+        case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG: {
+            cfaOut[0] = 1;
+            cfaOut[1] = 0;
+            cfaOut[2] = 2;
+            cfaOut[3] = 1;
+            break;
+        }
+        case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG: {
+            cfaOut[0] = 1;
+            cfaOut[1] = 2;
+            cfaOut[2] = 0;
+            cfaOut[3] = 1;
+            break;
+        }
+        case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR: {
+            cfaOut[0] = 2;
+            cfaOut[1] = 1;
+            cfaOut[2] = 1;
+            cfaOut[3] = 0;
+            break;
+        }
+        default: {
+            return BAD_VALUE;
+        }
+    }
+    return OK;
+}
+
+/**
+ * Convert the CFA layout enum to an OpcodeListBuilder::CfaLayout enum, defaults to
+ * RGGB for an unknown enum.
+ */
+static OpcodeListBuilder::CfaLayout convertCFAEnumToOpcodeLayout(uint8_t cfaEnum) {
+    camera_metadata_enum_android_sensor_info_color_filter_arrangement_t cfa =
+            static_cast<camera_metadata_enum_android_sensor_info_color_filter_arrangement_t>(
+            cfaEnum);
+    switch(cfa) {
+        case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB: {
+            return OpcodeListBuilder::CFA_RGGB;
+        }
+        case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG: {
+            return OpcodeListBuilder::CFA_GRBG;
+        }
+        case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG: {
+            return OpcodeListBuilder::CFA_GBRG;
+        }
+        case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR: {
+            return OpcodeListBuilder::CFA_BGGR;
+        }
+        default: {
+            return OpcodeListBuilder::CFA_RGGB;
+        }
+    }
+}
+
+/**
+ * For each color plane, find the corresponding noise profile coefficients given in the
+ * per-channel noise profile.  If multiple channels in the CFA correspond to a color in the color
+ * plane, this method takes the pair of noise profile coefficients with the higher S coefficient.
+ *
+ * perChannelNoiseProfile - numChannels * 2 noise profile coefficients.
+ * cfa - numChannels color channels corresponding to each of the per-channel noise profile
+ *       coefficients.
+ * numChannels - the number of noise profile coefficient pairs and color channels given in
+ *       the perChannelNoiseProfile and cfa arguments, respectively.
+ * planeColors - the color planes in the noise profile output.
+ * numPlanes - the number of planes in planeColors and pairs of coefficients in noiseProfile.
+ * noiseProfile - 2 * numPlanes doubles containing numPlanes pairs of noise profile coefficients.
+ *
+ * returns OK, or a negative error code on failure.
+ */
+static status_t generateNoiseProfile(const double* perChannelNoiseProfile, uint8_t* cfa,
+        size_t numChannels, const uint8_t* planeColors, size_t numPlanes,
+        /*out*/double* noiseProfile) {
+
+    for (size_t p = 0; p < numPlanes; ++p) {
+        size_t S = p * 2;
+        size_t O = p * 2 + 1;
+
+        noiseProfile[S] = 0;
+        noiseProfile[O] = 0;
+        bool uninitialized = true;
+        for (size_t c = 0; c < numChannels; ++c) {
+            if (cfa[c] == planeColors[p] && perChannelNoiseProfile[c * 2] > noiseProfile[S]) {
+                noiseProfile[S] = perChannelNoiseProfile[c * 2];
+                noiseProfile[O] = perChannelNoiseProfile[c * 2 + 1];
+                uninitialized = false;
+            }
+        }
+        if (uninitialized) {
+            ALOGE("%s: No valid NoiseProfile coefficients for color plane %u", __FUNCTION__, p);
+            return BAD_VALUE;
+        }
+    }
+    return OK;
+}
+
 // ----------------------------------------------------------------------------
 extern "C" {
 
@@ -745,6 +858,8 @@
     uint32_t imageHeight = 0;
 
     OpcodeListBuilder::CfaLayout opcodeCfaLayout = OpcodeListBuilder::CFA_RGGB;
+    uint8_t cfaPlaneColor[3] = {0, 1, 2};
+    uint8_t cfaEnum = -1;
 
     // TODO: Greensplit.
     // TODO: Add remaining non-essential tags
@@ -841,49 +956,23 @@
         camera_metadata_entry entry =
                         characteristics.find(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT);
         BAIL_IF_EMPTY(entry, env, TAG_CFAPATTERN, writer);
-        camera_metadata_enum_android_sensor_info_color_filter_arrangement_t cfa =
-                static_cast<camera_metadata_enum_android_sensor_info_color_filter_arrangement_t>(
-                entry.data.u8[0]);
-        switch(cfa) {
-            case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB: {
-                uint8_t cfa[4] = {0, 1, 1, 2};
-                BAIL_IF_INVALID(writer->addEntry(TAG_CFAPATTERN, 4, cfa, TIFF_IFD_0),
-                                                env, TAG_CFAPATTERN, writer);
-                opcodeCfaLayout = OpcodeListBuilder::CFA_RGGB;
-                break;
-            }
-            case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG: {
-                uint8_t cfa[4] = {1, 0, 2, 1};
-                BAIL_IF_INVALID(writer->addEntry(TAG_CFAPATTERN, 4, cfa, TIFF_IFD_0),
-                                                env, TAG_CFAPATTERN, writer);
-                opcodeCfaLayout = OpcodeListBuilder::CFA_GRBG;
-                break;
-            }
-            case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG: {
-                uint8_t cfa[4] = {1, 2, 0, 1};
-                BAIL_IF_INVALID(writer->addEntry(TAG_CFAPATTERN, 4, cfa, TIFF_IFD_0),
-                                                env, TAG_CFAPATTERN, writer);
-                opcodeCfaLayout = OpcodeListBuilder::CFA_GBRG;
-                break;
-            }
-            case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR: {
-                uint8_t cfa[4] = {2, 1, 1, 0};
-                BAIL_IF_INVALID(writer->addEntry(TAG_CFAPATTERN, 4, cfa, TIFF_IFD_0),
-                                env, TAG_CFAPATTERN, writer);
-                opcodeCfaLayout = OpcodeListBuilder::CFA_BGGR;
-                break;
-            }
-            default: {
-                jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
-                            "Invalid metadata for tag %d", TAG_CFAPATTERN);
-                return;
-            }
+
+        const int cfaLength = 4;
+        cfaEnum = entry.data.u8[0];
+        uint8_t cfa[cfaLength];
+        if ((err = convertCFA(cfaEnum, /*out*/cfa)) != OK) {
+            jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+                        "Invalid metadata for tag %d", TAG_CFAPATTERN);
         }
+
+        BAIL_IF_INVALID(writer->addEntry(TAG_CFAPATTERN, cfaLength, cfa, TIFF_IFD_0), env,
+                TAG_CFAPATTERN, writer);
+
+        opcodeCfaLayout = convertCFAEnumToOpcodeLayout(cfaEnum);
     }
 
     {
         // Set CFA plane color
-        uint8_t cfaPlaneColor[3] = {0, 1, 2};
         BAIL_IF_INVALID(writer->addEntry(TAG_CFAPLANECOLOR, 3, cfaPlaneColor, TIFF_IFD_0),
                 env, TAG_CFAPLANECOLOR, writer);
     }
@@ -1298,10 +1387,33 @@
         camera_metadata_entry entry =
             results.find(ANDROID_SENSOR_NOISE_PROFILE);
 
+        const status_t numPlaneColors = 3;
+        const status_t numCfaChannels = 4;
+
+        uint8_t cfaOut[numCfaChannels];
+        if ((err = convertCFA(cfaEnum, /*out*/cfaOut)) != OK) {
+            jniThrowException(env, "java/lang/IllegalArgumentException",
+                    "Invalid CFA from camera characteristics");
+            return;
+        }
+
+        double noiseProfile[numPlaneColors * 2];
+
         if (entry.count > 0) {
-            BAIL_IF_INVALID(writer->addEntry(TAG_NOISEPROFILE, entry.count,
-                    entry.data.d, TIFF_IFD_0), env,
-                    TAG_NOISEPROFILE, writer);
+            if (entry.count != numCfaChannels * 2) {
+                ALOGW("%s: Invalid entry count %u for noise profile returned in characteristics,"
+                        " no noise profile tag written...", __FUNCTION__, entry.count);
+            } else {
+                if ((err = generateNoiseProfile(entry.data.d, cfaOut, numCfaChannels,
+                        cfaPlaneColor, numPlaneColors, /*out*/ noiseProfile)) == OK) {
+
+                    BAIL_IF_INVALID(writer->addEntry(TAG_NOISEPROFILE, numPlaneColors * 2,
+                            noiseProfile, TIFF_IFD_0), env, TAG_NOISEPROFILE, writer);
+                } else {
+                    ALOGW("%s: Error converting coefficients for noise profile, no noise profile"
+                            " tag written...", __FUNCTION__);
+                }
+            }
         } else {
             ALOGW("%s: No noise profile found in result metadata.  Image quality may be reduced.",
                     __FUNCTION__);
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index afcfaf6..6080f2a 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -104,6 +104,12 @@
     renderer->setHighContrastText(highContrastText);
 }
 
+static void android_view_GLES20Canvas_insertReorderBarrier(JNIEnv* env, jobject clazz,
+        jlong rendererPtr, jboolean reorderEnable) {
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
+    renderer->insertReorderBarrier(reorderEnable);
+}
+
 static int android_view_GLES20Canvas_prepare(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jboolean opaque) {
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
@@ -859,6 +865,7 @@
     { "nDestroyRenderer",   "(J)V",            (void*) android_view_GLES20Canvas_destroyRenderer },
     { "nSetViewport",       "(JII)V",          (void*) android_view_GLES20Canvas_setViewport },
     { "nSetHighContrastText","(JZ)V",          (void*) android_view_GLES20Canvas_setHighContrastText },
+    { "nInsertReorderBarrier","(JZ)V",         (void*) android_view_GLES20Canvas_insertReorderBarrier },
     { "nPrepare",           "(JZ)I",           (void*) android_view_GLES20Canvas_prepare },
     { "nPrepareDirty",      "(JIIIIZ)I",       (void*) android_view_GLES20Canvas_prepareDirty },
     { "nFinish",            "(J)V",            (void*) android_view_GLES20Canvas_finish },
diff --git a/core/res/res/anim/launch_task_behind_background.xml b/core/res/res/anim/launch_task_behind_target.xml
similarity index 100%
rename from core/res/res/anim/launch_task_behind_background.xml
rename to core/res/res/anim/launch_task_behind_target.xml
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index 3180e58..c0d9995 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -19,9 +19,9 @@
 -->
 <resources>
     <!-- The width that is used when creating thumbnails of applications. -->
-    <dimen name="thumbnail_width">512dp</dimen>
+    <dimen name="thumbnail_width">360dp</dimen>
     <!-- The height that is used when creating thumbnails of applications. -->
-    <dimen name="thumbnail_height">512dp</dimen>
+    <dimen name="thumbnail_height">360dp</dimen>
     <!-- The maximum number of action buttons that should be permitted within
          an action bar/action mode. This will be used to determine how many
          showAsAction="ifRoom" items can fit. "always" items can override this. -->
diff --git a/core/res/res/values-television/styles.xml b/core/res/res/values-television/styles.xml
deleted file mode 100644
index 4c0562f..0000000
--- a/core/res/res/values-television/styles.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!-- Copyright (C) 2014 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.
--->
-
-<resources>
-    <style name="Lighting">
-        <item name="lightY">-300dp</item>
-        <item name="ambientShadowAlpha">0.4</item>
-        <item name="spotShadowAlpha">0.4</item>
-    </style>
-</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index cc8d7cf..e88fe0a 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1952,7 +1952,7 @@
         <!--  When opening an activity in a new task using Intent/FLAG_ACTIVITY_LAUNCH_BEHIND,
               this is the animation that is run on the activity of the new task (which is
               entering the screen and then leaving). -->
-        <attr name="launchTaskBehindBackgroundAnimation" format="reference" />
+        <attr name="launchTaskBehindTargetAnimation" format="reference" />
         <!--  When opening an activity in a new task using Intent.FLAG_ACTIVITY_LAUNCH_BEHIND,
               this is the animation that is run on the activity of the old task (which is
               already on the screen and then stays on). -->
@@ -5531,7 +5531,7 @@
          resource are available in addition to the specific attributes of Fade
          described here. -->
     <declare-styleable name="Fade">
-        <!-- Equivalent to <code>visibilityMode</code>, fadingMode works only
+        <!-- Equivalent to <code>transitionVisibilityMode</code>, fadingMode works only
              with the Fade transition. -->
         <attr name="fadingMode">
             <!-- Fade will only fade appearing items in. -->
@@ -5567,7 +5567,7 @@
     <declare-styleable name="VisibilityTransition">
         <!-- Changes whether the transition supports appearing and/or disappearing Views.
              Corresponds to {@link android.transition.Visibility#setMode(int)}. -->
-        <attr name="visibilityMode">
+        <attr name="transitionVisibilityMode">
             <!-- Only appearing Views will be supported. -->
             <flag name="mode_in" value="1" />
             <!-- Only disappearing Views will be supported. -->
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index 2348951..c9292eb 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -46,10 +46,14 @@
 
     <color name="hint_foreground_material_dark">@color/bright_foreground_disabled_material_dark</color>
     <color name="hint_foreground_material_light">@color/bright_foreground_disabled_material_light</color>
+
     <!-- TODO: This is 40% alpha on the default accent color. -->
-    <color name="highlighted_text_material_dark">#6640c4ff</color>
+    <color name="highlighted_text_material_dark">#6680cbc4</color>
     <!-- TODO: This is 40% alpha on the default accent color. -->
-    <color name="highlighted_text_material_light">#6640c4ff</color>
+    <color name="highlighted_text_material_light">#66009688</color>
+
+    <color name="link_text_material_dark">@color/material_deep_teal_200</color>
+    <color name="link_text_material_light">@color/material_deep_teal_500</color>
 
     <!-- Text & foreground colors -->
     <eat-comment />
@@ -71,114 +75,33 @@
     <!-- Primary & accent colors -->
     <eat-comment />
 
-    <color name="material_red_100">#fff4c7c3</color>
-    <color name="material_red_300">#ffe67c73</color>
-    <color name="material_red_500">#ffdb4437</color>
-    <color name="material_red_700">#ffc53929</color>
-    <color name="material_red_A200">#ffff5252</color>
-    <color name="material_red_A400">#ffff1744</color>
-
-    <color name="material_blue_100">#ffc6dafc</color>
-    <color name="material_blue_300">#ff7baaf7</color>
-    <color name="material_blue_500">#ff4285f4</color>
-    <color name="material_blue_700">#ff3367d6</color>
-    <color name="material_blue_A200">#ff448aff</color>
-    <color name="material_blue_A400">#ff2979ff</color>
-
-    <color name="material_light_blue_A200">#ff40c4ff</color>
-
-    <color name="material_teal_100">#ffb2ebf2</color>
-    <color name="material_teal_300">#ff4dd0e1</color>
-    <color name="material_teal_500">#ff00bcd4</color>
-    <color name="material_teal_700">#ff0097a7</color>
-    <color name="material_teal_A200">#ff18ffff</color>
-    <color name="material_teal_A400">#ff00e5ff</color>
-
-    <color name="material_deep_teal_A200">#ff80cbc4</color>
-    <color name="material_deep_teal_A500">#ff009688</color>
-
-    <color name="material_green_100">#ffb7e1cd</color>
-    <color name="material_green_300">#ff57bb8a</color>
-    <color name="material_green_500">#ff0f9d58</color>
-    <color name="material_green_700">#ff0b8043</color>
-    <color name="material_green_A200">#ff69f0ae</color>
-    <color name="material_green_A400">#ff00e676</color>
-
-    <color name="material_lime_100">#fff0f4c3</color>
-    <color name="material_lime_300">#ffdce775</color>
-    <color name="material_lime_500">#ffcddc39</color>
-    <color name="material_lime_700">#ffafb42b</color>
-    <color name="material_lime_A200">#ffeeff41</color>
-    <color name="material_lime_A400">#ffc6ff00</color>
-
-    <color name="material_yellow_100">#fffce8b2</color>
-    <color name="material_yellow_300">#fff7cb4d</color>
-    <color name="material_yellow_500">#fff4b400</color>
-    <color name="material_yellow_700">#fff09300</color>
-    <color name="material_yellow_A200">#ffffcd40</color>
-    <color name="material_yellow_A400">#ffffbc00</color>
-
-    <color name="material_orange_100">#ffffe0b2</color>
-    <color name="material_orange_300">#ffffb74d</color>
-    <color name="material_orange_500">#ffff9800</color>
-    <color name="material_orange_700">#fff57c00</color>
-    <color name="material_orange_A200">#ffffab40</color>
-    <color name="material_orange_A400">#ffff9100</color>
-
-    <color name="material_deep_orange_100">#fff4c7c3</color>
-    <color name="material_deep_orange_300">#ffe67c73</color>
-    <color name="material_deep_orange_500">#ffff5722</color>
-    <color name="material_deep_orange_700">#ffc53929</color>
-    <color name="material_deep_orange_A200">#ffff5252</color>
-    <color name="material_deep_orange_A400">#ffff1744</color>
-
-    <!-- Neutral colors -->
-    <eat-comment />
-
-    <color name="material_grey_50">#fffafafa</color>
-    <color name="material_grey_100">#fff5f5f5</color>
-    <color name="material_grey_300">#ffeeeeee</color>
-    <color name="material_grey_500">#ffa3a3a3</color>
-    <color name="material_grey_600">#ff757575</color>
-    <color name="material_grey_700">#ff717171</color>
-    <color name="material_grey_900">#ff212121</color>
+    <color name="material_deep_teal_200">#ff80cbc4</color>
+    <color name="material_deep_teal_500">#ff009688</color>
 
     <color name="material_blue_grey_50">#ffeceff1</color>
     <color name="material_blue_grey_100">#ffcfd8dc</color>
-    <color name="material_blue_grey_300">#ff90a4ae</color>
-    <color name="material_blue_grey_400">#ff78909c</color>
-    <color name="material_blue_grey_500">#ff607d8b</color>
-    <color name="material_blue_grey_600">#ff546e7a</color>
-    <color name="material_blue_grey_700">#ff455a64</color>
     <color name="material_blue_grey_800">#ff37474f</color>
-    <!-- Primary color used by Settings -->
     <color name="material_blue_grey_900">#ff263238</color>
-    <!-- Primary dark color used by Settings -->
     <color name="material_blue_grey_950">#ff21272b</color>
 
-    <color name="material_brown_100">#ffd7ccc8</color>
-    <color name="material_brown_300">#ffa1887f</color>
-    <color name="material_brown_500">#ff795548</color>
-    <color name="material_brown_700">#ff5d4037</color>
-
     <!-- Time picker defaults when no theme is set -->
     <eat-comment />
 
     <color name="timepicker_default_background_material">@color/primary_text_default_material_light</color>
     <color name="timepicker_default_text_color_material">@color/black</color>
-    <color name="timepicker_default_ampm_selected_background_color_material">@color/material_light_blue_A200</color>
+    <color name="timepicker_default_ampm_selected_background_color_material">@color/material_deep_teal_200</color>
     <color name="timepicker_default_ampm_unselected_background_color_material">@color/transparent</color>
-    <color name="timepicker_default_selector_color_material">@color/material_light_blue_A200</color>
+    <color name="timepicker_default_selector_color_material">@color/material_deep_teal_200</color>
     <color name="timepicker_default_numbers_background_color_material">@color/transparent</color>
 
     <!-- DatePicker colors -->
     <eat-comment />
 
-    <color name="datepicker_default_header_selector_background_material_light">@android:color/white</color>
+    <color name="datepicker_default_header_selector_background_material_light">@color/white</color>
     <color name="datepicker_default_header_selector_background_material_dark">#ff303030</color>
 
     <color name="datepicker_default_header_dayofweek_background_color_material_light">#999999</color>
-    <color name="datepicker_default_header_dayofweek_background_color_material_dark">@android:color/white</color>
+    <color name="datepicker_default_header_dayofweek_background_color_material_dark">@color/white</color>
 
     <color name="datepicker_default_normal_text_color_material_light">#ff999999</color>
     <color name="datepicker_default_normal_text_color_material_dark">@android:color/white</color>
@@ -192,8 +115,8 @@
     <color name="datepicker_default_pressed_text_color_material_light">#0099cc</color>
     <color name="datepicker_default_pressed_text_color_material_dark">#0099cc</color>
 
-    <color name="datepicker_default_circle_background_color_material_light">@android:color/holo_blue_light</color>
-    <color name="datepicker_default_circle_background_color_material_dark">@android:color/holo_blue_light</color>
+    <color name="datepicker_default_circle_background_color_material_light">@color/material_deep_teal_500</color>
+    <color name="datepicker_default_circle_background_color_material_dark">@color/material_deep_teal_200</color>
 
     <color name="datepicker_default_view_animator_color_material_light">#f2f2f2</color>
     <color name="datepicker_default_view_animator_color_material_dark">#ff303030</color>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index f2466f7..07874c7 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2211,7 +2211,7 @@
   <public type="attr" name="actionModeShareDrawable" />
   <public type="attr" name="actionModeFindDrawable" />
   <public type="attr" name="actionModeWebSearchDrawable" />
-  <public type="attr" name="visibilityMode" />
+  <public type="attr" name="transitionVisibilityMode" />
   <public type="attr" name="minimumHorizontalAngle" />
   <public type="attr" name="minimumVerticalAngle" />
   <public type="attr" name="maximumAngle" />
@@ -2232,7 +2232,7 @@
   <public type="attr" name="multiArch" />
   <public type="attr" name="touchscreenBlocksFocus" />
   <public type="attr" name="windowElevation" />
-  <public type="attr" name="launchTaskBehindBackgroundAnimation" />
+  <public type="attr" name="launchTaskBehindTargetAnimation" />
   <public type="attr" name="launchTaskBehindSourceAnimation" />
   <public type="attr" name="restrictionType" />
   <public type="attr" name="dayOfWeekBackgroundColor" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 8fc9bac..bb0be48 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -82,7 +82,7 @@
         <item name="activityCloseExitAnimation">@anim/activity_close_exit</item>
         <item name="taskOpenEnterAnimation">@anim/task_open_enter</item>
         <item name="taskOpenExitAnimation">@anim/task_open_exit</item>
-        <item name="launchTaskBehindBackgroundAnimation">@anim/launch_task_behind_background</item>
+        <item name="launchTaskBehindTargetAnimation">@anim/launch_task_behind_target</item>
         <item name="launchTaskBehindSourceAnimation">@anim/launch_task_behind_source</item>
         <item name="taskCloseEnterAnimation">@anim/task_close_enter</item>
         <item name="taskCloseExitAnimation">@anim/task_close_exit</item>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 7a208f7..a79bd0a 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -64,8 +64,8 @@
         <item name="textColorHintInverse">@color/hint_foreground_material_light</item>
         <item name="textColorHighlight">@color/highlighted_text_material_dark</item>
         <item name="textColorHighlightInverse">@color/highlighted_text_material_light</item>
-        <item name="textColorLink">@color/material_teal_500</item>
-        <item name="textColorLinkInverse">@color/material_teal_500</item>
+        <item name="textColorLink">@color/link_text_material_dark</item>
+        <item name="textColorLinkInverse">@color/link_text_material_light</item>
         <item name="textColorSearchUrl">@color/search_url_text_material_dark</item>
         <item name="textColorAlertDialogListItem">@color/primary_text_material_dark</item>
 
@@ -371,7 +371,7 @@
         <!-- Color palette -->
         <item name="colorPrimaryDark">@color/material_blue_grey_900</item>
         <item name="colorPrimary">@color/material_blue_grey_800</item>
-        <item name="colorAccent">@color/material_deep_teal_A200</item>
+        <item name="colorAccent">@color/material_deep_teal_200</item>
 
         <item name="colorControlNormal">?attr/textColorSecondary</item>
         <item name="colorControlActivated">?attr/colorAccent</item>
@@ -406,8 +406,8 @@
         <item name="textColorHintInverse">@color/hint_foreground_material_dark</item>
         <item name="textColorHighlight">@color/highlighted_text_material_light</item>
         <item name="textColorHighlightInverse">@color/highlighted_text_material_dark</item>
-        <item name="textColorLink">@color/material_teal_500</item>
-        <item name="textColorLinkInverse">@color/material_teal_500</item>
+        <item name="textColorLink">@color/link_text_material_light</item>
+        <item name="textColorLinkInverse">@color/link_text_material_dark</item>
         <item name="textColorSearchUrl">@color/search_url_text_material_light</item>
         <item name="textColorAlertDialogListItem">@color/primary_text_material_light</item>
 
@@ -713,7 +713,7 @@
         <!-- Color palette -->
         <item name="colorPrimaryDark">@color/material_blue_grey_100</item>
         <item name="colorPrimary">@color/material_blue_grey_50</item>
-        <item name="colorAccent">@color/material_deep_teal_A500</item>
+        <item name="colorAccent">@color/material_deep_teal_500</item>
 
         <item name="colorControlNormal">?attr/textColorSecondary</item>
         <item name="colorControlActivated">?attr/colorAccent</item>
@@ -758,8 +758,8 @@
         <item name="textColorHintInverse">@color/hint_foreground_material_dark</item>
         <item name="textColorHighlight">@color/highlighted_text_material_light</item>
         <item name="textColorHighlightInverse">@color/highlighted_text_material_dark</item>
-        <item name="textColorLink">@color/material_teal_500</item>
-        <item name="textColorLinkInverse">@color/material_teal_500</item>
+        <item name="textColorLink">@color/link_text_material_light</item>
+        <item name="textColorLinkInverse">@color/link_text_material_dark</item>
         <item name="textColorSearchUrl">@color/search_url_text_material_light</item>
         <item name="textColorAlertDialogListItem">@color/primary_text_material_light</item>
 
@@ -796,8 +796,8 @@
         <item name="textColorHintInverse">@color/hint_foreground_material_light</item>
         <item name="textColorHighlight">@color/highlighted_text_material_dark</item>
         <item name="textColorHighlightInverse">@color/highlighted_text_material_light</item>
-        <item name="textColorLink">@color/material_teal_500</item>
-        <item name="textColorLinkInverse">@color/material_teal_500</item>
+        <item name="textColorLink">@color/link_text_material_dark</item>
+        <item name="textColorLinkInverse">@color/link_text_material_light</item>
         <item name="textColorSearchUrl">@color/search_url_text_material_dark</item>
         <item name="textColorAlertDialogListItem">@color/primary_text_material_dark</item>
 
@@ -1214,7 +1214,7 @@
     <style name="Theme.Material.Settings" parent="Theme.Material.Light.DarkActionBar">
         <item name="colorPrimary">@color/material_blue_grey_900</item>
         <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
-        <item name="colorAccent">@color/material_deep_teal_A500</item>
+        <item name="colorAccent">@color/material_deep_teal_500</item>
 
         <item name="dialogTheme">@style/Theme.Material.Settings.Dialog</item>
         <item name="alertDialogTheme">@style/Theme.Material.Settings.Dialog.Alert</item>
@@ -1226,7 +1226,7 @@
     <style name="Theme.Material.Settings.BaseDialog" parent="Theme.Material.Light.BaseDialog">
         <item name="colorPrimary">@color/material_blue_grey_900</item>
         <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
-        <item name="colorAccent">@color/material_deep_teal_A500</item>
+        <item name="colorAccent">@color/material_deep_teal_500</item>
     </style>
 
     <style name="Theme.Material.Settings.Dialog" parent="Theme.Material.Settings.BaseDialog" />
@@ -1234,7 +1234,7 @@
     <style name="Theme.Material.Settings.Dialog.BaseAlert" parent="Theme.Material.Light.Dialog.BaseAlert">
         <item name="colorPrimary">@color/material_blue_grey_900</item>
         <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
-        <item name="colorAccent">@color/material_deep_teal_A500</item>
+        <item name="colorAccent">@color/material_deep_teal_500</item>
     </style>
 
     <style name="Theme.Material.Settings.Dialog.Alert" parent="Theme.Material.Settings.Dialog.BaseAlert" />
@@ -1242,19 +1242,19 @@
     <style name="Theme.Material.Settings.Dialog.Presentation" parent="Theme.Material.Light.Dialog.Presentation">
         <item name="colorPrimary">@color/material_blue_grey_900</item>
         <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
-        <item name="colorAccent">@color/material_deep_teal_A500</item>
+        <item name="colorAccent">@color/material_deep_teal_500</item>
     </style>
 
     <style name="Theme.Material.Settings.SearchBar" parent="Theme.Material.Light.SearchBar">
         <item name="colorPrimary">@color/material_blue_grey_900</item>
         <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
-        <item name="colorAccent">@color/material_deep_teal_A500</item>
+        <item name="colorAccent">@color/material_deep_teal_500</item>
     </style>
 
     <style name="Theme.Material.Settings.CompactMenu" parent="Theme.Material.Light.CompactMenu">
         <item name="colorPrimary">@color/material_blue_grey_900</item>
         <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
-        <item name="colorAccent">@color/material_deep_teal_A500</item>
+        <item name="colorAccent">@color/material_deep_teal_500</item>
     </style>
 
 </resources>
diff --git a/data/sounds/AudioPackage10.mk b/data/sounds/AudioPackage10.mk
index 879e57a..68a87f2 100644
--- a/data/sounds/AudioPackage10.mk
+++ b/data/sounds/AudioPackage10.mk
@@ -22,16 +22,16 @@
 	$(LOCAL_PATH)/effects/ogg/KeypressDelete_48k.ogg:system/media/audio/ui/KeypressDelete.ogg \
 	$(LOCAL_PATH)/effects/ogg/KeypressInvalid_48k.ogg:system/media/audio/ui/KeypressInvalid.ogg \
 	$(LOCAL_PATH)/effects/ogg/KeypressReturn_48k.ogg:system/media/audio/ui/KeypressReturn.ogg \
-	$(LOCAL_PATH)/effects/ogg/VideoRecord_48k.ogg:system/media/audio/ui/VideoRecord.ogg \
+	$(LOCAL_PATH)/effects/material/ogg/VideoRecord_48k.ogg:system/media/audio/ui/VideoRecord.ogg \
 	$(LOCAL_PATH)/effects/ogg/camera_click_48k.ogg:system/media/audio/ui/camera_click.ogg \
 	$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
-	$(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
+	$(LOCAL_PATH)/effects/material/ogg/LowBattery_48k.ogg:system/media/audio/ui/LowBattery.ogg \
 	$(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
 	$(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg \
 	$(LOCAL_PATH)/effects/ogg/Lock_48k.ogg:system/media/audio/ui/Lock.ogg \
 	$(LOCAL_PATH)/effects/ogg/Unlock_48k.ogg:system/media/audio/ui/Unlock.ogg \
 	$(LOCAL_PATH)/effects/ogg/Trusted_48k.ogg:system/media/audio/ui/Trusted.ogg \
-	$(LOCAL_PATH)/effects/ogg/WirelessChargingStarted.ogg:system/media/audio/ui/WirelessChargingStarted.ogg \
+	$(LOCAL_PATH)/effects/material/ogg/WirelessChargingStarted_48k.ogg:system/media/audio/ui/WirelessChargingStarted.ogg \
 	$(LOCAL_PATH)/notifications/ogg/Adara.ogg:system/media/audio/notifications/Adara.ogg \
 	$(LOCAL_PATH)/notifications/ogg/Alya.ogg:system/media/audio/notifications/Alya.ogg \
 	$(LOCAL_PATH)/notifications/ogg/Arcturus.ogg:system/media/audio/notifications/Arcturus.ogg \
diff --git a/data/sounds/AudioPackage11.mk b/data/sounds/AudioPackage11.mk
index 03e205b..f19ed30 100644
--- a/data/sounds/AudioPackage11.mk
+++ b/data/sounds/AudioPackage11.mk
@@ -22,16 +22,16 @@
 	$(LOCAL_PATH)/effects/ogg/KeypressDelete_48k.ogg:system/media/audio/ui/KeypressDelete.ogg \
 	$(LOCAL_PATH)/effects/ogg/KeypressInvalid_48k.ogg:system/media/audio/ui/KeypressInvalid.ogg \
 	$(LOCAL_PATH)/effects/ogg/KeypressReturn_48k.ogg:system/media/audio/ui/KeypressReturn.ogg \
-	$(LOCAL_PATH)/effects/ogg/VideoRecord_48k.ogg:system/media/audio/ui/VideoRecord.ogg \
+	$(LOCAL_PATH)/effects/material/ogg/VideoRecord_48k.ogg:system/media/audio/ui/VideoRecord.ogg \
 	$(LOCAL_PATH)/effects/ogg/camera_click_48k.ogg:system/media/audio/ui/camera_click.ogg \
 	$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
-	$(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
+	$(LOCAL_PATH)/effects/material/ogg/LowBattery_48k.ogg:system/media/audio/ui/LowBattery.ogg \
 	$(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
 	$(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg \
 	$(LOCAL_PATH)/effects/ogg/Lock_48k.ogg:system/media/audio/ui/Lock.ogg \
 	$(LOCAL_PATH)/effects/ogg/Unlock_48k.ogg:system/media/audio/ui/Unlock.ogg \
 	$(LOCAL_PATH)/effects/ogg/Trusted_48k.ogg:system/media/audio/ui/Trusted.ogg \
-	$(LOCAL_PATH)/effects/ogg/WirelessChargingStarted.ogg:system/media/audio/ui/WirelessChargingStarted.ogg \
+	$(LOCAL_PATH)/effects/material/ogg/WirelessChargingStarted_48k.ogg:system/media/audio/ui/WirelessChargingStarted.ogg \
 	$(LOCAL_PATH)/notifications/ogg/Adara.ogg:system/media/audio/notifications/Adara.ogg \
 	$(LOCAL_PATH)/notifications/ogg/Alya.ogg:system/media/audio/notifications/Alya.ogg \
 	$(LOCAL_PATH)/notifications/ogg/Arcturus.ogg:system/media/audio/notifications/Arcturus.ogg \
diff --git a/data/sounds/AudioPackage12.mk b/data/sounds/AudioPackage12.mk
index c37c392..c13689d 100644
--- a/data/sounds/AudioPackage12.mk
+++ b/data/sounds/AudioPackage12.mk
@@ -12,8 +12,8 @@
 NOTIFICATION_FILES := Ariel Ceres Carme Elara Europa Iapetus Io Rhea Salacia Titan Tethys
 RINGTONE_FILES := Callisto Dione Ganymede Luna Oberon Phobos Sedna Titania Triton Umbriel
 EFFECT_FILES := Effect_Tick KeypressReturn KeypressInvalid KeypressDelete KeypressSpacebar KeypressStandard \
-	VideoRecord camera_click camera_focus LowBattery Dock Undock Lock Unlock WirelessChargingStarted \
-	Trusted
+	camera_click camera_focus Dock Undock Lock Unlock Trusted
+MATERIAL_EFFECT_FILES := VideoRecord LowBattery WirelessChargingStarted
 
 PRODUCT_COPY_FILES += $(foreach fn,$(ALARM_FILES),\
 	$(LOCAL_PATH)/alarms/ogg/$(fn).ogg:system/media/audio/alarms/$(fn).ogg)
@@ -26,3 +26,5 @@
 
 PRODUCT_COPY_FILES += $(foreach fn,$(EFFECT_FILES),\
 	$(LOCAL_PATH)/effects/ogg/$(fn).ogg:system/media/audio/ui/$(fn).ogg)
+PRODUCT_COPY_FILES += $(foreach fn,$(MATERIAL_EFFECT_FILES),\
+	$(LOCAL_PATH)/effects/material/ogg/$(fn).ogg:system/media/audio/ui/$(fn).ogg)
diff --git a/data/sounds/AudioPackage12_48.mk b/data/sounds/AudioPackage12_48.mk
index 2a5efb0..6d86baf 100644
--- a/data/sounds/AudioPackage12_48.mk
+++ b/data/sounds/AudioPackage12_48.mk
@@ -12,7 +12,8 @@
 NOTIFICATION_FILES := Ariel Ceres Carme Elara Europa Iapetus Io Rhea Salacia Titan Tethys
 RINGTONE_FILES := Callisto Dione Ganymede Luna Oberon Phobos Sedna Titania Triton Umbriel
 EFFECT_FILES := Effect_Tick KeypressReturn KeypressInvalid KeypressDelete KeypressSpacebar KeypressStandard \
-	VideoRecord camera_click Lock Unlock Trusted
+	camera_click Lock Unlock Trusted
+MATERIAL_EFFECT_FILES := VideoRecord LowBattery WirelessChargingStarted
 
 # Alarms not yet available in 48 kHz
 PRODUCT_COPY_FILES += $(foreach fn,$(ALARM_FILES),\
@@ -26,11 +27,11 @@
 
 PRODUCT_COPY_FILES += $(foreach fn,$(EFFECT_FILES),\
 	$(LOCAL_PATH)/effects/ogg/$(fn)_48k.ogg:system/media/audio/ui/$(fn).ogg)
+PRODUCT_COPY_FILES += $(foreach fn,$(MATERIAL_EFFECT_FILES),\
+	$(LOCAL_PATH)/effects/material/ogg/$(fn)_48k.ogg:system/media/audio/ui/$(fn).ogg)
 
 # no gold-plated version yet
 PRODUCT_COPY_FILES += \
     $(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
-    $(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
-    $(LOCAL_PATH)/effects/ogg/WirelessChargingStarted.ogg:system/media/audio/ui/WirelessChargingStarted.ogg \
     $(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
     $(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg
\ No newline at end of file
diff --git a/data/sounds/AudioPackage13.mk b/data/sounds/AudioPackage13.mk
new file mode 100644
index 0000000..57fe762
--- /dev/null
+++ b/data/sounds/AudioPackage13.mk
@@ -0,0 +1,33 @@
+#
+# Audio Package 13 - L
+#
+# Include this file in a product makefile to include these audio files
+#
+#
+
+LOCAL_PATH := frameworks/base/data/sounds
+
+# Simple files that do not require renaming
+ALARM_FILES := Alarm1 Alarm2 Alarm3 Alarm4 Alarm5 Alarm6 Alarm7 Alarm8 Timer
+NOTIFICATION_FILES := Notification1 Notification2 Notification3 Notification4 \
+	Notification5 Notification6 Notification7 Notification8 Notification9 \
+	Notification10 Notification11
+RINGTONE_FILES := Ringtone1 Ringtone2 Ringtone3 Ringtone4 Ringtone5 Ringtone6 \
+	Ringtone7 Ringtone8 Ringtone9 Ringtone10 Ringtone11 Ringtone12
+EFFECT_FILES := Effect_Tick KeypressReturn KeypressInvalid KeypressDelete KeypressSpacebar KeypressStandard \
+	camera_click camera_focus Dock Undock Lock Unlock Trusted
+MATERIAL_EFFECT_FILES := VideoRecord WirelessChargingStarted LowBattery
+
+PRODUCT_COPY_FILES += $(foreach fn,$(ALARM_FILES),\
+	$(LOCAL_PATH)/alarms/material/ogg/$(fn).ogg:system/media/audio/alarms/$(fn).ogg)
+
+PRODUCT_COPY_FILES += $(foreach fn,$(NOTIFICATION_FILES),\
+	$(LOCAL_PATH)/notifications/material/ogg/$(fn).ogg:system/media/audio/notifications/$(fn).ogg)
+
+PRODUCT_COPY_FILES += $(foreach fn,$(RINGTONE_FILES),\
+	$(LOCAL_PATH)/ringtones/material/ogg/$(fn).ogg:system/media/audio/ringtones/$(fn).ogg)
+
+PRODUCT_COPY_FILES += $(foreach fn,$(EFFECT_FILES),\
+	$(LOCAL_PATH)/effects/ogg/$(fn).ogg:system/media/audio/ui/$(fn).ogg)
+PRODUCT_COPY_FILES += $(foreach fn,$(MATERIAL_EFFECT_FILES),\
+	$(LOCAL_PATH)/effects/material/ogg/$(fn).ogg:system/media/audio/ui/$(fn).ogg)
diff --git a/data/sounds/AudioPackage13_48.mk b/data/sounds/AudioPackage13_48.mk
new file mode 100644
index 0000000..187bccb
--- /dev/null
+++ b/data/sounds/AudioPackage13_48.mk
@@ -0,0 +1,39 @@
+#
+# Audio Package 13 - L (48kHz)
+#
+# Include this file in a product makefile to include these audio files
+#
+#
+
+LOCAL_PATH := frameworks/base/data/sounds
+
+# Simple files that do not require renaming
+ALARM_FILES := Alarm1 Alarm2 Alarm3 Alarm4 Alarm5 Alarm6 Alarm7 Alarm8 Timer
+NOTIFICATION_FILES := Notification1 Notification2 Notification3 Notification4 \
+	Notification5 Notification6 Notification7 Notification8 Notification9 \
+	Notification10 Notification11
+RINGTONE_FILES := Ringtone1 Ringtone2 Ringtone3 Ringtone4 Ringtone5 Ringtone6 \
+	Ringtone7 Ringtone8 Ringtone9 Ringtone10 Ringtone11 Ringtone12
+EFFECT_FILES := Effect_Tick KeypressReturn KeypressInvalid KeypressDelete KeypressSpacebar KeypressStandard \
+	camera_click Lock Unlock Trusted
+MATERIAL_EFFECT_FILES := VideoRecord WirelessChargingStarted LowBattery
+
+PRODUCT_COPY_FILES += $(foreach fn,$(ALARM_FILES),\
+	$(LOCAL_PATH)/alarms/material/ogg/$(fn)_48k.ogg:system/media/audio/alarms/$(fn).ogg)
+
+PRODUCT_COPY_FILES += $(foreach fn,$(NOTIFICATION_FILES),\
+	$(LOCAL_PATH)/notifications/material/ogg/$(fn)_48k.ogg:system/media/audio/notifications/$(fn).ogg)
+
+PRODUCT_COPY_FILES += $(foreach fn,$(RINGTONE_FILES),\
+	$(LOCAL_PATH)/ringtones/material/ogg/$(fn)_48k.ogg:system/media/audio/ringtones/$(fn).ogg)
+
+PRODUCT_COPY_FILES += $(foreach fn,$(EFFECT_FILES),\
+	$(LOCAL_PATH)/effects/ogg/$(fn)_48k.ogg:system/media/audio/ui/$(fn).ogg)
+PRODUCT_COPY_FILES += $(foreach fn,$(MATERIAL_EFFECT_FILES),\
+	$(LOCAL_PATH)/effects/material/ogg/$(fn)_48k.ogg:system/media/audio/ui/$(fn).ogg)
+
+# no gold-plated version yet
+PRODUCT_COPY_FILES += \
+    $(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
+    $(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
+    $(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg
\ No newline at end of file
diff --git a/data/sounds/AudioPackage6.mk b/data/sounds/AudioPackage6.mk
index 3205c0e..89b5f1b 100644
--- a/data/sounds/AudioPackage6.mk
+++ b/data/sounds/AudioPackage6.mk
@@ -18,10 +18,10 @@
 	$(LOCAL_PATH)/effects/ogg/KeypressDelete.ogg:system/media/audio/ui/KeypressDelete.ogg \
 	$(LOCAL_PATH)/effects/ogg/KeypressInvalid.ogg:system/media/audio/ui/KeypressInvalid.ogg \
 	$(LOCAL_PATH)/effects/ogg/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \
-	$(LOCAL_PATH)/effects/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+	$(LOCAL_PATH)/effects/material/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
 	$(LOCAL_PATH)/effects/ogg/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
 	$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
-	$(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
+	$(LOCAL_PATH)/effects/material/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
 	$(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
 	$(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg \
 	$(LOCAL_PATH)/effects/ogg/Lock.ogg:system/media/audio/ui/Lock.ogg \
diff --git a/data/sounds/AudioPackage7.mk b/data/sounds/AudioPackage7.mk
index c92c1d0..065fb84 100644
--- a/data/sounds/AudioPackage7.mk
+++ b/data/sounds/AudioPackage7.mk
@@ -20,10 +20,10 @@
 	$(LOCAL_PATH)/effects/ogg/KeypressDelete_120.ogg:system/media/audio/ui/KeypressDelete.ogg \
 	$(LOCAL_PATH)/effects/ogg/KeypressInvalid_120.ogg:system/media/audio/ui/KeypressInvalid.ogg \
 	$(LOCAL_PATH)/effects/ogg/KeypressReturn_120.ogg:system/media/audio/ui/KeypressReturn.ogg \
-	$(LOCAL_PATH)/effects/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+	$(LOCAL_PATH)/effects/material/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
 	$(LOCAL_PATH)/effects/ogg/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
 	$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
-	$(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
+	$(LOCAL_PATH)/effects/material/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
 	$(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
 	$(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg \
 	$(LOCAL_PATH)/effects/ogg/Lock.ogg:system/media/audio/ui/Lock.ogg \
diff --git a/data/sounds/AudioPackage8.mk b/data/sounds/AudioPackage8.mk
index b8be4e3e..070381d 100644
--- a/data/sounds/AudioPackage8.mk
+++ b/data/sounds/AudioPackage8.mk
@@ -22,10 +22,10 @@
 	$(LOCAL_PATH)/effects/ogg/KeypressDelete.ogg:system/media/audio/ui/KeypressDelete.ogg \
 	$(LOCAL_PATH)/effects/ogg/KeypressInvalid.ogg:system/media/audio/ui/KeypressInvalid.ogg \
 	$(LOCAL_PATH)/effects/ogg/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \
-	$(LOCAL_PATH)/effects/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+	$(LOCAL_PATH)/effects/material/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
 	$(LOCAL_PATH)/effects/ogg/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
 	$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
-	$(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
+	$(LOCAL_PATH)/effects/material/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
 	$(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
 	$(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg \
 	$(LOCAL_PATH)/effects/ogg/Lock.ogg:system/media/audio/ui/Lock.ogg \
diff --git a/data/sounds/AudioPackage9.mk b/data/sounds/AudioPackage9.mk
index 9b761bc..0673811 100644
--- a/data/sounds/AudioPackage9.mk
+++ b/data/sounds/AudioPackage9.mk
@@ -22,10 +22,10 @@
 	$(LOCAL_PATH)/effects/ogg/KeypressDelete.ogg:system/media/audio/ui/KeypressDelete.ogg \
 	$(LOCAL_PATH)/effects/ogg/KeypressInvalid.ogg:system/media/audio/ui/KeypressInvalid.ogg \
 	$(LOCAL_PATH)/effects/ogg/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \
-	$(LOCAL_PATH)/effects/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+	$(LOCAL_PATH)/effects/material/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
 	$(LOCAL_PATH)/effects/ogg/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
 	$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
-	$(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
+	$(LOCAL_PATH)/effects/material/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
 	$(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
 	$(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg \
 	$(LOCAL_PATH)/effects/ogg/Lock.ogg:system/media/audio/ui/Lock.ogg \
diff --git a/data/sounds/alarms/material/ogg/Alarm1.ogg b/data/sounds/alarms/material/ogg/Alarm1.ogg
new file mode 100644
index 0000000..87ecfeb
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm1.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm1_48k.ogg b/data/sounds/alarms/material/ogg/Alarm1_48k.ogg
new file mode 100644
index 0000000..7ca6faa
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm1_48k.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm2.ogg b/data/sounds/alarms/material/ogg/Alarm2.ogg
new file mode 100644
index 0000000..0d96853f
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm2.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm2_48k.ogg b/data/sounds/alarms/material/ogg/Alarm2_48k.ogg
new file mode 100644
index 0000000..133fcb5
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm2_48k.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm3.ogg b/data/sounds/alarms/material/ogg/Alarm3.ogg
new file mode 100644
index 0000000..d381448
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm3.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm3_48k.ogg b/data/sounds/alarms/material/ogg/Alarm3_48k.ogg
new file mode 100644
index 0000000..a53fbb8
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm3_48k.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm4.ogg b/data/sounds/alarms/material/ogg/Alarm4.ogg
new file mode 100644
index 0000000..4529aa8
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm4.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm4_48k.ogg b/data/sounds/alarms/material/ogg/Alarm4_48k.ogg
new file mode 100644
index 0000000..ac8781d
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm4_48k.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm5.ogg b/data/sounds/alarms/material/ogg/Alarm5.ogg
new file mode 100644
index 0000000..61582d5
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm5.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm5_48k.ogg b/data/sounds/alarms/material/ogg/Alarm5_48k.ogg
new file mode 100644
index 0000000..0f0ff03
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm5_48k.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm6.ogg b/data/sounds/alarms/material/ogg/Alarm6.ogg
new file mode 100644
index 0000000..245c4ce
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm6.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm6_48k.ogg b/data/sounds/alarms/material/ogg/Alarm6_48k.ogg
new file mode 100644
index 0000000..b8abc3a
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm6_48k.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm7.ogg b/data/sounds/alarms/material/ogg/Alarm7.ogg
new file mode 100644
index 0000000..0b489bd
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm7.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm7_48k.ogg b/data/sounds/alarms/material/ogg/Alarm7_48k.ogg
new file mode 100644
index 0000000..0fdeab6
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm7_48k.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm8.ogg b/data/sounds/alarms/material/ogg/Alarm8.ogg
new file mode 100644
index 0000000..053b008
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm8.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm8_48k.ogg b/data/sounds/alarms/material/ogg/Alarm8_48k.ogg
new file mode 100644
index 0000000..2107172
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm8_48k.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Timer.ogg b/data/sounds/alarms/material/ogg/Timer.ogg
new file mode 100644
index 0000000..97519aa
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Timer.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Timer_48k.ogg b/data/sounds/alarms/material/ogg/Timer_48k.ogg
new file mode 100644
index 0000000..bd30280
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Timer_48k.ogg
Binary files differ
diff --git a/data/sounds/effects/material/ogg/LowBattery.ogg b/data/sounds/effects/material/ogg/LowBattery.ogg
new file mode 100644
index 0000000..9dbce2b
--- /dev/null
+++ b/data/sounds/effects/material/ogg/LowBattery.ogg
Binary files differ
diff --git a/data/sounds/effects/material/ogg/LowBattery_48k.ogg b/data/sounds/effects/material/ogg/LowBattery_48k.ogg
new file mode 100644
index 0000000..f60f2b1
--- /dev/null
+++ b/data/sounds/effects/material/ogg/LowBattery_48k.ogg
Binary files differ
diff --git a/data/sounds/effects/material/ogg/VideoRecord.ogg b/data/sounds/effects/material/ogg/VideoRecord.ogg
new file mode 100644
index 0000000..e98fabc
--- /dev/null
+++ b/data/sounds/effects/material/ogg/VideoRecord.ogg
Binary files differ
diff --git a/data/sounds/effects/material/ogg/VideoRecord_48k.ogg b/data/sounds/effects/material/ogg/VideoRecord_48k.ogg
new file mode 100644
index 0000000..b1eb780
--- /dev/null
+++ b/data/sounds/effects/material/ogg/VideoRecord_48k.ogg
Binary files differ
diff --git a/data/sounds/effects/material/ogg/WirelessChargingStarted.ogg b/data/sounds/effects/material/ogg/WirelessChargingStarted.ogg
new file mode 100644
index 0000000..db5d2cb
--- /dev/null
+++ b/data/sounds/effects/material/ogg/WirelessChargingStarted.ogg
Binary files differ
diff --git a/data/sounds/effects/material/ogg/WirelessChargingStarted_48k.ogg b/data/sounds/effects/material/ogg/WirelessChargingStarted_48k.ogg
new file mode 100644
index 0000000..adacd47
--- /dev/null
+++ b/data/sounds/effects/material/ogg/WirelessChargingStarted_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification1.ogg b/data/sounds/notifications/material/ogg/Notification1.ogg
new file mode 100644
index 0000000..fc61f70
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification1.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification10.ogg b/data/sounds/notifications/material/ogg/Notification10.ogg
new file mode 100644
index 0000000..347c38d
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification10.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification10_48k.ogg b/data/sounds/notifications/material/ogg/Notification10_48k.ogg
new file mode 100644
index 0000000..1de91de
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification10_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification11.ogg b/data/sounds/notifications/material/ogg/Notification11.ogg
new file mode 100644
index 0000000..ea83b5b
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification11.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification11_48k.ogg b/data/sounds/notifications/material/ogg/Notification11_48k.ogg
new file mode 100644
index 0000000..dba0416
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification11_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification1_48k.ogg b/data/sounds/notifications/material/ogg/Notification1_48k.ogg
new file mode 100644
index 0000000..b2ab648
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification1_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification2.ogg b/data/sounds/notifications/material/ogg/Notification2.ogg
new file mode 100644
index 0000000..0e54844
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification2.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification2_48k.ogg b/data/sounds/notifications/material/ogg/Notification2_48k.ogg
new file mode 100644
index 0000000..4c4af31
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification2_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification3.ogg b/data/sounds/notifications/material/ogg/Notification3.ogg
new file mode 100644
index 0000000..ff17500
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification3.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification3_48k.ogg b/data/sounds/notifications/material/ogg/Notification3_48k.ogg
new file mode 100644
index 0000000..b138284
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification3_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification4.ogg b/data/sounds/notifications/material/ogg/Notification4.ogg
new file mode 100644
index 0000000..ec6e7cb
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification4.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification4_48k.ogg b/data/sounds/notifications/material/ogg/Notification4_48k.ogg
new file mode 100644
index 0000000..2be9332
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification4_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification5.ogg b/data/sounds/notifications/material/ogg/Notification5.ogg
new file mode 100644
index 0000000..f7386a7
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification5.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification5_48k.ogg b/data/sounds/notifications/material/ogg/Notification5_48k.ogg
new file mode 100644
index 0000000..0ffba07
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification5_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification6.ogg b/data/sounds/notifications/material/ogg/Notification6.ogg
new file mode 100644
index 0000000..e4dcf28
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification6.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification6_48k.ogg b/data/sounds/notifications/material/ogg/Notification6_48k.ogg
new file mode 100644
index 0000000..2891de6
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification6_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification7.ogg b/data/sounds/notifications/material/ogg/Notification7.ogg
new file mode 100644
index 0000000..ce94e21
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification7.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification7_48k.ogg b/data/sounds/notifications/material/ogg/Notification7_48k.ogg
new file mode 100644
index 0000000..45c5f0a
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification7_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification8.ogg b/data/sounds/notifications/material/ogg/Notification8.ogg
new file mode 100644
index 0000000..d7c810d
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification8.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification8_48k.ogg b/data/sounds/notifications/material/ogg/Notification8_48k.ogg
new file mode 100644
index 0000000..8b9703e
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification8_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification9.ogg b/data/sounds/notifications/material/ogg/Notification9.ogg
new file mode 100644
index 0000000..e05a529
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification9.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification9_48k.ogg b/data/sounds/notifications/material/ogg/Notification9_48k.ogg
new file mode 100644
index 0000000..599b3fc
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification9_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone1.ogg b/data/sounds/ringtones/material/ogg/Ringtone1.ogg
new file mode 100644
index 0000000..87a05ee
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone1.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone10.ogg b/data/sounds/ringtones/material/ogg/Ringtone10.ogg
new file mode 100644
index 0000000..5e312d2
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone10.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone10_48k.ogg b/data/sounds/ringtones/material/ogg/Ringtone10_48k.ogg
new file mode 100644
index 0000000..cd02cbc
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone10_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone11.ogg b/data/sounds/ringtones/material/ogg/Ringtone11.ogg
new file mode 100644
index 0000000..4786b18
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone11.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone11_48k.ogg b/data/sounds/ringtones/material/ogg/Ringtone11_48k.ogg
new file mode 100644
index 0000000..6b39351
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone11_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone12.ogg b/data/sounds/ringtones/material/ogg/Ringtone12.ogg
new file mode 100644
index 0000000..ff889e6
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone12.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone12_48k.ogg b/data/sounds/ringtones/material/ogg/Ringtone12_48k.ogg
new file mode 100644
index 0000000..68bc35e
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone12_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone1_48k.ogg b/data/sounds/ringtones/material/ogg/Ringtone1_48k.ogg
new file mode 100644
index 0000000..ebf8f32
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone1_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone2.ogg b/data/sounds/ringtones/material/ogg/Ringtone2.ogg
new file mode 100644
index 0000000..b5893bd
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone2.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone2_48k.ogg b/data/sounds/ringtones/material/ogg/Ringtone2_48k.ogg
new file mode 100644
index 0000000..e44d01e
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone2_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone3.ogg b/data/sounds/ringtones/material/ogg/Ringtone3.ogg
new file mode 100644
index 0000000..193e566
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone3.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone3_48k.ogg b/data/sounds/ringtones/material/ogg/Ringtone3_48k.ogg
new file mode 100644
index 0000000..583a1d7
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone3_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone4.ogg b/data/sounds/ringtones/material/ogg/Ringtone4.ogg
new file mode 100644
index 0000000..173f73d
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone4.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone4_48k.ogg b/data/sounds/ringtones/material/ogg/Ringtone4_48k.ogg
new file mode 100644
index 0000000..c98a437
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone4_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone5.ogg b/data/sounds/ringtones/material/ogg/Ringtone5.ogg
new file mode 100644
index 0000000..dd9bc5b
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone5.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone5_48k.ogg b/data/sounds/ringtones/material/ogg/Ringtone5_48k.ogg
new file mode 100644
index 0000000..44855dc
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone5_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone6.ogg b/data/sounds/ringtones/material/ogg/Ringtone6.ogg
new file mode 100644
index 0000000..cf7d1cb
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone6.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone6_48k.ogg b/data/sounds/ringtones/material/ogg/Ringtone6_48k.ogg
new file mode 100644
index 0000000..8abbf98
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone6_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone7.ogg b/data/sounds/ringtones/material/ogg/Ringtone7.ogg
new file mode 100644
index 0000000..e7ff9f4
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone7.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone7_48k.ogg b/data/sounds/ringtones/material/ogg/Ringtone7_48k.ogg
new file mode 100644
index 0000000..1ce7d33
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone7_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone8.ogg b/data/sounds/ringtones/material/ogg/Ringtone8.ogg
new file mode 100644
index 0000000..8aeb3a0
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone8.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone8_48k.ogg b/data/sounds/ringtones/material/ogg/Ringtone8_48k.ogg
new file mode 100644
index 0000000..a2f7f49
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone8_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone9.ogg b/data/sounds/ringtones/material/ogg/Ringtone9.ogg
new file mode 100644
index 0000000..145f474
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone9.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone9_48k.ogg b/data/sounds/ringtones/material/ogg/Ringtone9_48k.ogg
new file mode 100644
index 0000000..7f2e274
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone9_48k.ogg
Binary files differ
diff --git a/docs/html/_redirects.yaml b/docs/html/_redirects.yaml
index c5b6c24..45e2fed 100644
--- a/docs/html/_redirects.yaml
+++ b/docs/html/_redirects.yaml
@@ -59,6 +59,9 @@
 - from: /guide/google/gcm/server-javadoc/...
   to: /reference/com/google/android/gcm/server/package-summary.html
 
+- from: /google/play-services/auth.html
+  to: /google/auth/http-auth.html
+
 - from: /guide/google/play/services.html
   to: /google/play-services/index.html
 
diff --git a/docs/html/google/auth/http-auth.jd b/docs/html/google/auth/http-auth.jd
index 3b2a83f..804ba12 100644
--- a/docs/html/google/auth/http-auth.jd
+++ b/docs/html/google/auth/http-auth.jd
@@ -342,9 +342,9 @@
 "{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context,%20java.lang.String,%20java.lang.String)">
 {@code GoogleAuthUtil.getToken()}</a>, you must provide the app {@link android.content.Context},
 the account name retrieved from the account picker, and the scope for your auth
-token request. The above sample code (and the attached sample) defines these arguments with
-class members that the host activity passes to
-the {@link android.os.AsyncTask} class constructor.</p>
+token request. The above sample code (and the attached sample) defines these
+arguments with class members that the host activity passes to the {@link android.os.AsyncTask} class constructor. For more information about setting the scope, see
+the <a href="#SpecifyingScopes">Specifying Scopes</a> section below. </p>
 
 <p class="note"><strong>Note:</strong>
 As shown by the {@code fetchToken()} method above, you must handle
@@ -397,8 +397,32 @@
 "{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context,%20java.lang.String,%20java.lang.String)">
 {@code GoogleAuthUtil.getToken()}</a>.</p>
 
-
-
+<h3 id="SpecifyingScopes">Specifying scopes</h3>
+<p>The scope string is used to specify which Google services can be accessed by
+  an app using the requested auth token. An auth token can be associated with
+  multiple scopes.</p>
+<p>When specifying the scopes in your auth token request, prefix the
+  scope string with {@code "oauth2:"} followed by a list of one or more OAuth scope
+  values. Use a space to separate each scope value in the list. To see a list of
+  valid OAuth scope values for Google services, browse
+  the <a href="https://developers.google.com/oauthplayground/"
+  class="external-link">OAuth 2.0 Playground</a>.</p>
+<p class="note"><strong>Tip:</strong> Specify {@code "oauth2:&lt;scope&gt;"}
+  for a single scope. Specify
+  {@code "oauth2:&lt;scope1&gt; &lt;scope2&gt; &lt;scopeN&gt;"} for multiple
+  scopes (using a space to separate each scope).</p>
+<p>For example, to access the Google Books API, the scope is
+  {@code "oauth2:https://www.googleapis.com/auth/books"}. To add an additional
+  scope, say for Google+ login, your code might look like this:</p>
+<pre>
+private final static String BOOKS_API_SCOPE
+        = "https://www.googleapis.com/auth/books";
+private fina; static String GPLUS_SCOPE
+        = "https://www.googleapis.com/auth/plus.login";
+private final static String mScopes
+        = "oauth2:" + BOOKS_API_SCOPE + " " + GPLUS_SCOPE;
+String token = GoogleAuthUtil.getToken(mActivity, mEmail, mScopes);
+</pre>
 
 <h2 id="HandleExceptions">Handle Exceptions</h2>
 
diff --git a/docs/html/guide/topics/renderscript/compute.jd b/docs/html/guide/topics/renderscript/compute.jd
index 297a2dc..2e7ce56 100644
--- a/docs/html/guide/topics/renderscript/compute.jd
+++ b/docs/html/guide/topics/renderscript/compute.jd
@@ -159,8 +159,7 @@
 
 <ul>
   <li><strong>{@link android.renderscript}</strong> - The APIs in this class package are
-    available on devices running Android 3.0 (API level 11) and higher. These are the original APIs
-    for RenderScript and are not currently being updated.</li>
+    available on devices running Android 3.0 (API level 11) and higher. </li>
   <li><strong>{@link android.support.v8.renderscript}</strong> - The APIs in this package are
     available through a <a href="{@docRoot}tools/support-library/features.html#v8">Support
     Library</a>, which allows you to use them on devices running Android 2.2 (API level 8) and
@@ -168,8 +167,8 @@
 </ul>
 
 <p>We strongly recommend using the Support Library APIs for accessing RenderScript because they
-  include the latest improvements to the RenderScript compute framework and provide a wider range
-  of device compatibility.</p>
+  provide a wider range of device compatibility. Developers targeting specific versions of 
+  Android can use {@link android.renderscript} if necessary.</p>
 
 
 <h3 id="ide-setup">Using the RenderScript Support Library APIs</h3>
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index f3af8f6..f18694b 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -243,6 +243,12 @@
     /** @hide */
     public void setHighContrastText(boolean highContrastText) {}
 
+    /** @hide */
+    public void insertReorderBarrier() {}
+
+    /** @hide */
+    public void insertInorderBarrier() {}
+
     /**
      * @hide
      */
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 9ac6927..042da5b 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -119,7 +119,7 @@
  * <dd>Defines path string. This is using exactly same format as "d" attribute
  * in the SVG's path data. This is defined in the viewport space.</dd>
  * <dt><code>android:fillColor</code></dt>
- * <dd>Defines the color to fill the path (black if not present).</dd>
+ * <dd>Defines the color to fill the path (none if not present).</dd>
  * <dt><code>android:strokeColor</code></dt>
  * <dd>Defines the color to draw the path outline (none if not present).</dd>
  * <dt><code>android:strokeWidth</code></dt>
@@ -862,7 +862,7 @@
                 }
                 mRenderPath.addPath(path, mFinalPathMatrix);
 
-                if (fullPath.mFillColor != 0) {
+                if (fullPath.mFillColor != Color.TRANSPARENT) {
                     if (mFillPaint == null) {
                         mFillPaint = new Paint();
                         mFillPaint.setColorFilter(mColorFilter);
@@ -873,7 +873,7 @@
                     canvas.drawPath(mRenderPath, mFillPaint);
                 }
 
-                if (fullPath.mStrokeColor != 0) {
+                if (fullPath.mStrokeColor != Color.TRANSPARENT) {
                     if (mStrokePaint == null) {
                         mStrokePaint = new Paint();
                         mStrokePaint.setColorFilter(mColorFilter);
@@ -1237,9 +1237,9 @@
         // Variables below need to be copied (deep copy if applicable) for mutation.
         private int[] mThemeAttrs;
 
-        int mStrokeColor = 0;
+        int mStrokeColor = Color.TRANSPARENT;
         float mStrokeWidth = 0;
-        int mFillColor = Color.BLACK;
+        int mFillColor = Color.TRANSPARENT;
         int mFillRule;
         float mTrimPathStart = 0;
         float mTrimPathEnd = 1;
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index 1af497c..11568d2 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -954,6 +954,7 @@
         DENSITY_XHIGH = ACONFIGURATION_DENSITY_XHIGH,
         DENSITY_XXHIGH = ACONFIGURATION_DENSITY_XXHIGH,
         DENSITY_XXXHIGH = ACONFIGURATION_DENSITY_XXXHIGH,
+        DENSITY_ANY = ACONFIGURATION_DENSITY_ANY,
         DENSITY_NONE = ACONFIGURATION_DENSITY_NONE
     };
     
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 239d682..3f014ef 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -2206,13 +2206,30 @@
 
         if (screenType || o.screenType) {
             if (density != o.density) {
-                // density is tough.  Any density is potentially useful
+                // Use the system default density (DENSITY_MEDIUM, 160dpi) if none specified.
+                const int thisDensity = density ? density : int(ResTable_config::DENSITY_MEDIUM);
+                const int otherDensity = o.density ? o.density : int(ResTable_config::DENSITY_MEDIUM);
+
+                // We always prefer DENSITY_ANY over scaling a density bucket.
+                if (thisDensity == ResTable_config::DENSITY_ANY) {
+                    return true;
+                } else if (otherDensity == ResTable_config::DENSITY_ANY) {
+                    return false;
+                }
+
+                int requestedDensity = requested->density;
+                if (requested->density == 0 ||
+                        requested->density == ResTable_config::DENSITY_ANY) {
+                    requestedDensity = ResTable_config::DENSITY_MEDIUM;
+                }
+
+                // DENSITY_ANY is now dealt with. We should look to
+                // pick a density bucket and potentially scale it.
+                // Any density is potentially useful
                 // because the system will scale it.  Scaling down
                 // is generally better than scaling up.
-                // Default density counts as 160dpi (the system default)
-                // TODO - remove 160 constants
-                int h = (density?density:160);
-                int l = (o.density?o.density:160);
+                int h = thisDensity;
+                int l = otherDensity;
                 bool bImBigger = true;
                 if (l > h) {
                     int t = h;
@@ -2221,17 +2238,16 @@
                     bImBigger = false;
                 }
 
-                int reqValue = (requested->density?requested->density:160);
-                if (reqValue >= h) {
+                if (requestedDensity >= h) {
                     // requested value higher than both l and h, give h
                     return bImBigger;
                 }
-                if (l >= reqValue) {
+                if (l >= requestedDensity) {
                     // requested value lower than both l and h, give l
                     return !bImBigger;
                 }
                 // saying that scaling down is 2x better than up
-                if (((2 * l) - reqValue) * h > reqValue * reqValue) {
+                if (((2 * l) - requestedDensity) * h > requestedDensity * requestedDensity) {
                     return !bImBigger;
                 } else {
                     return bImBigger;
@@ -2702,6 +2718,9 @@
             case ResTable_config::DENSITY_NONE:
                 res.append("nodpi");
                 break;
+            case ResTable_config::DENSITY_ANY:
+                res.append("anydpi");
+                break;
             default:
                 res.appendFormat("%ddpi", dtohs(density));
                 break;
diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk
index 4ff6eec..a10c387 100644
--- a/libs/androidfw/tests/Android.mk
+++ b/libs/androidfw/tests/Android.mk
@@ -21,8 +21,9 @@
 LOCAL_PATH:= $(call my-dir)
 testFiles := \
     ByteBucketArray_test.cpp \
+    Config_test.cpp \
+    ConfigLocale_test.cpp \
     Idmap_test.cpp \
-    ResourceTypes_test.cpp \
     ResTable_test.cpp \
     Split_test.cpp \
     TypeWrappers_test.cpp \
diff --git a/libs/androidfw/tests/ResourceTypes_test.cpp b/libs/androidfw/tests/ConfigLocale_test.cpp
similarity index 90%
rename from libs/androidfw/tests/ResourceTypes_test.cpp
rename to libs/androidfw/tests/ConfigLocale_test.cpp
index f00a2d9..4999594 100644
--- a/libs/androidfw/tests/ResourceTypes_test.cpp
+++ b/libs/androidfw/tests/ConfigLocale_test.cpp
@@ -21,7 +21,7 @@
 #include <gtest/gtest.h>
 namespace android {
 
-TEST(ResourceTypesTest, ResourceConfig_packAndUnpack2LetterLanguage) {
+TEST(ConfigLocaleTest, packAndUnpack2LetterLanguage) {
      ResTable_config config;
      config.packLanguage("en");
 
@@ -44,7 +44,7 @@
      EXPECT_EQ(0, out[3]);
 }
 
-TEST(ResourceTypesTest, ResourceConfig_packAndUnpack2LetterRegion) {
+TEST(ConfigLocaleTest, packAndUnpack2LetterRegion) {
      ResTable_config config;
      config.packRegion("US");
 
@@ -59,7 +59,7 @@
      EXPECT_EQ(0, out[3]);
 }
 
-TEST(ResourceTypesTest, ResourceConfig_packAndUnpack3LetterLanguage) {
+TEST(ConfigLocaleTest, packAndUnpack3LetterLanguage) {
      ResTable_config config;
      config.packLanguage("eng");
 
@@ -75,7 +75,7 @@
      EXPECT_EQ(0, out[3]);
 }
 
-TEST(ResourceTypesTest, ResourceConfig_packAndUnpack3LetterLanguageAtOffset16) {
+TEST(ConfigLocaleTest, packAndUnpack3LetterLanguageAtOffset16) {
      ResTable_config config;
      config.packLanguage("tgp");
 
@@ -88,8 +88,8 @@
      // which is equivalent to:
      // 1  [0]   [1]   [2]
      // 1-01111-00110-10011
-     EXPECT_EQ(0xbc, config.language[0]);
-     EXPECT_EQ(0xd3, config.language[1]);
+     EXPECT_EQ(char(0xbc), config.language[0]);
+     EXPECT_EQ(char(0xd3), config.language[1]);
 
      char out[4] = { 1, 1, 1, 1};
      config.unpackLanguage(out);
@@ -99,7 +99,7 @@
      EXPECT_EQ(0, out[3]);
 }
 
-TEST(ResourceTypesTest, ResourceConfig_packAndUnpack3LetterRegion) {
+TEST(ConfigLocaleTest, packAndUnpack3LetterRegion) {
      ResTable_config config;
      config.packRegion("419");
 
@@ -131,7 +131,7 @@
      }
 }
 
-TEST(ResourceTypesTest, IsMoreSpecificThan) {
+TEST(ConfigLocaleTest, IsMoreSpecificThan) {
     ResTable_config l;
     ResTable_config r;
 
@@ -170,7 +170,7 @@
     EXPECT_TRUE(r.isMoreSpecificThan(l));
 }
 
-TEST(ResourceTypesTest, setLocale) {
+TEST(ConfigLocaleTest, setLocale) {
     ResTable_config test;
     test.setBcp47Locale("en-US");
     EXPECT_EQ('e', test.language[0]);
diff --git a/libs/androidfw/tests/Config_test.cpp b/libs/androidfw/tests/Config_test.cpp
new file mode 100644
index 0000000..ef30df4
--- /dev/null
+++ b/libs/androidfw/tests/Config_test.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include <androidfw/ResourceTypes.h>
+#include <utils/Log.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+#include "TestHelpers.h"
+#include <gtest/gtest.h>
+
+namespace android {
+
+static ResTable_config selectBest(const ResTable_config& target,
+        const Vector<ResTable_config>& configs) {
+    ResTable_config bestConfig;
+    memset(&bestConfig, 0, sizeof(bestConfig));
+    const size_t configCount = configs.size();
+    for (size_t i = 0; i < configCount; i++) {
+        const ResTable_config& thisConfig = configs[i];
+        if (!thisConfig.match(target)) {
+            continue;
+        }
+
+        if (thisConfig.isBetterThan(bestConfig, &target)) {
+            bestConfig = thisConfig;
+        }
+    }
+    return bestConfig;
+}
+
+static ResTable_config buildDensityConfig(int density) {
+    ResTable_config config;
+    memset(&config, 0, sizeof(config));
+    config.density = uint16_t(density);
+    config.sdkVersion = 4;
+    return config;
+}
+
+TEST(ConfigTest, shouldSelectBestDensity) {
+    ResTable_config deviceConfig;
+    memset(&deviceConfig, 0, sizeof(deviceConfig));
+    deviceConfig.density = ResTable_config::DENSITY_XHIGH;
+    deviceConfig.sdkVersion = 21;
+
+    Vector<ResTable_config> configs;
+
+    ResTable_config expectedBest = buildDensityConfig(ResTable_config::DENSITY_HIGH);
+    configs.add(expectedBest);
+    ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+
+    expectedBest = buildDensityConfig(ResTable_config::DENSITY_XXHIGH);
+    configs.add(expectedBest);
+    ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+
+    expectedBest = buildDensityConfig(int(ResTable_config::DENSITY_XXHIGH) - 20);
+    configs.add(expectedBest);
+    ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+
+    configs.add(buildDensityConfig(int(ResTable_config::DENSITY_HIGH) + 20));
+    ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+
+    expectedBest = buildDensityConfig(ResTable_config::DENSITY_XHIGH);
+    configs.add(expectedBest);
+    ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+
+    expectedBest = buildDensityConfig(ResTable_config::DENSITY_ANY);
+    expectedBest.sdkVersion = 21;
+    configs.add(expectedBest);
+    ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+}
+
+TEST(ConfigTest, shouldSelectBestDensityWhenNoneSpecified) {
+    ResTable_config deviceConfig;
+    memset(&deviceConfig, 0, sizeof(deviceConfig));
+    deviceConfig.sdkVersion = 21;
+
+    Vector<ResTable_config> configs;
+    configs.add(buildDensityConfig(ResTable_config::DENSITY_HIGH));
+
+    ResTable_config expectedBest = buildDensityConfig(ResTable_config::DENSITY_MEDIUM);
+    configs.add(expectedBest);
+    ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+
+    expectedBest = buildDensityConfig(ResTable_config::DENSITY_ANY);
+    configs.add(expectedBest);
+    ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+}
+
+}  // namespace android.
diff --git a/libs/androidfw/tests/TestHelpers.h b/libs/androidfw/tests/TestHelpers.h
index 75a233a..fe2e5ce 100644
--- a/libs/androidfw/tests/TestHelpers.h
+++ b/libs/androidfw/tests/TestHelpers.h
@@ -3,6 +3,7 @@
 
 #include <ostream>
 
+#include <androidfw/ResourceTypes.h>
 #include <utils/String8.h>
 #include <utils/String16.h>
 
@@ -14,4 +15,16 @@
     return out << android::String8(str).string();
 }
 
+namespace android {
+
+static inline bool operator==(const android::ResTable_config& a, const android::ResTable_config& b) {
+    return memcmp(&a, &b, sizeof(a)) == 0;
+}
+
+static inline ::std::ostream& operator<<(::std::ostream& out, const android::ResTable_config& c) {
+    return out << c.toString().string();
+}
+
+} // namespace android
+
 #endif // __TEST_HELPERS_H
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 6461ee7..d8932ce 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -89,11 +89,9 @@
     layers.clear();
 }
 
-void DisplayListData::addChild(DrawRenderNodeOp* op) {
-    LOG_ALWAYS_FATAL_IF(!op->renderNode(), "DrawRenderNodeOp with no render node!");
-
-    mChildren.push(op);
+size_t DisplayListData::addChild(DrawRenderNodeOp* op) {
     mReferenceHolders.push(op->renderNode());
+    return mChildren.add(op);
 }
 
 }; // namespace uirenderer
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index acfa98e..dea109c 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -115,13 +115,24 @@
  * Data structure that holds the list of commands used in display list stream
  */
 class DisplayListData {
+    friend class DisplayListRenderer;
 public:
+    struct Chunk {
+        // range of included ops in DLD::displayListOps
+        size_t beginOpIndex;
+        size_t endOpIndex;
+
+        // range of included children in DLD::mChildren
+        size_t beginChildIndex;
+        size_t endChildIndex;
+
+        // whether children with non-zero Z in the chunk should be reordered
+        bool reorderChildren;
+    };
+
     DisplayListData();
     ~DisplayListData();
 
-    // allocator into which all ops were allocated
-    LinearAllocator allocator;
-
     // pointers to all ops within display list, pointing into allocator data
     Vector<DisplayListOp*> displayListOps;
 
@@ -138,13 +149,12 @@
     Vector<const SkRegion*> regions;
     Vector<Layer*> layers;
     Vector<Functor*> functors;
-    bool hasDrawOps;
 
-    bool isEmpty() {
-        return !displayListOps.size();
+    const Vector<Chunk>& getChunks() const {
+        return chunks;
     }
 
-    void addChild(DrawRenderNodeOp* childOp);
+    size_t addChild(DrawRenderNodeOp* childOp);
     const Vector<DrawRenderNodeOp*>& children() { return mChildren; }
 
     void refProperty(CanvasPropertyPrimitive* prop) {
@@ -155,12 +165,25 @@
         mReferenceHolders.push(prop);
     }
 
+    size_t getUsedSize() {
+        return allocator.usedSize();
+    }
+    bool isEmpty() {
+        return !hasDrawOps;
+    }
+
 private:
     Vector< sp<VirtualLightRefBase> > mReferenceHolders;
 
     // list of children display lists for quick, non-drawing traversal
     Vector<DrawRenderNodeOp*> mChildren;
 
+    Vector<Chunk> chunks;
+
+    // allocator into which all ops were allocated
+    LinearAllocator allocator;
+    bool hasDrawOps;
+
     void cleanupResources();
 };
 
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 5f533a7..8818510 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1445,6 +1445,7 @@
 
 class DrawRenderNodeOp : public DrawBoundedOp {
     friend class RenderNode; // grant RenderNode access to info of child
+    friend class DisplayListData; // grant DisplayListData access to info of child
 public:
     DrawRenderNodeOp(RenderNode* renderNode, int flags, const mat4& transformFromParent)
             : DrawBoundedOp(0, 0, renderNode->getWidth(), renderNode->getHeight(), 0),
@@ -1452,13 +1453,14 @@
 
     virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
             bool useQuickReject) {
-        if (mRenderNode && mRenderNode->isRenderable() && !mSkipInOrderDraw) {
+        if (mRenderNode->isRenderable() && !mSkipInOrderDraw) {
             mRenderNode->defer(deferStruct, level + 1);
         }
     }
+
     virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
             bool useQuickReject) {
-        if (mRenderNode && mRenderNode->isRenderable() && !mSkipInOrderDraw) {
+        if (mRenderNode->isRenderable() && !mSkipInOrderDraw) {
             mRenderNode->replay(replayStruct, level + 1);
         }
     }
@@ -1469,7 +1471,7 @@
     }
 
     virtual void output(int level, uint32_t logFlags) const {
-        OP_LOG("Draw Display List %p, flags %#x", mRenderNode, mFlags);
+        OP_LOG("Draw RenderNode %p %s, flags %#x", mRenderNode, mRenderNode->getName(), mFlags);
         if (mRenderNode && (logFlags & kOpLogFlag_Recurse)) {
             mRenderNode->output(level + 1);
         }
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 9a9c544..5892978 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -33,10 +33,10 @@
 
 DisplayListRenderer::DisplayListRenderer()
     : mCaches(Caches::getInstance())
-    , mDisplayListData(0)
+    , mDisplayListData(NULL)
     , mTranslateX(0.0f)
     , mTranslateY(0.0f)
-    , mHasTranslate(false)
+    , mDeferredBarrierType(kBarrier_None)
     , mHighContrastText(false)
     , mRestoreSaveCount(-1) {
 }
@@ -68,6 +68,7 @@
 
     initializeSaveStack(0, 0, getWidth(), getHeight(), Vector3());
 
+    mDeferredBarrierType = kBarrier_InOrder;
     mDirtyClip = opaque;
     mRestoreSaveCount = -1;
 
@@ -75,8 +76,8 @@
 }
 
 void DisplayListRenderer::finish() {
-    insertRestoreToCount();
-    insertTranslate();
+    flushRestoreToCount();
+    flushTranslate();
 }
 
 void DisplayListRenderer::interrupt() {
@@ -104,13 +105,13 @@
     }
 
     mRestoreSaveCount--;
-    insertTranslate();
+    flushTranslate();
     StatefulBaseRenderer::restore();
 }
 
 void DisplayListRenderer::restoreToCount(int saveCount) {
     mRestoreSaveCount = saveCount;
-    insertTranslate();
+    flushTranslate();
     StatefulBaseRenderer::restoreToCount(saveCount);
 }
 
@@ -123,10 +124,10 @@
 
 void DisplayListRenderer::translate(float dx, float dy, float dz) {
     // ignore dz, not used at defer time
-    mHasTranslate = true;
+    mHasDeferredTranslate = true;
     mTranslateX += dx;
     mTranslateY += dy;
-    insertRestoreToCount();
+    flushRestoreToCount();
     StatefulBaseRenderer::translate(dx, dy, dz);
 }
 
@@ -174,16 +175,12 @@
 }
 
 status_t DisplayListRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t flags) {
+    LOG_ALWAYS_FATAL_IF(!renderNode, "missing rendernode");
+
     // dirty is an out parameter and should not be recorded,
     // it matters only when replaying the display list
     DrawRenderNodeOp* op = new (alloc()) DrawRenderNodeOp(renderNode, flags, *currentTransform());
-    int opIndex = addDrawOp(op);
-    mDisplayListData->addChild(op);
-
-    if (renderNode->stagingProperties().isProjectionReceiver()) {
-        // use staging property, since recording on UI thread
-        mDisplayListData->projectionReceiveIndex = opIndex;
-    }
+    addRenderNodeOp(op);
 
     return DrawGlInfo::kStatusDone;
 }
@@ -428,30 +425,60 @@
     addStateOp(new (alloc()) SetupPaintFilterOp(clearBits, setBits));
 }
 
-void DisplayListRenderer::insertRestoreToCount() {
+void DisplayListRenderer::insertReorderBarrier(bool enableReorder) {
+    flushRestoreToCount();
+    flushTranslate();
+    mDeferredBarrierType = enableReorder ? kBarrier_OutOfOrder : kBarrier_InOrder;
+}
+
+void DisplayListRenderer::flushRestoreToCount() {
     if (mRestoreSaveCount >= 0) {
-        DisplayListOp* op = new (alloc()) RestoreToCountOp(mRestoreSaveCount);
-        mDisplayListData->displayListOps.add(op);
+        addOpAndUpdateChunk(new (alloc()) RestoreToCountOp(mRestoreSaveCount));
         mRestoreSaveCount = -1;
     }
 }
 
-void DisplayListRenderer::insertTranslate() {
-    if (mHasTranslate) {
+void DisplayListRenderer::flushTranslate() {
+    if (mHasDeferredTranslate) {
         if (mTranslateX != 0.0f || mTranslateY != 0.0f) {
-            DisplayListOp* op = new (alloc()) TranslateOp(mTranslateX, mTranslateY);
-            mDisplayListData->displayListOps.add(op);
+            addOpAndUpdateChunk(new (alloc()) TranslateOp(mTranslateX, mTranslateY));
             mTranslateX = mTranslateY = 0.0f;
         }
-        mHasTranslate = false;
+        mHasDeferredTranslate = false;
     }
 }
 
-int DisplayListRenderer::addStateOp(StateOp* op) {
-    return addOpInternal(op);
+size_t DisplayListRenderer::addOpAndUpdateChunk(DisplayListOp* op) {
+    int insertIndex = mDisplayListData->displayListOps.add(op);
+    if (mDeferredBarrierType != kBarrier_None) {
+        // op is first in new chunk
+        mDisplayListData->chunks.push();
+        DisplayListData::Chunk& newChunk = mDisplayListData->chunks.editTop();
+        newChunk.beginOpIndex = insertIndex;
+        newChunk.endOpIndex = insertIndex + 1;
+        newChunk.reorderChildren = (mDeferredBarrierType == kBarrier_OutOfOrder);
+
+        int nextChildIndex = mDisplayListData->children().size();
+        newChunk.beginChildIndex = newChunk.endChildIndex = nextChildIndex;
+        mDeferredBarrierType = kBarrier_None;
+    } else {
+        // standard case - append to existing chunk
+        mDisplayListData->chunks.editTop().endOpIndex = insertIndex + 1;
+    }
+    return insertIndex;
 }
 
-int DisplayListRenderer::addDrawOp(DrawOp* op) {
+size_t DisplayListRenderer::flushAndAddOp(DisplayListOp* op) {
+    flushRestoreToCount();
+    flushTranslate();
+    return addOpAndUpdateChunk(op);
+}
+
+size_t DisplayListRenderer::addStateOp(StateOp* op) {
+    return flushAndAddOp(op);
+}
+
+size_t DisplayListRenderer::addDrawOp(DrawOp* op) {
     Rect localBounds;
     if (op->getLocalBounds(localBounds)) {
         bool rejected = quickRejectConservative(localBounds.left, localBounds.top,
@@ -460,7 +487,22 @@
     }
 
     mDisplayListData->hasDrawOps = true;
-    return addOpInternal(op);
+    return flushAndAddOp(op);
+}
+
+size_t DisplayListRenderer::addRenderNodeOp(DrawRenderNodeOp* op) {
+    int opIndex = addDrawOp(op);
+    int childIndex = mDisplayListData->addChild(op);
+
+    // update the chunk's child indices
+    DisplayListData::Chunk& chunk = mDisplayListData->chunks.editTop();
+    chunk.endChildIndex = childIndex + 1;
+
+    if (op->renderNode()->stagingProperties().isProjectionReceiver()) {
+        // use staging property, since recording on UI thread
+        mDisplayListData->projectionReceiveIndex = opIndex;
+    }
+    return opIndex;
 }
 
 }; // namespace uirenderer
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index b5c0159..e9c937cb 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -57,6 +57,8 @@
     DisplayListRenderer();
     virtual ~DisplayListRenderer();
 
+    void insertReorderBarrier(bool enableReorder);
+
     DisplayListData* finishRecording();
 
 // ----------------------------------------------------------------------------
@@ -154,19 +156,27 @@
         mHighContrastText = highContrastText;
     }
 private:
-    void insertRestoreToCount();
-    void insertTranslate();
+    enum DeferredBarrierType {
+        kBarrier_None,
+        kBarrier_InOrder,
+        kBarrier_OutOfOrder,
+    };
+
+    void flushRestoreToCount();
+    void flushTranslate();
+    void flushReorderBarrier();
 
     LinearAllocator& alloc() { return mDisplayListData->allocator; }
 
     // Each method returns final index of op
-    int addStateOp(StateOp* op);
-    int addDrawOp(DrawOp* op);
-    int addOpInternal(DisplayListOp* op) {
-        insertRestoreToCount();
-        insertTranslate();
-        return mDisplayListData->displayListOps.add(op);
-    }
+    size_t addOpAndUpdateChunk(DisplayListOp* op);
+    // flushes any deferred operations, and appends the op
+    size_t flushAndAddOp(DisplayListOp* op);
+
+    size_t addStateOp(StateOp* op);
+    size_t addDrawOp(DrawOp* op);
+    size_t addRenderNodeOp(DrawRenderNodeOp* op);
+
 
     template<class T>
     inline const T* refBuffer(const T* srcBuffer, int32_t count) {
@@ -205,11 +215,17 @@
         if (!paint) return NULL;
 
         const SkPaint* paintCopy = mPaintMap.valueFor(paint);
-        if (paintCopy == NULL || paintCopy->getGenerationID() != paint->getGenerationID()) {
-            paintCopy = new SkPaint(*paint);
+        if (paintCopy == NULL
+                || paintCopy->getGenerationID() != paint->getGenerationID()
+                // We can't compare shader pointers because that will always
+                // change as we do partial copying via wrapping. However, if the
+                // shader changes the paint generationID will have changed and
+                // so we don't hit this comparison anyway
+                || !(paint->getShader() && paintCopy->getShader()
+                        && paint->getShader()->getGenerationID() == paintCopy->getShader()->getGenerationID())) {
+            paintCopy = copyPaint(paint);
             // replaceValueFor() performs an add if the entry doesn't exist
             mPaintMap.replaceValueFor(paint, paintCopy);
-            mDisplayListData->paints.add(paintCopy);
         }
 
         return paintCopy;
@@ -218,8 +234,15 @@
     inline SkPaint* copyPaint(const SkPaint* paint) {
         if (!paint) return NULL;
         SkPaint* paintCopy = new SkPaint(*paint);
+        if (paint->getShader()) {
+            SkShader* shaderCopy = SkShader::CreateLocalMatrixShader(
+                    paint->getShader(), paint->getShader()->getLocalMatrix());
+            paintCopy->setShader(shaderCopy);
+            paintCopy->setGenerationID(paint->getGenerationID());
+            shaderCopy->setGenerationID(paint->getShader()->getGenerationID());
+            shaderCopy->unref();
+        }
         mDisplayListData->paints.add(paintCopy);
-
         return paintCopy;
     }
 
@@ -277,7 +300,8 @@
 
     float mTranslateX;
     float mTranslateY;
-    bool mHasTranslate;
+    bool mHasDeferredTranslate;
+    DeferredBarrierType mDeferredBarrierType;
     bool mHighContrastText;
 
     int mRestoreSaveCount;
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 977744f..658265d 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -95,6 +95,7 @@
     properties().debugOutputProperties(level);
     int flags = DisplayListOp::kOpLogFlag_Recurse;
     if (mDisplayListData) {
+        // TODO: consider printing the chunk boundaries here
         for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) {
             mDisplayListData->displayListOps[i]->output(level, flags);
         }
@@ -106,10 +107,10 @@
 int RenderNode::getDebugSize() {
     int size = sizeof(RenderNode);
     if (mStagingDisplayListData) {
-        size += mStagingDisplayListData->allocator.usedSize();
+        size += mStagingDisplayListData->getUsedSize();
     }
     if (mDisplayListData && mDisplayListData != mStagingDisplayListData) {
-        size += mDisplayListData->allocator.usedSize();
+        size += mDisplayListData->getUsedSize();
     }
     return size;
 }
@@ -593,15 +594,16 @@
     issueOperations<ReplayOperationHandler>(replayStruct.mRenderer, handler);
 }
 
-void RenderNode::buildZSortedChildList(Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes) {
-    if (mDisplayListData == NULL || mDisplayListData->children().size() == 0) return;
+void RenderNode::buildZSortedChildList(const DisplayListData::Chunk& chunk,
+        Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes) {
+    if (chunk.beginChildIndex == chunk.endChildIndex) return;
 
-    for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) {
+    for (unsigned int i = chunk.beginChildIndex; i < chunk.endChildIndex; i++) {
         DrawRenderNodeOp* childOp = mDisplayListData->children()[i];
         RenderNode* child = childOp->mRenderNode;
         float childZ = child->properties().getZ();
 
-        if (!MathUtils::isZero(childZ)) {
+        if (!MathUtils::isZero(childZ) && chunk.reorderChildren) {
             zTranslatedNodes.add(ZDrawRenderNodeOpPair(childZ, childOp));
             childOp->mSkipInOrderDraw = true;
         } else if (!child->properties().getProjectBackwards()) {
@@ -610,7 +612,7 @@
         }
     }
 
-    // Z sort 3d children (stable-ness makes z compare fall back to standard drawing order)
+    // Z sort any 3d children (stable-ness makes z compare fall back to standard drawing order)
     std::stable_sort(zTranslatedNodes.begin(), zTranslatedNodes.end());
 }
 
@@ -871,32 +873,35 @@
             handler(new (alloc) DrawLayerOp(mLayer, 0, 0),
                     renderer.getSaveCount() - 1, properties().getClipToBounds());
         } else {
-            Vector<ZDrawRenderNodeOpPair> zTranslatedNodes;
-            buildZSortedChildList(zTranslatedNodes);
-
-            // for 3d root, draw children with negative z values
-            int shadowRestoreTo = issueOperationsOfNegZChildren(zTranslatedNodes, renderer, handler);
-
             DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
-            const int saveCountOffset = renderer.getSaveCount() - 1;
-            const int projectionReceiveIndex = mDisplayListData->projectionReceiveIndex;
-            const int size = static_cast<int>(mDisplayListData->displayListOps.size());
-            for (int i = 0; i < size; i++) {
-                DisplayListOp *op = mDisplayListData->displayListOps[i];
+            for (size_t chunkIndex = 0; chunkIndex < mDisplayListData->getChunks().size(); chunkIndex++) {
+                const DisplayListData::Chunk& chunk = mDisplayListData->getChunks()[chunkIndex];
 
+                Vector<ZDrawRenderNodeOpPair> zTranslatedNodes;
+                buildZSortedChildList(chunk, zTranslatedNodes);
+
+                // for 3d root, draw children with negative z values
+                int shadowRestoreTo = issueOperationsOfNegZChildren(zTranslatedNodes,
+                        renderer, handler);
+                const int saveCountOffset = renderer.getSaveCount() - 1;
+                const int projectionReceiveIndex = mDisplayListData->projectionReceiveIndex;
+
+                for (int opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) {
+                    DisplayListOp *op = mDisplayListData->displayListOps[opIndex];
 #if DEBUG_DISPLAY_LIST
-                op->output(level + 1);
+                    op->output(level + 1);
 #endif
-                logBuffer.writeCommand(level, op->name());
-                handler(op, saveCountOffset, properties().getClipToBounds());
+                    logBuffer.writeCommand(level, op->name());
+                    handler(op, saveCountOffset, properties().getClipToBounds());
 
-                if (CC_UNLIKELY(i == projectionReceiveIndex && mProjectedNodes.size() > 0)) {
-                    issueOperationsOfProjectedChildren(renderer, handler);
+                    if (CC_UNLIKELY(!mProjectedNodes.isEmpty() && opIndex == projectionReceiveIndex)) {
+                        issueOperationsOfProjectedChildren(renderer, handler);
+                    }
                 }
-            }
 
-            // for 3d root, draw children with positive z values
-            issueOperationsOfPosZChildren(shadowRestoreTo, zTranslatedNodes, renderer, handler);
+                // for 3d root, draw children with positive z values
+                issueOperationsOfPosZChildren(shadowRestoreTo, zTranslatedNodes, renderer, handler);
+            }
         }
     }
 
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index afa17d5..18402b2 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -114,7 +114,7 @@
     ANDROID_API int getDebugSize();
 
     bool isRenderable() const {
-        return mDisplayListData && mDisplayListData->hasDrawOps;
+        return mDisplayListData && !mDisplayListData->isEmpty();
     }
 
     bool hasProjectionReceiver() const {
@@ -199,7 +199,8 @@
     template <class T>
     inline void setViewProperties(OpenGLRenderer& renderer, T& handler);
 
-    void buildZSortedChildList(Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes);
+    void buildZSortedChildList(const DisplayListData::Chunk& chunk,
+            Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes);
 
     template<class T>
     inline void issueDrawShadowOperation(const Matrix4& transformFromParent, T& handler);
diff --git a/libs/hwui/SpotShadow.cpp b/libs/hwui/SpotShadow.cpp
index cb20a0b..2178cc7 100644
--- a/libs/hwui/SpotShadow.cpp
+++ b/libs/hwui/SpotShadow.cpp
@@ -647,7 +647,7 @@
     if (lightToPolyZ != 0) {
         // If any caster's vertex is almost above the light, we just keep it as 95%
         // of the height of the light.
-        ratioZ = MathUtils::min(polyVertex.z / lightToPolyZ, CASTER_Z_CAP_RATIO);
+        ratioZ = MathUtils::clamp(polyVertex.z / lightToPolyZ, 0.0f, CASTER_Z_CAP_RATIO);
     }
 
     outline.x = polyVertex.x - ratioZ * (lightCenter.x - polyVertex.x);
@@ -669,6 +669,10 @@
 void SpotShadow::createSpotShadow(bool isCasterOpaque, const Vector3& lightCenter,
         float lightSize, const Vector3* poly, int polyLength, const Vector3& polyCentroid,
         VertexBuffer& shadowTriangleStrip) {
+    if (CC_UNLIKELY(lightCenter.z <= 0)) {
+        ALOGW("Relative Light Z is not positive. No spot shadow!");
+        return;
+    }
     OutlineData outlineData[polyLength];
     Vector2 outlineCentroid;
     // Calculate the projected outline for each polygon's vertices from the light center.
@@ -787,7 +791,7 @@
         // The ratio can be simulated by using the inverse of maximum of ratioVI for
         // all (V).
         distOutline = (outlineData[i].position - outlineCentroid).length();
-        if (distOutline == 0) {
+        if (CC_UNLIKELY(distOutline == 0)) {
             // If the outline has 0 area, then there is no spot shadow anyway.
             ALOGW("Outline has 0 area, no spot shadow!");
             return;
diff --git a/libs/hwui/utils/MathUtils.h b/libs/hwui/utils/MathUtils.h
index 00448b8..d89859b 100644
--- a/libs/hwui/utils/MathUtils.h
+++ b/libs/hwui/utils/MathUtils.h
@@ -76,6 +76,11 @@
         return a < b ? a : b;
     }
 
+    template<typename T>
+    static inline T clamp(T a, T minValue, T maxValue) {
+        return min(max(a, minValue), maxValue);
+    }
+
     inline static float lerp(float v1, float v2, float t) {
         return v1 + ((v2 - v1) * t);
     }
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 0af2457..dae539b 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -2912,13 +2912,13 @@
     }
 
     private boolean isInCommunication() {
-        boolean isInAPhoneCall = false;
+        boolean IsInCall = false;
 
         TelecommManager telecommManager =
                 (TelecommManager) mContext.getSystemService(Context.TELECOMM_SERVICE);
-        isInAPhoneCall = telecommManager.isInAPhoneCall();
+        IsInCall = telecommManager.isInCall();
 
-        return (isInAPhoneCall || getMode() == AudioManager.MODE_IN_COMMUNICATION);
+        return (IsInCall || getMode() == AudioManager.MODE_IN_COMMUNICATION);
     }
 
     /**
diff --git a/media/java/android/media/projection/MediaProjectionInfo.java b/media/java/android/media/projection/MediaProjectionInfo.java
index 7ebc31f..5a65e65 100644
--- a/media/java/android/media/projection/MediaProjectionInfo.java
+++ b/media/java/android/media/projection/MediaProjectionInfo.java
@@ -20,6 +20,8 @@
 import android.os.Parcelable;
 import android.os.UserHandle;
 
+import java.util.Objects;
+
 /** @hide */
 public final class MediaProjectionInfo implements Parcelable {
     private final String mPackageName;
@@ -44,6 +46,21 @@
     }
 
     @Override
+    public boolean equals(Object o) {
+        if (o instanceof MediaProjectionInfo) {
+            final MediaProjectionInfo other = (MediaProjectionInfo) o;
+            return Objects.equals(other.mPackageName, mPackageName)
+                    && Objects.equals(other.mUserHandle, mUserHandle);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mPackageName, mUserHandle);
+    }
+
+    @Override
     public String toString() {
         return "MediaProjectionInfo{mPackageName="
             + mPackageName + ", mUserHandle="
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 45aa6d6..13937e2 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -1170,16 +1170,19 @@
          */
         public void selectTrack(int type, String trackId) {
             if (type == TvTrackInfo.TYPE_AUDIO) {
-                if (trackId != null && !mAudioTracks.contains(trackId)) {
+                if (trackId != null && !containsTrack(mAudioTracks, trackId)) {
                     Log.w(TAG, "Invalid audio trackId: " + trackId);
+                    return;
                 }
             } else if (type == TvTrackInfo.TYPE_VIDEO) {
-                if (trackId != null && !mVideoTracks.contains(trackId)) {
+                if (trackId != null && !containsTrack(mVideoTracks, trackId)) {
                     Log.w(TAG, "Invalid video trackId: " + trackId);
+                    return;
                 }
             } else if (type == TvTrackInfo.TYPE_SUBTITLE) {
-                if (trackId != null && !mSubtitleTracks.contains(trackId)) {
+                if (trackId != null && !containsTrack(mSubtitleTracks, trackId)) {
                     Log.w(TAG, "Invalid subtitle trackId: " + trackId);
+                    return;
                 }
             } else {
                 throw new IllegalArgumentException("invalid type: " + type);
@@ -1195,6 +1198,15 @@
             }
         }
 
+        private boolean containsTrack(List<TvTrackInfo> tracks, String trackId) {
+            for (TvTrackInfo track : tracks) {
+                if (track.getId().equals(trackId)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
         /**
          * Returns the list of tracks for a given type. Returns {@code null} if the information is
          * not available.
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 4efbc30..72a6f88 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -1051,9 +1051,11 @@
         }
 
         private final void runOnMainThread(Runnable action) {
-            if (mHandler.getLooper().isCurrentThread()) {
+            if (mHandler.getLooper().isCurrentThread() && mSessionCallback != null) {
                 action.run();
             } else {
+                // Posts the runnable if this is not called from the main thread or the session
+                // is not initialized yet.
                 mHandler.post(action);
             }
         }
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index 7110db9..d058d64 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -858,6 +858,7 @@
                     mSession.setStreamVolume(mStreamVolume);
                 }
             } else {
+                mSessionCallback = null;
                 if (mListener != null) {
                     mListener.onConnectionFailed(mInputId);
                 }
@@ -869,6 +870,8 @@
             if (this != mSessionCallback) {
                 return;
             }
+            mOverlayViewCreated = false;
+            mOverlayViewFrame = null;
             mSessionCallback = null;
             mSession = null;
             if (mListener != null) {
diff --git a/packages/CaptivePortalLogin/res/values/styles.xml b/packages/CaptivePortalLogin/res/values/styles.xml
index 7ccd3d3..4a99638 100644
--- a/packages/CaptivePortalLogin/res/values/styles.xml
+++ b/packages/CaptivePortalLogin/res/values/styles.xml
@@ -16,7 +16,7 @@
     <style name="AppTheme" parent="AppBaseTheme">
         <!-- All customizations that are NOT specific to a particular API-level can go here. -->
         <!-- Setting's theme's accent color makes ProgressBar useless, reset back. -->
-        <item name="android:colorAccent">@*android:color/material_light_blue_A200</item>
+        <item name="android:colorAccent">@*android:color/material_deep_teal_500</item>
     </style>
 
 </resources>
diff --git a/packages/DocumentsUI/res/layout-sw720dp/activity.xml b/packages/DocumentsUI/res/layout-sw720dp/activity.xml
index c33932d..1cffd17 100644
--- a/packages/DocumentsUI/res/layout-sw720dp/activity.xml
+++ b/packages/DocumentsUI/res/layout-sw720dp/activity.xml
@@ -54,7 +54,7 @@
             android:layout_weight="1"
             android:orientation="vertical"
             android:elevation="8dp"
-            android:background="@*android:color/material_grey_50">
+            android:background="@color/material_grey_50">
 
             <com.android.documentsui.DirectoryContainerView
                 android:id="@+id/container_directory"
@@ -66,7 +66,7 @@
                 android:id="@+id/container_save"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:background="@*android:color/material_grey_50"
+                android:background="@color/material_grey_50"
                 android:elevation="8dp" />
 
         </LinearLayout>
diff --git a/packages/DocumentsUI/res/layout/activity.xml b/packages/DocumentsUI/res/layout/activity.xml
index d580821..120168e 100644
--- a/packages/DocumentsUI/res/layout/activity.xml
+++ b/packages/DocumentsUI/res/layout/activity.xml
@@ -51,7 +51,7 @@
             android:id="@+id/container_save"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:background="@*android:color/material_grey_50"
+            android:background="@color/material_grey_50"
             android:elevation="8dp" />
 
     </LinearLayout>
diff --git a/packages/DocumentsUI/res/layout/fragment_directory.xml b/packages/DocumentsUI/res/layout/fragment_directory.xml
index c8c707e..4717839 100644
--- a/packages/DocumentsUI/res/layout/fragment_directory.xml
+++ b/packages/DocumentsUI/res/layout/fragment_directory.xml
@@ -17,7 +17,7 @@
 <com.android.documentsui.DirectoryView xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:background="@*android:color/material_grey_50">
+    android:background="@color/material_grey_50">
 
     <TextView
         android:id="@android:id/empty"
diff --git a/packages/DocumentsUI/res/values/colors.xml b/packages/DocumentsUI/res/values/colors.xml
index 08159c4..7442b09 100644
--- a/packages/DocumentsUI/res/values/colors.xml
+++ b/packages/DocumentsUI/res/values/colors.xml
@@ -15,10 +15,11 @@
 -->
 
 <resources>
+    <color name="material_grey_50">#fffafafa</color>
+    <color name="material_grey_300">#ffeeeeee</color>
 
     <!-- Half-alpha of material_teal_500 -->
     <color name="accent_color_overlay">#8800bcd4</color>
 
-    <color name="grid_item_background">@*android:color/material_grey_300</color>
-
+    <color name="grid_item_background">@color/material_grey_300</color>
 </resources>
diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml
index 573081c..5cfe046 100644
--- a/packages/DocumentsUI/res/values/styles.xml
+++ b/packages/DocumentsUI/res/values/styles.xml
@@ -25,7 +25,7 @@
 
         <item name="android:colorPrimaryDark">@*android:color/material_blue_grey_900</item>
         <item name="android:colorPrimary">@*android:color/material_blue_grey_800</item>
-        <item name="android:colorAccent">@*android:color/material_teal_500</item>
+        <item name="android:colorAccent">@*android:color/material_deep_teal_500</item>
 
         <item name="android:windowActionBar">false</item>
         <item name="android:windowNoTitle">true</item>
diff --git a/packages/Keyguard/res/values/donottranslate.xml b/packages/Keyguard/res/values/donottranslate.xml
index 2f54406..a4d0ff7 100644
--- a/packages/Keyguard/res/values/donottranslate.xml
+++ b/packages/Keyguard/res/values/donottranslate.xml
@@ -19,7 +19,7 @@
     <string name="abbrev_wday_month_day_no_year">EEEEMMMMd</string>
 
     <!-- Skeleton string format for displaying the date when an alarm is set. -->
-    <string name="abbrev_wday_month_day_no_year_alarm">EEEMMMMd</string>
+    <string name="abbrev_wday_month_day_no_year_alarm">EEEMMMd</string>
 
     <!-- Skeleton string format for displaying the time in 12-hour format. -->
     <string name="clock_12hr_format">hm</string>
diff --git a/packages/PrintSpooler/res/layout/preview_page.xml b/packages/PrintSpooler/res/layout/preview_page.xml
index 76dd76b..df9848b 100644
--- a/packages/PrintSpooler/res/layout/preview_page.xml
+++ b/packages/PrintSpooler/res/layout/preview_page.xml
@@ -32,7 +32,7 @@
         android:id="@+id/page_footer"
         android:layout_width="fill_parent"
         android:layout_height="@dimen/preview_page_footer_height"
-        android:background="@*android:color/material_grey_500"
+        android:background="@color/material_grey_500"
         android:orientation="horizontal">
 
         <TextView
diff --git a/packages/PrintSpooler/res/values/colors.xml b/packages/PrintSpooler/res/values/colors.xml
index de74a41..d1bec32 100644
--- a/packages/PrintSpooler/res/values/colors.xml
+++ b/packages/PrintSpooler/res/values/colors.xml
@@ -24,4 +24,6 @@
 
     <color name="promoted_action_background_color">#FF80CBC4</color>
 
+    <color name="material_grey_500">#ffa3a3a3</color>
+
 </resources>
diff --git a/packages/PrintSpooler/res/values/themes.xml b/packages/PrintSpooler/res/values/themes.xml
index 08702291..db319e9 100644
--- a/packages/PrintSpooler/res/values/themes.xml
+++ b/packages/PrintSpooler/res/values/themes.xml
@@ -16,10 +16,7 @@
 
 <resources>
 
-    <style name="PrintActivity" parent="@android:style/Theme.Material">
-        <item name="android:colorPrimary">@*android:color/material_blue_grey_900</item>
-        <item name="android:colorPrimaryDark">@*android:color/material_blue_grey_950</item>
-        <item name="android:colorAccent">@*android:color/material_deep_teal_A500</item>
+    <style name="PrintActivity" parent="@android:style/Theme.Material.Settings">
         <item name="android:windowIsTranslucent">true</item>
         <item name="android:windowBackground">@android:color/transparent</item>
         <item name="android:windowContentOverlay">@null</item>
diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml
index 783aa03..469b776 100644
--- a/packages/SettingsProvider/AndroidManifest.xml
+++ b/packages/SettingsProvider/AndroidManifest.xml
@@ -16,6 +16,7 @@
                   android:multiprocess="false"
                   android:exported="true"
                   android:writePermission="android.permission.WRITE_SETTINGS"
+                  android:singleUser="true"
                   android:initOrder="100" />
     </application>
 </manifest>
diff --git a/packages/SystemUI/res/anim/recents_from_launcher_enter.xml b/packages/SystemUI/res/anim/recents_from_launcher_enter.xml
index 305a82f..4e1d66d 100644
--- a/packages/SystemUI/res/anim/recents_from_launcher_enter.xml
+++ b/packages/SystemUI/res/anim/recents_from_launcher_enter.xml
@@ -20,9 +20,9 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android"
      android:shareInterpolator="false"
      android:zAdjustment="normal">
-  <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
+  <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
          android:fillEnabled="true"
          android:fillBefore="true" android:fillAfter="true"
          android:interpolator="@android:interpolator/linear"
-         android:duration="200"/>
+         android:duration="100"/>
 </set>
diff --git a/packages/SystemUI/res/anim/recents_from_launcher_exit.xml b/packages/SystemUI/res/anim/recents_from_launcher_exit.xml
index 863591f..afab78d 100644
--- a/packages/SystemUI/res/anim/recents_from_launcher_exit.xml
+++ b/packages/SystemUI/res/anim/recents_from_launcher_exit.xml
@@ -24,5 +24,5 @@
          android:fillEnabled="true"
          android:fillBefore="true" android:fillAfter="true"
          android:interpolator="@android:interpolator/linear_out_slow_in"
-         android:duration="200"/>
+         android:duration="100"/>
 </set>
diff --git a/packages/SystemUI/res/anim/recents_to_launcher_enter.xml b/packages/SystemUI/res/anim/recents_to_launcher_enter.xml
index adcefe0..4e1d66d 100644
--- a/packages/SystemUI/res/anim/recents_to_launcher_enter.xml
+++ b/packages/SystemUI/res/anim/recents_to_launcher_enter.xml
@@ -23,6 +23,6 @@
   <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
          android:fillEnabled="true"
          android:fillBefore="true" android:fillAfter="true"
-         android:interpolator="@android:interpolator/fast_out_linear_in"
-         android:duration="200"/>
+         android:interpolator="@android:interpolator/linear"
+         android:duration="100"/>
 </set>
diff --git a/packages/SystemUI/res/anim/recents_to_launcher_exit.xml b/packages/SystemUI/res/anim/recents_to_launcher_exit.xml
index 863591f..afab78d 100644
--- a/packages/SystemUI/res/anim/recents_to_launcher_exit.xml
+++ b/packages/SystemUI/res/anim/recents_to_launcher_exit.xml
@@ -24,5 +24,5 @@
          android:fillEnabled="true"
          android:fillBefore="true" android:fillAfter="true"
          android:interpolator="@android:interpolator/linear_out_slow_in"
-         android:duration="200"/>
+         android:duration="100"/>
 </set>
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index 5253ee0..4cb8498 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -23,45 +23,7 @@
         android:id="@+id/task_view_thumbnail"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
-    <com.android.systemui.recents.views.TaskViewHeader
-        android:id="@+id/task_view_bar"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/recents_task_bar_height"
-        android:layout_gravity="top|center_horizontal">
-        <com.android.systemui.recents.views.FixedSizeImageView
-            android:id="@+id/application_icon"
-            android:layout_width="@dimen/recents_task_view_application_icon_size"
-            android:layout_height="@dimen/recents_task_view_application_icon_size"
-            android:layout_marginStart="8dp"
-            android:layout_gravity="center_vertical|start"
-            android:padding="8dp"
-            android:background="@drawable/recents_button_bg" />
-        <TextView
-            android:id="@+id/activity_description"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center_vertical|start"
-            android:layout_marginStart="64dp"
-            android:layout_marginEnd="64dp"
-            android:textSize="16sp"
-            android:textColor="#ffffffff"
-            android:text="@string/recents_empty_message"
-            android:fontFamily="sans-serif-medium"
-            android:singleLine="true"
-            android:maxLines="2"
-            android:ellipsize="marquee"
-            android:fadingEdge="horizontal" />
-        <com.android.systemui.recents.views.FixedSizeImageView
-            android:id="@+id/dismiss_task"
-            android:layout_width="48dp"
-            android:layout_height="48dp"
-            android:layout_marginEnd="4dp"
-            android:layout_gravity="center_vertical|end"
-            android:padding="12dp"
-            android:background="@drawable/recents_button_bg"
-            android:visibility="invisible"
-            android:src="@drawable/recents_dismiss_light" />
-    </com.android.systemui.recents.views.TaskViewHeader>
+    <include layout="@layout/recents_task_view_header" />
     <FrameLayout
         android:id="@+id/lock_to_app_fab"
         android:layout_width="48dp"
diff --git a/packages/SystemUI/res/layout/recents_task_view_header.xml b/packages/SystemUI/res/layout/recents_task_view_header.xml
new file mode 100644
index 0000000..f1d8ad0
--- /dev/null
+++ b/packages/SystemUI/res/layout/recents_task_view_header.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+<com.android.systemui.recents.views.TaskViewHeader
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/task_view_bar"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/recents_task_bar_height"
+    android:layout_gravity="top|center_horizontal">
+    <com.android.systemui.recents.views.FixedSizeImageView
+        android:id="@+id/application_icon"
+        android:layout_width="@dimen/recents_task_view_application_icon_size"
+        android:layout_height="@dimen/recents_task_view_application_icon_size"
+        android:layout_marginStart="8dp"
+        android:layout_gravity="center_vertical|start"
+        android:padding="8dp"
+        android:background="@drawable/recents_button_bg" />
+    <TextView
+        android:id="@+id/activity_description"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical|start"
+        android:layout_marginStart="64dp"
+        android:layout_marginEnd="64dp"
+        android:textSize="16sp"
+        android:textColor="#ffffffff"
+        android:text="@string/recents_empty_message"
+        android:fontFamily="sans-serif-medium"
+        android:singleLine="true"
+        android:maxLines="2"
+        android:ellipsize="marquee"
+        android:fadingEdge="horizontal" />
+    <com.android.systemui.recents.views.FixedSizeImageView
+        android:id="@+id/dismiss_task"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
+        android:layout_marginEnd="4dp"
+        android:layout_gravity="center_vertical|end"
+        android:padding="12dp"
+        android:background="@drawable/recents_button_bg"
+        android:visibility="invisible"
+        android:src="@drawable/recents_dismiss_light" />
+</com.android.systemui.recents.views.TaskViewHeader>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index f4f26a2..ef8a426 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -102,6 +102,7 @@
             android:singleLine="true"
             android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
             android:layout_below="@id/clock"
+            systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm"
             />
 
         <com.android.systemui.statusbar.policy.DateView android:id="@+id/date_expanded"
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 52dc000..fa00ebf 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -126,7 +126,7 @@
     <integer name="recents_animate_task_bar_enter_duration">275</integer>
     <!-- The animation delay for animating the first task in. This should roughly be the animation
      duration of the transition in to recents. -->
-    <integer name="recents_animate_task_bar_enter_delay">225</integer>
+    <integer name="recents_animate_task_bar_enter_delay">300</integer>
     <!-- The min animation duration for animating the task bar out. -->
     <integer name="recents_animate_task_exit_to_home_duration">225</integer>
     <!-- The min animation duration for animating the task bar out. -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index c8db284..0af693d 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -115,9 +115,6 @@
     <!-- Diameter of outer shape drawable shown in navbar search. Should be 1/2 of above value -->
     <dimen name="navbar_search_outerring_radius">170dp</dimen>
 
-    <!-- Threshold for swipe-up gesture to activate search dialog -->
-    <dimen name="navbar_search_up_threshhold">40dip</dimen>
-
     <!-- Height of search panel including navigation bar height -->
     <dimen name="navbar_search_panel_height">230dip</dimen>
 
@@ -420,7 +417,7 @@
     <dimen name="search_card_peek_height">100dp</dimen>
 
     <!-- How far the user needs to drag up to invoke search. -->
-    <dimen name="search_panel_threshold">150dp</dimen>
+    <dimen name="search_panel_threshold">100dp</dimen>
 
     <!-- The width/height of the phone/camera/unlock icon on keyguard. -->
     <dimen name="keyguard_affordance_height">56dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index ad568b8..f4d0669 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1323,9 +1323,7 @@
                 // (like recents). Temporary enable/disable (e.g. the "back" button) are
                 // done in KeyguardHostView.
                 flags |= StatusBarManager.DISABLE_RECENT;
-                if (!isAssistantAvailable()) {
-                    flags |= StatusBarManager.DISABLE_SEARCH;
-                }
+                flags |= StatusBarManager.DISABLE_SEARCH;
             }
             if (isShowingAndNotOccluded()) {
                 flags |= StatusBarManager.DISABLE_HOME;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 6cd0f39..f503657 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -239,7 +239,8 @@
         @Override
         public void onDetailItemDisconnect(Item item) {
             if (item == null || item.tag == null) return;
-            mController.stopCasting();
+            final CastDevice device = (CastDevice) item.tag;
+            mController.stopCasting(device);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 354eb55..8710aa2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -22,6 +22,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
@@ -29,6 +30,7 @@
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.UserHandle;
+import android.view.LayoutInflater;
 import android.view.View;
 import com.android.systemui.R;
 import com.android.systemui.RecentsComponent;
@@ -41,6 +43,7 @@
 import com.android.systemui.recents.model.TaskStack;
 import com.android.systemui.recents.views.TaskStackView;
 import com.android.systemui.recents.views.TaskStackViewLayoutAlgorithm;
+import com.android.systemui.recents.views.TaskViewHeader;
 import com.android.systemui.recents.views.TaskViewTransform;
 
 import java.util.ArrayList;
@@ -86,6 +89,10 @@
     int mNavBarHeight;
     int mNavBarWidth;
 
+    // Header (for transition)
+    TaskViewHeader mHeaderBar;
+    TaskStackView mDummyStackView;
+
     // Variables to keep track of if we need to start recents after binding
     View mStatusBarView;
     boolean mTriggeredFromAltTab;
@@ -114,6 +121,7 @@
     public void onStart() {
         // Initialize some static datastructures
         TaskStackViewLayoutAlgorithm.initializeCurve();
+        reloadHeaderBarLayout();
     }
 
     public void onBootCompleted() {
@@ -169,7 +177,7 @@
 
     void showRelativeAffiliatedTask(boolean showNextTask) {
         TaskStack stack = RecentsTaskLoader.getShallowTaskStack(mSystemServicesProxy,
-                Integer.MAX_VALUE);
+                Integer.MAX_VALUE, mContext.getResources());
         // Return early if there are no tasks
         if (stack.getTaskCount() == 0) return;
 
@@ -250,6 +258,28 @@
             mSystemInsets.set(0, mStatusBarHeight, 0, mNavBarHeight);
         }
         sLastScreenshot = null;
+        reloadHeaderBarLayout();
+    }
+
+    /** Prepares the header bar layout. */
+    void reloadHeaderBarLayout() {
+        // Inflate the header bar layout so that we can rebind and draw it for the transition
+        Resources res = mContext.getResources();
+        TaskStack stack = new TaskStack();
+        mDummyStackView = new TaskStackView(mContext, stack);
+        TaskStackViewLayoutAlgorithm algo = mDummyStackView.getStackAlgorithm();
+        Rect taskStackBounds = new Rect(mTaskStackBounds);
+        taskStackBounds.bottom -= mSystemInsets.bottom;
+        algo.computeRects(mWindowRect.width(), mWindowRect.height(), taskStackBounds);
+        Rect taskViewSize = algo.getUntransformedTaskViewSize();
+        int taskBarHeight = res.getDimensionPixelSize(R.dimen.recents_task_bar_height);
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        mHeaderBar = (TaskViewHeader) inflater.inflate(R.layout.recents_task_view_header, null,
+                false);
+        mHeaderBar.measure(
+                View.MeasureSpec.makeMeasureSpec(taskViewSize.width(), View.MeasureSpec.EXACTLY),
+                View.MeasureSpec.makeMeasureSpec(taskBarHeight, View.MeasureSpec.EXACTLY));
+        mHeaderBar.layout(0, 0, taskViewSize.width(), taskBarHeight);
     }
 
     /** Gets the top task. */
@@ -361,27 +391,37 @@
             }
         }
 
-        // If the screenshot fails, then load the first task thumbnail and use that
-        Bitmap firstThumbnail = mSystemServicesProxy.getTaskThumbnail(topTask.id);
-        if (firstThumbnail != null) {
-            // Update the destination rect
-            Rect toTaskRect = getThumbnailTransitionRect(topTask.id, isTopTaskHome);
-            if (toTaskRect.width() > 0 && toTaskRect.height() > 0) {
-                // Create the new thumbnail for the animation down
-                // XXX: We should find a way to optimize this so we don't need to create a new bitmap
-                Bitmap thumbnail = Bitmap.createBitmap(toTaskRect.width(), toTaskRect.height(),
-                        Bitmap.Config.ARGB_8888);
-                int size = Math.min(firstThumbnail.getWidth(), firstThumbnail.getHeight());
-                Canvas c = new Canvas(thumbnail);
-                c.drawBitmap(firstThumbnail, new Rect(0, 0, size, size),
-                        new Rect(0, 0, toTaskRect.width(), toTaskRect.height()), null);
-                c.setBitmap(null);
-                // Recycle the old thumbnail
-                firstThumbnail.recycle();
-                mStartAnimationTriggered = false;
-                return ActivityOptions.makeThumbnailScaleDownAnimation(mStatusBarView,
-                        thumbnail, toTaskRect.left, toTaskRect.top, this);
+        // Update the destination rect
+        Task toTask = new Task();
+        TaskViewTransform toTransform = getThumbnailTransitionTransform(topTask.id, isTopTaskHome,
+                toTask);
+        if (toTransform != null && toTask.key != null) {
+            Rect toTaskRect = toTransform.rect;
+            ActivityInfo info = mSystemServicesProxy.getActivityInfo(
+                    toTask.key.baseIntent.getComponent(), toTask.key.userId);
+            if (toTask.activityIcon == null) {
+                toTask.activityIcon = mSystemServicesProxy.getActivityIcon(info,
+                        toTask.key.userId);
             }
+            if (toTask.activityLabel == null) {
+                toTask.activityLabel = mSystemServicesProxy.getActivityLabel(info);
+            }
+
+            Bitmap thumbnail = Bitmap.createBitmap(toTaskRect.width(), toTaskRect.height(),
+                    Bitmap.Config.ARGB_8888);
+            if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
+                thumbnail.eraseColor(0xFFff0000);
+            } else {
+                Canvas c = new Canvas(thumbnail);
+                c.scale(toTransform.scale, toTransform.scale);
+                mHeaderBar.rebindToTask(toTask);
+                mHeaderBar.draw(c);
+                c.setBitmap(null);
+            }
+
+            mStartAnimationTriggered = false;
+            return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mStatusBarView,
+                    thumbnail, toTaskRect.left, toTaskRect.top, this);
         }
 
         // If both the screenshot and thumbnail fails, then just fall back to the default transition
@@ -389,21 +429,18 @@
     }
 
     /** Returns the transition rect for the given task id. */
-    Rect getThumbnailTransitionRect(int runningTaskId, boolean isTopTaskHome) {
+    TaskViewTransform getThumbnailTransitionTransform(int runningTaskId, boolean isTopTaskHome,
+                                                      Task runningTaskOut) {
         // Get the stack of tasks that we are animating into
-        TaskStack stack = RecentsTaskLoader.getShallowTaskStack(mSystemServicesProxy, -1);
+        TaskStack stack = RecentsTaskLoader.getShallowTaskStack(mSystemServicesProxy, -1,
+                mContext.getResources());
         if (stack.getTaskCount() == 0) {
-            return new Rect();
+            return null;
         }
 
         // Get the stack
-        TaskStackView tsv = new TaskStackView(mContext, stack);
-        TaskStackViewLayoutAlgorithm algo = tsv.getStackAlgorithm();
-        Rect taskStackBounds = new Rect(mTaskStackBounds);
-        taskStackBounds.bottom -= mSystemInsets.bottom;
-        tsv.computeRects(mWindowRect.width(), mWindowRect.height(), taskStackBounds,
-                mTriggeredFromAltTab, isTopTaskHome);
-        tsv.getScroller().setStackScrollToInitialState();
+        mDummyStackView.updateMinMaxScrollForStack(stack, mTriggeredFromAltTab, isTopTaskHome);
+        mDummyStackView.getScroller().setStackScrollToInitialState();
 
         // Find the running task in the TaskStack
         Task task = null;
@@ -415,6 +452,7 @@
                 Task t = tasks.get(i);
                 if (t.key.id == runningTaskId) {
                     task = t;
+                    runningTaskOut.copyFrom(t);
                     break;
                 }
             }
@@ -425,8 +463,9 @@
         }
 
         // Get the transform for the running task
-        mTmpTransform = algo.getStackTransform(task, tsv.getScroller().getStackScroll(), mTmpTransform, null);
-        return new Rect(mTmpTransform.rect);
+        mTmpTransform = mDummyStackView.getStackAlgorithm().getStackTransform(task,
+                mDummyStackView.getScroller().getStackScroll(), mTmpTransform, null);
+        return mTmpTransform;
     }
 
     /** Starts the recents activity */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 3709c43..6f4cf6b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -27,6 +27,8 @@
         public static class App {
             // Enables the screenshot app->Recents transition
             public static final boolean EnableScreenshotAppTransition = false;
+            // Enables debug drawing for the transition thumbnail
+            public static final boolean EnableTransitionThumbnailDebugMode = false;
             // Enables the filtering of tasks according to their grouping
             public static final boolean EnableTaskFiltering = false;
             // Enables clipping of tasks against each other
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 7fafe7a..a5b845d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -384,7 +384,6 @@
 
         // Private API calls to make the shadows look better
         try {
-            Utilities.setShadowProperty("ambientShadowStrength", String.valueOf(35f));
             Utilities.setShadowProperty("ambientRatio", String.valueOf(1.5f));
         } catch (IllegalAccessException e) {
             e.printStackTrace();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 5390daf..b29f3780 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -174,6 +174,7 @@
         int minNumTasksToQuery = 10;
         int numTasksToQuery = Math.max(minNumTasksToQuery, numLatestTasks);
         List<ActivityManager.RecentTaskInfo> tasks = mAm.getRecentTasksForUser(numTasksToQuery,
+                ActivityManager.RECENT_IGNORE_HOME_STACK_TASKS |
                 ActivityManager.RECENT_IGNORE_UNAVAILABLE |
                 ActivityManager.RECENT_INCLUDE_PROFILES |
                 ActivityManager.RECENT_WITH_EXCLUDED, userId);
@@ -185,11 +186,6 @@
             // NOTE: The order of these checks happens in the expected order of the traversal of the
             // tasks
 
-            // Skip tasks from this Recents package
-            if (t.baseIntent.getComponent().getPackageName().equals(mRecentsPackage)) {
-                iter.remove();
-                continue;
-            }
             // Check the first non-recents task, include this task even if it is marked as excluded
             // from recents.  In other words, only remove excluded tasks if it is not the first task
             boolean isExcluded = (t.baseIntent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
@@ -199,11 +195,6 @@
                 continue;
             }
             isFirstValidTask = false;
-            // Skip tasks in the home stack
-            if (isInHomeStack(t.persistentId)) {
-                iter.remove();
-                continue;
-            }
         }
 
         return tasks.subList(0, Math.min(tasks.size(), numLatestTasks));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index 0e2f370..b93c126 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -18,6 +18,7 @@
 
 import android.app.ActivityManager;
 import android.content.ComponentCallbacks2;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.res.Resources;
@@ -31,6 +32,7 @@
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.LinkedHashSet;
@@ -171,9 +173,9 @@
                     // Load the application icon if it is stale or we haven't cached one yet
                     if (cachedIcon == null) {
                         ActivityInfo info = ssp.getActivityInfo(t.key.baseIntent.getComponent(),
-                                t.userId);
+                                t.key.userId);
                         if (info != null) {
-                            cachedIcon = ssp.getActivityIcon(info, t.userId);
+                            cachedIcon = ssp.getActivityIcon(info, t.key.userId);
                         }
                         if (cachedIcon == null) {
                             cachedIcon = mDefaultApplicationIcon;
@@ -228,8 +230,10 @@
     static RecentsTaskLoader sInstance;
 
     SystemServicesProxy mSystemServicesProxy;
+    DrawableLruCache mTaskDescriptionIconCache;
     DrawableLruCache mApplicationIconCache;
     BitmapLruCache mThumbnailCache;
+    StringLruCache mActivityLabelCache;
     TaskResourceLoadQueue mLoadQueue;
     TaskResourceLoader mLoader;
 
@@ -270,8 +274,10 @@
         mSystemServicesProxy = new SystemServicesProxy(context);
         mPackageMonitor = new RecentsPackageMonitor();
         mLoadQueue = new TaskResourceLoadQueue();
+        mTaskDescriptionIconCache = new DrawableLruCache(iconCacheSize);
         mApplicationIconCache = new DrawableLruCache(iconCacheSize);
         mThumbnailCache = new BitmapLruCache(thumbnailCacheSize);
+        mActivityLabelCache = new StringLruCache(100);
         mLoader = new TaskResourceLoader(mLoadQueue, mApplicationIconCache, mThumbnailCache,
                 mDefaultThumbnail, mDefaultApplicationIcon);
     }
@@ -313,6 +319,7 @@
         RecentsConfiguration config = RecentsConfiguration.getInstance();
         Resources res = context.getResources();
         LinkedHashSet<Task> tasksToLoad = new LinkedHashSet<Task>();
+        ArrayList<Task> tasksToAdd = new ArrayList<Task>();
         TaskStack stack = new TaskStack();
         SpaceNode root = new SpaceNode();
         root.setStack(stack);
@@ -325,55 +332,80 @@
         int taskCount = tasks.size();
         for (int i = 0; i < taskCount; i++) {
             ActivityManager.RecentTaskInfo t = tasks.get(i);
-            ActivityInfo info = ssp.getActivityInfo(t.baseIntent.getComponent(), t.userId);
-            if (info == null) continue;
+            Task.TaskKey taskKey = new Task.TaskKey(t.persistentId, t.baseIntent, t.userId,
+                    t.firstActiveTime, t.lastActiveTime);
+            ComponentName cn = t.baseIntent.getComponent();
+            ActivityInfo info = null;
 
             ActivityManager.TaskDescription av = t.taskDescription;
-            String activityLabel = null;
+            String activityLabel  = null;
             Drawable activityIcon = mDefaultApplicationIcon;
             int activityColor = config.taskBarViewDefaultBackgroundColor;
+            boolean loadedActivityIcon = false;
             if (av != null) {
-                activityLabel = (av.getLabel() != null ? av.getLabel() : ssp.getActivityLabel(info));
-                activityIcon = (av.getIcon() != null) ?
+                activityLabel = av.getLabel();
+                activityIcon = mTaskDescriptionIconCache.getAndInvalidateIfModified(taskKey);
+                if (activityIcon == null) {
+                    activityIcon = (av.getIcon() != null) ?
                         ssp.getBadgedIcon(new BitmapDrawable(res, av.getIcon()), t.userId) : null;
+                    if (activityIcon != null) {
+                        mTaskDescriptionIconCache.put(taskKey, activityIcon);
+                    }
+                }
                 if (av.getPrimaryColor() != 0) {
                     activityColor = av.getPrimaryColor();
                 }
-            } else {
-                activityLabel = ssp.getActivityLabel(info);
+                loadedActivityIcon = (activityIcon != null);
+            }
+            // If there is no activity label, then try and read it from the label cache before
+            // loading it from the system
+            if (activityLabel == null) {
+                activityLabel = mActivityLabelCache.getAndInvalidateIfModified(taskKey);
+                if (activityLabel == null) {
+                    if (info == null) {
+                        info = ssp.getActivityInfo(cn, t.userId);
+                    }
+                    activityLabel = ssp.getActivityLabel(info);
+                    mActivityLabelCache.put(taskKey, activityLabel);
+                }
             }
 
             // Create a new task
-            Task task = new Task(t.persistentId, (t.id > -1), t.baseIntent, t.affiliatedTaskId,
-                    t.affiliatedTaskColor, activityLabel, activityIcon, activityColor, t.userId,
-                    t.firstActiveTime, t.lastActiveTime, (i == (taskCount - 1)),
+            Task task = new Task(taskKey, (t.id > -1), t.affiliatedTaskId, t.affiliatedTaskColor,
+                    activityLabel, activityIcon, activityColor, (i == (taskCount - 1)),
                     config.lockToAppEnabled);
 
             // Preload the specified number of apps
             if (i >= (taskCount - preloadCount)) {
-                // Load the icon from the cache if possible
-                task.applicationIcon = mApplicationIconCache.getAndInvalidateIfModified(task.key);
-                if (task.applicationIcon == null) {
-                    // Load the icon from the system
-                    task.applicationIcon = ssp.getActivityIcon(info, task.userId);
-                    if (task.applicationIcon != null) {
-                        mApplicationIconCache.put(task.key, task.applicationIcon);
+                // Load the icon from the cache if possible (only if we don't have an activity icon)
+                if (!loadedActivityIcon) {
+                    task.applicationIcon =
+                            mApplicationIconCache.getAndInvalidateIfModified(taskKey);
+                    if (task.applicationIcon == null) {
+                        // Load the icon from the system
+                        if (info == null) {
+                            info = ssp.getActivityInfo(cn, t.userId);
+                        }
+                        task.applicationIcon = ssp.getActivityIcon(info, taskKey.userId);
+                        if (task.applicationIcon != null) {
+                            mApplicationIconCache.put(taskKey, task.applicationIcon);
+                        }
                     }
-                }
-                if (task.applicationIcon == null) {
-                    // Either the task has changed since the last active time, or it was not
-                    // previously cached, so try and load the task anew.
-                    tasksToLoad.add(task);
+                    if (task.applicationIcon == null) {
+                        // Either the task has changed since the last active time, or it was not
+                        // previously cached, so try and load the task anew.
+                        tasksToLoad.add(task);
+                    }
                 }
 
                 // Load the thumbnail from the cache if possible
-                task.thumbnail = mThumbnailCache.getAndInvalidateIfModified(task.key);
+                task.thumbnail = mThumbnailCache.getAndInvalidateIfModified(taskKey);
                 if (task.thumbnail == null) {
                     // Load the thumbnail from the system
-                    task.thumbnail = ssp.getTaskThumbnail(task.key.id);
+                    task.thumbnail = ssp.getTaskThumbnail(taskKey.id);
                     if (task.thumbnail != null) {
                         task.thumbnail.setHasAlpha(false);
-                        mThumbnailCache.put(task.key, task.thumbnail);
+                        mThumbnailCache.put(taskKey, task.thumbnail);
                     }
                 }
                 if (task.thumbnail == null) {
@@ -384,10 +416,11 @@
             }
 
             // Add the task to the stack
-            stack.addTask(task);
+            tasksToAdd.add(task);
         }
 
         // Simulate the groupings that we describe
+        stack.setTasks(tasksToAdd);
         stack.createAffiliatedGroupings(config);
 
         // Start the task loader and add all the tasks we need to load
@@ -401,21 +434,29 @@
     }
 
     /** Creates a lightweight stack of the current recent tasks, without thumbnails and icons. */
-    public static TaskStack getShallowTaskStack(SystemServicesProxy ssp, int numTasks) {
+    public static TaskStack getShallowTaskStack(SystemServicesProxy ssp, int numTasks,
+            Resources resources) {
         RecentsConfiguration config = RecentsConfiguration.getInstance();
         List<ActivityManager.RecentTaskInfo> tasks = getRecentTasks(ssp, numTasks);
+        ArrayList<Task> tasksToAdd = new ArrayList<Task>();
         TaskStack stack = new TaskStack();
 
         int taskCount = tasks.size();
         for (int i = 0; i < taskCount; i++) {
             ActivityManager.RecentTaskInfo t = tasks.get(i);
-            ActivityInfo info = ssp.getActivityInfo(t.baseIntent.getComponent(), t.userId);
-            if (info == null) continue;
+            ActivityManager.TaskDescription av = t.taskDescription;
 
-            stack.addTask(new Task(t.persistentId, true, t.baseIntent, t.affiliatedTaskId,
-                    t.affiliatedTaskColor, null, null, 0, 0, t.firstActiveTime, t.lastActiveTime,
-                    (i == (taskCount - 1)), config.lockToAppEnabled));
+            BitmapDrawable icon = null;
+            if (av.getIcon() != null) {
+                icon = new BitmapDrawable(resources, av.getIcon());
+            }
+            Task.TaskKey taskKey = new Task.TaskKey(t.persistentId, t.baseIntent, t.userId,
+                    t.firstActiveTime, t.lastActiveTime);
+            tasksToAdd.add(new Task(taskKey, true, t.affiliatedTaskId, t.affiliatedTaskColor,
+                    av.getLabel(), icon, av.getPrimaryColor(), (i == (taskCount - 1)),
+                    config.lockToAppEnabled));
         }
+        stack.setTasks(tasksToAdd);
         stack.createAffiliatedGroupings(config);
         return stack;
     }
@@ -484,18 +525,23 @@
                 // We are leaving recents, so trim the data a bit
                 mThumbnailCache.trimToSize(mMaxThumbnailCacheSize / 2);
                 mApplicationIconCache.trimToSize(mMaxIconCacheSize / 2);
+                mTaskDescriptionIconCache.trimToSize(mMaxIconCacheSize / 2);
                 break;
             case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
             case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
                 // We are going to be low on memory
                 mThumbnailCache.trimToSize(mMaxThumbnailCacheSize / 4);
                 mApplicationIconCache.trimToSize(mMaxIconCacheSize / 4);
+                mTaskDescriptionIconCache.trimToSize(mMaxIconCacheSize / 4);
                 break;
             case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
             case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
                 // We are low on memory, so release everything
                 mThumbnailCache.evictAll();
                 mApplicationIconCache.evictAll();
+                mTaskDescriptionIconCache.evictAll();
+                // The cache is small, only clear the label cache when we are critical
+                mActivityLabelCache.evictAll();
                 break;
             default:
                 break;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/StringLruCache.java b/packages/SystemUI/src/com/android/systemui/recents/model/StringLruCache.java
new file mode 100644
index 0000000..b06c454
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/StringLruCache.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.model;
+
+/**
+ * The String LRU cache.
+ */
+class StringLruCache extends KeyStoreLruCache<String> {
+    public StringLruCache(int cacheSize) {
+        super(cacheSize);
+    }
+
+    @Override
+    protected int computeSize(String s) {
+        // The cache size is measured in number of strings
+        return 1;
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index f6c3a7e..977db60 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -88,7 +88,6 @@
     public boolean isActive;
     public boolean lockToThisTask;
     public boolean lockToTaskEnabled;
-    public int userId;
 
     TaskCallbacks mCb;
 
@@ -96,13 +95,12 @@
         // Only used by RecentsService for task rect calculations.
     }
 
-    public Task(int id, boolean isActive, Intent intent, int taskAffiliation, int taskAffiliationColor,
-                String activityTitle, Drawable activityIcon, int colorPrimary, int userId,
-                long firstActiveTime, long lastActiveTime, boolean lockToThisTask,
-                boolean lockToTaskEnabled) {
-        boolean isInAffiliationGroup = (taskAffiliation != id);
+    public Task(TaskKey key, boolean isActive, int taskAffiliation, int taskAffiliationColor,
+                String activityTitle, Drawable activityIcon, int colorPrimary,
+                boolean lockToThisTask, boolean lockToTaskEnabled) {
+        boolean isInAffiliationGroup = (taskAffiliation != key.id);
         boolean hasAffiliationGroupColor = isInAffiliationGroup && (taskAffiliationColor != 0);
-        this.key = new TaskKey(id, intent, userId, firstActiveTime, lastActiveTime);
+        this.key = key;
         this.taskAffiliation = taskAffiliation;
         this.taskAffiliationColor = taskAffiliationColor;
         this.activityLabel = activityTitle;
@@ -113,7 +111,20 @@
         this.isActive = isActive;
         this.lockToThisTask = lockToTaskEnabled && lockToThisTask;
         this.lockToTaskEnabled = lockToTaskEnabled;
-        this.userId = userId;
+    }
+
+    /** Copies the other task. */
+    public void copyFrom(Task o) {
+        this.key = o.key;
+        this.taskAffiliation = o.taskAffiliation;
+        this.taskAffiliationColor = o.taskAffiliationColor;
+        this.activityLabel = o.activityLabel;
+        this.activityIcon = o.activityIcon;
+        this.colorPrimary = o.colorPrimary;
+        this.useLightOnPrimaryColor = o.useLightOnPrimaryColor;
+        this.isActive = o.isActive;
+        this.lockToThisTask = o.lockToThisTask;
+        this.lockToTaskEnabled = o.lockToTaskEnabled;
     }
 
     /** Set the callbacks */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index 98bf151..1e47b50 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -92,7 +92,10 @@
 
     /** Returns the index of this task in the list of filtered tasks */
     int indexOf(Task t) {
-        return mTaskIndices.get(t.key);
+        if (mTaskIndices.containsKey(t.key)) {
+            return mTaskIndices.get(t.key);
+        }
+        return -1;
     }
 
     /** Returns the size of the list of filtered tasks */
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 07a7e74..1dd484b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -408,14 +408,26 @@
         int thumbnailHeight = transform.rect.height();
         if (task.thumbnail != null && thumbnailWidth > 0 && thumbnailHeight > 0 &&
                 task.thumbnail.getWidth() > 0 && task.thumbnail.getHeight() > 0) {
-            // Resize the thumbnail to the size of the view that we are animating from
-            Bitmap b = Bitmap.createBitmap(thumbnailWidth, thumbnailHeight,
-                    Bitmap.Config.ARGB_8888);
-            Canvas c = new Canvas(b);
-            c.drawBitmap(task.thumbnail,
-                    new Rect(0, 0, task.thumbnail.getWidth(), task.thumbnail.getHeight()),
-                    new Rect(0, 0, thumbnailWidth, thumbnailHeight), null);
-            c.setBitmap(null);
+            Bitmap b;
+            if (tv != null) {
+                // Disable any focused state before we draw the header
+                if (tv.isFocusedTask()) {
+                    tv.unsetFocusedTask();
+                }
+
+                b = Bitmap.createBitmap(thumbnailWidth, thumbnailHeight, Bitmap.Config.ARGB_8888);
+                if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
+                    b.eraseColor(0xFFff0000);
+                } else {
+                    Canvas c = new Canvas(b);
+                    c.scale(tv.getScaleX(), tv.getScaleY());
+                    tv.mHeaderView.draw(c);
+                    c.setBitmap(null);
+                }
+            } else {
+                // Notify the system to skip the thumbnail layer by using an ALPHA_8 bitmap
+                b = Bitmap.createBitmap(thumbnailWidth, thumbnailHeight, Bitmap.Config.ALPHA_8);
+            }
             ActivityOptions.OnAnimationStartedListener animStartedListener = null;
             if (lockToTask) {
                 animStartedListener = new ActivityOptions.OnAnimationStartedListener() {
@@ -434,7 +446,7 @@
                     }
                 };
             }
-            opts = ActivityOptions.makeThumbnailScaleUpAnimation(sourceView,
+            opts = ActivityOptions.makeThumbnailAspectScaleUpAnimation(sourceView,
                     b, offsetX, offsetY, animStartedListener);
         }
 
@@ -472,7 +484,15 @@
         if (tv == null) {
             post(launchRunnable);
         } else {
-            stackView.startLaunchTaskAnimation(tv, launchRunnable);
+            if (!task.group.isFrontMostTask(task)) {
+                // For affiliated tasks that are behind other tasks, we must animate the front cards
+                // out of view before starting the task transition
+                stackView.startLaunchTaskAnimation(tv, launchRunnable);
+            } else {
+                // Otherwise, we can start the task transition immediately
+                stackView.startLaunchTaskAnimation(tv, null);
+                postDelayed(launchRunnable, 17);
+            }
         }
     }
 
@@ -485,7 +505,7 @@
         intent.setComponent(intent.resolveActivity(getContext().getPackageManager()));
         TaskStackBuilder.create(getContext())
                 .addNextIntentWithParentStack(intent).startActivities(null,
-                new UserHandle(t.userId));
+                new UserHandle(t.key.userId));
     }
 
     @Override
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 aee558f..861011f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -460,7 +460,17 @@
     }
 
     /**
-     * This is called with the full window width and height to allow stack view children to 
+     * This is ONLY used from AlternateRecentsComponent to update the dummy stack view for purposes
+     * of getting the task rect to animate to.
+     */
+    public void updateMinMaxScrollForStack(TaskStack stack, boolean launchedWithAltTab,
+            boolean launchedFromHome) {
+        mStack = stack;
+        updateMinMaxScroll(false, launchedWithAltTab, launchedFromHome);
+    }
+
+    /**
+     * This is called with the full window width and height to allow stack view children to
      * perform the full screen transition down.
      */
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
index f0bdfa2..31fc701 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
@@ -33,7 +33,7 @@
 public class TaskStackViewLayoutAlgorithm {
 
     // These are all going to change
-    static final float StackPeekMinScale = 0.825f; // The min scale of the last card in the peek area
+    static final float StackPeekMinScale = 0.8f; // The min scale of the last card in the peek area
 
     RecentsConfiguration mConfig;
 
@@ -157,7 +157,7 @@
     public TaskViewTransform getStackTransform(Task task, float stackScroll, TaskViewTransform transformOut,
             TaskViewTransform prevTransform) {
         // Return early if we have an invalid index
-        if (task == null) {
+        if (task == null || !mTaskProgressMap.containsKey(task.key)) {
             transformOut.reset();
             return transformOut;
         }
@@ -200,6 +200,15 @@
     }
 
     /**
+     * Returns the untransformed task view size.
+     */
+    public Rect getUntransformedTaskViewSize() {
+        Rect tvSize = new Rect(mTaskRect);
+        tvSize.offsetTo(0, 0);
+        return tvSize;
+    }
+
+    /**
      * Returns the scroll to such task top = 1f;
      */
     float getStackScrollForTask(Task t) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index e514c90..dfbcce1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -235,7 +235,6 @@
         int initialDim = getDim();
         if (mConfig.launchedFromAppWithScreenshot) {
             if (isTaskViewLaunchTargetTask) {
-                mHeaderView.prepareEnterRecentsAnimation();
                 // Hide the footer during the transition in, and animate it out afterwards?
                 if (mFooterView != null) {
                     mFooterView.animateFooterVisibility(false, 0);
@@ -246,8 +245,6 @@
 
         } else if (mConfig.launchedFromAppWithThumbnail) {
             if (isTaskViewLaunchTargetTask) {
-                // Hide the front most task bar view so we can animate it in
-                mHeaderView.prepareEnterRecentsAnimation();
                 // Hide the action button if it exists
                 mActionButtonView.setAlpha(0f);
                 // Set the dim to 0 so we can animate it in
@@ -306,7 +303,6 @@
                     mViewBounds.animateClipBottom(getMeasuredHeight() - (windowInsetTop + size), duration);
                 }
                 // Animate the task bar of the first task view
-                mHeaderView.startEnterRecentsAnimation(0, null);
                 animate()
                         .scaleX(taskScale)
                         .scaleY(taskScale)
@@ -352,9 +348,8 @@
 
         } else if (mConfig.launchedFromAppWithThumbnail) {
             if (mTask.isLaunchTarget) {
-                // Animate the task bar of the first task view
-                mHeaderView.startEnterRecentsAnimation(mConfig.taskBarEnterAnimDelay,
-                        mThumbnailView.enableTaskBarClipAsRunnable(mHeaderView));
+                // Enable the task bar clip
+                mThumbnailView.enableTaskBarClip(mHeaderView);
                 // Animate the dim/overlay
                 if (Constants.DebugFlags.App.EnableThumbnailAlphaOnFrontmost) {
                     // Animate the thumbnail alpha before the dim animation (to prevent updating the
@@ -475,14 +470,13 @@
     }
 
     /** Animates this task view as it exits recents */
-    void startLaunchTaskAnimation(final Runnable r, boolean isLaunchingTask,
+    void startLaunchTaskAnimation(final Runnable postAnimRunnable, boolean isLaunchingTask,
             boolean occludesLaunchTarget) {
         if (isLaunchingTask) {
-            // Disable the thumbnail clip and animate the bar out for the window animation out
-            mHeaderView.startLaunchTaskAnimation(mThumbnailView.disableTaskBarClipAsRunnable(), r,
-                    mIsFocused);
+            // Disable the thumbnail clip
+            mThumbnailView.disableTaskBarClip();
             // Animate the thumbnail alpha back into full opacity for the window animation out
-            mThumbnailView.startLaunchTaskAnimation();
+            mThumbnailView.startLaunchTaskAnimation(postAnimRunnable);
 
             // Animate the dim
             if (mDim > 0) {
@@ -493,7 +487,11 @@
             }
 
             // Animate the action button away
-            mActionButtonView.animate().alpha(0f)
+            float toScale = 0.9f;
+            mActionButtonView.animate()
+                    .alpha(0f)
+                    .scaleX(toScale)
+                    .scaleY(toScale)
                     .setStartDelay(0)
                     .setDuration(mConfig.taskBarExitAnimDuration)
                     .setInterpolator(mConfig.fastOutLinearInInterpolator)
@@ -706,22 +704,30 @@
     }
 
     /**
+     * Unsets the focused task explicitly.
+     */
+    void unsetFocusedTask() {
+        mIsFocused = false;
+        if (mFocusAnimationsEnabled) {
+            // Un-focus the header bar
+            mHeaderView.onTaskViewFocusChanged(false);
+        }
+
+        // Update the thumbnail alpha with the focus
+        mThumbnailView.onFocusChanged(false);
+        // Call the callback
+        mCb.onTaskViewFocusChanged(this, false);
+        invalidate();
+    }
+
+    /**
      * Updates the explicitly focused state when the view focus changes.
      */
     @Override
     protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
         super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
         if (!gainFocus) {
-            mIsFocused = false;
-            if (mFocusAnimationsEnabled) {
-                // Un-focus the header bar
-                mHeaderView.onTaskViewFocusChanged(false);
-            }
-            // Update the thumbnail alpha with the focus
-            mThumbnailView.onFocusChanged(false);
-            // Call the callback
-            mCb.onTaskViewFocusChanged(this, false);
-            invalidate();
+            unsetFocusedTask();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index d39f64e..1743433 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -49,7 +49,7 @@
 
 
 /* The task bar view */
-class TaskViewHeader extends FrameLayout {
+public class TaskViewHeader extends FrameLayout {
 
     RecentsConfiguration mConfig;
 
@@ -156,8 +156,11 @@
             // Draw the highlight at the top edge (but put the bottom edge just out of view)
             float offset = (float) Math.ceil(mConfig.taskViewHighlightPx / 2f);
             float radius = mConfig.taskViewRoundedCornerRadiusPx;
+            int count = canvas.save(Canvas.CLIP_SAVE_FLAG);
+            canvas.clipRect(0, 0, getMeasuredWidth(), getMeasuredHeight());
             canvas.drawRoundRect(-offset, 0f, (float) getMeasuredWidth() + offset,
                     getMeasuredHeight() + radius, radius, radius, sHighlightPaint);
+            canvas.restoreToCount(count);
         }
     }
 
@@ -178,7 +181,7 @@
     }
 
     /** Binds the bar view to the task */
-    void rebindToTask(Task t) {
+    public void rebindToTask(Task t) {
         // If an activity icon is defined, then we use that as the primary icon to show in the bar,
         // otherwise, we fall back to the application icon
         if (t.activityIcon != null) {
@@ -212,51 +215,6 @@
         mApplicationIcon.setImageDrawable(null);
     }
 
-    /** Prepares this task view for the enter-recents animations.  This is called earlier in the
-     * first layout because the actual animation into recents may take a long time. */
-    void prepareEnterRecentsAnimation() {
-        setVisibility(View.INVISIBLE);
-    }
-
-    /** Animates this task bar as it enters recents */
-    void startEnterRecentsAnimation(int delay, Runnable postAnimRunnable) {
-        // Animate the task bar of the first task view
-        setVisibility(View.VISIBLE);
-        setAlpha(0f);
-        animate()
-                .alpha(1f)
-                .setStartDelay(delay)
-                .setInterpolator(mConfig.linearOutSlowInInterpolator)
-                .setDuration(mConfig.taskBarEnterAnimDuration)
-                .withEndAction(postAnimRunnable)
-                .withLayer()
-                .start();
-    }
-
-    /** Animates this task bar as it exits recents */
-    void startLaunchTaskAnimation(Runnable preAnimRunnable, final Runnable postAnimRunnable,
-            boolean isFocused) {
-        if (isFocused) {
-            onTaskViewFocusChanged(false);
-        }
-
-        // Animate the task bar out of the first task view
-        animate()
-                .alpha(0f)
-                .setStartDelay(0)
-                .setInterpolator(mConfig.linearOutSlowInInterpolator)
-                .setDuration(mConfig.taskBarExitAnimDuration)
-                .withStartAction(preAnimRunnable)
-                .withEndAction(new Runnable() {
-                    @Override
-                    public void run() {
-                        post(postAnimRunnable);
-                    }
-                })
-                .withLayer()
-                .start();
-    }
-
     /** Animates this task bar dismiss button when launching a task. */
     void startLaunchTaskDismissAnimation() {
         if (mDismissButton.getVisibility() == View.VISIBLE) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index f223bf3..fe36987 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -64,25 +64,10 @@
         setClipBounds(mClipRect);
     }
 
-    /** Convenience method to enable task bar clipping as a runnable. */
-    Runnable enableTaskBarClipAsRunnable(final View taskBar) {
-        return new Runnable() {
-            @Override
-            public void run() {
-                enableTaskBarClip(taskBar);
-            }
-        };
-    }
-
     /** Disables the task bar clipping. */
-    Runnable disableTaskBarClipAsRunnable() {
-        return new Runnable() {
-            @Override
-            public void run() {
-                mClipRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
-                setClipBounds(mClipRect);
-            }
-        };
+    void disableTaskBarClip() {
+        mClipRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
+        setClipBounds(mClipRect);
     }
 
     /** Binds the thumbnail view to the screenshot. */
@@ -140,8 +125,8 @@
     }
 
     /** Animates this task thumbnail as it exits recents */
-    void startLaunchTaskAnimation() {
-        startFadeAnimation(1f, 0, mConfig.taskBarExitAnimDuration, null);
+    void startLaunchTaskAnimation(Runnable postAnimRunnable) {
+        startFadeAnimation(1f, 0, mConfig.taskBarExitAnimDuration, postAnimRunnable);
     }
 
     /** Animates the thumbnail alpha. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 57df1d8..8b50a36 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -21,7 +21,6 @@
 import android.animation.TimeInterpolator;
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
-import android.app.ActivityThread;
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.app.TaskStackBuilder;
@@ -32,16 +31,12 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.UserInfo;
 import android.content.res.Configuration;
 import android.database.ContentObserver;
-import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Build;
 import android.os.Handler;
@@ -114,7 +109,6 @@
     protected static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 1023;
     protected static final int MSG_SHOW_NEXT_AFFILIATED_TASK = 1024;
     protected static final int MSG_SHOW_PREV_AFFILIATED_TASK = 1025;
-    protected static final int MSG_OPEN_SEARCH_PANEL = 1026;
     protected static final int MSG_CLOSE_SEARCH_PANEL = 1027;
     protected static final int MSG_SHOW_HEADS_UP = 1028;
     protected static final int MSG_HIDE_HEADS_UP = 1029;
@@ -580,7 +574,7 @@
     }
 
 
-    protected void applyLegacyRowBackground(StatusBarNotification sbn,
+    protected void applyColorsAndBackgrounds(StatusBarNotification sbn,
             NotificationData.Entry entry) {
         int version = 0;
         try {
@@ -603,6 +597,14 @@
                 entry.row.setTintColor(color);
             }
         }
+
+        if (entry.icon != null) {
+            if (version >= Build.VERSION_CODES.L) {
+                entry.icon.setColorFilter(mContext.getResources().getColor(android.R.color.white));
+            } else {
+                entry.icon.setColorFilter(null);
+            }
+        }
     }
 
     public boolean isMediaNotification(NotificationData.Entry entry) {
@@ -751,9 +753,9 @@
 
     @Override
     public void showSearchPanel() {
-        int msg = MSG_OPEN_SEARCH_PANEL;
-        mHandler.removeMessages(msg);
-        mHandler.sendEmptyMessage(msg);
+        if (mSearchPanelView != null && mSearchPanelView.isAssistantAvailable()) {
+            mSearchPanelView.show(true, true);
+        }
     }
 
     @Override
@@ -966,12 +968,6 @@
              case MSG_SHOW_PREV_AFFILIATED_TASK:
                   showRecentsPreviousAffiliatedTask();
                   break;
-             case MSG_OPEN_SEARCH_PANEL:
-                 if (DEBUG) Log.d(TAG, "opening search panel");
-                 if (mSearchPanelView != null && mSearchPanelView.isAssistantAvailable()) {
-                     mSearchPanelView.show(true, true);
-                 }
-                 break;
              case MSG_CLOSE_SEARCH_PANEL:
                  if (DEBUG) Log.d(TAG, "closing search panel");
                  if (mSearchPanelView != null && mSearchPanelView.isShowing()) {
@@ -1257,7 +1253,7 @@
         entry.expandedPublic = publicViewLocal;
         entry.setBigContentView(bigContentViewLocal);
 
-        applyLegacyRowBackground(sbn, entry);
+        applyColorsAndBackgrounds(sbn, entry);
 
         // Restore previous flags.
         if (hasUserChangedExpansion) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
index 3a82753..628aab8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
@@ -20,8 +20,7 @@
 import android.graphics.RectF;
 import android.view.MotionEvent;
 import android.view.View;
-
-import com.android.systemui.R;
+import android.view.ViewConfiguration;
 
 public class DelegateViewHelper {
     private View mDelegateView;
@@ -107,8 +106,8 @@
     public void setSourceView(View view) {
         mSourceView = view;
         if (mSourceView != null) {
-            mTriggerThreshhold = mSourceView.getContext().getResources()
-                    .getDimension(R.dimen.navbar_search_up_threshhold);
+            mTriggerThreshhold =
+                    ViewConfiguration.get(mSourceView.getContext()).getScaledPagingTouchSlop();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index cb2d40a..c0b171a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -29,7 +29,6 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.phone.PhoneManager;
 import android.provider.MediaStore;
 import android.telecomm.TelecommManager;
 import android.util.AttributeSet;
@@ -324,13 +323,12 @@
     }
 
     public void launchPhone() {
-        TelecommManager tm = TelecommManager.from(mContext);
-        if (tm.isInAPhoneCall()) {
-            final PhoneManager pm = (PhoneManager) mContext.getSystemService(Context.PHONE_SERVICE);
+        final TelecommManager tm = TelecommManager.from(mContext);
+        if (tm.isInCall()) {
             AsyncTask.execute(new Runnable() {
                 @Override
                 public void run() {
-                    pm.showCallScreen(false /* showDialpad */);
+                    tm.showInCallScreen(false /* showDialpad */);
                 }
             });
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java
index 3c20d1f..b633453 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java
@@ -33,10 +33,11 @@
     private final int mMinFlingVelocity;
     private boolean mInterceptTouches;
     private int mTouchDownX;
+    private int mTouchDownY;
 
     public NavigationBarViewTaskSwitchHelper(Context context) {
         ViewConfiguration configuration = ViewConfiguration.get(context);
-        mScrollTouchSlop = configuration.getScaledTouchSlop();
+        mScrollTouchSlop = 4 * configuration.getScaledTouchSlop();
         mMinFlingVelocity = configuration.getScaledMinimumFlingVelocity();
         mTaskSwitcherDetector = new GestureDetector(context, this);
     }
@@ -58,12 +59,19 @@
         switch (action & MotionEvent.ACTION_MASK) {
             case MotionEvent.ACTION_DOWN: {
                 mTouchDownX = (int) event.getX();
+                mTouchDownY = (int) event.getY();
                 mInterceptTouches = false;
                 break;
             }
             case MotionEvent.ACTION_MOVE: {
                 int x = (int) event.getX();
-                if (Math.abs(x - mTouchDownX) > mScrollTouchSlop) {
+                int y = (int) event.getY();
+                int xDiff = Math.abs(x - mTouchDownX);
+                int yDiff = Math.abs(y - mTouchDownY);
+                boolean exceededTouchSlop = !mIsVertical
+                        ? xDiff > mScrollTouchSlop && xDiff > yDiff
+                        : yDiff > mScrollTouchSlop && yDiff > xDiff;
+                if (exceededTouchSlop) {
                     mInterceptTouches = true;
                     return true;
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index e1beb08..387abc3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -58,7 +58,7 @@
     private static final int CAP_HEIGHT = 1456;
     private static final int FONT_HEIGHT = 2163;
 
-    private static final float HEADER_RUBBERBAND_FACTOR = 2.15f;
+    private static final float HEADER_RUBBERBAND_FACTOR = 2.05f;
     private static final float LOCK_ICON_ACTIVE_SCALE = 1.2f;
 
     private KeyguardAffordanceHelper mAfforanceHelper;
@@ -1665,7 +1665,7 @@
     @Override
     protected boolean fullyExpandedClearAllVisible() {
         return mNotificationStackScroller.isDismissViewNotGone()
-                && mNotificationStackScroller.isScrolledToBottom();
+                && mNotificationStackScroller.isScrolledToBottom() && !mTwoFingerQsExpand;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index f427ec4..3338f6a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -298,9 +298,7 @@
      */
     public boolean onBackPressed() {
         if (mBouncer.isShowing()) {
-            mBouncer.hide(false /* destroyView */);
-            mPhoneStatusBar.showKeyguard();
-            updateStates();
+            reset();
             return true;
         }
         return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java
index eb5804a..7713e57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java
@@ -25,7 +25,7 @@
     void setCurrentUserId(int currentUserId);
     Set<CastDevice> getCastDevices();
     void startCasting(CastDevice device);
-    void stopCasting();
+    void stopCasting(CastDevice device);
 
     public interface Callback {
         void onCastDevicesChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
index 22179e0..eb0be05 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
@@ -19,15 +19,25 @@
 import static android.media.MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY;
 
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.media.MediaRouter;
 import android.media.MediaRouter.RouteInfo;
+import android.media.projection.MediaProjectionInfo;
+import android.media.projection.MediaProjectionManager;
+import android.os.Handler;
+import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
 
+import com.android.systemui.R;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Objects;
 import java.util.Set;
 import java.util.UUID;
 
@@ -41,12 +51,19 @@
     private final MediaRouter mMediaRouter;
     private final ArrayMap<String, RouteInfo> mRoutes = new ArrayMap<>();
     private final Object mDiscoveringLock = new Object();
+    private final MediaProjectionManager mProjectionManager;
+    private final Object mProjectionLock = new Object();
 
     private boolean mDiscovering;
+    private MediaProjectionInfo mProjection;
 
     public CastControllerImpl(Context context) {
         mContext = context;
         mMediaRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
+        mProjectionManager = (MediaProjectionManager)
+                context.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
+        mProjection = mProjectionManager.getActiveProjectionInfo();
+        mProjectionManager.addCallback(mProjectionCallback, new Handler());
         if (DEBUG) Log.d(TAG, "new CastController()");
     }
 
@@ -59,6 +76,7 @@
             final RouteInfo route = mRoutes.valueAt(i);
             pw.print("    "); pw.println(routeToString(route));
         }
+        pw.print("  mProjection="); pw.println(mProjection);
     }
 
     @Override
@@ -95,6 +113,18 @@
     @Override
     public Set<CastDevice> getCastDevices() {
         final ArraySet<CastDevice> devices = new ArraySet<CastDevice>();
+        synchronized (mProjectionLock) {
+            if (mProjection != null) {
+                final CastDevice device = new CastDevice();
+                device.id = mProjection.getPackageName();
+                device.name = getAppName(mProjection.getPackageName());
+                device.description = mContext.getString(R.string.quick_settings_casting);
+                device.state = CastDevice.STATE_CONNECTED;
+                device.tag = mProjection;
+                devices.add(device);
+                return devices;
+            }
+        }
         synchronized(mRoutes) {
             for (RouteInfo route : mRoutes.values()) {
                 final CastDevice device = new CastDevice();
@@ -122,9 +152,55 @@
     }
 
     @Override
-    public void stopCasting() {
-        if (DEBUG) Log.d(TAG, "stopCasting");
-        mMediaRouter.getDefaultRoute().select();
+    public void stopCasting(CastDevice device) {
+        final boolean isProjection = device.tag instanceof MediaProjectionInfo;
+        if (DEBUG) Log.d(TAG, "stopCasting isProjection=" + isProjection);
+        if (isProjection) {
+            final MediaProjectionInfo projection = (MediaProjectionInfo) device.tag;
+            if (Objects.equals(mProjectionManager.getActiveProjectionInfo(), projection)) {
+                mProjectionManager.stopActiveProjection();
+            } else {
+                Log.w(TAG, "Projection is no longer active: " + projection);
+            }
+        } else {
+            mMediaRouter.getDefaultRoute().select();
+        }
+    }
+
+    private void setProjection(MediaProjectionInfo projection, boolean started) {
+        boolean changed = false;
+        final MediaProjectionInfo oldProjection = mProjection;
+        synchronized (mProjectionLock) {
+            final boolean isCurrent = Objects.equals(projection, mProjection);
+            if (started && !isCurrent) {
+                mProjection = projection;
+                changed = true;
+            } else if (!started && isCurrent) {
+                mProjection = null;
+                changed = true;
+            }
+        }
+        if (changed) {
+            if (DEBUG) Log.d(TAG, "setProjection: " + oldProjection + " -> " + mProjection);
+            fireOnCastDevicesChanged();
+        }
+    }
+
+    private String getAppName(String packageName) {
+        final PackageManager pm = mContext.getPackageManager();
+        try {
+            final ApplicationInfo appInfo = pm.getApplicationInfo(packageName, 0);
+            if (appInfo != null) {
+                final CharSequence label = appInfo.loadLabel(pm);
+                if (!TextUtils.isEmpty(label)) {
+                    return label.toString();
+                }
+            }
+            Log.w(TAG, "No label found for package: " + packageName);
+        } catch (NameNotFoundException e) {
+            Log.w(TAG, "Error getting appName for package: " + packageName, e);
+        }
+        return packageName;
     }
 
     private void updateRemoteDisplays() {
@@ -202,4 +278,17 @@
             updateRemoteDisplays();
         }
     };
+
+    private final MediaProjectionManager.Callback mProjectionCallback
+            = new MediaProjectionManager.Callback() {
+        @Override
+        public void onStart(MediaProjectionInfo info) {
+            setProjection(info, true);
+        }
+
+        @Override
+        public void onStop(MediaProjectionInfo info) {
+            setProjection(info, false);
+        }
+    };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 68a02cf..82efd1d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -2150,7 +2150,15 @@
     }
 
     public int getDismissViewHeight() {
-        return mDismissView.getHeight() + mPaddingBetweenElementsNormal;
+        int height = mDismissView.getHeight() + mPaddingBetweenElementsNormal;
+
+        // Hack: Accommodate for additional distance when we only have one notification and the
+        // dismiss all button.
+        if (getNotGoneChildCount() == 2 && getLastChildNotGone() == mDismissView
+                && getFirstChildNotGone() instanceof ActivatableNotificationView) {
+            height += mCollapseSecondCardPadding;
+        }
+        return height;
     }
 
     public float getBottomMostNotificationBottom() {
diff --git a/phone/java/android/phone/PhoneManager.java b/phone/java/android/phone/PhoneManager.java
deleted file mode 100644
index f61b054..0000000
--- a/phone/java/android/phone/PhoneManager.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2014 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 android.phone;
-
-import android.content.Context;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.util.Log;
-
-import com.android.internal.telecomm.ITelecommService;
-
-/**
- * Exposes call-related functionality for use by phone and dialer apps.
- */
-public final class PhoneManager {
-    private static final String TAG = PhoneManager.class.getSimpleName();
-
-    private final Context mContext;
-
-    /**
-     * @hide
-     */
-    public PhoneManager(Context context) {
-        Context appContext = context.getApplicationContext();
-        if (appContext != null) {
-            mContext = appContext;
-        } else {
-            mContext = context;
-        }
-    }
-
-    /**
-     * Processes the specified dial string as an MMI code.
-     * <p>
-     * Requires that the method-caller be set as the system dialer app.
-     * </p>
-     *
-     * @param dialString The digits to dial.
-     * @return True if the digits were processed as an MMI code, false otherwise.
-     */
-    public boolean handlePinMmi(String dialString) {
-        ITelecommService service = getTelecommService();
-        if (service != null) {
-            try {
-                return service.handlePinMmi(dialString);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Error calling ITelecommService#handlePinMmi", e);
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Removes the missed-call notification if one is present.
-     * <p>
-     * Requires that the method-caller be set as the system dialer app.
-     * </p>
-     */
-    public void cancelMissedCallsNotification() {
-        ITelecommService service = getTelecommService();
-        if (service != null) {
-            try {
-                service.cancelMissedCallsNotification();
-            } catch (RemoteException e) {
-                Log.e(TAG, "Error calling ITelecommService#cancelMissedCallsNotification", e);
-            }
-        }
-    }
-
-    /**
-     * Brings the in-call screen to the foreground if there is an ongoing call. If there is
-     * currently no ongoing call, then this method does nothing.
-     * <p>
-     * Requires that the method-caller be set as the system dialer app or have the
-     * {@link android.Manifest.permission#READ_PHONE_STATE} permission.
-     * </p>
-     *
-     * @param showDialpad Brings up the in-call dialpad as part of showing the in-call screen.
-     */
-    public void showCallScreen(boolean showDialpad) {
-        ITelecommService service = getTelecommService();
-        if (service != null) {
-            try {
-                service.showCallScreen(showDialpad);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Error calling ITelecommService#showCallScreen", e);
-            }
-        }
-    }
-
-    /**
-     * Returns whether there is an ongoing phone call.
-     * <p>
-     * Requires permission: {@link android.Manifest.permission#READ_PHONE_STATE}
-     * </p>
-     */
-    public boolean isInAPhoneCall() {
-        ITelecommService service = getTelecommService();
-        if (service != null) {
-            try {
-                return service.isInAPhoneCall();
-            } catch (RemoteException e) {
-                Log.e(TAG, "Error caling ITelecommService#isInAPhoneCall", e);
-            }
-        }
-        return false;
-    }
-
-    private ITelecommService getTelecommService() {
-        return ITelecommService.Stub.asInterface(
-                ServiceManager.getService(Context.TELECOMM_SERVICE));
-    }
-}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 9652ebd..e240127 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -876,6 +876,13 @@
         }
     }
 
+    void doPendingInvalidatePanelMenu() {
+        if (mInvalidatePanelMenuPosted) {
+            mDecor.removeCallbacks(mInvalidatePanelMenuRunnable);
+            mInvalidatePanelMenuRunnable.run();
+        }
+    }
+
     void doInvalidatePanelMenu(int featureId) {
         PanelFeatureState st = getPanelState(featureId, true);
         Bundle savedActionViewStates = null;
@@ -1979,6 +1986,7 @@
             SparseArray<Parcelable> actionBarStates =
                     savedInstanceState.getSparseParcelableArray(ACTION_BAR_TAG);
             if (actionBarStates != null) {
+                doPendingInvalidatePanelMenu();
                 mDecorContentParent.restoreToolbarHierarchyState(actionBarStates);
             } else {
                 Log.w(TAG, "Missing saved instance states for action bar views! " +
@@ -3468,17 +3476,15 @@
                     mDecorContentParent.setLogo(mLogoRes);
                 }
 
-                // Post the panel invalidate for later; avoid application onCreateOptionsMenu
+                // Invalidate if the panel menu hasn't been created before this.
+                // Panel menu invalidation is deferred avoiding application onCreateOptionsMenu
                 // being called in the middle of onCreate or similar.
-                mDecor.post(new Runnable() {
-                    public void run() {
-                        // Invalidate if the panel menu hasn't been created before this.
-                        PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
-                        if (!isDestroyed() && (st == null || st.menu == null)) {
-                            invalidatePanelMenu(FEATURE_ACTION_BAR);
-                        }
-                    }
-                });
+                // A pending invalidation will typically be resolved before the posted message
+                // would run normally in order to satisfy instance state restoration.
+                PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
+                if (!isDestroyed() && (st == null || st.menu == null)) {
+                    invalidatePanelMenu(FEATURE_ACTION_BAR);
+                }
             } else {
                 mTitleView = (TextView)findViewById(R.id.title);
                 if (mTitleView != null) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index c10d929..20206b9 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -2978,7 +2978,10 @@
             boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
             boolean navAllowedHidden = immersive || immersiveSticky;
             navTranslucent &= !immersiveSticky;  // transient trumps translucent
-            navTranslucent &= areTranslucentBarsAllowed();
+            boolean isKeyguardShowing = isStatusBarKeyguard() && !mHideLockScreen;
+            if (!isKeyguardShowing) {
+                navTranslucent &= areTranslucentBarsAllowed();
+            }
 
             // When the navigation bar isn't visible, we put up a fake
             // input window to catch all touch events.  This way we can
@@ -3102,7 +3105,9 @@
                 boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
                 boolean statusBarTranslucent = (sysui
                         & (View.STATUS_BAR_TRANSLUCENT | View.SYSTEM_UI_TRANSPARENT)) != 0;
-                statusBarTranslucent &= areTranslucentBarsAllowed();
+                if (!isKeyguardShowing) {
+                    statusBarTranslucent &= areTranslucentBarsAllowed();
+                }
 
                 // If the status bar is hidden, we don't want to cause
                 // windows behind it to scroll.
@@ -4274,7 +4279,7 @@
                             result &= ~ACTION_PASS_TO_USER;
                             break;
                         }
-                        if (telecommManager.isInAPhoneCall()
+                        if (telecommManager.isInCall()
                                 && (result & ACTION_PASS_TO_USER) == 0) {
                             // If we are in call but we decided not to pass the key to
                             // the application, just pass it to the session service.
@@ -4349,7 +4354,7 @@
                             telecommManager.silenceRinger();
                         } else if ((mIncallPowerBehavior
                                 & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
-                                && telecommManager.isInAPhoneCall() && interactive) {
+                                && telecommManager.isInCall() && interactive) {
                             // Otherwise, if "Power button ends call" is enabled,
                             // the Power button will hang up any current active call.
                             hungUp = telecommManager.endCall();
@@ -4392,7 +4397,7 @@
                 if (down) {
                     TelecommManager telecommManager = getTelecommService();
                     if (telecommManager != null) {
-                        if (telecommManager.isInAPhoneCall()) {
+                        if (telecommManager.isInCall()) {
                             // Suppress PLAY/PAUSE toggle when phone is ringing or in-call
                             // to avoid music playback.
                             break;
@@ -5611,7 +5616,7 @@
             vis = (vis & ~flags) | (oldVis & flags);
         }
 
-        if (!areTranslucentBarsAllowed()) {
+        if (!areTranslucentBarsAllowed() && transWin != mStatusBar) {
             vis &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSLUCENT
                     | View.SYSTEM_UI_TRANSPARENT);
         }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index ad8f446..8dd6420 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2167,41 +2167,53 @@
             if (DBG) log("releasing NetworkRequest " + request);
             nri.unlinkDeathRecipient();
             mNetworkRequests.remove(request);
-            // tell the network currently servicing this that it's no longer interested
-            NetworkAgentInfo affectedNetwork = mNetworkForRequestId.get(nri.request.requestId);
-            if (affectedNetwork != null) {
-                mNetworkForRequestId.remove(nri.request.requestId);
-                affectedNetwork.networkRequests.remove(nri.request.requestId);
-                if (VDBG) {
-                    log(" Removing from current network " + affectedNetwork.name() + ", leaving " +
-                            affectedNetwork.networkRequests.size() + " requests.");
-                }
-                if (nri.isRequest && nri.request.legacyType != TYPE_NONE) {
-                    mLegacyTypeTracker.remove(nri.request.legacyType, affectedNetwork);
-                }
-            }
-
             if (nri.isRequest) {
+                // Find all networks that are satisfying this request and remove the request
+                // from their request lists.
+                for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
+                    if (nai.networkRequests.get(nri.request.requestId) != null) {
+                        nai.networkRequests.remove(nri.request.requestId);
+                        if (VDBG) {
+                            log(" Removing from current network " + nai.name() +
+                                    ", leaving " + nai.networkRequests.size() +
+                                    " requests.");
+                        }
+                        // check if has any requests remaining and if not,
+                        // disconnect (unless it's a VPN).
+                        boolean keep = nai.isVPN();
+                        for (int i = 0; i < nai.networkRequests.size() && !keep; i++) {
+                            NetworkRequest r = nai.networkRequests.valueAt(i);
+                            if (mNetworkRequests.get(r).isRequest) keep = true;
+                        }
+                        if (!keep) {
+                            if (DBG) log("no live requests for " + nai.name() + "; disconnecting");
+                            nai.asyncChannel.disconnect();
+                        }
+                    }
+                }
+
+                // Maintain the illusion.  When this request arrived, we might have preteneded
+                // that a network connected to serve it, even though the network was already
+                // connected.  Now that this request has gone away, we might have to pretend
+                // that the network disconnected.  LegacyTypeTracker will generate that
+                // phatom disconnect for this type.
+                NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
+                if (nai != null) {
+                    mNetworkForRequestId.remove(nri.request.requestId);
+                    if (nri.request.legacyType != TYPE_NONE) {
+                        mLegacyTypeTracker.remove(nri.request.legacyType, nai);
+                    }
+                }
+
                 for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
                     nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_CANCEL_REQUEST,
                             nri.request);
                 }
-
-                if (affectedNetwork != null) {
-                    // check if this network still has live requests - otherwise, tear down
-                    // TODO - probably push this to the NF/NA
-                    boolean keep = affectedNetwork.isVPN();
-                    for (int i = 0; i < affectedNetwork.networkRequests.size() && !keep; i++) {
-                        NetworkRequest r = affectedNetwork.networkRequests.valueAt(i);
-                        if (mNetworkRequests.get(r).isRequest) {
-                            keep = true;
-                        }
-                    }
-                    if (keep == false) {
-                        if (DBG) log("no live requests for " + affectedNetwork.name() +
-                                "; disconnecting");
-                        affectedNetwork.asyncChannel.disconnect();
-                    }
+            } else {
+                // listens don't have a singular affectedNetwork.  Check all networks to see
+                // if this listen request applies and remove it.
+                for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
+                    nai.networkRequests.remove(nri.request.requestId);
                 }
             }
             callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_RELEASED);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index dd3d862..1acbec7 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -6615,6 +6615,10 @@
         return false;
     }
 
+    /**
+     * @param uri This uri must NOT contain an embedded userId.
+     * @param userId The userId in which the uri is to be resolved.
+     */
     @Override
     public int checkUriPermission(Uri uri, int pid, int uid,
             final int modeFlags, int userId) {
@@ -6767,6 +6771,10 @@
         return targetUid;
     }
 
+    /**
+     * @param uri This uri must NOT contain an embedded userId.
+     * @param userId The userId in which the uri is to be resolved.
+     */
     @Override
     public int checkGrantUriPermission(int callingUid, String targetPkg, Uri uri,
             final int modeFlags, int userId) {
@@ -6951,6 +6959,10 @@
         grantUriPermissionUncheckedFromIntentLocked(needed, owner);
     }
 
+    /**
+     * @param uri This uri must NOT contain an embedded userId.
+     * @param userId The userId in which the uri is to be resolved.
+     */
     @Override
     public void grantUriPermission(IApplicationThread caller, String targetPkg, Uri uri,
             final int modeFlags, int userId) {
@@ -7053,6 +7065,10 @@
         }
     }
 
+    /**
+     * @param uri This uri must NOT contain an embedded userId.
+     * @param userId The userId in which the uri is to be resolved.
+     */
     @Override
     public void revokeUriPermission(IApplicationThread caller, Uri uri, final int modeFlags,
             int userId) {
@@ -7151,9 +7167,16 @@
         }
     }
 
+    /**
+     * @param uri This uri must NOT contain an embedded userId.
+     * @param sourceUserId The userId in which the uri is to be resolved.
+     * @param targetUserId The userId of the app that receives the grant.
+     */
     @Override
     public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg, Uri uri,
             final int modeFlags, int sourceUserId, int targetUserId) {
+        targetUserId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+                targetUserId, false, ALLOW_FULL_ONLY, "grantUriPermissionFromOwner", null);
         synchronized(this) {
             UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
             if (owner == null) {
@@ -7178,6 +7201,10 @@
         }
     }
 
+    /**
+     * @param uri This uri must NOT contain an embedded userId.
+     * @param userId The userId in which the uri is to be resolved.
+     */
     @Override
     public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode, int userId) {
         synchronized(this) {
@@ -7318,6 +7345,10 @@
         }
     }
 
+    /**
+     * @param uri This uri must NOT contain an embedded userId.
+     * @param userId The userId in which the uri is to be resolved.
+     */
     @Override
     public void takePersistableUriPermission(Uri uri, final int modeFlags, int userId) {
         enforceNotIsolatedCaller("takePersistableUriPermission");
@@ -7360,6 +7391,10 @@
         }
     }
 
+    /**
+     * @param uri This uri must NOT contain an embedded userId.
+     * @param userId The userId in which the uri is to be resolved.
+     */
     @Override
     public void releasePersistableUriPermission(Uri uri, final int modeFlags, int userId) {
         enforceNotIsolatedCaller("releasePersistableUriPermission");
@@ -7516,18 +7551,10 @@
     // =========================================================
 
     @Override
-    public List<IAppTask> getAppTasks() {
-        final PackageManager pm = mContext.getPackageManager();
+    public List<IAppTask> getAppTasks(String callingPackage) {
         int callingUid = Binder.getCallingUid();
         long ident = Binder.clearCallingIdentity();
 
-        // Compose the list of packages for this id to test against
-        HashSet<String> packages = new HashSet<String>();
-        String[] uidPackages = pm.getPackagesForUid(callingUid);
-        for (int i = 0; i < uidPackages.length; i++) {
-            packages.add(uidPackages[i]);
-        }
-
         synchronized(this) {
             ArrayList<IAppTask> list = new ArrayList<IAppTask>();
             try {
@@ -7536,13 +7563,21 @@
                 final int N = mRecentTasks.size();
                 for (int i = 0; i < N; i++) {
                     TaskRecord tr = mRecentTasks.get(i);
-                    // Skip tasks that do not match the package name
-                    if (packages.contains(tr.getBaseIntent().getComponent().getPackageName())) {
-                        ActivityManager.RecentTaskInfo taskInfo =
-                                createRecentTaskInfoFromTaskRecord(tr);
-                        AppTaskImpl taskImpl = new AppTaskImpl(taskInfo.persistentId, callingUid);
-                        list.add(taskImpl);
+                    // Skip tasks that do not match the caller.  We don't need to verify
+                    // callingPackage, because we are also limiting to callingUid and know
+                    // that will limit to the correct security sandbox.
+                    if (tr.effectiveUid != callingUid) {
+                        continue;
                     }
+                    Intent intent = tr.getBaseIntent();
+                    if (intent == null ||
+                            !callingPackage.equals(intent.getComponent().getPackageName())) {
+                        continue;
+                    }
+                    ActivityManager.RecentTaskInfo taskInfo =
+                            createRecentTaskInfoFromTaskRecord(tr);
+                    AppTaskImpl taskImpl = new AppTaskImpl(taskInfo.persistentId, callingUid);
+                    list.add(taskImpl);
                 }
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -7706,11 +7741,17 @@
                     if (!allowed) {
                         // If the caller doesn't have the GET_TASKS permission, then only
                         // allow them to see a small subset of tasks -- their own and home.
-                        if (!tr.isHomeTask() && tr.creatorUid != callingUid) {
+                        if (!tr.isHomeTask() && tr.effectiveUid != callingUid) {
                             if (DEBUG_RECENTS) Slog.d(TAG, "Skipping, not allowed: " + tr);
                             continue;
                         }
                     }
+                    if ((flags & ActivityManager.RECENT_IGNORE_HOME_STACK_TASKS) != 0) {
+                        if (tr.stack != null && tr.stack.isHomeStack()) {
+                            if (DEBUG_RECENTS) Slog.d(TAG, "Skipping, home stack task: " + tr);
+                            continue;
+                        }
+                    }
                     if (tr.autoRemoveRecents && tr.getTopActivity() == null) {
                         // Don't include auto remove tasks that are finished or finishing.
                         if (DEBUG_RECENTS) Slog.d(TAG, "Skipping, auto-remove without activity: "
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index fcbe71e..39b6375 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -723,6 +723,22 @@
                                         + pendingOptions.getThumbnail().getHeight()));
                     }
                     break;
+                case ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP:
+                case ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
+                    service.mWindowManager.overridePendingAppTransitionAspectScaledThumb(
+                            pendingOptions.getThumbnail(),
+                            pendingOptions.getStartX(), pendingOptions.getStartY(),
+                            pendingOptions.getOnAnimationStartListener(),
+                            (animationType == ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP));
+                    if (intent.getSourceBounds() == null) {
+                        intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
+                                pendingOptions.getStartY(),
+                                pendingOptions.getStartX()
+                                        + pendingOptions.getThumbnail().getWidth(),
+                                pendingOptions.getStartY()
+                                        + pendingOptions.getThumbnail().getHeight()));
+                    }
+                    break;
                 default:
                     Slog.e(TAG, "applyOptionsLocked: Unknown animationType=" + animationType);
                     break;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 4bd86e4..41ed4ce7 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -3799,7 +3799,7 @@
             if (activities.isEmpty()) {
                 continue;
             }
-            if (!allowed && !task.isHomeTask() && task.creatorUid != callingUid) {
+            if (!allowed && !task.isHomeTask() && task.effectiveUid != callingUid) {
                 continue;
             }
             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 8aec392..bd8501c 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2430,7 +2430,6 @@
                         r.userId, r.info.configChanges, task.voiceSession != null,
                         r.mLaunchTaskBehind);
             }
-            mWindowManager.addTask(taskId, stackId, false);
         }
         resumeHomeStackTask(HOME_ACTIVITY_TYPE, null);
     }
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index d35e09f..7e42232 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -26,11 +26,16 @@
 import android.app.ActivityManager;
 import android.app.ActivityManager.TaskThumbnail;
 import android.app.ActivityOptions;
+import android.app.AppGlobals;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
 import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.service.voice.IVoiceInteractionSession;
 import android.util.Slog;
@@ -57,6 +62,7 @@
     private static final String ATTR_AUTOREMOVERECENTS = "auto_remove_recents";
     private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode";
     private static final String ATTR_USERID = "user_id";
+    private static final String ATTR_EFFECTIVE_UID = "effective_uid";
     private static final String ATTR_TASKTYPE = "task_type";
     private static final String ATTR_FIRSTACTIVETIME = "first_active_time";
     private static final String ATTR_LASTACTIVETIME = "last_active_time";
@@ -83,6 +89,7 @@
     final IVoiceInteractor voiceInteractor;         // Associated interactor to provide to app
     Intent intent;          // The original intent that started the task.
     Intent affinityIntent;  // Intent of affinity-moved activity that started this task.
+    int effectiveUid;       // The current effective uid of the identity of this task.
     ComponentName origActivity; // The non-alias activity component of the intent.
     ComponentName realActivity; // The actual activity component that started the task.
     long firstActiveTime;   // First time this task was active.
@@ -198,7 +205,7 @@
     TaskRecord(ActivityManagerService service, int _taskId, Intent _intent, Intent _affinityIntent,
             String _affinity, ComponentName _realActivity, ComponentName _origActivity,
             boolean _rootWasReset, boolean _autoRemoveRecents, boolean _askedCompatMode,
-            int _taskType, int _userId,
+            int _taskType, int _userId, int _effectiveUid,
             String _lastDescription, ArrayList<ActivityRecord> activities, long _firstActiveTime,
             long _lastActiveTime, long lastTimeMoved, boolean neverRelinquishIdentity,
             ActivityManager.TaskDescription _lastTaskDescription, int taskAffiliation,
@@ -222,6 +229,7 @@
         taskType = _taskType;
         mTaskToReturnTo = HOME_ACTIVITY_TYPE;
         userId = _userId;
+        effectiveUid = _effectiveUid;
         firstActiveTime = _firstActiveTime;
         lastActiveTime = _lastActiveTime;
         lastDescription = _lastDescription;
@@ -265,6 +273,7 @@
         }
 
         affinity = info.taskAffinity;
+        effectiveUid = info.applicationInfo.uid;
         stringName = null;
 
         if (info.targetActivity == null) {
@@ -311,7 +320,6 @@
         }
 
         userId = UserHandle.getUserId(info.applicationInfo.uid);
-        creatorUid = info.applicationInfo.uid;
         if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) {
             // If the activity itself has requested auto-remove, then just always do it.
             autoRemoveRecents = true;
@@ -823,6 +831,7 @@
         out.attribute(null, ATTR_AUTOREMOVERECENTS, String.valueOf(autoRemoveRecents));
         out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode));
         out.attribute(null, ATTR_USERID, String.valueOf(userId));
+        out.attribute(null, ATTR_EFFECTIVE_UID, String.valueOf(effectiveUid));
         out.attribute(null, ATTR_TASKTYPE, String.valueOf(taskType));
         out.attribute(null, ATTR_FIRSTACTIVETIME, String.valueOf(firstActiveTime));
         out.attribute(null, ATTR_LASTACTIVETIME, String.valueOf(lastActiveTime));
@@ -881,6 +890,7 @@
         boolean askedCompatMode = false;
         int taskType = ActivityRecord.APPLICATION_ACTIVITY_TYPE;
         int userId = 0;
+        int effectiveUid = -1;
         String lastDescription = null;
         long firstActiveTime = -1;
         long lastActiveTime = -1;
@@ -917,6 +927,8 @@
                 askedCompatMode = Boolean.valueOf(attrValue);
             } else if (ATTR_USERID.equals(attrName)) {
                 userId = Integer.valueOf(attrValue);
+            } else if (ATTR_EFFECTIVE_UID.equals(attrName)) {
+                effectiveUid = Integer.valueOf(attrValue);
             } else if (ATTR_TASKTYPE.equals(attrName)) {
                 taskType = Integer.valueOf(attrValue);
             } else if (ATTR_FIRSTACTIVETIME.equals(attrName)) {
@@ -979,10 +991,30 @@
                     createLastTaskDescriptionIconFilename(taskId, lastActiveTime)));
         }
 
+        if (effectiveUid <= 0) {
+            Intent checkIntent = intent != null ? intent : affinityIntent;
+            effectiveUid = 0;
+            if (checkIntent != null) {
+                IPackageManager pm = AppGlobals.getPackageManager();
+                try {
+                    ApplicationInfo ai = pm.getApplicationInfo(
+                            checkIntent.getComponent().getPackageName(),
+                            PackageManager.GET_UNINSTALLED_PACKAGES
+                                    | PackageManager.GET_DISABLED_COMPONENTS, userId);
+                    if (ai != null) {
+                        effectiveUid = ai.uid;
+                    }
+                } catch (RemoteException e) {
+                }
+            }
+            Slog.w(TAG, "Updating task #" + taskId + " for " + checkIntent
+                    + ": effectiveUid=" + effectiveUid);
+        }
+
         final TaskRecord task = new TaskRecord(stackSupervisor.mService, taskId, intent,
                 affinityIntent, affinity, realActivity, origActivity, rootHasReset,
-                autoRemoveRecents, askedCompatMode, taskType, userId, lastDescription, activities,
-                firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity,
+                autoRemoveRecents, askedCompatMode, taskType, userId, effectiveUid, lastDescription,
+                activities, firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity,
                 taskDescription, taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor,
                 callingUid, callingPackage);
 
@@ -996,8 +1028,8 @@
 
     void dump(PrintWriter pw, String prefix) {
         pw.print(prefix); pw.print("userId="); pw.print(userId);
-                pw.print(" creatorUid="); pw.print(creatorUid);
-                pw.print(" mCallingUid="); pw.print(mCallingUid);
+                pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
+                pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid);
                 pw.print(" mCallingPackage="); pw.println(mCallingPackage);
         if (affinity != null) {
             pw.print(prefix); pw.print("affinity="); pw.println(affinity);
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 949019e..9e169d9 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -152,7 +152,10 @@
      */
     private static final int DELAY_RETRY_SYNC_IN_PROGRESS_IN_SECONDS = 10;
 
-    private static final int INITIALIZATION_UNBIND_DELAY_MS = 5000;
+    /**
+     * How long to wait before considering an active sync to have timed-out, and cancelling it.
+     */
+    private static final long ACTIVE_SYNC_TIMEOUT_MILLIS = 30L * 60 * 1000;  // 30 mins.
 
     private static final String SYNC_WAKE_LOCK_PREFIX = "*sync*/";
     private static final String HANDLE_SYNC_ALARM_WAKE_LOCK = "SyncManagerHandleSyncAlarm";
@@ -851,6 +854,31 @@
         mSyncHandler.sendMessage(msg);
     }
 
+    /**
+     * Post a delayed message to the handler that will result in the cancellation of the provided
+     * running sync's context.
+     */
+    private void postSyncExpiryMessage(ActiveSyncContext activeSyncContext) {
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            Log.v(TAG, "posting MESSAGE_SYNC_EXPIRED in " +
+                    (ACTIVE_SYNC_TIMEOUT_MILLIS/1000) + "s");
+        }
+        Message msg = mSyncHandler.obtainMessage();
+        msg.what = SyncHandler.MESSAGE_SYNC_EXPIRED;
+        msg.obj = activeSyncContext;
+        mSyncHandler.sendMessageDelayed(msg, ACTIVE_SYNC_TIMEOUT_MILLIS);
+    }
+
+    /**
+     * Remove any time-outs previously posted for the provided active sync.
+     */
+    private void removeSyncExpiryMessage(ActiveSyncContext activeSyncContext) {
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            Log.v(TAG, "removing all MESSAGE_SYNC_EXPIRED for " + activeSyncContext.toString());
+        }
+        mSyncHandler.removeMessages(SyncHandler.MESSAGE_SYNC_EXPIRED, activeSyncContext);
+    }
+
     class SyncHandlerMessagePayload {
         public final ActiveSyncContext activeSyncContext;
         public final SyncResult syncResult;
@@ -1902,6 +1930,8 @@
         private static final int MESSAGE_SERVICE_CONNECTED = 4;
         private static final int MESSAGE_SERVICE_DISCONNECTED = 5;
         private static final int MESSAGE_CANCEL = 6;
+        /** Posted delayed in order to expire syncs that are long-running. */
+        private static final int MESSAGE_SYNC_EXPIRED = 7;
 
         public final SyncNotificationInfo mSyncNotificationInfo = new SyncNotificationInfo();
         private Long mAlarmScheduleTime = null;
@@ -2000,10 +2030,21 @@
                 // to also take into account the periodic syncs.
                 earliestFuturePollTime = scheduleReadyPeriodicSyncs();
                 switch (msg.what) {
+                    case SyncHandler.MESSAGE_SYNC_EXPIRED:
+                        ActiveSyncContext expiredContext = (ActiveSyncContext) msg.obj;
+                        if (Log.isLoggable(TAG, Log.DEBUG)) {
+                            Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_SYNC_EXPIRED: expiring "
+                                    + expiredContext);
+                        }
+                        cancelActiveSync(expiredContext.mSyncOperation.target,
+                                expiredContext.mSyncOperation.extras);
+                        nextPendingSyncTime = maybeStartNextSyncLocked();
+                        break;
+
                     case SyncHandler.MESSAGE_CANCEL: {
                         SyncStorageEngine.EndPoint payload = (SyncStorageEngine.EndPoint) msg.obj;
                         Bundle extras = msg.peekData();
-                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                        if (Log.isLoggable(TAG, Log.DEBUG)) {
                             Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_SERVICE_CANCEL: "
                                     + payload + " bundle: " + extras);
                         }
@@ -2653,6 +2694,13 @@
                     new ActiveSyncContext(op, insertStartSyncEvent(op), targetUid);
             activeSyncContext.mSyncInfo = mSyncStorageEngine.addActiveSync(activeSyncContext);
             mActiveSyncContexts.add(activeSyncContext);
+            if (!activeSyncContext.mSyncOperation.isInitialization() &&
+                    !activeSyncContext.mSyncOperation.isExpedited() &&
+                    !activeSyncContext.mSyncOperation.isManual() &&
+                    !activeSyncContext.mSyncOperation.isIgnoreSettings()) {
+                // Post message to expire this sync if it runs for too long.
+                postSyncExpiryMessage(activeSyncContext);
+            }
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
                 Log.v(TAG, "dispatchSyncOperation: starting " + activeSyncContext);
             }
@@ -2757,9 +2805,7 @@
                 } else {
                     Log.d(TAG, "failed sync operation " + syncOperation + ", " + syncResult);
                     // the operation failed so increase the backoff time
-                    if (!syncResult.syncAlreadyInProgress) {
-                        increaseBackoffSetting(syncOperation);
-                    }
+                    increaseBackoffSetting(syncOperation);
                     // reschedule the sync if so indicated by the syncResult
                     maybeRescheduleSync(syncResult, syncOperation);
                     historyMessage = ContentResolver.syncErrorToString(
@@ -2768,7 +2814,6 @@
                     downstreamActivity = 0;
                     upstreamActivity = 0;
                 }
-
                 setDelayUntilTime(syncOperation, syncResult.delayUntil);
             } else {
                 if (isLoggable) {
@@ -2794,7 +2839,6 @@
 
             stopSyncEvent(activeSyncContext.mHistoryRowId, syncOperation, historyMessage,
                     upstreamActivity, downstreamActivity, elapsedTime);
-
             // Check for full-resync and schedule it after closing off the last sync.
             if (info.target_provider) {
                 if (syncResult != null && syncResult.tooManyDeletions) {
@@ -2833,6 +2877,7 @@
             mActiveSyncContexts.remove(activeSyncContext);
             mSyncStorageEngine.removeActiveSync(activeSyncContext.mSyncInfo,
                     activeSyncContext.mSyncOperation.target.userId);
+            removeSyncExpiryMessage(activeSyncContext);
         }
 
         /**
diff --git a/services/core/java/com/android/server/content/SyncOperation.java b/services/core/java/com/android/server/content/SyncOperation.java
index 9a4abce..35827cc 100644
--- a/services/core/java/com/android/server/content/SyncOperation.java
+++ b/services/core/java/com/android/server/content/SyncOperation.java
@@ -273,6 +273,14 @@
         return extras.getBoolean(ContentResolver.SYNC_EXTRAS_DISALLOW_METERED, false);
     }
 
+    public boolean isManual() {
+        return extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);
+    }
+
+    public boolean isIgnoreSettings() {
+        return extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false);
+    }
+
     /** Changed in V3. */
     public static String toKey(SyncStorageEngine.EndPoint info, Bundle extras) {
         StringBuilder sb = new StringBuilder();
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 935714c..10a47d8 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -22,6 +22,7 @@
 import static android.hardware.hdmi.HdmiControlManager.ONE_TOUCH_RECORD_CEC_DISABLED;
 import static android.hardware.hdmi.HdmiControlManager.ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION;
 import static android.hardware.hdmi.HdmiControlManager.ONE_TOUCH_RECORD_FAIL_TO_RECORD_DISPLAYED_SCREEN;
+import static android.hardware.hdmi.HdmiControlManager.OSD_MESSAGE_ARC_CONNECTED_INVALID_PORT;
 import static android.hardware.hdmi.HdmiControlManager.TIMER_RECORDING_RESULT_EXTRA_CEC_DISABLED;
 import static android.hardware.hdmi.HdmiControlManager.TIMER_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION;
 import static android.hardware.hdmi.HdmiControlManager.TIMER_RECORDING_RESULT_EXTRA_FAIL_TO_RECORD_SELECTED_SOURCE;
@@ -29,7 +30,6 @@
 import static android.hardware.hdmi.HdmiControlManager.TIMER_RECORDING_TYPE_DIGITAL;
 import static android.hardware.hdmi.HdmiControlManager.TIMER_RECORDING_TYPE_EXTERNAL;
 
-import android.content.Intent;
 import android.hardware.hdmi.HdmiControlManager;
 import android.hardware.hdmi.HdmiDeviceInfo;
 import android.hardware.hdmi.HdmiRecordSources;
@@ -39,7 +39,6 @@
 import android.media.AudioSystem;
 import android.os.RemoteException;
 import android.os.SystemProperties;
-import android.os.UserHandle;
 import android.provider.Settings.Global;
 import android.util.ArraySet;
 import android.util.Slog;
@@ -57,7 +56,6 @@
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Locale;
 
 /**
  * Represent a logical device of type TV residing in Android system.
@@ -70,8 +68,9 @@
     @ServiceThreadOnly
     private boolean mArcEstablished = false;
 
-    // Whether ARC feature is enabled or not.
-    private boolean mArcFeatureEnabled = false;
+    // Whether ARC feature is enabled or not. The default value is true.
+    // TODO: once adding system setting for it, read the value to it.
+    private boolean mArcFeatureEnabled = true;
 
     // Whether System audio mode is activated or not.
     // This becomes true only when all system audio sequences are finished.
@@ -642,19 +641,26 @@
                         // If there is AVR, initiate System Audio Auto initiation action,
                         // which turns on and off system audio according to last system
                         // audio setting.
-                        if (mSystemAudioActivated && getAvrDeviceInfo() != null) {
-                            addAndStartAction(new SystemAudioAutoInitiationAction(
-                                    HdmiCecLocalDeviceTv.this,
-                                    getAvrDeviceInfo().getLogicalAddress()));
-                            if (mArcEstablished) {
-                                startArcAction(true);
-                            }
+                        HdmiDeviceInfo avr = getAvrDeviceInfo();
+                        if (avr != null) {
+                            onNewAvrAdded(avr);
                         }
                     }
                 });
         addAndStartAction(action);
     }
 
+    @ServiceThreadOnly
+    void onNewAvrAdded(HdmiDeviceInfo avr) {
+        assertRunOnServiceThread();
+        if (getSystemAudioModeSetting()) {
+            addAndStartAction(new SystemAudioAutoInitiationAction(this, avr.getLogicalAddress()));
+        }
+        if (isArcFeatureEnabled()) {
+            startArcAction(true);
+        }
+    }
+
     // Clear all device info.
     @ServiceThreadOnly
     private void clearDeviceInfoList() {
@@ -757,6 +763,7 @@
         assertRunOnServiceThread();
 
         if (mArcFeatureEnabled != enabled) {
+            mArcFeatureEnabled = enabled;
             if (enabled) {
                 if (!mArcEstablished) {
                     startArcAction(true);
@@ -766,7 +773,6 @@
                     startArcAction(false);
                 }
             }
-            mArcFeatureEnabled = enabled;
         }
     }
 
@@ -777,13 +783,18 @@
     }
 
     @ServiceThreadOnly
-    private void startArcAction(boolean enabled) {
+    void startArcAction(boolean enabled) {
         assertRunOnServiceThread();
         HdmiDeviceInfo info = getAvrDeviceInfo();
         if (info == null) {
+            Slog.w(TAG, "Failed to start arc action; No AVR device.");
             return;
         }
-        if (!isConnectedToArcPort(info.getPhysicalAddress())) {
+        if (!canStartArcUpdateAction(info.getLogicalAddress(), enabled)) {
+            Slog.w(TAG, "Failed to start arc action; ARC configuration check failed.");
+            if (enabled && !isConnectedToArcPort(info.getPhysicalAddress())) {
+                displayOsd(OSD_MESSAGE_ARC_CONNECTED_INVALID_PORT);
+            }
             return;
         }
 
@@ -801,6 +812,10 @@
         }
     }
 
+    private boolean isDirectConnectAddress(int physicalAddress) {
+        return (physicalAddress & Constants.ROUTING_PATH_TOP_MASK) == physicalAddress;
+    }
+
     void setAudioStatus(boolean mute, int volume) {
         synchronized (mLock) {
             mSystemAudioMute = mute;
@@ -857,6 +872,15 @@
     @ServiceThreadOnly
     protected boolean handleInitiateArc(HdmiCecMessage message) {
         assertRunOnServiceThread();
+
+        if (!canStartArcUpdateAction(message.getSource(), true)) {
+            mService.maySendFeatureAbortCommand(message, Constants.ABORT_REFUSED);
+            if (!isConnectedToArcPort(message.getSource())) {
+                displayOsd(OSD_MESSAGE_ARC_CONNECTED_INVALID_PORT);
+            }
+            return true;
+        }
+
         // In case where <Initiate Arc> is started by <Request ARC Initiation>
         // need to clean up RequestArcInitiationAction.
         removeAction(RequestArcInitiationAction.class);
@@ -866,10 +890,29 @@
         return true;
     }
 
+    private boolean canStartArcUpdateAction(int avrAddress, boolean shouldCheckArcFeatureEnabled) {
+        HdmiDeviceInfo avr = getAvrDeviceInfo();
+        if (avr != null
+                && (avrAddress == avr.getLogicalAddress())
+                && isConnectedToArcPort(avr.getPhysicalAddress())
+                && isDirectConnectAddress(avr.getPhysicalAddress())) {
+            if (shouldCheckArcFeatureEnabled) {
+                return isArcFeatureEnabled();
+            } else {
+                return true;
+            }
+        } else {
+            return false;
+        }
+    }
+
     @Override
     @ServiceThreadOnly
     protected boolean handleTerminateArc(HdmiCecMessage message) {
         assertRunOnServiceThread();
+        // In cast of termination, do not check ARC configuration in that AVR device
+        // might be removed already.
+
         // In case where <Terminate Arc> is started by <Request ARC Termination>
         // need to clean up RequestArcInitiationAction.
         removeAction(RequestArcTerminationAction.class);
@@ -1000,7 +1043,7 @@
      * Return a list of all {@link HdmiDeviceInfo}.
      *
      * <p>Declared as package-private. accessed by {@link HdmiControlService} only.
-     * This is not thread-safe. For thread safety, call {@link #getSafeExternalInputs} which
+     * This is not thread-safe. For thread safety, call {@link #getSafeExternalInputsLocked} which
      * does not include local device.
      */
     @ServiceThreadOnly
@@ -1116,7 +1159,7 @@
      *
      * This is not thread-safe. For thread safety, call {@link #getSafeCecDeviceInfo(int)}.
      *
-     * @param address logical address of the device to be retrieved
+     * @param logicalAddress logical address of the device to be retrieved
      * @return {@link HdmiDeviceInfo} matched with the given {@code logicalAddress}.
      *         Returns null if no logical address matched
      */
@@ -1388,11 +1431,10 @@
         return mService.isPowerStandbyOrTransient();
     }
 
+    @ServiceThreadOnly
     void displayOsd(int messageId) {
-        Intent intent = new Intent(HdmiControlManager.ACTION_OSD_MESSAGE);
-        intent.putExtra(HdmiControlManager.EXTRA_MESSAGE_ID, messageId);
-        mService.getContext().sendBroadcastAsUser(intent, UserHandle.ALL,
-                HdmiControlService.PERMISSION);
+        assertRunOnServiceThread();
+        mService.displayOsd(messageId);
     }
 
     // Seq #54 and #55
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
index b53cd45..9a51e3c 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
@@ -54,8 +54,8 @@
     static HdmiCecMessage buildFeatureAbortCommand(int src, int dest, int originalOpcode,
             int reason) {
         byte[] params = new byte[] {
-                (byte) originalOpcode,
-                (byte) reason,
+                (byte) (originalOpcode & 0xFF),
+                (byte) (reason & 0xFF),
         };
         return buildCommand(src, dest, Constants.MESSAGE_FEATURE_ABORT, params);
     }
@@ -110,9 +110,9 @@
         // Hdmi CEC uses lower-cased ISO 639-2 (3 letters code).
         String normalized = language.toLowerCase();
         byte[] params = new byte[] {
-                (byte) normalized.charAt(0),
-                (byte) normalized.charAt(1),
-                (byte) normalized.charAt(2),
+                (byte) (normalized.charAt(0) & 0xFF),
+                (byte) (normalized.charAt(1) & 0xFF),
+                (byte) (normalized.charAt(2) & 0xFF),
         };
         // <Set Menu Language> is broadcast message.
         return buildCommand(src, Constants.ADDR_BROADCAST,
@@ -155,7 +155,7 @@
                 (byte) ((address >> 8) & 0xFF),
                 (byte) (address & 0xFF),
                 // One byte device type
-                (byte) deviceType
+                (byte) (deviceType & 0xFF)
         };
         // <Report Physical Address> is broadcast message.
         return buildCommand(src, Constants.ADDR_BROADCAST,
@@ -194,7 +194,7 @@
      */
     static HdmiCecMessage buildCecVersion(int src, int dest, int version) {
         byte[] params = new byte[] {
-                (byte) version
+                (byte) (version & 0xFF)
         };
         return buildCommand(src, dest, Constants.MESSAGE_CEC_VERSION, params);
     }
@@ -332,7 +332,7 @@
      */
     static HdmiCecMessage buildReportPowerStatus(int src, int dest, int powerStatus) {
         byte[] param = new byte[] {
-                (byte) (powerStatus)
+                (byte) (powerStatus & 0xFF)
         };
         return buildCommand(src, dest, Constants.MESSAGE_REPORT_POWER_STATUS, param);
     }
@@ -347,7 +347,7 @@
      */
     static HdmiCecMessage buildReportMenuStatus(int src, int dest, int menuStatus) {
         byte[] param = new byte[] {
-                (byte) (menuStatus)
+                (byte) (menuStatus & 0xFF)
         };
         return buildCommand(src, dest, Constants.MESSAGE_MENU_STATUS, param);
     }
@@ -391,7 +391,7 @@
      * @return newly created {@link HdmiCecMessage}
      */
     static HdmiCecMessage buildUserControlPressed(int src, int dest, int uiCommand) {
-        return buildUserControlPressed(src, dest, new byte[] { (byte) uiCommand });
+        return buildUserControlPressed(src, dest, new byte[] { (byte) (uiCommand & 0xFF) });
     }
 
     /**
@@ -594,7 +594,7 @@
 
     private static byte[] physicalAddressToParam(int physicalAddress) {
         return new byte[] {
-                (byte) (physicalAddress >> 8),
+                (byte) ((physicalAddress >> 8) & 0xFF),
                 (byte) (physicalAddress & 0xFF)
         };
     }
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 3021285..fcccfc0 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -606,7 +606,7 @@
      * Whether a device of the specified physical address is connected to ARC enabled port.
      */
     boolean isConnectedToArcPort(int physicalAddress) {
-        int portId = mPortIdMap.get(physicalAddress);
+        int portId = pathToPortId(physicalAddress);
         if (portId != Constants.INVALID_PORT_ID) {
             return mPortInfoMap.get(portId).isArcSupported();
         }
@@ -1980,4 +1980,13 @@
             return mMhlInputChangeEnabled;
         }
     }
+
+    @ServiceThreadOnly
+    void displayOsd(int messageId) {
+        assertRunOnServiceThread();
+        Intent intent = new Intent(HdmiControlManager.ACTION_OSD_MESSAGE);
+        intent.putExtra(HdmiControlManager.EXTRA_MESSAGE_ID, messageId);
+        getContext().sendBroadcastAsUser(intent, UserHandle.ALL,
+                HdmiControlService.PERMISSION);
+    }
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiLogger.java b/services/core/java/com/android/server/hdmi/HdmiLogger.java
index 93ccfe1..cb72bc1 100644
--- a/services/core/java/com/android/server/hdmi/HdmiLogger.java
+++ b/services/core/java/com/android/server/hdmi/HdmiLogger.java
@@ -16,6 +16,7 @@
 
 package com.android.server.hdmi;
 
+import android.annotation.Nullable;
 import android.os.SystemClock;
 import android.util.Pair;
 import android.util.Slog;
@@ -47,7 +48,7 @@
         long curTime = SystemClock.uptimeMillis();
         Pair<Long, Integer> timing = mWarningTimingCache.get(logMessage);
         if (shouldLogNow(timing, curTime)) {
-            Slog.w(mTag, buildMessage(logMessage, timing, curTime));
+            Slog.w(mTag, buildMessage(logMessage, timing));
             mWarningTimingCache.put(logMessage, new Pair<>(curTime, 1));
         } else {
             increaseLogCount(mWarningTimingCache, logMessage);
@@ -58,16 +59,16 @@
         long curTime = SystemClock.uptimeMillis();
         Pair<Long, Integer> timing = mErrorTimingCache.get(logMessage);
         if (shouldLogNow(timing, curTime)) {
-            Slog.e(mTag, buildMessage(logMessage, timing, curTime));
+            Slog.e(mTag, buildMessage(logMessage, timing));
             mErrorTimingCache.put(logMessage, new Pair<>(curTime, 1));
         } else {
             increaseLogCount(mErrorTimingCache, logMessage);
         }
     }
 
-    private String buildMessage(String message, Pair<Long, Integer> timing, long curTime) {
+    private String buildMessage(String message, @Nullable Pair<Long, Integer> timing) {
         return new StringBuilder()
-            .append("[").append(timing == null ? curTime : timing.second).append("]:")
+            .append("[").append(timing == null ? 1 : timing.second).append("]:")
             .append(message).toString();
     }
 
@@ -78,7 +79,7 @@
         }
     }
 
-    private boolean shouldLogNow(Pair<Long, Integer> timing, long curTime) {
+    private boolean shouldLogNow(@Nullable Pair<Long, Integer> timing, long curTime) {
         return timing == null || curTime - timing.first > ERROR_LOG_DURATTION_MILLIS;
     }
 }
diff --git a/services/core/java/com/android/server/hdmi/NewDeviceAction.java b/services/core/java/com/android/server/hdmi/NewDeviceAction.java
index a5fdbea..2074085 100644
--- a/services/core/java/com/android/server/hdmi/NewDeviceAction.java
+++ b/services/core/java/com/android/server/hdmi/NewDeviceAction.java
@@ -103,8 +103,8 @@
                 requestVendorId();
                 return true;
             } else if (opcode == Constants.MESSAGE_FEATURE_ABORT) {
-                int requestOpcode = params[1] & 0xFF;
-                if (requestOpcode == Constants.MESSAGE_SET_OSD_NAME) {
+                int requestOpcode = params[0] & 0xFF;
+                if (requestOpcode == Constants.MESSAGE_GIVE_OSD_NAME) {
                     requestVendorId();
                     return true;
                 }
@@ -116,8 +116,8 @@
                 finish();
                 return true;
             } else if (opcode == Constants.MESSAGE_FEATURE_ABORT) {
-                int requestOpcode = params[1] & 0xFF;
-                if (requestOpcode == Constants.MESSAGE_DEVICE_VENDOR_ID) {
+                int requestOpcode = params[0] & 0xFF;
+                if (requestOpcode == Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID) {
                     addDeviceInfo();
                     finish();
                     return true;
@@ -152,30 +152,19 @@
         if (mDisplayName == null) {
             mDisplayName = HdmiUtils.getDefaultDeviceName(mDeviceLogicalAddress);
         }
-        tv().addCecDevice(new HdmiDeviceInfo(
+        HdmiDeviceInfo deviceInfo = new HdmiDeviceInfo(
                 mDeviceLogicalAddress, mDevicePhysicalAddress,
                 tv().getPortId(mDevicePhysicalAddress),
                 HdmiUtils.getTypeFromAddress(mDeviceLogicalAddress),
-                mVendorId, mDisplayName));
+                mVendorId, mDisplayName);
+        tv().addCecDevice(deviceInfo);
 
         if (HdmiUtils.getTypeFromAddress(mDeviceLogicalAddress)
                 == HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM) {
-            if (tv().getSystemAudioModeSetting()) {
-                addAndStartAction(new SystemAudioAutoInitiationAction(localDevice(),
-                        mDeviceLogicalAddress));
-            }
-
-            if (shouldTryArcInitiation()) {
-                addAndStartAction(new RequestArcInitiationAction(localDevice(),
-                        mDeviceLogicalAddress));
-            }
+            tv().onNewAvrAdded(deviceInfo);
         }
     }
 
-    private boolean shouldTryArcInitiation() {
-        return tv().isConnectedToArcPort(mDevicePhysicalAddress) && tv().isArcFeatureEnabled();
-    }
-
     @Override
     public void handleTimerEvent(int state) {
         if (mState == STATE_NONE || mState != state) {
diff --git a/services/core/java/com/android/server/hdmi/RequestArcAction.java b/services/core/java/com/android/server/hdmi/RequestArcAction.java
index 9c530a3..17c2d6c 100644
--- a/services/core/java/com/android/server/hdmi/RequestArcAction.java
+++ b/services/core/java/com/android/server/hdmi/RequestArcAction.java
@@ -17,7 +17,6 @@
 package com.android.server.hdmi;
 
 import android.hardware.hdmi.HdmiDeviceInfo;
-
 import android.util.Slog;
 
 /**
@@ -57,11 +56,17 @@
         switch (opcode) {
             // Handles only <Feature Abort> here and, both <Initiate ARC> and <Terminate ARC>
             // are handled in HdmiControlService itself because both can be
-            // received wihtout <Request ARC Initiation> or <Request ARC Termination>.
+            // received without <Request ARC Initiation> or <Request ARC Termination>.
             case Constants.MESSAGE_FEATURE_ABORT:
-                disableArcTransmission();
-                finish();
-                return true;
+                int originalOpcode = cmd.getParams()[0] & 0xFF;
+                if (originalOpcode == Constants.MESSAGE_REQUEST_ARC_INITIATION
+                        || originalOpcode == Constants.MESSAGE_REQUEST_ARC_TERMINATION) {
+                    disableArcTransmission();
+                    finish();
+                    return true;
+                } else {
+                    return false;
+                }
             default:
                 Slog.w(TAG, "Unsupported opcode:" + cmd.toString());
         }
diff --git a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
index 9f7f98a..c1c6b91 100644
--- a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
+++ b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
@@ -110,10 +110,14 @@
 
         int opcode = cmd.getOpcode();
         if (opcode == Constants.MESSAGE_FEATURE_ABORT) {
-            setArcStatus(false);
+            int originalOpcode = cmd.getParams()[0] & 0xFF;
+            if (originalOpcode == Constants.MESSAGE_REPORT_ARC_INITIATED) {
+                setArcStatus(false);
+                finish();
+                return true;
+            }
         }
-        finish();
-        return true;
+        return false;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAction.java
index 7e45a99..ac2c7b9 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioAction.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioAction.java
@@ -127,7 +127,8 @@
         switch (mState) {
             case STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE:
                 if (cmd.getOpcode() == Constants.MESSAGE_FEATURE_ABORT
-                        && cmd.getParams()[0] == Constants.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST) {
+                        && (cmd.getParams()[0] & 0xFF)
+                                == Constants.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST) {
                     setSystemAudioMode(false);
                     finishWithCallback(HdmiControlManager.RESULT_EXCEPTION);
                     return true;
diff --git a/services/core/java/com/android/server/hdmi/VolumeControlAction.java b/services/core/java/com/android/server/hdmi/VolumeControlAction.java
index 01c6f3e..ddc267a 100644
--- a/services/core/java/com/android/server/hdmi/VolumeControlAction.java
+++ b/services/core/java/com/android/server/hdmi/VolumeControlAction.java
@@ -156,10 +156,14 @@
                 handleReportAudioStatus(cmd);
                 return true;
             case Constants.MESSAGE_FEATURE_ABORT:
-                // TODO: handle feature abort.
-                finish();
-                return true;
-            default:
+                int originalOpcode = cmd.getParams()[0] & 0xFF;
+                if (originalOpcode == Constants.MESSAGE_USER_CONTROL_PRESSED
+                        || originalOpcode == Constants.MESSAGE_USER_CONTROL_RELEASED) {
+                    // TODO: handle feature abort.
+                    finish();
+                    return true;
+                }
+            default:  // fall through
                 return false;
         }
     }
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index 69d1dc9..8ec9b254 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -111,7 +111,6 @@
             @Override
             public void binderDied() {
                 synchronized (mLock) {
-                    unlinkDeathRecipientLocked(callback);
                     removeCallback(callback);
                 }
             }
@@ -125,7 +124,7 @@
     private void removeCallback(IMediaProjectionWatcherCallback callback) {
         synchronized (mLock) {
             unlinkDeathRecipientLocked(callback);
-            removeCallback(callback);
+            mCallbackDelegate.remove(callback);
         }
     }
 
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index c390f9b..6fd4eb7 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1277,21 +1277,29 @@
          * should be used.
          *
          * @param token The binder for the listener, to check that the caller is allowed
+         * @param keys An array of notification keys to fetch, or null to fetch everything
          * @returns The return value will contain the notifications specified in keys, in that
          *      order, or if keys is null, all the notifications, in natural order.
          */
         @Override
         public ParceledListSlice<StatusBarNotification> getActiveNotificationsFromListener(
-                INotificationListener token) {
+                INotificationListener token, String[] keys) {
             synchronized (mNotificationList) {
                 final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
                 final ArrayList<StatusBarNotification> list
                         = new ArrayList<StatusBarNotification>();
-                final int N = mNotificationList.size();
+                final boolean getKeys = keys != null;
+                final int N = getKeys ? keys.length : mNotificationList.size();
+                list.ensureCapacity(N);
                 for (int i=0; i<N; i++) {
-                    StatusBarNotification sbn = mNotificationList.get(i).sbn;
-                    if (isVisibleToListener(sbn, info)) {
-                        list.add(sbn);
+                    final NotificationRecord r = getKeys
+                            ? mNotificationsByKey.get(keys[i])
+                            : mNotificationList.get(i);
+                    if (r != null) {
+                        StatusBarNotification sbn = r.sbn;
+                        if (isVisibleToListener(sbn, info)) {
+                            list.add(sbn);
+                        }
                     }
                 }
                 return new ParceledListSlice<StatusBarNotification>(list);
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index f6ec86d..aabb8f7 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -19,7 +19,6 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
-import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.Debug;
 import android.os.Handler;
@@ -46,7 +45,7 @@
 import static com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
 import static com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation;
 import static com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_launchTaskBehindBackgroundAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_launchTaskBehindTargetAnimation;
 import static com.android.internal.R.styleable.WindowAnimation_launchTaskBehindSourceAnimation;
 import static com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation;
 import static com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation;
@@ -111,11 +110,14 @@
      * The new window will show briefly and then be gone. */
     public static final int TRANSIT_TASK_OPEN_BEHIND = 16;
 
+    /** Fraction of animation at which the recents thumbnail stays completely transparent */
+    private static final float RECENTS_THUMBNAIL_FADEIN_FRACTION = 0.7f;
     /** Fraction of animation at which the recents thumbnail becomes completely transparent */
-    private static final float RECENTS_THUMBNAIL_FADEOUT_FRACTION = 0.25f;
+    private static final float RECENTS_THUMBNAIL_FADEOUT_FRACTION = 0.3f;
 
     private static final int DEFAULT_APP_TRANSITION_DURATION = 250;
-    private static final int THUMBNAIL_APP_TRANSITION_DURATION = 275;
+    private static final int THUMBNAIL_APP_TRANSITION_DURATION = 300;
+    private static final int THUMBNAIL_APP_TRANSITION_ALPHA_DURATION = 325;
 
     private final Context mContext;
     private final Handler mH;
@@ -127,6 +129,8 @@
     private static final int NEXT_TRANSIT_TYPE_SCALE_UP = 2;
     private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP = 3;
     private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN = 4;
+    private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP = 5;
+    private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN = 6;
     private int mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE;
 
     // These are the possible states for the enter/exit activities during a thumbnail transition
@@ -146,6 +150,7 @@
     private int mNextAppTransitionStartY;
     private int mNextAppTransitionStartWidth;
     private int mNextAppTransitionStartHeight;
+    private Rect mNextAppTransitionInsets = new Rect();
 
     private Rect mTmpFromClipRect = new Rect();
     private Rect mTmpToClipRect = new Rect();
@@ -158,7 +163,8 @@
 
     private final int mConfigShortAnimTime;
     private final Interpolator mDecelerateInterpolator;
-    private final Interpolator mThumbnailFadeoutInterpolator;
+    private final Interpolator mThumbnailFadeInInterpolator;
+    private final Interpolator mThumbnailFadeOutInterpolator;
     private final Interpolator mThumbnailFastOutSlowInInterpolator;
 
     private int mCurrentUserId = 0;
@@ -172,14 +178,25 @@
                 com.android.internal.R.interpolator.decelerate_cubic);
         mThumbnailFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
                 com.android.internal.R.interpolator.fast_out_slow_in);
-        mThumbnailFadeoutInterpolator = new Interpolator() {
+        mThumbnailFadeInInterpolator = new Interpolator() {
+            @Override
+            public float getInterpolation(float input) {
+                // Linear response for first fraction, then complete after that.
+                if (input < RECENTS_THUMBNAIL_FADEIN_FRACTION) {
+                    return 0f;
+                }
+                return (input - RECENTS_THUMBNAIL_FADEIN_FRACTION) /
+                        (1f - RECENTS_THUMBNAIL_FADEIN_FRACTION);
+            }
+        };
+        mThumbnailFadeOutInterpolator = new Interpolator() {
             @Override
             public float getInterpolation(float input) {
                 // Linear response for first fraction, then complete after that.
                 if (input < RECENTS_THUMBNAIL_FADEOUT_FRACTION) {
                     return input / RECENTS_THUMBNAIL_FADEOUT_FRACTION;
                 }
-                return 1.0f;
+                return 1f;
             }
         };
     }
@@ -233,9 +250,23 @@
         return mNextAppTransitionThumbnail;
     }
 
-    void getStartingPoint(Point outPoint) {
-        outPoint.x = mNextAppTransitionStartX;
-        outPoint.y = mNextAppTransitionStartY;
+    /** Returns whether the next thumbnail transition is aspect scaled up. */
+    boolean isNextThumbnailTransitionAspectScaled() {
+        return mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP ||
+                mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
+    }
+
+    /** Returns whether the next thumbnail transition is scaling up. */
+    boolean isNextThumbnailTransitionScaleUp() {
+        return mNextAppTransitionScaleUp;
+    }
+
+    int getStartingX() {
+        return mNextAppTransitionStartX;
+    }
+
+    int getStartingY() {
+        return mNextAppTransitionStartY;
     }
 
     void prepare() {
@@ -372,7 +403,7 @@
             scale.setInterpolator(mDecelerateInterpolator);
 
             Animation alpha = new AlphaAnimation(0, 1);
-            alpha.setInterpolator(mThumbnailFadeoutInterpolator);
+            alpha.setInterpolator(mThumbnailFadeOutInterpolator);
 
             AnimationSet set = new AnimationSet(false);
             set.addAnimation(scale);
@@ -417,7 +448,9 @@
      */
     Animation prepareThumbnailAnimationWithDuration(Animation a, int appWidth, int appHeight,
             int duration, Interpolator interpolator) {
-        a.setDuration(duration);
+        if (duration > 0) {
+            a.setDuration(duration);
+        }
         a.setFillAfter(true);
         a.setInterpolator(interpolator);
         a.initialize(appWidth, appHeight, appWidth, appHeight);
@@ -468,50 +501,73 @@
      * This animation runs for the thumbnail that gets cross faded with the enter/exit activity
      * when a thumbnail is specified with the activity options.
      */
-    Animation createThumbnailScaleAnimationLocked(int appWidth, int appHeight, int transit) {
+    Animation createThumbnailAspectScaleAnimationLocked(int appWidth, int appHeight,
+            int deviceWidth, int transit) {
         Animation a;
         final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
         final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
         final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
         final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
 
+        float scaleW = deviceWidth / thumbWidth;
+        float unscaledWidth = deviceWidth;
+        float unscaledHeight = thumbHeight * scaleW;
+        float unscaledStartY = mNextAppTransitionStartY - (unscaledHeight - thumbHeight) / 2f;
         if (mNextAppTransitionScaleUp) {
-            // Animation for the thumbnail zooming from its initial size to the full screen
-            float scaleW = appWidth / thumbWidth;
-            float scaleH = appHeight / thumbHeight;
-            Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
-                    computePivot(mNextAppTransitionStartX, 1 / scaleW),
-                    computePivot(mNextAppTransitionStartY, 1 / scaleH));
-            scale.setInterpolator(mDecelerateInterpolator);
-
+            // Animation up from the thumbnail to the full screen
+            Animation scale = new ScaleAnimation(1f, scaleW, 1f, scaleW,
+                    mNextAppTransitionStartX + (thumbWidth / 2f),
+                    mNextAppTransitionStartY + (thumbHeight / 2f));
+            scale.setInterpolator(mThumbnailFastOutSlowInInterpolator);
+            scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
             Animation alpha = new AlphaAnimation(1, 0);
-            alpha.setInterpolator(mThumbnailFadeoutInterpolator);
+            alpha.setInterpolator(mThumbnailFadeOutInterpolator);
+            alpha.setDuration(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION);
+            Animation translate = new TranslateAnimation(0, 0, 0, -unscaledStartY +
+                    mNextAppTransitionInsets.top);
+            translate.setInterpolator(mThumbnailFastOutSlowInInterpolator);
+            translate.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
 
             // This AnimationSet uses the Interpolators assigned above.
             AnimationSet set = new AnimationSet(false);
             set.addAnimation(scale);
             set.addAnimation(alpha);
+            set.addAnimation(translate);
             a = set;
         } else {
-            // Animation for the thumbnail zooming down from the full screen to its final size
-            float scaleW = appWidth / thumbWidth;
-            float scaleH = appHeight / thumbHeight;
-            a = new ScaleAnimation(scaleW, 1, scaleH, 1,
-                    computePivot(mNextAppTransitionStartX, 1 / scaleW),
-                    computePivot(mNextAppTransitionStartY, 1 / scaleH));
-        }
+            // Animation down from the full screen to the thumbnail
+            Animation scale = new ScaleAnimation(scaleW, 1f, scaleW, 1f,
+                    mNextAppTransitionStartX + (thumbWidth / 2f),
+                    mNextAppTransitionStartY + (thumbHeight / 2f));
+            scale.setInterpolator(mThumbnailFastOutSlowInInterpolator);
+            scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
+            Animation alpha = new AlphaAnimation(0f, 1f);
+            alpha.setInterpolator(mThumbnailFadeInInterpolator);
+            alpha.setDuration(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION);
+            Animation translate = new TranslateAnimation(0, 0, -unscaledStartY +
+                    mNextAppTransitionInsets.top, 0);
+            translate.setInterpolator(mThumbnailFastOutSlowInInterpolator);
+            translate.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
 
-        return prepareThumbnailAnimation(a, appWidth, appHeight, transit);
+            // This AnimationSet uses the Interpolators assigned above.
+            AnimationSet set = new AnimationSet(false);
+            set.addAnimation(scale);
+            set.addAnimation(alpha);
+            set.addAnimation(translate);
+            a = set;
+
+        }
+        return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, 0,
+                mThumbnailFastOutSlowInInterpolator);
     }
 
     /**
      * This alternate animation is created when we are doing a thumbnail transition, for the
      * activity that is leaving, and the activity that is entering.
      */
-    Animation createAlternateThumbnailEnterExitAnimationLocked(int thumbTransitState, int appWidth,
-                                                    int appHeight, int orientation, int transit,
-                                                    Rect containingFrame, Rect contentInsets,
-                                                    boolean isFullScreen) {
+    Animation createAspectScaledThumbnailEnterExitAnimationLocked(int thumbTransitState,
+            int appWidth, int appHeight, int orientation, int transit, Rect containingFrame,
+            Rect contentInsets, boolean isFullScreen) {
         Animation a;
         final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
         final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
@@ -524,7 +580,7 @@
 
         switch (thumbTransitState) {
             case THUMBNAIL_TRANSITION_ENTER_SCALE_UP: {
-                // Entering app scales up with the thumbnail
+                // App window scaling up to become full screen
                 if (orientation == Configuration.ORIENTATION_PORTRAIT) {
                     // In portrait, we scale the width and clip to the top/left square
                     scale = thumbWidth / appWidth;
@@ -550,16 +606,15 @@
                     mTmpFromClipRect.right = (mTmpFromClipRect.left + unscaledThumbWidth);
                     mTmpToClipRect.set(containingFrame);
                 }
+                mNextAppTransitionInsets.set(contentInsets);
 
                 Animation scaleAnim = new ScaleAnimation(scale, 1, scale, 1,
                         computePivot(mNextAppTransitionStartX, scale),
                         computePivot(mNextAppTransitionStartY, scale));
-                Animation alphaAnim = new AlphaAnimation(1, 1);
                 Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
                 Animation translateAnim = new TranslateAnimation(0, 0, -scaledTopDecor, 0);
 
                 AnimationSet set = new AnimationSet(true);
-                set.addAnimation(alphaAnim);
                 set.addAnimation(clipAnim);
                 set.addAnimation(scaleAnim);
                 set.addAnimation(translateAnim);
@@ -567,26 +622,29 @@
                 break;
             }
             case THUMBNAIL_TRANSITION_EXIT_SCALE_UP: {
-                // Exiting app while the thumbnail is scaling up should fade
+                // Previous app window during the scale up
                 if (transit == TRANSIT_WALLPAPER_INTRA_OPEN) {
-                    // Fade out while bringing up selected activity. This keeps the
-                    // current activity from showing through a launching wallpaper
+                    // Fade out the source activity if we are animating to a wallpaper
                     // activity.
                     a = new AlphaAnimation(1, 0);
                 } else {
-                    // noop animation
                     a = new AlphaAnimation(1, 1);
                 }
                 break;
             }
             case THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN: {
-                // Entering the other app, it should just be visible while we scale the thumbnail
-                // down above it
-                a = new AlphaAnimation(1, 1);
+                // Target app window during the scale down
+                if (transit == TRANSIT_WALLPAPER_INTRA_OPEN) {
+                    // Fade in the destination activity if we are animating from a wallpaper
+                    // activity.
+                    a = new AlphaAnimation(0, 1);
+                } else {
+                    a = new AlphaAnimation(1, 1);
+                }
                 break;
             }
             case THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN: {
-                // Exiting the current app, the app should scale down with the thumbnail
+                // App window scaling down from full screen
                 if (orientation == Configuration.ORIENTATION_PORTRAIT) {
                     // In portrait, we scale the width and clip to the top/left square
                     scale = thumbWidth / appWidth;
@@ -612,16 +670,15 @@
                     }
                     mTmpToClipRect.right = (mTmpToClipRect.left + unscaledThumbWidth);
                 }
+                mNextAppTransitionInsets.set(contentInsets);
 
                 Animation scaleAnim = new ScaleAnimation(1, scale, 1, scale,
                         computePivot(mNextAppTransitionStartX, scale),
                         computePivot(mNextAppTransitionStartY, scale));
-                Animation alphaAnim = new AlphaAnimation(1, 1);
                 Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
                 Animation translateAnim = new TranslateAnimation(0, 0, 0, -scaledTopDecor);
 
                 AnimationSet set = new AnimationSet(true);
-                set.addAnimation(alphaAnim);
                 set.addAnimation(clipAnim);
                 set.addAnimation(scaleAnim);
                 set.addAnimation(translateAnim);
@@ -639,6 +696,46 @@
     }
 
     /**
+     * This animation runs for the thumbnail that gets cross faded with the enter/exit activity
+     * when a thumbnail is specified with the activity options.
+     */
+    Animation createThumbnailScaleAnimationLocked(int appWidth, int appHeight, int transit) {
+        Animation a;
+        final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
+        final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
+        final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
+        final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
+
+        if (mNextAppTransitionScaleUp) {
+            // Animation for the thumbnail zooming from its initial size to the full screen
+            float scaleW = appWidth / thumbWidth;
+            float scaleH = appHeight / thumbHeight;
+            Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
+                    computePivot(mNextAppTransitionStartX, 1 / scaleW),
+                    computePivot(mNextAppTransitionStartY, 1 / scaleH));
+            scale.setInterpolator(mDecelerateInterpolator);
+
+            Animation alpha = new AlphaAnimation(1, 0);
+            alpha.setInterpolator(mThumbnailFadeOutInterpolator);
+
+            // This AnimationSet uses the Interpolators assigned above.
+            AnimationSet set = new AnimationSet(false);
+            set.addAnimation(scale);
+            set.addAnimation(alpha);
+            a = set;
+        } else {
+            // Animation for the thumbnail zooming down from the full screen to its final size
+            float scaleW = appWidth / thumbWidth;
+            float scaleH = appHeight / thumbHeight;
+            a = new ScaleAnimation(scaleW, 1, scaleH, 1,
+                    computePivot(mNextAppTransitionStartX, 1 / scaleW),
+                    computePivot(mNextAppTransitionStartY, 1 / scaleH));
+        }
+
+        return prepareThumbnailAnimation(a, appWidth, appHeight, transit);
+    }
+
+    /**
      * This animation is created when we are doing a thumbnail transition, for the activity that is
      * leaving, and the activity that is entering.
      */
@@ -747,12 +844,26 @@
                 mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN) {
             mNextAppTransitionScaleUp =
                     (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP);
-            a = createAlternateThumbnailEnterExitAnimationLocked(
+            a = createThumbnailEnterExitAnimationLocked(getThumbnailTransitionState(enter),
+                    appWidth, appHeight, transit);
+            if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
+                String animName = mNextAppTransitionScaleUp ?
+                        "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN";
+                Slog.v(TAG, "applyAnimation:"
+                        + " anim=" + a + " nextAppTransition=" + animName
+                        + " transit=" + transit + " isEntrance=" + enter
+                        + " Callers=" + Debug.getCallers(3));
+            }
+        } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP ||
+                mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN) {
+            mNextAppTransitionScaleUp =
+                    (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP);
+            a = createAspectScaledThumbnailEnterExitAnimationLocked(
                     getThumbnailTransitionState(enter), appWidth, appHeight, orientation,
                     transit, containingFrame, contentInsets, isFullScreen);
             if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
                 String animName = mNextAppTransitionScaleUp ?
-                        "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN";
+                        "ANIM_THUMBNAIL_ASPECT_SCALE_UP" : "ANIM_THUMBNAIL_ASPECT_SCALE_DOWN";
                 Slog.v(TAG, "applyAnimation:"
                         + " anim=" + a + " nextAppTransition=" + animName
                         + " transit=" + transit + " isEntrance=" + enter
@@ -814,7 +925,7 @@
                 case TRANSIT_TASK_OPEN_BEHIND:
                     animAttr = enter
                             ? WindowAnimation_launchTaskBehindSourceAnimation
-                            : WindowAnimation_launchTaskBehindBackgroundAnimation;
+                            : WindowAnimation_launchTaskBehindTargetAnimation;
             }
             a = animAttr != 0 ? loadAnimationAttr(lp, animAttr) : null;
             if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
@@ -881,6 +992,23 @@
         }
     }
 
+    void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX, int startY,
+            IRemoteCallback startedCallback, boolean scaleUp) {
+        if (isTransitionSet()) {
+            mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP
+                    : NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
+            mNextAppTransitionPackage = null;
+            mNextAppTransitionThumbnail = srcThumb;
+            mNextAppTransitionScaleUp = scaleUp;
+            mNextAppTransitionStartX = startX;
+            mNextAppTransitionStartY = startY;
+            postAnimationCallback();
+            mNextAppTransitionCallback = startedCallback;
+        } else {
+            postAnimationCallback();
+        }
+    }
+
     @Override
     public String toString() {
         return "mNextAppTransition=0x" + Integer.toHexString(mNextAppTransition);
@@ -966,6 +1094,10 @@
                 return "NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP";
             case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN:
                 return "NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN";
+            case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP:
+                return "NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP";
+            case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN:
+                return "NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN";
             default:
                 return "unknown type=" + mNextAppTransitionType;
         }
@@ -998,6 +1130,8 @@
                 break;
             case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP:
             case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN:
+            case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP:
+            case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN:
                 pw.print("  mNextAppTransitionThumbnail=");
                         pw.print(mNextAppTransitionThumbnail);
                         pw.print(" mNextAppTransitionStartX=");
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index 5b05d53..ef74205 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -64,8 +64,17 @@
     int thumbnailX;
     int thumbnailY;
     int thumbnailLayer;
+    int thumbnailForceAboveLayer;
     Animation thumbnailAnimation;
     final Transformation thumbnailTransformation = new Transformation();
+    // This flag indicates that the destruction of the thumbnail surface is synchronized with
+    // another animation, so do not pre-emptively destroy the thumbnail surface when the animation
+    // completes
+    boolean deferThumbnailDestruction;
+    // This is the thumbnail surface that has been bestowed upon this animator, and when the
+    // surface for this animator's animation is complete, we will destroy the thumbnail surface
+    // as well.  Do not animate or do anything with this surface.
+    SurfaceControl deferredThumbnail;
 
     /** WindowStateAnimator from mAppAnimator.allAppWindows as of last performLayout */
     ArrayList<WindowStateAnimator> mAllAppWinAnimators = new ArrayList<WindowStateAnimator>();
@@ -121,7 +130,9 @@
             animation = null;
             animating = true;
         }
-        clearThumbnail();
+        if (!deferThumbnailDestruction) {
+            clearThumbnail();
+        }
         if (mAppToken.deferClearAllDrawn) {
             mAppToken.allDrawn = false;
             mAppToken.deferClearAllDrawn = false;
@@ -135,6 +146,13 @@
         }
     }
 
+    public void clearDeferredThumbnail() {
+        if (deferredThumbnail != null) {
+            deferredThumbnail.destroy();
+            deferredThumbnail = null;
+        }
+    }
+
     void updateLayers() {
         final int N = mAppToken.allAppWindows.size();
         final int adj = animLayerAdjustment;
@@ -184,10 +202,14 @@
                 + "][" + tmpFloats[Matrix.MSKEW_X]
                 + "," + tmpFloats[Matrix.MSCALE_Y] + "]", null);
         thumbnail.setAlpha(thumbnailTransformation.getAlpha());
-        // The thumbnail is layered below the window immediately above this
-        // token's anim layer.
-        thumbnail.setLayer(thumbnailLayer + WindowManagerService.WINDOW_LAYER_MULTIPLIER
-                - WindowManagerService.LAYER_OFFSET_THUMBNAIL);
+        if (thumbnailForceAboveLayer > 0) {
+            thumbnail.setLayer(thumbnailForceAboveLayer + 1);
+        } else {
+            // The thumbnail is layered below the window immediately above this
+            // token's anim layer.
+            thumbnail.setLayer(thumbnailLayer + WindowManagerService.WINDOW_LAYER_MULTIPLIER
+                    - WindowManagerService.LAYER_OFFSET_THUMBNAIL);
+        }
         thumbnail.setMatrix(tmpFloats[Matrix.MSCALE_X], tmpFloats[Matrix.MSKEW_Y],
                 tmpFloats[Matrix.MSKEW_X], tmpFloats[Matrix.MSCALE_Y]);
     }
@@ -202,7 +224,9 @@
             TAG, "Stepped animation in " + mAppToken + ": more=" + more + ", xform=" + transformation);
         if (!more) {
             animation = null;
-            clearThumbnail();
+            if (!deferThumbnailDestruction) {
+                clearThumbnail();
+            }
             if (WindowManagerService.DEBUG_ANIM) Slog.v(
                 TAG, "Finished animation in " + mAppToken + " @ " + currentTime);
         }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 32f3707..e144bde 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -95,7 +95,6 @@
 import android.provider.Settings;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
-import android.util.FloatMath;
 import android.util.Log;
 import android.util.SparseArray;
 import android.util.Pair;
@@ -4038,6 +4037,15 @@
     }
 
     @Override
+    public void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX,
+            int startY, IRemoteCallback startedCallback, boolean scaleUp) {
+        synchronized(mWindowMap) {
+            mAppTransition.overridePendingAppTransitionAspectScaledThumb(srcThumb, startX,
+                    startY, startedCallback, scaleUp);
+        }
+    }
+
+    @Override
     public void executeAppTransition() {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "executeAppTransition()")) {
@@ -8893,7 +8901,9 @@
             }
 
             AppWindowToken topOpeningApp = null;
+            AppWindowToken topClosingApp = null;
             int topOpeningLayer = 0;
+            int topClosingLayer = 0;
 
             NN = mOpeningApps.size();
             for (i=0; i<NN; i++) {
@@ -8901,8 +8911,8 @@
                 final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
                 appAnimator.clearThumbnail();
-                wtoken.inPendingTransaction = false;
                 appAnimator.animation = null;
+                wtoken.inPendingTransaction = false;
                 setTokenVisibilityLocked(wtoken, animLp, true, transit, false, voiceInteraction);
                 wtoken.updateReportedVisibilityLocked();
                 wtoken.waitingToShow = false;
@@ -8931,10 +8941,11 @@
             NN = mClosingApps.size();
             for (i=0; i<NN; i++) {
                 AppWindowToken wtoken = mClosingApps.valueAt(i);
+                final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
-                wtoken.mAppAnimator.clearThumbnail();
+                appAnimator.clearThumbnail();
+                appAnimator.animation = null;
                 wtoken.inPendingTransaction = false;
-                wtoken.mAppAnimator.animation = null;
                 setTokenVisibilityLocked(wtoken, animLp, false, transit, false, voiceInteraction);
                 wtoken.updateReportedVisibilityLocked();
                 wtoken.waitingToHide = false;
@@ -8943,14 +8954,30 @@
                 // gotten drawn.
                 wtoken.allDrawn = true;
                 wtoken.deferClearAllDrawn = false;
+
+                if (animLp != null) {
+                    int layer = -1;
+                    for (int j=0; j<wtoken.windows.size(); j++) {
+                        WindowState win = wtoken.windows.get(j);
+                        if (win.mWinAnimator.mAnimLayer > layer) {
+                            layer = win.mWinAnimator.mAnimLayer;
+                        }
+                    }
+                    if (topClosingApp == null || layer > topClosingLayer) {
+                        topClosingApp = wtoken;
+                        topClosingLayer = layer;
+                    }
+                }
             }
 
-            boolean useAlternateThumbnailAnimation = true;
-            AppWindowAnimator appAnimator =
-                    topOpeningApp == null ? null : topOpeningApp.mAppAnimator;
+            AppWindowAnimator openingAppAnimator = (topOpeningApp == null) ? null :
+                    topOpeningApp.mAppAnimator;
+            AppWindowAnimator closingAppAnimator = (topClosingApp == null) ? null :
+                    topClosingApp.mAppAnimator;
             Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail();
-            if (!useAlternateThumbnailAnimation && nextAppTransitionThumbnail != null
-                    && appAnimator != null && appAnimator.animation != null) {
+            if (nextAppTransitionThumbnail != null
+                    && openingAppAnimator != null && openingAppAnimator.animation != null &&
+                    nextAppTransitionThumbnail.getConfig() != Config.ALPHA_8) {
                 // This thumbnail animation is very special, we need to have
                 // an extra surface with the thumbnail included with the animation.
                 Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(),
@@ -8959,34 +8986,61 @@
                     // TODO(multi-display): support other displays
                     final DisplayContent displayContent = getDefaultDisplayContentLocked();
                     final Display display = displayContent.getDisplay();
+                    final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+
+                    // Create a new surface for the thumbnail
                     SurfaceControl surfaceControl = new SurfaceControl(mFxSession,
-                            "thumbnail anim",
-                            dirty.width(), dirty.height(),
+                            "thumbnail anim", dirty.width(), dirty.height(),
                             PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
                     surfaceControl.setLayerStack(display.getLayerStack());
-                    appAnimator.thumbnail = surfaceControl;
-                    if (SHOW_TRANSACTIONS) Slog.i(TAG, "  THUMBNAIL " + surfaceControl + ": CREATE");
+                    if (SHOW_TRANSACTIONS) {
+                        Slog.i(TAG, "  THUMBNAIL " + surfaceControl + ": CREATE");
+                    }
+
+                    // Draw the thumbnail onto the surface
                     Surface drawSurface = new Surface();
                     drawSurface.copyFrom(surfaceControl);
                     Canvas c = drawSurface.lockCanvas(dirty);
                     c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null);
                     drawSurface.unlockCanvasAndPost(c);
                     drawSurface.release();
-                    appAnimator.thumbnailLayer = topOpeningLayer;
-                    DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
-                    Animation anim = mAppTransition.createThumbnailScaleAnimationLocked(
-                            displayInfo.appWidth, displayInfo.appHeight, transit);
-                    appAnimator.thumbnailAnimation = anim;
+
+                    // Get the thumbnail animation
+                    Animation anim;
+                    if (mAppTransition.isNextThumbnailTransitionAspectScaled()) {
+                        // For the new aspect-scaled transition, we want it to always show
+                        // above the animating opening/closing window, and we want to
+                        // synchronize its thumbnail surface with the surface for the
+                        // open/close animation (only on the way down)
+                        anim = mAppTransition.createThumbnailAspectScaleAnimationLocked(
+                                displayInfo.appWidth, displayInfo.appHeight,
+                                displayInfo.logicalWidth, transit);
+                        openingAppAnimator.thumbnailForceAboveLayer = Math.max(topOpeningLayer,
+                                topClosingLayer);
+                        openingAppAnimator.deferThumbnailDestruction =
+                                !mAppTransition.isNextThumbnailTransitionScaleUp();
+                        if (openingAppAnimator.deferThumbnailDestruction) {
+                            if (closingAppAnimator != null &&
+                                    closingAppAnimator.animation != null) {
+                                closingAppAnimator.deferredThumbnail = surfaceControl;
+                            }
+                        }
+                    } else {
+                        anim = mAppTransition.createThumbnailScaleAnimationLocked(
+                                displayInfo.appWidth, displayInfo.appHeight, transit);
+                    }
                     anim.restrictDuration(MAX_ANIMATION_DURATION);
                     anim.scaleCurrentDuration(getTransitionAnimationScaleLocked());
-                    Point p = new Point();
-                    mAppTransition.getStartingPoint(p);
-                    appAnimator.thumbnailX = p.x;
-                    appAnimator.thumbnailY = p.y;
+
+                    openingAppAnimator.thumbnail = surfaceControl;
+                    openingAppAnimator.thumbnailLayer = topOpeningLayer;
+                    openingAppAnimator.thumbnailAnimation = anim;
+                    openingAppAnimator.thumbnailX = mAppTransition.getStartingX();
+                    openingAppAnimator.thumbnailY = mAppTransition.getStartingY();
                 } catch (OutOfResourcesException e) {
                     Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width()
                             + " h=" + dirty.height(), e);
-                    appAnimator.clearThumbnail();
+                    openingAppAnimator.clearThumbnail();
                 }
             }
 
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 7bf090a..38433ae 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -902,6 +902,11 @@
             mWin.mHasSurface = false;
             mDrawState = NO_SURFACE;
         }
+
+        // Destroy any deferred thumbnail surfaces
+        if (mAppAnimator != null) {
+            mAppAnimator.clearDeferredThumbnail();
+        }
     }
 
     void destroyDeferredSurfaceLocked() {
diff --git a/telecomm/java/android/telecomm/Conference.java b/telecomm/java/android/telecomm/Conference.java
index 44accb7..879ff66 100644
--- a/telecomm/java/android/telecomm/Conference.java
+++ b/telecomm/java/android/telecomm/Conference.java
@@ -18,9 +18,7 @@
 
 import android.telephony.DisconnectCause;
 
-import java.util.ArrayList;
 import java.util.Collections;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
@@ -43,7 +41,7 @@
 
     private final Set<Listener> mListeners = new CopyOnWriteArraySet<>();
     private final List<Connection> mChildConnections = new CopyOnWriteArrayList<>();
-    private final List<Connection> mUnmodifiableChildConnection =
+    private final List<Connection> mUnmodifiableChildConnections =
             Collections.unmodifiableList(mChildConnections);
 
     private PhoneAccountHandle mPhoneAccount;
@@ -61,7 +59,7 @@
     }
 
     public final List<Connection> getConnections() {
-        return mUnmodifiableChildConnection;
+        return mUnmodifiableChildConnections;
     }
 
     public final int getState() {
@@ -125,7 +123,7 @@
     }
 
     /**
-     * Sets the cabilities of a conference.
+     * Sets the capabilities of a conference.
      */
     public final void setCapabilities(int capabilities) {
         if (capabilities != mCapabilities) {
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
index b77bb18..4696815 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -39,7 +39,6 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.UUID;
 
 /**
@@ -79,7 +78,8 @@
     private final Map<Connection, String> mIdByConnection = new HashMap<>();
     private final Map<String, Conference> mConferenceById = new HashMap<>();
     private final Map<Conference, String> mIdByConference = new HashMap<>();
-    private final RemoteConnectionManager mRemoteConnectionManager = new RemoteConnectionManager();
+    private final RemoteConnectionManager mRemoteConnectionManager =
+            new RemoteConnectionManager(this);
     private final List<Runnable> mPreInitializationConnectionRequests = new ArrayList<>();
     private final ConnectionServiceAdapter mAdapter = new ConnectionServiceAdapter();
 
@@ -461,15 +461,9 @@
         @Override
         public void onConferenceableConnectionsChanged(
                 Connection connection, List<Connection> conferenceableConnections) {
-            String id = mIdByConnection.get(connection);
-            List<String> conferenceableCallIds = new ArrayList<>(conferenceableConnections.size());
-            for (Connection c : conferenceableConnections) {
-                if (mIdByConnection.containsKey(c)) {
-                    conferenceableCallIds.add(mIdByConnection.get(c));
-                }
-            }
-            Collections.sort(conferenceableCallIds);
-            mAdapter.setConferenceableConnections(id, conferenceableCallIds);
+            mAdapter.setConferenceableConnections(
+                    mIdByConnection.get(connection),
+                    createConnectionIdList(conferenceableConnections));
         }
 
         @Override
@@ -542,7 +536,8 @@
                         connection.getAudioModeIsVoip(),
                         connection.getStatusHints(),
                         connection.getDisconnectCause(),
-                        connection.getDisconnectMessage()));
+                        connection.getDisconnectMessage(),
+                        createConnectionIdList(connection.getConferenceableConnections())));
     }
 
     private void abort(String callId) {
@@ -717,6 +712,15 @@
     }
 
     /**
+     * Adds two {@code RemoteConnection}s to some {@code RemoteConference}.
+     */
+    public final void conferenceRemoteConnections(
+            RemoteConnection a,
+            RemoteConnection b) {
+        mRemoteConnectionManager.conferenceRemoteConnections(a, b);
+    }
+
+    /**
      * Adds a new conference call. When a conference call is created either as a result of an
      * explicit request via {@link #onConference} or otherwise, the connection service should supply
      * an instance of {@link Conference} by invoking this method. A conference call provided by this
@@ -824,11 +828,17 @@
 
     /**
      * Notified that a connection has been removed from this connection service.
+     * <p>
+     * TODO: Deprecate this since we can listen to the Connection onDestroyed() to determine when
+     * it is destroyed. This then percolates down to the RemoteConference stuff, where we can also
+     * have a callback for one being added, but we don't need one for being destroyed.
      *
      * @param connection The connection which was removed.
      */
     public void onConnectionRemoved(Connection connection) {}
 
+    public void onRemoteConferenceAdded(RemoteConference conference) {}
+
     /**
      * @hide
      */
@@ -836,6 +846,11 @@
         return mIdByConference.containsKey(conference);
     }
 
+    /** {@hide} */
+    void addRemoteConference(RemoteConference remoteConference) {
+        onRemoteConferenceAdded(remoteConference);
+    }
+
     private void onAccountsInitialized() {
         mAreAccountsInitialized = true;
         for (Runnable r : mPreInitializationConnectionRequests) {
@@ -910,6 +925,17 @@
         return getNullConference();
     }
 
+    private List<String> createConnectionIdList(List<Connection> connections) {
+        List<String> ids = new ArrayList<>();
+        for (Connection c : connections) {
+            if (mIdByConnection.containsKey(c)) {
+                ids.add(mIdByConnection.get(c));
+            }
+        }
+        Collections.sort(ids);
+        return ids;
+    }
+
     private Conference getNullConference() {
         if (sNullConference == null) {
             sNullConference = new Conference(null) {};
diff --git a/telecomm/java/android/telecomm/ParcelableConnection.java b/telecomm/java/android/telecomm/ParcelableConnection.java
index 812ee55..2e21d37 100644
--- a/telecomm/java/android/telecomm/ParcelableConnection.java
+++ b/telecomm/java/android/telecomm/ParcelableConnection.java
@@ -22,6 +22,9 @@
 
 import com.android.internal.telecomm.IVideoProvider;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Information about a connection that is used between Telecomm and the ConnectionService.
  * This is used to send initial Connection information to Telecomm when the connection is
@@ -29,20 +32,21 @@
  * @hide
  */
 public final class ParcelableConnection implements Parcelable {
-    private PhoneAccountHandle mPhoneAccount;
-    private int mState;
-    private int mCapabilities;
-    private Uri mHandle;
-    private int mHandlePresentation;
-    private String mCallerDisplayName;
-    private int mCallerDisplayNamePresentation;
-    private IVideoProvider mVideoProvider;
-    private int mVideoState;
-    private boolean mRequestingRingback;
-    private boolean mAudioModeIsVoip;
-    private StatusHints mStatusHints;
-    private int mDisconnectCause;
-    private String mDisconnectMessage;
+    private final PhoneAccountHandle mPhoneAccount;
+    private final int mState;
+    private final int mCapabilities;
+    private final Uri mHandle;
+    private final int mHandlePresentation;
+    private final String mCallerDisplayName;
+    private final int mCallerDisplayNamePresentation;
+    private final IVideoProvider mVideoProvider;
+    private final int mVideoState;
+    private final boolean mRequestingRingback;
+    private final boolean mAudioModeIsVoip;
+    private final StatusHints mStatusHints;
+    private final int mDisconnectCause;
+    private final String mDisconnectMessage;
+    private final List<String> mConferenceableConnectionIds;
 
     /** @hide */
     public ParcelableConnection(
@@ -59,7 +63,8 @@
             boolean audioModeIsVoip,
             StatusHints statusHints,
             int disconnectCause,
-            String disconnectMessage) {
+            String disconnectMessage,
+            List<String> conferenceableConnectionIds) {
         mPhoneAccount = phoneAccount;
         mState = state;
         mCapabilities = capabilities;
@@ -74,6 +79,7 @@
         mStatusHints = statusHints;
         mDisconnectCause = disconnectCause;
         mDisconnectMessage = disconnectMessage;
+        this.mConferenceableConnectionIds = conferenceableConnectionIds;
     }
 
     public PhoneAccountHandle getPhoneAccount() {
@@ -133,6 +139,10 @@
         return mDisconnectMessage;
     }
 
+    public final List<String> getConferenceableConnectionIds() {
+        return mConferenceableConnectionIds;
+    }
+
     @Override
     public String toString() {
         return new StringBuilder()
@@ -166,6 +176,8 @@
             StatusHints statusHints = source.readParcelable(classLoader);
             int disconnectCauseCode = source.readInt();
             String disconnectCauseMessage = source.readString();
+            List<String> conferenceableConnectionIds = new ArrayList<>();
+            source.readStringList(conferenceableConnectionIds);
 
             return new ParcelableConnection(
                     phoneAccount,
@@ -181,7 +193,8 @@
                     audioModeIsVoip,
                     statusHints,
                     disconnectCauseCode,
-                    disconnectCauseMessage);
+                    disconnectCauseMessage,
+                    conferenceableConnectionIds);
         }
 
         @Override
@@ -214,5 +227,6 @@
         destination.writeParcelable(mStatusHints, 0);
         destination.writeInt(mDisconnectCause);
         destination.writeString(mDisconnectMessage);
+        destination.writeStringList(mConferenceableConnectionIds);
     }
 }
diff --git a/telecomm/java/android/telecomm/RemoteConference.java b/telecomm/java/android/telecomm/RemoteConference.java
new file mode 100644
index 0000000..02f6de6
--- /dev/null
+++ b/telecomm/java/android/telecomm/RemoteConference.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2014 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 android.telecomm;
+
+import com.android.internal.telecomm.IConnectionService;
+
+import android.os.RemoteException;
+import android.telephony.DisconnectCause;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+/**
+ * Represents a conference call which can contain any number of {@link Connection} objects.
+ */
+public final class RemoteConference {
+
+    public abstract static class Listener {
+        public void onStateChanged(RemoteConference conference, int oldState, int newState) {}
+        public void onDisconnected(RemoteConference conference, int cause, String message) {}
+        public void onConnectionAdded(RemoteConference conference, RemoteConnection connection) {}
+        public void onConnectionRemoved(RemoteConference conference, RemoteConnection connection) {}
+        public void onCapabilitiesChanged(RemoteConference conference, int capabilities) {}
+        public void onDestroyed(RemoteConference conference) {}
+    }
+
+    private final String mId;
+    private final IConnectionService mConnectionService;
+
+    private final Set<Listener> mListeners = new CopyOnWriteArraySet<>();
+    private final List<RemoteConnection> mChildConnections = new CopyOnWriteArrayList<>();
+    private final List<RemoteConnection> mUnmodifiableChildConnections =
+            Collections.unmodifiableList(mChildConnections);
+
+    private int mState = Connection.STATE_NEW;
+    private int mDisconnectCause = DisconnectCause.NOT_VALID;
+    private int mCallCapabilities;
+    private String mDisconnectMessage;
+
+    /** {@hide} */
+    RemoteConference(String id, IConnectionService connectionService) {
+        mId = id;
+        mConnectionService = connectionService;
+    }
+
+    /** {@hide} */
+    String getId() {
+        return mId;
+    }
+
+    /** {@hide} */
+    void setDestroyed() {
+        for (RemoteConnection connection : mChildConnections) {
+            connection.setConference(null);
+        }
+        for (Listener l : mListeners) {
+            l.onDestroyed(this);
+        }
+    }
+
+    /** {@hide} */
+    void setState(int newState) {
+        if (newState != Connection.STATE_ACTIVE &&
+                newState != Connection.STATE_HOLDING &&
+                newState != Connection.STATE_DISCONNECTED) {
+            Log.w(this, "Unsupported state transition for Conference call.",
+                    Connection.stateToString(newState));
+            return;
+        }
+
+        if (mState != newState) {
+            int oldState = mState;
+            mState = newState;
+            for (Listener l : mListeners) {
+                l.onStateChanged(this, oldState, newState);
+            }
+        }
+    }
+
+    /** {@hide} */
+    void addConnection(RemoteConnection connection) {
+        if (!mChildConnections.contains(connection)) {
+            mChildConnections.add(connection);
+            connection.setConference(this);
+            for (Listener l : mListeners) {
+                l.onConnectionAdded(this, connection);
+            }
+        }
+    }
+
+    /** {@hide} */
+    void removeConnection(RemoteConnection connection) {
+        if (mChildConnections.contains(connection)) {
+            mChildConnections.remove(connection);
+            connection.setConference(null);
+            for (Listener l : mListeners) {
+                l.onConnectionRemoved(this, connection);
+            }
+        }
+    }
+
+    /** {@hide} */
+    void setCallCapabilities(int capabilities) {
+        if (mCallCapabilities != capabilities) {
+            mCallCapabilities = capabilities;
+            for (Listener l : mListeners) {
+                l.onCapabilitiesChanged(this, mCallCapabilities);
+            }
+        }
+    }
+
+    /** {@hide} */
+    void setDisconnected(int cause, String message) {
+        if (mState != Connection.STATE_DISCONNECTED) {
+            mDisconnectCause = cause;
+            mDisconnectMessage = message;
+            setState(Connection.STATE_DISCONNECTED);
+            for (Listener l : mListeners) {
+                l.onDisconnected(this, cause, message);
+            }
+        }
+    }
+
+    public final List<RemoteConnection> getConnections() {
+        return mUnmodifiableChildConnections;
+    }
+
+    public final int getState() {
+        return mState;
+    }
+
+    public final int getCallCapabilities() {
+        return mCallCapabilities;
+    }
+
+    public void disconnect() {
+        try {
+            mConnectionService.disconnect(mId);
+        } catch (RemoteException e) {
+        }
+    }
+
+    public void separate(RemoteConnection connection) {
+        if (mChildConnections.contains(connection)) {
+            try {
+                mConnectionService.splitFromConference(connection.getId());
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    public void hold() {
+        try {
+            mConnectionService.hold(mId);
+        } catch (RemoteException e) {
+        }
+    }
+
+    public void unhold() {
+        try {
+            mConnectionService.unhold(mId);
+        } catch (RemoteException e) {
+        }
+    }
+
+    public int getDisconnectCause() {
+        return mDisconnectCause;
+    }
+
+    public String getDisconnectMessage() {
+        return mDisconnectMessage;
+    }
+
+    public final void addListener(Listener listener) {
+        mListeners.add(listener);
+    }
+
+    public final void removeListener(Listener listener) {
+        mListeners.remove(listener);
+    }
+}
diff --git a/telecomm/java/android/telecomm/RemoteConnection.java b/telecomm/java/android/telecomm/RemoteConnection.java
index 70db6f5..20d1574 100644
--- a/telecomm/java/android/telecomm/RemoteConnection.java
+++ b/telecomm/java/android/telecomm/RemoteConnection.java
@@ -179,8 +179,30 @@
          * @param connection The {@code RemoteConnection} invoking this method.
          */
         public void onDestroyed(RemoteConnection connection) {}
+
+        /**
+         * Indicates that the {@code RemoteConnection}s with which this {@code RemoteConnection}
+         * may be asked to create a conference has changed.
+         *
+         * @param connection The {@code RemoteConnection} invoking this method.
+         * @param conferenceableConnections The {@code RemoteConnection}s with which this
+         *         {@code RemoteConnection} may be asked to create a conference.
+         */
         public void onConferenceableConnectionsChanged(
-                RemoteConnection connection, List<RemoteConnection> conferenceableConnections) {}
+                RemoteConnection connection,
+                List<RemoteConnection> conferenceableConnections) {}
+
+        /**
+         * Indicates that the {@code RemoteConference} that this {@code RemoteConnection} is a part
+         * of has changed.
+         *
+         * @param connection The {@code RemoteConnection} invoking this method.
+         * @param conference The {@code RemoteConference} of which this {@code RemoteConnection} is
+         *         a part, which may be {@code null}.
+         */
+        public void onConferenceChanged(
+                RemoteConnection connection,
+                RemoteConference conference) {}
     }
 
     private IConnectionService mConnectionService;
@@ -192,7 +214,9 @@
      */
     private final Set<Listener> mListeners = Collections.newSetFromMap(
             new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1));
-    private final Set<RemoteConnection> mConferenceableConnections = new HashSet<>();
+    private final List<RemoteConnection> mConferenceableConnections = new ArrayList<>();
+    private final List<RemoteConnection> mUnmodifiableconferenceableConnections =
+            Collections.unmodifiableList(mConferenceableConnections);
 
     private int mState = Connection.STATE_NEW;
     private int mDisconnectCauseCode = DisconnectCause.NOT_VALID;
@@ -209,6 +233,7 @@
     private int mCallerDisplayNamePresentation;
     private int mFailureCode;
     private String mFailureMessage;
+    private RemoteConference mConference;
 
     /**
      * @hide
@@ -539,6 +564,37 @@
     }
 
     /**
+     * Obtain the {@code RemoteConnection}s with which this {@code RemoteConnection} may be
+     * successfully asked to create a conference with.
+     *
+     * @return The {@code RemoteConnection}s with which this {@code RemoteConnection} may be
+     *         merged into a {@link RemoteConference}.
+     */
+    public List<RemoteConnection> getConferenceableConnections() {
+        return mUnmodifiableconferenceableConnections;
+    }
+
+    /**
+     * Obtain the {@code RemoteConference} that this {@code RemoteConnection} may be a part
+     * of, or {@code null} if there is no such {@code RemoteConference}.
+     *
+     * @return A {@code RemoteConference} or {@code null};
+     */
+    public RemoteConference getConference() {
+        return mConference;
+    }
+
+    /** {@hide} */
+    String getId() {
+        return mConnectionId;
+    }
+
+    /** {@hide} */
+    IConnectionService getConnectionService() {
+        return mConnectionService;
+    }
+
+    /**
      * @hide
      */
     void setState(int state) {
@@ -671,8 +727,17 @@
         mConferenceableConnections.clear();
         mConferenceableConnections.addAll(conferenceableConnections);
         for (Listener l : mListeners) {
-            l.onConferenceableConnectionsChanged(
-                    this, new ArrayList<RemoteConnection>(mConferenceableConnections));
+            l.onConferenceableConnectionsChanged(this, mUnmodifiableconferenceableConnections);
+        }
+    }
+
+    /** @hide */
+    void setConference(RemoteConference conference) {
+        if (mConference != conference) {
+            mConference = conference;
+            for (Listener l : mListeners) {
+                l.onConferenceChanged(this, conference);
+            }
         }
     }
 
diff --git a/telecomm/java/android/telecomm/RemoteConnectionManager.java b/telecomm/java/android/telecomm/RemoteConnectionManager.java
index 365ed5b..83502c5 100644
--- a/telecomm/java/android/telecomm/RemoteConnectionManager.java
+++ b/telecomm/java/android/telecomm/RemoteConnectionManager.java
@@ -28,13 +28,22 @@
  * @hide
  */
 public class RemoteConnectionManager {
-    private Map<ComponentName, RemoteConnectionService> mRemoteConnectionServices = new HashMap<>();
+    private final Map<ComponentName, RemoteConnectionService> mRemoteConnectionServices =
+            new HashMap<>();
+    private final ConnectionService mOurConnectionServiceImpl;
 
-    void addConnectionService(ComponentName componentName, IConnectionService connectionService) {
+    public RemoteConnectionManager(ConnectionService ourConnectionServiceImpl) {
+        mOurConnectionServiceImpl = ourConnectionServiceImpl;
+    }
+
+    void addConnectionService(
+            ComponentName componentName,
+            IConnectionService outgoingConnectionServiceRpc) {
         if (!mRemoteConnectionServices.containsKey(componentName)) {
             try {
-                RemoteConnectionService remoteConnectionService =
-                        new RemoteConnectionService(connectionService);
+                RemoteConnectionService remoteConnectionService = new RemoteConnectionService(
+                        outgoingConnectionServiceRpc,
+                        mOurConnectionServiceImpl);
                 mRemoteConnectionServices.put(componentName, remoteConnectionService);
             } catch (RemoteException ignored) {
             }
@@ -63,4 +72,17 @@
         }
         return null;
     }
+
+    public void conferenceRemoteConnections(RemoteConnection a, RemoteConnection b) {
+        if (a.getConnectionService() == b.getConnectionService()) {
+            try {
+                a.getConnectionService().conference(a.getId(), b.getId());
+            } catch (RemoteException e) {
+            }
+        } else {
+            Log.w(this, "Request to conference incompatible remote connections (%s,%s) (%s,%s)",
+                    a.getConnectionService(), a.getId(),
+                    b.getConnectionService(), b.getId());
+        }
+    }
 }
diff --git a/telecomm/java/android/telecomm/RemoteConnectionService.java b/telecomm/java/android/telecomm/RemoteConnectionService.java
index 541df4e..51722fe 100644
--- a/telecomm/java/android/telecomm/RemoteConnectionService.java
+++ b/telecomm/java/android/telecomm/RemoteConnectionService.java
@@ -28,11 +28,11 @@
 import com.android.internal.telecomm.IVideoProvider;
 import com.android.internal.telecomm.RemoteServiceCallback;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
-import java.util.Collections;
 import java.util.List;
 import java.util.UUID;
 
@@ -43,8 +43,11 @@
  */
 final class RemoteConnectionService {
 
-    private static final RemoteConnection
-            NULL_CONNECTION = new RemoteConnection("NULL", null, null);
+    private static final RemoteConnection NULL_CONNECTION =
+            new RemoteConnection("NULL", null, null);
+
+    private static final RemoteConference NULL_CONFERENCE =
+            new RemoteConference("NULL", null);
 
     private final IConnectionServiceAdapter mServantDelegate = new IConnectionServiceAdapter() {
         @Override
@@ -64,6 +67,13 @@
                 connection.setCallerDisplayName(
                         parcel.getCallerDisplayName(),
                         parcel.getCallerDisplayNamePresentation());
+                List<RemoteConnection> conferenceable = new ArrayList<>();
+                for (String confId : parcel.getConferenceableConnectionIds()) {
+                    if (mConnectionById.containsKey(confId)) {
+                        conferenceable.add(mConnectionById.get(confId));
+                    }
+                }
+                connection.setConferenceableConnections(conferenceable);
                 // TODO: Do we need to support video providers for remote connections?
                 if (connection.getState() == Connection.STATE_DISCONNECTED) {
                     // ... then, if it was created in a disconnected state, that indicates
@@ -75,8 +85,13 @@
 
         @Override
         public void setActive(String callId) {
-            findConnectionForAction(callId, "setActive")
-                    .setState(Connection.STATE_ACTIVE);
+            if (mConnectionById.containsKey(callId)) {
+                findConnectionForAction(callId, "setActive")
+                        .setState(Connection.STATE_ACTIVE);
+            } else {
+                findConferenceForAction(callId, "setActive")
+                        .setState(Connection.STATE_ACTIVE);
+            }
         }
 
         @Override
@@ -94,14 +109,24 @@
         @Override
         public void setDisconnected(String callId, int disconnectCause,
                 String disconnectMessage) {
-            findConnectionForAction(callId, "setDisconnected")
-                    .setDisconnected(disconnectCause, disconnectMessage);
+            if (mConnectionById.containsKey(callId)) {
+                findConnectionForAction(callId, "setDisconnected")
+                        .setDisconnected(disconnectCause, disconnectMessage);
+            } else {
+                findConferenceForAction(callId, "setDisconnected")
+                        .setDisconnected(disconnectCause, disconnectMessage);
+            }
         }
 
         @Override
         public void setOnHold(String callId) {
-            findConnectionForAction(callId, "setOnHold")
-                    .setState(Connection.STATE_HOLDING);
+            if (mConnectionById.containsKey(callId)) {
+                findConnectionForAction(callId, "setOnHold")
+                        .setState(Connection.STATE_HOLDING);
+            } else {
+                findConferenceForAction(callId, "setOnHold")
+                        .setState(Connection.STATE_HOLDING);
+            }
         }
 
         @Override
@@ -112,24 +137,80 @@
 
         @Override
         public void setCallCapabilities(String callId, int callCapabilities) {
-            findConnectionForAction("callId", "setCallCapabilities")
-                    .setCallCapabilities(callCapabilities);
+            if (mConnectionById.containsKey(callId)) {
+                findConnectionForAction(callId, "setCallCapabilities")
+                        .setCallCapabilities(callCapabilities);
+            } else {
+                findConferenceForAction(callId, "setCallCapabilities")
+                        .setCallCapabilities(callCapabilities);
+            }
         }
 
         @Override
         public void setIsConferenced(String callId, String conferenceCallId) {
-            // not supported for remote connections.
+            // Note: callId should not be null; conferenceCallId may be null
+            RemoteConnection connection =
+                    findConnectionForAction(callId, "setIsConferenced");
+            if (connection != NULL_CONNECTION) {
+                if (conferenceCallId == null) {
+                    // 'connection' is being split from its conference
+                    if (connection.getConference() != null) {
+                        connection.getConference().removeConnection(connection);
+                    }
+                } else {
+                    RemoteConference conference =
+                            findConferenceForAction(conferenceCallId, "setIsConferenced");
+                    if (conference != NULL_CONFERENCE) {
+                        conference.addConnection(connection);
+                    }
+                }
+            }
         }
 
         @Override
-        public void addConferenceCall(String callId, ParcelableConference parcelableConference) {
-            // not supported for remote connections.
+        public void addConferenceCall(
+                final String callId,
+                ParcelableConference parcel) {
+            RemoteConference conference = new RemoteConference(callId,
+                    mOutgoingConnectionServiceRpc);
+
+            for (String id : parcel.getConnectionIds()) {
+                RemoteConnection c = mConnectionById.get(id);
+                if (c != null) {
+                    conference.addConnection(c);
+                }
+            }
+
+            if (conference.getConnections().size() == 0) {
+                // A conference was created, but none of its connections are ones that have been
+                // created by, and therefore being tracked by, this remote connection service. It
+                // is of no interest to us.
+                return;
+            }
+
+            conference.setState(parcel.getState());
+            conference.setCallCapabilities(parcel.getCapabilities());
+            mConferenceById.put(callId, conference);
+            conference.addListener(new RemoteConference.Listener() {
+                @Override
+                public void onDestroyed(RemoteConference c) {
+                    mConferenceById.remove(callId);
+                    maybeDisconnectAdapter();
+                }
+            });
+
+            mOurConnectionServiceImpl.addRemoteConference(conference);
         }
 
         @Override
         public void removeCall(String callId) {
-            findConnectionForAction(callId, "removeCall")
-                    .setDestroyed();
+            if (mConnectionById.containsKey(callId)) {
+                findConnectionForAction(callId, "removeCall")
+                        .setDestroyed();
+            } else {
+                findConferenceForAction(callId, "removeCall")
+                        .setDestroyed();
+            }
         }
 
         @Override
@@ -193,13 +274,15 @@
         @Override
         public final void setConferenceableConnections(
                 String callId, List<String> conferenceableConnectionIds) {
+            List<RemoteConnection> conferenceable = new ArrayList<>();
+            for (String id : conferenceableConnectionIds) {
+                if (mConnectionById.containsKey(id)) {
+                    conferenceable.add(mConnectionById.get(id));
+                }
+            }
 
-            // TODO: When we support more than 1 remote connection, this should
-            // loop through the incoming list of connection IDs and acquire the list
-            // of remote connections which correspond to the IDs. That list should
-            // be set onto the remote connections.
             findConnectionForAction(callId, "setConferenceableConnections")
-                    .setConferenceableConnections(Collections.<RemoteConnection>emptyList());
+                    .setConferenceableConnections(conferenceable);
         }
     };
 
@@ -212,24 +295,33 @@
             for (RemoteConnection c : mConnectionById.values()) {
                 c.setDestroyed();
             }
+            for (RemoteConference c : mConferenceById.values()) {
+                c.setDestroyed();
+            }
             mConnectionById.clear();
+            mConferenceById.clear();
             mPendingConnections.clear();
-            mConnectionService.asBinder().unlinkToDeath(mDeathRecipient, 0);
+            mOutgoingConnectionServiceRpc.asBinder().unlinkToDeath(mDeathRecipient, 0);
         }
     };
 
-    private final IConnectionService mConnectionService;
+    private final IConnectionService mOutgoingConnectionServiceRpc;
+    private final ConnectionService mOurConnectionServiceImpl;
     private final Map<String, RemoteConnection> mConnectionById = new HashMap<>();
+    private final Map<String, RemoteConference> mConferenceById = new HashMap<>();
     private final Set<RemoteConnection> mPendingConnections = new HashSet<>();
 
-    RemoteConnectionService(IConnectionService connectionService) throws RemoteException {
-        mConnectionService = connectionService;
-        mConnectionService.asBinder().linkToDeath(mDeathRecipient, 0);
+    RemoteConnectionService(
+            IConnectionService outgoingConnectionServiceRpc,
+            ConnectionService ourConnectionServiceImpl) throws RemoteException {
+        mOutgoingConnectionServiceRpc = outgoingConnectionServiceRpc;
+        mOutgoingConnectionServiceRpc.asBinder().linkToDeath(mDeathRecipient, 0);
+        mOurConnectionServiceImpl = ourConnectionServiceImpl;
     }
 
     @Override
     public String toString() {
-        return "[RemoteCS - " + mConnectionService.asBinder().toString() + "]";
+        return "[RemoteCS - " + mOutgoingConnectionServiceRpc.asBinder().toString() + "]";
     }
 
     final RemoteConnection createRemoteConnection(
@@ -245,13 +337,13 @@
                 request.getVideoState());
         try {
             if (mConnectionById.isEmpty()) {
-                mConnectionService.addConnectionServiceAdapter(mServant.getStub());
+                mOutgoingConnectionServiceRpc.addConnectionServiceAdapter(mServant.getStub());
             }
             RemoteConnection connection =
-                    new RemoteConnection(id, mConnectionService, newRequest);
+                    new RemoteConnection(id, mOutgoingConnectionServiceRpc, newRequest);
             mPendingConnections.add(connection);
             mConnectionById.put(id, connection);
-            mConnectionService.createConnection(
+            mOutgoingConnectionServiceRpc.createConnection(
                     connectionManagerPhoneAccount,
                     id,
                     newRequest,
@@ -260,12 +352,7 @@
                 @Override
                 public void onDestroyed(RemoteConnection connection) {
                     mConnectionById.remove(id);
-                    if (mConnectionById.isEmpty()) {
-                        try {
-                            mConnectionService.removeConnectionServiceAdapter(mServant.getStub());
-                        } catch (RemoteException e) {
-                        }
-                    }
+                    maybeDisconnectAdapter();
                 }
             });
             return connection;
@@ -283,4 +370,22 @@
         Log.w(this, "%s - Cannot find Connection %s", action, callId);
         return NULL_CONNECTION;
     }
+
+    private RemoteConference findConferenceForAction(
+            String callId, String action) {
+        if (mConferenceById.containsKey(callId)) {
+            return mConferenceById.get(callId);
+        }
+        Log.w(this, "%s - Cannot find Conference %s", action, callId);
+        return NULL_CONFERENCE;
+    }
+
+    private void maybeDisconnectAdapter() {
+        if (mConnectionById.isEmpty() && mConferenceById.isEmpty()) {
+            try {
+                mOutgoingConnectionServiceRpc.removeConnectionServiceAdapter(mServant.getStub());
+            } catch (RemoteException e) {
+            }
+        }
+    }
 }
diff --git a/telecomm/java/android/telecomm/TelecommManager.java b/telecomm/java/android/telecomm/TelecommManager.java
index e59fea1..178a25f 100644
--- a/telecomm/java/android/telecomm/TelecommManager.java
+++ b/telecomm/java/android/telecomm/TelecommManager.java
@@ -17,7 +17,6 @@
 import android.annotation.SystemApi;
 import android.content.ComponentName;
 import android.content.Context;
-
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -394,14 +393,15 @@
     /**
      * Returns whether there is an ongoing phone call (can be in dialing, ringing, active or holding
      * states).
-     *
-     * @hide
+     * <p>
+     * Requires permission: {@link android.Manifest.permission#READ_PHONE_STATE}
+     * </p>
      */
     @SystemApi
-    public boolean isInAPhoneCall() {
+    public boolean isInCall() {
         try {
             if (isServiceConnected()) {
-                return getTelecommService().isInAPhoneCall();
+                return getTelecommService().isInCall();
             }
         } catch (RemoteException e) {
             Log.e(TAG, "RemoteException attempting to get default phone app.", e);
@@ -541,6 +541,67 @@
         }
     }
 
+    /**
+     * Processes the specified dial string as an MMI code.
+     * MMI codes are any sequence of characters entered into the dialpad that contain a "*" or "#".
+     * Some of these sequences launch special behavior through handled by Telephony.
+     * <p>
+     * Requires that the method-caller be set as the system dialer app.
+     * </p>
+     *
+     * @param dialString The digits to dial.
+     * @return True if the digits were processed as an MMI code, false otherwise.
+     */
+    public boolean handleMmi(String dialString) {
+        ITelecommService service = getTelecommService();
+        if (service != null) {
+            try {
+                return service.handlePinMmi(dialString);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling ITelecommService#handlePinMmi", e);
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Removes the missed-call notification if one is present.
+     * <p>
+     * Requires that the method-caller be set as the system dialer app.
+     * </p>
+     */
+    public void cancelMissedCallsNotification() {
+        ITelecommService service = getTelecommService();
+        if (service != null) {
+            try {
+                service.cancelMissedCallsNotification();
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling ITelecommService#cancelMissedCallsNotification", e);
+            }
+        }
+    }
+
+    /**
+     * Brings the in-call screen to the foreground if there is an ongoing call. If there is
+     * currently no ongoing call, then this method does nothing.
+     * <p>
+     * Requires that the method-caller be set as the system dialer app or have the
+     * {@link android.Manifest.permission#READ_PHONE_STATE} permission.
+     * </p>
+     *
+     * @param showDialpad Brings up the in-call dialpad as part of showing the in-call screen.
+     */
+    public void showInCallScreen(boolean showDialpad) {
+        ITelecommService service = getTelecommService();
+        if (service != null) {
+            try {
+                service.showInCallScreen(showDialpad);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling ITelecommService#showCallScreen", e);
+            }
+        }
+    }
+
     private ITelecommService getTelecommService() {
         return ITelecommService.Stub.asInterface(ServiceManager.getService(TELECOMM_SERVICE_NAME));
     }
diff --git a/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl b/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
index 3c1dea6..0ac5078 100644
--- a/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
@@ -32,7 +32,7 @@
      *
      * @param showDialpad if true, make the dialpad visible initially.
      */
-    void showCallScreen(boolean showDialpad);
+    void showInCallScreen(boolean showDialpad);
 
     /**
      * @see TelecommManager#getDefaultOutgoingPhoneAccount
@@ -79,9 +79,9 @@
     void silenceRinger();
 
     /**
-     * @see TelecommManager#isInAPhoneCall
+     * @see TelecommManager#isInCall
      */
-    boolean isInAPhoneCall();
+    boolean isInCall();
 
     /**
      * @see TelecomManager#isRinging
@@ -99,12 +99,12 @@
     void acceptRingingCall();
 
     /**
-     * @see PhoneManager#cancelMissedCallsNotification
+     * @see TelecommManager#cancelMissedCallsNotification
      */
     void cancelMissedCallsNotification();
 
     /**
-     * @see PhoneManager#handlePinMmi
+     * @see TelecommManager#handleMmi
      */
     boolean handlePinMmi(String dialString);
 
diff --git a/telephony/java/android/telephony/IccOpenLogicalChannelResponse.java b/telephony/java/android/telephony/IccOpenLogicalChannelResponse.java
index e9db030..dbe38ea 100644
--- a/telephony/java/android/telephony/IccOpenLogicalChannelResponse.java
+++ b/telephony/java/android/telephony/IccOpenLogicalChannelResponse.java
@@ -24,14 +24,23 @@
  * Response to the {@link TelephonyManager#iccOpenLogicalChannel} command.
  */
 public class IccOpenLogicalChannelResponse implements Parcelable {
-    // Indicates an invalid channel.
+    /**
+     * Indicates an invalid channel.
+     */
     public static int INVALID_CHANNEL = -1;
 
-    // Possible status values.
-    public static int NO_ERROR = 1;
-    public static int MISSING_RESOURCE = 2;
-    public static int NO_SUCH_ELEMENT = 3;
-    public static int UNKNOWN_ERROR = 4;
+    /**
+     * Possible status values returned by open channel command.
+     *
+     * STATUS_NO_ERROR: Open channel command returned successfully.
+     * STATUS_MISSING_RESOURCE: No logical channels available.
+     * STATUS_NO_SUCH_ELEMENT: AID not found on UICC.
+     * STATUS_UNKNOWN_ERROR: Unknown error in open channel command.
+     */
+    public static int STATUS_NO_ERROR = 1;
+    public static int STATUS_MISSING_RESOURCE = 2;
+    public static int STATUS_NO_SUCH_ELEMENT = 3;
+    public static int STATUS_UNKNOWN_ERROR = 4;
 
     private final int mChannel;
     private final int mStatus;
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
index 6633787..78e360b 100644
--- a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
@@ -20,6 +20,7 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.graphics.Color;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
@@ -199,6 +200,7 @@
         mLocalCheckBox = (CheckBox)findViewById(R.id.local);
 
         mLog = (TextView)findViewById(R.id.log);
+        mLog.setTextColor(Color.RED);
 
         PowerManager pm = (PowerManager)getSystemService(POWER_SERVICE);
         mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Scheduler");
diff --git a/tools/aapt/AaptConfig.cpp b/tools/aapt/AaptConfig.cpp
index 69a9c7f..32a0cd3 100644
--- a/tools/aapt/AaptConfig.cpp
+++ b/tools/aapt/AaptConfig.cpp
@@ -255,6 +255,8 @@
                 != ResTable_config::SCREENLONG_ANY
             || config->density != ResTable_config::DENSITY_DEFAULT) {
         minSdk = SDK_DONUT;
+    } else if ((config->density == ResTable_config::DENSITY_ANY)) {
+        minSdk = SDK_L;
     }
 
     if (minSdk > config->sdkVersion) {
@@ -477,6 +479,11 @@
         return true;
     }
 
+    if (strcmp(name, "anydpi") == 0) {
+        if (out) out->density = ResTable_config::DENSITY_ANY;
+        return true;
+    }
+
     if (strcmp(name, "nodpi") == 0) {
         if (out) out->density = ResTable_config::DENSITY_NONE;
         return true;
diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h
index 1439f14..af49461 100644
--- a/tools/aapt/Bundle.h
+++ b/tools/aapt/Bundle.h
@@ -24,6 +24,7 @@
     SDK_HONEYCOMB_MR2 = 13,
     SDK_ICE_CREAM_SANDWICH = 14,
     SDK_ICE_CREAM_SANDWICH_MR1 = 15,
+    SDK_L = 21,
 };
 
 /*
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index f8bc2ae..2604e97 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -221,6 +221,12 @@
     }
 
     @Override
+    public void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX,
+            int startY, IRemoteCallback startedCallback, boolean scaleUp) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
     public void pauseKeyDispatching(IBinder arg0) throws RemoteException {
         // TODO Auto-generated method stub