Merge "Add a hidden method to query profile owner name for a user" into lmp-dev
diff --git a/CleanSpec.mk b/CleanSpec.mk
index c7cf940..7bc30fd 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -221,6 +221,7 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/services.core_intermediates)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/services_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/inputflinger $(PRODUCT_OUT)/symbols/system/bin/inputflinger)
 
 # ******************************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
diff --git a/api/current.txt b/api/current.txt
index 8f75785..5159a3a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -929,6 +929,7 @@
     field public static final int orderingFromXml = 16843239; // 0x10101e7
     field public static final int orientation = 16842948; // 0x10100c4
     field public static final int outAnimation = 16843128; // 0x1010178
+    field public static final int outlineProvider = 16843961; // 0x10104b9
     field public static final int overScrollFooter = 16843459; // 0x10102c3
     field public static final int overScrollHeader = 16843458; // 0x10102c2
     field public static final int overScrollMode = 16843457; // 0x10102c1
@@ -8667,7 +8668,7 @@
     method public void removeSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
     method public void uninstall(java.lang.String, android.content.IntentSender);
     field public static final java.lang.String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS";
-    field public static final java.lang.String EXTRA_PACKAGE_NAMES = "android.content.pm.extra.PACKAGE_NAMES";
+    field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME";
     field public static final java.lang.String EXTRA_SESSION_ID = "android.content.pm.extra.SESSION_ID";
     field public static final java.lang.String EXTRA_STATUS = "android.content.pm.extra.STATUS";
     field public static final java.lang.String EXTRA_STATUS_MESSAGE = "android.content.pm.extra.STATUS_MESSAGE";
@@ -16381,16 +16382,16 @@
     method public void addCallback(android.media.session.MediaController.Callback, android.os.Handler);
     method public void adjustVolume(int, int);
     method public boolean dispatchMediaButtonEvent(android.view.KeyEvent);
-    method public android.media.session.MediaController.AudioInfo getAudioInfo();
     method public android.os.Bundle getExtras();
     method public long getFlags();
-    method public android.app.PendingIntent getLaunchActivity();
     method public android.media.MediaMetadata getMetadata();
     method public java.lang.String getPackageName();
+    method public android.media.session.MediaController.PlaybackInfo getPlaybackInfo();
     method public android.media.session.PlaybackState getPlaybackState();
     method public java.util.List<android.media.session.MediaSession.Item> getQueue();
     method public java.lang.CharSequence getQueueTitle();
     method public int getRatingType();
+    method public android.app.PendingIntent getSessionActivity();
     method public android.media.session.MediaSession.Token getSessionToken();
     method public android.media.session.MediaController.TransportControls getTransportControls();
     method public void removeCallback(android.media.session.MediaController.Callback);
@@ -16398,17 +16399,9 @@
     method public void setVolumeTo(int, int);
   }
 
-  public static final class MediaController.AudioInfo {
-    method public android.media.AudioAttributes getAudioAttributes();
-    method public int getCurrentVolume();
-    method public int getMaxVolume();
-    method public int getVolumeControl();
-    method public int getVolumeType();
-  }
-
   public static abstract class MediaController.Callback {
     ctor public MediaController.Callback();
-    method public void onAudioInfoChanged(android.media.session.MediaController.AudioInfo);
+    method public void onAudioInfoChanged(android.media.session.MediaController.PlaybackInfo);
     method public void onExtrasChanged(android.os.Bundle);
     method public void onMetadataChanged(android.media.MediaMetadata);
     method public void onPlaybackStateChanged(android.media.session.PlaybackState);
@@ -16418,6 +16411,16 @@
     method public void onSessionEvent(java.lang.String, android.os.Bundle);
   }
 
+  public static final class MediaController.PlaybackInfo {
+    method public android.media.AudioAttributes getAudioAttributes();
+    method public int getCurrentVolume();
+    method public int getMaxVolume();
+    method public int getPlaybackType();
+    method public int getVolumeControl();
+    field public static final int PLAYBACK_TYPE_LOCAL = 1; // 0x1
+    field public static final int PLAYBACK_TYPE_REMOTE = 2; // 0x2
+  }
+
   public final class MediaController.TransportControls {
     method public void fastForward();
     method public void pause();
@@ -16447,7 +16450,6 @@
     method public void setCallback(android.media.session.MediaSession.Callback, android.os.Handler);
     method public void setExtras(android.os.Bundle);
     method public void setFlags(int);
-    method public void setLaunchActivity(android.app.PendingIntent);
     method public void setMediaButtonReceiver(android.app.PendingIntent);
     method public void setMetadata(android.media.MediaMetadata);
     method public void setPlaybackState(android.media.session.PlaybackState);
@@ -16455,10 +16457,9 @@
     method public void setPlaybackToRemote(android.media.VolumeProvider);
     method public void setQueue(java.util.List<android.media.session.MediaSession.Item>);
     method public void setQueueTitle(java.lang.CharSequence);
+    method public void setSessionActivity(android.app.PendingIntent);
     field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
     field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
-    field public static final int PLAYBACK_TYPE_LOCAL = 1; // 0x1
-    field public static final int PLAYBACK_TYPE_REMOTE = 2; // 0x2
   }
 
   public static abstract class MediaSession.Callback {
@@ -16505,6 +16506,7 @@
 
   public final class MediaSessionManager {
     method public void addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName);
+    method public void addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName, android.os.Handler);
     method public java.util.List<android.media.session.MediaController> getActiveSessions(android.content.ComponentName);
     method public void removeOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener);
   }
@@ -16516,7 +16518,7 @@
   public final class PlaybackState implements android.os.Parcelable {
     method public int describeContents();
     method public long getActions();
-    method public long getBufferPosition();
+    method public long getBufferedPosition();
     method public java.util.List<android.media.session.PlaybackState.CustomAction> getCustomActions();
     method public java.lang.CharSequence getErrorMessage();
     method public long getLastPositionUpdateTime();
@@ -16560,7 +16562,7 @@
     method public android.media.session.PlaybackState build();
     method public android.media.session.PlaybackState.Builder setActions(long);
     method public android.media.session.PlaybackState.Builder setActiveItem(long);
-    method public android.media.session.PlaybackState.Builder setBufferPosition(long);
+    method public android.media.session.PlaybackState.Builder setBufferedPosition(long);
     method public android.media.session.PlaybackState.Builder setErrorMessage(java.lang.CharSequence);
     method public android.media.session.PlaybackState.Builder setState(int, long, float, long);
     method public android.media.session.PlaybackState.Builder setState(int, long, float);
@@ -18463,25 +18465,8 @@
 package android.net.wifi.passpoint {
 
   public abstract interface IWifiPasspointManager implements android.os.IInterface {
-    method public abstract boolean addCredential(android.net.wifi.passpoint.WifiPasspointCredential) throws android.os.RemoteException;
-    method public abstract java.util.List<android.net.wifi.passpoint.WifiPasspointCredential> getCredentials() throws android.os.RemoteException;
     method public abstract android.os.Messenger getMessenger() throws android.os.RemoteException;
     method public abstract int getPasspointState() throws android.os.RemoteException;
-    method public abstract boolean removeCredential(android.net.wifi.passpoint.WifiPasspointCredential) throws android.os.RemoteException;
-    method public abstract java.util.List<android.net.wifi.passpoint.WifiPasspointPolicy> requestCredentialMatch(java.util.List<android.net.wifi.ScanResult>) throws android.os.RemoteException;
-    method public abstract boolean updateCredential(android.net.wifi.passpoint.WifiPasspointCredential) throws android.os.RemoteException;
-  }
-
-  public class WifiPasspointCredential implements android.os.Parcelable {
-    ctor public WifiPasspointCredential(java.lang.String, java.lang.String, android.net.wifi.WifiEnterpriseConfig);
-    method public int describeContents();
-    method public android.net.wifi.WifiEnterpriseConfig getEnterpriseConfig();
-    method public java.lang.String getHomeSpFqdn();
-    method public java.lang.String getRealm();
-    method public void setEnterpriseConfig(android.net.wifi.WifiEnterpriseConfig);
-    method public void setHomeFqdn(java.lang.String);
-    method public void setRealm(java.lang.String);
-    method public void writeToParcel(android.os.Parcel, int);
   }
 
   public class WifiPasspointInfo implements android.os.Parcelable {
@@ -18654,17 +18639,6 @@
     field public java.lang.String ssid;
   }
 
-  public class WifiPasspointPolicy implements android.os.Parcelable {
-    method public android.net.wifi.WifiConfiguration createWifiConfiguration();
-    method public int describeContents();
-    method public java.lang.String getBssid();
-    method public android.net.wifi.passpoint.WifiPasspointCredential getCredential();
-    method public int getCredentialPriority();
-    method public int getRoamingPriority();
-    method public java.lang.String getSsid();
-    method public void writeToParcel(android.os.Parcel, int);
-  }
-
 }
 
 package android.nfc {
@@ -28569,8 +28543,8 @@
     method public final int getCallerDisplayNamePresentation();
     method public final android.telecomm.Conference getConference();
     method public final java.util.List<android.telecomm.Connection> getConferenceableConnections();
-    method public final int getFailureCode();
-    method public final java.lang.String getFailureMessage();
+    method public final int getDisconnectCause();
+    method public final java.lang.String getDisconnectMessage();
     method public final android.net.Uri getHandle();
     method public final int getHandlePresentation();
     method public final int getState();
@@ -34958,6 +34932,8 @@
     ctor public ViewOutlineProvider();
     method public abstract void getOutline(android.view.View, android.graphics.Outline);
     field public static final android.view.ViewOutlineProvider BACKGROUND;
+    field public static final android.view.ViewOutlineProvider BOUNDS;
+    field public static final android.view.ViewOutlineProvider PADDED_BOUNDS;
   }
 
   public class ViewOverlay {
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 3c13115..1691d8e 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -178,8 +178,13 @@
         //}
 
         AssetManager assets = new AssetManager();
-        if (assets.addAssetPath(resDir) == 0) {
-            return null;
+        // resDir can be null if the 'android' package is creating a new Resources object.
+        // This is fine, since each AssetManager automatically loads the 'android' package
+        // already.
+        if (resDir != null) {
+            if (assets.addAssetPath(resDir) == 0) {
+                return null;
+            }
         }
 
         if (splitResDirs != null) {
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 4ac701f..7419ebc 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -105,10 +105,14 @@
     public static final String EXTRA_STATUS_MESSAGE = "android.content.pm.extra.STATUS_MESSAGE";
 
     /**
-     * List of package names that are relevant to a status.
+     * Package name relevant to a status.
      *
-     * @see Intent#getStringArrayExtra(String)
+     * @see Intent#getStringExtra(String)
      */
+    public static final String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME";
+
+    /** {@hide} */
+    @Deprecated
     public static final String EXTRA_PACKAGE_NAMES = "android.content.pm.extra.PACKAGE_NAMES";
 
     /** {@hide} */
@@ -178,8 +182,8 @@
      * permission, incompatible certificates, etc. The user may be able to
      * uninstall another app to fix the issue.
      * <p>
-     * The result may also contain {@link #EXTRA_PACKAGE_NAMES} with the
-     * specific packages identified as the cause of the conflict.
+     * The result may also contain {@link #EXTRA_PACKAGE_NAME} with the
+     * specific package identified as the cause of the conflict.
      *
      * @see #EXTRA_STATUS_MESSAGE
      */
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 2c50f25..eb8b762 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -596,7 +596,7 @@
     public final static int PARSE_ON_SDCARD = 1<<5;
     public final static int PARSE_IS_SYSTEM_DIR = 1<<6;
     public final static int PARSE_IS_PRIVILEGED = 1<<7;
-    public final static int PARSE_GET_SIGNATURES = 1<<8;
+    public final static int PARSE_COLLECT_CERTIFICATES = 1<<8;
     public final static int PARSE_TRUSTED_OVERLAY = 1<<9;
 
     private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
@@ -1087,34 +1087,6 @@
         }
     }
 
-    /**
-     * Only collect certificates on the manifest; does not validate signatures
-     * across remainder of package.
-     */
-    private static Signature[] collectManifestCertificates(File apkFile)
-            throws PackageParserException {
-        final String apkPath = apkFile.getAbsolutePath();
-        try {
-            final StrictJarFile jarFile = new StrictJarFile(apkPath);
-            try {
-                final ZipEntry jarEntry = jarFile.findEntry(ANDROID_MANIFEST_FILENAME);
-                if (jarEntry == null) {
-                    throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                            "Package " + apkPath + " has no manifest");
-                }
-
-                final Certificate[][] certs = loadCertificates(jarFile, jarEntry);
-                return convertToSignatures(certs);
-
-            } finally {
-                jarFile.close();
-            }
-        } catch (GeneralSecurityException | IOException | RuntimeException e) {
-            throw new PackageParserException(INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING,
-                    "Failed to collect certificates from " + apkPath, e);
-        }
-    }
-
     private static Signature[] convertToSignatures(Certificate[][] certs)
             throws CertificateEncodingException {
         final Signature[] res = new Signature[certs.length];
@@ -1129,7 +1101,8 @@
      * file, including package name, split name, and install location.
      *
      * @param apkFile path to a single APK
-     * @param flags optional parse flags, such as {@link #PARSE_GET_SIGNATURES}
+     * @param flags optional parse flags, such as
+     *            {@link #PARSE_COLLECT_CERTIFICATES}
      */
     public static ApkLite parseApkLite(File apkFile, int flags)
             throws PackageParserException {
@@ -1154,11 +1127,12 @@
             final Resources res = new Resources(assets, metrics, null);
             parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
 
-            // Only collect certificates on the manifest; does not validate
-            // signatures across remainder of package.
             final Signature[] signatures;
-            if ((flags & PARSE_GET_SIGNATURES) != 0) {
-                signatures = collectManifestCertificates(apkFile);
+            if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
+                // TODO: factor signature related items out of Package object
+                final Package tempPkg = new Package(null);
+                collectCertificates(tempPkg, apkFile, 0);
+                signatures = tempPkg.mSignatures;
             } else {
                 signatures = null;
             }
diff --git a/core/java/android/content/res/ResourcesKey.java b/core/java/android/content/res/ResourcesKey.java
index 53e0f2c..e0f1b3a 100644
--- a/core/java/android/content/res/ResourcesKey.java
+++ b/core/java/android/content/res/ResourcesKey.java
@@ -62,8 +62,12 @@
             return false;
         }
         ResourcesKey peer = (ResourcesKey) obj;
-        if (!mResDir.equals(peer.mResDir)) {
-            return false;
+        if (mResDir != peer.mResDir) {
+            if (mResDir == null || peer.mResDir == null) {
+                return false;
+            } else if (!mResDir.equals(peer.mResDir)) {
+                return false;
+            }
         }
         if (mDisplayId != peer.mDisplayId) {
             return false;
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index d60a2c2..b52a0c5 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -348,7 +348,7 @@
      * A sensor of this type returns the number of steps taken by the user since the last reboot
      * while activated. The value is returned as a float (with the fractional part set to zero) and
      * is reset to zero only on a system reboot. The timestamp of the event is set to the time when
-     * the first step for that event was taken. This sensor is implemented in hardware and is
+     * the last step for that event was taken. This sensor is implemented in hardware and is
      * expected to be low power.
      * <p>
      * See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details.
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 5189155..e215669 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -57,8 +57,7 @@
 
     /**
      * Key for user restrictions. Specifies if a user is disallowed from changing Wi-Fi
-     * access points.
-     * The default value is <code>false</code>.
+     * access points. The default value is <code>false</code>.
      * <p/>
      * Type: Boolean
      * @see #setUserRestrictions(Bundle)
@@ -119,7 +118,7 @@
 
     /**
      * Key for user restrictions. Specifies if a user is disallowed from transferring files over
-     * USB. The default value is <code>false</code>.
+     * USB. This can only be set by device owners. The default value is <code>false</code>.
      * <p/>
      * Type: Boolean
      * @see #setUserRestrictions(Bundle)
@@ -139,8 +138,7 @@
 
     /**
      * Key for user restrictions. Specifies if a user is disallowed from removing itself and other
-     * users.
-     * The default value is <code>false</code>.
+     * users. The default value is <code>false</code>.
      * <p/>
      * Type: Boolean
      * @see #setUserRestrictions(Bundle)
@@ -170,7 +168,8 @@
 
     /**
      * Key for user restrictions. Specifies if a user is disallowed from configuring Tethering
-     * & portable hotspots. The default value is <code>false</code>.
+     * & portable hotspots. This can only be set by device owners. The default value is
+     * <code>false</code>.
      * <p/>
      * Type: Boolean
      * @see #setUserRestrictions(Bundle)
@@ -180,8 +179,8 @@
 
     /**
      * Key for user restrictions. Specifies if a user is disallowed from factory resetting
-     * from Settings.
-     * The default value is <code>false</code>.
+     * from Settings. This can only be set by device owners. The default value is
+     * <code>false</code>.
      * <p>
      * @see #setUserRestrictions(Bundle)
      * @see #getUserRestrictions()
@@ -190,7 +189,7 @@
 
     /**
      * Key for user restrictions. Specifies if a user is disallowed from adding new users and
-     * profiles. The default value is <code>false</code>.
+     * profiles. This can only be set by device owners. The default value is <code>false</code>.
      * <p>
      * Type: Boolean
      * @see #setUserRestrictions(Bundle)
@@ -210,7 +209,7 @@
 
     /**
      * Key for user restrictions. Specifies if a user is disallowed from configuring cell
-     * broadcasts. The default value is <code>false</code>.
+     * broadcasts. This can only be set by device owners. The default value is <code>false</code>.
      * <p>
      * Type: Boolean
      * @see #setUserRestrictions(Bundle)
@@ -220,7 +219,7 @@
 
     /**
      * Key for user restrictions. Specifies if a user is disallowed from configuring mobile
-     * networks. The default value is <code>false</code>.
+     * networks. This can only be set by device owners. The default value is <code>false</code>.
      * <p>
      * Type: Boolean
      * @see #setUserRestrictions(Bundle)
@@ -249,7 +248,8 @@
 
     /**
      * Key for user restrictions. Specifies if a user is disallowed from mounting
-     * physical external media. The default value is <code>false</code>.
+     * physical external media. This can only be set by device owners. The default value is
+     * <code>false</code>.
      * <p/>
      * Type: Boolean
      * @see #setUserRestrictions(Bundle)
@@ -259,7 +259,7 @@
 
     /**
      * Key for user restrictions. Specifies if a user is disallowed from adjusting microphone
-     * volume.
+     * volume. If set, the microphone will be muted. This can only be set by device owners.
      * The default value is <code>false</code>.
      * <p/>
      * Type: Boolean
@@ -270,7 +270,7 @@
 
     /**
      * Key for user restrictions. Specifies if a user is disallowed from adjusting the master
-     * volume.
+     * volume. If set, the master volume will be muted. This can only be set by device owners.
      * The default value is <code>false</code>.
      * <p/>
      * Type: Boolean
@@ -292,8 +292,7 @@
 
     /**
      * Key for user restrictions. Specifies that the user is not allowed to send or receive
-     * SMS messages.
-     * The default value is <code>false</code>.
+     * SMS messages. This can only be set by device owners. The default value is <code>false</code>.
      * <p/>
      * Type: Boolean
      * @see #setUserRestrictions(Bundle)
@@ -311,7 +310,7 @@
      * <li>{@link LayoutParams#TYPE_SYSTEM_ERROR}</li>
      * <li>{@link LayoutParams#TYPE_SYSTEM_OVERLAY}</li>
      *
-     * <p>The default value is <code>false</code>.
+     * <p>This can only be set by device owners. The default value is <code>false</code>.
      * <p/>
      * Type: Boolean
      * @see #setUserRestrictions(Bundle)
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 8c9b819..de90899 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -349,6 +349,8 @@
      */
     abstract HardwareLayer createTextureLayer();
 
+    abstract void buildLayer(RenderNode node);
+
     abstract boolean copyLayerInto(HardwareLayer layer, Bitmap bitmap);
 
     /**
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index f9333d5..50341fc 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -332,6 +332,11 @@
     }
 
     @Override
+    void buildLayer(RenderNode node) {
+        nBuildLayer(mNativeProxy, node.getNativeDisplayList());
+    }
+
+    @Override
     boolean copyLayerInto(final HardwareLayer layer, final Bitmap bitmap) {
         return nCopyLayerInto(mNativeProxy,
                 layer.getDeferredLayerUpdater(), bitmap.mNativeBitmap);
@@ -468,6 +473,7 @@
 
     private static native long nCreateDisplayListLayer(long nativeProxy, int width, int height);
     private static native long nCreateTextureLayer(long nativeProxy);
+    private static native void nBuildLayer(long nativeProxy, long node);
     private static native boolean nCopyLayerInto(long nativeProxy, long layer, long bitmap);
     private static native void nPushLayerUpdate(long nativeProxy, long layer);
     private static native void nCancelLayerUpdate(long nativeProxy, long layer);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 3adc41a..243d7d7 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4047,6 +4047,10 @@
                     mBackgroundTintMode = Drawable.parseTintMode(a.getInt(
                             R.styleable.View_backgroundTintMode, -1), mBackgroundTintMode);
                     break;
+                case R.styleable.View_outlineProvider:
+                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
+                            PROVIDER_BACKGROUND));
+                    break;
             }
         }
 
@@ -10824,14 +10828,6 @@
     }
 
     /**
-     * Deprecated, pending removal
-     *
-     * @hide
-     */
-    @Deprecated
-    public void setOutline(@Nullable Outline outline) {}
-
-    /**
      * Returns whether the Outline should be used to clip the contents of the View.
      * <p>
      * Note that this flag will only be respected if the View's Outline returns true from
@@ -10860,6 +10856,28 @@
         }
     }
 
+    // correspond to the enum values of View_outlineProvider
+    private static final int PROVIDER_BACKGROUND = 0;
+    private static final int PROVIDER_NONE = 1;
+    private static final int PROVIDER_BOUNDS = 2;
+    private static final int PROVIDER_PADDED_BOUNDS = 3;
+    private void setOutlineProviderFromAttribute(int providerInt) {
+        switch (providerInt) {
+            case PROVIDER_BACKGROUND:
+                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
+                break;
+            case PROVIDER_NONE:
+                setOutlineProvider(null);
+                break;
+            case PROVIDER_BOUNDS:
+                setOutlineProvider(ViewOutlineProvider.BOUNDS);
+                break;
+            case PROVIDER_PADDED_BOUNDS:
+                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
+                break;
+        }
+    }
+
     /**
      * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
      * the shape of the shadow it casts, and enables outline clipping.
@@ -13640,11 +13658,10 @@
 
         switch (mLayerType) {
             case LAYER_TYPE_HARDWARE:
-                // The only part of a hardware layer we can build in response to
-                // this call is to ensure the display list is up to date.
-                // The actual rendering of the display list into the layer must
-                // be done at playback time
                 updateDisplayListIfDirty();
+                if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
+                    attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
+                }
                 break;
             case LAYER_TYPE_SOFTWARE:
                 buildDrawingCache(true);
diff --git a/core/java/android/view/ViewOutlineProvider.java b/core/java/android/view/ViewOutlineProvider.java
index 170c5d8..a1a02f6 100644
--- a/core/java/android/view/ViewOutlineProvider.java
+++ b/core/java/android/view/ViewOutlineProvider.java
@@ -44,6 +44,35 @@
     };
 
     /**
+     * Maintains the outline of the View to match its rectangular bounds,
+     * at <code>1.0f</code> alpha.
+     *
+     * This can be used to enable Views that are opaque but lacking a background cast a shadow.
+     */
+    public static final ViewOutlineProvider BOUNDS = new ViewOutlineProvider() {
+        @Override
+        public void getOutline(View view, Outline outline) {
+            outline.setRect(0, 0, view.getWidth(), view.getHeight());
+        }
+    };
+
+    /**
+     * Maintains the outline of the View to match its rectangular padded bounds,
+     * at <code>1.0f</code> alpha.
+     *
+     * This can be used to enable Views that are opaque but lacking a background cast a shadow.
+     */
+    public static final ViewOutlineProvider PADDED_BOUNDS = new ViewOutlineProvider() {
+        @Override
+        public void getOutline(View view, Outline outline) {
+            outline.setRect(view.getPaddingLeft(),
+                    view.getPaddingTop(),
+                    view.getWidth() - view.getPaddingRight(),
+                    view.getHeight() - view.getPaddingBottom());
+        }
+    };
+
+    /**
      * Called to get the provider to populate the Outline.
      *
      * This method will be called by a View when its owned Drawables are invalidated, when the
diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java
index a0d9475..27763eb 100644
--- a/core/java/android/widget/SimpleMonthView.java
+++ b/core/java/android/widget/SimpleMonthView.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.res.ColorStateList;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.Paint;
@@ -38,6 +39,7 @@
 import com.android.internal.R;
 import com.android.internal.widget.ExploreByTouchHelper;
 
+import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Formatter;
 import java.util.List;
@@ -72,6 +74,9 @@
     // used for scaling to the device density
     private static float mScale = 0;
 
+    /** Single-letter (when available) formatter for the day of week label. */
+    private SimpleDateFormat mDayFormatter = new SimpleDateFormat("EEEEE", Locale.getDefault());
+
     // affects the padding on the sides of this view
     private int mPadding = 0;
 
@@ -181,6 +186,13 @@
         initView();
     }
 
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+
+        mDayFormatter = new SimpleDateFormat("EEEEE", newConfig.locale);
+    }
+
     void setTextColor(ColorStateList colors) {
         final Resources res = getContext().getResources();
 
@@ -426,16 +438,16 @@
     }
 
     private void drawWeekDayLabels(Canvas canvas) {
-        int y = mMonthHeaderSize - (mMonthDayLabelTextSize / 2);
-        int dayWidthHalf = (mWidth - mPadding * 2) / (mNumDays * 2);
+        final int y = mMonthHeaderSize - (mMonthDayLabelTextSize / 2);
+        final int dayWidthHalf = (mWidth - mPadding * 2) / (mNumDays * 2);
 
         for (int i = 0; i < mNumDays; i++) {
-            int calendarDay = (i + mWeekStart) % mNumDays;
-            int x = (2 * i + 1) * dayWidthHalf + mPadding;
+            final int calendarDay = (i + mWeekStart) % mNumDays;
             mDayLabelCalendar.set(Calendar.DAY_OF_WEEK, calendarDay);
-            canvas.drawText("" + mDayLabelCalendar.getDisplayName(Calendar.DAY_OF_WEEK,
-                    Calendar.SHORT, Locale.getDefault()).toUpperCase(Locale.getDefault()).charAt(0),
-                    x, y, mMonthDayLabelPaint);
+
+            final String dayLabel = mDayFormatter.format(mDayLabelCalendar.getTime());
+            final int x = (2 * i + 1) * dayWidthHalf + mPadding;
+            canvas.drawText(dayLabel, x, y, mMonthDayLabelPaint);
         }
     }
 
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 636c712..61b4567 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -22,6 +22,7 @@
 import android.app.usage.UsageStatsManager;
 import android.os.AsyncTask;
 import android.provider.Settings;
+import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Slog;
 import android.widget.AbsListView;
@@ -278,12 +279,15 @@
             });
         }
 
-        final TextView titleView = (TextView) findViewById(R.id.title);
-        if (titleView != null) {
-            if (title == null) {
-                title = getTitleForAction(intent.getAction(), defaultTitleRes);
+        if (title == null) {
+            title = getTitleForAction(intent.getAction(), defaultTitleRes);
+        }
+        if (!TextUtils.isEmpty(title)) {
+            final TextView titleView = (TextView) findViewById(R.id.title);
+            if (titleView != null) {
+                titleView.setText(title);
             }
-            titleView.setText(title);
+            setTitle(title);
         }
 
         final ImageView iconView = (ImageView) findViewById(R.id.icon);
diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java
index d76d0d4..179d5e8 100644
--- a/core/java/com/android/internal/content/NativeLibraryHelper.java
+++ b/core/java/com/android/internal/content/NativeLibraryHelper.java
@@ -19,15 +19,25 @@
 import static android.content.pm.PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS;
 import static android.content.pm.PackageManager.INSTALL_SUCCEEDED;
 import static android.content.pm.PackageManager.NO_NATIVE_LIBRARIES;
+import static android.system.OsConstants.S_IRGRP;
+import static android.system.OsConstants.S_IROTH;
+import static android.system.OsConstants.S_IRWXU;
+import static android.system.OsConstants.S_IXGRP;
+import static android.system.OsConstants.S_IXOTH;
 
 import android.content.pm.PackageManager;
 import android.content.pm.PackageParser;
 import android.content.pm.PackageParser.Package;
 import android.content.pm.PackageParser.PackageLite;
 import android.content.pm.PackageParser.PackageParserException;
+import android.os.Build;
+import android.os.SELinux;
+import android.system.ErrnoException;
+import android.system.Os;
 import android.util.Slog;
 
 import dalvik.system.CloseGuard;
+import dalvik.system.VMRuntime;
 
 import java.io.Closeable;
 import java.io.File;
@@ -44,6 +54,10 @@
 
     private static final boolean DEBUG_NATIVE = false;
 
+    // Special value for {@code PackageParser.Package#cpuAbiOverride} to indicate
+    // that the cpuAbiOverride must be clear.
+    public static final String CLEAR_ABI_OVERRIDE = "-";
+
     /**
      * A handle to an opened package, consisting of one or more APKs. Used as
      * input to the various NativeLibraryHelper methods. Allows us to scan and
@@ -126,27 +140,17 @@
 
     private static native long nativeSumNativeBinaries(long handle, String cpuAbi);
 
-    /**
-     * Sums the size of native binaries in an APK for a given ABI.
-     *
-     * @return size of all native binary files in bytes
-     */
-    public static long sumNativeBinariesLI(Handle handle, String[] abis) {
+    private native static int nativeCopyNativeBinaries(long handle,
+            String sharedLibraryPath, String abiToCopy);
+
+    private static long sumNativeBinaries(Handle handle, String abi) {
         long sum = 0;
         for (long apkHandle : handle.apkHandles) {
-            // NOTE: For a given APK handle, we parse the central directory precisely
-            // once, but prefix matching of entries requires a CD traversal, which can
-            // take a while (even if it needs no additional I/O).
-            for (String abi : abis) {
-                sum += nativeSumNativeBinaries(apkHandle, abi);
-            }
+            sum += nativeSumNativeBinaries(apkHandle, abi);
         }
         return sum;
     }
 
-    private native static int nativeCopyNativeBinaries(long handle,
-            String sharedLibraryPath, String abiToCopy);
-
     /**
      * Copies native binaries to a shared library directory.
      *
@@ -244,9 +248,171 @@
         }
     }
 
+    private static void createNativeLibrarySubdir(File path) throws IOException {
+        if (!path.isDirectory()) {
+            path.delete();
+
+            if (!path.mkdir()) {
+                throw new IOException("Cannot create " + path.getPath());
+            }
+
+            try {
+                Os.chmod(path.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
+            } catch (ErrnoException e) {
+                throw new IOException("Cannot chmod native library directory "
+                        + path.getPath(), e);
+            }
+        } else if (!SELinux.restorecon(path)) {
+            throw new IOException("Cannot set SELinux context for " + path.getPath());
+        }
+    }
+
+    private static long sumNativeBinaries(Handle handle, String[] abiList) {
+        int abi = findSupportedAbi(handle, abiList);
+        if (abi >= 0) {
+            return sumNativeBinaries(handle, abiList[abi]);
+        } else {
+            return 0;
+        }
+    }
+
+    public static int copyNativeBinariesIfNeededLI(Handle handle, File libraryRoot,
+            String[] abiList, boolean useIsaSubdir) throws IOException {
+        createNativeLibrarySubdir(libraryRoot);
+
+        /*
+         * If this is an internal application or our nativeLibraryPath points to
+         * the app-lib directory, unpack the libraries if necessary.
+         */
+        int abi = findSupportedAbi(handle, abiList);
+        if (abi >= 0) {
+            /*
+             * If we have a matching instruction set, construct a subdir under the native
+             * library root that corresponds to this instruction set.
+             */
+            final String instructionSet = VMRuntime.getInstructionSet(abiList[abi]);
+            final File subDir;
+            if (useIsaSubdir) {
+                final File isaSubdir = new File(libraryRoot, instructionSet);
+                createNativeLibrarySubdir(isaSubdir);
+                subDir = isaSubdir;
+            } else {
+                subDir = libraryRoot;
+            }
+
+            int copyRet = copyNativeBinariesIfNeededLI(handle, subDir, abiList[abi]);
+            if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
+                return copyRet;
+            }
+        }
+
+        return abi;
+    }
+
+    public static int copyNativeBinariesIfNeededLI(Handle handle, File libraryRoot,
+            String abiOverride, boolean multiArch) {
+        try {
+            if (multiArch) {
+                // Warn if we've set an abiOverride for multi-lib packages..
+                // By definition, we need to copy both 32 and 64 bit libraries for
+                // such packages.
+                if (abiOverride != null && !CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
+                    Slog.w(TAG, "Ignoring abiOverride for multi arch application.");
+                }
+
+                int copyRet = PackageManager.NO_NATIVE_LIBRARIES;
+                if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
+                    copyRet = copyNativeBinariesIfNeededLI(handle, libraryRoot,
+                            Build.SUPPORTED_32_BIT_ABIS, true /* use isa specific subdirs */);
+                    if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES &&
+                            copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) {
+                        Slog.w(TAG, "Failure copying 32 bit native libraries; copyRet=" +copyRet);
+                        return copyRet;
+                    }
+                }
+
+                if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
+                    copyRet = copyNativeBinariesIfNeededLI(handle, libraryRoot,
+                            Build.SUPPORTED_64_BIT_ABIS, true /* use isa specific subdirs */);
+                    if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES &&
+                            copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) {
+                        Slog.w(TAG, "Failure copying 64 bit native libraries; copyRet=" +copyRet);
+                        return copyRet;
+                    }
+                }
+            } else {
+                String cpuAbiOverride = null;
+                if (CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
+                    cpuAbiOverride = null;
+                } else if (abiOverride != null) {
+                    cpuAbiOverride = abiOverride;
+                }
+
+                String[] abiList = (cpuAbiOverride != null) ?
+                        new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS;
+                if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null &&
+                        hasRenderscriptBitcode(handle)) {
+                    abiList = Build.SUPPORTED_32_BIT_ABIS;
+                }
+
+                int copyRet = copyNativeBinariesIfNeededLI(handle, libraryRoot, abiList,
+                        true /* use isa specific subdirs */);
+                if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
+                    Slog.w(TAG, "Failure copying native libraries [errorCode=" + copyRet + "]");
+                    return copyRet;
+                }
+            }
+
+            return PackageManager.INSTALL_SUCCEEDED;
+        } catch (IOException e) {
+            Slog.e(TAG, "Copying native libraries failed", e);
+            return PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+        }
+    }
+
+    public static long sumNativeBinaries(Handle handle, String abiOverride, boolean multiArch)
+            throws IOException {
+        long sum = 0;
+        if (multiArch) {
+            // Warn if we've set an abiOverride for multi-lib packages..
+            // By definition, we need to copy both 32 and 64 bit libraries for
+            // such packages.
+            if (abiOverride != null && !CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
+                Slog.w(TAG, "Ignoring abiOverride for multi arch application.");
+            }
+
+            if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
+                sum += sumNativeBinaries(handle, Build.SUPPORTED_32_BIT_ABIS);
+            }
+
+            if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
+                sum += sumNativeBinaries(handle, Build.SUPPORTED_64_BIT_ABIS);
+            }
+        } else {
+            String cpuAbiOverride = null;
+            if (CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
+                cpuAbiOverride = null;
+            } else if (abiOverride != null) {
+                cpuAbiOverride = abiOverride;
+            }
+
+            String[] abiList = (cpuAbiOverride != null) ?
+                    new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS;
+            if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null &&
+                    hasRenderscriptBitcode(handle)) {
+                abiList = Build.SUPPORTED_32_BIT_ABIS;
+            }
+
+            sum += sumNativeBinaries(handle, abiList);
+        }
+        return sum;
+    }
+
     // We don't care about the other return values for now.
     private static final int BITCODE_PRESENT = 1;
 
+    private static native int hasRenderscriptBitcode(long apkHandle);
+
     public static boolean hasRenderscriptBitcode(Handle handle) throws IOException {
         for (long apkHandle : handle.apkHandles) {
             final int res = hasRenderscriptBitcode(apkHandle);
@@ -258,6 +424,4 @@
         }
         return false;
     }
-
-    private static native int hasRenderscriptBitcode(long apkHandle);
 }
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index fd96f64..a529cc3 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -17,13 +17,17 @@
 package com.android.internal.content;
 
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.Environment;
+import android.os.Environment.UserEnvironment;
 import android.os.FileUtils;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.os.storage.IMountService;
 import android.os.storage.StorageManager;
 import android.os.storage.StorageResultCode;
@@ -215,7 +219,7 @@
     /**
      * Extract public files for the single given APK.
      */
-    public static int extractPublicFiles(String apkPath, File publicZipFile)
+    public static long extractPublicFiles(File apkFile, File publicZipFile)
             throws IOException {
         final FileOutputStream fstr;
         final ZipOutputStream publicZipOutStream;
@@ -226,12 +230,13 @@
         } else {
             fstr = new FileOutputStream(publicZipFile);
             publicZipOutStream = new ZipOutputStream(fstr);
+            Log.d(TAG, "Extracting " + apkFile + " to " + publicZipFile);
         }
 
-        int size = 0;
+        long size = 0L;
 
         try {
-            final ZipFile privateZip = new ZipFile(apkPath);
+            final ZipFile privateZip = new ZipFile(apkFile.getAbsolutePath());
             try {
                 // Copy manifest, resources.arsc and res directory to public zip
                 for (final ZipEntry zipEntry : Collections.list(privateZip.entries())) {
@@ -308,8 +313,15 @@
      * Given a requested {@link PackageInfo#installLocation} and calculated
      * install size, pick the actual location to install the app.
      */
-    public static int resolveInstallLocation(Context context, int installLocation, long sizeBytes,
-            int installFlags) {
+    public static int resolveInstallLocation(Context context, String packageName,
+            int installLocation, long sizeBytes, int installFlags) {
+        ApplicationInfo existingInfo = null;
+        try {
+            existingInfo = context.getPackageManager().getApplicationInfo(packageName,
+                    PackageManager.GET_UNINSTALLED_PACKAGES);
+        } catch (NameNotFoundException ignored) {
+        }
+
         final int prefer;
         final boolean checkBoth;
         if ((installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
@@ -325,7 +337,16 @@
             prefer = RECOMMEND_INSTALL_EXTERNAL;
             checkBoth = true;
         } else if (installLocation == PackageInfo.INSTALL_LOCATION_AUTO) {
-            prefer = RECOMMEND_INSTALL_INTERNAL;
+            // When app is already installed, prefer same medium
+            if (existingInfo != null) {
+                if ((existingInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
+                    prefer = RECOMMEND_INSTALL_EXTERNAL;
+                } else {
+                    prefer = RECOMMEND_INSTALL_INTERNAL;
+                }
+            } else {
+                prefer = RECOMMEND_INSTALL_INTERNAL;
+            }
             checkBoth = true;
         } else {
             prefer = RECOMMEND_INSTALL_INTERNAL;
@@ -337,14 +358,15 @@
 
         boolean fitsOnInternal = false;
         if (checkBoth || prefer == RECOMMEND_INSTALL_INTERNAL) {
-            fitsOnInternal = (sizeBytes
-                    <= storage.getStorageBytesUntilLow(Environment.getDataDirectory()));
+            final File target = Environment.getDataDirectory();
+            fitsOnInternal = (sizeBytes <= storage.getStorageBytesUntilLow(target));
         }
 
         boolean fitsOnExternal = false;
         if (!emulated && (checkBoth || prefer == RECOMMEND_INSTALL_EXTERNAL)) {
-            fitsOnExternal = (sizeBytes
-                    <= storage.getStorageBytesUntilLow(Environment.getExternalStorageDirectory()));
+            final File target = new UserEnvironment(UserHandle.USER_OWNER)
+                    .getExternalStorageDirectory();
+            fitsOnExternal = (sizeBytes <= storage.getStorageBytesUntilLow(target));
         }
 
         if (prefer == RECOMMEND_INSTALL_INTERNAL) {
@@ -377,4 +399,12 @@
             return PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
         }
     }
+
+    public static String replaceEnd(String str, String before, String after) {
+        if (!str.endsWith(before)) {
+            throw new IllegalArgumentException(
+                    "Expected " + str + " to end with " + before);
+        }
+        return str.substring(0, str.length() - before.length()) + after;
+    }
 }
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index d183d8e..4e3419a 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -264,6 +264,13 @@
     return reinterpret_cast<jlong>(layer);
 }
 
+static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz,
+        jlong proxyPtr, jlong nodePtr) {
+    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+    RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr);
+    proxy->buildLayer(node);
+}
+
 static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
         jlong proxyPtr, jlong layerPtr, jlong bitmapPtr) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
@@ -367,6 +374,7 @@
     { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
     { "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer },
     { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
+    { "nBuildLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_buildLayer },
     { "nCopyLayerInto", "(JJJ)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
     { "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate },
     { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate },
diff --git a/core/res/res/anim/progress_indeterminate_horizontal_rect1.xml b/core/res/res/anim/progress_indeterminate_horizontal_rect1.xml
new file mode 100644
index 0000000..980c8e4
--- /dev/null
+++ b/core/res/res/anim/progress_indeterminate_horizontal_rect1.xml
@@ -0,0 +1,32 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="2000"
+        android:propertyXName="translateX"
+        android:propertyYName="translateY"
+        android:repeatCount="infinite"
+        android:pathData="M -522.59998 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.0 0 l 0.1294 0 l 0.33832 0 l 0.5545 0 l 0.77088 0 l 0.98065 0 l 1.19641 0 l 1.41351 0 l 1.63153 0 l 1.85053 0 l 2.07052 0 l 2.29081 0 l 2.5115 0 l 2.73261 0 l 2.95355 0 l 3.17404 0 l 3.39423 0 l 3.61355 0 l 3.83164 0 l 4.04849 0 l 4.26367 0 l 5.74725 0 l 6.10266 0 l 6.45981 0 l 6.81781 0 l 7.17655 0 l 7.53366 0 l 7.88861 0 l 8.23975 0 l 8.58447 0 l 8.92157 0 l 9.24811 0 l 9.56137 0 l 9.85907 0 l 10.13778 0 l 10.39557 0 l 10.62876 0 l 10.83572 0 l 11.01492 0 l 11.16397 0 l 11.28324 0 l 11.3714 0 l 11.43011 0 l 11.45966 0 l 11.4611 0 l 11.43691 0 l 11.38878 0 l 11.31834 0 l 11.2276 0 l 11.11856 0 l 10.99338 0 l 10.85347 0 l 10.69954 0 l 10.53393 0 l 10.37447 0 l 10.37077 0 l 10.43095 0 l 10.52757 0 l 10.6715 0 l 10.8764 0 l 11.15665 0 l 11.52708 0 l 11.9948 0 l 12.55024 0 l 13.14534 0 l 13.68079 0 l 14.02233 0 l 14.06503 0 l 13.79804 0 l 13.295 0 l 12.65849 0 l 11.9693 0 l 11.2773 0 l 10.60766 0 l 9.97053 0 l 9.36723 0 l 8.79752 0 l 8.25793 0 l 7.74495 0 l 7.25633 0 l 6.78856 0 l 6.33934 0 l 5.9071 0 l 5.48941 0 l 5.08502 0 l 4.69292 0 l 4.33431 0 l 4.00734 0 l 3.68829 0 l 3.37685 0 l 3.07246 0 l 2.7744 0 l 2.48253 0 l 2.20102 0 l 1.91748 0 l 1.63726 0 l 1.36773 0 "
+        android:interpolator="@interpolator/progress_indeterminate_horizontal_rect1_grp_position" />
+    <objectAnimator
+        android:duration="2000"
+        android:propertyXName="scaleX"
+        android:propertyYName="scaleY"
+        android:repeatCount="infinite"
+        android:pathData="M 0.1 1 l 0.0 0 l 0.00882427215576 0 l 0.00982859611511 0 l 0.0108650398254 0 l 0.011930847168 0 l 0.0130220413208 0 l 0.0141334056854 0 l 0.0152582168579 0 l 0.0163880157471 0 l 0.0175127220154 0 l 0.0186203575134 0 l 0.0196973228455 0 l 0.0207285499573 0 l 0.0216978645325 0 l 0.0225887107849 0 l 0.0233847427368 0 l 0.0240707015991 0 l 0.0246334838867 0 l 0.0250626373291 0 l 0.0253514099121 0 l 0.0254969406128 0 l 0.0255004882813 0 l 0.0253670883179 0 l 0.0251052856445 0 l 0.0247262573242 0 l 0.0242431640625 0 l 0.0236701583862 0 l 0.0230218887329 0 l 0.0223124694824 0 l 0.021555557251 0 l 0.0207632446289 0 l 0.0199468231201 0 l 0.0191157531738 0 l 0.0182782745361 0 l 0.0173241424561 0 l 0.0152210998535 0 l 0.0126258087158 0 l 0.00973388671875 0 l 0.00647575378418 0 l 0.00276618957519 0 l -0.00149223327636 0 l -0.00639404296875 0 l -0.0119906616211 0 l -0.0182067108154 0 l -0.0247090148926 0 l -0.0308044433594 0 l -0.0355574798584 0 l -0.0382397460938 0 l -0.0387688446045 0 l -0.0376621246338 0 l -0.0356225204468 0 l -0.03321434021 0 l -0.0307815170288 0 l -0.0284958267212 0 l -0.0264254379272 0 l -0.024584236145 0 l -0.0229611587524 0 l -0.0215351867676 0 l -0.0202828598023 0 l -0.0191815567017 0 l -0.018210849762 0 l -0.0173528671265 0 l -0.0165923118591 0 l -0.0159160423279 0 l -0.0153129196167 0 l -0.0147735023499 0 l -0.0141336250305 0 l -0.0133926582336 0 l -0.01270362854 0 l -0.0120610809326 0 l -0.0114603328705 0 l -0.0108972930908 0 l -0.0103683567047 0 l -0.00987038612366 0 l -0.00940062522888 0 l -0.00895661354065 0 l -0.00853617668152 0 "
+        android:interpolator="@interpolator/progress_indeterminate_horizontal_rect1_grp_scale" />
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/progress_indeterminate_horizontal_rect2.xml b/core/res/res/anim/progress_indeterminate_horizontal_rect2.xml
new file mode 100644
index 0000000..8f0b2e8
--- /dev/null
+++ b/core/res/res/anim/progress_indeterminate_horizontal_rect2.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="2000"
+        android:propertyXName="translateX"
+        android:propertyYName="translateY"
+        android:repeatCount="infinite"
+        android:pathData="M -197.60001 0 l 1.42626 0 l 1.80754 0 l 2.18779 0 l 2.5611 0 l 2.9181 0 l 3.25482 0 l 3.5716 0 l 3.86255 0 l 4.12494 0 l 4.35758 0 l 4.56035 0 l 4.73427 0 l 4.88091 0 l 5.00271 0 l 5.10274 0 l 5.18401 0 l 5.24911 0 l 5.30098 0 l 5.34226 0 l 5.37535 0 l 5.40181 0 l 5.42322 0 l 5.44123 0 l 5.45705 0 l 5.47099 0 l 5.48396 0 l 5.4967 0 l 5.5095 0 l 5.52215 0 l 5.53528 0 l 5.54913 0 l 5.56306 0 l 5.57743 0 l 5.59244 0 l 5.60744 0 l 5.62244 0 l 5.63767 0 l 5.65263 0 l 5.6669 0 l 5.6807 0 l 5.69401 0 l 5.70899 0 l 5.7517 0 l 5.80327 0 l 5.8571 0 l 5.914 0 l 5.9745 0 l 6.03849 0 l 6.10729 0 l 6.18126 0 l 6.26117 0 l 6.3484 0 l 6.44406 0 l 6.54867 0 l 6.66372 0 l 6.79021 0 l 6.92859 0 l 7.07807 0 l 7.23712 0 l 7.40254 0 l 7.56885 0 l 7.72841 0 l 7.87199 0 l 7.98993 0 l 8.07417 0 l 8.12013 0 l 8.12656 0 l 8.09511 0 l 8.03091 0 l 7.93996 0 l 7.82788 0 l 7.69977 0 l 7.56065 0 l 7.41323 0 l 7.26063 0 l 7.10471 0 l 6.94624 0 l 6.78694 0 l 6.63904 0 l 6.50302 0 l 6.36688 0 l 6.23044 0 l 6.09357 0 l 5.95706 0 l 5.82065 0 l 5.68396 0 l 5.54773 0 l 5.41144 0 l 5.27533 0 l 5.13922 0 l 5.00348 0 l 4.86804 0 l 4.73251 0 l 4.59732 0 l 4.46259 0 l 4.32812 0 l 4.19373 0 l 4.05993 0 l 3.92673 0 l 3.79376 0 l 3.6612 0 l 3.52936 0 l 3.39819 0 l 3.26749 0 l 3.13726 0 l 3.00797 0 l 2.87939 0 l 2.75159 0 l 2.62445 0 l 2.49811 0 l 2.37268 0 l 2.24817 0 l 2.12457 0 l 2.00174 0 l 1.87997 0 l 1.76185 0 l 1.64154 0 l 1.51962 0 l 1.40018 0 l 1.28421 0 "
+        android:interpolator="@interpolator/progress_indeterminate_horizontal_rect2_grp_position" />
+    <objectAnimator
+        android:duration="2000"
+        android:propertyXName="scaleX"
+        android:propertyYName="scaleY"
+        android:repeatCount="infinite"
+        android:pathData="M 0.1 1 l 0.00930031776428 0 l 0.0112302875519 0 l 0.0131314373016 0 l 0.014971075058 0 l 0.0167151069641 0 l 0.0183303451538 0 l 0.0197867202759 0 l 0.0210597610474 0 l 0.0221322822571 0 l 0.0229952049255 0 l 0.0236479568482 0 l 0.0240972709656 0 l 0.0243561935425 0 l 0.0244421386719 0 l 0.0243751525879 0 l 0.0241764450073 0 l 0.0238669586182 0 l 0.0234665298462 0 l 0.0229933547974 0 l 0.0224634552002 0 l 0.0218908691406 0 l 0.0212874603272 0 l 0.0206631851196 0 l 0.0200262451172 0 l 0.019383354187 0 l 0.0187397766113 0 l 0.018099899292 0 l 0.0174669647217 0 l 0.0168434906006 0 l 0.0162316131592 0 l 0.0156324005127 0 l 0.0150471496582 0 l 0.0144763183594 0 l 0.0139205169678 0 l 0.0133796691894 0 l 0.0128540802002 0 l 0.0123434448242 0 l 0.0118475341797 0 l 0.0113663482666 0 l 0.0108992004395 0 l 0.0104459381103 0 l 0.00998542785645 0 l 0.00933837890625 0 l 0.0086334991455 0 l 0.00791206359864 0 l 0.00717010498047 0 l 0.00640274047851 0 l 0.00560478210449 0 l 0.00477012634278 0 l 0.00389221191406 0 l 0.00296325683594 0 l 0.00197517395019 0 l 0.00091903686524 0 l -0.00021408081055 0 l -0.00143287658691 0 l -0.00274444580079 0 l -0.00415267944336 0 l -0.00565589904785 0 l -0.00724327087402 0 l -0.00889205932617 0 l -0.0105648040771 0 l -0.0122087860107 0 l -0.0137604522705 0 l -0.0151544952393 0 l -0.0163356018066 0 l -0.0172690582275 0 l -0.017946395874 0 l -0.0183829498291 0 l -0.0186113739014 0 l -0.018671798706 0 l -0.0186050415039 0 l -0.0184476470947 0 l -0.018229598999 0 l -0.017974319458 0 l -0.0176993560791 0 l -0.0174169921875 0 l -0.0171360397339 0 l -0.0168621444702 0 l -0.0165135955811 0 l -0.0160948562622 0 l -0.0156935882568 0 l -0.0153102493286 0 l -0.0149446105957 0 l -0.0145963287353 0 l -0.0142646408081 0 l -0.0139489364624 0 l -0.0136483383179 0 l -0.0133620071411 0 l -0.0130891799927 0 l -0.0128289794922 0 l -0.0125807571411 0 l -0.0123436355591 0 l -0.0121170043945 0 l -0.0119002914429 0 l -0.0116927337646 0 l -0.0114939498901 0 l -0.0113032531738 0 l -0.0111202430725 0 l -0.010944442749 0 l -0.0107754516601 0 l -0.0106128692627 0 l -0.0104563140869 0 l -0.0103054428101 0 l -0.0101600074768 0 l -0.0100196266174 0 l -0.0098840713501 0 l -0.00975311279297 0 l -0.00962644577026 0 l -0.00950393676758 0 l -0.00938529968262 0 l -0.00927038192749 0 l -0.00915899276733 0 l -0.00905097961426 0 l -0.00894614219665 0 l -0.0088443851471 0 l -0.00874552726745 0 l -0.00864946365357 0 l -0.00855606079101 0 l -0.00846519470215 0 l -0.00837676048279 0 "
+        android:interpolator="@interpolator/progress_indeterminate_horizontal_rect2_grp_scale" />
+</set>
\ No newline at end of file
diff --git a/core/res/res/drawable/progress_indeterminate_horizontal_material.xml b/core/res/res/drawable/progress_indeterminate_horizontal_material.xml
index 4fc68ce..e92f090 100644
--- a/core/res/res/drawable/progress_indeterminate_horizontal_material.xml
+++ b/core/res/res/drawable/progress_indeterminate_horizontal_material.xml
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="utf-8"?>
 <!--
  Copyright (C) 2014 The Android Open Source Project
 
@@ -14,20 +13,13 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
+
 <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:drawable="@drawable/vector_drawable_progress_indeterminate_horizontal" >
-
     <target
-        android:name="path1"
-        android:animation="@anim/progress_indeterminate_horizontal_rect1_translate" />
+        android:name="rect2_grp"
+        android:animation="@anim/progress_indeterminate_horizontal_rect2" />
     <target
-        android:name="path1"
-        android:animation="@anim/progress_indeterminate_horizontal_rect1_scale" />
-
-    <target
-        android:name="path2"
-        android:animation="@anim/progress_indeterminate_horizontal_rect2_translate" />
-    <target
-        android:name="path2"
-        android:animation="@anim/progress_indeterminate_horizontal_rect2_scale" />
-</animated-vector>
+        android:name="rect1_grp"
+        android:animation="@anim/progress_indeterminate_horizontal_rect1" />
+</animated-vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/vector_drawable_progress_indeterminate_horizontal.xml b/core/res/res/drawable/vector_drawable_progress_indeterminate_horizontal.xml
index 0cc7202..7ceb772 100644
--- a/core/res/res/drawable/vector_drawable_progress_indeterminate_horizontal.xml
+++ b/core/res/res/drawable/vector_drawable_progress_indeterminate_horizontal.xml
@@ -13,48 +13,47 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<!--
- 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.
--->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:height="4dp"
-    android:viewportHeight="4"
+    android:height="10dp"
+    android:viewportHeight="10"
     android:viewportWidth="360"
     android:width="360dp" >
 
     <group
-        android:name="linear_indeterminate"
-        android:translateX="180.0"
-        android:translateY="0.0" >
-        <group
-            android:name="path1"
-            android:scaleX="0.1"
-            android:translateX="-522.59" >
-            <path
-                android:name="rect1"
-                android:fillColor="?attr/colorControlActivated"
-                android:pathData="m 0 1.6 l 288 0 l 0 0.8 l -288 0 z" />
-        </group>
-        <group
-            android:name="path2"
-            android:scaleX="0.1"
-            android:translateX="-197.6" >
-            <path
-                android:name="rect2"
-                android:fillColor="?attr/colorControlActivated"
-                android:pathData="m 0 1.6 l 288 0 l 0 0.8 l -288 0 z" />
+        android:name="v21"
+        android:translateX="180"
+        android:translateY="5" >
+        <group android:name="v21_pivot" >
+            <group
+                android:name="rectangle_path_1_position"
+                android:alpha="0.1" >
+                <path
+                    android:name="rectangle_path_1"
+                    android:fillColor="?attr/colorControlActivated"
+                    android:pathData="M -180.0 -1.0 l 360 0 l 0 2 l -360 0 Z" />
+            </group>
+            <group
+                android:name="rect2_grp"
+                android:scaleX="0.1"
+                android:scaleY="1"
+                android:translateX="-197.60001" >
+                <path
+                    android:name="rect2"
+                    android:fillColor="?attr/colorControlActivated"
+                    android:pathData="M -144.0 -1.0 l 288 0 l 0 2 l -288 0 Z" />
+            </group>
+            <group
+                android:name="rect1_grp"
+                android:scaleX="0.1"
+                android:scaleY="1"
+                android:translateX="-522.59998" >
+                <path
+                    android:name="rect1"
+                    android:fillColor="?attr/colorControlActivated"
+                    android:pathData="M -144.0 -1.0 l 288 0 l 0 2 l -288 0 Z" />
+            </group>
         </group>
     </group>
+
 </vector>
\ No newline at end of file
diff --git a/core/res/res/interpolator/progress_indeterminate_horizontal_rect1_grp_position.xml b/core/res/res/interpolator/progress_indeterminate_horizontal_rect1_grp_position.xml
new file mode 100644
index 0000000..1e5490b
--- /dev/null
+++ b/core/res/res/interpolator/progress_indeterminate_horizontal_rect1_grp_position.xml
@@ -0,0 +1,17 @@
+<!--
+ 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.
+-->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="M 0.0 0.0 L 0.00833333333334 0.0 L 0.0166666666667 0.0 L 0.025 0.0 L 0.0333333333333 0.0 L 0.0416666666667 0.0 L 0.05 0.0 L 0.0583333333333 0.0 L 0.0666666666667 0.0 L 0.075 0.0 L 0.0833333333333 0.0 L 0.0916666666667 0.0 L 0.1 0.0 L 0.108333333333 0.0 L 0.116666666667 0.0 L 0.125 0.0 L 0.133333333333 0.0 L 0.141666666667 0.0 L 0.15 0.0 L 0.158333333333 0.0 L 0.166666666667 0.0 L 0.175 0.0 L 0.183333333333 0.0 L 0.191666666667 0.0 L 0.2 0.0 L 0.208333333333 0.000179174746319 L 0.216666666667 0.000647632243805 L 0.225 0.0014154251096 L 0.233333333333 0.00248283027531 L 0.241666666667 0.00384069515149 L 0.25 0.00549731383962 L 0.258333333333 0.00745454178143 L 0.266666666667 0.00971365286228 L 0.275 0.012276004047 L 0.283333333333 0.0151429661471 L 0.291666666667 0.0183149545599 L 0.3 0.0217925231486 L 0.308333333333 0.0255762534696 L 0.316666666667 0.0296659101311 L 0.325 0.0340608700368 L 0.333333333333 0.0387607177895 L 0.341666666667 0.0437642487367 L 0.35 0.049069759749 L 0.358333333333 0.0546755338504 L 0.366666666667 0.0605792586621 L 0.375 0.0685372344023 L 0.383333333333 0.0769873314454 L 0.391666666667 0.0859319590963 L 0.4 0.0953722943142 L 0.408333333333 0.105309361746 L 0.416666666667 0.1157409044 L 0.425 0.126663931413 L 0.433333333333 0.13807316724 L 0.441666666667 0.149959722376 L 0.45 0.162313045726 L 0.458333333333 0.175118515302 L 0.466666666667 0.188357742846 L 0.475 0.20200918308 L 0.483333333333 0.216046541347 L 0.491666666667 0.230440850602 L 0.5 0.245158048258 L 0.508333333333 0.260161814735 L 0.516666666667 0.275413711928 L 0.525 0.290871992396 L 0.533333333333 0.306495421026 L 0.541666666667 0.322240921106 L 0.55 0.338067714457 L 0.558333333333 0.353935424452 L 0.566666666667 0.369805128355 L 0.575 0.385641337381 L 0.583333333333 0.401410902817 L 0.591666666667 0.417082932942 L 0.6 0.4326293192 L 0.608333333333 0.448024722349 L 0.616666666667 0.463246794008 L 0.625 0.478275138165 L 0.633333333333 0.493090341915 L 0.641666666667 0.507676232452 L 0.65 0.522041325423 L 0.658333333333 0.536401295159 L 0.666666666667 0.550844593615 L 0.675 0.565421677727 L 0.683333333333 0.580198055666 L 0.691666666667 0.595258150031 L 0.7 0.610706294803 L 0.708333333333 0.626667358442 L 0.716666666667 0.643276054324 L 0.725 0.66065384465 L 0.733333333333 0.678855644958 L 0.741666666667 0.697798860396 L 0.75 0.71721499193 L 0.758333333333 0.736690248362 L 0.766666666667 0.755795814951 L 0.775 0.774204843176 L 0.783333333333 0.791732522732 L 0.791666666667 0.808305909835 L 0.8 0.823921113596 L 0.808333333333 0.838609094968 L 0.816666666667 0.852414869183 L 0.825 0.865385279222 L 0.833333333333 0.877566835746 L 0.841666666667 0.889001244655 L 0.85 0.899725351699 L 0.858333333333 0.909772887147 L 0.866666666667 0.919172721118 L 0.875 0.927950539019 L 0.883333333333 0.936129852342 L 0.891666666667 0.943730807861 L 0.9 0.950771821528 L 0.908333333333 0.95726991079 L 0.916666666667 0.963271447844 L 0.925 0.968820243268 L 0.933333333333 0.973927263555 L 0.941666666667 0.978603045951 L 0.95 0.982857352297 L 0.958333333333 0.986698947476 L 0.966666666667 0.990136402522 L 0.975 0.993184062492 L 0.983333333333 0.995839116531 L 0.991666666667 0.998106161702 L 1.0 1.0 " />
diff --git a/core/res/res/interpolator/progress_indeterminate_horizontal_rect1_grp_scale.xml b/core/res/res/interpolator/progress_indeterminate_horizontal_rect1_grp_scale.xml
new file mode 100644
index 0000000..dc0e485
--- /dev/null
+++ b/core/res/res/interpolator/progress_indeterminate_horizontal_rect1_grp_scale.xml
@@ -0,0 +1,17 @@
+<!--
+ 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.
+-->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="M 0.0 0.0 L 0.366666666667 0.0 L 0.375 0.00607022199531 L 0.383333333333 0.0128313190317 L 0.391666666667 0.0203053863048 L 0.4 0.0285126230744 L 0.408333333333 0.0374704929422 L 0.416666666667 0.0471928710088 L 0.425 0.0576890073411 L 0.433333333333 0.0689623329923 L 0.441666666667 0.0810093447457 L 0.45 0.0938182996083 L 0.458333333333 0.107368099555 L 0.466666666667 0.121627281237 L 0.475 0.136553254984 L 0.483333333333 0.152092042392 L 0.491666666667 0.168178420646 L 0.5 0.184736670404 L 0.508333333333 0.201682058428 L 0.516666666667 0.218922661357 L 0.525 0.236361911116 L 0.533333333333 0.253901271529 L 0.541666666667 0.271443072385 L 0.55 0.288893107328 L 0.558333333333 0.306163048058 L 0.566666666667 0.323172254984 L 0.575 0.339849141772 L 0.583333333333 0.356131857619 L 0.591666666667 0.371968628391 L 0.6 0.387317389244 L 0.608333333333 0.402145469729 L 0.616666666667 0.416428517896 L 0.625 0.430149949228 L 0.633333333333 0.443299687056 L 0.641666666667 0.455873322838 L 0.65 0.467790610602 L 0.658333333333 0.478261214125 L 0.666666666667 0.486946515351 L 0.675 0.493642461739 L 0.683333333333 0.498097136568 L 0.691666666667 0.5 L 0.7 0.501026508147 L 0.708333333333 0.505424974058 L 0.716666666667 0.513673357225 L 0.725 0.526197764281 L 0.733333333333 0.543195110129 L 0.741666666667 0.564385504796 L 0.75 0.588845516061 L 0.758333333333 0.615150659843 L 0.766666666667 0.641819770802 L 0.775 0.667727568443 L 0.783333333333 0.692232321167 L 0.791666666667 0.715080485292 L 0.8 0.736255108924 L 0.808333333333 0.755857404851 L 0.816666666667 0.774035479111 L 0.825 0.790946989585 L 0.833333333333 0.806741984167 L 0.841666666667 0.821556051785 L 0.85 0.835508642948 L 0.858333333333 0.848703647061 L 0.866666666667 0.861230901301 L 0.875 0.873167948783 L 0.883333333333 0.884581809849 L 0.891666666667 0.895530464709 L 0.9 0.906064231101 L 0.908333333333 0.916226932039 L 0.916666666667 0.925949460993 L 0.925 0.935162278452 L 0.933333333333 0.943901111981 L 0.941666666667 0.952197936634 L 0.95 0.960081506342 L 0.958333333333 0.967577760656 L 0.966666666667 0.974710159318 L 0.975 0.981500003726 L 0.983333333333 0.987966699339 L 0.991666666667 0.994127959051 L 1.0 1.0 " />
diff --git a/core/res/res/interpolator/progress_indeterminate_horizontal_rect2_grp_position.xml b/core/res/res/interpolator/progress_indeterminate_horizontal_rect2_grp_position.xml
new file mode 100644
index 0000000..e2c463d
--- /dev/null
+++ b/core/res/res/interpolator/progress_indeterminate_horizontal_rect2_grp_position.xml
@@ -0,0 +1,17 @@
+<!--
+ 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.
+-->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="M 0.0 0.0 L 0.00833333333334 0.00229967744922 L 0.0166666666667 0.00521412430783 L 0.025 0.00874167982129 L 0.0333333333333 0.0128711540512 L 0.0416666666667 0.0175762490301 L 0.05 0.0228242656297 L 0.0583333333333 0.0285830529319 L 0.0666666666667 0.0348109630825 L 0.075 0.0414619464217 L 0.0833333333333 0.0484880345538 L 0.0916666666667 0.0558410655969 L 0.1 0.0634745223001 L 0.108333333333 0.0713444188538 L 0.116666666667 0.079410703663 L 0.125 0.0876382751487 L 0.133333333333 0.0959968850049 L 0.141666666667 0.104460460998 L 0.15 0.113007671299 L 0.158333333333 0.121621440773 L 0.166666666667 0.130288564002 L 0.175 0.138998350887 L 0.183333333333 0.147742658893 L 0.191666666667 0.156516005917 L 0.2 0.165314860841 L 0.208333333333 0.174136192385 L 0.216666666667 0.182978436537 L 0.225 0.191841222449 L 0.233333333333 0.200724646865 L 0.241666666667 0.209628467926 L 0.25 0.218553459576 L 0.258333333333 0.227500782731 L 0.266666666667 0.236470566383 L 0.275 0.245463519979 L 0.283333333333 0.254480675444 L 0.291666666667 0.263522016655 L 0.3 0.272587543612 L 0.308333333333 0.281677627163 L 0.316666666667 0.290791831964 L 0.325 0.299929045471 L 0.333333333333 0.309088509865 L 0.341666666667 0.318269435077 L 0.35 0.327474513787 L 0.358333333333 0.336748457377 L 0.366666666667 0.346105551561 L 0.375 0.355549440324 L 0.383333333333 0.365085073683 L 0.391666666667 0.374718256217 L 0.4 0.384454615142 L 0.408333333333 0.394301906021 L 0.416666666667 0.404268464874 L 0.425 0.414363869256 L 0.433333333333 0.424599921812 L 0.441666666667 0.434990214931 L 0.45 0.445549179441 L 0.458333333333 0.45629364862 L 0.466666666667 0.467242068132 L 0.475 0.478413609209 L 0.483333333333 0.489826169306 L 0.491666666667 0.501495178926 L 0.5 0.513430908951 L 0.508333333333 0.525634794401 L 0.516666666667 0.53809595169 L 0.525 0.550788614937 L 0.533333333333 0.563671442642 L 0.541666666667 0.576690097495 L 0.55 0.589782857472 L 0.558333333333 0.602885985073 L 0.566666666667 0.615938403227 L 0.575 0.628887306389 L 0.583333333333 0.641689563312 L 0.591666666667 0.654311104343 L 0.6 0.666726082982 L 0.608333333333 0.678916746891 L 0.616666666667 0.69086971329 L 0.625 0.702576630036 L 0.633333333333 0.714032144017 L 0.641666666667 0.725232143656 L 0.65 0.736175290675 L 0.658333333333 0.746879966241 L 0.666666666667 0.757365325464 L 0.675 0.767631174859 L 0.683333333333 0.77767703071 L 0.691666666667 0.787502199694 L 0.7 0.797107262267 L 0.708333333333 0.806492379668 L 0.716666666667 0.81565710043 L 0.725 0.82460216625 L 0.733333333333 0.833327480383 L 0.741666666667 0.841833333059 L 0.75 0.850119724279 L 0.758333333333 0.858187250623 L 0.766666666667 0.866036395807 L 0.775 0.873667014716 L 0.783333333333 0.88107965556 L 0.791666666667 0.888275060036 L 0.8 0.895253647364 L 0.808333333333 0.902015546533 L 0.816666666667 0.90856170885 L 0.825 0.914893101745 L 0.833333333333 0.921010096065 L 0.841666666667 0.926913352889 L 0.85 0.932604033131 L 0.858333333333 0.938083217089 L 0.866666666667 0.943351662581 L 0.875 0.94841012743 L 0.883333333333 0.953260127273 L 0.891666666667 0.957902806904 L 0.9 0.962339423981 L 0.908333333333 0.966571042677 L 0.916666666667 0.970598952899 L 0.925 0.974424621915 L 0.933333333333 0.978049533117 L 0.941666666667 0.981475153774 L 0.95 0.984702725421 L 0.958333333333 0.987733957184 L 0.966666666667 0.990574734261 L 0.975 0.993221525533 L 0.983333333333 0.995671735064 L 0.991666666667 0.997929361563 L 1.0 1.0 " />
diff --git a/core/res/res/interpolator/progress_indeterminate_horizontal_rect2_grp_scale.xml b/core/res/res/interpolator/progress_indeterminate_horizontal_rect2_grp_scale.xml
new file mode 100644
index 0000000..e19e3bd
--- /dev/null
+++ b/core/res/res/interpolator/progress_indeterminate_horizontal_rect2_grp_scale.xml
@@ -0,0 +1,17 @@
+<!--
+ 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.
+-->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="M 0.0 0.0 L 0.00833333333334 0.00574128947512 L 0.0166666666667 0.0126739914922 L 0.025 0.0207803148119 L 0.0333333333333 0.0300222867359 L 0.0416666666667 0.0403408876828 L 0.05 0.0516566104757 L 0.0583333333333 0.0638713854701 L 0.0666666666667 0.0768720363634 L 0.075 0.0905347780463 L 0.0833333333333 0.104730220757 L 0.0916666666667 0.1193286215 L 0.1 0.134204393671 L 0.108333333333 0.149240004408 L 0.116666666667 0.164328670953 L 0.125 0.179375985524 L 0.133333333333 0.194300633561 L 0.141666666667 0.209034228885 L 0.15 0.223520630773 L 0.158333333333 0.237714931359 L 0.166666666667 0.25158211334 L 0.175 0.265095825429 L 0.183333333333 0.278237040065 L 0.191666666667 0.290992875969 L 0.2 0.303355514884 L 0.208333333333 0.315321283173 L 0.216666666667 0.326889756956 L 0.225 0.33806322048 L 0.233333333333 0.348845959658 L 0.241666666667 0.35924381463 L 0.25 0.369263944281 L 0.258333333333 0.378914166866 L 0.266666666667 0.388203101304 L 0.275 0.397139649102 L 0.283333333333 0.40573308855 L 0.291666666667 0.413992650841 L 0.3 0.421927755558 L 0.308333333333 0.429547633895 L 0.316666666667 0.436861375749 L 0.325 0.44387807102 L 0.333333333333 0.450606385724 L 0.341666666667 0.457054891684 L 0.35 0.463219114597 L 0.358333333333 0.468983900047 L 0.366666666667 0.474313547811 L 0.375 0.47919783764 L 0.383333333333 0.483624100194 L 0.391666666667 0.487576651865 L 0.4 0.491036606388 L 0.408333333333 0.493981309661 L 0.416666666667 0.496384057166 L 0.425 0.498213340392 L 0.433333333333 0.499432658452 L 0.441666666667 0.5 L 0.45 0.500132156764 L 0.458333333333 0.501016702806 L 0.466666666667 0.502710909197 L 0.475 0.505274449001 L 0.483333333333 0.50876595913 L 0.491666666667 0.51323738859 L 0.5 0.518726651206 L 0.508333333333 0.525248535726 L 0.516666666667 0.532785286233 L 0.525 0.541279914244 L 0.533333333333 0.550635115456 L 0.541666666667 0.560719439572 L 0.55 0.571380006744 L 0.558333333333 0.582458709253 L 0.566666666667 0.593806906062 L 0.575 0.605296114045 L 0.583333333333 0.61682262358 L 0.591666666667 0.628307922435 L 0.6 0.639696058281 L 0.608333333333 0.65094958827 L 0.616666666667 0.662045528618 L 0.625 0.67297172806 L 0.633333333333 0.6837236181 L 0.641666666667 0.694302070048 L 0.65 0.704711440462 L 0.658333333333 0.714905644026 L 0.666666666667 0.724841350655 L 0.675 0.734529345772 L 0.683333333333 0.743980697388 L 0.691666666667 0.753206332221 L 0.7 0.762216965048 L 0.708333333333 0.771022839665 L 0.716666666667 0.779633823089 L 0.725 0.788059240706 L 0.733333333333 0.796307899828 L 0.741666666667 0.804388136787 L 0.75 0.812307746289 L 0.758333333333 0.820074122707 L 0.766666666667 0.827694118788 L 0.775 0.835174210498 L 0.783333333333 0.842520520564 L 0.791666666667 0.849738700738 L 0.8 0.856834167281 L 0.808333333333 0.863811912571 L 0.816666666667 0.870676681725 L 0.825 0.877432925497 L 0.833333333333 0.884084847374 L 0.841666666667 0.890636403584 L 0.85 0.897091314861 L 0.858333333333 0.90345309 L 0.866666666667 0.909725084729 L 0.875 0.915910419285 L 0.883333333333 0.92201207261 L 0.891666666667 0.928032882355 L 0.9 0.933975497778 L 0.908333333333 0.939842485715 L 0.916666666667 0.945636236386 L 0.925 0.951359045815 L 0.933333333333 0.95701309228 L 0.941666666667 0.962600459864 L 0.95 0.968123109018 L 0.958333333333 0.973582941322 L 0.966666666667 0.978981746494 L 0.975 0.984321249498 L 0.983333333333 0.989603092873 L 0.991666666667 0.994828842625 L 1.0 1.0 " />
diff --git a/core/res/res/layout-sw600dp/date_picker_holo.xml b/core/res/res/layout-sw600dp/date_picker_holo.xml
deleted file mode 100644
index e5c886b..0000000
--- a/core/res/res/layout-sw600dp/date_picker_holo.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:layout_width="wrap_content"
-              android:layout_height="match_parent"
-              android:gravity="center"
-              android:orientation="vertical" >
-
-    <include
-        layout="@layout/date_picker_selected_date"
-        android:layout_width="wrap_content"
-        android:layout_height="@dimen/datepicker_selected_calendar_layout_height" />
-
-    <include layout="@layout/date_picker_view_animator" />
-
-</LinearLayout>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index f9ea5d8..08aaa6a 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2513,6 +2513,19 @@
                  result to valid color values. Saturate(S + D) -->
             <enum name="add" value="16" />
         </attr>
+
+        <!-- ViewOutlineProvider used to determine the View's Outline. -->
+        <attr name="outlineProvider">
+            <!-- Default, background drawable-driven outline. -->
+            <enum name="background" value="0" />
+            <!-- No outline provider. -->
+            <enum name="none" value="1" />
+            <!-- Generates an opaque outline for the bounds of the view. -->
+            <enum name="bounds" value="2" />
+            <!-- Generates an opaque outline for the padded bounds of the view. -->
+            <enum name="paddedBounds" value="3" />
+        </attr>
+
     </declare-styleable>
 
     <!-- Attributes that can be assigned to a tag for a particular View. -->
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index d170fd4..e58bc6f 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -374,7 +374,6 @@
     <dimen name="datepicker_year_label_height">64dp</dimen>
     <dimen name="datepicker_year_label_text_size">22dp</dimen>
     <dimen name="datepicker_component_width">270dp</dimen>
-    <dimen name="datepicker_selected_calendar_layout_height">155dp</dimen>
     <dimen name="datepicker_selected_date_day_size">75dp</dimen>
     <dimen name="datepicker_selected_date_month_size">30dp</dimen>
     <dimen name="datepicker_selected_date_year_size">30dp</dimen>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 7ade51d..ed66c65 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2272,6 +2272,7 @@
   <public type="attr" name="inset" />
   <public type="attr" name="letterSpacing" />
   <public type="attr" name="fontFeatureSettings" />
+  <public type="attr" name="outlineProvider" />
 
   <public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
 
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 00c92fa..4dcbc40 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -17,11 +17,15 @@
 import android.animation.Animator;
 import android.animation.AnimatorInflater;
 import android.animation.ValueAnimator;
+import android.annotation.NonNull;
+import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
+import android.graphics.Outline;
+import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -129,7 +133,6 @@
 
     private final AnimatedVectorDrawableState mAnimatedVectorState;
 
-
     public AnimatedVectorDrawable() {
         mAnimatedVectorState = new AnimatedVectorDrawableState(
                 new AnimatedVectorDrawableState(null));
@@ -163,6 +166,16 @@
     }
 
     @Override
+    protected boolean onStateChange(int[] state) {
+        return mAnimatedVectorState.mVectorDrawable.setState(state);
+    }
+
+    @Override
+    protected boolean onLevelChange(int level) {
+        return mAnimatedVectorState.mVectorDrawable.setLevel(level);
+    }
+
+    @Override
     public int getAlpha() {
         return mAnimatedVectorState.mVectorDrawable.getAlpha();
     }
@@ -178,6 +191,43 @@
     }
 
     @Override
+    public void setTintList(ColorStateList tint) {
+        mAnimatedVectorState.mVectorDrawable.setTintList(tint);
+    }
+
+    @Override
+    public void setHotspot(float x, float y) {
+        mAnimatedVectorState.mVectorDrawable.setHotspot(x, y);
+    }
+
+    @Override
+    public void setHotspotBounds(int left, int top, int right, int bottom) {
+        mAnimatedVectorState.mVectorDrawable.setHotspotBounds(left, top, right, bottom);
+    }
+
+    @Override
+    public void setTintMode(PorterDuff.Mode tintMode) {
+        mAnimatedVectorState.mVectorDrawable.setTintMode(tintMode);
+    }
+
+    @Override
+    public boolean setVisible(boolean visible, boolean restart) {
+        mAnimatedVectorState.mVectorDrawable.setVisible(visible, restart);
+        return super.setVisible(visible, restart);
+    }
+
+    /** {@hide} */
+    @Override
+    public void setLayoutDirection(int layoutDirection) {
+        mAnimatedVectorState.mVectorDrawable.setLayoutDirection(layoutDirection);
+    }
+
+    @Override
+    public boolean isStateful() {
+        return mAnimatedVectorState.mVectorDrawable.isStateful();
+    }
+
+    @Override
     public int getOpacity() {
         return mAnimatedVectorState.mVectorDrawable.getOpacity();
     }
@@ -193,6 +243,11 @@
     }
 
     @Override
+    public void getOutline(@NonNull Outline outline) {
+        mAnimatedVectorState.mVectorDrawable.getOutline(outline);
+    }
+
+    @Override
     public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
             throws XmlPullParserException, IOException {
 
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index e52d778..715da7e 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -81,14 +81,14 @@
     private static final int TILE_MODE_REPEAT = 1;
     private static final int TILE_MODE_MIRROR = 2;
 
-    private final Rect mDstRect = new Rect();   // Gravity.apply() sets this
+    private final Rect mDstRect = new Rect();   // #updateDstRectAndInsetsIfDirty() sets this
 
     private BitmapState mBitmapState;
     private PorterDuffColorFilter mTintFilter;
 
     private int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
 
-    private boolean mApplyGravity;
+    private boolean mDstRectAndInsetsDirty = true;
     private boolean mMutated;
 
      // These are scaled to match the target density.
@@ -96,7 +96,7 @@
     private int mBitmapHeight;
 
     /** Optical insets due to gravity. */
-    private Insets mOpticalInsets = null;
+    private Insets mOpticalInsets = Insets.NONE;
 
     // Mirroring matrix for using with Shaders
     private Matrix mMirrorMatrix;
@@ -285,7 +285,7 @@
     public void setGravity(int gravity) {
         if (mBitmapState.mGravity != gravity) {
             mBitmapState.mGravity = gravity;
-            mApplyGravity = true;
+            mDstRectAndInsetsDirty = true;
             invalidateSelf();
         }
     }
@@ -428,6 +428,7 @@
             state.mTileModeX = xmode;
             state.mTileModeY = ymode;
             state.mRebuildShader = true;
+            mDstRectAndInsetsDirty = true;
             invalidateSelf();
         }
     }
@@ -464,7 +465,7 @@
 
     @Override
     protected void onBoundsChange(Rect bounds) {
-        mApplyGravity = true;
+        mDstRectAndInsetsDirty = true;
 
         final Shader shader = mBitmapState.mPaint.getShader();
         if (shader != null) {
@@ -503,7 +504,6 @@
             }
 
             state.mRebuildShader = false;
-            copyBounds(mDstRect);
         }
 
         final int restoreAlpha;
@@ -523,14 +523,10 @@
             clearColorFilter = false;
         }
 
+        updateDstRectAndInsetsIfDirty();
         final Shader shader = paint.getShader();
         final boolean needMirroring = needMirroring();
         if (shader == null) {
-            if (mApplyGravity) {
-                applyGravity();
-                mApplyGravity = false;
-            }
-
             if (needMirroring) {
                 canvas.save();
                 // Mirror the bitmap
@@ -544,11 +540,6 @@
                 canvas.restore();
             }
         } else {
-            if (mApplyGravity) {
-                copyBounds(mDstRect);
-                mApplyGravity = false;
-            }
-
             if (needMirroring) {
                 // Mirror the bitmap
                 updateMirrorMatrix(mDstRect.right - mDstRect.left);
@@ -574,39 +565,46 @@
         }
     }
 
+    private void updateDstRectAndInsetsIfDirty() {
+        if (mDstRectAndInsetsDirty) {
+            if (mBitmapState.mTileModeX == null && mBitmapState.mTileModeY == null) {
+                final Rect bounds = getBounds();
+                final int layoutDirection = getLayoutDirection();
+                Gravity.apply(mBitmapState.mGravity, mBitmapWidth, mBitmapHeight,
+                        bounds, mDstRect, layoutDirection);
+
+                final int left = mDstRect.left - bounds.left;
+                final int top = mDstRect.top - bounds.top;
+                final int right = bounds.right - mDstRect.right;
+                final int bottom = bounds.bottom - mDstRect.bottom;
+                mOpticalInsets = Insets.of(left, top, right, bottom);
+            } else {
+                copyBounds(mDstRect);
+                mOpticalInsets = Insets.NONE;
+            }
+        }
+        mDstRectAndInsetsDirty = false;
+    }
+
     /**
      * @hide
      */
     @Override
     public Insets getOpticalInsets() {
-        if (mApplyGravity && mBitmapState.mPaint.getShader() == null) {
-            applyGravity();
-            mApplyGravity = false;
-        }
-        return mOpticalInsets == null ? Insets.NONE : mOpticalInsets;
-    }
-
-    private void applyGravity() {
-        final Rect bounds = getBounds();
-        final int layoutDirection = getLayoutDirection();
-        Gravity.apply(mBitmapState.mGravity, mBitmapWidth, mBitmapHeight,
-                bounds, mDstRect, layoutDirection);
-
-        final int left = mDstRect.left - bounds.left;
-        final int top = mDstRect.top - bounds.top;
-        final int right = bounds.right - mDstRect.right;
-        final int bottom = bounds.bottom - mDstRect.bottom;
-        mOpticalInsets = Insets.of(left, top, right, bottom);
+        updateDstRectAndInsetsIfDirty();
+        return mOpticalInsets;
     }
 
     @Override
     public void getOutline(@NonNull Outline outline) {
-        super.getOutline(outline);
-        if (mBitmapState.mBitmap == null || mBitmapState.mBitmap.hasAlpha()) {
-            // Only opaque Bitmaps can report a non-0 alpha,
-            // since only they are guaranteed to fill their bounds
-            outline.setAlpha(0.0f);
-        }
+        updateDstRectAndInsetsIfDirty();
+        outline.setRect(mDstRect);
+
+        // Only opaque Bitmaps can report a non-0 alpha,
+        // since only they are guaranteed to fill their bounds
+        boolean opaqueOverShape = mBitmapState.mBitmap != null
+                && !mBitmapState.mBitmap.hasAlpha();
+        outline.setAlpha(opaqueOverShape ? getAlpha() / 255.0f : 0.0f);
     }
 
     @Override
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index e673b0d..5922135 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -244,6 +244,29 @@
     thread.renderState().invokeFunctor(functor, mode, NULL);
 }
 
+void CanvasContext::buildLayer(RenderNode* node) {
+    ATRACE_CALL();
+    if (!mEglManager.hasEglContext() || !mCanvas) {
+        return;
+    }
+    requireGlContext();
+    // buildLayer() will leave the tree in an unknown state, so we must stop drawing
+    stopDrawing();
+
+    TreeInfo info(TreeInfo::MODE_FULL, mRenderThread.renderState());
+    info.frameTimeMs = mRenderThread.timeLord().frameTimeMs();
+    info.damageAccumulator = &mDamageAccumulator;
+    info.renderer = mCanvas;
+    node->prepareTree(info);
+    SkRect ignore;
+    mDamageAccumulator.finish(&ignore);
+    // Tickle the GENERIC property on node to mark it as dirty for damaging
+    // purposes when the frame is actually drawn
+    node->setPropertyFieldsDirty(RenderNode::GENERIC);
+
+    mCanvas->flushLayerUpdates();
+}
+
 bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
     requireGlContext();
     layer->apply();
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 2a01027..0cbed6f 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -65,6 +65,7 @@
     // IFrameCallback, Chroreographer-driven frame callback entry point
     virtual void doFrame();
 
+    void buildLayer(RenderNode* node);
     bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
 
     void destroyHardwareResources();
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index d9b96f6c..405ce24 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -284,6 +284,18 @@
     return layer;
 }
 
+CREATE_BRIDGE2(buildLayer, CanvasContext* context, RenderNode* node) {
+    args->context->buildLayer(args->node);
+    return NULL;
+}
+
+void RenderProxy::buildLayer(RenderNode* node) {
+    SETUP_TASK(buildLayer);
+    args->context = mContext;
+    args->node = node;
+    postAndWait(task);
+}
+
 CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* layer,
         SkBitmap* bitmap) {
     bool success = args->context->copyLayerInto(args->layer, args->bitmap);
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 28d0173..eea3674 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -81,6 +81,7 @@
     static void enqueueDestroyLayer(Layer* layer);
     ANDROID_API DeferredLayerUpdater* createDisplayListLayer(int width, int height);
     ANDROID_API DeferredLayerUpdater* createTextureLayer();
+    ANDROID_API void buildLayer(RenderNode* node);
     ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
     ANDROID_API void pushLayerUpdate(DeferredLayerUpdater* layer);
     ANDROID_API void cancelLayerUpdate(DeferredLayerUpdater* layer);
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 7cda961..6a4bf07 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -190,14 +190,6 @@
 
             final int mainType = mCurAudioRoutesInfo.mMainType;
 
-            boolean a2dpEnabled;
-            try {
-                a2dpEnabled = mAudioService.isBluetoothA2dpOn();
-            } catch (RemoteException e) {
-                Log.e(TAG, "Error querying Bluetooth A2DP state", e);
-                a2dpEnabled = false;
-            }
-
             if (!TextUtils.equals(newRoutes.mBluetoothName, mCurAudioRoutesInfo.mBluetoothName)) {
                 mCurAudioRoutesInfo.mBluetoothName = newRoutes.mBluetoothName;
                 if (mCurAudioRoutesInfo.mBluetoothName != null) {
@@ -220,6 +212,7 @@
             }
 
             if (mBluetoothA2dpRoute != null) {
+                final boolean a2dpEnabled = isBluetoothA2dpOn();
                 if (mainType != AudioRoutesInfo.MAIN_SPEAKER &&
                         mSelectedRoute == mBluetoothA2dpRoute && !a2dpEnabled) {
                     selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mDefaultAudioVideo, false);
@@ -230,6 +223,15 @@
             }
         }
 
+        boolean isBluetoothA2dpOn() {
+            try {
+                return mAudioService.isBluetoothA2dpOn();
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error querying Bluetooth A2DP state", e);
+                return false;
+            }
+        }
+
         void updateDiscoveryRequest() {
             // What are we looking for today?
             int routeTypes = 0;
@@ -950,7 +952,7 @@
     static void selectDefaultRouteStatic() {
         // TODO: Be smarter about the route types here; this selects for all valid.
         if (sStatic.mSelectedRoute != sStatic.mBluetoothA2dpRoute
-                && sStatic.mBluetoothA2dpRoute != null) {
+                && sStatic.mBluetoothA2dpRoute != null && sStatic.isBluetoothA2dpOn()) {
             selectRouteStatic(ROUTE_TYPE_ANY, sStatic.mBluetoothA2dpRoute, false);
         } else {
             selectRouteStatic(ROUTE_TYPE_ANY, sStatic.mDefaultAudioVideo, false);
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 2ec0293..d7baaa9 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -247,14 +247,14 @@
     }
 
     /**
-     * Get the current audio info for this session.
+     * Get the current playback info for this session.
      *
-     * @return The current audio info or null.
+     * @return The current playback info or null.
      */
-    public @Nullable AudioInfo getAudioInfo() {
+    public @Nullable PlaybackInfo getPlaybackInfo() {
         try {
             ParcelableVolumeInfo result = mSessionBinder.getVolumeAttributes();
-            return new AudioInfo(result.volumeType, result.audioAttrs, result.controlType,
+            return new PlaybackInfo(result.volumeType, result.audioAttrs, result.controlType,
                     result.maxVolume, result.currentVolume);
 
         } catch (RemoteException e) {
@@ -269,7 +269,7 @@
      *
      * @return A {@link PendingIntent} to launch UI or null.
      */
-    public @Nullable PendingIntent getLaunchActivity() {
+    public @Nullable PendingIntent getSessionActivity() {
         try {
             return mSessionBinder.getLaunchPendingIntent();
         } catch (RemoteException e) {
@@ -293,9 +293,10 @@
      * {@link VolumeProvider#VOLUME_CONTROL_ABSOLUTE}. The flags in
      * {@link AudioManager} may be used to affect the handling.
      *
-     * @see #getAudioInfo()
+     * @see #getPlaybackInfo()
      * @param value The value to set it to, between 0 and the reported max.
-     * @param flags Any flags to pass with the command.
+     * @param flags Flags from {@link AudioManager} to include with the volume
+     *            request.
      */
     public void setVolumeTo(int value, int flags) {
         try {
@@ -314,7 +315,7 @@
      * {@link VolumeProvider#VOLUME_CONTROL_ABSOLUTE}. The flags in
      * {@link AudioManager} may be used to affect the handling.
      *
-     * @see #getAudioInfo()
+     * @see #getPlaybackInfo()
      * @param direction The direction to adjust the volume in.
      * @param flags Any flags to pass with the command.
      */
@@ -565,7 +566,7 @@
          *
          * @param info The current audio info for this session.
          */
-        public void onAudioInfoChanged(AudioInfo info) {
+        public void onAudioInfoChanged(PlaybackInfo info) {
         }
     }
 
@@ -773,9 +774,19 @@
     }
 
     /**
-     * Holds information about the way audio is handled for this session.
+     * Holds information about the current playback and how audio is handled for
+     * this session.
      */
-    public static final class AudioInfo {
+    public static final class PlaybackInfo {
+        /**
+         * The session uses remote playback.
+         */
+        public static final int PLAYBACK_TYPE_REMOTE = 2;
+        /**
+         * The session uses local playback.
+         */
+        public static final int PLAYBACK_TYPE_LOCAL = 1;
+
         private final int mVolumeType;
         private final int mVolumeControl;
         private final int mMaxVolume;
@@ -785,7 +796,7 @@
         /**
          * @hide
          */
-        public AudioInfo(int type, AudioAttributes attrs, int control, int max, int current) {
+        public PlaybackInfo(int type, AudioAttributes attrs, int control, int max, int current) {
             mVolumeType = type;
             mAudioAttrs = attrs;
             mVolumeControl = control;
@@ -794,22 +805,22 @@
         }
 
         /**
-         * Get the type of volume handling, either local or remote. One of:
+         * Get the type of playback which affects volume handling. One of:
          * <ul>
-         * <li>{@link MediaSession#PLAYBACK_TYPE_LOCAL}</li>
-         * <li>{@link MediaSession#PLAYBACK_TYPE_REMOTE}</li>
+         * <li>{@link #PLAYBACK_TYPE_LOCAL}</li>
+         * <li>{@link #PLAYBACK_TYPE_REMOTE}</li>
          * </ul>
          *
-         * @return The type of volume handling this session is using.
+         * @return The type of playback this session is using.
          */
-        public int getVolumeType() {
+        public int getPlaybackType() {
             return mVolumeType;
         }
 
         /**
          * Get the audio attributes for this session. The attributes will affect
          * volume handling for the session. When the volume type is
-         * {@link MediaSession#PLAYBACK_TYPE_REMOTE} these may be ignored by the
+         * {@link PlaybackInfo#PLAYBACK_TYPE_REMOTE} these may be ignored by the
          * remote volume handler.
          *
          * @return The attributes for this session.
@@ -920,7 +931,7 @@
         public void onVolumeInfoChanged(ParcelableVolumeInfo pvi) {
             MediaController controller = mController.get();
             if (controller != null) {
-                AudioInfo info = new AudioInfo(pvi.volumeType, pvi.audioAttrs, pvi.controlType,
+                PlaybackInfo info = new PlaybackInfo(pvi.volumeType, pvi.audioAttrs, pvi.controlType,
                         pvi.maxVolume, pvi.currentVolume);
                 controller.postMessage(MSG_UPDATE_VOLUME, info, null);
             }
@@ -958,7 +969,7 @@
                     mCallback.onExtrasChanged((Bundle) msg.obj);
                     break;
                 case MSG_UPDATE_VOLUME:
-                    mCallback.onAudioInfoChanged((AudioInfo) msg.obj);
+                    mCallback.onAudioInfoChanged((PlaybackInfo) msg.obj);
                     break;
                 case MSG_DESTROYED:
                     mCallback.onSessionDestroyed();
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index de725fc..eac6809 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -101,16 +101,6 @@
             FLAG_EXCLUSIVE_GLOBAL_PRIORITY })
     public @interface SessionFlags { }
 
-    /**
-     * The session uses local playback.
-     */
-    public static final int PLAYBACK_TYPE_LOCAL = 1;
-
-    /**
-     * The session uses remote playback.
-     */
-    public static final int PLAYBACK_TYPE_REMOTE = 2;
-
     private final Object mLock = new Object();
 
     private final MediaSession.Token mSessionToken;
@@ -215,7 +205,7 @@
      *
      * @param pi The intent to launch to show UI for this Session.
      */
-    public void setLaunchActivity(@Nullable PendingIntent pi) {
+    public void setSessionActivity(@Nullable PendingIntent pi) {
         try {
             mBinder.setLaunchPendingIntent(pi);
         } catch (RemoteException e) {
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 8a1e076..185c6d8 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -148,8 +148,29 @@
     public void addOnActiveSessionsChangedListener(
             @NonNull OnActiveSessionsChangedListener sessionListener,
             @Nullable ComponentName notificationListener) {
+        addOnActiveSessionsChangedListener(sessionListener, notificationListener, null);
+    }
+
+    /**
+     * Add a listener to be notified when the list of active sessions
+     * changes.This requires the
+     * android.Manifest.permission.MEDIA_CONTENT_CONTROL permission be held by
+     * the calling app. You may also retrieve this list if your app is an
+     * enabled notification listener using the
+     * {@link NotificationListenerService} APIs, in which case you must pass the
+     * {@link ComponentName} of your enabled listener. Updates will be posted to
+     * the handler specified or to the caller's thread if the handler is null.
+     *
+     * @param sessionListener The listener to add.
+     * @param notificationListener The enabled notification listener component.
+     *            May be null.
+     * @param handler The handler to post events to.
+     */
+    public void addOnActiveSessionsChangedListener(
+            @NonNull OnActiveSessionsChangedListener sessionListener,
+            @Nullable ComponentName notificationListener, @Nullable Handler handler) {
         addOnActiveSessionsChangedListener(sessionListener, notificationListener,
-                UserHandle.myUserId(), null);
+                UserHandle.myUserId(), handler);
     }
 
     /**
diff --git a/media/java/android/media/session/ParcelableVolumeInfo.java b/media/java/android/media/session/ParcelableVolumeInfo.java
index 96a45d9b..f59c975 100644
--- a/media/java/android/media/session/ParcelableVolumeInfo.java
+++ b/media/java/android/media/session/ParcelableVolumeInfo.java
@@ -21,7 +21,7 @@
 
 /**
  * Convenience class for passing information about the audio configuration of a
- * session. The public implementation is {@link MediaController.AudioInfo}.
+ * session. The public implementation is {@link MediaController.PlaybackInfo}.
  *
  * @hide
  */
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index 566e218..2ca97dd 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -217,7 +217,7 @@
 
     private final int mState;
     private final long mPosition;
-    private final long mBufferPosition;
+    private final long mBufferedPosition;
     private final float mSpeed;
     private final long mActions;
     private List<PlaybackState.CustomAction> mCustomActions;
@@ -226,14 +226,14 @@
     private final long mActiveItemId;
 
     private PlaybackState(int state, long position, long updateTime, float speed,
-            long bufferPosition, long transportControls,
+            long bufferedPosition, long transportControls,
             List<PlaybackState.CustomAction> customActions, long activeItemId,
             CharSequence error) {
         mState = state;
         mPosition = position;
         mSpeed = speed;
         mUpdateTime = updateTime;
-        mBufferPosition = bufferPosition;
+        mBufferedPosition = bufferedPosition;
         mActions = transportControls;
         mCustomActions = new ArrayList<>(customActions);
         mActiveItemId = activeItemId;
@@ -245,7 +245,7 @@
         mPosition = in.readLong();
         mSpeed = in.readFloat();
         mUpdateTime = in.readLong();
-        mBufferPosition = in.readLong();
+        mBufferedPosition = in.readLong();
         mActions = in.readLong();
         mCustomActions = in.createTypedArrayList(CustomAction.CREATOR);
         mActiveItemId = in.readLong();
@@ -258,7 +258,7 @@
         StringBuilder bob = new StringBuilder("PlaybackState {");
         bob.append("state=").append(mState);
         bob.append(", position=").append(mPosition);
-        bob.append(", buffered position=").append(mBufferPosition);
+        bob.append(", buffered position=").append(mBufferedPosition);
         bob.append(", speed=").append(mSpeed);
         bob.append(", updated=").append(mUpdateTime);
         bob.append(", actions=").append(mActions);
@@ -280,7 +280,7 @@
         dest.writeLong(mPosition);
         dest.writeFloat(mSpeed);
         dest.writeLong(mUpdateTime);
-        dest.writeLong(mBufferPosition);
+        dest.writeLong(mBufferedPosition);
         dest.writeLong(mActions);
         dest.writeTypedList(mCustomActions);
         dest.writeLong(mActiveItemId);
@@ -310,12 +310,12 @@
     }
 
     /**
-     * Get the current buffer position in ms. This is the farthest playback
+     * Get the current buffered position in ms. This is the farthest playback
      * point that can be reached from the current position using only buffered
      * content.
      */
-    public long getBufferPosition() {
-        return mBufferPosition;
+    public long getBufferedPosition() {
+        return mBufferedPosition;
     }
 
     /**
@@ -711,7 +711,7 @@
 
         private int mState;
         private long mPosition;
-        private long mBufferPosition;
+        private long mBufferedPosition;
         private float mSpeed;
         private long mActions;
         private CharSequence mErrorMessage;
@@ -736,7 +736,7 @@
             }
             mState = from.mState;
             mPosition = from.mPosition;
-            mBufferPosition = from.mBufferPosition;
+            mBufferedPosition = from.mBufferedPosition;
             mSpeed = from.mSpeed;
             mActions = from.mActions;
             if (from.mCustomActions != null) {
@@ -889,15 +889,16 @@
         }
 
         /**
-         * Set the current buffer position in ms. This is the farthest playback
-         * point that can be reached from the current position using only
-         * buffered content.
+         * Set the current buffered position in ms. This is the farthest
+         * playback point that can be reached from the current position using
+         * only buffered content.
          *
-         * @param bufferPosition The position in ms that playback is buffered to.
+         * @param bufferedPosition The position in ms that playback is buffered
+         *            to.
          * @return this
          */
-        public Builder setBufferPosition(long bufferPosition) {
-            mBufferPosition = bufferPosition;
+        public Builder setBufferedPosition(long bufferedPosition) {
+            mBufferedPosition = bufferedPosition;
             return this;
         }
 
@@ -931,7 +932,7 @@
          * @return A new state instance.
          */
         public PlaybackState build() {
-            return new PlaybackState(mState, mPosition, mUpdateTime, mSpeed, mBufferPosition,
+            return new PlaybackState(mState, mPosition, mUpdateTime, mSpeed, mBufferedPosition,
                     mActions, mCustomActions, mActiveItemId, mErrorMessage);
         }
     }
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index 4c225c1..fae30e5 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -30,7 +30,6 @@
 import android.content.pm.PackageParser.PackageParserException;
 import android.content.res.ObbInfo;
 import android.content.res.ObbScanner;
-import android.os.Build;
 import android.os.Environment;
 import android.os.Environment.UserEnvironment;
 import android.os.FileUtils;
@@ -67,7 +66,6 @@
  */
 public class DefaultContainerService extends IntentService {
     private static final String TAG = "DefContainer";
-    private static final boolean localLOGV = false;
 
     private static final String LIB_DIR_NAME = "lib";
 
@@ -112,7 +110,7 @@
                 return copyPackageToContainerInner(pkg, handle, containerId, key, isExternal,
                         isForwardLocked, abiOverride);
             } catch (PackageParserException | IOException e) {
-                Slog.w(TAG, "Failed to parse package at " + packagePath);
+                Slog.w(TAG, "Failed to copy package at " + packagePath, e);
                 return null;
             } finally {
                 IoUtils.closeQuietly(handle);
@@ -188,7 +186,7 @@
             ret.installLocation = pkg.installLocation;
             ret.verifiers = pkg.verifiers;
             ret.recommendedInstallLocation = PackageHelper.resolveInstallLocation(context,
-                    pkg.installLocation, sizeBytes, flags);
+                    pkg.packageName, pkg.installLocation, sizeBytes, flags);
             ret.multiArch = pkg.multiArch;
 
             return ret;
@@ -313,161 +311,73 @@
 
     private String copyPackageToContainerInner(PackageLite pkg, NativeLibraryHelper.Handle handle,
             String newCid, String key, boolean isExternal, boolean isForwardLocked,
-            String abiOverride) {
-        // TODO: extend to support copying all split APKs
-        if (!ArrayUtils.isEmpty(pkg.splitNames)) {
-            throw new UnsupportedOperationException("Copying split APKs not yet supported");
-        }
+            String abiOverride) throws IOException {
 
-        final String resFileName = "pkg.apk";
-        final String publicResFileName = "res.zip";
-
-        if (pkg.multiArch) {
-            // TODO: Support multiArch installs on ASEC.
-            throw new IllegalArgumentException("multiArch not supported on ASEC installs.");
-        }
-
-        // The .apk file
-        final String codePath = pkg.baseCodePath;
-        final File codeFile = new File(codePath);
-        final String[] abis;
-        try {
-            abis = calculateAbiList(handle, abiOverride, pkg.multiArch);
-        } catch (IOException ioe) {
-            Slog.w(TAG, "Problem determining app ABIS: " + ioe);
-            return null;
-        }
-
-        // Calculate size of container needed to hold base APK. Round up to
-        // nearest MB, and tack on an extra MB for filesystem overhead.
-        final int sizeMb;
-        try {
-            final long sizeBytes = calculateInstalledSizeInner(pkg, handle, isForwardLocked, abis);
-            sizeMb = ((int) ((sizeBytes + MB_IN_BYTES) / MB_IN_BYTES)) + 1;
-        } catch (IOException e) {
-            Slog.w(TAG, "Problem when trying to copy " + codeFile.getPath());
-            return null;
-        }
+        // Calculate container size, rounding up to nearest MB and adding an
+        // extra MB for filesystem overhead
+        final long sizeBytes = calculateInstalledSizeInner(pkg, handle, isForwardLocked,
+                abiOverride);
+        final int sizeMb = ((int) ((sizeBytes + MB_IN_BYTES) / MB_IN_BYTES)) + 1;
 
         // Create new container
-        final String newCachePath = PackageHelper.createSdDir(sizeMb, newCid, key, Process.myUid(),
+        final String newMountPath = PackageHelper.createSdDir(sizeMb, newCid, key, Process.myUid(),
                 isExternal);
-        if (newCachePath == null) {
-            Slog.e(TAG, "Failed to create container " + newCid);
-            return null;
+        if (newMountPath == null) {
+            throw new IOException("Failed to create container " + newCid);
         }
-
-        if (localLOGV) {
-            Slog.i(TAG, "Created container for " + newCid + " at path : " + newCachePath);
-        }
-
-        final File resFile = new File(newCachePath, resFileName);
-        if (FileUtils.copyFile(new File(codePath), resFile)) {
-            if (localLOGV) {
-                Slog.i(TAG, "Copied " + codePath + " to " + resFile);
-            }
-        } else {
-            Slog.e(TAG, "Failed to copy " + codePath + " to " + resFile);
-            // Clean up container
-            PackageHelper.destroySdDir(newCid);
-            return null;
-        }
+        final File targetDir = new File(newMountPath);
 
         try {
-            Os.chmod(resFile.getAbsolutePath(), 0640);
+            // Copy all APKs
+            copyFile(pkg.baseCodePath, targetDir, "base.apk", isForwardLocked);
+            if (!ArrayUtils.isEmpty(pkg.splitNames)) {
+                for (int i = 0; i < pkg.splitNames.length; i++) {
+                    copyFile(pkg.splitCodePaths[i], targetDir,
+                            "split_" + pkg.splitNames[i] + ".apk", isForwardLocked);
+                }
+            }
+
+            // Extract native code
+            final File libraryRoot = new File(targetDir, LIB_DIR_NAME);
+            final int res = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle, libraryRoot,
+                    abiOverride, pkg.multiArch);
+            if (res != PackageManager.INSTALL_SUCCEEDED) {
+                throw new IOException("Failed to extract native code, res=" + res);
+            }
+
+            if (!PackageHelper.finalizeSdDir(newCid)) {
+                throw new IOException("Failed to finalize " + newCid);
+            }
+
+            if (PackageHelper.isContainerMounted(newCid)) {
+                PackageHelper.unMountSdDir(newCid);
+            }
+
         } catch (ErrnoException e) {
-            Slog.e(TAG, "Could not chown APK: " + e.getMessage());
             PackageHelper.destroySdDir(newCid);
-            return null;
-        }
-
-        if (isForwardLocked) {
-            File publicZipFile = new File(newCachePath, publicResFileName);
-            try {
-                PackageHelper.extractPublicFiles(resFile.getAbsolutePath(), publicZipFile);
-                if (localLOGV) {
-                    Slog.i(TAG, "Copied resources to " + publicZipFile);
-                }
-            } catch (IOException e) {
-                Slog.e(TAG, "Could not chown public APK " + publicZipFile.getAbsolutePath() + ": "
-                        + e.getMessage());
-                PackageHelper.destroySdDir(newCid);
-                return null;
-            }
-
-            try {
-                Os.chmod(publicZipFile.getAbsolutePath(), 0644);
-            } catch (ErrnoException e) {
-                Slog.e(TAG, "Could not chown public resource file: " + e.getMessage());
-                PackageHelper.destroySdDir(newCid);
-                return null;
-            }
-        }
-
-        final File sharedLibraryDir = new File(newCachePath, LIB_DIR_NAME);
-        if (sharedLibraryDir.mkdir()) {
-            int ret = PackageManager.INSTALL_SUCCEEDED;
-            if (abis != null) {
-                // TODO(multiArch): Support multi-arch installs on asecs. Note that we are NOT
-                // using an ISA specific subdir here for now.
-                final String abi = abis[0];
-                ret = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
-                        sharedLibraryDir, abi);
-
-                if (ret != PackageManager.INSTALL_SUCCEEDED) {
-                    Slog.e(TAG, "Could not copy native libraries to " + sharedLibraryDir.getPath());
-                    PackageHelper.destroySdDir(newCid);
-                    return null;
-                }
-            }
-        } else {
-            Slog.e(TAG, "Could not create native lib directory: " + sharedLibraryDir.getPath());
+            throw e.rethrowAsIOException();
+        } catch (IOException e) {
             PackageHelper.destroySdDir(newCid);
-            return null;
+            throw e;
         }
 
-        if (!PackageHelper.finalizeSdDir(newCid)) {
-            Slog.e(TAG, "Failed to finalize " + newCid + " at path " + newCachePath);
-            // Clean up container
-            PackageHelper.destroySdDir(newCid);
-            return null;
-        }
-
-        if (localLOGV) {
-            Slog.i(TAG, "Finalized container " + newCid);
-        }
-
-        if (PackageHelper.isContainerMounted(newCid)) {
-            if (localLOGV) {
-                Slog.i(TAG, "Unmounting " + newCid + " at path " + newCachePath);
-            }
-
-            // Force a gc to avoid being killed.
-            Runtime.getRuntime().gc();
-            PackageHelper.unMountSdDir(newCid);
-        } else {
-            if (localLOGV) {
-                Slog.i(TAG, "Container " + newCid + " not mounted");
-            }
-        }
-
-        return newCachePath;
+        return newMountPath;
     }
 
     private int copyPackageInner(PackageLite pkg, IParcelFileDescriptorFactory target)
             throws IOException, RemoteException {
-        copyFile(pkg.baseCodePath, "base.apk", target);
+        copyFile(pkg.baseCodePath, target, "base.apk");
         if (!ArrayUtils.isEmpty(pkg.splitNames)) {
             for (int i = 0; i < pkg.splitNames.length; i++) {
-                copyFile(pkg.splitCodePaths[i], "split_" + pkg.splitNames[i] + ".apk", target);
+                copyFile(pkg.splitCodePaths[i], target, "split_" + pkg.splitNames[i] + ".apk");
             }
         }
 
         return PackageManager.INSTALL_SUCCEEDED;
     }
 
-    private void copyFile(String sourcePath, String targetName,
-            IParcelFileDescriptorFactory target) throws IOException, RemoteException {
+    private void copyFile(String sourcePath, IParcelFileDescriptorFactory target, String targetName)
+            throws IOException, RemoteException {
         Slog.d(TAG, "Copying " + sourcePath + " to " + targetName);
         InputStream in = null;
         OutputStream out = null;
@@ -482,76 +392,58 @@
         }
     }
 
+    private void copyFile(String sourcePath, File targetDir, String targetName,
+            boolean isForwardLocked) throws IOException, ErrnoException {
+        final File sourceFile = new File(sourcePath);
+        final File targetFile = new File(targetDir, targetName);
+
+        Slog.d(TAG, "Copying " + sourceFile + " to " + targetFile);
+        if (!FileUtils.copyFile(sourceFile, targetFile)) {
+            throw new IOException("Failed to copy " + sourceFile + " to " + targetFile);
+        }
+
+        if (isForwardLocked) {
+            final String publicTargetName = PackageHelper.replaceEnd(targetName,
+                    ".apk", ".zip");
+            final File publicTargetFile = new File(targetDir, publicTargetName);
+
+            PackageHelper.extractPublicFiles(sourceFile, publicTargetFile);
+
+            Os.chmod(targetFile.getAbsolutePath(), 0640);
+            Os.chmod(publicTargetFile.getAbsolutePath(), 0644);
+        } else {
+            Os.chmod(targetFile.getAbsolutePath(), 0644);
+        }
+    }
+
     private long calculateInstalledSizeInner(PackageLite pkg, boolean isForwardLocked,
             String abiOverride) throws IOException {
         NativeLibraryHelper.Handle handle = null;
         try {
             handle = NativeLibraryHelper.Handle.create(pkg);
-            return calculateInstalledSizeInner(pkg, handle, isForwardLocked,
-                    calculateAbiList(handle, abiOverride, pkg.multiArch));
+            return calculateInstalledSizeInner(pkg, handle, isForwardLocked, abiOverride);
         } finally {
             IoUtils.closeQuietly(handle);
         }
     }
 
     private long calculateInstalledSizeInner(PackageLite pkg, NativeLibraryHelper.Handle handle,
-            boolean isForwardLocked, String[] abis) throws IOException {
+            boolean isForwardLocked, String abiOverride) throws IOException {
         long sizeBytes = 0;
 
         // Include raw APKs, and possibly unpacked resources
         for (String codePath : pkg.getAllCodePaths()) {
-            sizeBytes += new File(codePath).length();
+            final File codeFile = new File(codePath);
+            sizeBytes += codeFile.length();
 
             if (isForwardLocked) {
-                sizeBytes += PackageHelper.extractPublicFiles(codePath, null);
+                sizeBytes += PackageHelper.extractPublicFiles(codeFile, null);
             }
         }
 
         // Include all relevant native code
-        if (!ArrayUtils.isEmpty(abis)) {
-            sizeBytes += NativeLibraryHelper.sumNativeBinariesLI(handle, abis);
-        }
+        sizeBytes += NativeLibraryHelper.sumNativeBinaries(handle, abiOverride, pkg.multiArch);
 
         return sizeBytes;
     }
-
-    private String[] calculateAbiList(NativeLibraryHelper.Handle handle, String abiOverride,
-                                      boolean isMultiArch) throws IOException {
-        if (isMultiArch) {
-            final int abi32 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS);
-            final int abi64 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS);
-
-            if (abi32 >= 0 && abi64 >= 0) {
-                return new String[] { Build.SUPPORTED_64_BIT_ABIS[abi64], Build.SUPPORTED_32_BIT_ABIS[abi32] };
-            } else if (abi64 >= 0) {
-                return new String[] { Build.SUPPORTED_64_BIT_ABIS[abi64] };
-            } else if (abi32 >= 0) {
-                return new String[] { Build.SUPPORTED_32_BIT_ABIS[abi32] };
-            }
-
-            if (abi64 != PackageManager.NO_NATIVE_LIBRARIES || abi32 != PackageManager.NO_NATIVE_LIBRARIES) {
-                throw new IOException("Error determining ABI list: errorCode=[" + abi32 + "," + abi64 + "]");
-            }
-
-        } else {
-            String[] abiList = Build.SUPPORTED_ABIS;
-            if (abiOverride != null) {
-                abiList = new String[] { abiOverride };
-            } else if (Build.SUPPORTED_64_BIT_ABIS.length > 0 &&
-                    NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
-                abiList = Build.SUPPORTED_32_BIT_ABIS;
-            }
-
-            final int abi = NativeLibraryHelper.findSupportedAbi(handle,abiList);
-            if (abi >= 0) {
-               return new String[]{Build.SUPPORTED_ABIS[abi]};
-            }
-
-            if (abi != PackageManager.NO_NATIVE_LIBRARIES) {
-                throw new IOException("Error determining ABI list: errorCode=" + abi);
-            }
-        }
-
-        return null;
-    }
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 0d79ee2..dc12cc7 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -218,7 +218,7 @@
                     handleFingerprintProcessed(msg.arg1);
                     break;
                 case MSG_FACE_UNLOCK_STATE_CHANGED:
-                    handleFaceUnlockStateChanged(msg.arg1 != 0);
+                    handleFaceUnlockStateChanged(msg.arg1 != 0, msg.arg2);
                     break;
             }
         }
@@ -227,6 +227,7 @@
     private SparseBooleanArray mUserHasTrust = new SparseBooleanArray();
     private SparseBooleanArray mUserTrustIsManaged = new SparseBooleanArray();
     private SparseBooleanArray mUserFingerprintRecognized = new SparseBooleanArray();
+    private SparseBooleanArray mUserFaceUnlockRunning = new SparseBooleanArray();
 
     @Override
     public void onTrustChanged(boolean enabled, int userId, boolean initiatedByUser) {
@@ -297,15 +298,20 @@
         }
     }
 
-    private void handleFaceUnlockStateChanged(boolean running) {
+    private void handleFaceUnlockStateChanged(boolean running, int userId) {
+        mUserFaceUnlockRunning.put(userId, running);
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
-                cb.onFaceUnlockStateChanged(running);
+                cb.onFaceUnlockStateChanged(running, userId);
             }
         }
     }
 
+    public boolean isFaceUnlockRunning(int userId) {
+        return mUserFaceUnlockRunning.get(userId);
+    }
+
     private boolean isTrustDisabled(int userId) {
         final DevicePolicyManager dpm =
                 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
@@ -398,9 +404,11 @@
             } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
                 dispatchBootCompleted();
             } else if (ACTION_FACE_UNLOCK_STARTED.equals(action)) {
-                mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 1, 0));
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 1,
+                        getSendingUserId()));
             } else if (ACTION_FACE_UNLOCK_STOPPED.equals(action)) {
-                mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 0, 0));
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 0,
+                        getSendingUserId()));
             }
         }
     };
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 0acb9d0..33cab8f 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -197,5 +197,5 @@
     /**
      * Called when the state of face unlock changed.
      */
-    public void onFaceUnlockStateChanged(boolean running) { }
+    public void onFaceUnlockStateChanged(boolean running, int userId) { }
 }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 13301fb..edefb13 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -70,7 +70,7 @@
     // database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
     // is properly propagated through your change.  Not doing so will result in a loss of user
     // settings.
-    private static final int DATABASE_VERSION = 107;
+    private static final int DATABASE_VERSION = 108;
 
     private Context mContext;
     private int mUserHandle;
@@ -1714,6 +1714,25 @@
             upgradeVersion = 107;
         }
 
+        if (upgradeVersion < 108) {
+            // Reset the auto-brightness setting to default since the behavior
+            // of the feature is now quite different and is being presented to
+            // the user in a new way as "adaptive brightness".
+            db.beginTransaction();
+            SQLiteStatement stmt = null;
+            try {
+                stmt = db.compileStatement("INSERT OR REPLACE INTO system(name,value)"
+                        + " VALUES(?,?);");
+                loadBooleanSetting(stmt, Settings.System.SCREEN_BRIGHTNESS_MODE,
+                        R.bool.def_screen_brightness_automatic_mode);
+                db.setTransactionSuccessful();
+            } finally {
+                db.endTransaction();
+                if (stmt != null) stmt.close();
+            }
+            upgradeVersion = 108;
+        }
+
         // *** Remember to update DATABASE_VERSION above!
 
         if (upgradeVersion != currentVersion) {
diff --git a/core/res/res/anim/progress_indeterminate_horizontal_rect1_scale.xml b/packages/SystemUI/res/anim/progress_indeterminate_horizontal_rect1_scale.xml
similarity index 100%
rename from core/res/res/anim/progress_indeterminate_horizontal_rect1_scale.xml
rename to packages/SystemUI/res/anim/progress_indeterminate_horizontal_rect1_scale.xml
diff --git a/core/res/res/anim/progress_indeterminate_horizontal_rect1_translate.xml b/packages/SystemUI/res/anim/progress_indeterminate_horizontal_rect1_translate.xml
similarity index 100%
rename from core/res/res/anim/progress_indeterminate_horizontal_rect1_translate.xml
rename to packages/SystemUI/res/anim/progress_indeterminate_horizontal_rect1_translate.xml
diff --git a/core/res/res/anim/progress_indeterminate_horizontal_rect2_scale.xml b/packages/SystemUI/res/anim/progress_indeterminate_horizontal_rect2_scale.xml
similarity index 100%
rename from core/res/res/anim/progress_indeterminate_horizontal_rect2_scale.xml
rename to packages/SystemUI/res/anim/progress_indeterminate_horizontal_rect2_scale.xml
diff --git a/core/res/res/anim/progress_indeterminate_horizontal_rect2_translate.xml b/packages/SystemUI/res/anim/progress_indeterminate_horizontal_rect2_translate.xml
similarity index 100%
rename from core/res/res/anim/progress_indeterminate_horizontal_rect2_translate.xml
rename to packages/SystemUI/res/anim/progress_indeterminate_horizontal_rect2_translate.xml
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png
index b28624f..5be74ec 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime.png
index 9ce434d..305c9fb 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_land.png
index 51dce69..3e676ab 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png
index 3f3e288..d3e1f7a 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_land.png
index 9856cbf..d632600 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png
index 6910456..8984a49d 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_land.png
index e8c6ec6..2e8f8f0 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent.png
index 06dcd20..ec499d4 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_land.png
index 240f536..13e8a4f 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back.png
index e464347..c697da7 100644
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_land.png
index f8b59e8..94404df 100644
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back.png
index 1b578a6..9d0014d 100644
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_land.png
index 80ecaba..9a8b0e9 100644
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back.png
index c7bf2c7..80d60af 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back_land.png
index 278de42..2dfe964 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back.png
index 464831c..fd1cc27 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back_land.png
index c24132c..183aa0d 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back.png
index bc84f22..6f763a4 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back_land.png
index f4e219e..3dc75a3 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back.png
index ece2e37..83040fd 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back_land.png
index d524dcf..9917be4 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back.png
index 373e84a..c116bbe 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_land.png
index e5a102a..1446850 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back.png
index 6b19593..83040fd 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_land.png
index a5e0686..9917be4 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png
index f878093..447c655 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime.png
index 7780b16..d5ca622 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_land.png
index 343d0dd..47985de 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png
index 8e9583b..7b5fe8b 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_land.png
index 7d38703..9fcb705 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png
index 6e186a3..23c24ba 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_land.png
index 12b4042..41c1acb 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.png
index e2a89c3..11a92f0 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_land.png
index 311720b..7fb14a8 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back.png
index 67e4ee7..eaac305 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_ime.png
index dfef430..b5d3739 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_land.png
index de6d109..9915260 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home.png
index 7d0c3fbe..4a349e2 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home_land.png
index 3baeb52..d14da80 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu.png
index d5b48e8..4f5e723 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu_land.png
index 26d7e7b..05b9b44 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent.png
index c49198d..2035323 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent_land.png
index 2a21f29..69b541b 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back.png
index 538d7d1..3f2b8b4 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_ime.png
index eb8e80b..23e5e8f 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_land.png
index 1c2c35a..4b7f3ac 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home.png
index eec613f..41054f6 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home_land.png
index 1c0bad8..e4a7181 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu.png
index 1293fa8..be678e0 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu_land.png
index 96a9cce..24d37e0 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent.png
index 9ffc80a..9443656 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent_land.png
index aa9b57b..c3c64f4 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back.png
index b343522..0ab43ce 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_ime.png
index f2f7b50..3c58211 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_land.png
index 383398c..14ff6d3 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home.png
index 53444ab..eb74d0d 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home_land.png
index 4294937..e29c9d0 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu.png
index 7cb3ee4..cfecdcf 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu_land.png
index b017946..d98208a 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent.png
index e8dd07c..71cc61b 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent_land.png
index f396ea9..bdecf06 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back.png
index 1b817cf..01edd86 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_ime.png
index 21b7a06..52bd6e8 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_land.png
index 676fc14..b0dd0f0 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home.png
index 26f4ba9..b5c189d 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home_land.png
index ea21b60..42e9e31 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu.png
index c7d77c2..669d8ba 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu_land.png
index ae12cfd..0fbf1f6 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent.png
index 8c27d45..023b94c 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent_land.png
index c98827c..5884492 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
index ec2951d..4956aad 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime.png
index 5103190..e9a6223 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png
index 818aa4f..e9767a1 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
index 254f757..acaf32d 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png
index f0de417..20cb101 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
index 97f1526..cc620a2 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png
index 773fa94..aa8a60e 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
index 8a8e941..88d6a41 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png
index ad7dfc3..8acdd3c 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back.png
index 77969b8..01edd86 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime.png
index b171f92..52bd6e8 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_land.png
index ad35c65..b0dd0f0 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home.png
index d60229f..b5c189d 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_land.png
index 8fffa8e..42e9e31 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu.png
index 9215055..669d8ba 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_land.png
index bcf7eb1..0fbf1f6 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent.png
index a261f85..023b94c 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_land.png
index 4c612f7..5884492 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/indeterminate_anim.xml b/packages/SystemUI/res/drawable/indeterminate_anim.xml
index 52c6d16..13b1ccf 100644
--- a/packages/SystemUI/res/drawable/indeterminate_anim.xml
+++ b/packages/SystemUI/res/drawable/indeterminate_anim.xml
@@ -18,15 +18,15 @@
 
     <target
         android:name="path1"
-        android:animation="@*android:anim/progress_indeterminate_horizontal_rect1_translate" />
+        android:animation="@anim/progress_indeterminate_horizontal_rect1_translate" />
     <target
         android:name="path1"
-        android:animation="@*android:anim/progress_indeterminate_horizontal_rect1_scale" />
+        android:animation="@anim/progress_indeterminate_horizontal_rect1_scale" />
 
     <target
         android:name="path2"
-        android:animation="@*android:anim/progress_indeterminate_horizontal_rect2_translate" />
+        android:animation="@anim/progress_indeterminate_horizontal_rect2_translate" />
     <target
         android:name="path2"
-        android:animation="@*android:anim/progress_indeterminate_horizontal_rect2_scale" />
+        android:animation="@anim/progress_indeterminate_horizontal_rect2_scale" />
 </animated-vector>
diff --git a/packages/SystemUI/res/drawable/trust_circle.xml b/packages/SystemUI/res/drawable/trust_circle.xml
deleted file mode 100644
index 56fc62e..0000000
--- a/packages/SystemUI/res/drawable/trust_circle.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?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
-  -->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="ring"
-        android:innerRadius="22dp" android:thickness="2dp">
-    <solid android:color="#4cffffff" />
-</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 8e9b501..ca07c87 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -31,7 +31,7 @@
         android:layout_gravity="bottom|center_horizontal"
         android:textStyle="italic"
         android:textColor="#ffffff"
-        android:textAppearance="?android:attr/textAppearanceSmall"/>
+        android:textAppearance="?android:attr/textAppearanceSmall" />
 
     <FrameLayout
         android:id="@+id/preview_container"
@@ -66,6 +66,7 @@
         android:layout_gravity="bottom|center_horizontal"
         android:src="@drawable/ic_lock_24dp"
         android:scaleType="center"
-        android:tint="#ffffffff" />
+        android:tint="#ffffffff"
+        android:contentDescription="@string/accessibility_unlock_button" />
 
 </com.android.systemui.statusbar.phone.KeyguardBottomAreaView>
diff --git a/packages/SystemUI/res/layout/volume_panel.xml b/packages/SystemUI/res/layout/volume_panel.xml
index c85a750..4d8aaa7 100644
--- a/packages/SystemUI/res/layout/volume_panel.xml
+++ b/packages/SystemUI/res/layout/volume_panel.xml
@@ -25,7 +25,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:background="@color/system_secondary_color"
-        android:paddingTop="12dp"
+        android:paddingTop="8dp"
         android:paddingLeft="8dp"
         android:paddingRight="8dp"
         android:clipChildren="false" />
diff --git a/packages/SystemUI/res/layout/zen_mode_panel.xml b/packages/SystemUI/res/layout/zen_mode_panel.xml
index 9d5f7bd..3949d7d 100644
--- a/packages/SystemUI/res/layout/zen_mode_panel.xml
+++ b/packages/SystemUI/res/layout/zen_mode_panel.xml
@@ -35,8 +35,8 @@
             android:layout_height="wrap_content"
             android:layout_marginLeft="@dimen/qs_panel_padding"
             android:layout_marginRight="@dimen/qs_panel_padding"
-            android:layout_marginTop="8dp"
-            android:layout_marginBottom="12dp"
+            android:layout_marginTop="4dp"
+            android:layout_marginBottom="8dp"
             android:clipChildren="false" />
     </FrameLayout>
 
diff --git a/packages/SystemUI/res/values/arrays.xml b/packages/SystemUI/res/values/arrays.xml
index 630a48d..6102aa6 100644
--- a/packages/SystemUI/res/values/arrays.xml
+++ b/packages/SystemUI/res/values/arrays.xml
@@ -25,7 +25,7 @@
         <item>100</item>
     </array>
     <array name="batterymeter_color_values">
-        <item>#FFFF3300</item>
+        <item>@*android:color/battery_saver_mode_color</item>
         <item>#FFFFFFFF</item>
     </array>
     <array name="batterymeter_bolt_points">
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index c6b3222..42d9734 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -92,7 +92,7 @@
 
     <!-- The default tiles to display in QuickSettings -->
     <string name="quick_settings_tiles_default" translatable="false">
-        wifi,bt,inversion,cell,airplane,rotation,flashlight,location,cast
+        wifi,bt,inversion,cell,airplane,rotation,flashlight,location,cast,hotspot
     </string>
 
     <!-- The tiles to display in QuickSettings -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 1b8eeb2..c8db284 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -430,4 +430,16 @@
 
     <!-- The text size for battery level -->
     <dimen name="battery_level_text_size">12sp</dimen>
+
+    <!-- TrustDrawable: Minimum inner radius of the breathing animation -->
+    <dimen name="trust_circle_inner_radius_visible_min">22dp</dimen>
+    <!-- TrustDrawable: Maximum inner radius of the breathing animation -->
+    <dimen name="trust_circle_inner_radius_visible_max">24dp</dimen>
+    <!-- TrustDrawable: Inner radius at the end of the exit animation -->
+    <dimen name="trust_circle_inner_radius_exit">38dp</dimen>
+    <!-- TrustDrawable: Inner radius at the beginning of the enter animation -->
+    <dimen name="trust_circle_inner_radius_enter">18dp</dimen>
+    <!-- TrustDrawable: Thickness of the circle -->
+    <dimen name="trust_circle_thickness">2dp</dimen>
+
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index d49312d..ed3fa58 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -213,6 +213,14 @@
     <string name="accessibility_camera_button">Camera</string>
     <!-- Content description of the phone button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_phone_button">Phone</string>
+    <!-- Content description of the unlock button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_unlock_button">Unlock</string>
+    <!-- Click action label for accessibility for the unlock button. [CHAR LIMIT=NONE] -->
+    <string name="unlock_label">unlock</string>
+    <!-- Click action label for accessibility for the phone button. [CHAR LIMIT=NONE] -->
+    <string name="phone_label">open phone</string>
+    <!-- Click action label for accessibility for the phone button. [CHAR LIMIT=NONE] -->
+    <string name="camera_label">open camera</string>
 
     <!-- Content description of the switch input method button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_ime_switch_button">Switch input method button.</string>
@@ -306,15 +314,6 @@
     <!-- Content description of an item with full signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_signal_full">Signal full.</string>
 
-    <!-- Content description of an item that is turned on for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_desc_on">On.</string>
-    <!-- Content description of an item that is turned off for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_desc_off">Off.</string>
-    <!-- Content description of an item that is connected for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_desc_connected">Connected.</string>
-    <!-- Content description of an item that is connecting for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_desc_connecting">Connecting.</string>
-
     <!-- Content description of the data connection type GPRS for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_data_connection_gprs">GPRS</string>
 
@@ -408,24 +407,68 @@
     <string name="accessibility_quick_settings_user">User <xliff:g id="user" example="John Doe">%s</xliff:g>.</string>
     <!-- Content description of the wifi tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_quick_settings_wifi"><xliff:g id="signal" example="Three bars">%1$s</xliff:g>.</string>
+    <!-- Announcement made when the wifi is turned off (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_wifi_changed_off">Wifi turned off.</string>
+    <!-- Announcement made when the wifi is turned on (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_wifi_changed_on">Wifi turned on.</string>
     <!-- Content description of the mobile data tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_quick_settings_mobile">Mobile <xliff:g id="signal" example="Three bars">%1$s</xliff:g>. <xliff:g id="type" example="4G">%2$s</xliff:g>. <xliff:g id="network" example="T-Mobile">%3$s</xliff:g>.</string>
     <!-- Content description of the battery tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_quick_settings_battery">Battery <xliff:g id="state" example="50% charging">%s</xliff:g>.</string>
-    <!-- Content description of the airplane mode tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_quick_settings_airplane">Airplane Mode <xliff:g id="state" example="Off">%s</xliff:g>.</string>
-    <!-- Content description of the bluetooth tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_quick_settings_bluetooth">Bluetooth <xliff:g id="state" example="Off">%s</xliff:g>.</string>
-    <!-- Content description of the location tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_quick_settings_location">Location <xliff:g id="state" example="Off">%s</xliff:g>.</string>
+    <!-- Content description of the airplane mode tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_airplane_off">Airplane mode off.</string>
+    <!-- Content description of the airplane mode tile in quick settings when on (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_airplane_on">Airplane mode on.</string>
+    <!-- Announcement made when the airplane mode changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_airplane_changed_off">Airplane mode turned off.</string>
+    <!-- Announcement made when the airplane mode changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_airplane_changed_on">Airplane mode turned on.</string>
+    <!-- Content description of the bluetooth tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_bluetooth_off">Bluetooth off.</string>
+    <!-- Content description of the bluetooth tile in quick settings when on (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_bluetooth_on">Bluetooth on.</string>
+    <!-- Content description of the bluetooth tile in quick settings when connecting (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_bluetooth_connecting">Bluetooth connecting.</string>
+    <!-- Content description of the bluetooth tile in quick settings when connected (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_bluetooth_connected">Bluetooth connected.</string>
+    <!-- Announcement made when the bluetooth is turned off (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_bluetooth_changed_off">Bluetooth turned off.</string>
+    <!-- Announcement made when the bluetooth is turned on (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_bluetooth_changed_on">Bluetooth turned on.</string>
+    <!-- Content description of the location tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_location_off">Location reporting off.</string>
+    <!-- Content description of the location tile in quick settings when on (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_location_on">Location reporting on.</string>
+    <!-- Announcement made when the location tile changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_location_changed_off">Location reporting turned off.</string>
+    <!-- Announcement made when the location tile changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_location_changed_on">Location reporting turned on.</string>
     <!-- Content description of the alarm tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_quick_settings_alarm">Alarm set for <xliff:g id="time" example="Wed 3:30 PM">%s</xliff:g>.</string>
     <!-- Content description of quick settings detail panel close button (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_quick_settings_close">Close panel</string>
+    <string name="accessibility_quick_settings_close">Close panel.</string>
     <!-- Content description of zen mode time condition plus button (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_quick_settings_more_time">More time</string>
+    <string name="accessibility_quick_settings_more_time">More time.</string>
     <!-- Content description of zen mode time condition minus button (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_quick_settings_less_time">Less time</string>
+    <string name="accessibility_quick_settings_less_time">Less time.</string>
+    <!-- Content description of the flashlight tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_flashlight_off">Flashlight off.</string>
+    <!-- Content description of the flashlight tile in quick settings when on (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_flashlight_on">Flashlight on.</string>
+    <!-- Announcement made when the flashlight state changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_flashlight_changed_off">Flashlight turned off.</string>
+    <!-- Announcement made when the flashlight state changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_flashlight_changed_on">Flashlight turned on.</string>
+    <!-- Announcement made when the color inversion state changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_color_inversion_changed_off">Color inversion turned off.</string>
+    <!-- Announcement made when the color inversion state changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_color_inversion_changed_on">Color inversion turned on.</string>
+    <!-- Announcement made when the hotspot state changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_hotspot_changed_off">Mobile hotspot turned off.</string>
+    <!-- Announcement made when the hotspot state changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_hotspot_changed_on">Mobile hotspot turned on.</string>
+    <!-- Announcement made when the screen stopped casting (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_casting_turned_off">Screen casting stopped.</string>
 
     <!-- Content description of the display brightness slider (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_brightness">Display brightness</string>
@@ -480,6 +523,15 @@
     <!-- Description of the button in the phone-style notification panel that controls auto-rotation, when auto-rotation is off. [CHAR LIMIT=NONE] -->
     <string name="accessibility_rotation_lock_on_portrait">Screen is locked in portrait orientation.</string>
 
+    <!-- Announcement made when the screen is rotating automatically again (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_rotation_lock_off_changed">Screen will now rotate automatically.</string>
+
+    <!-- Announcement made when the rotation lock state changes to landscape only (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_rotation_lock_on_landscape_changed">Screen is now locked in landscape orientation.</string>
+
+    <!-- Announcement made when the rotation lock state changes to portrait only (not shown on the screen).  [CHAR LIMIT=NONE] -->
+    <string name="accessibility_rotation_lock_on_portrait_changed">Screen is now locked in portrait orientation.</string>
+
     <!-- Name of the K-release easter egg: a display case for all our tastiest desserts. [CHAR LIMIT=30] -->
     <string name="dessert_case">Dessert Case</string>
 
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index b9ffdbb..5e2f784 100755
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -33,7 +33,10 @@
 import android.util.AttributeSet;
 import android.view.View;
 
-public class BatteryMeterView extends View implements DemoMode {
+import com.android.systemui.statusbar.policy.BatteryController;
+
+public class BatteryMeterView extends View implements DemoMode,
+        BatteryController.BatteryStateChangeCallback {
     public static final String TAG = BatteryMeterView.class.getSimpleName();
     public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST";
 
@@ -68,6 +71,9 @@
     private final Path mClipPath = new Path();
     private final Path mTextPath = new Path();
 
+    private BatteryController mBatteryController;
+    private boolean mPowerSaveEnabled;
+
     private class BatteryTracker extends BroadcastReceiver {
         public static final int UNKNOWN_LEVEL = -1;
 
@@ -155,6 +161,7 @@
             // preload the battery level
             mTracker.onReceive(getContext(), sticky);
         }
+        mBatteryController.addStateChangedCallback(this);
     }
 
     @Override
@@ -162,6 +169,7 @@
         super.onDetachedFromWindow();
 
         getContext().unregisterReceiver(mTracker);
+        mBatteryController.removeStateChangedCallback(this);
     }
 
     public BatteryMeterView(Context context) {
@@ -227,6 +235,22 @@
         mBoltPoints = loadBoltPoints(res);
     }
 
+    public void setBatteryController(BatteryController batteryController) {
+        mBatteryController = batteryController;
+        mPowerSaveEnabled = mBatteryController.isPowerSave();
+    }
+
+    @Override
+    public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
+        // TODO: Use this callback instead of own broadcast receiver.
+    }
+
+    @Override
+    public void onPowerSaveChanged() {
+        mPowerSaveEnabled = mBatteryController.isPowerSave();
+        invalidate();
+    }
+
     private static float[] loadBoltPoints(Resources res) {
         final int[] pts = res.getIntArray(R.array.batterymeter_bolt_points);
         int maxX = 0, maxY = 0;
@@ -251,6 +275,11 @@
     }
 
     private int getColorForLevel(int percent) {
+
+        // If we are in power save mode, always use the normal color.
+        if (mPowerSaveEnabled) {
+            return mColors[mColors.length-1];
+        }
         int thresh, color = 0;
         for (int i=0; i<mColors.length; i+=2) {
             thresh = mColors[i];
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java
index 9c1ff9d..eb4560d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java
@@ -46,7 +46,11 @@
         r = (int) Math.max(r, Math.ceil(Math.sqrt(w * w + y * y)));
         r = (int) Math.max(r, Math.ceil(Math.sqrt(w * w + h * h)));
         r = (int) Math.max(r, Math.ceil(Math.sqrt(x * x + h * h)));
-        mAnimator = ViewAnimationUtils.createCircularReveal(mDetail, x, y, 0, r);
+        if (in) {
+            mAnimator = ViewAnimationUtils.createCircularReveal(mDetail, x, y, 0, r);
+        } else {
+            mAnimator = ViewAnimationUtils.createCircularReveal(mDetail, x, y, r, 0);
+        }
         mAnimator.setDuration((long)(mAnimator.getDuration() * 1.5));
         if (listener != null) {
             mAnimator.addListener(listener);
@@ -55,12 +59,11 @@
         if (in) {
             mBackground.startTransition((int)(mAnimator.getDuration() * 0.6));
             mAnimator.addListener(mVisibleOnStart);
-            mAnimator.start();
         } else {
             mDetail.postDelayed(mReverseBackground, (long)(mAnimator.getDuration() * 0.65));
             mAnimator.addListener(mGoneOnEnd);
-            mAnimator.reverse();
         }
+        mAnimator.start();
     }
 
     private final Runnable mReverseBackground = new Runnable() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index bf01b7b..c1fd509 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -239,6 +239,11 @@
                     fireScanStateChanged(r.scanState);
                 }
             }
+
+            @Override
+            public void onAnnouncementRequested(CharSequence announcement) {
+                announceForAccessibility(announcement);
+            }
         };
         r.tile.setCallback(callback);
         final View.OnClickListener click = new View.OnClickListener() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 409cc46..876652c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -60,6 +60,7 @@
     private Callback mCallback;
     protected final TState mState = newTileState();
     private final TState mTmpState = newTileState();
+    private boolean mAnnounceNextStateChange;
 
     abstract protected TState newTileState();
     abstract protected void handleClick();
@@ -161,9 +162,25 @@
     }
 
     private void handleStateChanged() {
+        boolean delayAnnouncement = shouldAnnouncementBeDelayed();
         if (mCallback != null) {
             mCallback.onStateChanged(mState);
+            if (mAnnounceNextStateChange && !delayAnnouncement) {
+                String announcement = composeChangeAnnouncement();
+                if (announcement != null) {
+                    mCallback.onAnnouncementRequested(announcement);
+                }
+            }
         }
+        mAnnounceNextStateChange = mAnnounceNextStateChange && delayAnnouncement;
+    }
+
+    protected boolean shouldAnnouncementBeDelayed() {
+        return false;
+    }
+
+    protected String composeChangeAnnouncement() {
+        return null;
     }
 
     private void handleShowDetail(boolean show) {
@@ -217,6 +234,7 @@
                     handleSetCallback((QSTile.Callback)msg.obj);
                 } else if (msg.what == CLICK) {
                     name = "handleClick";
+                    mAnnounceNextStateChange = true;
                     handleClick();
                 } else if (msg.what == SECONDARY_CLICK) {
                     name = "handleSecondaryClick";
@@ -255,6 +273,7 @@
         void onShowDetail(boolean show);
         void onToggleStateChanged(boolean state);
         void onScanStateChanged(boolean state);
+        void onAnnouncementRequested(CharSequence announcement);
     }
 
     public interface Host {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index 5d1fa80..51401c8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -70,13 +70,20 @@
         if (airplaneMode) {
             state.iconId =  R.drawable.ic_qs_airplane_on;
             state.contentDescription =  mContext.getString(
-                    R.string.accessibility_quick_settings_airplane,
-                    mContext.getString(R.string.accessibility_desc_on));
+                    R.string.accessibility_quick_settings_airplane_on);
         } else {
             state.iconId = R.drawable.ic_qs_airplane_off;
             state.contentDescription =  mContext.getString(
-                    R.string.accessibility_quick_settings_airplane,
-                    mContext.getString(R.string.accessibility_desc_off));
+                    R.string.accessibility_quick_settings_airplane_off);
+        }
+    }
+
+    @Override
+    protected String composeChangeAnnouncement() {
+        if (mState.value) {
+            return mContext.getString(R.string.accessibility_quick_settings_airplane_changed_on);
+        } else {
+            return mContext.getString(R.string.accessibility_quick_settings_airplane_changed_off);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 19b9ec1..63c880f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -88,21 +88,22 @@
         final boolean connecting = mController.isBluetoothConnecting();
         state.visible = supported;
         state.value = enabled;
-        final String stateContentDescription;
         if (enabled) {
             state.label = null;
             if (connected) {
                 state.iconId = R.drawable.ic_qs_bluetooth_connected;
-                stateContentDescription = mContext.getString(R.string.accessibility_desc_connected);
+                state.contentDescription = mContext.getString(
+                        R.string.accessibility_quick_settings_bluetooth_connected);
                 state.label = mController.getLastDeviceName();
             } else if (connecting) {
                 state.iconId = R.drawable.ic_qs_bluetooth_connecting;
-                stateContentDescription =
-                        mContext.getString(R.string.accessibility_desc_connecting);
+                state.contentDescription = mContext.getString(
+                        R.string.accessibility_quick_settings_bluetooth_connecting);
                 state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
             } else {
                 state.iconId = R.drawable.ic_qs_bluetooth_on;
-                stateContentDescription = mContext.getString(R.string.accessibility_desc_on);
+                state.contentDescription = mContext.getString(
+                        R.string.accessibility_quick_settings_bluetooth_on);
             }
             if (TextUtils.isEmpty(state.label)) {
                 state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
@@ -110,10 +111,10 @@
         } else {
             state.iconId = R.drawable.ic_qs_bluetooth_off;
             state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
-            stateContentDescription = mContext.getString(R.string.accessibility_desc_off);
+            state.contentDescription = mContext.getString(
+                    R.string.accessibility_quick_settings_bluetooth_off);
         }
-        state.contentDescription = mContext.getString(
-                R.string.accessibility_quick_settings_bluetooth, stateContentDescription);
+
         String bluetoothName = state.label;
         if (connected) {
             bluetoothName = state.dualLabelContentDescription = mContext.getString(
@@ -122,6 +123,15 @@
         state.dualLabelContentDescription = bluetoothName;
     }
 
+    @Override
+    protected String composeChangeAnnouncement() {
+        if (mState.value) {
+            return mContext.getString(R.string.accessibility_quick_settings_bluetooth_changed_on);
+        } else {
+            return mContext.getString(R.string.accessibility_quick_settings_bluetooth_changed_off);
+        }
+    }
+
     private final BluetoothController.Callback mCallback = new BluetoothController.Callback() {
         @Override
         public void onBluetoothStateChange(boolean enabled, boolean connecting) {
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 6b3e871..6cd0f39 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -110,6 +110,15 @@
         mDetailAdapter.updateItems(devices);
     }
 
+    @Override
+    protected String composeChangeAnnouncement() {
+        if (!mState.value) {
+            // We only announce when it's turned off to avoid vocal overflow.
+            return mContext.getString(R.string.accessibility_casting_turned_off);
+        }
+        return null;
+    }
+
     private String getDeviceName(CastDevice device) {
         return device.name != null ? device.name
                 : mContext.getString(R.string.quick_settings_cast_device_default_name);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index edb5932..a62bbff 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -88,4 +88,15 @@
         state.label = mContext.getString(R.string.quick_settings_inversion_label);
         state.iconId = enabled ? R.drawable.ic_qs_inversion_on : R.drawable.ic_qs_inversion_off;
     }
+
+    @Override
+    protected String composeChangeAnnouncement() {
+        if (mState.value) {
+            return mContext.getString(
+                    R.string.accessibility_quick_settings_color_inversion_changed_on);
+        } else {
+            return mContext.getString(
+                    R.string.accessibility_quick_settings_color_inversion_changed_off);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index 3ddf5e3..e6b7f02 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -94,6 +94,19 @@
         state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label);
         state.iconId = state.value
                 ? R.drawable.ic_qs_flashlight_on : R.drawable.ic_qs_flashlight_off;
+        int onOrOffId = state.value
+                ? R.string.accessibility_quick_settings_flashlight_on
+                : R.string.accessibility_quick_settings_flashlight_off;
+        state.contentDescription = mContext.getString(onOrOffId);
+    }
+
+    @Override
+    protected String composeChangeAnnouncement() {
+        if (mState.value) {
+            return mContext.getString(R.string.accessibility_quick_settings_flashlight_changed_on);
+        } else {
+            return mContext.getString(R.string.accessibility_quick_settings_flashlight_changed_off);
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 96333a3..9984fca 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -74,6 +74,15 @@
                 : R.drawable.ic_qs_hotspot_off;
     }
 
+    @Override
+    protected String composeChangeAnnouncement() {
+        if (mState.value) {
+            return mContext.getString(R.string.accessibility_quick_settings_hotspot_changed_on);
+        } else {
+            return mContext.getString(R.string.accessibility_quick_settings_hotspot_changed_off);
+        }
+    }
+
     private final class Callback implements HotspotController.Callback {
         @Override
         public void onHotspotChanged(boolean enabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index c4dd643..7ac6644 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -71,14 +71,21 @@
             state.iconId = R.drawable.ic_qs_location_on;
             state.label = mContext.getString(R.string.quick_settings_location_label);
             state.contentDescription = mContext.getString(
-                    R.string.accessibility_quick_settings_location,
-                    mContext.getString(R.string.accessibility_desc_on));
+                    R.string.accessibility_quick_settings_location_on);
         } else {
             state.iconId = R.drawable.ic_qs_location_off;
             state.label = mContext.getString(R.string.quick_settings_location_label);
             state.contentDescription = mContext.getString(
-                    R.string.accessibility_quick_settings_location,
-                    mContext.getString(R.string.accessibility_desc_off));
+                    R.string.accessibility_quick_settings_location_off);
+        }
+    }
+
+    @Override
+    protected String composeChangeAnnouncement() {
+        if (mState.value) {
+            return mContext.getString(R.string.accessibility_quick_settings_location_changed_on);
+        } else {
+            return mContext.getString(R.string.accessibility_quick_settings_location_changed_off);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index 21cf9ec..ae40a4d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -74,6 +74,38 @@
             state.label = mContext.getString(R.string.quick_settings_rotation_unlocked_label);
             state.icon = res.getDrawable(R.drawable.ic_qs_rotation_unlocked);
         }
+        state.contentDescription = getAccessibilityString(
+                R.string.accessibility_rotation_lock_on_portrait,
+                R.string.accessibility_rotation_lock_on_landscape,
+                R.string.accessibility_rotation_lock_off);
+    }
+
+    /**
+     * Get the correct accessibility string based on the state
+     *
+     * @param idWhenPortrait The id which should be used when locked in portrait.
+     * @param idWhenLandscape The id which should be used when locked in landscape.
+     * @param idWhenOff The id which should be used when the rotation lock is off.
+     * @return
+     */
+    private String getAccessibilityString(int idWhenPortrait, int idWhenLandscape, int idWhenOff) {
+        int stringID;
+        if (mState.value) {
+            final boolean portrait = mContext.getResources().getConfiguration().orientation
+                    != Configuration.ORIENTATION_LANDSCAPE;
+            stringID = portrait ? idWhenPortrait: idWhenLandscape;
+        } else {
+            stringID = idWhenOff;
+        }
+        return mContext.getString(stringID);
+    }
+
+    @Override
+    protected String composeChangeAnnouncement() {
+        return getAccessibilityString(
+                R.string.accessibility_rotation_lock_on_portrait_changed,
+                R.string.accessibility_rotation_lock_on_landscape_changed,
+                R.string.accessibility_rotation_lock_off_changed);
     }
 
     private final RotationLockControllerCallback mCallback = new RotationLockControllerCallback() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index a8bf026..b12c6c1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -40,6 +40,7 @@
 
     private final NetworkController mController;
     private final WifiDetailAdapter mDetailAdapter;
+    private final QSTile.SignalState mStateBeforeClick = newTileState();
 
     public WifiTile(Host host) {
         super(host);
@@ -80,6 +81,7 @@
 
     @Override
     protected void handleClick() {
+        mState.copyTo(mStateBeforeClick);
         mController.setWifiEnabled(!mState.enabled);
     }
 
@@ -140,6 +142,20 @@
         state.dualLabelContentDescription = wifiName;
     }
 
+    @Override
+    protected boolean shouldAnnouncementBeDelayed() {
+        return mStateBeforeClick.enabled == mState.enabled;
+    }
+
+    @Override
+    protected String composeChangeAnnouncement() {
+        if (mState.enabled) {
+            return mContext.getString(R.string.accessibility_quick_settings_wifi_changed_on);
+        } else {
+            return mContext.getString(R.string.accessibility_quick_settings_wifi_changed_off);
+        }
+    }
+
     private static String removeDoubleQuotes(String string) {
         if (string == null) return null;
         final int length = string.length();
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 3e2a398..44d8d23 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -26,6 +26,7 @@
 import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
 import android.os.AsyncTask;
+import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.phone.PhoneManager;
@@ -36,7 +37,7 @@
 import android.util.TypedValue;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.FrameLayout;
 import android.widget.TextView;
 
@@ -44,17 +45,23 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.KeyguardIndicationController;
-import com.android.systemui.statusbar.policy.FlashlightController;
+import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.KeyguardAffordanceView;
+import com.android.systemui.statusbar.KeyguardIndicationController;
+import com.android.systemui.statusbar.policy.AccessibilityController;
+import com.android.systemui.statusbar.policy.FlashlightController;
 import com.android.systemui.statusbar.policy.PreviewInflater;
 
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
+import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
+
 /**
  * Implementation for the bottom area of the Keyguard, including camera/phone affordance and status
  * text.
  */
 public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickListener,
-        UnlockMethodCache.OnUnlockMethodChangedListener {
+        UnlockMethodCache.OnUnlockMethodChangedListener,
+        AccessibilityController.AccessibilityStateChangedCallback, View.OnLongClickListener {
 
     final static String TAG = "PhoneStatusBar/KeyguardBottomAreaView";
 
@@ -80,25 +87,63 @@
     private FlashlightController mFlashlightController;
     private PreviewInflater mPreviewInflater;
     private KeyguardIndicationController mIndicationController;
-    private boolean mFaceUnlockRunning;
+    private AccessibilityController mAccessibilityController;
+    private PhoneStatusBar mPhoneStatusBar;
+
+    private final TrustDrawable mTrustDrawable;
 
     public KeyguardBottomAreaView(Context context) {
-        super(context);
+        this(context, null);
     }
 
     public KeyguardBottomAreaView(Context context, AttributeSet attrs) {
-        super(context, attrs);
+        this(context, attrs, 0);
     }
 
     public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
+        this(context, attrs, defStyleAttr, 0);
     }
 
     public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr,
             int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
+        mTrustDrawable = new TrustDrawable(mContext);
     }
 
+    private AccessibilityDelegate mAccessibilityDelegate = new AccessibilityDelegate() {
+        @Override
+        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+            super.onInitializeAccessibilityNodeInfo(host, info);
+            String label = null;
+            if (host == mLockIcon) {
+                label = getResources().getString(R.string.unlock_label);
+            } else if (host == mCameraImageView) {
+                label = getResources().getString(R.string.camera_label);
+            } else if (host == mPhoneImageView) {
+                label = getResources().getString(R.string.phone_label);
+            }
+            info.addAction(new AccessibilityAction(ACTION_CLICK, label));
+        }
+
+        @Override
+        public boolean performAccessibilityAction(View host, int action, Bundle args) {
+            if (action == ACTION_CLICK) {
+                if (host == mLockIcon) {
+                    mPhoneStatusBar.animateCollapsePanels(
+                            CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
+                    return true;
+                } else if (host == mCameraImageView) {
+                    launchCamera();
+                    return true;
+                } else if (host == mPhoneImageView) {
+                    launchPhone();
+                    return true;
+                }
+            }
+            return super.performAccessibilityAction(host, action, args);
+        }
+    };
+
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
@@ -109,7 +154,6 @@
         mLockIcon = (KeyguardAffordanceView) findViewById(R.id.lock_icon);
         mIndicationText = (TextView) findViewById(R.id.keyguard_indication_text);
         watchForCameraPolicyChanges();
-        watchForAccessibilityChanges();
         updateCameraVisibility();
         updatePhoneVisibility();
         mUnlockMethodCache = UnlockMethodCache.getInstance(getContext());
@@ -120,6 +164,17 @@
         mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext));
         inflatePreviews();
         mLockIcon.setOnClickListener(this);
+        mLockIcon.setBackground(mTrustDrawable);
+        mLockIcon.setOnLongClickListener(this);
+        mCameraImageView.setOnClickListener(this);
+        mPhoneImageView.setOnClickListener(this);
+        initAccessibility();
+    }
+
+    private void initAccessibility() {
+        mLockIcon.setAccessibilityDelegate(mAccessibilityDelegate);
+        mPhoneImageView.setAccessibilityDelegate(mAccessibilityDelegate);
+        mCameraImageView.setAccessibilityDelegate(mAccessibilityDelegate);
     }
 
     @Override
@@ -147,6 +202,15 @@
         mFlashlightController = flashlightController;
     }
 
+    public void setAccessibilityController(AccessibilityController accessibilityController) {
+        mAccessibilityController = accessibilityController;
+        accessibilityController.addStateChangedCallback(this);
+    }
+
+    public void setPhoneStatusBar(PhoneStatusBar phoneStatusBar) {
+        mPhoneStatusBar = phoneStatusBar;
+    }
+
     private Intent getCameraIntent() {
         KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
         boolean currentUserHasTrust = updateMonitor.getUserHasTrust(
@@ -200,28 +264,24 @@
         KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback);
     }
 
-    private void watchForAccessibilityChanges() {
-        final AccessibilityManager am =
-                (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
-
-        // Set the initial state
-        enableAccessibility(am.isTouchExplorationEnabled());
-
-        // Watch for changes
-        am.addTouchExplorationStateChangeListener(
-                new AccessibilityManager.TouchExplorationStateChangeListener() {
-            @Override
-            public void onTouchExplorationStateChanged(boolean enabled) {
-                enableAccessibility(enabled);
-            }
-        });
+    @Override
+    public void onStateChanged(boolean accessibilityEnabled, boolean touchExplorationEnabled) {
+        mCameraImageView.setClickable(touchExplorationEnabled);
+        mPhoneImageView.setClickable(touchExplorationEnabled);
+        mCameraImageView.setFocusable(accessibilityEnabled);
+        mPhoneImageView.setFocusable(accessibilityEnabled);
+        updateLockIconClickability();
     }
 
-    private void enableAccessibility(boolean touchExplorationEnabled) {
-        mCameraImageView.setOnClickListener(touchExplorationEnabled ? this : null);
-        mCameraImageView.setClickable(touchExplorationEnabled);
-        mPhoneImageView.setOnClickListener(touchExplorationEnabled ? this : null);
-        mPhoneImageView.setClickable(touchExplorationEnabled);
+    private void updateLockIconClickability() {
+        if (mAccessibilityController == null) {
+            return;
+        }
+        mLockIcon.setClickable(mUnlockMethodCache.isTrustManaged()
+                || mAccessibilityController.isTouchExplorationEnabled());
+        mLockIcon.setLongClickable(mAccessibilityController.isTouchExplorationEnabled()
+                && mUnlockMethodCache.isTrustManaged());
+        mLockIcon.setFocusable(mAccessibilityController.isAccessibilityEnabled());
     }
 
     @Override
@@ -231,12 +291,27 @@
         } else if (v == mPhoneImageView) {
             launchPhone();
         } if (v == mLockIcon) {
-            mIndicationController.showTransientIndication(
-                    R.string.keyguard_indication_trust_disabled);
-            mLockPatternUtils.requireCredentialEntry(mLockPatternUtils.getCurrentUser());
+            if (!mAccessibilityController.isAccessibilityEnabled()) {
+                handleTrustCircleClick();
+            } else {
+                mPhoneStatusBar.animateCollapsePanels(
+                        CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
+            }
         }
     }
 
+    @Override
+    public boolean onLongClick(View v) {
+        handleTrustCircleClick();
+        return true;
+    }
+
+    private void handleTrustCircleClick() {
+        mIndicationController.showTransientIndication(
+                R.string.keyguard_indication_trust_disabled);
+        mLockPatternUtils.requireCredentialEntry(mLockPatternUtils.getCurrentUser());
+    }
+
     public void launchCamera() {
         mFlashlightController.killFlashlight();
         Intent intent = getCameraIntent();
@@ -267,27 +342,47 @@
     @Override
     protected void onVisibilityChanged(View changedView, int visibility) {
         super.onVisibilityChanged(changedView, visibility);
+        if (isShown()) {
+            mTrustDrawable.start();
+        } else {
+            mTrustDrawable.stop();
+        }
         if (changedView == this && visibility == VISIBLE) {
             updateLockIcon();
             updateCameraVisibility();
         }
     }
 
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        mTrustDrawable.stop();
+    }
+
     private void updateLockIcon() {
-        if (getVisibility() != VISIBLE) {
+        boolean visible = isShown() && KeyguardUpdateMonitor.getInstance(mContext).isScreenOn();
+        if (visible) {
+            mTrustDrawable.start();
+        } else {
+            mTrustDrawable.stop();
+        }
+        if (!visible) {
             return;
         }
         // TODO: Real icon for facelock.
-        int iconRes = mFaceUnlockRunning ? R.drawable.ic_account_circle
+        int iconRes = mUnlockMethodCache.isFaceUnlockRunning() ? R.drawable.ic_account_circle
                 : mUnlockMethodCache.isMethodInsecure() ? R.drawable.ic_lock_open_24dp
                 : R.drawable.ic_lock_24dp;
         mLockIcon.setImageResource(iconRes);
         boolean trustManaged = mUnlockMethodCache.isTrustManaged();
-        mLockIcon.setBackgroundResource(trustManaged && !mFaceUnlockRunning
-                ? R.drawable.trust_circle : 0);
-        mLockIcon.setClickable(trustManaged);
+        mTrustDrawable.setTrustManaged(trustManaged);
+
+        // TODO: Update content description depending on state
+        updateLockIconClickability();
     }
 
+
+
     public KeyguardAffordanceView getPhoneView() {
         return mPhoneImageView;
     }
@@ -355,8 +450,12 @@
         }
 
         @Override
-        public void onFaceUnlockStateChanged(boolean running) {
-            mFaceUnlockRunning = running;
+        public void onScreenTurnedOn() {
+            updateLockIcon();
+        }
+
+        @Override
+        public void onScreenTurnedOff(int why) {
             updateLockIcon();
         }
     };
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index 5e5c3aa..650a14f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -30,6 +30,7 @@
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 
+import com.android.systemui.BatteryMeterView;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
@@ -135,6 +136,7 @@
 
     public void setBatteryController(BatteryController batteryController) {
         mBatteryController = batteryController;
+        ((BatteryMeterView) findViewById(R.id.battery)).setBatteryController(batteryController);
     }
 
     public void setUserInfoController(UserInfoController userInfoController) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index decf231..b3042b9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -109,6 +109,7 @@
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.keyguard.KeyguardHostView.OnDismissAction;
 import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.BatteryMeterView;
 import com.android.systemui.DemoMode;
 import com.android.systemui.EventLogTags;
 import com.android.systemui.R;
@@ -131,6 +132,7 @@
 import com.android.systemui.statusbar.SpeedBumpView;
 import com.android.systemui.statusbar.StatusBarIconView;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.policy.AccessibilityController;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
 import com.android.systemui.statusbar.policy.BluetoothControllerImpl;
@@ -236,6 +238,7 @@
     NextAlarmController mNextAlarmController;
     KeyguardMonitor mKeyguardMonitor;
     BrightnessMirrorController mBrightnessMirrorController;
+    AccessibilityController mAccessibilityController;
 
     int mNaturalBarHeight = -1;
     int mIconSize = -1;
@@ -804,6 +807,9 @@
 
         mFlashlightController = new FlashlightController(mContext);
         mKeyguardBottomArea.setFlashlightController(mFlashlightController);
+        mKeyguardBottomArea.setPhoneStatusBar(this);
+        mAccessibilityController = new AccessibilityController(mContext);
+        mKeyguardBottomArea.setAccessibilityController(mAccessibilityController);
         mNextAlarmController = new NextAlarmController(mContext);
         mKeyguardMonitor = new KeyguardMonitor();
         mUserSwitcherController = new UserSwitcherController(mContext, mKeyguardMonitor);
@@ -845,6 +851,8 @@
         mUserInfoController.reloadUserInfo();
 
         mHeader.setBatteryController(mBatteryController);
+        ((BatteryMeterView) mStatusBarView.findViewById(R.id.battery)).setBatteryController(
+                mBatteryController);
         mKeyguardStatusBar.setBatteryController(mBatteryController);
         mHeader.setNextAlarmController(mNextAlarmController);
 
@@ -1346,7 +1354,7 @@
             updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
 
             if (CLOSE_PANEL_WHEN_EMPTIED && !hasActiveNotifications()
-                    && !mNotificationPanel.isTracking()) {
+                    && !mNotificationPanel.isTracking() && !mNotificationPanel.isQsExpanded()) {
                 if (mState == StatusBarState.SHADE) {
                     animateCollapsePanels();
                 } else if (mState == StatusBarState.SHADE_LOCKED) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index 8bc7dd4..807a37b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -714,6 +714,7 @@
             final boolean showingDetail = detail != null;
             transition(mClock, !showingDetail);
             transition(mDateGroup, !showingDetail);
+            transition(mAlarmStatus, !showingDetail);
             transition(mQsDetailHeader, showingDetail);
             if (showingDetail) {
                 mQsDetailHeaderTitle.setText(detail.getTitle());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrustDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrustDrawable.java
new file mode 100644
index 0000000..dcda2c7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrustDrawable.java
@@ -0,0 +1,297 @@
+/*
+ * 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.statusbar.phone;
+
+import com.android.systemui.R;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+
+public class TrustDrawable extends Drawable {
+
+    private static final long ENTERING_FROM_UNSET_START_DELAY = 200;
+    private static final long VISIBLE_DURATION = 1000;
+    private static final long EXIT_DURATION = 500;
+    private static final long ENTER_DURATION = 500;
+
+    private static final int ALPHA_VISIBLE_MIN = 0x26;
+    private static final int ALPHA_VISIBLE_MAX = 0x4c;
+
+    private static final int STATE_UNSET = -1;
+    private static final int STATE_GONE = 0;
+    private static final int STATE_ENTERING = 1;
+    private static final int STATE_VISIBLE = 2;
+    private static final int STATE_EXITING = 3;
+
+    private int mAlpha;
+    private boolean mAnimating;
+
+    private int mCurAlpha;
+    private float mCurInnerRadius;
+    private Animator mCurAnimator;
+    private int mState = STATE_UNSET;
+    private Paint mPaint;
+    private boolean mTrustManaged;
+
+    private final float mInnerRadiusVisibleMin;
+    private final float mInnerRadiusVisibleMax;
+    private final float mInnerRadiusExit;
+    private final float mInnerRadiusEnter;
+    private final float mThickness;
+
+    private final Animator mVisibleAnimator;
+
+    private final Interpolator mLinearOutSlowInInterpolator;
+    private final Interpolator mFastOutSlowInInterpolator;
+    private final Interpolator mAccelerateDecelerateInterpolator;
+
+    public TrustDrawable(Context context) {
+        Resources r = context.getResources();
+        mInnerRadiusVisibleMin = r.getDimension(R.dimen.trust_circle_inner_radius_visible_min);
+        mInnerRadiusVisibleMax = r.getDimension(R.dimen.trust_circle_inner_radius_visible_max);
+        mInnerRadiusExit = r.getDimension(R.dimen.trust_circle_inner_radius_exit);
+        mInnerRadiusEnter = r.getDimension(R.dimen.trust_circle_inner_radius_enter);
+        mThickness = r.getDimension(R.dimen.trust_circle_thickness);
+
+        mCurInnerRadius = mInnerRadiusEnter;
+
+        mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(
+                context, android.R.interpolator.linear_out_slow_in);
+        mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(
+                context, android.R.interpolator.fast_out_slow_in);
+        mAccelerateDecelerateInterpolator = new AccelerateDecelerateInterpolator();
+
+        mVisibleAnimator = makeVisibleAnimator();
+
+        mPaint = new Paint();
+        mPaint.setStyle(Paint.Style.STROKE);
+        mPaint.setColor(Color.WHITE);
+        mPaint.setAntiAlias(true);
+        mPaint.setStrokeWidth(mThickness);
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        int newAlpha = (mCurAlpha * mAlpha) / 256;
+        if (newAlpha == 0) {
+            return;
+        }
+        final Rect r = getBounds();
+        mPaint.setAlpha(newAlpha);
+        canvas.drawCircle(r.exactCenterX(), r.exactCenterY(), mCurInnerRadius, mPaint);
+    }
+
+    @Override
+    public void setAlpha(int alpha) {
+        mAlpha = alpha;
+    }
+
+    @Override
+    public int getAlpha() {
+        return mAlpha;
+    }
+
+    @Override
+    public void setColorFilter(ColorFilter cf) {
+        throw new UnsupportedOperationException("not implemented");
+    }
+
+    @Override
+    public int getOpacity() {
+        return PixelFormat.TRANSLUCENT;
+    }
+
+    public void start() {
+        if (!mAnimating) {
+            mAnimating = true;
+            updateState(true);
+        }
+    }
+
+    public void stop() {
+        if (mAnimating) {
+            mAnimating = false;
+            if (mCurAnimator != null) {
+                mCurAnimator.cancel();
+                mCurAnimator = null;
+            }
+            mState = STATE_UNSET;
+            mCurAlpha = 0;
+            mCurInnerRadius = mInnerRadiusEnter;
+        }
+    }
+
+    public void setTrustManaged(boolean trustManaged) {
+        if (trustManaged == mTrustManaged && mState != STATE_UNSET) return;
+        mTrustManaged = trustManaged;
+        if (mAnimating) {
+            updateState(true);
+        }
+    }
+
+    private void updateState(boolean animate) {
+        int nextState = mState;
+        if (mState == STATE_UNSET) {
+            nextState = mTrustManaged ? STATE_ENTERING : STATE_GONE;
+        } else if (mState == STATE_GONE) {
+            if (mTrustManaged) nextState = STATE_ENTERING;
+        } else if (mState == STATE_ENTERING) {
+            if (!mTrustManaged) nextState = STATE_EXITING;
+        } else if (mState == STATE_VISIBLE) {
+            if (!mTrustManaged) nextState = STATE_EXITING;
+        } else if (mState == STATE_EXITING) {
+            if (mTrustManaged) nextState = STATE_ENTERING;
+        }
+        if (!animate) {
+            if (nextState == STATE_ENTERING) nextState = STATE_VISIBLE;
+            if (nextState == STATE_EXITING) nextState = STATE_GONE;
+        }
+
+        if (nextState != mState) {
+            if (mCurAnimator != null) {
+                mCurAnimator.cancel();
+                mCurAnimator = null;
+            }
+
+            if (nextState == STATE_GONE) {
+                mCurAlpha = 0;
+                mCurInnerRadius = mInnerRadiusEnter;
+            } else if (nextState == STATE_ENTERING) {
+                mCurAnimator = makeEnterAnimator(mCurInnerRadius, mCurAlpha);
+                if (mState == STATE_UNSET) {
+                    mCurAnimator.setStartDelay(ENTERING_FROM_UNSET_START_DELAY);
+                }
+            } else if (nextState == STATE_VISIBLE) {
+                mCurAlpha = ALPHA_VISIBLE_MAX;
+                mCurInnerRadius = mInnerRadiusVisibleMax;
+                mCurAnimator = mVisibleAnimator;
+            } else if (nextState == STATE_EXITING) {
+                mCurAnimator = makeExitAnimator(mCurInnerRadius, mCurAlpha);
+            }
+
+            mState = nextState;
+            if (mCurAnimator != null) {
+                mCurAnimator.start();
+            } else {
+                invalidateSelf();
+            }
+        }
+    }
+
+    private Animator makeVisibleAnimator() {
+        return makeAnimators(mInnerRadiusVisibleMax, mInnerRadiusVisibleMin,
+                ALPHA_VISIBLE_MAX, ALPHA_VISIBLE_MIN, VISIBLE_DURATION,
+                mAccelerateDecelerateInterpolator,
+                true /* repeating */, false /* stateUpdateListener */);
+    }
+
+    private Animator makeEnterAnimator(float radius, int alpha) {
+        return makeAnimators(radius, mInnerRadiusVisibleMax,
+                alpha, ALPHA_VISIBLE_MAX, ENTER_DURATION, mLinearOutSlowInInterpolator,
+                false /* repeating */, true /* stateUpdateListener */);
+    }
+
+    private Animator makeExitAnimator(float radius, int alpha) {
+        return makeAnimators(radius, mInnerRadiusExit,
+                alpha, 0, EXIT_DURATION, mFastOutSlowInInterpolator,
+                false /* repeating */, true /* stateUpdateListener */);
+    }
+
+    private Animator makeAnimators(float startRadius, float endRadius,
+            int startAlpha, int endAlpha, long duration, Interpolator interpolator,
+            boolean repeating, boolean stateUpdateListener) {
+        ValueAnimator alphaAnimator = configureAnimator(
+                ValueAnimator.ofInt(startAlpha, endAlpha),
+                duration, mAlphaUpdateListener, interpolator, repeating);
+        ValueAnimator sizeAnimator = configureAnimator(
+                ValueAnimator.ofFloat(startRadius, endRadius),
+                duration, mRadiusUpdateListener, interpolator, repeating);
+
+        AnimatorSet set = new AnimatorSet();
+        set.playTogether(alphaAnimator, sizeAnimator);
+        if (stateUpdateListener) {
+            set.addListener(new StateUpdateAnimatorListener());
+        }
+        return set;
+    }
+
+    private ValueAnimator configureAnimator(ValueAnimator animator, long duration,
+            ValueAnimator.AnimatorUpdateListener updateListener, Interpolator interpolator,
+            boolean repeating) {
+        animator.setDuration(duration);
+        animator.addUpdateListener(updateListener);
+        animator.setInterpolator(interpolator);
+        if (repeating) {
+            animator.setRepeatCount(ValueAnimator.INFINITE);
+            animator.setRepeatMode(ValueAnimator.REVERSE);
+        }
+        return animator;
+    }
+
+    private final ValueAnimator.AnimatorUpdateListener mAlphaUpdateListener =
+            new ValueAnimator.AnimatorUpdateListener() {
+        @Override
+        public void onAnimationUpdate(ValueAnimator animation) {
+            mCurAlpha = (int) animation.getAnimatedValue();
+            invalidateSelf();
+        }
+    };
+
+    private final ValueAnimator.AnimatorUpdateListener mRadiusUpdateListener =
+            new ValueAnimator.AnimatorUpdateListener() {
+        @Override
+        public void onAnimationUpdate(ValueAnimator animation) {
+            mCurInnerRadius = (float) animation.getAnimatedValue();
+            invalidateSelf();
+        }
+    };
+
+    private class StateUpdateAnimatorListener extends AnimatorListenerAdapter {
+        boolean mCancelled;
+
+        @Override
+        public void onAnimationStart(Animator animation) {
+            mCancelled = false;
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animation) {
+            mCancelled = true;
+        }
+
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            if (!mCancelled) {
+                updateState(false);
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
index 58196f7..e5eef9d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
@@ -38,6 +38,7 @@
     private final ArrayList<OnUnlockMethodChangedListener> mListeners = new ArrayList<>();
     private boolean mMethodInsecure;
     private boolean mTrustManaged;
+    private boolean mFaceUnlockRunning;
 
     private UnlockMethodCache(Context ctx) {
         mLockPatternUtils = new LockPatternUtils(ctx);
@@ -73,10 +74,14 @@
         boolean methodInsecure = !mLockPatternUtils.isSecure() ||
                 mKeyguardUpdateMonitor.getUserHasTrust(user);
         boolean trustManaged = mKeyguardUpdateMonitor.getUserTrustIsManaged(user);
-        boolean changed = methodInsecure != mMethodInsecure || trustManaged != mTrustManaged;
+        boolean faceUnlockRunning = mKeyguardUpdateMonitor.isFaceUnlockRunning(user)
+                && trustManaged;
+        boolean changed = methodInsecure != mMethodInsecure || trustManaged != mTrustManaged
+                || faceUnlockRunning != mFaceUnlockRunning;
         if (changed || updateAlways) {
             mMethodInsecure = methodInsecure;
             mTrustManaged = trustManaged;
+            mFaceUnlockRunning = faceUnlockRunning;
             notifyListeners(mMethodInsecure);
         }
     }
@@ -112,12 +117,21 @@
         public void onFingerprintRecognized(int userId) {
             updateMethodSecure(false /* updateAlways */);
         }
+
+        @Override
+        public void onFaceUnlockStateChanged(boolean running, int userId) {
+            updateMethodSecure(false /* updateAlways */);
+        }
     };
 
     public boolean isTrustManaged() {
         return mTrustManaged;
     }
 
+    public boolean isFaceUnlockRunning() {
+        return mFaceUnlockRunning;
+    }
+
     public static interface OnUnlockMethodChangedListener {
         void onMethodSecureChanged(boolean methodSecure);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityController.java
new file mode 100644
index 0000000..89ed787
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityController.java
@@ -0,0 +1,90 @@
+/*
+ * 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.statusbar.policy;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.accessibility.AccessibilityManager;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+public class AccessibilityController implements
+        AccessibilityManager.AccessibilityStateChangeListener,
+        AccessibilityManager.TouchExplorationStateChangeListener {
+
+    private final ArrayList<AccessibilityStateChangedCallback> mChangeCallbacks = new ArrayList<>();
+
+    private boolean mAccessibilityEnabled;
+    private boolean mTouchExplorationEnabled;
+
+    public AccessibilityController(Context context) {
+        AccessibilityManager am =
+                (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
+        am.addTouchExplorationStateChangeListener(this);
+        am.addAccessibilityStateChangeListener(this);
+        mAccessibilityEnabled = am.isEnabled();
+        mTouchExplorationEnabled = am.isTouchExplorationEnabled();
+    }
+
+    public boolean isAccessibilityEnabled() {
+        return mAccessibilityEnabled;
+    }
+
+    public boolean isTouchExplorationEnabled() {
+        return mTouchExplorationEnabled;
+    }
+
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("AccessibilityController state:");
+        pw.print("  mAccessibilityEnabled="); pw.println(mAccessibilityEnabled);
+        pw.print("  mTouchExplorationEnabled="); pw.println(mTouchExplorationEnabled);
+    }
+
+    public void addStateChangedCallback(AccessibilityStateChangedCallback cb) {
+        mChangeCallbacks.add(cb);
+        cb.onStateChanged(mAccessibilityEnabled, mTouchExplorationEnabled);
+    }
+
+    public void removeStateChangedCallback(AccessibilityStateChangedCallback cb) {
+        mChangeCallbacks.remove(cb);
+    }
+
+    private void fireChanged() {
+        final int N = mChangeCallbacks.size();
+        for (int i = 0; i < N; i++) {
+            mChangeCallbacks.get(i).onStateChanged(mAccessibilityEnabled, mTouchExplorationEnabled);
+        }
+    }
+
+    @Override
+    public void onAccessibilityStateChanged(boolean enabled) {
+        mAccessibilityEnabled = enabled;
+        fireChanged();
+    }
+
+    @Override
+    public void onTouchExplorationStateChanged(boolean enabled) {
+        mTouchExplorationEnabled = enabled;
+        fireChanged();
+    }
+
+    public interface AccessibilityStateChangedCallback {
+        void onStateChanged(boolean accessibilityEnabled, boolean touchExplorationEnabled);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index 51876b8..8a14288 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -37,7 +37,7 @@
 import android.media.ToneGenerator;
 import android.media.VolumeProvider;
 import android.media.session.MediaController;
-import android.media.session.MediaController.AudioInfo;
+import android.media.session.MediaController.PlaybackInfo;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.Message;
@@ -537,7 +537,7 @@
             if (mStreamControls != null) {
                 StreamControl sc = mStreamControls.get(streamType);
                 if (sc != null && sc.controller != null) {
-                    AudioInfo ai = sc.controller.getAudioInfo();
+                    PlaybackInfo ai = sc.controller.getPlaybackInfo();
                     return ai.getMaxVolume();
                 }
             }
@@ -554,7 +554,7 @@
             if (mStreamControls != null) {
                 StreamControl sc = mStreamControls.get(streamType);
                 if (sc != null && sc.controller != null) {
-                    AudioInfo ai = sc.controller.getAudioInfo();
+                    PlaybackInfo ai = sc.controller.getPlaybackInfo();
                     return ai.getCurrentVolume();
                 }
             }
@@ -990,7 +990,7 @@
                     // We still don't have one, ignore the command.
                     Log.w(mTag, "sent remote volume change without a controller!");
                 } else {
-                    AudioInfo vi = controller.getAudioInfo();
+                    PlaybackInfo vi = controller.getPlaybackInfo();
                     index = vi.getCurrentVolume();
                     max = vi.getMaxVolume();
                     if ((vi.getVolumeControl() & VolumeProvider.VOLUME_CONTROL_FIXED) != 0) {
@@ -1362,7 +1362,7 @@
     };
 
     private final MediaController.Callback mMediaControllerCb = new MediaController.Callback() {
-        public void onAudioInfoChanged(AudioInfo info) {
+        public void onAudioInfoChanged(PlaybackInfo info) {
             onRemoteVolumeUpdateIfShown();
         }
     };
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 5900612..2e5d43f 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -867,6 +867,7 @@
                         // the timeout is suspended while a restore is in progress.  Clean
                         // up now.
                         Slog.w(TAG, "Restore session timed out; aborting");
+                        mActiveRestoreSession.markTimedOut();
                         post(mActiveRestoreSession.new EndRestoreRunnable(
                                 BackupManagerService.this, mActiveRestoreSession));
                     }
@@ -8738,12 +8739,17 @@
         private IBackupTransport mRestoreTransport = null;
         RestoreSet[] mRestoreSets = null;
         boolean mEnded = false;
+        boolean mTimedOut = false;
 
         ActiveRestoreSession(String packageName, String transport) {
             mPackageName = packageName;
             mRestoreTransport = getTransport(transport);
         }
 
+        public void markTimedOut() {
+            mTimedOut = true;
+        }
+
         // --- Binder interface ---
         public synchronized int getAvailableRestoreSets(IRestoreObserver observer) {
             mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
@@ -8756,6 +8762,11 @@
                 throw new IllegalStateException("Restore session already ended");
             }
 
+            if (mTimedOut) {
+                Slog.i(TAG, "Session already timed out");
+                return -1;
+            }
+
             long oldId = Binder.clearCallingIdentity();
             try {
                 if (mRestoreTransport == null) {
@@ -8787,6 +8798,11 @@
                 throw new IllegalStateException("Restore session already ended");
             }
 
+            if (mTimedOut) {
+                Slog.i(TAG, "Session already timed out");
+                return -1;
+            }
+
             if (mRestoreTransport == null || mRestoreSets == null) {
                 Slog.e(TAG, "Ignoring restoreAll() with no restore set");
                 return -1;
@@ -8861,6 +8877,11 @@
                 throw new IllegalStateException("Restore session already ended");
             }
 
+            if (mTimedOut) {
+                Slog.i(TAG, "Session already timed out");
+                return -1;
+            }
+
             if (mRestoreTransport == null || mRestoreSets == null) {
                 Slog.e(TAG, "Ignoring restoreAll() with no restore set");
                 return -1;
@@ -8909,6 +8930,11 @@
                 throw new IllegalStateException("Restore session already ended");
             }
 
+            if (mTimedOut) {
+                Slog.i(TAG, "Session already timed out");
+                return -1;
+            }
+
             if (mPackageName != null) {
                 if (! mPackageName.equals(packageName)) {
                     Slog.e(TAG, "Ignoring attempt to restore pkg=" + packageName
@@ -9006,6 +9032,11 @@
         public synchronized void endRestoreSession() {
             if (DEBUG) Slog.d(TAG, "endRestoreSession");
 
+            if (mTimedOut) {
+                Slog.i(TAG, "Session already timed out");
+                return;
+            }
+
             if (mEnded) {
                 throw new IllegalStateException("Restore session already ended");
             }
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 07c9048..7b64139 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -121,6 +121,7 @@
     private int mState;
     private final BluetoothHandler mHandler;
     private int mErrorRecoveryRetryCounter;
+    private final int mSystemUiUid;
 
     private void registerForAirplaneMode(IntentFilter filter) {
         final ContentResolver resolver = mContext.getContentResolver();
@@ -218,6 +219,15 @@
         if (isBluetoothPersistedStateOn()) {
             mEnableExternal = true;
         }
+
+        int sysUiUid = -1;
+        try {
+            sysUiUid = mContext.getPackageManager().getPackageUid("com.android.systemui",
+                    UserHandle.USER_OWNER);
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.wtf(TAG, "Unable to resolve SystemUI's UID.", e);
+        }
+        mSystemUiUid = sysUiUid;
     }
 
     /**
@@ -1118,7 +1128,8 @@
         try {
             foregroundUser = ActivityManager.getCurrentUser();
             valid = (callingUser == foregroundUser) ||
-                    callingAppId == Process.NFC_UID;
+                    callingAppId == Process.NFC_UID ||
+                    callingAppId == mSystemUiUid;
             if (DBG) {
                 Log.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid
                     + " callingUser=" + callingUser
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 05179a4..b1d84f58 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3463,7 +3463,7 @@
             if (sourceRecord.app == null) {
                 throw new SecurityException("Called without a process attached to activity");
             }
-            if (sourceRecord.app.uid != Process.SYSTEM_UID) {
+            if (UserHandle.getAppId(sourceRecord.app.uid) != Process.SYSTEM_UID) {
                 // This is still okay, as long as this activity is running under the
                 // uid of the original calling activity.
                 if (sourceRecord.app.uid != sourceRecord.launchedFromUid) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 931f448..8aec392 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -3189,7 +3189,11 @@
 
     void endLockTaskModeIfTaskEnding(TaskRecord task) {
         if (mLockTaskModeTask != null && mLockTaskModeTask == task) {
+            final Message lockTaskMsg = Message.obtain();
+            lockTaskMsg.arg1 = mLockTaskModeTask.userId;
+            lockTaskMsg.what = LOCK_TASK_END_MSG;
             mLockTaskModeTask = null;
+            mHandler.sendMessage(lockTaskMsg);
         }
     }
 
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 46cb6c3..2a1ceaa 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -87,7 +87,7 @@
     private static final int SCREEN_DIM_MINIMUM_REDUCTION = 10;
 
     private static final int COLOR_FADE_ON_ANIMATION_DURATION_MILLIS = 250;
-    private static final int COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS = 600;
+    private static final int COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS = 400;
 
     private static final int MSG_UPDATE_POWER_STATE = 1;
     private static final int MSG_PROXIMITY_SENSOR_DEBOUNCED = 2;
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 84027e2..978a9f4 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -31,6 +31,7 @@
 import android.media.session.ISessionController;
 import android.media.session.ISessionControllerCallback;
 import android.media.session.MediaController;
+import android.media.session.MediaController.PlaybackInfo;
 import android.media.session.MediaSession;
 import android.media.session.ParcelableVolumeInfo;
 import android.media.session.PlaybackState;
@@ -111,7 +112,7 @@
     private AudioAttributes mAudioAttrs;
     private AudioManager mAudioManager;
     private AudioManagerInternal mAudioManagerInternal;
-    private int mVolumeType = MediaSession.PLAYBACK_TYPE_LOCAL;
+    private int mVolumeType = PlaybackInfo.PLAYBACK_TYPE_LOCAL;
     private int mVolumeControlType = VolumeProvider.VOLUME_CONTROL_ABSOLUTE;
     private int mMaxVolume = 0;
     private int mCurrentVolume = 0;
@@ -237,7 +238,7 @@
         } else if (direction < -1) {
             direction = -1;
         }
-        if (mVolumeType == MediaSession.PLAYBACK_TYPE_LOCAL) {
+        if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) {
             int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
             mAudioManagerInternal.adjustStreamVolumeForUid(stream, direction, flags, packageName,
                     uid);
@@ -265,7 +266,7 @@
     }
 
     public void setVolumeTo(int value, int flags, String packageName, int uid) {
-        if (mVolumeType == MediaSession.PLAYBACK_TYPE_LOCAL) {
+        if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) {
             int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
             mAudioManagerInternal.setStreamVolumeForUid(stream, value, flags, packageName, uid);
         } else {
@@ -748,8 +749,8 @@
         public void setPlaybackToLocal(AudioAttributes attributes) {
             boolean typeChanged;
             synchronized (mLock) {
-                typeChanged = mVolumeType == MediaSession.PLAYBACK_TYPE_REMOTE;
-                mVolumeType = MediaSession.PLAYBACK_TYPE_LOCAL;
+                typeChanged = mVolumeType == PlaybackInfo.PLAYBACK_TYPE_REMOTE;
+                mVolumeType = PlaybackInfo.PLAYBACK_TYPE_LOCAL;
                 if (attributes != null) {
                     mAudioAttrs = attributes;
                 } else {
@@ -765,8 +766,8 @@
         public void setPlaybackToRemote(int control, int max) {
             boolean typeChanged;
             synchronized (mLock) {
-                typeChanged = mVolumeType == MediaSession.PLAYBACK_TYPE_LOCAL;
-                mVolumeType = MediaSession.PLAYBACK_TYPE_REMOTE;
+                typeChanged = mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL;
+                mVolumeType = PlaybackInfo.PLAYBACK_TYPE_REMOTE;
                 mVolumeControlType = control;
                 mMaxVolume = max;
             }
@@ -998,7 +999,7 @@
                 int type;
                 int max;
                 int current;
-                if (mVolumeType == MediaSession.PLAYBACK_TYPE_REMOTE) {
+                if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_REMOTE) {
                     type = mVolumeControlType;
                     max = mMaxVolume;
                     current = mOptimisticVolume != -1 ? mOptimisticVolume
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 1221aa4..0c6d46c 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -37,6 +37,7 @@
 import android.media.session.ISession;
 import android.media.session.ISessionCallback;
 import android.media.session.ISessionManager;
+import android.media.session.MediaController.PlaybackInfo;
 import android.media.session.MediaSession;
 import android.net.Uri;
 import android.os.Binder;
@@ -814,7 +815,7 @@
             } else {
                 session.adjustVolume(direction, flags, getContext().getPackageName(),
                         UserHandle.myUserId());
-                if (session.getPlaybackType() == MediaSession.PLAYBACK_TYPE_REMOTE
+                if (session.getPlaybackType() == PlaybackInfo.PLAYBACK_TYPE_REMOTE
                         && mRvc != null) {
                     try {
                         mRvc.remoteVolumeChanged(session.getControllerBinder(), flags);
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index fec11fba..a9bc818 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -16,6 +16,7 @@
 
 package com.android.server.media;
 
+import android.media.session.MediaController.PlaybackInfo;
 import android.media.session.PlaybackState;
 import android.media.session.MediaSession;
 import android.os.UserHandle;
@@ -209,7 +210,7 @@
         int size = records.size();
         for (int i = 0; i < size; i++) {
             MediaSessionRecord record = records.get(i);
-            if (record.getPlaybackType() == MediaSession.PLAYBACK_TYPE_REMOTE) {
+            if (record.getPlaybackType() == PlaybackInfo.PLAYBACK_TYPE_REMOTE) {
                 return record;
             }
         }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 7117933..45bd812 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1528,14 +1528,15 @@
         }
         checkCallerIsSystemOrSameApp(pkg);
         final boolean isSystemNotification = isUidSystem(callingUid) || ("android".equals(pkg));
+        final boolean isNotificationFromListener = mListeners.isListenerPackage(pkg);
 
         final int userId = ActivityManager.handleIncomingUser(callingPid,
                 callingUid, incomingUserId, true, false, "enqueueNotification", pkg);
         final UserHandle user = new UserHandle(userId);
 
         // Limit the number of notifications that any given package except the android
-        // package can enqueue.  Prevents DOS attacks and deals with leaks.
-        if (!isSystemNotification) {
+        // package or a registered listener can enqueue.  Prevents DOS attacks and deals with leaks.
+        if (!isSystemNotification && !isNotificationFromListener) {
             synchronized (mNotificationList) {
                 int count = 0;
                 final int N = mNotificationList.size();
@@ -2720,6 +2721,21 @@
                 Log.e(TAG, "unable to notify listener (listener hints): " + listener, ex);
             }
         }
+
+        private boolean isListenerPackage(String packageName) {
+            if (packageName == null) {
+                return false;
+            }
+            // TODO: clean up locking object later
+            synchronized (mNotificationList) {
+                for (final ManagedServiceInfo serviceInfo : mServices) {
+                    if (packageName.equals(serviceInfo.component.getPackageName())) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
     }
 
     public static final class DumpFilter {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 0393518..03cb2e9 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -56,6 +56,7 @@
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Environment;
+import android.os.Environment.UserEnvironment;
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -485,7 +486,8 @@
             // Brand new install, use best resolved location. This also verifies
             // that target has enough free space for the install.
             final int resolved = PackageHelper.resolveInstallLocation(mContext,
-                    params.installLocation, params.sizeBytes, params.installFlags);
+                    params.appPackageName, params.installLocation, params.sizeBytes,
+                    params.installFlags);
             if (resolved == PackageHelper.RECOMMEND_INSTALL_INTERNAL) {
                 stageInternal = true;
             } else if (resolved == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
@@ -568,7 +570,8 @@
     private void checkExternalStorage(long sizeBytes) throws IOException {
         if (sizeBytes <= 0) return;
 
-        final File target = Environment.getExternalStorageDirectory();
+        final File target = new UserEnvironment(UserHandle.USER_OWNER)
+                .getExternalStorageDirectory();
         final long targetBytes = sizeBytes + mStorage.getStorageLowBytes(target);
 
         if (target.getUsableSpace() < targetBytes) {
@@ -696,7 +699,7 @@
         mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "uninstall");
 
         final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext,
-                statusReceiver);
+                statusReceiver, packageName);
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DELETE_PACKAGES)
                 == PackageManager.PERMISSION_GRANTED) {
             // Sweet, call straight through!
@@ -773,15 +776,19 @@
     static class PackageDeleteObserverAdapter extends PackageDeleteObserver {
         private final Context mContext;
         private final IntentSender mTarget;
+        private final String mPackageName;
 
-        public PackageDeleteObserverAdapter(Context context, IntentSender target) {
+        public PackageDeleteObserverAdapter(Context context, IntentSender target,
+                String packageName) {
             mContext = context;
             mTarget = target;
+            mPackageName = packageName;
         }
 
         @Override
         public void onUserActionRequired(Intent intent) {
             final Intent fillIn = new Intent();
+            fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, mPackageName);
             fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
                     PackageInstaller.STATUS_PENDING_USER_ACTION);
             fillIn.putExtra(Intent.EXTRA_INTENT, intent);
@@ -794,6 +801,7 @@
         @Override
         public void onPackageDeleted(String basePackageName, int returnCode, String msg) {
             final Intent fillIn = new Intent();
+            fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, mPackageName);
             fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
                     PackageManager.deleteStatusToPublicStatus(returnCode));
             fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE,
@@ -809,15 +817,18 @@
     static class PackageInstallObserverAdapter extends PackageInstallObserver {
         private final Context mContext;
         private final IntentSender mTarget;
+        private final int mSessionId;
 
-        public PackageInstallObserverAdapter(Context context, IntentSender target) {
+        public PackageInstallObserverAdapter(Context context, IntentSender target, int sessionId) {
             mContext = context;
             mTarget = target;
+            mSessionId = sessionId;
         }
 
         @Override
         public void onUserActionRequired(Intent intent) {
             final Intent fillIn = new Intent();
+            fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId);
             fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
                     PackageInstaller.STATUS_PENDING_USER_ACTION);
             fillIn.putExtra(Intent.EXTRA_INTENT, intent);
@@ -831,6 +842,7 @@
         public void onPackageInstalled(String basePackageName, int returnCode, String msg,
                 Bundle extras) {
             final Intent fillIn = new Intent();
+            fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId);
             fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
                     PackageManager.installStatusToPublicStatus(returnCode));
             fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE,
@@ -840,8 +852,7 @@
                 final String existing = extras.getString(
                         PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE);
                 if (!TextUtils.isEmpty(existing)) {
-                    fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAMES, new String[] {
-                            existing });
+                    fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, existing);
                 }
             }
             try {
@@ -986,5 +997,12 @@
             }
             writeSessionsAsync();
         }
+
+        public void onSessionSealed(PackageInstallerSession session) {
+            // It's very important that we block until we've recorded the
+            // session as being sealed, since we never want to allow mutation
+            // after sealing.
+            writeSessionsLocked();
+        }
     }
 }
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 0616460..38a2016 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -195,6 +195,11 @@
         this.internalStageDir = internalStageDir;
         this.externalStageCid = externalStageCid;
 
+        if ((internalStageDir == null) == (externalStageCid == null)) {
+            throw new IllegalArgumentException(
+                    "Exactly one of internal or external stage must be set");
+        }
+
         mSealed = sealed;
 
         // Always derived at runtime
@@ -395,7 +400,7 @@
         Preconditions.checkNotNull(statusReceiver);
 
         final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(mContext,
-                statusReceiver);
+                statusReceiver, sessionId);
         mHandler.obtainMessage(MSG_COMMIT, adapter.getBinder()).sendToTarget();
     }
 
@@ -414,8 +419,9 @@
             }
             mSealed = true;
 
-            // TODO: persist disabled mutations before going forward, since
-            // beyond this point we may have hardlinks to the valid install
+            // Persist the fact that we've sealed ourselves to prevent mutations
+            // of any hard links we create below.
+            mCallback.onSessionSealed(this);
         }
 
         final File stageDir;
@@ -476,9 +482,8 @@
             }
         };
 
-        // TODO: send ASEC cid if that's where we staged things
-        mPm.installStage(mPackageName, this.internalStageDir, null, localObserver, params,
-                installerPackageName, installerUid, new UserHandle(userId));
+        mPm.installStage(mPackageName, this.internalStageDir, this.externalStageCid, localObserver,
+                params, installerPackageName, installerUid, new UserHandle(userId));
     }
 
     /**
@@ -486,6 +491,9 @@
      * consistent package name, version code, and signing certificates.
      * <p>
      * Renames package files in stage to match split names defined inside.
+     * <p>
+     * Note that upgrade compatibility is still performed by
+     * {@link PackageManagerService}.
      */
     private void validateInstallLocked(File stageDir) throws PackageManagerException {
         mPackageName = null;
@@ -498,13 +506,17 @@
             throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged");
         }
 
-        final ArraySet<String> seenSplits = new ArraySet<>();
-
         // Verify that all staged packages are internally consistent
+        final ArraySet<String> seenSplits = new ArraySet<>();
         for (File file : files) {
+
+            // Installers can't stage directories, so it's fine to ignore
+            // entries like "lost+found".
+            if (file.isDirectory()) continue;
+
             final ApkLite info;
             try {
-                info = PackageParser.parseApkLite(file, PackageParser.PARSE_GET_SIGNATURES);
+                info = PackageParser.parseApkLite(file, PackageParser.PARSE_COLLECT_CERTIFICATES);
             } catch (PackageParserException e) {
                 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
                         "Failed to parse " + file + ": " + e);
@@ -550,10 +562,6 @@
             }
         }
 
-        // TODO: shift package signature verification to installer; we're
-        // currently relying on PMS to do this.
-        // TODO: teach about compatible upgrade keysets.
-
         if (params.mode == SessionParams.MODE_FULL_INSTALL) {
             // Full installs must include a base package
             if (!seenSplits.contains(null)) {
@@ -577,7 +585,7 @@
             final ApkLite info;
             try {
                 info = PackageParser.parseApkLite(new File(app.getBaseCodePath()),
-                        PackageParser.PARSE_GET_SIGNATURES);
+                        PackageParser.PARSE_COLLECT_CERTIFICATES);
             } catch (PackageParserException e) {
                 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
                         "Failed to parse existing base " + app.getBaseCodePath() + ": " + e);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index f47e64f..aa49b27 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -48,11 +48,6 @@
 import static android.os.Process.SYSTEM_UID;
 import static android.system.OsConstants.O_CREAT;
 import static android.system.OsConstants.O_RDWR;
-import static android.system.OsConstants.S_IRGRP;
-import static android.system.OsConstants.S_IROTH;
-import static android.system.OsConstants.S_IRWXU;
-import static android.system.OsConstants.S_IXGRP;
-import static android.system.OsConstants.S_IXOTH;
 import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
 import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_USER_OWNER;
 import static com.android.internal.util.ArrayUtils.appendInt;
@@ -70,7 +65,6 @@
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.IndentingPrintWriter;
-import com.android.internal.util.Preconditions;
 import com.android.server.EventLogTags;
 import com.android.server.IntentResolver;
 import com.android.server.LocalServices;
@@ -255,10 +249,6 @@
     // package apks to install directory.
     private static final String INSTALL_PACKAGE_SUFFIX = "-";
 
-    // Special value for {@code PackageParser.Package#cpuAbiOverride} to indicate
-    // that the cpuAbiOverride must be clear.
-    private static final String CLEAR_ABI_OVERRIDE = "-";
-
     static final int SCAN_MONITOR = 1<<0;
     static final int SCAN_NO_DEX = 1<<1;
     static final int SCAN_FORCE_DEX = 1<<2;
@@ -5022,7 +5012,7 @@
     private static String deriveAbiOverride(String abiOverride, PackageSetting settings) {
         String cpuAbiOverride = null;
 
-        if (CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
+        if (NativeLibraryHelper.CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
             cpuAbiOverride = null;
         } else if (abiOverride != null) {
             cpuAbiOverride = abiOverride;
@@ -5526,7 +5516,8 @@
                     // Warn if we've set an abiOverride for multi-lib packages..
                     // By definition, we need to copy both 32 and 64 bit libraries for
                     // such packages.
-                    if (pkg.cpuAbiOverride != null && !CLEAR_ABI_OVERRIDE.equals(pkg.cpuAbiOverride)) {
+                    if (pkg.cpuAbiOverride != null
+                            && !NativeLibraryHelper.CLEAR_ABI_OVERRIDE.equals(pkg.cpuAbiOverride)) {
                         Slog.w(TAG, "Ignoring abiOverride for multi arch application.");
                     }
 
@@ -5536,7 +5527,7 @@
                         if (isAsec) {
                             abi32 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS);
                         } else {
-                            abi32 = copyNativeLibrariesForInternalApp(handle,
+                            abi32 = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
                                     nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS, useIsaSpecificSubdirs);
                         }
                     }
@@ -5548,7 +5539,7 @@
                         if (isAsec) {
                             abi64 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS);
                         } else {
-                            abi64 = copyNativeLibrariesForInternalApp(handle,
+                            abi64 = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
                                     nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS, useIsaSpecificSubdirs);
                         }
                     }
@@ -5587,8 +5578,8 @@
                     if (isAsec) {
                         copyRet = NativeLibraryHelper.findSupportedAbi(handle, abiList);
                     } else {
-                        copyRet = copyNativeLibrariesForInternalApp(handle, nativeLibraryRoot, abiList,
-                                useIsaSpecificSubdirs);
+                        copyRet = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
+                                nativeLibraryRoot, abiList, useIsaSpecificSubdirs);
                     }
 
                     if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
@@ -6471,58 +6462,6 @@
         }
     }
 
-    private static void createNativeLibrarySubdir(File path) throws IOException {
-        if (!path.isDirectory()) {
-            path.delete();
-
-            if (!path.mkdir()) {
-                throw new IOException("Cannot create " + path.getPath());
-            }
-
-            try {
-                Os.chmod(path.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
-            } catch (ErrnoException e) {
-                throw new IOException("Cannot chmod native library directory "
-                        + path.getPath(), e);
-            }
-        } else if (!SELinux.restorecon(path)) {
-            throw new IOException("Cannot set SELinux context for " + path.getPath());
-        }
-    }
-
-    private static int copyNativeLibrariesForInternalApp(NativeLibraryHelper.Handle handle,
-            final File nativeLibraryRoot, String[] abiList, boolean useIsaSubdir) throws IOException {
-        createNativeLibrarySubdir(nativeLibraryRoot);
-
-        /*
-         * If this is an internal application or our nativeLibraryPath points to
-         * the app-lib directory, unpack the libraries if necessary.
-         */
-        int abi = NativeLibraryHelper.findSupportedAbi(handle, abiList);
-        if (abi >= 0) {
-            /*
-             * If we have a matching instruction set, construct a subdir under the native
-             * library root that corresponds to this instruction set.
-             */
-            final String instructionSet = VMRuntime.getInstructionSet(abiList[abi]);
-            final File subDir;
-            if (useIsaSubdir) {
-                final File isaSubdir = new File(nativeLibraryRoot, instructionSet);
-                createNativeLibrarySubdir(isaSubdir);
-                subDir = isaSubdir;
-            } else {
-                subDir = nativeLibraryRoot;
-            }
-
-            int copyRet = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle, subDir, abiList[abi]);
-            if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
-                return copyRet;
-            }
-        }
-
-        return abi;
-    }
-
     private void killApplication(String pkgName, int appId, String reason) {
         // Request the ActivityManager to kill the process(only for existing packages)
         // so that we do not end up in a confused state while the user is still using the older
@@ -8667,6 +8606,20 @@
          */
         public void handleStartCopy() throws RemoteException {
             int ret = PackageManager.INSTALL_SUCCEEDED;
+
+            // If we're already staged, we've firmly committed to an install location
+            if (originStaged) {
+                if (originFile != null) {
+                    flags |= PackageManager.INSTALL_INTERNAL;
+                    flags &= ~PackageManager.INSTALL_EXTERNAL;
+                } else if (originCid != null) {
+                    flags |= PackageManager.INSTALL_EXTERNAL;
+                    flags &= ~PackageManager.INSTALL_INTERNAL;
+                } else {
+                    throw new IllegalStateException("Invalid stage location");
+                }
+            }
+
             final boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
             final boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0;
             PackageInfoLite pkgLite = null;
@@ -8690,7 +8643,7 @@
                  * If we have too little free space, try to free cache
                  * before giving up.
                  */
-                if (pkgLite.recommendedInstallLocation
+                if (!originStaged && pkgLite.recommendedInstallLocation
                         == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
                     // TODO: focus freeing disk space on the target device
                     final StorageManager storage = StorageManager.from(mContext);
@@ -9287,49 +9240,11 @@
             NativeLibraryHelper.Handle handle = null;
             try {
                 handle = NativeLibraryHelper.Handle.create(codeFile);
-                if (multiArch) {
-                    // Warn if we've set an abiOverride for multi-lib packages..
-                    // By definition, we need to copy both 32 and 64 bit libraries for
-                    // such packages.
-                    if (abiOverride != null &&  !CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
-                        Slog.w(TAG, "Ignoring abiOverride for multi arch application.");
-                    }
-
-                    int copyRet = PackageManager.NO_NATIVE_LIBRARIES;
-                    if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
-                        copyRet = copyNativeLibrariesForInternalApp(handle, libraryRoot,
-                                Build.SUPPORTED_32_BIT_ABIS, true /* use isa specific subdirs */);
-                        maybeThrowExceptionForMultiArchCopy("Failure copying 32 bit native libraries", copyRet);
-                    }
-
-                    if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
-                        copyRet = copyNativeLibrariesForInternalApp(handle, libraryRoot,
-                                Build.SUPPORTED_64_BIT_ABIS, true /* use isa specific subdirs */);
-                        maybeThrowExceptionForMultiArchCopy("Failure copying 64 bit native libraries", copyRet);
-                    }
-                } else {
-                    final String cpuAbiOverride = deriveAbiOverride(this.abiOverride, null /* package setting */);
-                    String[] abiList = (cpuAbiOverride != null) ?
-                            new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS;
-
-                    if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null &&
-                            NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
-                        abiList = Build.SUPPORTED_32_BIT_ABIS;
-                    }
-
-                    int copyRet = copyNativeLibrariesForInternalApp(handle, libraryRoot, abiList,
-                            true /* use isa specific subdirs */);
-                    if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
-                        Slog.w(TAG, "Failure copying native libraries [errorCode=" + copyRet + "]");
-                        return copyRet;
-                    }
-                }
+                ret = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle, libraryRoot,
+                        abiOverride, multiArch);
             } catch (IOException e) {
                 Slog.e(TAG, "Copying native libraries failed", e);
                 ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
-            } catch (PackageManagerException pme) {
-                Slog.e(TAG, "Copying native libraries failed", pme);
-                ret = pme.error;
             } finally {
                 IoUtils.closeQuietly(handle);
             }
@@ -9504,8 +9419,6 @@
      * renaming logic.
      */
     class AsecInstallArgs extends InstallArgs {
-        // TODO: teach about handling cluster directories
-
         static final String RES_FILE_NAME = "pkg.apk";
         static final String PUBLIC_RES_FILE_NAME = "res.zip";
 
@@ -9528,12 +9441,17 @@
             super(null, false, null, (isExternal ? INSTALL_EXTERNAL : 0)
                     | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
                     instructionSets, null, isMultiArch);
+            // Hackily pretend we're still looking at a full code path
+            if (!fullCodePath.endsWith(RES_FILE_NAME)) {
+                fullCodePath = new File(fullCodePath, RES_FILE_NAME).getAbsolutePath();
+            }
+
             // Extract cid from fullCodePath
             int eidx = fullCodePath.lastIndexOf("/");
             String subStr1 = fullCodePath.substring(0, eidx);
             int sidx = subStr1.lastIndexOf("/");
             cid = subStr1.substring(sidx+1, eidx);
-            setCachePath(subStr1);
+            setMountPath(subStr1);
         }
 
         AsecInstallArgs(String cid, String[] instructionSets, boolean isForwardLocked,
@@ -9542,7 +9460,7 @@
                     | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
                     instructionSets, null, isMultiArch);
             this.cid = cid;
-            setCachePath(PackageHelper.getSdDir(cid));
+            setMountPath(PackageHelper.getSdDir(cid));
         }
 
         /** New install from existing */
@@ -9564,7 +9482,7 @@
 
             final File target;
             if (isExternal()) {
-                target = Environment.getExternalStorageDirectory();
+                target = new UserEnvironment(UserHandle.USER_OWNER).getExternalStorageDirectory();
             } else {
                 target = Environment.getDataDirectory();
             }
@@ -9578,6 +9496,7 @@
         }
 
         int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
+            // TODO: if already staged, we only need to extract native code
             if (temp) {
                 createCopyFile();
             } else {
@@ -9588,12 +9507,12 @@
                 PackageHelper.destroySdDir(cid);
             }
 
-            final String newCachePath = imcs.copyPackageToContainer(
+            final String newMountPath = imcs.copyPackageToContainer(
                     originFile.getAbsolutePath(), cid, getEncryptKey(), isExternal(),
                     isFwdLocked(), deriveAbiOverride(abiOverride, null /* settings */));
 
-            if (newCachePath != null) {
-                setCachePath(newCachePath);
+            if (newMountPath != null) {
+                setMountPath(newMountPath);
                 return PackageManager.INSTALL_SUCCEEDED;
             } else {
                 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
@@ -9622,10 +9541,10 @@
             } else {
                 boolean mounted = PackageHelper.isContainerMounted(cid);
                 if (!mounted) {
-                    String newCachePath = PackageHelper.mountSdDir(cid, getEncryptKey(),
+                    String newMountPath = PackageHelper.mountSdDir(cid, getEncryptKey(),
                             Process.SYSTEM_UID);
-                    if (newCachePath != null) {
-                        setCachePath(newCachePath);
+                    if (newMountPath != null) {
+                        setMountPath(newMountPath);
                     } else {
                         return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
                     }
@@ -9636,7 +9555,7 @@
 
         boolean doRename(int status, PackageParser.Package pkg, String oldCodePath) {
             String newCacheId = getNextCodePath(oldCodePath, pkg.packageName, "/" + RES_FILE_NAME);
-            String newCachePath = null;
+            String newMountPath = null;
             if (PackageHelper.isContainerMounted(cid)) {
                 // Unmount the container
                 if (!PackageHelper.unMountSdDir(cid)) {
@@ -9661,46 +9580,59 @@
             }
             if (!PackageHelper.isContainerMounted(newCacheId)) {
                 Slog.w(TAG, "Mounting container " + newCacheId);
-                newCachePath = PackageHelper.mountSdDir(newCacheId,
+                newMountPath = PackageHelper.mountSdDir(newCacheId,
                         getEncryptKey(), Process.SYSTEM_UID);
             } else {
-                newCachePath = PackageHelper.getSdDir(newCacheId);
+                newMountPath = PackageHelper.getSdDir(newCacheId);
             }
-            if (newCachePath == null) {
+            if (newMountPath == null) {
                 Slog.w(TAG, "Failed to get cache path for  " + newCacheId);
                 return false;
             }
             Log.i(TAG, "Succesfully renamed " + cid +
                     " to " + newCacheId +
-                    " at new path: " + newCachePath);
+                    " at new path: " + newMountPath);
             cid = newCacheId;
-            setCachePath(newCachePath);
 
-            // TODO: extend to support split APKs
-            pkg.codePath = getCodePath();
-            pkg.baseCodePath = getCodePath();
-            pkg.splitCodePaths = null;
+            final File beforeCodeFile = new File(packagePath);
+            setMountPath(newMountPath);
+            final File afterCodeFile = new File(packagePath);
 
-            pkg.applicationInfo.setCodePath(getCodePath());
-            pkg.applicationInfo.setBaseCodePath(getCodePath());
-            pkg.applicationInfo.setSplitCodePaths(null);
-            pkg.applicationInfo.setResourcePath(getResourcePath());
-            pkg.applicationInfo.setBaseResourcePath(getResourcePath());
-            pkg.applicationInfo.setSplitResourcePaths(null);
+            // Reflect the rename in scanned details
+            pkg.codePath = afterCodeFile.getAbsolutePath();
+            pkg.baseCodePath = FileUtils.rewriteAfterRename(beforeCodeFile, afterCodeFile,
+                    pkg.baseCodePath);
+            pkg.splitCodePaths = FileUtils.rewriteAfterRename(beforeCodeFile, afterCodeFile,
+                    pkg.splitCodePaths);
+
+            // Reflect the rename in app info
+            pkg.applicationInfo.setCodePath(pkg.codePath);
+            pkg.applicationInfo.setBaseCodePath(pkg.baseCodePath);
+            pkg.applicationInfo.setSplitCodePaths(pkg.splitCodePaths);
+            pkg.applicationInfo.setResourcePath(pkg.codePath);
+            pkg.applicationInfo.setBaseResourcePath(pkg.baseCodePath);
+            pkg.applicationInfo.setSplitResourcePaths(pkg.splitCodePaths);
 
             return true;
         }
 
-        private void setCachePath(String newCachePath) {
-            File cachePath = new File(newCachePath);
-            legacyNativeLibraryDir = new File(cachePath, LIB_DIR_NAME).getPath();
-            packagePath = new File(cachePath, RES_FILE_NAME).getPath();
+        private void setMountPath(String mountPath) {
+            final File mountFile = new File(mountPath);
 
-            if (isFwdLocked()) {
-                resourcePath = new File(cachePath, PUBLIC_RES_FILE_NAME).getPath();
+            final File monolithicFile = new File(mountFile, RES_FILE_NAME);
+            if (monolithicFile.exists()) {
+                packagePath = monolithicFile.getAbsolutePath();
+                if (isFwdLocked()) {
+                    resourcePath = new File(mountFile, PUBLIC_RES_FILE_NAME).getAbsolutePath();
+                } else {
+                    resourcePath = packagePath;
+                }
             } else {
+                packagePath = mountFile.getAbsolutePath();
                 resourcePath = packagePath;
             }
+
+            legacyNativeLibraryDir = new File(mountFile, LIB_DIR_NAME).getAbsolutePath();
         }
 
         int doPostInstall(int status, int uid) {
@@ -9739,23 +9671,43 @@
             PackageHelper.destroySdDir(cid);
         }
 
-        void cleanUpResourcesLI() {
-            String sourceFile = getCodePath();
-            // Remove dex file
-            if (instructionSets == null) {
-                throw new IllegalStateException("instructionSet == null");
-            }
-            String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
-            for (String dexCodeInstructionSet : dexCodeInstructionSets) {
-                int retCode = mInstaller.rmdex(sourceFile, dexCodeInstructionSet);
-                if (retCode < 0) {
-                    Slog.w(TAG, "Couldn't remove dex file for package: "
-                            + " at location "
-                            + sourceFile.toString() + ", retcode=" + retCode);
-                    // we don't consider this to be a failure of the core package deletion
+        private List<String> getAllCodePaths() {
+            final File codeFile = new File(getCodePath());
+            if (codeFile != null && codeFile.exists()) {
+                try {
+                    final PackageLite pkg = PackageParser.parsePackageLite(codeFile, 0);
+                    return pkg.getAllCodePaths();
+                } catch (PackageParserException e) {
+                    // Ignored; we tried our best
                 }
             }
+            return Collections.EMPTY_LIST;
+        }
+
+        void cleanUpResourcesLI() {
+            // Enumerate all code paths before deleting
+            cleanUpResourcesLI(getAllCodePaths());
+        }
+
+        private void cleanUpResourcesLI(List<String> allCodePaths) {
             cleanUp();
+
+            if (!allCodePaths.isEmpty()) {
+                if (instructionSets == null) {
+                    throw new IllegalStateException("instructionSet == null");
+                }
+                String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
+                for (String codePath : allCodePaths) {
+                    for (String dexCodeInstructionSet : dexCodeInstructionSets) {
+                        int retCode = mInstaller.rmdex(codePath, dexCodeInstructionSet);
+                        if (retCode < 0) {
+                            Slog.w(TAG, "Couldn't remove dex file for package: "
+                                    + " at location " + codePath + ", retcode=" + retCode);
+                            // we don't consider this to be a failure of the core package deletion
+                        }
+                    }
+                }
+            }
         }
 
         boolean matchContainer(String app) {
@@ -9770,16 +9722,19 @@
         }
 
         boolean doPostDeleteLI(boolean delete) {
-            boolean ret = false;
+            if (DEBUG_SD_INSTALL) Slog.i(TAG, "doPostDeleteLI() del=" + delete);
+            final List<String> allCodePaths = getAllCodePaths();
             boolean mounted = PackageHelper.isContainerMounted(cid);
             if (mounted) {
                 // Unmount first
-                ret = PackageHelper.unMountSdDir(cid);
+                if (PackageHelper.unMountSdDir(cid)) {
+                    mounted = false;
+                }
             }
-            if (ret && delete) {
-                cleanUpResourcesLI();
+            if (!mounted && delete) {
+                cleanUpResourcesLI(allCodePaths);
             }
-            return ret;
+            return !mounted;
         }
 
         @Override
@@ -10966,6 +10921,7 @@
             outInfo.args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
                     ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString,
                     getAppDexInstructionSets(ps), isMultiArch(ps));
+            if (DEBUG_SD_INSTALL) Slog.i(TAG, "args=" + outInfo.args);
         }
         return true;
     }
@@ -12772,7 +12728,8 @@
                             getAppDexInstructionSets(ps), isForwardLocked(ps), isMultiArch(ps));
                     // The package status is changed only if the code path
                     // matches between settings and the container id.
-                    if (ps.codePathString != null && ps.codePathString.equals(args.getCodePath())) {
+                    if (ps.codePathString != null
+                            && ps.codePathString.startsWith(args.getCodePath())) {
                         if (DEBUG_SD_INSTALL) {
                             Log.i(TAG, "Container : " + cid + " corresponds to pkg : " + pkgName
                                     + " at code path: " + ps.codePathString);
@@ -12851,7 +12808,7 @@
                     continue;
                 }
                 // Check code path here.
-                if (codePath == null || !codePath.equals(args.getCodePath())) {
+                if (codePath == null || !codePath.startsWith(args.getCodePath())) {
                     Slog.e(TAG, "Container " + args.cid + " cachepath " + args.getCodePath()
                             + " does not match one in settings " + codePath);
                     continue;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 2c3c510..02f8bd5 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -18,18 +18,6 @@
 
 import static android.Manifest.permission.MANAGE_CA_CERTIFICATES;
 
-import android.app.admin.DevicePolicyManagerInternal;
-
-import com.android.internal.R;
-import com.android.internal.os.storage.ExternalStorageFormatter;
-import com.android.internal.util.FastXmlSerializer;
-import com.android.internal.util.JournaledFile;
-import com.android.internal.util.XmlUtils;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.org.conscrypt.TrustedCertificateStore;
-import com.android.server.LocalServices;
-import com.android.server.SystemService;
-
 import android.app.Activity;
 import android.app.ActivityManagerNative;
 import android.app.AlarmManager;
@@ -41,6 +29,7 @@
 import android.app.admin.DeviceAdminInfo;
 import android.app.admin.DeviceAdminReceiver;
 import android.app.admin.DevicePolicyManager;
+import android.app.admin.DevicePolicyManagerInternal;
 import android.app.admin.IDevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -90,6 +79,16 @@
 import android.util.Xml;
 import android.view.IWindowManager;
 
+import com.android.internal.R;
+import com.android.internal.os.storage.ExternalStorageFormatter;
+import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.JournaledFile;
+import com.android.internal.util.XmlUtils;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.org.conscrypt.TrustedCertificateStore;
+import com.android.server.LocalServices;
+import com.android.server.SystemService;
+
 import org.xmlpull.v1.XmlPullParser;
 
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
@@ -147,6 +146,21 @@
     private static final String ATTR_PERMISSION_PROVIDER = "permission-provider";
     private static final String ATTR_SETUP_COMPLETE = "setup-complete";
 
+    private static final Set<String> DEVICE_OWNER_USER_RESTRICTIONS;
+    static {
+        DEVICE_OWNER_USER_RESTRICTIONS = new HashSet();
+        DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_USB_FILE_TRANSFER);
+        DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_CONFIG_TETHERING);
+        DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_FACTORY_RESET);
+        DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_ADD_USER);
+        DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_CONFIG_CELL_BROADCASTS);
+        DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
+        DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA);
+        DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_UNMUTE_MICROPHONE);
+        DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_ADJUST_VOLUME);
+        DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_SMS);
+    }
+
     final Context mContext;
     final UserManager mUserManager;
     final PowerManager.WakeLock mWakeLock;
@@ -4046,7 +4060,12 @@
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
             }
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            ActiveAdmin activeAdmin =
+                    getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            boolean isDeviceOwner = isDeviceOwner(activeAdmin.info.getPackageName());
+            if (!isDeviceOwner && DEVICE_OWNER_USER_RESTRICTIONS.contains(key)) {
+                throw new SecurityException("Profile owners cannot set user restriction " + key);
+            }
 
             long id = Binder.clearCallingIdentity();
             try {
diff --git a/telecomm/java/android/telecomm/Call.java b/telecomm/java/android/telecomm/Call.java
index d90ec13..63f85e9 100644
--- a/telecomm/java/android/telecomm/Call.java
+++ b/telecomm/java/android/telecomm/Call.java
@@ -16,6 +16,7 @@
 
 package android.telecomm;
 
+import android.annotation.SystemApi;
 import android.app.PendingIntent;
 import android.net.Uri;
 import android.os.Bundle;
@@ -34,6 +35,7 @@
  *
  * {@hide}
  */
+@SystemApi
 public final class Call {
     /**
      * The state of a {@code Call} when newly created.
diff --git a/telecomm/java/android/telecomm/CallState.java b/telecomm/java/android/telecomm/CallState.java
index 73edbe2..0770e26 100644
--- a/telecomm/java/android/telecomm/CallState.java
+++ b/telecomm/java/android/telecomm/CallState.java
@@ -16,6 +16,8 @@
 
 package android.telecomm;
 
+import android.annotation.SystemApi;
+
 /**
  * Defines call-state constants of the different states in which a call can exist. Although states
  * have the notion of normal transitions, due to the volatile nature of telephony systems, code
@@ -24,6 +26,7 @@
  *
  * {@hide}
  */
+@SystemApi
 public final class CallState {
 
     private CallState() {}
diff --git a/telecomm/java/android/telecomm/Connection.java b/telecomm/java/android/telecomm/Connection.java
index c1d5715..c307a25 100644
--- a/telecomm/java/android/telecomm/Connection.java
+++ b/telecomm/java/android/telecomm/Connection.java
@@ -65,8 +65,6 @@
     // Flag controlling whether PII is emitted into the logs
     private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
 
-    private static Connection sNullConnection;
-
     /** @hide */
     public abstract static class Listener {
         public void onStateChanged(Connection c, int state) {}
@@ -476,9 +474,8 @@
     private boolean mAudioModeIsVoip;
     private StatusHints mStatusHints;
     private int mVideoState;
-    private int mFailureCode;
-    private String mFailureMessage;
-    private boolean mIsCanceled;
+    private int mDisconnectCause;
+    private String mDisconnectMessage;
     private Conference mConference;
     private ConnectionService mConnectionService;
 
@@ -604,17 +601,17 @@
     }
 
     /**
-     * @return The failure code ({@see DisconnectCause}) associated with this failed connection.
+     * @return The {@link DisconnectCause} for this connection.
      */
-    public final int getFailureCode() {
-        return mFailureCode;
+    public final int getDisconnectCause() {
+        return mDisconnectCause;
     }
 
     /**
-     * @return The reason for the connection failure. This will not be displayed to the user.
+     * @return The disconnect message for this connection.
      */
-    public final String getFailureMessage() {
-        return mFailureMessage;
+    public final String getDisconnectMessage() {
+        return mDisconnectMessage;
     }
 
     /**
@@ -778,6 +775,8 @@
      * @param message Optional call-service-provided message about the disconnect.
      */
     public final void setDisconnected(int cause, String message) {
+        mDisconnectCause = cause;
+        mDisconnectMessage = message;
         setState(STATE_DISCONNECTED);
         Log.d(this, "Disconnected with cause %d message %s", cause, message);
         for (Listener l : mListeners) {
@@ -1060,13 +1059,6 @@
         return builder.toString();
     }
 
-    static synchronized Connection getNullConnection() {
-        if (sNullConnection == null) {
-            sNullConnection = new Connection() {};
-        }
-        return sNullConnection;
-    }
-
     private void setState(int state) {
         if (mState == STATE_DISCONNECTED && mState != state) {
             Log.d(this, "Connection already DISCONNECTED; cannot transition out of this state.");
@@ -1082,31 +1074,29 @@
         }
     }
 
-    static class FailureSignalingConnection extends Connection {
-        public FailureSignalingConnection(int code, String message) {
-            setDisconnected(code, message);
+    private static class FailureSignalingConnection extends Connection {
+        public FailureSignalingConnection(int cause, String message) {
+            setDisconnected(cause, message);
         }
     }
 
     /**
      * Return a {@code Connection} which represents a failed connection attempt. The returned
-     * {@code Connection} will have a {@link #getFailureCode()} and {@link #getFailureMessage()}
-     * as specified, a {@link #getState()} of {@link #STATE_DISCONNECTED}.
+     * {@code Connection} will have a {@link #getDisconnectCause()} and
+     * {@link #getDisconnectMessage()} as specified, and a {@link #getState()} of
+     * {@link #STATE_DISCONNECTED}.
      * <p>
      * The returned {@code Connection} can be assumed to {@link #destroy()} itself when appropriate,
      * so users of this method need not maintain a reference to its return value to destroy it.
      *
-     * @param code The failure code ({@see DisconnectCause}).
+     * @param cause The disconnect cause, ({@see DisconnectCause}).
      * @param message A reason for why the connection failed (not intended to be shown to the user).
      * @return A {@code Connection} which indicates failure.
      */
-    public static Connection createFailedConnection(final int code, final String message) {
-        return new FailureSignalingConnection(code, message);
+    public static Connection createFailedConnection(int cause, String message) {
+        return new FailureSignalingConnection(cause, message);
     }
 
-    private static final Connection CANCELED_CONNECTION =
-            new FailureSignalingConnection(DisconnectCause.OUTGOING_CANCELED, null);
-
     /**
      * Return a {@code Connection} which represents a canceled connection attempt. The returned
      * {@code Connection} will have state {@link #STATE_DISCONNECTED}, and cannot be moved out of
@@ -1119,7 +1109,7 @@
      * @return A {@code Connection} which indicates that the underlying call should be canceled.
      */
     public static Connection createCanceledConnection() {
-        return CANCELED_CONNECTION;
+        return new FailureSignalingConnection(DisconnectCause.OUTGOING_CANCELED, null);
     }
 
     private final void  fireOnConferenceableConnectionsChanged() {
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
index 03b6c7b..c805978 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -73,6 +73,8 @@
     private static final int MSG_ON_PHONE_ACCOUNT_CLICKED = 15;
     private static final int MSG_REMOVE_CONNECTION_SERVICE_ADAPTER = 16;
 
+    private static Connection sNullConnection;
+
     private final Map<String, Connection> mConnectionById = new HashMap<>();
     private final Map<Connection, String> mIdByConnection = new HashMap<>();
     private final Map<String, Conference> mConferenceById = new HashMap<>();
@@ -498,36 +500,29 @@
             final String callId,
             final ConnectionRequest request,
             boolean isIncoming) {
-        Log.d(this, "call %s", request);
+        Log.d(this, "createConnection, callManagerAccount: %s, callId: %s, request: %s, " +
+                "isIncoming: %b", callManagerAccount, callId, request, isIncoming);
 
-        Connection createdConnection = isIncoming
+        Connection connection = isIncoming
                 ? onCreateIncomingConnection(callManagerAccount, request)
                 : onCreateOutgoingConnection(callManagerAccount, request);
-
-        if (createdConnection == null) {
-            Log.d(this, "adapter handleCreateConnectionComplete CANCELED %s", callId);
-            // Tell telecomm to try a different service.
-            createdConnection = Connection.createCanceledConnection();
+        Log.d(this, "createConnection, connection: %s", connection);
+        if (connection == null) {
+            connection = Connection.createFailedConnection(DisconnectCause.OUTGOING_FAILURE, null);
         }
-        connectionCreated(callId, request, createdConnection);
-    }
 
-    private void connectionCreated(
-            String callId,
-            ConnectionRequest request,
-            Connection connection) {
-        if (!(connection instanceof Connection.FailureSignalingConnection)) {
+        if (connection.getState() != Connection.STATE_DISCONNECTED) {
             addConnection(callId, connection);
         }
 
         Uri handle = connection.getHandle();
         String number = handle == null ? "null" : handle.getSchemeSpecificPart();
-        Log.v(this, "connectionCreated, parcelableconnection: %s, %d, %s",
+        Log.v(this, "createConnection, number: %s, state: %s, capabilities: %s",
                 Connection.toLogSafePhoneNumber(number),
-                connection.getState(),
+                Connection.stateToString(connection.getState()),
                 PhoneCapabilities.toString(connection.getCallCapabilities()));
 
-        Log.d(this, "adapter handleCreateConnectionSuccessful %s", callId);
+        Log.d(this, "createConnection, calling handleCreateConnectionSuccessful %s", callId);
         mAdapter.handleCreateConnectionComplete(
                 callId,
                 request,
@@ -545,8 +540,8 @@
                         connection.isRequestingRingback(),
                         connection.getAudioModeIsVoip(),
                         connection.getStatusHints(),
-                        connection.getFailureCode(),
-                        connection.getFailureMessage()));
+                        connection.getDisconnectCause(),
+                        connection.getDisconnectMessage()));
     }
 
     private void abort(String callId) {
@@ -598,13 +593,13 @@
         Log.d(this, "conference %s, %s", callId1, callId2);
 
         Connection connection1 = findConnectionForAction(callId1, "conference");
-        if (connection1 == Connection.getNullConnection()) {
+        if (connection1 == getNullConnection()) {
             Log.w(this, "Connection1 missing in conference request %s.", callId1);
             return;
         }
 
         Connection connection2 = findConnectionForAction(callId2, "conference");
-        if (connection2 == Connection.getNullConnection()) {
+        if (connection2 == getNullConnection()) {
             Log.w(this, "Connection2 missing in conference request %s.", callId2);
             return;
         }
@@ -616,7 +611,7 @@
         Log.d(this, "splitFromConference(%s)", callId);
 
         Connection connection = findConnectionForAction(callId, "splitFromConference");
-        if (connection == Connection.getNullConnection()) {
+        if (connection == getNullConnection()) {
             Log.w(this, "Connection missing in conference request %s.", callId);
             return;
         }
@@ -881,6 +876,13 @@
             return mConnectionById.get(callId);
         }
         Log.w(this, "%s - Cannot find Connection %s", action, callId);
-        return Connection.getNullConnection();
+        return getNullConnection();
+    }
+
+    static synchronized Connection getNullConnection() {
+        if (sNullConnection == null) {
+            sNullConnection = new Connection() {};
+        }
+        return sNullConnection;
     }
 }
diff --git a/telecomm/java/android/telecomm/InCallService.java b/telecomm/java/android/telecomm/InCallService.java
index 5795e0e..794ec41 100644
--- a/telecomm/java/android/telecomm/InCallService.java
+++ b/telecomm/java/android/telecomm/InCallService.java
@@ -16,6 +16,7 @@
 
 package android.telecomm;
 
+import android.annotation.SystemApi;
 import android.annotation.SdkConstant;
 import android.app.PendingIntent;
 import android.app.Service;
@@ -39,6 +40,7 @@
  *
  * {@hide}
  */
+@SystemApi
 public abstract class InCallService extends Service {
 
     /**
diff --git a/telecomm/java/android/telecomm/ParcelableConnection.java b/telecomm/java/android/telecomm/ParcelableConnection.java
index 30ff5be..812ee55 100644
--- a/telecomm/java/android/telecomm/ParcelableConnection.java
+++ b/telecomm/java/android/telecomm/ParcelableConnection.java
@@ -41,8 +41,8 @@
     private boolean mRequestingRingback;
     private boolean mAudioModeIsVoip;
     private StatusHints mStatusHints;
-    private int mFailureCode;
-    private String mFailureMessage;
+    private int mDisconnectCause;
+    private String mDisconnectMessage;
 
     /** @hide */
     public ParcelableConnection(
@@ -58,8 +58,8 @@
             boolean requestingRingback,
             boolean audioModeIsVoip,
             StatusHints statusHints,
-            int failureCode,
-            String failureMessage) {
+            int disconnectCause,
+            String disconnectMessage) {
         mPhoneAccount = phoneAccount;
         mState = state;
         mCapabilities = capabilities;
@@ -72,8 +72,8 @@
         mRequestingRingback = requestingRingback;
         mAudioModeIsVoip = audioModeIsVoip;
         mStatusHints = statusHints;
-        mFailureCode = failureCode;
-        mFailureMessage = failureMessage;
+        mDisconnectCause = disconnectCause;
+        mDisconnectMessage = disconnectMessage;
     }
 
     public PhoneAccountHandle getPhoneAccount() {
@@ -125,12 +125,12 @@
         return mStatusHints;
     }
 
-    public final int getFailureCode() {
-        return mFailureCode;
+    public final int getDisconnectCause() {
+        return mDisconnectCause;
     }
 
-    public final String getFailureMessage() {
-        return mFailureMessage;
+    public final String getDisconnectMessage() {
+        return mDisconnectMessage;
     }
 
     @Override
@@ -212,7 +212,7 @@
         destination.writeByte((byte) (mRequestingRingback ? 1 : 0));
         destination.writeByte((byte) (mAudioModeIsVoip ? 1 : 0));
         destination.writeParcelable(mStatusHints, 0);
-        destination.writeInt(mFailureCode);
-        destination.writeString(mFailureMessage);
+        destination.writeInt(mDisconnectCause);
+        destination.writeString(mDisconnectMessage);
     }
 }
diff --git a/telecomm/java/android/telecomm/Phone.java b/telecomm/java/android/telecomm/Phone.java
index 03a8676..e125342 100644
--- a/telecomm/java/android/telecomm/Phone.java
+++ b/telecomm/java/android/telecomm/Phone.java
@@ -16,6 +16,7 @@
 
 package android.telecomm;
 
+import android.annotation.SystemApi;
 import android.app.PendingIntent;
 import android.util.ArrayMap;
 
@@ -31,6 +32,7 @@
  *
  * {@hide}
  */
+@SystemApi
 public final class Phone {
 
     public abstract static class Listener {
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index a561dc2..a01a6b6 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -18,8 +18,8 @@
 
 import android.net.wifi.passpoint.WifiPasspointInfo;
 import android.net.wifi.passpoint.WifiPasspointManager;
-import android.os.Parcelable;
 import android.os.Parcel;
+import android.os.Parcelable;
 
 /**
  * Describes information about a detected access point. In addition
@@ -48,7 +48,10 @@
      */
     public String capabilities;
     /**
-     * The detected signal level in dBm.
+     * The detected signal level in dBm, also known as the RSSI.
+     *
+     * <p>Use {@link android.net.wifi.WifiManager#calculateSignalLevel} to convert this number into
+     * an absolute signal level which can be displayed to a user.
      */
     public int level;
     /**
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index e808136..44a7108 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -323,7 +323,11 @@
     /**
      * Returns the received signal strength indicator of the current 802.11
      * network, in dBm.
-     * @return the RSSI, in the range -127 to 200
+     *
+     * <p>Use {@link android.net.wifi.WifiManager#calculateSignalLevel} to convert this number into
+     * an absolute signal level which can be displayed to a user.
+     *
+     * @return the RSSI.
      */
     public int getRssi() {
         return mRssi;
diff --git a/wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl b/wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl
index 50bec33..54237c4 100644
--- a/wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl
+++ b/wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl
@@ -31,15 +31,5 @@
     Messenger getMessenger();
 
     int getPasspointState();
-
-    List<WifiPasspointPolicy> requestCredentialMatch(in List<ScanResult> requested);
-
-    List<WifiPasspointCredential> getCredentials();
-
-    boolean addCredential(in WifiPasspointCredential cred);
-
-    boolean updateCredential(in WifiPasspointCredential cred);
-
-    boolean removeCredential(in WifiPasspointCredential cred);
 }