Merge "Clean up and fix bugs in ConnectionService.createConnection" into lmp-dev
diff --git a/Android.mk b/Android.mk
index 1cdc709..80b860b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -330,12 +330,6 @@
 	media/java/android/media/projection/IMediaProjectionCallback.aidl \
 	media/java/android/media/projection/IMediaProjectionManager.aidl \
 	media/java/android/media/projection/IMediaProjectionWatcherCallback.aidl \
-	media/java/android/media/routing/IMediaRouteService.aidl \
-	media/java/android/media/routing/IMediaRouteClientCallback.aidl \
-	media/java/android/media/routing/IMediaRouter.aidl \
-	media/java/android/media/routing/IMediaRouterDelegate.aidl \
-	media/java/android/media/routing/IMediaRouterRoutingCallback.aidl \
-	media/java/android/media/routing/IMediaRouterStateCallback.aidl \
 	media/java/android/media/session/IActiveSessionsListener.aidl \
 	media/java/android/media/session/ISessionController.aidl \
 	media/java/android/media/session/ISessionControllerCallback.aidl \
@@ -497,7 +491,6 @@
 	frameworks/base/location/java/com/android/internal/location/ProviderRequest.aidl \
 	frameworks/base/media/java/android/media/MediaMetadata.aidl \
 	frameworks/base/media/java/android/media/Rating.aidl \
-	frameworks/base/media/java/android/media/routing/MediaRouteSelector.aidl \
 	frameworks/base/media/java/android/media/session/MediaSession.aidl \
 	frameworks/base/media/java/android/media/session/PlaybackState.aidl \
 	frameworks/base/telephony/java/android/telephony/ServiceState.aidl \
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 7536998..5159a3a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -23,7 +23,6 @@
     field public static final java.lang.String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN";
     field public static final java.lang.String BIND_DREAM_SERVICE = "android.permission.BIND_DREAM_SERVICE";
     field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD";
-    field public static final java.lang.String BIND_MEDIA_ROUTE_SERVICE = "android.permission.BIND_MEDIA_ROUTE_SERVICE";
     field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE";
     field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
     field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
@@ -930,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
@@ -6755,12 +6755,6 @@
 
 package android.content {
 
-  public abstract class AbstractRestrictionsProvider extends android.content.BroadcastReceiver {
-    ctor public AbstractRestrictionsProvider();
-    method public void onReceive(android.content.Context, android.content.Intent);
-    method public abstract void requestPermission(android.content.Context, java.lang.String, java.lang.String, java.lang.String, android.os.PersistableBundle);
-  }
-
   public abstract class AbstractThreadedSyncAdapter {
     ctor public AbstractThreadedSyncAdapter(android.content.Context, boolean);
     ctor public AbstractThreadedSyncAdapter(android.content.Context, boolean, boolean);
@@ -8674,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";
@@ -16380,242 +16374,6 @@
 
 }
 
-package android.media.routing {
-
-  public final class MediaRouteSelector implements android.os.Parcelable {
-    method public boolean containsProtocol(java.lang.Class<?>);
-    method public boolean containsProtocol(java.lang.String);
-    method public int describeContents();
-    method public android.os.Bundle getExtras();
-    method public int getOptionalFeatures();
-    method public java.util.List<java.lang.String> getOptionalProtocols();
-    method public int getRequiredFeatures();
-    method public java.util.List<java.lang.String> getRequiredProtocols();
-    method public java.lang.String getServicePackageName();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator CREATOR;
-  }
-
-  public static final class MediaRouteSelector.Builder {
-    ctor public MediaRouteSelector.Builder();
-    method public android.media.routing.MediaRouteSelector.Builder addOptionalProtocol(java.lang.Class<?>);
-    method public android.media.routing.MediaRouteSelector.Builder addOptionalProtocol(java.lang.String);
-    method public android.media.routing.MediaRouteSelector.Builder addRequiredProtocol(java.lang.Class<?>);
-    method public android.media.routing.MediaRouteSelector.Builder addRequiredProtocol(java.lang.String);
-    method public android.media.routing.MediaRouteSelector build();
-    method public android.media.routing.MediaRouteSelector.Builder setExtras(android.os.Bundle);
-    method public android.media.routing.MediaRouteSelector.Builder setOptionalFeatures(int);
-    method public android.media.routing.MediaRouteSelector.Builder setRequiredFeatures(int);
-    method public android.media.routing.MediaRouteSelector.Builder setServicePackageName(java.lang.String);
-  }
-
-  public abstract class MediaRouteService extends android.app.Service {
-    ctor public MediaRouteService();
-    method public android.media.routing.MediaRouter.ServiceMetadata getServiceMetadata();
-    method public android.os.IBinder onBind(android.content.Intent);
-    method public abstract android.media.routing.MediaRouteService.ClientSession onCreateClientSession(android.media.routing.MediaRouteService.ClientInfo);
-    field public static final java.lang.String SERVICE_INTERFACE = "android.media.routing.MediaRouteService";
-  }
-
-  public static final class MediaRouteService.ClientInfo {
-    method public java.lang.String getPackageName();
-    method public int getUid();
-  }
-
-  public static abstract class MediaRouteService.ClientSession {
-    ctor public MediaRouteService.ClientSession();
-    method public abstract boolean onConnect(android.media.routing.MediaRouter.ConnectionRequest, android.media.routing.MediaRouteService.ConnectionCallback);
-    method public abstract void onDisconnect();
-    method public void onPauseStream();
-    method public void onRelease();
-    method public void onResumeStream();
-    method public abstract boolean onStartDiscovery(android.media.routing.MediaRouter.DiscoveryRequest, android.media.routing.MediaRouteService.DiscoveryCallback);
-    method public abstract void onStopDiscovery();
-  }
-
-  public final class MediaRouteService.ConnectionCallback {
-    method public void onConnected(android.media.routing.MediaRouter.ConnectionInfo);
-    method public void onConnectionFailed(int, java.lang.CharSequence, android.os.Bundle);
-    method public void onDisconnected();
-  }
-
-  public final class MediaRouteService.DiscoveryCallback {
-    method public void onDestinationFound(android.media.routing.MediaRouter.DestinationInfo, java.util.List<android.media.routing.MediaRouter.RouteInfo>);
-    method public void onDestinationLost(android.media.routing.MediaRouter.DestinationInfo);
-    method public void onDiscoveryFailed(int, java.lang.CharSequence, android.os.Bundle);
-  }
-
-  public final class MediaRouter {
-    ctor public MediaRouter(android.content.Context);
-    method public void addSelector(android.media.routing.MediaRouteSelector);
-    method public void clearSelectors();
-    method public android.media.routing.MediaRouter.Delegate createDelegate();
-    method public android.media.routing.MediaRouter.ConnectionInfo getConnection();
-    method public int getConnectionState();
-    method public java.util.List<android.media.routing.MediaRouter.DestinationInfo> getDiscoveredDestinations();
-    method public java.util.List<android.media.routing.MediaRouter.RouteInfo> getDiscoveredRoutes(android.media.routing.MediaRouter.DestinationInfo);
-    method public int getDiscoveryState();
-    method public android.media.AudioAttributes getPreferredAudioAttributes();
-    method public android.view.Display getPreferredPresentationDisplay();
-    method public android.media.VolumeProvider getPreferredVolumeProvider();
-    method public android.media.routing.MediaRouter.DestinationInfo getSelectedDestination();
-    method public android.media.routing.MediaRouter.RouteInfo getSelectedRoute();
-    method public java.util.List<android.media.routing.MediaRouteSelector> getSelectors();
-    method public boolean isReleased();
-    method public void pauseStream();
-    method public void release();
-    method public void removeSelector(android.media.routing.MediaRouteSelector);
-    method public void resumeStream();
-    method public void setRoutingCallback(android.media.routing.MediaRouter.RoutingCallback, android.os.Handler);
-    field public static final int CONNECTION_ERROR_ABORTED = 1; // 0x1
-    field public static final int CONNECTION_ERROR_BARGED = 7; // 0x7
-    field public static final int CONNECTION_ERROR_BROKEN = 6; // 0x6
-    field public static final int CONNECTION_ERROR_BUSY = 4; // 0x4
-    field public static final int CONNECTION_ERROR_TIMEOUT = 5; // 0x5
-    field public static final int CONNECTION_ERROR_UNAUTHORIZED = 2; // 0x2
-    field public static final int CONNECTION_ERROR_UNKNOWN = 0; // 0x0
-    field public static final int CONNECTION_ERROR_UNREACHABLE = 3; // 0x3
-    field public static final int CONNECTION_FLAG_BARGE = 1; // 0x1
-    field public static final int CONNECTION_STATE_CONNECTED = 2; // 0x2
-    field public static final int CONNECTION_STATE_CONNECTING = 1; // 0x1
-    field public static final int CONNECTION_STATE_DISCONNECTED = 0; // 0x0
-    field public static final int DISCONNECTION_REASON_APPLICATION_REQUEST = 0; // 0x0
-    field public static final int DISCONNECTION_REASON_ERROR = 2; // 0x2
-    field public static final int DISCONNECTION_REASON_USER_REQUEST = 1; // 0x1
-    field public static final int DISCOVERY_ERROR_ABORTED = 1; // 0x1
-    field public static final int DISCOVERY_ERROR_NO_CONNECTIVITY = 2; // 0x2
-    field public static final int DISCOVERY_ERROR_UNKNOWN = 0; // 0x0
-    field public static final int DISCOVERY_FLAG_BACKGROUND = 1; // 0x1
-    field public static final int DISCOVERY_STATE_STARTED = 1; // 0x1
-    field public static final int DISCOVERY_STATE_STOPPED = 0; // 0x0
-    field public static final int ROUTE_FEATURE_LIVE_AUDIO = 1; // 0x1
-    field public static final int ROUTE_FEATURE_LIVE_VIDEO = 2; // 0x2
-  }
-
-  public static final class MediaRouter.ConnectionInfo {
-    method public android.media.AudioAttributes getAudioAttributes();
-    method public android.os.Bundle getExtras();
-    method public int getFeatures();
-    method public android.view.Display getPresentationDisplay();
-    method public android.os.IBinder getProtocolBinder(java.lang.String);
-    method public android.os.IBinder getProtocolBinder(int);
-    method public T getProtocolObject(java.lang.Class<T>);
-    method public java.util.List<java.lang.String> getProtocols();
-    method public android.media.routing.MediaRouter.RouteInfo getRoute();
-    method public android.media.VolumeProvider getVolumeProvider();
-  }
-
-  public static final class MediaRouter.ConnectionInfo.Builder {
-    ctor public MediaRouter.ConnectionInfo.Builder(android.media.routing.MediaRouter.RouteInfo);
-    method public android.media.routing.MediaRouter.ConnectionInfo build();
-    method public android.media.routing.MediaRouter.ConnectionInfo.Builder setAudioAttributes(android.media.AudioAttributes);
-    method public android.media.routing.MediaRouter.ConnectionInfo.Builder setExtras(android.os.Bundle);
-    method public android.media.routing.MediaRouter.ConnectionInfo.Builder setPresentationDisplay(android.view.Display);
-    method public android.media.routing.MediaRouter.ConnectionInfo.Builder setProtocolBinder(java.lang.String, android.os.IBinder);
-    method public android.media.routing.MediaRouter.ConnectionInfo.Builder setProtocolStub(java.lang.Class<?>, android.os.IInterface);
-    method public android.media.routing.MediaRouter.ConnectionInfo.Builder setVolumeProvider(android.media.VolumeProvider);
-  }
-
-  public static final class MediaRouter.ConnectionRequest {
-    method public android.os.Bundle getExtras();
-    method public int getFlags();
-    method public android.media.routing.MediaRouter.RouteInfo getRoute();
-    method public void setExtras(android.os.Bundle);
-    method public void setFlags(int);
-    method public void setRoute(android.media.routing.MediaRouter.RouteInfo);
-  }
-
-  public static final class MediaRouter.Delegate {
-    ctor public MediaRouter.Delegate();
-    method public void addStateCallback(android.media.routing.MediaRouter.StateCallback, android.os.Handler);
-    method public void connect(android.media.routing.MediaRouter.DestinationInfo, int);
-    method public void disconnect(int);
-    method public int getConnectionState();
-    method public java.util.List<android.media.routing.MediaRouter.DestinationInfo> getDiscoveredDestinations();
-    method public int getDiscoveryState();
-    method public android.media.routing.MediaRouter.DestinationInfo getSelectedDestination();
-    method public boolean isReleased();
-    method public void removeStateCallback(android.media.routing.MediaRouter.StateCallback);
-    method public void startDiscovery(int);
-    method public void stopDiscovery();
-  }
-
-  public static final class MediaRouter.DestinationInfo {
-    method public java.lang.CharSequence getDescription();
-    method public android.os.Bundle getExtras();
-    method public int getIconResourceId();
-    method public java.lang.String getId();
-    method public java.lang.CharSequence getName();
-    method public android.media.routing.MediaRouter.ServiceMetadata getServiceMetadata();
-    method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
-  }
-
-  public static final class MediaRouter.DestinationInfo.Builder {
-    ctor public MediaRouter.DestinationInfo.Builder(java.lang.String, android.media.routing.MediaRouter.ServiceMetadata, java.lang.CharSequence);
-    method public android.media.routing.MediaRouter.DestinationInfo build();
-    method public android.media.routing.MediaRouter.DestinationInfo.Builder setDescription(java.lang.CharSequence);
-    method public android.media.routing.MediaRouter.DestinationInfo.Builder setExtras(android.os.Bundle);
-    method public android.media.routing.MediaRouter.DestinationInfo.Builder setIconResourceId(int);
-  }
-
-  public static final class MediaRouter.DiscoveryRequest {
-    method public int getFlags();
-    method public java.util.List<android.media.routing.MediaRouteSelector> getSelectors();
-    method public void setFlags(int);
-    method public void setSelectors(java.util.List<android.media.routing.MediaRouteSelector>);
-  }
-
-  public static final class MediaRouter.RouteInfo {
-    method public android.media.routing.MediaRouter.DestinationInfo getDestination();
-    method public android.os.Bundle getExtras();
-    method public int getFeatures();
-    method public java.lang.String getId();
-    method public java.util.List<java.lang.String> getProtocols();
-    method public android.media.routing.MediaRouteSelector getSelector();
-  }
-
-  public static final class MediaRouter.RouteInfo.Builder {
-    ctor public MediaRouter.RouteInfo.Builder(java.lang.String, android.media.routing.MediaRouter.DestinationInfo, android.media.routing.MediaRouteSelector);
-    method public android.media.routing.MediaRouter.RouteInfo.Builder addProtocol(java.lang.Class<T>);
-    method public android.media.routing.MediaRouter.RouteInfo.Builder addProtocol(java.lang.String);
-    method public android.media.routing.MediaRouter.RouteInfo build();
-    method public android.media.routing.MediaRouter.RouteInfo.Builder setExtras(android.os.Bundle);
-    method public android.media.routing.MediaRouter.RouteInfo.Builder setFeatures(int);
-  }
-
-  public static abstract class MediaRouter.RoutingCallback extends android.media.routing.MediaRouter.StateCallback {
-    ctor public MediaRouter.RoutingCallback();
-    method public boolean onPrepareConnectionRequest(android.media.routing.MediaRouter.ConnectionRequest, android.media.routing.MediaRouter.DestinationInfo, java.util.List<android.media.routing.MediaRouter.RouteInfo>);
-    method public boolean onPrepareDiscoveryRequest(android.media.routing.MediaRouter.DiscoveryRequest, java.util.List<android.media.routing.MediaRouteSelector>);
-  }
-
-  public static final class MediaRouter.ServiceMetadata {
-    method public android.content.ComponentName getComponentName();
-    method public android.graphics.drawable.Drawable getIcon(android.content.pm.PackageManager);
-    method public java.lang.CharSequence getLabel(android.content.pm.PackageManager);
-    method public java.lang.String getPackageName();
-    method public android.content.pm.ServiceInfo getService();
-  }
-
-  public static abstract class MediaRouter.StateCallback {
-    ctor public MediaRouter.StateCallback();
-    method public void onConnected();
-    method public void onConnecting();
-    method public void onConnectionFailed(int, java.lang.CharSequence, android.os.Bundle);
-    method public void onConnectionStateChanged(int);
-    method public void onDestinationFound(android.media.routing.MediaRouter.DestinationInfo);
-    method public void onDestinationLost(android.media.routing.MediaRouter.DestinationInfo);
-    method public void onDisconnected();
-    method public void onDiscoveryFailed(int, java.lang.CharSequence, android.os.Bundle);
-    method public void onDiscoveryStarted();
-    method public void onDiscoveryStateChanged(int);
-    method public void onDiscoveryStopped();
-    method public void onReleased();
-    method public void onSelectedDestinationChanged(android.media.routing.MediaRouter.DestinationInfo);
-  }
-
-}
-
 package android.media.session {
 
   public final class MediaController {
@@ -16623,18 +16381,17 @@
     method public void addCallback(android.media.session.MediaController.Callback);
     method public void addCallback(android.media.session.MediaController.Callback, android.os.Handler);
     method public void adjustVolume(int, int);
-    method public android.media.routing.MediaRouter.Delegate createMediaRouterDelegate();
     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);
@@ -16642,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);
@@ -16662,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();
@@ -16691,19 +16450,16 @@
     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 setMediaRouter(android.media.routing.MediaRouter);
     method public void setMetadata(android.media.MediaMetadata);
     method public void setPlaybackState(android.media.session.PlaybackState);
     method public void setPlaybackToLocal(android.media.AudioAttributes);
     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 {
@@ -16750,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);
   }
@@ -16761,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();
@@ -16805,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);
@@ -17072,6 +16829,7 @@
     method public final java.lang.String getId();
     method public final java.lang.String getLanguage();
     method public final int getType();
+    method public final float getVideoFrameRate();
     method public final int getVideoHeight();
     method public final int getVideoWidth();
     method public void writeToParcel(android.os.Parcel, int);
@@ -17088,6 +16846,7 @@
     method public final android.media.tv.TvTrackInfo.Builder setAudioSampleRate(int);
     method public final android.media.tv.TvTrackInfo.Builder setExtra(android.os.Bundle);
     method public final android.media.tv.TvTrackInfo.Builder setLanguage(java.lang.String);
+    method public final android.media.tv.TvTrackInfo.Builder setVideoFrameRate(float);
     method public final android.media.tv.TvTrackInfo.Builder setVideoHeight(int);
     method public final android.media.tv.TvTrackInfo.Builder setVideoWidth(int);
   }
@@ -18706,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 {
@@ -18897,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 {
@@ -27656,6 +27387,16 @@
 
 }
 
+package android.service.restrictions {
+
+  public abstract class RestrictionsReceiver extends android.content.BroadcastReceiver {
+    ctor public RestrictionsReceiver();
+    method public void onReceive(android.content.Context, android.content.Intent);
+    method public abstract void onRequestPermission(android.content.Context, java.lang.String, java.lang.String, java.lang.String, android.os.PersistableBundle);
+  }
+
+}
+
 package android.service.textservice {
 
   public abstract class SpellCheckerService extends android.app.Service {
@@ -35191,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/Notification.java b/core/java/android/app/Notification.java
index 5f58839..70ba8ea 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1607,6 +1607,7 @@
         builder.setPriority(this.priority);
         builder.setTicker(this.tickerText);
         builder.setNumber(this.number);
+        builder.setColor(this.color);
         builder.mFlags = this.flags;
         builder.setSound(this.sound, this.audioStreamType);
         builder.setDefaults(this.defaults);
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/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index f3f0c4d..053afb7 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -21,7 +21,6 @@
 import android.annotation.SystemApi;
 import android.app.Activity;
 import android.app.admin.IDevicePolicyManager;
-import android.content.AbstractRestrictionsProvider;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -39,6 +38,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.service.restrictions.RestrictionsReceiver;
 import android.util.Log;
 
 import com.android.org.conscrypt.TrustedCertificateStore;
@@ -3037,7 +3037,7 @@
      * Only a profile owner can designate the restrictions provider.
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param provider The component name of the service that implements
-     * {@link AbstractRestrictionsProvider}. If this param is null,
+     * {@link RestrictionsReceiver}. If this param is null,
      * it removes the restrictions provider previously assigned.
      */
     public void setRestrictionsProvider(ComponentName admin, ComponentName provider) {
diff --git a/core/java/android/content/AbstractRestrictionsProvider.java b/core/java/android/content/AbstractRestrictionsProvider.java
index 2b40870..262980e 100644
--- a/core/java/android/content/AbstractRestrictionsProvider.java
+++ b/core/java/android/content/AbstractRestrictionsProvider.java
@@ -21,6 +21,7 @@
 import android.os.PersistableBundle;
 
 /**
+ * @hide
  * Abstract implementation of a Restrictions Provider BroadcastReceiver. To implement a
  * Restrictions Provider, extend from this class and implement the abstract methods.
  * Export this receiver in the manifest. A profile owner device admin can then register this
@@ -33,6 +34,8 @@
  * {@link RestrictionsManager#notifyPermissionResponse(String, PersistableBundle)}.
  *
  * @see RestrictionsManager
+ * TODO: STOPSHIP: Remove before L ships, after clients have switched over
+ * to android.service.restrictions.RestrictionsReceiver. Bug: 17006805
  */
 public abstract class AbstractRestrictionsProvider extends BroadcastReceiver {
 
diff --git a/core/java/android/content/RestrictionsManager.java b/core/java/android/content/RestrictionsManager.java
index c1226c0..849df55 100644
--- a/core/java/android/content/RestrictionsManager.java
+++ b/core/java/android/content/RestrictionsManager.java
@@ -26,6 +26,7 @@
 import android.os.Bundle;
 import android.os.PersistableBundle;
 import android.os.RemoteException;
+import android.service.restrictions.RestrictionsReceiver;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Xml;
@@ -107,7 +108,7 @@
  * </pre>
  *
  * @see RestrictionEntry
- * @see AbstractRestrictionsProvider
+ * @see RestrictionsReceiver
  * @see DevicePolicyManager#setRestrictionsProvider(ComponentName, ComponentName)
  * @see DevicePolicyManager#setApplicationRestrictions(ComponentName, String, Bundle)
  */
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/Camera.java b/core/java/android/hardware/Camera.java
index eadfa73..310ab76 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -1558,6 +1558,26 @@
         return _enableShutterSound(enabled);
     }
 
+    /**
+     * Disable the shutter sound unconditionally.
+     *
+     * <p>
+     * This is only guaranteed to work for legacy cameras
+     * (i.e. initialized with {@link #cameraInitUnspecified}). Trying to call this on
+     * a regular camera will force a conditional check in the camera service.
+     * </p>
+     *
+     * @return {@code true} if the shutter sound state was successfully
+     *         changed. {@code false} if the shutter sound state could not be
+     *         changed. {@code true} is also returned if shutter sound playback
+     *         is already set to the requested state.
+     *
+     * @hide
+     */
+    public final boolean disableShutterSound() {
+        return _enableShutterSound(/*enabled*/false);
+    }
+
     private native final boolean _enableShutterSound(boolean enabled);
 
     /**
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/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
index c68d8c3..5cbf109 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
@@ -56,6 +56,7 @@
  * Keep up to date with ICameraDeviceUser.aidl.
  * </p>
  */
+@SuppressWarnings("deprecation")
 public class CameraDeviceUserShim implements ICameraDeviceUser {
     private static final String TAG = "CameraDeviceUserShim";
 
@@ -259,6 +260,7 @@
                 super(l);
             }
 
+            @Override
             public void handleMessage(Message msg) {
                 try {
                     switch (msg.what) {
@@ -320,6 +322,9 @@
         // Check errors old HAL initialization
         CameraBinderDecorator.throwOnError(initErrors);
 
+        // Disable shutter sounds (this will work unconditionally) for api2 clients
+        legacyCamera.disableShutterSound();
+
         CameraInfo info = new CameraInfo();
         Camera.getCameraInfo(cameraId, info);
 
diff --git a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
index d8da80e..7abea36 100644
--- a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
+++ b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
@@ -416,7 +416,8 @@
         switch (mHdmiDeviceType) {
             case HDMI_DEVICE_TYPE_CEC:
                 s.append("CEC: ");
-                s.append("logical_address: ").append(mLogicalAddress).append(" ");
+                s.append("logical_address: ").append(String.format("0x%02X", mLogicalAddress));
+                s.append(" ");
                 s.append("device_type: ").append(mDeviceType).append(" ");
                 s.append("vendor_id: ").append(mVendorId).append(" ");
                 s.append("display_name: ").append(mDisplayName).append(" ");
@@ -424,8 +425,8 @@
                 break;
             case HDMI_DEVICE_TYPE_MHL:
                 s.append("MHL: ");
-                s.append("device_id: ").append(mDeviceId).append(" ");
-                s.append("adopter_id: ").append(mAdopterId).append(" ");
+                s.append("device_id: ").append(String.format("0x%04X", mDeviceId)).append(" ");
+                s.append("adopter_id: ").append(String.format("0x%04X", mAdopterId)).append(" ");
                 break;
 
             case HDMI_DEVICE_TYPE_HARDWARE:
@@ -434,7 +435,8 @@
             default:
                 return "";
         }
-        s.append("physical_address: ").append(String.format("0x04X", mPhysicalAddress)).append(" ");
+        s.append("physical_address: ").append(String.format("0x%04X", mPhysicalAddress));
+        s.append(" ");
         s.append("port_id: ").append(mPortId);
         return s.toString();
     }
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/provider/Settings.java b/core/java/android/provider/Settings.java
index 5e77d28..52f1dd9 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -305,7 +305,7 @@
 
     /**
      * Activity Action: Show settings to allow configuration of
-     * {@link android.media.routing.MediaRouteService media route providers}.
+     * cast endpoints.
      * <p>
      * In some cases, a matching Activity may not exist, so ensure you
      * safeguard against this.
diff --git a/core/java/android/service/restrictions/RestrictionsReceiver.java b/core/java/android/service/restrictions/RestrictionsReceiver.java
new file mode 100644
index 0000000..7c6e1f6
--- /dev/null
+++ b/core/java/android/service/restrictions/RestrictionsReceiver.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.restrictions;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.RestrictionsManager;
+import android.os.IBinder;
+import android.os.PersistableBundle;
+
+/**
+ * Abstract implementation of a Restrictions Provider BroadcastReceiver. To implement a
+ * Restrictions Provider, extend from this class and implement the abstract methods.
+ * Export this receiver in the manifest. A profile owner device admin can then register this
+ * component as a Restrictions Provider using
+ * {@link DevicePolicyManager#setRestrictionsProvider(ComponentName, ComponentName)}.
+ * <p>
+ * The function of a Restrictions Provider is to transport permission requests from apps on this
+ * device to an administrator (most likely on a remote device or computer) and deliver back
+ * responses. The response should be sent back to the app via
+ * {@link RestrictionsManager#notifyPermissionResponse(String, PersistableBundle)}.
+ *
+ * @see RestrictionsManager
+ */
+public abstract class RestrictionsReceiver extends BroadcastReceiver {
+
+    private static final String TAG = "RestrictionsReceiver";
+
+    /**
+     * An asynchronous permission request made by an application for an operation that requires
+     * authorization by a local or remote administrator other than the user. The Restrictions
+     * Provider should transfer the request to the administrator and deliver back a response, when
+     * available. The calling application is aware that the response could take an indefinite
+     * amount of time.
+     * <p>
+     * If the request bundle contains the key {@link RestrictionsManager#REQUEST_KEY_NEW_REQUEST},
+     * then a new request must be sent. Otherwise the provider can look up any previous response
+     * to the same requestId and return the cached response.
+     *
+     * @param packageName the application requesting permission.
+     * @param requestType the type of request, which determines the content and presentation of
+     * the request data.
+     * @param request the request data bundle containing at a minimum a request id.
+     *
+     * @see RestrictionsManager#REQUEST_TYPE_APPROVAL
+     * @see RestrictionsManager#REQUEST_TYPE_LOCAL_APPROVAL
+     * @see RestrictionsManager#REQUEST_KEY_ID
+     */
+    public abstract void onRequestPermission(Context context,
+            String packageName, String requestType, String requestId, PersistableBundle request);
+
+    /**
+     * Intercept standard Restrictions Provider broadcasts.  Implementations
+     * should not override this method; it is better to implement the
+     * convenience callbacks for each action.
+     */
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        String action = intent.getAction();
+
+        if (RestrictionsManager.ACTION_REQUEST_PERMISSION.equals(action)) {
+            String packageName = intent.getStringExtra(RestrictionsManager.EXTRA_PACKAGE_NAME);
+            String requestType = intent.getStringExtra(RestrictionsManager.EXTRA_REQUEST_TYPE);
+            String requestId = intent.getStringExtra(RestrictionsManager.EXTRA_REQUEST_ID);
+            PersistableBundle request = (PersistableBundle)
+                    intent.getParcelableExtra(RestrictionsManager.EXTRA_REQUEST_BUNDLE);
+            onRequestPermission(context, packageName, requestType, requestId, request);
+        }
+    }
+}
diff --git a/core/java/android/transition/ChangeBounds.java b/core/java/android/transition/ChangeBounds.java
index efcbdb3..6246cbe 100644
--- a/core/java/android/transition/ChangeBounds.java
+++ b/core/java/android/transition/ChangeBounds.java
@@ -16,13 +16,11 @@
 
 package android.transition;
 
-import android.animation.TypeConverter;
 import android.content.Context;
 import android.graphics.PointF;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
 import android.animation.RectEvaluator;
@@ -119,9 +117,11 @@
         values.values.put(PROPNAME_BOUNDS, new Rect(view.getLeft(), view.getTop(),
                 view.getRight(), view.getBottom()));
         values.values.put(PROPNAME_PARENT, values.view.getParent());
-        values.view.getLocationInWindow(tempLocation);
-        values.values.put(PROPNAME_WINDOW_X, tempLocation[0]);
-        values.values.put(PROPNAME_WINDOW_Y, tempLocation[1]);
+        if (mReparent) {
+            values.view.getLocationInWindow(tempLocation);
+            values.values.put(PROPNAME_WINDOW_X, tempLocation[0]);
+            values.values.put(PROPNAME_WINDOW_Y, tempLocation[1]);
+        }
     }
 
     @Override
@@ -134,6 +134,19 @@
         captureValues(transitionValues);
     }
 
+    private boolean parentMatches(View startParent, View endParent) {
+        boolean parentMatches = true;
+        if (mReparent) {
+            TransitionValues endValues = getMatchedTransitionValues(startParent, true);
+            if (endValues == null) {
+                parentMatches = startParent == endParent;
+            } else {
+                parentMatches = endParent == endValues.view;
+            }
+        }
+        return parentMatches;
+    }
+
     @Override
     public Animator createAnimator(final ViewGroup sceneRoot, TransitionValues startValues,
             TransitionValues endValues) {
@@ -148,13 +161,7 @@
             return null;
         }
         final View view = endValues.view;
-        boolean parentsEqual = (startParent == endParent) ||
-                (startParent.getId() == endParent.getId());
-        // TODO: Might want reparenting to be separate/subclass transition, or at least
-        // triggered by a property on ChangeBounds. Otherwise, we're forcing the requirement that
-        // all parents in layouts have IDs to avoid layout-inflation resulting in a side-effect
-        // of reparenting the views.
-        if (!mReparent || parentsEqual) {
+        if (parentMatches(startParent, endParent)) {
             Rect startBounds = (Rect) startValues.values.get(PROPNAME_BOUNDS);
             Rect endBounds = (Rect) endValues.values.get(PROPNAME_BOUNDS);
             int startLeft = startBounds.left;
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index 2fa8d2a..0d32d40 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -192,6 +192,8 @@
     private TransitionValuesMaps mEndValues = new TransitionValuesMaps();
     TransitionSet mParent = null;
     private int[] mMatchOrder = DEFAULT_MATCH_ORDER;
+    ArrayList<TransitionValues> mStartValuesList; // only valid after playTransition starts
+    ArrayList<TransitionValues> mEndValuesList; // only valid after playTransitions starts
 
     // Per-animator information used for later canceling when future transitions overlap
     private static ThreadLocal<ArrayMap<Animator, AnimationInfo>> sRunningAnimators =
@@ -518,32 +520,28 @@
     }
 
     /**
-     * Match start/end values by View instance. Adds matched values to startValuesList
-     * and endValuesList and removes them from unmatchedStart and unmatchedEnd.
+     * Match start/end values by View instance. Adds matched values to mStartValuesList
+     * and mEndValuesList and removes them from unmatchedStart and unmatchedEnd.
      */
-    private void matchInstances(ArrayList<TransitionValues> startValuesList,
-            ArrayList<TransitionValues> endValuesList,
-            ArrayMap<View, TransitionValues> unmatchedStart,
+    private void matchInstances(ArrayMap<View, TransitionValues> unmatchedStart,
             ArrayMap<View, TransitionValues> unmatchedEnd) {
         for (int i = unmatchedStart.size() - 1; i >= 0; i--) {
             View view = unmatchedStart.keyAt(i);
             TransitionValues end = unmatchedEnd.remove(view);
             if (end != null) {
                 TransitionValues start = unmatchedStart.removeAt(i);
-                startValuesList.add(start);
-                endValuesList.add(end);
+                mStartValuesList.add(start);
+                mEndValuesList.add(end);
             }
         }
     }
 
     /**
-     * Match start/end values by Adapter item ID. Adds matched values to startValuesList
-     * and endValuesList and removes them from unmatchedStart and unmatchedEnd, using
+     * Match start/end values by Adapter item ID. Adds matched values to mStartValuesList
+     * and mEndValuesList and removes them from unmatchedStart and unmatchedEnd, using
      * startItemIds and endItemIds as a guide for which Views have unique item IDs.
      */
-    private void matchItemIds(ArrayList<TransitionValues> startValuesList,
-            ArrayList<TransitionValues> endValuesList,
-            ArrayMap<View, TransitionValues> unmatchedStart,
+    private void matchItemIds(ArrayMap<View, TransitionValues> unmatchedStart,
             ArrayMap<View, TransitionValues> unmatchedEnd,
             LongSparseArray<View> startItemIds, LongSparseArray<View> endItemIds) {
         int numStartIds = startItemIds.size();
@@ -555,8 +553,8 @@
                     TransitionValues startValues = unmatchedStart.get(startView);
                     TransitionValues endValues = unmatchedEnd.get(endView);
                     if (startValues != null && endValues != null) {
-                        startValuesList.add(startValues);
-                        endValuesList.add(endValues);
+                        mStartValuesList.add(startValues);
+                        mEndValuesList.add(endValues);
                         unmatchedStart.remove(startView);
                         unmatchedEnd.remove(endView);
                     }
@@ -566,13 +564,11 @@
     }
 
     /**
-     * Match start/end values by Adapter view ID. Adds matched values to startValuesList
-     * and endValuesList and removes them from unmatchedStart and unmatchedEnd, using
+     * Match start/end values by Adapter view ID. Adds matched values to mStartValuesList
+     * and mEndValuesList and removes them from unmatchedStart and unmatchedEnd, using
      * startIds and endIds as a guide for which Views have unique IDs.
      */
-    private void matchIds(ArrayList<TransitionValues> startValuesList,
-            ArrayList<TransitionValues> endValuesList,
-            ArrayMap<View, TransitionValues> unmatchedStart,
+    private void matchIds(ArrayMap<View, TransitionValues> unmatchedStart,
             ArrayMap<View, TransitionValues> unmatchedEnd,
             SparseArray<View> startIds, SparseArray<View> endIds) {
         int numStartIds = startIds.size();
@@ -584,8 +580,8 @@
                     TransitionValues startValues = unmatchedStart.get(startView);
                     TransitionValues endValues = unmatchedEnd.get(endView);
                     if (startValues != null && endValues != null) {
-                        startValuesList.add(startValues);
-                        endValuesList.add(endValues);
+                        mStartValuesList.add(startValues);
+                        mEndValuesList.add(endValues);
                         unmatchedStart.remove(startView);
                         unmatchedEnd.remove(endView);
                     }
@@ -595,13 +591,11 @@
     }
 
     /**
-     * Match start/end values by Adapter transitionName. Adds matched values to startValuesList
-     * and endValuesList and removes them from unmatchedStart and unmatchedEnd, using
+     * Match start/end values by Adapter transitionName. Adds matched values to mStartValuesList
+     * and mEndValuesList and removes them from unmatchedStart and unmatchedEnd, using
      * startNames and endNames as a guide for which Views have unique transitionNames.
      */
-    private void matchNames(ArrayList<TransitionValues> startValuesList,
-            ArrayList<TransitionValues> endValuesList,
-            ArrayMap<View, TransitionValues> unmatchedStart,
+    private void matchNames(ArrayMap<View, TransitionValues> unmatchedStart,
             ArrayMap<View, TransitionValues> unmatchedEnd,
             ArrayMap<String, View> startNames, ArrayMap<String, View> endNames) {
         int numStartNames = startNames.size();
@@ -613,8 +607,8 @@
                     TransitionValues startValues = unmatchedStart.get(startView);
                     TransitionValues endValues = unmatchedEnd.get(endView);
                     if (startValues != null && endValues != null) {
-                        startValuesList.add(startValues);
-                        endValuesList.add(endValues);
+                        mStartValuesList.add(startValues);
+                        mEndValuesList.add(endValues);
                         unmatchedStart.remove(startView);
                         unmatchedEnd.remove(endView);
                     }
@@ -624,30 +618,26 @@
     }
 
     /**
-     * Adds all values from unmatchedStart and unmatchedEnd to startValuesList and endValuesList,
+     * Adds all values from unmatchedStart and unmatchedEnd to mStartValuesList and mEndValuesList,
      * assuming that there is no match between values in the list.
      */
-    private void addUnmatched(ArrayList<TransitionValues> startValuesList,
-            ArrayList<TransitionValues> endValuesList,
-            ArrayMap<View, TransitionValues> unmatchedStart,
+    private void addUnmatched(ArrayMap<View, TransitionValues> unmatchedStart,
             ArrayMap<View, TransitionValues> unmatchedEnd) {
         // Views that only exist in the start Scene
         for (int i = 0; i < unmatchedStart.size(); i++) {
-            startValuesList.add(unmatchedStart.valueAt(i));
-            endValuesList.add(null);
+            mStartValuesList.add(unmatchedStart.valueAt(i));
+            mEndValuesList.add(null);
         }
 
         // Views that only exist in the end Scene
         for (int i = 0; i < unmatchedEnd.size(); i++) {
-            endValuesList.add(unmatchedEnd.valueAt(i));
-            startValuesList.add(null);
+            mEndValuesList.add(unmatchedEnd.valueAt(i));
+            mStartValuesList.add(null);
         }
     }
 
     private void matchStartAndEnd(TransitionValuesMaps startValues,
-            TransitionValuesMaps endValues,
-            ArrayList<TransitionValues> startValuesList,
-            ArrayList<TransitionValues> endValuesList) {
+            TransitionValuesMaps endValues) {
         ArrayMap<View, TransitionValues> unmatchedStart =
                 new ArrayMap<View, TransitionValues>(startValues.viewValues);
         ArrayMap<View, TransitionValues> unmatchedEnd =
@@ -656,23 +646,23 @@
         for (int i = 0; i < mMatchOrder.length; i++) {
             switch (mMatchOrder[i]) {
                 case MATCH_INSTANCE:
-                    matchInstances(startValuesList, endValuesList, unmatchedStart, unmatchedEnd);
+                    matchInstances(unmatchedStart, unmatchedEnd);
                     break;
                 case MATCH_NAME:
-                    matchNames(startValuesList, endValuesList, unmatchedStart, unmatchedEnd,
+                    matchNames(unmatchedStart, unmatchedEnd,
                             startValues.nameValues, endValues.nameValues);
                     break;
                 case MATCH_ID:
-                    matchIds(startValuesList, endValuesList, unmatchedStart, unmatchedEnd,
+                    matchIds(unmatchedStart, unmatchedEnd,
                             startValues.idValues, endValues.idValues);
                     break;
                 case MATCH_ITEM_ID:
-                    matchItemIds(startValuesList, endValuesList, unmatchedStart, unmatchedEnd,
+                    matchItemIds(unmatchedStart, unmatchedEnd,
                             startValues.itemIdValues, endValues.itemIdValues);
                     break;
             }
         }
-        addUnmatched(startValuesList, endValuesList, unmatchedStart, unmatchedEnd);
+        addUnmatched(unmatchedStart, unmatchedEnd);
     }
 
     /**
@@ -687,19 +677,17 @@
      * @hide
      */
     protected void createAnimators(ViewGroup sceneRoot, TransitionValuesMaps startValues,
-            TransitionValuesMaps endValues) {
+            TransitionValuesMaps endValues, ArrayList<TransitionValues> startValuesList,
+            ArrayList<TransitionValues> endValuesList) {
         if (DBG) {
             Log.d(LOG_TAG, "createAnimators() for " + this);
         }
-        ArrayList<TransitionValues> startValuesList = new ArrayList<TransitionValues>();
-        ArrayList<TransitionValues> endValuesList = new ArrayList<TransitionValues>();
-        matchStartAndEnd(startValues, endValues, startValuesList, endValuesList);
-
         ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
         long minStartDelay = Long.MAX_VALUE;
         int minAnimator = mAnimators.size();
         SparseLongArray startDelays = new SparseLongArray();
-        for (int i = 0; i < startValuesList.size(); ++i) {
+        int startValuesListCount = startValuesList.size();
+        for (int i = 0; i < startValuesListCount; ++i) {
             TransitionValues start = startValuesList.get(i);
             TransitionValues end = endValuesList.get(i);
             // Only bother trying to animate with valid values that differ between start/end
@@ -1523,11 +1511,13 @@
             mStartValues.idValues.clear();
             mStartValues.itemIdValues.clear();
             mStartValues.nameValues.clear();
+            mStartValuesList = null;
         } else {
             mEndValues.viewValues.clear();
             mEndValues.idValues.clear();
             mEndValues.itemIdValues.clear();
             mEndValues.nameValues.clear();
+            mEndValuesList = null;
         }
     }
 
@@ -1613,6 +1603,45 @@
     }
 
     /**
+     * Find the matched start or end value for a given View. This is only valid
+     * after playTransition starts. For example, it will be valid in
+     * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)}, but not
+     * in {@link #captureStartValues(TransitionValues)}.
+     *
+     * @param view The view to find the match for.
+     * @param viewInStart Is View from the start values or end values.
+     * @return The matching TransitionValues for view in either start or end values, depending
+     * on viewInStart or null if there is no match for the given view.
+     */
+    TransitionValues getMatchedTransitionValues(View view, boolean viewInStart) {
+        if (mParent != null) {
+            return mParent.getMatchedTransitionValues(view, viewInStart);
+        }
+        ArrayList<TransitionValues> lookIn = viewInStart ? mStartValuesList : mEndValuesList;
+        if (lookIn == null) {
+            return null;
+        }
+        int count = lookIn.size();
+        int index = -1;
+        for (int i = 0; i < count; i++) {
+            TransitionValues values = lookIn.get(i);
+            if (values == null) {
+                return null;
+            }
+            if (values.view == view) {
+                index = i;
+                break;
+            }
+        }
+        TransitionValues values = null;
+        if (index >= 0) {
+            ArrayList<TransitionValues> matchIn = viewInStart ? mEndValuesList : mStartValuesList;
+            values = matchIn.get(index);
+        }
+        return values;
+    }
+
+    /**
      * Pauses this transition, sending out calls to {@link
      * TransitionListener#onTransitionPause(Transition)} to all listeners
      * and pausing all running animators started by this transition.
@@ -1684,6 +1713,10 @@
      * runAnimations() to actually start the animations.
      */
     void playTransition(ViewGroup sceneRoot) {
+        mStartValuesList = new ArrayList<TransitionValues>();
+        mEndValuesList = new ArrayList<TransitionValues>();
+        matchStartAndEnd(mStartValues, mEndValues);
+
         ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
         int numOldAnims = runningAnimators.size();
         WindowId windowId = sceneRoot.getWindowId();
@@ -1694,7 +1727,7 @@
                 if (oldInfo != null && oldInfo.view != null && oldInfo.windowId == windowId) {
                     TransitionValues oldValues = oldInfo.values;
                     View oldView = oldInfo.view;
-                    TransitionValues newValues = mEndValues.viewValues.get(oldView);
+                    TransitionValues newValues = getMatchedTransitionValues(oldView, true);
                     boolean cancel = oldInfo.transition.areValuesChanged(oldValues, newValues);
                     if (cancel) {
                         if (anim.isRunning() || anim.isStarted()) {
@@ -1713,7 +1746,7 @@
             }
         }
 
-        createAnimators(sceneRoot, mStartValues, mEndValues);
+        createAnimators(sceneRoot, mStartValues, mEndValues, mStartValuesList, mEndValuesList);
         runAnimators();
     }
 
@@ -2055,6 +2088,8 @@
             clone.mAnimators = new ArrayList<Animator>();
             clone.mStartValues = new TransitionValuesMaps();
             clone.mEndValues = new TransitionValuesMaps();
+            clone.mStartValuesList = null;
+            clone.mEndValuesList = null;
         } catch (CloneNotSupportedException e) {}
 
         return clone;
diff --git a/core/java/android/transition/TransitionSet.java b/core/java/android/transition/TransitionSet.java
index 68af2d1..f6499ae 100644
--- a/core/java/android/transition/TransitionSet.java
+++ b/core/java/android/transition/TransitionSet.java
@@ -386,11 +386,13 @@
      */
     @Override
     protected void createAnimators(ViewGroup sceneRoot, TransitionValuesMaps startValues,
-            TransitionValuesMaps endValues) {
+            TransitionValuesMaps endValues, ArrayList<TransitionValues> startValuesList,
+            ArrayList<TransitionValues> endValuesList) {
         startValues = removeExcludes(startValues);
         endValues = removeExcludes(endValues);
         for (Transition childTransition : mTransitions) {
-            childTransition.createAnimators(sceneRoot, startValues, endValues);
+            childTransition.createAnimators(sceneRoot, startValues, endValues, startValuesList,
+                    endValuesList);
         }
     }
 
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index cec7e63..f17daaf 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.
@@ -13831,6 +13849,7 @@
                     } else {
                         draw(canvas);
                     }
+                    drawAccessibilityFocus(canvas);
                 }
             } finally {
                 renderNode.end(canvas);
@@ -14125,6 +14144,7 @@
             } else {
                 draw(canvas);
             }
+            drawAccessibilityFocus(canvas);
 
             canvas.restoreToCount(restoreCount);
             canvas.setBitmap(null);
@@ -14199,6 +14219,7 @@
         } else {
             draw(canvas);
         }
+        drawAccessibilityFocus(canvas);
 
         mPrivateFlags = flags;
 
@@ -14792,9 +14813,13 @@
                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
                         mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                         dispatchDraw(canvas);
+                        if (mOverlay != null && !mOverlay.isEmpty()) {
+                            mOverlay.getOverlayView().draw(canvas);
+                        }
                     } else {
                         draw(canvas);
                     }
+                    drawAccessibilityFocus(canvas);
                 } else {
                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                     ((HardwareCanvas) canvas).drawRenderNode(renderNode, null, flags);
@@ -15046,6 +15071,45 @@
     }
 
     /**
+     * Draws the accessibility focus rect onto the specified canvas.
+     *
+     * @param canvas Canvas on which to draw the focus rect
+     */
+    private void drawAccessibilityFocus(Canvas canvas) {
+        if (mAttachInfo == null) {
+            return;
+        }
+
+        final Rect bounds = mAttachInfo.mTmpInvalRect;
+        final ViewRootImpl viewRoot = getViewRootImpl();
+        if (viewRoot == null || viewRoot.getAccessibilityFocusedHost() != this) {
+            return;
+        }
+
+        final AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
+        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
+            return;
+        }
+
+        final Drawable drawable = viewRoot.getAccessibilityFocusedDrawable();
+        if (drawable == null) {
+            return;
+        }
+
+        final AccessibilityNodeInfo virtualView = viewRoot.getAccessibilityFocusedVirtualView();
+        if (virtualView != null) {
+            virtualView.getBoundsInParent(bounds);
+        } else {
+            bounds.set(0, 0, mRight - mLeft, mBottom - mTop);
+        }
+
+        canvas.translate(mScrollX, mScrollY);
+        drawable.setBounds(bounds);
+        drawable.draw(canvas);
+        canvas.translate(-mScrollX, -mScrollY);
+    }
+
+    /**
      * Draws the background onto the specified canvas.
      *
      * @param canvas Canvas on which to draw the background
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/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 92e0245..bb469a3 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2244,7 +2244,6 @@
             canvas.drawHardwareLayer(mResizeBuffer, mHardwareXOffset, mHardwareYOffset,
                     mResizePaint);
         }
-        drawAccessibilityFocusedDrawableIfNeeded(canvas);
     }
 
     /**
@@ -2462,25 +2461,9 @@
                 if (mHardwareYOffset != yOffset || mHardwareXOffset != xOffset) {
                     mHardwareYOffset = yOffset;
                     mHardwareXOffset = xOffset;
-                    invalidateRoot = true;
-                }
-                mResizeAlpha = resizeAlpha;
-
-                if (!invalidateRoot) {
-                    // If accessibility focus moved, invalidate the root.
-                    final Drawable drawable = mAttachInfo.mAccessibilityFocusDrawable;
-                    if (drawable != null) {
-                        final Rect bounds = mAttachInfo.mTmpInvalRect;
-                        if (getAccessibilityFocusedRect(bounds)
-                                && !bounds.equals(drawable.getBounds())) {
-                            invalidateRoot = true;
-                        }
-                    }
-                }
-
-                if (invalidateRoot) {
                     mAttachInfo.mHardwareRenderer.invalidateRoot();
                 }
+                mResizeAlpha = resizeAlpha;
 
                 dirty.setEmpty();
 
@@ -2600,8 +2583,6 @@
                 attachInfo.mSetIgnoreDirtyState = false;
 
                 mView.draw(canvas);
-
-                drawAccessibilityFocusedDrawableIfNeeded(canvas);
             } finally {
                 if (!attachInfo.mSetIgnoreDirtyState) {
                     // Only clear the flag if it was not set during the mView.draw() call
@@ -2625,54 +2606,7 @@
         return true;
     }
 
-    /**
-     * We want to draw a highlight around the current accessibility focused.
-     * Since adding a style for all possible view is not a viable option we
-     * have this specialized drawing method.
-     *
-     * Note: We are doing this here to be able to draw the highlight for
-     *       virtual views in addition to real ones.
-     *
-     * @param canvas The canvas on which to draw.
-     */
-    private void drawAccessibilityFocusedDrawableIfNeeded(Canvas canvas) {
-        final Rect bounds = mAttachInfo.mTmpInvalRect;
-        if (getAccessibilityFocusedRect(bounds)) {
-            final Drawable drawable = getAccessibilityFocusedDrawable();
-            if (drawable != null) {
-                drawable.setBounds(bounds);
-                drawable.draw(canvas);
-            }
-        }
-    }
-
-    private boolean getAccessibilityFocusedRect(Rect bounds) {
-        final AccessibilityManager manager = AccessibilityManager.getInstance(mView.mContext);
-        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
-            return false;
-        }
-
-        final View host = mAccessibilityFocusedHost;
-        if (host == null || host.mAttachInfo == null) {
-            return false;
-        }
-
-        final AccessibilityNodeProvider provider = host.getAccessibilityNodeProvider();
-        if (provider == null) {
-            host.getBoundsOnScreen(bounds);
-        } else if (mAccessibilityFocusedVirtualView != null) {
-            mAccessibilityFocusedVirtualView.getBoundsInScreen(bounds);
-        } else {
-            return false;
-        }
-
-        final AttachInfo attachInfo = mAttachInfo;
-        bounds.offset(-attachInfo.mWindowLeft, -attachInfo.mWindowTop);
-        bounds.intersect(0, 0, attachInfo.mViewRootImpl.mWidth, attachInfo.mViewRootImpl.mHeight);
-        return true;
-    }
-
-    private Drawable getAccessibilityFocusedDrawable() {
+    Drawable getAccessibilityFocusedDrawable() {
         // Lazily load the accessibility focus drawable.
         if (mAttachInfo.mAccessibilityFocusDrawable == null) {
             final TypedValue value = new TypedValue();
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index b37ee06..3f5f045 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -3158,6 +3158,7 @@
         // Offset from touch position to mPosition
         private float mTouchToWindowOffsetX, mTouchToWindowOffsetY;
         protected int mHotspotX;
+        protected int mHorizontalGravity;
         // Offsets the hotspot point up, so that cursor is not hidden by the finger when moving up
         private float mTouchOffsetY;
         // Where the touch position should be on the handle to ensure a maximum cursor visibility
@@ -3172,6 +3173,8 @@
         private boolean mPositionHasChanged = true;
         // Used to delay the appearance of the action popup window
         private Runnable mActionPopupShower;
+        // Minimum touch target size for handles
+        private int mMinSize;
 
         public HandleView(Drawable drawableLtr, Drawable drawableRtl) {
             super(mTextView.getContext());
@@ -3184,10 +3187,12 @@
 
             mDrawableLtr = drawableLtr;
             mDrawableRtl = drawableRtl;
+            mMinSize = mTextView.getContext().getResources().getDimensionPixelSize(
+                    com.android.internal.R.dimen.text_handle_min_size);
 
             updateDrawable();
 
-            final int handleHeight = mDrawable.getIntrinsicHeight();
+            final int handleHeight = getPreferredHeight();
             mTouchOffsetY = -0.3f * handleHeight;
             mIdealVerticalOffset = 0.7f * handleHeight;
         }
@@ -3197,9 +3202,11 @@
             final boolean isRtlCharAtOffset = mTextView.getLayout().isRtlCharAt(offset);
             mDrawable = isRtlCharAtOffset ? mDrawableRtl : mDrawableLtr;
             mHotspotX = getHotspotX(mDrawable, isRtlCharAtOffset);
+            mHorizontalGravity = getHorizontalGravity(isRtlCharAtOffset);
         }
 
         protected abstract int getHotspotX(Drawable drawable, boolean isRtlRun);
+        protected abstract int getHorizontalGravity(boolean isRtlRun);
 
         // Touch-up filter: number of previous positions remembered
         private static final int HISTORY_SIZE = 5;
@@ -3244,7 +3251,15 @@
 
         @Override
         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-            setMeasuredDimension(mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight());
+            setMeasuredDimension(getPreferredWidth(), getPreferredHeight());
+        }
+
+        private int getPreferredWidth() {
+            return Math.max(mDrawable.getIntrinsicWidth(), mMinSize);
+        }
+
+        private int getPreferredHeight() {
+            return Math.max(mDrawable.getIntrinsicHeight(), mMinSize);
         }
 
         public void show() {
@@ -3336,7 +3351,8 @@
                 }
                 final int line = layout.getLineForOffset(offset);
 
-                mPositionX = (int) (layout.getPrimaryHorizontal(offset) - 0.5f - mHotspotX);
+                mPositionX = (int) (layout.getPrimaryHorizontal(offset) - 0.5f - mHotspotX -
+                        getHorizontalOffset() + getCursorOffset());
                 mPositionY = layout.getLineBottom(line);
 
                 // Take TextView's padding and scroll into account.
@@ -3385,10 +3401,36 @@
 
         @Override
         protected void onDraw(Canvas c) {
-            mDrawable.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
+            final int drawWidth = mDrawable.getIntrinsicWidth();
+            final int left = getHorizontalOffset();
+
+            mDrawable.setBounds(left, 0, left + drawWidth, mDrawable.getIntrinsicHeight());
             mDrawable.draw(c);
         }
 
+        private int getHorizontalOffset() {
+            final int width = getPreferredWidth();
+            final int drawWidth = mDrawable.getIntrinsicWidth();
+            final int left;
+            switch (mHorizontalGravity) {
+                case Gravity.LEFT:
+                    left = 0;
+                    break;
+                default:
+                case Gravity.CENTER:
+                    left = (width - drawWidth) / 2;
+                    break;
+                case Gravity.RIGHT:
+                    left = width - drawWidth;
+                    break;
+            }
+            return left;
+        }
+
+        protected int getCursorOffset() {
+            return 0;
+        }
+
         @Override
         public boolean onTouchEvent(MotionEvent ev) {
             switch (ev.getActionMasked()) {
@@ -3508,6 +3550,22 @@
         }
 
         @Override
+        protected int getHorizontalGravity(boolean isRtlRun) {
+            return Gravity.CENTER_HORIZONTAL;
+        }
+
+        @Override
+        protected int getCursorOffset() {
+            int offset = super.getCursorOffset();
+            final Drawable cursor = mCursorCount > 0 ? mCursorDrawable[0] : null;
+            if (cursor != null) {
+                cursor.getPadding(mTempRect);
+                offset += (cursor.getIntrinsicWidth() - mTempRect.left - mTempRect.right) / 2;
+            }
+            return offset;
+        }
+
+        @Override
         public boolean onTouchEvent(MotionEvent ev) {
             final boolean result = super.onTouchEvent(ev);
 
@@ -3594,6 +3652,11 @@
         }
 
         @Override
+        protected int getHorizontalGravity(boolean isRtlRun) {
+            return isRtlRun ? Gravity.RIGHT : Gravity.LEFT;
+        }
+
+        @Override
         public int getCurrentCursorOffset() {
             return mTextView.getSelectionStart();
         }
@@ -3637,6 +3700,11 @@
         }
 
         @Override
+        protected int getHorizontalGravity(boolean isRtlRun) {
+            return isRtlRun ? Gravity.LEFT : Gravity.RIGHT;
+        }
+
+        @Override
         public int getCurrentCursorOffset() {
             return mTextView.getSelectionEnd();
         }
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 4dd7e07..23f911c 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -1501,7 +1501,7 @@
                     mRules[ALIGN_PARENT_START] = 0;
                 }
 
-                if (mRules[ALIGN_PARENT_RIGHT] == 0) {
+                if (mRules[ALIGN_PARENT_END] != 0) {
                     if (mRules[ALIGN_PARENT_RIGHT] == 0) {
                         // "right" rule is not defined but "end" rule is: use the "end" rule as the
                         // "right" rule
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/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 157147e..7809c71 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2210,14 +2210,6 @@
         android:description="@string/permdesc_modifyParentalControls"
         android:protectionLevel="signature" />
 
-    <!-- Must be required by a {@link android.media.routing.MediaRouteService}
-         to ensure that only the system can interact with it.
-         @hide -->
-    <permission android:name="android.permission.BIND_ROUTE_PROVIDER"
-        android:label="@string/permlab_bindRouteProvider"
-        android:description="@string/permdesc_bindRouteProvider"
-        android:protectionLevel="signature" />
-
     <!-- Must be required by device administration receiver, to ensure that only the
          system can interact with it. -->
     <permission android:name="android.permission.BIND_DEVICE_ADMIN"
@@ -2783,13 +2775,6 @@
         android:description="@string/permdesc_bindConditionProviderService"
         android:protectionLevel="signature" />
 
-    <!-- Must be required by a {@link android.media.routing.MediaRouteService},
-         to ensure that only the system can bind to it. -->
-    <permission android:name="android.permission.BIND_MEDIA_ROUTE_SERVICE"
-        android:label="@string/permlab_bindMediaRouteService"
-        android:description="@string/permdesc_bindMediaRouteService"
-        android:protectionLevel="signature" />
-
     <!-- Must be required by an {@link android.service.dreams.DreamService},
          to ensure that only the system can bind to it. -->
     <permission android:name="android.permission.BIND_DREAM_SERVICE"
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-hdpi/btn_switch_to_off_mtrl_00001.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00001.9.png
index 9076900..c31194e 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00001.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00002.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00002.9.png
index 3c72bf8..52ed6b2 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00002.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00003.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00003.9.png
index d31e113..7b7cde586 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00003.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00004.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00004.9.png
index d0c693e..859642a 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00004.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00005.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00005.9.png
index dfa19b4..5b71dda 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00005.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00006.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00006.9.png
index 151f205..378d82d 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00006.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00007.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00007.9.png
index ad3ee2c..43c995a 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00007.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00008.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00008.9.png
index 43d66d7..c937837 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00008.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00009.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00009.9.png
index 13e4f8b..a60a127 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00009.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00010.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00010.9.png
index a09b6b2..db0bf2d 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00010.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00011.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00011.9.png
index be02e53..4a6adbe 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00011.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00012.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00012.9.png
index 655d387..98983ef 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00012.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00001.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00001.9.png
index e870a0a..8e7b62f 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00001.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00002.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00002.9.png
index 1d8f805..479a26e 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00002.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00003.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00003.9.png
index d348871..77d3130 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00003.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00004.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00004.9.png
index 941e91e..cfe684f 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00004.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00005.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00005.9.png
index adee78d..4a64a36 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00005.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00006.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00006.9.png
index e6b4ca3..29591ff 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00006.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00007.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00007.9.png
index 6c2bc0d..cf7cf49 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00007.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00008.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00008.9.png
index 763833c..2a2a9af 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00008.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00009.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00009.9.png
index 9a87fbc..1f7fe5f 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00009.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00010.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00010.9.png
index 6ccf70b..f5d7093 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00010.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00011.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00011.9.png
index d1c14a5..3878386 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00011.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00012.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00012.9.png
index c2290f0..adcb9e9 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00012.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00001.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00001.9.png
index 0238898..36ed954 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00001.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00002.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00002.9.png
index ada1be9..863eee1 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00002.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00003.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00003.9.png
index 82aec64..63e93a8 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00003.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00004.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00004.9.png
index 1c6ea9f..85c851d 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00004.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00005.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00005.9.png
index ac11400..8637636 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00005.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00006.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00006.9.png
index 2025972..2945c29 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00006.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00007.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00007.9.png
index 7420fd8..678a6c8 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00007.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00008.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00008.9.png
index 1f40832..238a6f1 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00008.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00009.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00009.9.png
index cf58e44..4a342a6 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00009.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00010.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00010.9.png
index 930a280..5842b19 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00010.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00011.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00011.9.png
index ed9bc37..3e1bd2d 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00011.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00012.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00012.9.png
index cddb5b0..73ed10b 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00012.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00001.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00001.9.png
index bc1f979..03d3dfb 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00001.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00002.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00002.9.png
index e6fdbcc..25085ce 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00002.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00003.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00003.9.png
index 3d60b43..9e4d2f3 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00003.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00004.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00004.9.png
index b9afdc2..ab5bd1e 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00004.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00005.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00005.9.png
index c3c8bf2..f5297ce 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00005.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00006.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00006.9.png
index 1c7e5e1..1ad56e9 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00006.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00007.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00007.9.png
index 6329b73..4bad055 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00007.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00008.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00008.9.png
index 424202c..d908034 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00008.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00009.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00009.9.png
index 313beca..8ed4fb4 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00009.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00010.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00010.9.png
index f18d86a..61d3ced 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00010.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00011.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00011.9.png
index 8ab48c0..dec2a82 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00011.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00012.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00012.9.png
index fbc2c16..6635830 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00012.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00001.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00001.9.png
index 265aeb7..df73ef7 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00001.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00002.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00002.9.png
index 2f036ad..baf52ed 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00002.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00003.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00003.9.png
index bb26440..c8f3b1c 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00003.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00004.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00004.9.png
index 1b70047..fe715cf 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00004.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00005.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00005.9.png
index b544b98..8e66e11 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00005.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00006.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00006.9.png
index c461f3d..537496e 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00006.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00007.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00007.9.png
index f57da14..2722a98 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00007.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00008.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00008.9.png
index 22c6fbc..81fad09 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00008.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00009.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00009.9.png
index cd21ac9..cda20c8 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00009.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00010.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00010.9.png
index a38dc87..a61ad4b 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00010.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00011.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00011.9.png
index d84a342..d6e8e4c 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00011.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00012.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00012.9.png
index b82a2eb..785168e 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00012.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00001.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00001.9.png
index 6a33ebf..8a648b8 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00001.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00002.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00002.9.png
index dafc250..03063d4 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00002.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00003.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00003.9.png
index 27df6ff..6159dec 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00003.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00004.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00004.9.png
index cb4121c..6f1c96c 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00004.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00005.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00005.9.png
index c5cbb75..2eaff46 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00005.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00006.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00006.9.png
index c69ef41..c4d9db8 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00006.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00007.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00007.9.png
index aff03d1..f276f16 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00007.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00008.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00008.9.png
index fb56ae6..cf9133e 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00008.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00009.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00009.9.png
index 88b9d28..8f1a6a8 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00009.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00010.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00010.9.png
index 8451958..5080c46 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00010.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00011.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00011.9.png
index 6f57654..5e39408 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00011.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00012.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00012.9.png
index 21bfc28..435ce21 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00012.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00001.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00001.9.png
index c30cb5a..1eca9a9 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00001.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00002.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00002.9.png
index eaba558..5427211 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00002.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00003.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00003.9.png
index 17c18c9..43c06ab 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00003.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00004.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00004.9.png
index 0fce07a..6db3f1e 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00004.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00005.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00005.9.png
index c29b837..53b3a62 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00005.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00006.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00006.9.png
index ae56a41..7add520 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00006.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00007.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00007.9.png
index 85290ac..a4d57de 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00007.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00008.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00008.9.png
index 1e8513b..4b3a023 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00008.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00009.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00009.9.png
index 8810a12..a4caa65 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00009.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00010.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00010.9.png
index 717207f..2ab46c0 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00010.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00011.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00011.9.png
index db046f3..5c06e44 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00011.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00012.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00012.9.png
index c5c07a4..60d8c11 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00012.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00001.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00001.9.png
index c9bdf1f..b149e47 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00001.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00002.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00002.9.png
index 6bfd943..6a12a1f 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00002.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00003.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00003.9.png
index a1d3fbb..2803c7c 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00003.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00004.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00004.9.png
index 40c3a5b..032f6ea 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00004.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00005.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00005.9.png
index 26b8736..ea83c35 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00005.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00006.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00006.9.png
index 88c027e..2801f29 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00006.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00007.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00007.9.png
index 02567c6..66b89b3 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00007.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00008.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00008.9.png
index 037d3bf..1f8770c 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00008.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00009.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00009.9.png
index 0252769..0d6a95b 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00009.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00010.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00010.9.png
index 3ae501d..8e602db 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00010.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00011.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00011.9.png
index ecf2831..3143c1f 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00011.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00012.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00012.9.png
index 0877749..00fb83e 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00012.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00001.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00001.9.png
index bc21279..786f493 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00001.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00002.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00002.9.png
index b57b592..c6e1ac1f 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00002.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00003.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00003.9.png
index 0fb9277..2a65baa 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00003.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00004.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00004.9.png
index 340722d..efce521 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00004.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00005.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00005.9.png
index 8554a76..5566524 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00005.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00006.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00006.9.png
index a05e335..ee676a6 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00006.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00007.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00007.9.png
index a5ded14..e0bb175 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00007.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00008.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00008.9.png
index 0300a49..de9eada 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00008.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00009.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00009.9.png
index 37dd7ce..3c59ad8 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00009.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00010.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00010.9.png
index 6bc549a..d524098 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00010.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00011.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00011.9.png
index b026d5d..7c08d71 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00011.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00012.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00012.9.png
index 89238dc..017c2e1 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00012.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00001.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00001.9.png
index 1d309fe..d3f2a9a 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00001.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00002.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00002.9.png
index 2e58fa9..cb75295a 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00002.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00003.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00003.9.png
index 2ebe7a7..445644e 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00003.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00004.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00004.9.png
index 04bab76..5819f90 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00004.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00005.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00005.9.png
index 3497e48..91cb90f 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00005.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00006.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00006.9.png
index 42333b4..cf6147c 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00006.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00007.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00007.9.png
index 732e175..75fca7c 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00007.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00008.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00008.9.png
index 12eddd8..b71a0b4 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00008.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00009.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00009.9.png
index 95cbc61..edb7671 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00009.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00010.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00010.9.png
index 105ec07..5e0be17 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00010.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00011.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00011.9.png
index fac253a..b727eda 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00011.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00012.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00012.9.png
index 1b8d11c..a3caefb 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00012.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00012.9.png
Binary files differ
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/layout/alert_dialog_material.xml b/core/res/res/layout/alert_dialog_material.xml
index c3f9c76..5f9066a 100644
--- a/core/res/res/layout/alert_dialog_material.xml
+++ b/core/res/res/layout/alert_dialog_material.xml
@@ -31,9 +31,9 @@
             android:layout_height="wrap_content"
             android:orientation="horizontal"
             android:gravity="center_vertical|start"
-            android:paddingStart="16dip"
-            android:paddingEnd="16dip"
-            android:paddingTop="16dip"
+            android:paddingStart="@dimen/alert_dialog_padding_material"
+            android:paddingEnd="@dimen/alert_dialog_padding_material"
+            android:paddingTop="@dimen/alert_dialog_padding_material"
             android:paddingBottom="8dip">
             <ImageView android:id="@+id/icon"
                 android:layout_width="32dip"
@@ -66,10 +66,10 @@
                 style="?attr/textAppearanceMedium"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:paddingStart="16dip"
-                android:paddingEnd="16dip"
-                android:paddingTop="16dip"
-                android:paddingBottom="16dip" />
+                android:paddingStart="@dimen/alert_dialog_padding_material"
+                android:paddingEnd="@dimen/alert_dialog_padding_material"
+                android:paddingTop="@dimen/alert_dialog_padding_material"
+                android:paddingBottom="@dimen/alert_dialog_padding_material" />
         </ScrollView>
     </LinearLayout>
 
@@ -87,35 +87,33 @@
         style="?attr/buttonBarStyle"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:orientation="vertical"
-        android:gravity="end">
-        <LinearLayout
-            android:layout_width="match_parent"
+        android:layoutDirection="locale"
+        android:orientation="horizontal"
+        android:paddingStart="6dp"
+        android:paddingEnd="6dp"
+        android:paddingBottom="6dp">
+        <Button android:id="@+id/button3"
+            style="?attr/buttonBarNeutralButtonStyle"
+            android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layoutDirection="locale">
-            <Button android:id="@+id/button3"
-                style="?attr/buttonBarNeutralButtonStyle"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:maxLines="2"
-                android:minHeight="@dimen/alert_dialog_button_bar_height" />
-            <Space
-                android:layout_width="0dp"
-                android:layout_height="0dp"
-                android:layout_weight="1"
-                android:visibility="invisible" />
-            <Button android:id="@+id/button2"
-                style="?attr/buttonBarNegativeButtonStyle"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:maxLines="2"
-                android:minHeight="@dimen/alert_dialog_button_bar_height" />
-            <Button android:id="@+id/button1"
-                style="?attr/buttonBarPositiveButtonStyle"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:maxLines="2"
-                android:minHeight="@dimen/alert_dialog_button_bar_height" />
-        </LinearLayout>
-     </LinearLayout>
+            android:maxLines="2"
+            android:minHeight="@dimen/alert_dialog_button_bar_height" />
+        <Space
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_weight="1"
+            android:visibility="invisible" />
+        <Button android:id="@+id/button2"
+            style="?attr/buttonBarNegativeButtonStyle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:maxLines="2"
+            android:minHeight="@dimen/alert_dialog_button_bar_height" />
+        <Button android:id="@+id/button1"
+            style="?attr/buttonBarPositiveButtonStyle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:maxLines="2"
+            android:minHeight="@dimen/alert_dialog_button_bar_height" />
+    </LinearLayout>
 </LinearLayout>
diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml
index e3d8420..1c83644 100644
--- a/core/res/res/values-mcc311-mnc480/config.xml
+++ b/core/res/res/values-mcc311-mnc480/config.xml
@@ -38,4 +38,9 @@
         be disabled) but individual Features can be disabled using ImsConfig.setFeatureValue() -->
     <bool name="imsServiceAllowTurnOff">false</bool>
 
+    <!-- Flag specifying whether VoLTE & VT should be allowed on device: independent of the
+         carrier provisioning. If false: hard disabled. If true: then depends on carrier
+         provisioning, availability etc -->
+    <bool name="config_mobile_allow_volte_vt">false</bool>
+
 </resources>
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/colors.xml b/core/res/res/values/colors.xml
index dd316ed..d538352 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -128,7 +128,7 @@
     <drawable name="notification_template_icon_bg">#3333B5E5</drawable>
     <drawable name="notification_template_icon_low_bg">#0cffffff</drawable>
 
-    <color name="notification_icon_bg_color">#ffa3a3a3</color>
+    <color name="notification_icon_bg_color">#ff9e9e9e</color>
     <color name="notification_action_legacy_color_filter">#ff555555</color>
 
     <color name="notification_media_action_bg">#00000000</color>
@@ -142,5 +142,8 @@
 
     <color name="accessibility_focus_highlight">#bf39b500</color>
 
+    <color name="system_notification_accent_color">#ff607D8B</color>
+    <color name="battery_saver_mode_color">#fff4511e</color><!-- deep orange 600 -->
+
 </resources>
 
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f702b95..a59a489 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1641,6 +1641,11 @@
         be disabled) but individual Features can be disabled using ImsConfig.setFeatureValue() -->
     <bool name="imsServiceAllowTurnOff">true</bool>
 
+    <!-- Flag specifying whether VoLTE & VT should be allowed on device: independent of the
+         carrier provisioning. If false: hard disabled. If true: then depends on carrier
+         provisioning, availability etc -->
+    <bool name="config_mobile_allow_volte_vt">true</bool>
+
     <bool name="config_networkSamplingWakesDevice">true</bool>
 
     <string-array translatable="false" name="config_cdma_home_system" />
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index a29a34c..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>
@@ -394,4 +393,7 @@
      <dimen name="lock_pattern_dot_line_width">3dp</dimen>
      <dimen name="lock_pattern_dot_size">12dp</dimen>
      <dimen name="lock_pattern_dot_size_activated">28dp</dimen>
+
+     <dimen name="text_handle_min_size">40dp</dimen>
+
 </resources>
diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml
index 250d5f8..972ae5e 100644
--- a/core/res/res/values/dimens_material.xml
+++ b/core/res/res/values/dimens_material.xml
@@ -73,4 +73,6 @@
 
     <!-- Default alpha value for disabled elements. -->
     <item name="disabled_alpha_material" format="float" type="dimen">0.26</item>
+
+    <dimen name="alert_dialog_padding_material">12dp</dimen>
 </resources>
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/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 2936e2b..78ba738 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1160,12 +1160,6 @@
         interface of a widget service. Should never be needed for normal apps.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permlab_bindRouteProvider">bind to a route provider service</string>
-    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permdesc_bindRouteProvider">Allows the holder to bind to any registered
-        route providers. Should never be needed for normal apps.</string>
-
-    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_bindDeviceAdmin">interact with a device admin</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_bindDeviceAdmin">Allows the holder to send intents to
@@ -2157,11 +2151,6 @@
     <string name="permdesc_bindConditionProviderService">Allows the holder to bind to the top-level interface of a condition provider service. Should never be needed for normal apps.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permlab_bindMediaRouteService">bind to a media route service</string>
-    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permdesc_bindMediaRouteService">Allows the holder to bind to the top-level interface of a media route service. Should never be needed for normal apps.</string>
-
-    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_bindDreamService">bind to a dream service</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_bindDreamService">Allows the holder to bind to the top-level interface of a dream service. Should never be needed for normal apps.</string>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 9420f3a..c8ea699 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -451,12 +451,15 @@
     <style name="Widget.Material" parent="Widget" />
 
     <!-- Bordered ink button -->
-    <style name="Widget.Material.Button" parent="Widget.Button">
+    <style name="Widget.Material.Button">
         <item name="background">@drawable/btn_default_material</item>
         <item name="textAppearance">?attr/textAppearanceButton</item>
         <item name="minHeight">48dip</item>
         <item name="minWidth">88dip</item>
         <item name="stateListAnimator">@anim/button_state_list_anim_material</item>
+        <item name="focusable">true</item>
+        <item name="clickable">true</item>
+        <item name="gravity">center_vertical|center_horizontal</item>
     </style>
 
     <!-- Small bordered ink button -->
@@ -499,9 +502,6 @@
 
     <style name="Widget.Material.ButtonBar.AlertDialog">
         <item name="background">@null</item>
-        <item name="paddingStart">16dp</item>
-        <item name="paddingEnd">16dp</item>
-        <item name="paddingBottom">16dp</item>
         <item name="minHeight">@dimen/alert_dialog_button_bar_height</item>
     </style>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 1cb7b17..0b3a132 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1956,6 +1956,7 @@
   <java-symbol type="attr" name="preferenceFragmentStyle" />
   <java-symbol type="bool" name="skipHoldBeforeMerge" />
   <java-symbol type="bool" name="imsServiceAllowTurnOff" />
+  <java-symbol type="bool" name="config_mobile_allow_volte_vt" />
   <java-symbol type="bool" name="useImsAlwaysForEmergencyCall" />
   <java-symbol type="attr" name="touchscreenBlocksFocus" />
   <java-symbol type="layout" name="resolver_list_with_default" />
@@ -1983,4 +1984,7 @@
   <java-symbol type="layout" name="select_dialog_singlechoice_material" />
   <java-symbol type="layout" name="select_dialog_multichoice_material" />
   <java-symbol type="array" name="no_ems_support_sim_operators" />
+  <java-symbol type="color" name="battery_saver_mode_color" />
+  <java-symbol type="color" name="system_notification_accent_color" />
+  <java-symbol type="dimen" name="text_handle_min_size" />
 </resources>
diff --git a/data/fonts/AndroidClock.ttf b/data/fonts/AndroidClock.ttf
index 4781ccd..a955442 100644
--- a/data/fonts/AndroidClock.ttf
+++ b/data/fonts/AndroidClock.ttf
Binary files differ
diff --git a/data/fonts/AndroidClock_Highlight.ttf b/data/fonts/AndroidClock_Highlight.ttf
index 3fa6d88..923bb30 100644
--- a/data/fonts/AndroidClock_Highlight.ttf
+++ b/data/fonts/AndroidClock_Highlight.ttf
Binary files differ
diff --git a/data/fonts/AndroidClock_Solid.ttf b/data/fonts/AndroidClock_Solid.ttf
index 3fa6d88..923bb30 100644
--- a/data/fonts/AndroidClock_Solid.ttf
+++ b/data/fonts/AndroidClock_Solid.ttf
Binary files differ
diff --git a/data/fonts/Clockopia.ttf b/data/fonts/Clockopia.ttf
index 123ea4f..3f7b6aa 100644
--- a/data/fonts/Clockopia.ttf
+++ b/data/fonts/Clockopia.ttf
Binary files differ
diff --git a/data/fonts/DroidSansFallback.ttf b/data/fonts/DroidSansFallback.ttf
index 03f49a8..96b16bb 100644
--- a/data/fonts/DroidSansFallback.ttf
+++ b/data/fonts/DroidSansFallback.ttf
Binary files differ
diff --git a/data/fonts/DroidSansFallbackFull.ttf b/data/fonts/DroidSansFallbackFull.ttf
index 1dfcc33..89959f5 100644
--- a/data/fonts/DroidSansFallbackFull.ttf
+++ b/data/fonts/DroidSansFallbackFull.ttf
Binary files differ
diff --git a/data/fonts/DroidSansMono.ttf b/data/fonts/DroidSansMono.ttf
index a007071..4085cee 100644
--- a/data/fonts/DroidSansMono.ttf
+++ b/data/fonts/DroidSansMono.ttf
Binary files differ
diff --git a/data/fonts/MTLc3m.ttf b/data/fonts/MTLc3m.ttf
index 86bdcc7..e9018f6 100644
--- a/data/fonts/MTLc3m.ttf
+++ b/data/fonts/MTLc3m.ttf
Binary files differ
diff --git a/data/fonts/MTLmr3m.ttf b/data/fonts/MTLmr3m.ttf
index 91dd47f..14f27d4 100644
--- a/data/fonts/MTLmr3m.ttf
+++ b/data/fonts/MTLmr3m.ttf
Binary files differ
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 1c76d9c..652fe64 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1109,9 +1109,16 @@
      * This draws a shadow layer below the main layer, with the specified
      * offset and color, and blur radius. If radius is 0, then the shadow
      * layer is removed.
+     * <p>
+     * Can be used to create a blurred shadow underneath text. Support for use
+     * with other drawing operations is constrained to the software rendering
+     * pipeline.
+     * <p>
+     * The alpha of the shadow will be the paint's alpha if the shadow color is
+     * opaque, or the alpha from the shadow color if not.
      */
-    public void setShadowLayer(float radius, float dx, float dy, int color) {
-      native_setShadowLayer(mNativePaint, radius, dx, dy, color);
+    public void setShadowLayer(float radius, float dx, float dy, int shadowColor) {
+      native_setShadowLayer(mNativePaint, radius, dx, dy, shadowColor);
     }
 
     /**
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/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 0aa1b0d..c185a9e 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -446,19 +446,8 @@
                         ": <nine-patch> requires a valid 9-patch source image");
             }
 
-            // Hey, now might be a good time to actually load optical bounds!
             bitmap.getOpticalInsets(opticalInsets);
 
-            // Sanity check for valid padding when we have optical insets.
-            if (padding.left < opticalInsets.left) {
-                padding.left = opticalInsets.left;
-                padding.right = opticalInsets.right;
-            }
-            if (padding.top < opticalInsets.top) {
-                padding.top = opticalInsets.top;
-                padding.bottom = opticalInsets.bottom;
-            }
-
             state.mNinePatch = new NinePatch(bitmap, bitmap.getNinePatchChunk());
             state.mPadding = padding;
             state.mOpticalInsets = Insets.of(opticalInsets);
@@ -626,21 +615,6 @@
             mOpticalInsets = Insets.of(opticalInsets);
             mDither = dither;
             mAutoMirrored = autoMirror;
-
-            // Sanity check for valid padding when we have optical insets.
-            if (opticalInsets != null && !opticalInsets.isEmpty()) {
-                if (mPadding == null) {
-                    mPadding = new Rect();
-                }
-                if (mPadding.left < opticalInsets.left) {
-                    mPadding.left = opticalInsets.left;
-                    mPadding.right = opticalInsets.right;
-                }
-                if (mPadding.top < opticalInsets.top) {
-                    mPadding.top = opticalInsets.top;
-                    mPadding.bottom = opticalInsets.bottom;
-                }
-            }
         }
 
         // Copy constructor
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 1032a75..5f533a7 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1001,6 +1001,8 @@
 public:
     DrawStrokableOp(float left, float top, float right, float bottom, const SkPaint* paint)
             : DrawBoundedOp(left, top, right, bottom, paint) {};
+    DrawStrokableOp(const Rect& localBounds, const SkPaint* paint)
+            : DrawBoundedOp(localBounds, paint) {};
 
     virtual bool getLocalBounds(Rect& localBounds) {
         localBounds.set(mLocalBounds);
@@ -1339,11 +1341,11 @@
     const float* mPositions;
 };
 
-class DrawTextOp : public DrawBoundedOp {
+class DrawTextOp : public DrawStrokableOp {
 public:
     DrawTextOp(const char* text, int bytesCount, int count, float x, float y,
             const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds)
-            : DrawBoundedOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count),
+            : DrawStrokableOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count),
             mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) {
         mPrecacheTransform = SkMatrix::InvalidMatrix();
     }
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 94162fc..9a9c544 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -376,7 +376,7 @@
         float x, float y, const float* positions, const SkPaint* paint,
         float totalAdvance, const Rect& bounds, DrawOpMode drawOpMode) {
 
-    if (!text || count <= 0) return DrawGlInfo::kStatusDone;
+    if (!text || count <= 0 || paintWillNotDrawText(*paint)) return DrawGlInfo::kStatusDone;
 
     text = refText(text, bytesCount);
     positions = refBuffer<float>(positions, count * 2);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 721ab3d..bbf0551 100755
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2518,8 +2518,9 @@
 
 status_t OpenGLRenderer::drawRoundRect(float left, float top, float right, float bottom,
         float rx, float ry, const SkPaint* p) {
-    if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
-            (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
+    if (currentSnapshot()->isIgnored()
+            || quickRejectSetupScissor(left, top, right, bottom, p)
+            || paintWillNotDraw(*p)) {
         return DrawGlInfo::kStatusDone;
     }
 
@@ -2536,9 +2537,9 @@
 }
 
 status_t OpenGLRenderer::drawCircle(float x, float y, float radius, const SkPaint* p) {
-    if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(x - radius, y - radius,
-            x + radius, y + radius, p) ||
-            (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
+    if (currentSnapshot()->isIgnored()
+            || quickRejectSetupScissor(x - radius, y - radius, x + radius, y + radius, p)
+            || paintWillNotDraw(*p)) {
         return DrawGlInfo::kStatusDone;
     }
     if (p->getPathEffect() != 0) {
@@ -2558,8 +2559,9 @@
 
 status_t OpenGLRenderer::drawOval(float left, float top, float right, float bottom,
         const SkPaint* p) {
-    if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
-            (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
+    if (currentSnapshot()->isIgnored()
+            || quickRejectSetupScissor(left, top, right, bottom, p)
+            || paintWillNotDraw(*p)) {
         return DrawGlInfo::kStatusDone;
     }
 
@@ -2580,8 +2582,9 @@
 
 status_t OpenGLRenderer::drawArc(float left, float top, float right, float bottom,
         float startAngle, float sweepAngle, bool useCenter, const SkPaint* p) {
-    if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
-            (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
+    if (currentSnapshot()->isIgnored()
+            || quickRejectSetupScissor(left, top, right, bottom, p)
+            || paintWillNotDraw(*p)) {
         return DrawGlInfo::kStatusDone;
     }
 
@@ -2614,8 +2617,9 @@
 
 status_t OpenGLRenderer::drawRect(float left, float top, float right, float bottom,
         const SkPaint* p) {
-    if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
-            (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
+    if (currentSnapshot()->isIgnored()
+            || quickRejectSetupScissor(left, top, right, bottom, p)
+            || paintWillNotDraw(*p)) {
         return DrawGlInfo::kStatusDone;
     }
 
diff --git a/libs/hwui/Renderer.h b/libs/hwui/Renderer.h
index f5cd266..6d4bb4a 100644
--- a/libs/hwui/Renderer.h
+++ b/libs/hwui/Renderer.h
@@ -67,6 +67,18 @@
         return resultMode;
     }
 
+    // TODO: move to a method on android:Paint
+    static inline bool paintWillNotDraw(const SkPaint& paint) {
+        return paint.getAlpha() == 0
+                && getXfermode(paint.getXfermode()) != SkXfermode::kClear_Mode;
+    }
+
+    // TODO: move to a method on android:Paint
+    static inline bool paintWillNotDrawText(const SkPaint& paint) {
+        return paint.getAlpha() == 0
+                && paint.getLooper() == NULL
+                && getXfermode(paint.getXfermode()) == SkXfermode::kSrcOver_Mode;
+    }
 // ----------------------------------------------------------------------------
 // Frame state operations
 // ----------------------------------------------------------------------------
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index b33ba00..5a286ee 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -209,7 +209,9 @@
 
         // if not to popup dialog immediately, pending intent will open the dialog
         Intent intent = !mPopupImmediately ? getDlgIntent(notif) : new Intent();
-        PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, intent, 0);                
+        PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, intent, 0);
+        mNiNotification.color = mContext.getResources().getColor(
+                com.android.internal.R.color.system_notification_accent_color);
         mNiNotification.setLatestEventInfo(mContext, title, message, pi);
 
         notificationManager.notifyAsUser(null, notif.notificationId, mNiNotification,
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/routing/IMediaRouteClientCallback.aidl b/media/java/android/media/routing/IMediaRouteClientCallback.aidl
deleted file mode 100644
index d90ea3b..0000000
--- a/media/java/android/media/routing/IMediaRouteClientCallback.aidl
+++ /dev/null
@@ -1,41 +0,0 @@
-/* Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.routing;
-
-import android.media.routing.MediaRouteSelector;
-import android.media.routing.ParcelableConnectionInfo;
-import android.media.routing.ParcelableDestinationInfo;
-import android.media.routing.ParcelableRouteInfo;
-import android.os.IBinder;
-import android.os.Bundle;
-
-/**
- * @hide
- */
-oneway interface IMediaRouteClientCallback {
-    void onDestinationFound(int seq, in ParcelableDestinationInfo destination,
-            in ParcelableRouteInfo[] routes);
-
-    void onDestinationLost(int seq, String id);
-
-    void onDiscoveryFailed(int seq, int error, in CharSequence message, in Bundle extras);
-
-    void onConnected(int seq, in ParcelableConnectionInfo connection);
-
-    void onDisconnected(int seq);
-
-    void onConnectionFailed(int seq, int error, in CharSequence message, in Bundle extras);
-}
diff --git a/media/java/android/media/routing/IMediaRouteService.aidl b/media/java/android/media/routing/IMediaRouteService.aidl
deleted file mode 100644
index 493ab6d..0000000
--- a/media/java/android/media/routing/IMediaRouteService.aidl
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.routing;
-
-import android.media.routing.IMediaRouteClientCallback;
-import android.media.routing.MediaRouteSelector;
-import android.os.Bundle;
-
-/**
- * Interface to an app's MediaRouteService.
- * @hide
- */
-oneway interface IMediaRouteService {
-    void registerClient(int clientUid, String clientPackageName,
-            in IMediaRouteClientCallback callback);
-
-    void unregisterClient(in IMediaRouteClientCallback callback);
-
-    void startDiscovery(in IMediaRouteClientCallback callback, int seq,
-            in List<MediaRouteSelector> selectors, int flags);
-
-    void stopDiscovery(in IMediaRouteClientCallback callback);
-
-    void connect(in IMediaRouteClientCallback callback, int seq,
-            String destinationId, String routeId, int flags, in Bundle extras);
-
-    void disconnect(in IMediaRouteClientCallback callback);
-
-    void pauseStream(in IMediaRouteClientCallback callback);
-
-    void resumeStream(in IMediaRouteClientCallback callback);
-}
-
diff --git a/media/java/android/media/routing/IMediaRouter.aidl b/media/java/android/media/routing/IMediaRouter.aidl
deleted file mode 100644
index 0abb258..0000000
--- a/media/java/android/media/routing/IMediaRouter.aidl
+++ /dev/null
@@ -1,22 +0,0 @@
-/* Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.routing;
-
-/** @hide */
-interface IMediaRouter {
-
-}
-
diff --git a/media/java/android/media/routing/IMediaRouterDelegate.aidl b/media/java/android/media/routing/IMediaRouterDelegate.aidl
deleted file mode 100644
index 35f84c8..0000000
--- a/media/java/android/media/routing/IMediaRouterDelegate.aidl
+++ /dev/null
@@ -1,22 +0,0 @@
-/* Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.routing;
-
-/** @hide */
-interface IMediaRouterDelegate {
-
-}
-
diff --git a/media/java/android/media/routing/IMediaRouterRoutingCallback.aidl b/media/java/android/media/routing/IMediaRouterRoutingCallback.aidl
deleted file mode 100644
index 173ae55..0000000
--- a/media/java/android/media/routing/IMediaRouterRoutingCallback.aidl
+++ /dev/null
@@ -1,22 +0,0 @@
-/* Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.routing;
-
-/** @hide */
-interface IMediaRouterRoutingCallback {
-
-}
-
diff --git a/media/java/android/media/routing/IMediaRouterStateCallback.aidl b/media/java/android/media/routing/IMediaRouterStateCallback.aidl
deleted file mode 100644
index 0299904..0000000
--- a/media/java/android/media/routing/IMediaRouterStateCallback.aidl
+++ /dev/null
@@ -1,22 +0,0 @@
-/* Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.routing;
-
-/** @hide */
-interface IMediaRouterStateCallback {
-
-}
-
diff --git a/media/java/android/media/routing/MediaRouteSelector.aidl b/media/java/android/media/routing/MediaRouteSelector.aidl
deleted file mode 100644
index 37bfa4a..0000000
--- a/media/java/android/media/routing/MediaRouteSelector.aidl
+++ /dev/null
@@ -1,18 +0,0 @@
-/* Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.media.routing;
-
-parcelable MediaRouteSelector;
diff --git a/media/java/android/media/routing/MediaRouteSelector.java b/media/java/android/media/routing/MediaRouteSelector.java
deleted file mode 100644
index 26a9b1c..0000000
--- a/media/java/android/media/routing/MediaRouteSelector.java
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.media.routing;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.media.routing.MediaRouter.RouteFeatures;
-import android.os.Bundle;
-import android.os.IInterface;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A media route selector consists of a set of constraints that are used to select
- * the routes to which an application would like to connect.  The constraints consist
- * of a set of required or optional features and protocols.  The constraints may also
- * require the use of a specific media route service package or additional characteristics
- * that are described by a bundle of extra parameters.
- * <p>
- * The application will typically create several different selectors that express
- * various combinations of characteristics that it would like to use together when
- * it connects to a destination media device.  For each destination that is discovered,
- * media route services will publish some number of routes and include information
- * about which selector each route matches.  The application will then choose among
- * these routes to determine which best satisfies its desired purpose and connect to it.
- * </p>
- */
-public final class MediaRouteSelector implements Parcelable {
-    private final int mRequiredFeatures;
-    private final int mOptionalFeatures;
-    private final List<String> mRequiredProtocols;
-    private final List<String> mOptionalProtocols;
-    private final String mServicePackageName;
-    private final Bundle mExtras;
-
-    MediaRouteSelector(int requiredFeatures, int optionalFeatures,
-            List<String> requiredProtocols, List<String> optionalProtocols,
-            String servicePackageName, Bundle extras) {
-        mRequiredFeatures = requiredFeatures;
-        mOptionalFeatures = optionalFeatures;
-        mRequiredProtocols = requiredProtocols;
-        mOptionalProtocols = optionalProtocols;
-        mServicePackageName = servicePackageName;
-        mExtras = extras;
-    }
-
-    /**
-     * Gets the set of required route features.
-     *
-     * @return A set of required route feature flags.
-     */
-    public @RouteFeatures int getRequiredFeatures() {
-        return mRequiredFeatures;
-    }
-
-    /**
-     * Gets the set of optional route features.
-     *
-     * @return A set of optional route feature flags.
-     */
-    public @RouteFeatures int getOptionalFeatures() {
-        return mOptionalFeatures;
-    }
-
-    /**
-     * Gets the list of route protocols that a route must support in order to be selected.
-     * <p>
-     * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
-     * for more information.
-     * </p>
-     *
-     * @return The list of fully qualified route protocol names.
-     */
-    public @NonNull List<String> getRequiredProtocols() {
-        return mRequiredProtocols;
-    }
-
-    /**
-     * Gets the list of optional route protocols that a client may use if they are available.
-     * <p>
-     * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
-     * for more information.
-     * </p>
-     *
-     * @return The list of optional fully qualified route protocol names.
-     */
-    public @NonNull List<String> getOptionalProtocols() {
-        return mOptionalProtocols;
-    }
-
-    /**
-     * Returns true if the selector includes a required or optional request for
-     * the specified protocol using its fully qualified class name.
-     * <p>
-     * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
-     * for more information.
-     * </p>
-     *
-     * @param clazz The protocol class.
-     * @return True if the protocol was requested.
-     */
-    public boolean containsProtocol(@NonNull Class<?> clazz) {
-        return containsProtocol(clazz.getName());
-    }
-
-    /**
-     * Returns true if the selector includes a required or optional request for
-     * the specified protocol.
-     * <p>
-     * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
-     * for more information.
-     * </p>
-     *
-     * @param name The name of the protocol.
-     * @return True if the protocol was requested.
-     */
-    public boolean containsProtocol(@NonNull String name) {
-        return mRequiredProtocols.contains(name)
-                || mOptionalProtocols.contains(name);
-    }
-
-    /**
-     * Gets the package name of a specific media route service that this route selector
-     * requires.
-     *
-     * @return The required media route service package name, or null if none.
-     */
-    public @Nullable String getServicePackageName() {
-        return mServicePackageName;
-    }
-
-    /**
-     * Gets optional extras that may be used to select or configure routes for a
-     * particular purpose.  Some extras may be used by media route services to apply
-     * additional constraints or parameters for the routes to be discovered.
-     *
-     * @return The optional extras, or null if none.
-     */
-    public @Nullable Bundle getExtras() {
-        return mExtras;
-    }
-
-    @Override
-    public String toString() {
-        return "MediaRouteSelector{ "
-                + ", requiredFeatures=0x" + Integer.toHexString(mRequiredFeatures)
-                + ", optionalFeatures=0x" + Integer.toHexString(mOptionalFeatures)
-                + ", requiredProtocols=" + mRequiredProtocols
-                + ", optionalProtocols=" + mOptionalProtocols
-                + ", servicePackageName=" + mServicePackageName
-                + ", extras=" + mExtras + " }";
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mRequiredFeatures);
-        dest.writeInt(mOptionalFeatures);
-        dest.writeStringList(mRequiredProtocols);
-        dest.writeStringList(mOptionalProtocols);
-        dest.writeString(mServicePackageName);
-        dest.writeBundle(mExtras);
-    }
-
-    public static final Parcelable.Creator<MediaRouteSelector> CREATOR =
-            new Parcelable.Creator<MediaRouteSelector>() {
-        @Override
-        public MediaRouteSelector createFromParcel(Parcel source) {
-            int requiredFeatures = source.readInt();
-            int optionalFeatures = source.readInt();
-            ArrayList<String> requiredProtocols = new ArrayList<String>();
-            ArrayList<String> optionalProtocols = new ArrayList<String>();
-            source.readStringList(requiredProtocols);
-            source.readStringList(optionalProtocols);
-            return new MediaRouteSelector(requiredFeatures, optionalFeatures,
-                    requiredProtocols, optionalProtocols,
-                    source.readString(), source.readBundle());
-        }
-
-        @Override
-        public MediaRouteSelector[] newArray(int size) {
-            return new MediaRouteSelector[size];
-        }
-    };
-
-    /**
-     * Builder for {@link MediaRouteSelector} objects.
-     */
-    public static final class Builder {
-        private int mRequiredFeatures;
-        private int mOptionalFeatures;
-        private final ArrayList<String> mRequiredProtocols = new ArrayList<String>();
-        private final ArrayList<String> mOptionalProtocols = new ArrayList<String>();
-        private String mServicePackageName;
-        private Bundle mExtras;
-
-        /**
-         * Creates an initially empty selector builder.
-         */
-        public Builder() {
-        }
-
-        /**
-         * Sets the set of required route features.
-         *
-         * @param features A set of required route feature flags.
-         */
-        public @NonNull Builder setRequiredFeatures(@RouteFeatures int features) {
-            mRequiredFeatures = features;
-            return this;
-        }
-
-        /**
-         * Sets the set of optional route features.
-         *
-         * @param features A set of optional route feature flags.
-         */
-        public @NonNull Builder setOptionalFeatures(@RouteFeatures int features) {
-            mOptionalFeatures = features;
-            return this;
-        }
-
-        /**
-         * Adds a route protocol that a route must support in order to be selected
-         * using its fully qualified class name.
-         * <p>
-         * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
-         * for more information.
-         * </p>
-         *
-         * @param clazz The protocol class.
-         * @return this
-         */
-        public @NonNull Builder addRequiredProtocol(@NonNull Class<?> clazz) {
-            if (clazz == null) {
-                throw new IllegalArgumentException("clazz must not be null");
-            }
-            return addRequiredProtocol(clazz.getName());
-        }
-
-        /**
-         * Adds a route protocol that a route must support in order to be selected.
-         * <p>
-         * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
-         * for more information.
-         * </p>
-         *
-         * @param name The fully qualified name of the required protocol.
-         * @return this
-         */
-        public @NonNull Builder addRequiredProtocol(@NonNull String name) {
-            if (TextUtils.isEmpty(name)) {
-                throw new IllegalArgumentException("name must not be null or empty");
-            }
-            mRequiredProtocols.add(name);
-            return this;
-        }
-
-        /**
-         * Adds an optional route protocol that a client may use if available
-         * using its fully qualified class name.
-         * <p>
-         * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
-         * for more information.
-         * </p>
-         *
-         * @param clazz The protocol class.
-         * @return this
-         */
-        public @NonNull Builder addOptionalProtocol(@NonNull Class<?> clazz) {
-            if (clazz == null) {
-                throw new IllegalArgumentException("clazz must not be null");
-            }
-            return addOptionalProtocol(clazz.getName());
-        }
-
-        /**
-         * Adds an optional route protocol that a client may use if available.
-         * <p>
-         * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
-         * for more information.
-         * </p>
-         *
-         * @param name The fully qualified name of the optional protocol.
-         * @return this
-         */
-        public @NonNull Builder addOptionalProtocol(@NonNull String name) {
-            if (TextUtils.isEmpty(name)) {
-                throw new IllegalArgumentException("name must not be null or empty");
-            }
-            mOptionalProtocols.add(name);
-            return this;
-        }
-
-        /**
-         * Sets the package name of the media route service to which this selector
-         * appertains.
-         * <p>
-         * If a package name is specified here then this selector will only be
-         * passed to media route services from that package.  This has the effect
-         * of restricting the set of matching routes to just those that are offered
-         * by that package.
-         * </p>
-         *
-         * @param packageName The required service package name, or null if none.
-         * @return this
-         */
-        public @NonNull Builder setServicePackageName(@Nullable String packageName) {
-            mServicePackageName = packageName;
-            return this;
-        }
-
-        /**
-         * Sets optional extras that may be used to select or configure routes for a
-         * particular purpose.  Some extras may be used by route services to specify
-         * additional constraints or parameters for the routes to be discovered.
-         *
-         * @param extras The optional extras, or null if none.
-         * @return this
-         */
-        public @NonNull Builder setExtras(@Nullable Bundle extras) {
-            mExtras = extras;
-            return this;
-        }
-
-        /**
-         * Builds the {@link MediaRouteSelector} object.
-         *
-         * @return The new media route selector instance.
-         */
-        public @NonNull MediaRouteSelector build() {
-            return new MediaRouteSelector(mRequiredFeatures, mOptionalFeatures,
-                    mRequiredProtocols, mOptionalProtocols, mServicePackageName, mExtras);
-        }
-    }
-}
diff --git a/media/java/android/media/routing/MediaRouteService.java b/media/java/android/media/routing/MediaRouteService.java
deleted file mode 100644
index 4d5a8a9..0000000
--- a/media/java/android/media/routing/MediaRouteService.java
+++ /dev/null
@@ -1,1023 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.media.routing;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SdkConstant;
-import android.app.Service;
-import android.content.Intent;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.media.routing.MediaRouter.ConnectionError;
-import android.media.routing.MediaRouter.ConnectionInfo;
-import android.media.routing.MediaRouter.ConnectionRequest;
-import android.media.routing.MediaRouter.DestinationInfo;
-import android.media.routing.MediaRouter.DiscoveryError;
-import android.media.routing.MediaRouter.DiscoveryRequest;
-import android.media.routing.MediaRouter.RouteInfo;
-import android.media.routing.MediaRouter.ServiceMetadata;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.ArrayMap;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Media route services implement strategies for discovering
- * and establishing connections to media devices and their routes.  These services
- * are also known as media route providers.
- * <p>
- * Each media route service subclass is responsible for enabling applications
- * and the system to interact with media devices of some kind.
- * For example, one particular media route service implementation might
- * offer support for discovering nearby wireless display devices and streaming
- * video contents to them; another media route service implementation might
- * offer support for discovering nearby speakers and streaming media appliances
- * and sending commands to play content on request.
- * </p><p>
- * Subclasses must override the {@link #onCreateClientSession} method to return
- * a {@link ClientSession} object that implements the {@link ClientSession#onStartDiscovery},
- * {@link ClientSession#onStopDiscovery}, and {@link ClientSession#onConnect} methods
- * to allow clients to discover and connect to media devices.
- * </p><p>
- * This object is not thread-safe.  All callbacks are invoked on the main looper.
- * </p>
- *
- * <h3>Clients</h3>
- * <p>
- * The clients of this API are media applications that would like to discover
- * and connect to media devices.  The client may also be the system, such as
- * when the user initiates display mirroring via the Cast Screen function.
- * </p><p>
- * There may be multiple client sessions active at the same time.  Each client
- * session can request discovery and connect to routes independently of any
- * other client.  It is the responsibility of the media route service to maintain
- * separate state for each client session and to ensure that clients cannot interfere
- * with one another in harmful ways.
- * </p><p>
- * Notwithstanding the requirement to support any number of concurrent client
- * sessions, the media route service may impose constraints on how many clients
- * can connect to the same media device in a particular mode at the same time.
- * In some cases, media devices may support connections from an arbitrary number
- * of clients simultaneously but often it may be necessary to ensure that only
- * one client is in control.  When this happens, the media route service should
- * report a connection error unless the connection request specifies that the
- * client should take control of the media device (and forcibly disconnect other
- * clients that may be using it).
- * </p>
- *
- * <h3>Destinations</h3>
- * <p>
- * The media devices to which an application may send media content are referred
- * to in the API as destinations.  Each destination therefore represents a single
- * independent device such as a speaker or TV set.  Destinations are given meaningful
- * names and descriptions to help the user associate them with devices in their
- * environment.
- * </p><p>
- * Destinations may be local or remote and may be accessed through various means,
- * often wirelessly.  The user may install media route services to enable
- * media applications to connect to a variety of destinations with different
- * capabilities.
- * </p>
- *
- * <h3>Routes</h3>
- * <p>
- * Routes represent possible usages or means of reaching and interacting with
- * a destination.  Since destinations may support many different features, they may
- * each offer multiple routes for applications to choose from based on their needs.
- * For example, one route might express the ability to stream locally rendered audio
- * and video to the device; another route might express the ability to send a URL for
- * the destination to download from the network and play all by itself.
- * </p><p>
- * Routes are discovered according to the set of capabilities that
- * an application or the system is seeking to use at a particular time.  For example,
- * if an application wants to stream music to a destination then it will ask the
- * {@link MediaRouter} to find routes to destinations can stream music and ignore
- * all other destinations that cannot.
- * </p><p>
- * In general, the application will inspect the set of routes that have been
- * offered then connect to the most appropriate route for its desired purpose.
- * </p>
- *
- * <h3>Discovery</h3>
- * <p>
- * Discovery is the process of finding destinations based on a description of the
- * kinds of routes that an application or the system would like to use.
- * </p><p>
- * Discovery begins when {@link ClientSession#onStartDiscovery} is called and ends when
- * {@link ClientSession#onStopDiscovery} is called.  There may be multiple simultaneous
- * discovery requests in progress at the same time from different clients.  It is up to
- * the media route service to perform these requests in parallel or multiplex them
- * as required.
- * </p><p>
- * Media route services are <em>strongly encouraged</em> to use the information
- * in the discovery request to optimize discovery and avoid redundant work.
- * In the case where no media device supported by the media route service
- * could possibly offer the requested capabilities, the
- * {@link ClientSession#onStartDiscovery} method should return <code>false</code> to
- * let the system know that it can unbind from the media route service and
- * release its resources.
- * </p>
- *
- * <h3>Settings</h3>
- * <p>
- * Many kinds of devices can be discovered on demand simply by scanning the local network
- * or using wireless protocols such as Bluetooth to find them.  However, in some cases
- * it may be necessary for the user to manually configure destinations before they
- * can be used (or to adjust settings later).  Actual user configuration of destinations
- * is beyond the scope of this API but media route services may specify an activity
- * in their manifest that the user can launch to perform these tasks.
- * </p><p>
- * Note that media route services that are installed from the store must be enabled
- * by the user before they become available for applications to use.
- * The {@link android.provider.Settings#ACTION_CAST_SETTINGS Settings.ACTION_CAST_SETTINGS}
- * settings activity provides the ability for the user to configure media route services.
- * </p>
- *
- * <h3>Manifest Declaration</h3>
- * <p>
- * Media route services must be declared in the manifest along with meta-data
- * about the kinds of routes that they are capable of discovering.  The system
- * uses this information to optimize the set of services to which it binds in
- * order to satisfy a particular discovery request.
- * </p><p>
- * To extend this class, you must declare the service in your manifest file with
- * the {@link android.Manifest.permission#BIND_MEDIA_ROUTE_SERVICE} permission
- * and include an intent filter with the {@link #SERVICE_INTERFACE} action.  You must
- * also add meta-data to describe the kinds of routes that your service is capable
- * of discovering.
- * </p><p>
- * For example:
- * </p><pre>
- * &lt;service android:name=".MediaRouteProvider"
- *          android:label="&#64;string/service_name"
- *          android:permission="android.permission.BIND_MEDIA_ROUTE_SERVICE">
- *     &lt;intent-filter>
- *         &lt;action android:name="android.media.routing.MediaRouteService" />
- *     &lt;/intent-filter>
- *
- *     TODO: INSERT METADATA DECLARATIONS HERE
- *
- * &lt;/service>
- * </pre>
- */
-public abstract class MediaRouteService extends Service {
-    private static final String TAG = "MediaRouteService";
-
-    private static final boolean DEBUG = true;
-
-    private final Handler mHandler;
-    private final BinderService mService;
-    private final ArrayMap<IBinder, ClientRecord> mClientRecords =
-            new ArrayMap<IBinder, ClientRecord>();
-
-    private ServiceMetadata mMetadata;
-
-    /**
-     * The {@link Intent} that must be declared as handled by the service.
-     */
-    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
-    public static final String SERVICE_INTERFACE =
-            "android.media.routing.MediaRouteService";
-
-    /**
-     * Creates a media route service.
-     */
-    public MediaRouteService() {
-        mHandler = new Handler(true);
-        mService = new BinderService();
-    }
-
-    @Override
-    public @Nullable IBinder onBind(Intent intent) {
-        if (SERVICE_INTERFACE.equals(intent.getAction())) {
-            return mService;
-        }
-        return null;
-    }
-
-    /**
-     * Creates a new client session on behalf of a client.
-     * <p>
-     * The implementation should return a {@link ClientSession} for the client
-     * to use.  The media route service must take care to manage the state of
-     * each client session independently from any others that might also be
-     * in use at the same time.
-     * </p>
-     *
-     * @param client Information about the client.
-     * @return The client session object, or null if the client is not allowed
-     * to interact with this media route service.
-     */
-    public abstract @Nullable ClientSession onCreateClientSession(@NonNull ClientInfo client);
-
-    /**
-     * Gets metadata about this service.
-     * <p>
-     * Use this method to obtain a {@link ServiceMetadata} object to provide when creating
-     * a {@link android.media.routing.MediaRouter.DestinationInfo.Builder}.
-     * </p>
-     *
-     * @return Metadata about this service.
-     */
-    public @NonNull ServiceMetadata getServiceMetadata() {
-        if (mMetadata == null) {
-            try {
-                mMetadata = new ServiceMetadata(this);
-            } catch (NameNotFoundException ex) {
-                Log.wtf(TAG, "Could not retrieve own service metadata!");
-            }
-        }
-        return mMetadata;
-    }
-
-    /**
-     * Enables a single client to access the functionality of the media route service.
-     */
-    public static abstract class ClientSession {
-        /**
-         * Starts discovery.
-         * <p>
-         * If the media route service is capable of discovering routes that satisfy
-         * the request then this method should start discovery and return true.
-         * Otherwise, this method should return false.  If false is returned,
-         * then the framework will not call {@link #onStopDiscovery} since discovery
-         * was never actually started.
-         * </p><p>
-         * There may already be other discovery requests in progress at the same time
-         * for other clients; the media route service must keep track of them all.
-         * </p>
-         *
-         * @param req The discovery request to start.
-         * @param callback A callback to receive discovery events related to this
-         * particular request.  The events that the service sends to this callback
-         * will be sent to the client that initiated the discovery request.
-         * @return True if discovery has started.  False if the media route service
-         * is unable to discover routes that satisfy the request.
-         */
-        public abstract boolean onStartDiscovery(@NonNull DiscoveryRequest req,
-                @NonNull DiscoveryCallback callback);
-
-        /**
-         * Stops discovery.
-         * <p>
-         * If {@link #onStartDiscovery} returned true, then this method will eventually
-         * be called when the framework no longer requires this discovery request
-         * to be performed.
-         * </p><p>
-         * There may still be other discovery requests in progress for other clients;
-         * they must keep working until they have each been stopped by their client.
-         * </p>
-         */
-        public abstract void onStopDiscovery();
-
-        /**
-         * Starts connecting to a route.
-         *
-         * @param req The connection request.
-         * @param callback A callback to receive events connection events related
-         * to this particular request.  The events that the service sends to this callback
-         * will be sent to the client that initiated the discovery request.
-         * @return True if the connection is in progress, or false if the client
-         * unable to connect to the requested route.
-         */
-        public abstract boolean onConnect(@NonNull ConnectionRequest req,
-                @NonNull ConnectionCallback callback);
-
-        /**
-         * Called when the client requests to disconnect from the route
-         * or abort a connection attempt in progress.
-         */
-        public abstract void onDisconnect();
-
-        /**
-         * Called when the client requests to pause streaming of content to
-         * live audio/video routes such as when it goes into the background.
-         * <p>
-         * The default implementation does nothing.
-         * </p>
-         */
-        public void onPauseStream() { }
-
-        /**
-         * Called when the application requests to resume streaming of content to
-         * live audio/video routes such as when it returns to the foreground.
-         * <p>
-         * The default implementation does nothing.
-         * </p>
-         */
-        public void onResumeStream() { }
-
-        /**
-         * Called when the client is releasing the session.
-         * <p>
-         * The framework automatically takes care of stopping discovery and
-         * terminating the connection politely before calling this method to release
-         * the session.
-         * </p><p>
-         * The default implementation does nothing.
-         * </p>
-         */
-        public void onRelease() { }
-    }
-
-    /**
-     * Provides events in response to a discovery request.
-     */
-    public final class DiscoveryCallback {
-        private final ClientRecord mRecord;
-
-        DiscoveryCallback(ClientRecord record) {
-            mRecord = record;
-        }
-
-        /**
-         * Called by the service when a destination is found that
-         * offers one or more routes that satisfy the discovery request.
-         * <p>
-         * This method should be called whenever the list of available routes
-         * at a destination changes or whenever the properties of the destination
-         * itself change.
-         * </p>
-         *
-         * @param destination The destination that was found.
-         * @param routes The list of that destination's routes that satisfy the
-         * discovery request.
-         */
-        public void onDestinationFound(final @NonNull DestinationInfo destination,
-                final @NonNull List<RouteInfo> routes) {
-            if (destination == null) {
-                throw new IllegalArgumentException("destination must not be null");
-            }
-            if (routes == null) {
-                throw new IllegalArgumentException("routes must not be null");
-            }
-            for (int i = 0; i < routes.size(); i++) {
-                if (routes.get(i).getDestination() != destination) {
-                    throw new IllegalArgumentException("routes must refer to the "
-                            + "destination");
-                }
-            }
-
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mRecord.dispatchDestinationFound(DiscoveryCallback.this,
-                            destination, routes);
-                }
-            });
-        }
-
-        /**
-         * Called by the service when a destination is no longer
-         * reachable or is no longer offering any routes that satisfy
-         * the discovery request.
-         *
-         * @param destination The destination that went away.
-         */
-        public void onDestinationLost(final @NonNull DestinationInfo destination) {
-            if (destination == null) {
-                throw new IllegalArgumentException("destination must not be null");
-            }
-
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mRecord.dispatchDestinationLost(DiscoveryCallback.this, destination);
-                }
-            });
-        }
-
-        /**
-         * Called by the service when a discovery has failed in a non-recoverable manner.
-         *
-         * @param error The error code: one of
-         * {@link MediaRouter#DISCOVERY_ERROR_UNKNOWN},
-         * {@link MediaRouter#DISCOVERY_ERROR_ABORTED},
-         * or {@link MediaRouter#DISCOVERY_ERROR_NO_CONNECTIVITY}.
-         * @param message The localized error message, or null if none.  This message
-         * may be shown to the user.
-         * @param extras Additional information about the error which a client
-         * may use, or null if none.
-         */
-        public void onDiscoveryFailed(final @DiscoveryError int error,
-                final @Nullable CharSequence message, final @Nullable Bundle extras) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mRecord.dispatchDiscoveryFailed(DiscoveryCallback.this,
-                            error, message, extras);
-                }
-            });
-        }
-    }
-
-    /**
-     * Provides events in response to a connection request.
-     */
-    public final class ConnectionCallback {
-        private final ClientRecord mRecord;
-
-        ConnectionCallback(ClientRecord record) {
-            mRecord = record;
-        }
-
-        /**
-         * Called by the service when the connection succeeds.
-         *
-         * @param connection Immutable information about the connection.
-         */
-        public void onConnected(final @NonNull ConnectionInfo connection) {
-            if (connection == null) {
-                throw new IllegalArgumentException("connection must not be null");
-            }
-
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mRecord.dispatchConnected(ConnectionCallback.this, connection);
-                }
-            });
-        }
-
-        /**
-         * Called by the service when the connection is terminated normally.
-         * <p>
-         * Abnormal termination is reported via {@link #onConnectionFailed}.
-         * </p>
-         */
-        public void onDisconnected() {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mRecord.dispatchDisconnected(ConnectionCallback.this);
-                }
-            });
-        }
-
-        /**
-         * Called by the service when a connection attempt or connection in
-         * progress has failed in a non-recoverable manner.
-         *
-         * @param error The error code: one of
-         * {@link MediaRouter#CONNECTION_ERROR_ABORTED},
-         * {@link MediaRouter#CONNECTION_ERROR_UNAUTHORIZED},
-         * {@link MediaRouter#CONNECTION_ERROR_UNREACHABLE},
-         * {@link MediaRouter#CONNECTION_ERROR_BUSY},
-         * {@link MediaRouter#CONNECTION_ERROR_TIMEOUT},
-         * {@link MediaRouter#CONNECTION_ERROR_BROKEN},
-         * or {@link MediaRouter#CONNECTION_ERROR_BARGED}.
-         * @param message The localized error message, or null if none.  This message
-         * may be shown to the user.
-         * @param extras Additional information about the error which a client
-         * may use, or null if none.
-         */
-        public void onConnectionFailed(final @ConnectionError int error,
-                final @Nullable CharSequence message, final @Nullable Bundle extras) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mRecord.dispatchConnectionFailed(ConnectionCallback.this,
-                            error, message, extras);
-                }
-            });
-        }
-    }
-
-    /**
-     * Identifies a client of the media route service.
-     */
-    public static final class ClientInfo {
-        private final int mUid;
-        private final String mPackageName;
-
-        ClientInfo(int uid, String packageName) {
-            mUid = uid;
-            mPackageName = packageName;
-        }
-
-        /**
-         * Gets the UID of the client application.
-         */
-        public int getUid() {
-            return mUid;
-        }
-
-        /**
-         * Gets the package name of the client application.
-         */
-        public @NonNull String getPackageName() {
-            return mPackageName;
-        }
-
-        @Override
-        public @NonNull String toString() {
-            return "ClientInfo{ uid=" + mUid + ", package=" + mPackageName + " }";
-        }
-    }
-
-    private final class BinderService extends IMediaRouteService.Stub {
-        @Override
-        public void registerClient(final int clientUid, final String clientPackageName,
-                final IMediaRouteClientCallback callback) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    ClientInfo client = new ClientInfo(clientUid, clientPackageName);
-                    if (DEBUG) {
-                        Log.d(TAG, "registerClient: client=" + client);
-                    }
-
-                    ClientSession session = onCreateClientSession(client);
-                    if (session == null) {
-                        // request refused by service
-                        Log.w(TAG, "Media route service refused to create session for client: "
-                                + "client=" + client);
-                        return;
-                    }
-
-                    ClientRecord record = new ClientRecord(callback, client, session);
-                    try {
-                        callback.asBinder().linkToDeath(record, 0);
-                    } catch (RemoteException ex) {
-                        // client died prematurely
-                        Log.w(TAG, "Client died prematurely while creating session: "
-                                + "client=" + client);
-                        record.release();
-                        return;
-                    }
-
-                    mClientRecords.put(callback.asBinder(), record);
-                }
-            });
-        }
-
-        @Override
-        public void unregisterClient(IMediaRouteClientCallback callback) {
-            unregisterClient(callback, false);
-        }
-
-        void unregisterClient(final IMediaRouteClientCallback callback,
-                final boolean died) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    ClientRecord record = mClientRecords.remove(callback.asBinder());
-                    if (record == null) {
-                        return; // spurious
-                    }
-
-                    if (DEBUG) {
-                        Log.d(TAG, "unregisterClient: client=" + record.getClientInfo()
-                                + ", died=" + died);
-                    }
-
-                    record.release();
-                    callback.asBinder().unlinkToDeath(record, 0);
-                }
-            });
-        }
-
-        @Override
-        public void startDiscovery(final IMediaRouteClientCallback callback,
-                final int seq, final List<MediaRouteSelector> selectors,
-                final int flags) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    ClientRecord record = mClientRecords.get(callback.asBinder());
-                    if (record == null) {
-                        return; // spurious
-                    }
-
-                    if (DEBUG) {
-                        Log.d(TAG, "startDiscovery: client=" + record.getClientInfo()
-                                + ", seq=" + seq + ", selectors=" + selectors
-                                + ", flags=0x" + Integer.toHexString(flags));
-                    }
-                    record.startDiscovery(seq, selectors, flags);
-                }
-            });
-        }
-
-        @Override
-        public void stopDiscovery(final IMediaRouteClientCallback callback) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    ClientRecord record = mClientRecords.get(callback.asBinder());
-                    if (record == null) {
-                        return; // spurious
-                    }
-
-                    if (DEBUG) {
-                        Log.d(TAG, "stopDiscovery: client=" + record.getClientInfo());
-                    }
-                    record.stopDiscovery();
-                }
-            });
-        }
-
-        @Override
-        public void connect(final IMediaRouteClientCallback callback,
-                final int seq, final String destinationId, final String routeId,
-                final int flags, final Bundle extras) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    ClientRecord record = mClientRecords.get(callback.asBinder());
-                    if (record == null) {
-                        return; // spurious
-                    }
-
-                    if (DEBUG) {
-                        Log.d(TAG, "connect: client=" + record.getClientInfo()
-                                + ", seq=" + seq + ", destinationId=" + destinationId
-                                + ", routeId=" + routeId
-                                + ", flags=0x" + Integer.toHexString(flags)
-                                + ", extras=" + extras);
-                    }
-                    record.connect(seq, destinationId, routeId, flags, extras);
-                }
-            });
-        }
-
-        @Override
-        public void disconnect(final IMediaRouteClientCallback callback) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    ClientRecord record = mClientRecords.get(callback.asBinder());
-                    if (record == null) {
-                        return; // spurious
-                    }
-
-                    if (DEBUG) {
-                        Log.d(TAG, "disconnect: client=" + record.getClientInfo());
-                    }
-                    record.disconnect();
-                }
-            });
-        }
-
-        @Override
-        public void pauseStream(final IMediaRouteClientCallback callback) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    ClientRecord record = mClientRecords.get(callback.asBinder());
-                    if (record == null) {
-                        return; // spurious
-                    }
-
-                    if (DEBUG) {
-                        Log.d(TAG, "pauseStream: client=" + record.getClientInfo());
-                    }
-                    record.pauseStream();
-                }
-            });
-        }
-
-        @Override
-        public void resumeStream(final IMediaRouteClientCallback callback) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    ClientRecord record = mClientRecords.get(callback.asBinder());
-                    if (record == null) {
-                        return; // spurious
-                    }
-
-                    if (DEBUG) {
-                        Log.d(TAG, "resumeStream: client=" + record.getClientInfo());
-                    }
-                    record.resumeStream();
-                }
-            });
-        }
-    }
-
-    // Must be accessed on handler
-    private final class ClientRecord implements IBinder.DeathRecipient {
-        private final IMediaRouteClientCallback mClientCallback;
-        private final ClientInfo mClient;
-        private final ClientSession mSession;
-
-        private int mDiscoverySeq;
-        private DiscoveryRequest mDiscoveryRequest;
-        private DiscoveryCallback mDiscoveryCallback;
-        private final ArrayMap<String, DestinationRecord> mDestinations =
-                new ArrayMap<String, DestinationRecord>();
-
-        private int mConnectionSeq;
-        private ConnectionRequest mConnectionRequest;
-        private ConnectionCallback mConnectionCallback;
-        private ConnectionInfo mConnection;
-        private boolean mConnectionPaused;
-
-        public ClientRecord(IMediaRouteClientCallback callback,
-                ClientInfo client, ClientSession session) {
-            mClientCallback = callback;
-            mClient = client;
-            mSession = session;
-        }
-
-        // Invoked on binder thread unlike all other methods in this class.
-        @Override
-        public void binderDied() {
-            mService.unregisterClient(mClientCallback, true);
-        }
-
-        public ClientInfo getClientInfo() {
-            return mClient;
-        }
-
-        public void release() {
-            stopDiscovery();
-            disconnect();
-        }
-
-        public void startDiscovery(int seq, List<MediaRouteSelector> selectors,
-                int flags) {
-            stopDiscovery();
-
-            mDiscoverySeq = seq;
-            mDiscoveryRequest = new DiscoveryRequest(selectors);
-            mDiscoveryRequest.setFlags(flags);
-            mDiscoveryCallback = new DiscoveryCallback(this);
-            boolean started = mSession.onStartDiscovery(mDiscoveryRequest, mDiscoveryCallback);
-            if (!started) {
-                dispatchDiscoveryFailed(mDiscoveryCallback,
-                        MediaRouter.DISCOVERY_ERROR_ABORTED, null, null);
-                clearDiscovery();
-            }
-        }
-
-        public void stopDiscovery() {
-            if (mDiscoveryRequest != null) {
-                mSession.onStopDiscovery();
-                clearDiscovery();
-            }
-        }
-
-        private void clearDiscovery() {
-            mDestinations.clear();
-            mDiscoveryRequest = null;
-            mDiscoveryCallback = null;
-        }
-
-        public void connect(int seq, String destinationId, String routeId,
-                int flags, Bundle extras) {
-            disconnect();
-
-            mConnectionSeq = seq;
-            mConnectionCallback = new ConnectionCallback(this);
-
-            DestinationRecord destinationRecord = mDestinations.get(destinationId);
-            if (destinationRecord == null) {
-                Log.w(TAG, "Aborting connection to route since no matching destination "
-                        + "was found in the list of known destinations: "
-                        + "destinationId=" + destinationId);
-                dispatchConnectionFailed(mConnectionCallback,
-                        MediaRouter.CONNECTION_ERROR_ABORTED, null, null);
-                clearConnection();
-                return;
-            }
-
-            RouteInfo route = destinationRecord.getRoute(routeId);
-            if (route == null) {
-                Log.w(TAG, "Aborting connection to route since no matching route "
-                        + "was found in the list of known routes: "
-                        + "destination=" + destinationRecord.destination
-                        + ", routeId=" + routeId);
-                dispatchConnectionFailed(mConnectionCallback,
-                        MediaRouter.CONNECTION_ERROR_ABORTED, null, null);
-                clearConnection();
-                return;
-            }
-
-            mConnectionRequest = new ConnectionRequest(route);
-            mConnectionRequest.setFlags(flags);
-            mConnectionRequest.setExtras(extras);
-            boolean started = mSession.onConnect(mConnectionRequest, mConnectionCallback);
-            if (!started) {
-                dispatchConnectionFailed(mConnectionCallback,
-                        MediaRouter.CONNECTION_ERROR_ABORTED, null, null);
-                clearConnection();
-            }
-        }
-
-        public void disconnect() {
-            if (mConnectionRequest != null) {
-                mSession.onDisconnect();
-                clearConnection();
-            }
-        }
-
-        private void clearConnection() {
-            mConnectionRequest = null;
-            mConnectionCallback = null;
-            if (mConnection != null) {
-                mConnection.close();
-                mConnection = null;
-            }
-            mConnectionPaused = false;
-        }
-
-        public void pauseStream() {
-            if (mConnectionRequest != null && !mConnectionPaused) {
-                mConnectionPaused = true;
-                mSession.onPauseStream();
-            }
-        }
-
-        public void resumeStream() {
-            if (mConnectionRequest != null && mConnectionPaused) {
-                mConnectionPaused = false;
-                mSession.onResumeStream();
-            }
-        }
-
-        public void dispatchDestinationFound(DiscoveryCallback callback,
-                DestinationInfo destination, List<RouteInfo> routes) {
-            if (callback == mDiscoveryCallback) {
-                if (DEBUG) {
-                    Log.d(TAG, "destinationFound: destination=" + destination
-                            + ", routes=" + routes);
-                }
-                mDestinations.put(destination.getId(),
-                        new DestinationRecord(destination, routes));
-
-                ParcelableDestinationInfo pdi = new ParcelableDestinationInfo();
-                pdi.id = destination.getId();
-                pdi.name = destination.getName();
-                pdi.description = destination.getDescription();
-                pdi.iconResourceId = destination.getIconResourceId();
-                pdi.extras = destination.getExtras();
-                ArrayList<ParcelableRouteInfo> pris = new ArrayList<ParcelableRouteInfo>();
-                for (RouteInfo route : routes) {
-                    int selectorIndex = mDiscoveryRequest.getSelectors().indexOf(
-                            route.getSelector());
-                    if (selectorIndex < 0) {
-                        Log.w(TAG, "Ignoring route because the selector does not match "
-                                + "any of those that were originally supplied by the "
-                                + "client's discovery request: destination=" + destination
-                                + ", route=" + route);
-                        continue;
-                    }
-
-                    ParcelableRouteInfo pri = new ParcelableRouteInfo();
-                    pri.id = route.getId();
-                    pri.selectorIndex = selectorIndex;
-                    pri.features = route.getFeatures();
-                    pri.protocols = route.getProtocols().toArray(
-                            new String[route.getProtocols().size()]);
-                    pri.extras = route.getExtras();
-                    pris.add(pri);
-                }
-                try {
-                    mClientCallback.onDestinationFound(mDiscoverySeq, pdi,
-                            pris.toArray(new ParcelableRouteInfo[pris.size()]));
-                } catch (RemoteException ex) {
-                    // binder death handled elsewhere
-                }
-            }
-        }
-
-        public void dispatchDestinationLost(DiscoveryCallback callback,
-                DestinationInfo destination) {
-            if (callback == mDiscoveryCallback) {
-                if (DEBUG) {
-                    Log.d(TAG, "destinationLost: destination=" + destination);
-                }
-
-                if (mDestinations.get(destination.getId()).destination == destination) {
-                    mDestinations.remove(destination.getId());
-                    try {
-                        mClientCallback.onDestinationLost(mDiscoverySeq, destination.getId());
-                    } catch (RemoteException ex) {
-                        // binder death handled elsewhere
-                    }
-                }
-            }
-        }
-
-        public void dispatchDiscoveryFailed(DiscoveryCallback callback,
-                int error, CharSequence message, Bundle extras) {
-            if (callback == mDiscoveryCallback) {
-                if (DEBUG) {
-                    Log.d(TAG, "discoveryFailed: error=" + error + ", message=" + message
-                            + ", extras=" + extras);
-                }
-
-                try {
-                    mClientCallback.onDiscoveryFailed(mDiscoverySeq, error, message, extras);
-                } catch (RemoteException ex) {
-                    // binder death handled elsewhere
-                }
-            }
-        }
-
-        public void dispatchConnected(ConnectionCallback callback, ConnectionInfo connection) {
-            if (callback == mConnectionCallback) {
-                if (DEBUG) {
-                    Log.d(TAG, "connected: connection=" + connection);
-                }
-                if (mConnection == null) {
-                    mConnection = connection;
-
-                    ParcelableConnectionInfo pci = new ParcelableConnectionInfo();
-                    pci.audioAttributes = connection.getAudioAttributes();
-                    pci.presentationDisplayId = connection.getPresentationDisplay() != null ?
-                            connection.getPresentationDisplay().getDisplayId() : -1;
-                    pci.protocolBinders = new IBinder[connection.getProtocols().size()];
-                    for (int i = 0; i < pci.protocolBinders.length; i++) {
-                        pci.protocolBinders[i] = connection.getProtocolBinder(i);
-                    }
-                    pci.extras = connection.getExtras();
-                    try {
-                        mClientCallback.onConnected(mConnectionSeq, pci);
-                    } catch (RemoteException ex) {
-                        // binder death handled elsewhere
-                    }
-                } else {
-                    Log.w(TAG, "Media route service called onConnected() while already "
-                            + "connected.");
-                }
-            }
-        }
-
-        public void dispatchDisconnected(ConnectionCallback callback) {
-            if (callback == mConnectionCallback) {
-                if (DEBUG) {
-                    Log.d(TAG, "disconnected");
-                }
-
-                if (mConnection != null) {
-                    mConnection.close();
-                    mConnection = null;
-
-                    try {
-                        mClientCallback.onDisconnected(mConnectionSeq);
-                    } catch (RemoteException ex) {
-                        // binder death handled elsewhere
-                    }
-                }
-            }
-        }
-
-        public void dispatchConnectionFailed(ConnectionCallback callback,
-                int error, CharSequence message, Bundle extras) {
-            if (callback == mConnectionCallback) {
-                if (DEBUG) {
-                    Log.d(TAG, "connectionFailed: error=" + error + ", message=" + message
-                            + ", extras=" + extras);
-                }
-
-                try {
-                    mClientCallback.onConnectionFailed(mConnectionSeq, error, message, extras);
-                } catch (RemoteException ex) {
-                    // binder death handled elsewhere
-                }
-            }
-        }
-    }
-
-    private static final class DestinationRecord {
-        public final DestinationInfo destination;
-        public final List<RouteInfo> routes;
-
-        public DestinationRecord(DestinationInfo destination, List<RouteInfo> routes) {
-            this.destination = destination;
-            this.routes = routes;
-        }
-
-        public RouteInfo getRoute(String routeId) {
-            final int count = routes.size();
-            for (int i = 0; i < count; i++) {
-                RouteInfo route = routes.get(i);
-                if (route.getId().equals(routeId)) {
-                    return route;
-                }
-            }
-            return null;
-        }
-    }
-}
diff --git a/media/java/android/media/routing/MediaRouter.java b/media/java/android/media/routing/MediaRouter.java
deleted file mode 100644
index 4f6d324..0000000
--- a/media/java/android/media/routing/MediaRouter.java
+++ /dev/null
@@ -1,1886 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.media.routing;
-
-import android.annotation.DrawableRes;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.Presentation;
-import android.app.Service;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ServiceInfo;
-import android.graphics.drawable.Drawable;
-import android.hardware.display.DisplayManager;
-import android.media.AudioAttributes;
-import android.media.AudioManager;
-import android.media.AudioTrack;
-import android.media.VolumeProvider;
-import android.media.session.MediaController;
-import android.media.session.MediaSession;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.IInterface;
-import android.text.TextUtils;
-import android.util.ArrayMap;
-import android.view.Display;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Media router allows applications to discover, connect to, control,
- * and send content to nearby media devices known as destinations.
- * <p>
- * There are generally two participants involved in media routing: an
- * application that wants to send media content to a destination and a
- * {@link MediaRouteService media route service} that provides the
- * service of transporting that content where it needs to go on behalf of the
- * application.
- * </p><p>
- * To send media content to a destination, the application must ask the system
- * to discover available routes to destinations that provide certain capabilities,
- * establish a connection to a route, then send messages through the connection to
- * control the routing of audio and video streams, launch remote applications,
- * and invoke other functions of the destination.
- * </p><p>
- * Media router objects are thread-safe.
- * </p>
- *
- * <h3>Destinations</h3>
- * <p>
- * The media devices to which an application may send media content are referred
- * to in the API as destinations.  Each destination therefore represents a single
- * independent device such as a speaker or TV set.  Destinations are given meaningful
- * names and descriptions to help the user associate them with devices in their
- * environment.
- * </p><p>
- * Destinations may be local or remote and may be accessed through various means,
- * often wirelessly.  The user may install media route services to enable
- * media applications to connect to a variety of destinations with different
- * capabilities.
- * </p>
- *
- * <h3>Routes</h3>
- * <p>
- * Routes represent possible usages or means of reaching and interacting with
- * a destination.  Since destinations may support many different features, they may
- * each offer multiple routes for applications to choose from based on their needs.
- * For example, one route might express the ability to stream locally rendered audio
- * and video to the device; another route might express the ability to send a URL for
- * the destination to download from the network and play all by itself.
- * </p><p>
- * Routes are discovered according to the set of capabilities that
- * an application or the system is seeking to use at a particular time.  For example,
- * if an application wants to stream music to a destination then it will ask the
- * {@link MediaRouter} to find routes to destinations can stream music and ignore
- * all other destinations that cannot.
- * </p><p>
- * In general, the application will inspect the set of routes that have been
- * offered then connect to the most appropriate route for its desired purpose.
- * </p>
- *
- * <h3>Route Selection</h3>
- * <p>
- * When the user open the media route chooser activity, the system will display
- * a list of nearby media destinations which have been discovered.  After the
- * choice is made the application may connect to one of the routes offered by
- * this destination and begin communicating with the destination.
- * </p><p>
- * Destinations are located through a process called discovery.  During discovery,
- * the system will start installed {@link MediaRouteService media route services}
- * to scan the network for nearby devices that offer the kinds of capabilities that the
- * application is seeking to use.  The application specifies the capabilities it requires by
- * adding {@link MediaRouteSelector media route selectors} to the media router
- * using the {@link #addSelector} method.  Only destinations that provide routes
- * which satisfy at least one of these media route selectors will be discovered.
- * </p><p>
- * Once the user has selected a destination, the application will be given a chance
- * to choose one of the routes to which it would like to connect.  The application
- * may switch to a different route from the same destination at a later time but
- * in order to connect to a new destination, the application must once again launch
- * the media route chooser activity to ask the user to choose a destination.
- * </p>
- *
- * <h3>Route Protocols</h3>
- * <p>
- * Route protocols express capabilities offered by routes.  Each media route selector
- * must specify at least one required protocol by which the routes will be selected.
- * </p><p>
- * The framework provides several predefined <code>MediaRouteProtocols</code> which are
- * defined in the <code>android-support-media-protocols.jar</code> support library.
- * Applications must statically link this library to make use of these protocols.
- * </p><p>
- * The static library approach is used to enable ongoing extension and refinement
- * of protocols in the SDK and interoperability with the media router implementation
- * for older platform versions which is offered by the framework support library.
- * </p><p>
- * Media route services may also define custom media route protocols of their own
- * to enable applications to access specialized capabilities of certain destinations
- * assuming they have linked in the required protocol code.
- * </p><p>
- * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code> for more information.
- * </p>
- *
- * <h3>Connections</h3>
- * <p>
- * After connecting to a media route, the application can send commands to
- * the route using any of the protocols that it requested.  If the route supports live
- * audio or video streaming then the application can create an {@link AudioTrack} or
- * {@link Presentation} to route locally generated content to the destination.
- * </p>
- *
- * <h3>Delegation</h3>
- * <p>
- * The creator of the media router is responsible for establishing the policy for
- * discovering and connecting to destinations.  UI components may observe the state
- * of the media router by {@link #createDelegate creating} a {@link Delegate}.
- * </p><p>
- * The media router should also be attached to the {@link MediaSession media session}
- * that is handling media playback lifecycle.  This will allow
- * authorized {@link MediaController media controllers}, possibly running in other
- * processes, to provide UI to examine and change the media destination by
- * {@link MediaController#createMediaRouterDelegate creating} a {@link Delegate}
- * for the media router associated with the session.
- * </p>
- */
-public final class MediaRouter {
-    private final DisplayManager mDisplayManager;
-
-    private final Object mLock = new Object();
-
-    private RoutingCallback mRoutingCallback;
-    private Handler mRoutingCallbackHandler;
-
-    private boolean mReleased;
-    private int mDiscoveryState;
-    private int mConnectionState;
-    private final ArrayList<MediaRouteSelector> mSelectors =
-            new ArrayList<MediaRouteSelector>();
-    private final ArrayMap<DestinationInfo, List<RouteInfo>> mDiscoveredDestinations =
-            new ArrayMap<DestinationInfo, List<RouteInfo>>();
-    private RouteInfo mSelectedRoute;
-    private ConnectionInfo mConnection;
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(value = { DISCOVERY_STATE_STOPPED, DISCOVERY_STATE_STARTED })
-    public @interface DiscoveryState { }
-
-    /**
-     * Discovery state: Discovery is not currently in progress.
-     */
-    public static final int DISCOVERY_STATE_STOPPED = 0;
-
-    /**
-     * Discovery state: Discovery is being performed.
-     */
-    public static final int DISCOVERY_STATE_STARTED = 1;
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(flag = true, value = { DISCOVERY_FLAG_BACKGROUND })
-    public @interface DiscoveryFlags { }
-
-    /**
-     * Discovery flag: Indicates that the client has requested passive discovery in
-     * the background.  The media route service should try to use less power and rely
-     * more on its internal caches to minimize its impact.
-     */
-    public static final int DISCOVERY_FLAG_BACKGROUND = 1 << 0;
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(value = { DISCOVERY_ERROR_UNKNOWN, DISCOVERY_ERROR_ABORTED,
-            DISCOVERY_ERROR_NO_CONNECTIVITY })
-    public @interface DiscoveryError { }
-
-    /**
-     * Discovery error: Unknown error; refer to the error message for details.
-     */
-    public static final int DISCOVERY_ERROR_UNKNOWN = 0;
-
-    /**
-     * Discovery error: The media router or media route service has decided not to
-     * handle the discovery request for some reason.
-     */
-    public static final int DISCOVERY_ERROR_ABORTED = 1;
-
-    /**
-     * Discovery error: The media route service is unable to perform discovery
-     * due to a lack of connectivity such as because the radio is disabled.
-     */
-    public static final int DISCOVERY_ERROR_NO_CONNECTIVITY = 2;
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(value = { CONNECTION_STATE_DISCONNECTED, CONNECTION_STATE_CONNECTING,
-            CONNECTION_STATE_CONNECTED })
-    public @interface ConnectionState { }
-
-    /**
-     * Connection state: No destination has been selected.  Media content should
-     * be sent to the default output.
-     */
-    public static final int CONNECTION_STATE_DISCONNECTED = 0;
-
-    /**
-     * Connection state: The application is in the process of connecting to
-     * a route offered by the selected destination.
-     */
-    public static final int CONNECTION_STATE_CONNECTING = 1;
-
-    /**
-     * Connection state: The application has connected to a route offered by
-     * the selected destination.
-     */
-    public static final int CONNECTION_STATE_CONNECTED = 2;
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(flag = true, value = { CONNECTION_FLAG_BARGE })
-    public @interface ConnectionFlags { }
-
-    /**
-     * Connection flag: Indicates that the client has requested to barge in and evict
-     * other clients that might have already connected to the destination and that
-     * would otherwise prevent this client from connecting.  When this flag is not
-     * set, the media route service should be polite and report
-     * {@link MediaRouter#CONNECTION_ERROR_BUSY} in case the destination is
-     * already occupied and cannot accept additional connections.
-     */
-    public static final int CONNECTION_FLAG_BARGE = 1 << 0;
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(value = { CONNECTION_ERROR_UNKNOWN, CONNECTION_ERROR_ABORTED,
-            CONNECTION_ERROR_UNAUTHORIZED, CONNECTION_ERROR_UNAUTHORIZED,
-            CONNECTION_ERROR_BUSY, CONNECTION_ERROR_TIMEOUT, CONNECTION_ERROR_BROKEN })
-    public @interface ConnectionError { }
-
-    /**
-     * Connection error: Unknown error; refer to the error message for details.
-     */
-    public static final int CONNECTION_ERROR_UNKNOWN = 0;
-
-    /**
-     * Connection error: The media router or media route service has decided not to
-     * handle the connection request for some reason.
-     */
-    public static final int CONNECTION_ERROR_ABORTED = 1;
-
-    /**
-     * Connection error: The device has refused the connection from this client.
-     * This error should be avoided because the media route service should attempt
-     * to filter out devices that the client cannot access as it performs discovery
-     * on behalf of that client.
-     */
-    public static final int CONNECTION_ERROR_UNAUTHORIZED = 2;
-
-    /**
-     * Connection error: The device is unreachable over the network.
-     */
-    public static final int CONNECTION_ERROR_UNREACHABLE = 3;
-
-    /**
-     * Connection error: The device is already busy serving another client and
-     * the connection request did not ask to barge in.
-     */
-    public static final int CONNECTION_ERROR_BUSY = 4;
-
-    /**
-     * Connection error: A timeout occurred during connection.
-     */
-    public static final int CONNECTION_ERROR_TIMEOUT = 5;
-
-    /**
-     * Connection error: The connection to the device was severed unexpectedly.
-     */
-    public static final int CONNECTION_ERROR_BROKEN = 6;
-
-    /**
-     * Connection error: The connection was terminated because a different client barged
-     * in and took control of the destination.
-     */
-    public static final int CONNECTION_ERROR_BARGED = 7;
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(value = { DISCONNECTION_REASON_APPLICATION_REQUEST,
-            DISCONNECTION_REASON_USER_REQUEST, DISCONNECTION_REASON_ERROR })
-    public @interface DisconnectionReason { }
-
-    /**
-     * Disconnection reason: The application requested disconnection itself.
-     */
-    public static final int DISCONNECTION_REASON_APPLICATION_REQUEST = 0;
-
-    /**
-     * Disconnection reason: The user requested disconnection.
-     */
-    public static final int DISCONNECTION_REASON_USER_REQUEST = 1;
-
-    /**
-     * Disconnection reason: An error occurred.
-     */
-    public static final int DISCONNECTION_REASON_ERROR = 2;
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(flag = true, value = { ROUTE_FEATURE_LIVE_AUDIO, ROUTE_FEATURE_LIVE_VIDEO })
-    public @interface RouteFeatures { }
-
-    /**
-     * Route feature: Live audio.
-     * <p>
-     * A route that supports live audio streams audio rendered by the application
-     * to the destination.
-     * </p><p>
-     * To take advantage of live audio routing, the application must render its
-     * media using the audio attributes specified by {@link #getPreferredAudioAttributes}.
-     * </p>
-     *
-     * @see #getPreferredAudioAttributes
-     * @see android.media.AudioAttributes
-     */
-    public static final int ROUTE_FEATURE_LIVE_AUDIO = 1 << 0;
-
-    /**
-     * Route feature: Live video.
-     * <p>
-     * A route that supports live video streams video rendered by the application
-     * to the destination.
-     * </p><p>
-     * To take advantage of live video routing, the application must render its
-     * media to a {@link android.app.Presentation presentation window} on the
-     * display specified by {@link #getPreferredPresentationDisplay}.
-     * </p>
-     *
-     * @see #getPreferredPresentationDisplay
-     * @see android.app.Presentation
-     */
-    public static final int ROUTE_FEATURE_LIVE_VIDEO = 1 << 1;
-
-    /**
-     * Creates a media router.
-     *
-     * @param context The context with which the router is associated.
-     */
-    public MediaRouter(@NonNull Context context) {
-        if (context == null) {
-            throw new IllegalArgumentException("context must not be null");
-        }
-
-        mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
-    }
-
-    /** @hide */
-    public IMediaRouter getBinder() {
-        // todo
-        return null;
-    }
-
-    /**
-     * Disconnects from the selected destination and releases the media router.
-     * <p>
-     * This method should be called by the application when it no longer requires
-     * the media router to ensure that all bound resources may be cleaned up.
-     * </p>
-     */
-    public void release() {
-        synchronized (mLock) {
-            mReleased = true;
-            // todo
-        }
-    }
-
-    /**
-     * Returns true if the media router has been released.
-     */
-    public boolean isReleased() {
-        synchronized (mLock) {
-            return mReleased;
-        }
-    }
-
-    /**
-     * Gets the current route discovery state.
-     *
-     * @return The current discovery state: one of {@link #DISCOVERY_STATE_STOPPED},
-     * {@link #DISCOVERY_STATE_STARTED}.
-     */
-    public @DiscoveryState int getDiscoveryState() {
-        synchronized (mLock) {
-            return mDiscoveryState;
-        }
-    }
-
-    /**
-     * Gets the current route connection state.
-     *
-     * @return The current state: one of {@link #CONNECTION_STATE_DISCONNECTED},
-     * {@link #CONNECTION_STATE_CONNECTING} or {@link #CONNECTION_STATE_CONNECTED}.
-     */
-    public @ConnectionState int getConnectionState() {
-        synchronized (mLock) {
-            return mConnectionState;
-        }
-    }
-
-    /**
-     * Creates a media router delegate through which the destination of the media
-     * router may be controlled.
-     * <p>
-     * This is the point of entry for UI code that initiates discovery and
-     * connection to routes.
-     * </p>
-     */
-    public @NonNull Delegate createDelegate() {
-        return null; // todo
-    }
-
-    /**
-     * Sets a callback to participate in route discovery, filtering, and connection
-     * establishment.
-     *
-     * @param callback The callback to set, or null if none.
-     * @param handler The handler to receive callbacks, or null to use the current thread.
-     */
-    public void setRoutingCallback(@Nullable RoutingCallback callback,
-            @Nullable Handler handler) {
-        synchronized (mLock) {
-            if (callback == null) {
-                mRoutingCallback = null;
-                mRoutingCallbackHandler = null;
-            } else {
-                mRoutingCallback = callback;
-                mRoutingCallbackHandler = handler != null ? handler : new Handler();
-            }
-        }
-    }
-
-    /**
-     * Adds a media route selector to use to find destinations that have
-     * routes with the specified capabilities during route discovery.
-     */
-    public void addSelector(@NonNull MediaRouteSelector selector) {
-        if (selector == null) {
-            throw new IllegalArgumentException("selector must not be null");
-        }
-
-        synchronized (mLock) {
-            if (!mSelectors.contains(selector)) {
-                mSelectors.add(selector);
-                // todo
-            }
-        }
-    }
-
-    /**
-     * Removes a media route selector.
-     */
-    public void removeSelector(@NonNull MediaRouteSelector selector) {
-        if (selector == null) {
-            throw new IllegalArgumentException("selector must not be null");
-        }
-
-        synchronized (mLock) {
-            if (mSelectors.remove(selector)) {
-                // todo
-            }
-        }
-    }
-
-    /**
-     * Removes all media route selectors.
-     * <p>
-     * Note that at least one selector must be added in order to perform discovery.
-     * </p>
-     */
-    public void clearSelectors() {
-        synchronized (mLock) {
-            if (!mSelectors.isEmpty()) {
-                mSelectors.clear();
-                // todo
-            }
-        }
-    }
-
-    /**
-     * Gets a list of all media route selectors to consider during discovery.
-     */
-    public @NonNull List<MediaRouteSelector> getSelectors() {
-        synchronized (mLock) {
-            return new ArrayList<MediaRouteSelector>(mSelectors);
-        }
-    }
-
-    /**
-     * Gets the connection to the currently selected route.
-     *
-     * @return The connection to the currently selected route, or null if not connected.
-     */
-    public @NonNull ConnectionInfo getConnection() {
-        synchronized (mLock) {
-            return mConnection;
-        }
-    }
-
-    /**
-     * Gets the list of discovered destinations.
-     * <p>
-     * This list is only valid while discovery is running and is null otherwise.
-     * </p>
-     *
-     * @return The list of discovered destinations, or null if discovery is not running.
-     */
-    public @NonNull List<DestinationInfo> getDiscoveredDestinations() {
-        synchronized (mLock) {
-            if (mDiscoveryState == DISCOVERY_STATE_STARTED) {
-                return new ArrayList<DestinationInfo>(mDiscoveredDestinations.keySet());
-            }
-            return null;
-        }
-    }
-
-    /**
-     * Gets the list of discovered routes for a particular destination.
-     * <p>
-     * This list is only valid while discovery is running and is null otherwise.
-     * </p>
-     *
-     * @param destination The destination for which to get the list of discovered routes.
-     * @return The list of discovered routes for the destination, or null if discovery
-     * is not running.
-     */
-    public @NonNull List<RouteInfo> getDiscoveredRoutes(@NonNull DestinationInfo destination) {
-        if (destination == null) {
-            throw new IllegalArgumentException("destination must not be null");
-        }
-        synchronized (mLock) {
-            if (mDiscoveryState == DISCOVERY_STATE_STARTED) {
-                List<RouteInfo> routes = mDiscoveredDestinations.get(destination);
-                if (routes != null) {
-                    return new ArrayList<RouteInfo>(routes);
-                }
-            }
-            return null;
-        }
-    }
-
-    /**
-     * Gets the destination that has been selected.
-     *
-     * @return The selected destination, or null if disconnected.
-     */
-    public @Nullable DestinationInfo getSelectedDestination() {
-        synchronized (mLock) {
-            return mSelectedRoute != null ? mSelectedRoute.getDestination() : null;
-        }
-    }
-
-    /**
-     * Gets the route that has been selected.
-     *
-     * @return The selected destination, or null if disconnected.
-     */
-    public @Nullable RouteInfo getSelectedRoute() {
-        synchronized (mLock) {
-            return mSelectedRoute;
-        }
-    }
-
-    /**
-     * Gets the preferred audio attributes that should be used to stream live audio content
-     * based on the connected route.
-     * <p>
-     * Use an {@link AudioTrack} to send audio content to the destination with these
-     * audio attributes.
-     * </p><p>
-     * The preferred audio attributes may change when a connection is established but it
-     * will remain constant until disconnected.
-     * </p>
-     *
-     * @return The preferred audio attributes to use.  When connected, returns the
-     * route's audio attributes or null if it does not support live audio streaming.
-     * Otherwise returns audio attributes associated with {@link AudioAttributes#USAGE_MEDIA}.
-     */
-    public @Nullable AudioAttributes getPreferredAudioAttributes() {
-        synchronized (mLock) {
-            if (mConnection != null) {
-                return mConnection.getAudioAttributes();
-            }
-            return new AudioAttributes.Builder()
-                    .setLegacyStreamType(AudioManager.STREAM_MUSIC)
-                    .build();
-        }
-    }
-
-    /**
-     * Gets the preferred presentation display that should be used to stream live video content
-     * based on the connected route.
-     * <p>
-     * Use a {@link Presentation} to send video content to the destination with this display.
-     * </p><p>
-     * The preferred presentation display may change when a connection is established but it
-     * will remain constant until disconnected.
-     * </p>
-     *
-     * @return The preferred presentation display to use.  When connected, returns
-     * the route's presentation display or null if it does not support live video
-     * streaming.  Otherwise returns the first available
-     * {@link DisplayManager#DISPLAY_CATEGORY_PRESENTATION presentation display},
-     * such as a mirrored wireless or HDMI display or null if none.
-     */
-    public @Nullable Display getPreferredPresentationDisplay() {
-        synchronized (mLock) {
-            if (mConnection != null) {
-                return mConnection.getPresentationDisplay();
-            }
-            Display[] displays = mDisplayManager.getDisplays(
-                    DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
-            return displays.length != 0 ? displays[0] : null;
-        }
-    }
-
-    /**
-     * Gets the preferred volume provider that should be used to control the volume
-     * of content rendered on the currently selected route.
-     * <p>
-     * The preferred volume provider may change when a connection is established but it
-     * will remain the same until disconnected.
-     * </p>
-     *
-     * @return The preferred volume provider to use, or null if the currently
-     * selected route does not support remote volume adjustment or if the connection
-     * is not yet established.  If no route is selected, returns null to indicate
-     * that system volume control should be used.
-     */
-    public @Nullable VolumeProvider getPreferredVolumeProvider() {
-        synchronized (mLock) {
-            if (mConnection != null) {
-                return mConnection.getVolumeProvider();
-            }
-            return null;
-        }
-    }
-
-    /**
-     * Requests to pause streaming of live audio or video routes.
-     * Should be called when the application is going into the background and is
-     * no longer rendering content locally.
-     * <p>
-     * This method does nothing unless a connection has been established.
-     * </p>
-     */
-    public void pauseStream() {
-        // todo
-    }
-
-    /**
-     * Requests to resume streaming of live audio or video routes.
-     * May be called when the application is returning to the foreground and is
-     * about to resume rendering content locally.
-     * <p>
-     * This method does nothing unless a connection has been established.
-     * </p>
-     */
-    public void resumeStream() {
-        // todo
-    }
-
-    /**
-     * This class is used by UI components to let the user discover and
-     * select a destination to which the media router should connect.
-     * <p>
-     * This API has somewhat more limited functionality than the {@link MediaRouter}
-     * itself because it is designed to allow applications to control
-     * the destination of media router instances that belong to other processes.
-     * </p><p>
-     * To control the destination of your own media router, call
-     * {@link #createDelegate} to obtain a local delegate object.
-     * </p><p>
-     * To control the destination of a media router that belongs to another process,
-     * first obtain a {@link MediaController} that is associated with the media playback
-     * that is occurring in that process, then call
-     * {@link MediaController#createMediaRouterDelegate} to obtain an instance of
-     * its destination controls.  Note that special permissions may be required to
-     * obtain the {@link MediaController} instance in the first place.
-     * </p>
-     */
-    public static final class Delegate {
-        /**
-         * Returns true if the media router has been released.
-         */
-        public boolean isReleased() {
-            // todo
-            return false;
-        }
-
-        /**
-         * Gets the current route discovery state.
-         *
-         * @return The current discovery state: one of {@link #DISCOVERY_STATE_STOPPED},
-         * {@link #DISCOVERY_STATE_STARTED}.
-         */
-        public @DiscoveryState int getDiscoveryState() {
-            // todo
-            return -1;
-        }
-
-        /**
-         * Gets the current route connection state.
-         *
-         * @return The current state: one of {@link #CONNECTION_STATE_DISCONNECTED},
-         * {@link #CONNECTION_STATE_CONNECTING} or {@link #CONNECTION_STATE_CONNECTED}.
-         */
-        public @ConnectionState int getConnectionState() {
-            // todo
-            return -1;
-        }
-
-        /**
-         * Gets the currently selected destination.
-         *
-         * @return The destination information, or null if none.
-         */
-        public @Nullable DestinationInfo getSelectedDestination() {
-            return null;
-        }
-
-        /**
-         * Gets the list of discovered destinations.
-         * <p>
-         * This list is only valid while discovery is running and is null otherwise.
-         * </p>
-         *
-         * @return The list of discovered destinations, or null if discovery is not running.
-         */
-        public @NonNull List<DestinationInfo> getDiscoveredDestinations() {
-            return null;
-        }
-
-        /**
-         * Adds a callback to receive state changes.
-         *
-         * @param callback The callback to set, or null if none.
-         * @param handler The handler to receive callbacks, or null to use the current thread.
-         */
-        public void addStateCallback(@Nullable StateCallback callback,
-                @Nullable Handler handler) {
-            if (callback == null) {
-                throw new IllegalArgumentException("callback must not be null");
-            }
-            if (handler == null) {
-                handler = new Handler();
-            }
-            // todo
-        }
-
-        /**
-         * Removes a callback for state changes.
-         *
-         * @param callback The callback to set, or null if none.
-         */
-        public void removeStateCallback(@Nullable StateCallback callback) {
-            // todo
-        }
-
-        /**
-         * Starts performing discovery.
-         * <p>
-         * Performing discovery is expensive.  Make sure to call {@link #stopDiscovery}
-         * as soon as possible once a new destination has been selected to allow the system
-         * to stop services associated with discovery.
-         * </p>
-         *
-         * @param flags The discovery flags, such as {@link MediaRouter#DISCOVERY_FLAG_BACKGROUND}.
-         */
-        public void startDiscovery(@DiscoveryFlags int flags) {
-            // todo
-        }
-
-        /**
-         * Stops performing discovery.
-         */
-        public void stopDiscovery() {
-            // todo
-        }
-
-        /**
-         * Connects to a destination during route discovery.
-         * <p>
-         * This method may only be called while route discovery is active and the
-         * destination appears in the
-         * {@link #getDiscoveredDestinations list of discovered destinations}.
-         * If the media router is already connected to a route then it will first disconnect
-         * from the current route then connect to the new route.
-         * </p>
-         *
-         * @param destination The destination to which the media router should connect.
-         * @param flags The connection flags, such as {@link MediaRouter#CONNECTION_FLAG_BARGE}.
-         */
-        public void connect(@NonNull DestinationInfo destination, @DiscoveryFlags int flags) {
-            // todo
-        }
-
-        /**
-         * Disconnects from the currently selected destination.
-         * <p>
-         * Does nothing if not currently connected.
-         * </p>
-         *
-         * @param reason The reason for the disconnection: one of
-         * {@link #DISCONNECTION_REASON_APPLICATION_REQUEST},
-         * {@link #DISCONNECTION_REASON_USER_REQUEST}, or {@link #DISCONNECTION_REASON_ERROR}.
-         */
-        public void disconnect(@DisconnectionReason int reason) {
-            // todo
-        }
-    }
-
-    /**
-     * Describes immutable properties of a connection to a route.
-     */
-    public static final class ConnectionInfo {
-        private final RouteInfo mRoute;
-        private final AudioAttributes mAudioAttributes;
-        private final Display mPresentationDisplay;
-        private final VolumeProvider mVolumeProvider;
-        private final IBinder[] mProtocolBinders;
-        private final Object[] mProtocolInstances;
-        private final Bundle mExtras;
-        private final ArrayList<Closeable> mCloseables;
-
-        private static final Class<?>[] MEDIA_ROUTE_PROTOCOL_CTOR_PARAMETERS =
-                new Class<?>[] { IBinder.class };
-
-        ConnectionInfo(RouteInfo route,
-                AudioAttributes audioAttributes, Display display,
-                VolumeProvider volumeProvider, IBinder[] protocolBinders,
-                Bundle extras, ArrayList<Closeable> closeables) {
-            mRoute = route;
-            mAudioAttributes = audioAttributes;
-            mPresentationDisplay = display;
-            mVolumeProvider = volumeProvider;
-            mProtocolBinders = protocolBinders;
-            mProtocolInstances = new Object[mProtocolBinders.length];
-            mExtras = extras;
-            mCloseables = closeables;
-        }
-
-        /**
-         * Gets the route that is connected.
-         */
-        public @NonNull RouteInfo getRoute() {
-            return mRoute;
-        }
-
-        /**
-         * Gets the audio attributes which the client should use to stream audio
-         * to the destination, or null if the route does not support live audio streaming.
-         */
-        public @Nullable AudioAttributes getAudioAttributes() {
-            return mAudioAttributes;
-        }
-
-        /**
-         * Gets the display which the client should use to stream video to the
-         * destination using a {@link Presentation}, or null if the route does not
-         * support live video streaming.
-         */
-        public @Nullable Display getPresentationDisplay() {
-            return mPresentationDisplay;
-        }
-
-        /**
-         * Gets the route's volume provider, or null if none.
-         */
-        public @Nullable VolumeProvider getVolumeProvider() {
-            return mVolumeProvider;
-        }
-
-        /**
-         * Gets the set of supported route features.
-         */
-        public @RouteFeatures int getFeatures() {
-            return mRoute.getFeatures();
-        }
-
-        /**
-         * Gets the list of supported route protocols.
-         * <p>
-         * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
-         * for more information.
-         * </p>
-         */
-        public @NonNull List<String> getProtocols() {
-            return mRoute.getProtocols();
-        }
-
-        /**
-         * Gets an instance of a route protocol object that wraps the protocol binder
-         * and provides easy access to the protocol's functionality.
-         * <p>
-         * This is a convenience method which invokes {@link #getProtocolBinder(String)}
-         * using the name of the provided class then passes the resulting {@link IBinder}
-         * to a single-argument constructor of that class.
-         * </p><p>
-         * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
-         * for more information.
-         * </p>
-         */
-        @SuppressWarnings("unchecked")
-        public @Nullable <T> T getProtocolObject(Class<T> clazz) {
-            int index = getProtocols().indexOf(clazz.getName());
-            if (index < 0) {
-                return null;
-            }
-            if (mProtocolInstances[index] == null && mProtocolBinders[index] != null) {
-                final Constructor<T> ctor;
-                try {
-                    ctor = clazz.getConstructor(MEDIA_ROUTE_PROTOCOL_CTOR_PARAMETERS);
-                } catch (NoSuchMethodException ex) {
-                    throw new RuntimeException("Could not find public constructor "
-                            + "with IBinder argument in protocol class: " + clazz.getName(), ex);
-                }
-                try {
-                    mProtocolInstances[index] = ctor.newInstance(mProtocolBinders[index]);
-                } catch (InstantiationException | IllegalAccessException
-                        | InvocationTargetException ex) {
-                    throw new RuntimeException("Could create instance of protocol class: "
-                            + clazz.getName(), ex);
-                }
-            }
-            return (T)mProtocolInstances[index];
-        }
-
-        /**
-         * Gets the {@link IBinder} that provides access to the specified route protocol
-         * or null if the protocol is not supported.
-         * <p>
-         * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
-         * for more information.
-         * </p>
-         */
-        public @Nullable IBinder getProtocolBinder(@NonNull String name) {
-            int index = getProtocols().indexOf(name);
-            return index >= 0 ? mProtocolBinders[index] : null;
-        }
-
-        /**
-         * Gets the {@link IBinder} that provides access to the specified route protocol
-         * at the given index in the protocol list or null if the protocol is not supported.
-         * <p>
-         * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
-         * for more information.
-         * </p>
-         */
-        public @Nullable IBinder getProtocolBinder(int index) {
-            return mProtocolBinders[index];
-        }
-
-        /**
-         * Gets optional extra media route service or protocol specific information about
-         * the connection.  Use the service or protocol name as the prefix for
-         * any extras to avoid namespace collisions.
-         */
-        public @Nullable Bundle getExtras() {
-            return mExtras;
-        }
-
-        /**
-         * Closes all closeables associated with the connection when the connection
-         * is being torn down.
-         */
-        void close() {
-            final int count = mCloseables.size();
-            for (int i = 0; i < count; i++) {
-                try {
-                    mCloseables.get(i).close();
-                } catch (IOException ex) {
-                }
-            }
-        }
-
-        @Override
-        public @NonNull String toString() {
-            return "ConnectionInfo{ route=" + mRoute
-                    + ", audioAttributes=" + mAudioAttributes
-                    + ", presentationDisplay=" + mPresentationDisplay
-                    + ", volumeProvider=" + mVolumeProvider
-                    + ", protocolBinders=" + mProtocolBinders + " }";
-        }
-
-        /**
-         * Builds {@link ConnectionInfo} objects.
-         */
-        public static final class Builder {
-            private final RouteInfo mRoute;
-            private AudioAttributes mAudioAttributes;
-            private Display mPresentationDisplay;
-            private VolumeProvider mVolumeProvider;
-            private final IBinder[] mProtocols;
-            private Bundle mExtras;
-            private final ArrayList<Closeable> mCloseables = new ArrayList<Closeable>();
-
-            /**
-             * Creates a builder for connection information.
-             *
-             * @param route The route that is connected.
-             */
-            public Builder(@NonNull RouteInfo route) {
-                if (route == null) {
-                    throw new IllegalArgumentException("route");
-                }
-                mRoute = route;
-                mProtocols = new IBinder[route.getProtocols().size()];
-            }
-
-            /**
-             * Sets the audio attributes which the client should use to stream audio
-             * to the destination, or null if the route does not support live audio streaming.
-             */
-            public @NonNull Builder setAudioAttributes(
-                    @Nullable AudioAttributes audioAttributes) {
-                mAudioAttributes = audioAttributes;
-                return this;
-            }
-
-            /**
-             * Sets the display which the client should use to stream video to the
-             * destination using a {@link Presentation}, or null if the route does not
-             * support live video streaming.
-             */
-            public @NonNull Builder setPresentationDisplay(@Nullable Display display) {
-                mPresentationDisplay = display;
-                return this;
-            }
-
-            /**
-             * Sets the route's volume provider, or null if none.
-             */
-            public @NonNull Builder setVolumeProvider(@Nullable VolumeProvider provider) {
-                mVolumeProvider = provider;
-                return this;
-            }
-
-            /**
-             * Sets the binder stub of a supported route protocol using
-             * the protocol's fully qualified class name.  The protocol must be one
-             * of those that was indicated as being supported by the route.
-             * <p>
-             * If the stub implements {@link Closeable} then it will automatically
-             * be closed when the client disconnects from the route.
-             * </p><p>
-             * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
-             * for more information.
-             * </p>
-             */
-            public @NonNull Builder setProtocolStub(@NonNull Class<?> clazz,
-                    @NonNull IInterface stub) {
-                if (clazz == null) {
-                    throw new IllegalArgumentException("clazz must not be null");
-                }
-                if (stub == null) {
-                    throw new IllegalArgumentException("stub must not be null");
-                }
-                if (stub instanceof Closeable) {
-                    mCloseables.add((Closeable)stub);
-                }
-                return setProtocolBinder(clazz.getName(), stub.asBinder());
-            }
-
-            /**
-             * Sets the binder interface of a supported route protocol by name.
-             * The protocol must be one of those that was indicated as being supported
-             * by the route.
-             * <p>
-             * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
-             * for more information.
-             * </p>
-             */
-            public @NonNull Builder setProtocolBinder(@NonNull String name,
-                    @NonNull IBinder binder) {
-                if (TextUtils.isEmpty(name)) {
-                    throw new IllegalArgumentException("name must not be null or empty");
-                }
-                if (binder == null) {
-                    throw new IllegalArgumentException("binder must not be null");
-                }
-                int index = mRoute.getProtocols().indexOf(name);
-                if (index < 0) {
-                    throw new IllegalArgumentException("name must specify a protocol that "
-                            + "the route actually declared that it supports: "
-                            + "name=" + name + ", protocols=" + mRoute.getProtocols());
-                }
-                mProtocols[index] = binder;
-                return this;
-            }
-
-            /**
-             * Sets optional extra media route service or protocol specific information about
-             * the connection.  Use the service or protocol name as the prefix for
-             * any extras to avoid namespace collisions.
-             */
-            public @NonNull Builder setExtras(@Nullable Bundle extras) {
-                mExtras = extras;
-                return this;
-            }
-
-            /**
-             * Builds the {@link ConnectionInfo} object.
-             */
-            public @NonNull ConnectionInfo build() {
-                return new ConnectionInfo(mRoute,
-                        mAudioAttributes, mPresentationDisplay,
-                        mVolumeProvider, mProtocols, mExtras, mCloseables);
-            }
-        }
-    }
-
-    /**
-     * Describes one particular way of routing media content to a destination
-     * according to the capabilities specified by a media route selector on behalf
-     * of an application.
-     */
-    public static final class RouteInfo {
-        private final String mId;
-        private final DestinationInfo mDestination;
-        private final MediaRouteSelector mSelector;
-        private final int mFeatures;
-        private final ArrayList<String> mProtocols;
-        private final Bundle mExtras;
-
-        RouteInfo(String id, DestinationInfo destination, MediaRouteSelector selector,
-                int features, ArrayList<String> protocols, Bundle extras) {
-            mId = id;
-            mDestination = destination;
-            mSelector = selector;
-            mFeatures = features;
-            mProtocols = protocols;
-            mExtras = extras;
-        }
-
-        /**
-         * Gets the route's stable identifier.
-         * <p>
-         * The id is intended to uniquely identify the route among all routes that
-         * are offered by a particular destination in such a way that the client can
-         * refer to it at a later time.
-         * </p>
-         */
-        public @NonNull String getId() {
-            return mId;
-        }
-
-        /**
-         * Gets the destination that is offering this route.
-         */
-        public @NonNull DestinationInfo getDestination() {
-            return mDestination;
-        }
-
-        /**
-         * Gets the media route selector provided by the client for which this
-         * route was created.
-         * <p>
-         * It is implied that this route supports all of the required capabilities
-         * that were expressed in the selector.
-         * </p>
-         */
-        public @NonNull MediaRouteSelector getSelector() {
-            return mSelector;
-        }
-
-        /**
-         * Gets the set of supported route features.
-         */
-        public @RouteFeatures int getFeatures() {
-            return mFeatures;
-        }
-
-        /**
-         * Gets the list of supported route protocols.
-         * <p>
-         * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
-         * for more information.
-         * </p>
-         */
-        public @NonNull List<String> getProtocols() {
-            return mProtocols;
-        }
-
-        /**
-         * Gets optional extra information about the route, or null if none.
-         */
-        public @Nullable Bundle getExtras() {
-            return mExtras;
-        }
-
-        @Override
-        public @NonNull String toString() {
-            return "RouteInfo{ id=" + mId + ", destination=" + mDestination
-                    + ", features=0x" + Integer.toHexString(mFeatures)
-                    + ", selector=" + mSelector + ", protocols=" + mProtocols
-                    + ", extras=" + mExtras + " }";
-        }
-
-        /**
-         * Builds {@link RouteInfo} objects.
-         */
-        public static final class Builder {
-            private final DestinationInfo mDestination;
-            private final String mId;
-            private final MediaRouteSelector mSelector;
-            private int mFeatures;
-            private final ArrayList<String> mProtocols = new ArrayList<String>();
-            private Bundle mExtras;
-
-            /**
-             * Creates a builder for route information.
-             *
-             * @param id The route's stable identifier.
-             * @param destination The destination of this route.
-             * @param selector The media route selector provided by the client for which
-             * this route was created.  This must be one of the selectors that was
-             * included in the discovery request.
-             */
-            public Builder(@NonNull String id, @NonNull DestinationInfo destination,
-                    @NonNull MediaRouteSelector selector) {
-                if (TextUtils.isEmpty(id)) {
-                    throw new IllegalArgumentException("id must not be null or empty");
-                }
-                if (destination == null) {
-                    throw new IllegalArgumentException("destination must not be null");
-                }
-                if (selector == null) {
-                    throw new IllegalArgumentException("selector must not be null");
-                }
-                mDestination = destination;
-                mId = id;
-                mSelector = selector;
-            }
-
-            /**
-             * Sets the set of supported route features.
-             */
-            public @NonNull Builder setFeatures(@RouteFeatures int features) {
-                mFeatures = features;
-                return this;
-            }
-
-            /**
-             * Adds a supported route protocol using its fully qualified class name.
-             * <p>
-             * If the protocol was not requested by the client in its selector
-             * then it will be silently discarded.
-             * </p>
-             */
-            public @NonNull <T extends IInterface> Builder addProtocol(@NonNull Class<T> clazz) {
-                if (clazz == null) {
-                    throw new IllegalArgumentException("clazz must not be null");
-                }
-                return addProtocol(clazz.getName());
-            }
-
-            /**
-             * Adds a supported route protocol by name.
-             * <p>
-             * If the protocol was not requested by the client in its selector
-             * then it will be silently discarded.
-             * </p>
-             */
-            public @NonNull Builder addProtocol(@NonNull String name) {
-                if (TextUtils.isEmpty(name)) {
-                    throw new IllegalArgumentException("name must not be null");
-                }
-                if (mSelector.containsProtocol(name)) {
-                    mProtocols.add(name);
-                }
-                return this;
-            }
-
-            /**
-             * Sets optional extra information about the route, or null if none.
-             */
-            public @NonNull Builder setExtras(@Nullable Bundle extras) {
-                mExtras = extras;
-                return this;
-            }
-
-            /**
-             * Builds the {@link RouteInfo} object.
-             * <p>
-             * Ensures that all required protocols have been supplied.
-             * </p>
-             */
-            public @NonNull RouteInfo build() {
-                int missingFeatures = mSelector.getRequiredFeatures() & ~mFeatures;
-                if (missingFeatures != 0) {
-                    throw new IllegalStateException("The media route selector "
-                            + "specified required features which this route does "
-                            + "not appear to support so it should not have been published: "
-                            + "missing 0x" + Integer.toHexString(missingFeatures));
-                }
-                for (String protocol : mSelector.getRequiredProtocols()) {
-                    if (!mProtocols.contains(protocol)) {
-                        throw new IllegalStateException("The media route selector "
-                                + "specified required protocols which this route "
-                                + "does not appear to support so it should not have "
-                                + "been published: missing " + protocol);
-                    }
-                }
-                return new RouteInfo(mId, mDestination, mSelector,
-                        mFeatures, mProtocols, mExtras);
-            }
-        }
-    }
-
-    /**
-     * Describes a destination for media content such as a device,
-     * an individual port on a device, or a group of devices.
-     */
-    public static final class DestinationInfo {
-        private final String mId;
-        private final ServiceMetadata mService;
-        private final CharSequence mName;
-        private final CharSequence mDescription;
-        private final int mIconResourceId;
-        private final Bundle mExtras;
-
-        DestinationInfo(String id, ServiceMetadata service,
-                CharSequence name, CharSequence description,
-                int iconResourceId, Bundle extras) {
-            mId = id;
-            mService = service;
-            mName = name;
-            mDescription = description;
-            mIconResourceId = iconResourceId;
-            mExtras = extras;
-        }
-
-        /**
-         * Gets the destination's stable identifier.
-         * <p>
-         * The id is intended to uniquely identify the destination among all destinations
-         * provided by the media route service in such a way that the client can
-         * refer to it at a later time.  Ideally, the id should be resilient to
-         * user-initiated actions such as changes to the name or description
-         * of the destination.
-         * </p>
-         */
-        public @NonNull String getId() {
-            return mId;
-        }
-
-        /**
-         * Gets metadata about the service that is providing access to this destination.
-         */
-        public @NonNull ServiceMetadata getServiceMetadata() {
-            return mService;
-        }
-
-        /**
-         * Gets the destination's name for display to the user.
-         */
-        public @NonNull CharSequence getName() {
-            return mName;
-        }
-
-        /**
-         * Gets the destination's description for display to the user, or null if none.
-         */
-        public @Nullable CharSequence getDescription() {
-            return mDescription;
-        }
-
-        /**
-         * Gets an icon resource from the service's package which is used
-         * to identify the destination, or -1 if none.
-         */
-        public @DrawableRes int getIconResourceId() {
-            return mIconResourceId;
-        }
-
-        /**
-         * Loads the icon drawable, or null if none.
-         */
-        public @Nullable Drawable loadIcon(@NonNull PackageManager pm) {
-            return mIconResourceId >= 0 ? mService.getDrawable(pm, mIconResourceId) : null;
-        }
-
-        /**
-         * Gets optional extra information about the destination, or null if none.
-         */
-        public @Nullable Bundle getExtras() {
-            return mExtras;
-        }
-
-        @Override
-        public @NonNull String toString() {
-            return "DestinationInfo{ id=" + mId + ", service=" + mService + ", name=" + mName
-                    + ", description=" + mDescription + ", iconResourceId=" + mIconResourceId
-                    + ", extras=" + mExtras + " }";
-        }
-
-        /**
-         * Builds {@link DestinationInfo} objects.
-         */
-        public static final class Builder {
-            private final String mId;
-            private final ServiceMetadata mService;
-            private final CharSequence mName;
-            private CharSequence mDescription;
-            private int mIconResourceId = -1;
-            private Bundle mExtras;
-
-            /**
-             * Creates a builder for destination information.
-             *
-             * @param id The destination's stable identifier.
-             * @param service Metatada about the service that is providing access to
-             * this destination.
-             * @param name The destination's name for display to the user.
-             */
-            public Builder(@NonNull String id, @NonNull ServiceMetadata service,
-                    @NonNull CharSequence name) {
-                if (TextUtils.isEmpty(id)) {
-                    throw new IllegalArgumentException("id must not be null or empty");
-                }
-                if (service == null) {
-                    throw new IllegalArgumentException("service must not be null");
-                }
-                if (TextUtils.isEmpty(name)) {
-                    throw new IllegalArgumentException("name must not be null or empty");
-                }
-                mId = id;
-                mService = service;
-                mName = name;
-            }
-
-            /**
-             * Sets the destination's description for display to the user, or null if none.
-             */
-            public @NonNull Builder setDescription(@Nullable CharSequence description) {
-                mDescription = description;
-                return this;
-            }
-
-            /**
-             * Sets an icon resource from this package used to identify the destination,
-             * or -1 if none.
-             */
-            public @NonNull Builder setIconResourceId(@DrawableRes int resid) {
-                mIconResourceId = resid;
-                return this;
-            }
-
-            /**
-             * Gets optional extra information about the destination, or null if none.
-             */
-            public @NonNull Builder setExtras(@Nullable Bundle extras) {
-                mExtras = extras;
-                return this;
-            }
-
-            /**
-             * Builds the {@link DestinationInfo} object.
-             */
-            public @NonNull DestinationInfo build() {
-                return new DestinationInfo(mId, mService, mName, mDescription,
-                        mIconResourceId, mExtras);
-            }
-        }
-    }
-
-    /**
-     * Describes metadata about a {@link MediaRouteService} which is providing
-     * access to certain kinds of destinations.
-     */
-    public static final class ServiceMetadata {
-        private final ServiceInfo mService;
-        private CharSequence mLabel;
-        private Drawable mIcon;
-
-        ServiceMetadata(Service service) throws NameNotFoundException {
-            mService = service.getPackageManager().getServiceInfo(
-                    new ComponentName(service, service.getClass()),
-                    PackageManager.GET_META_DATA);
-        }
-
-        ServiceMetadata(ServiceInfo service) {
-            mService = service;
-        }
-
-        /**
-         * Gets the service's component information including it name, label and icon.
-         */
-        public @NonNull ServiceInfo getService() {
-            return mService;
-        }
-
-        /**
-         * Gets the service's component name.
-         */
-        public @NonNull ComponentName getComponentName() {
-            return new ComponentName(mService.packageName, mService.name);
-        }
-
-        /**
-         * Gets the service's package name.
-         */
-        public @NonNull String getPackageName() {
-            return mService.packageName;
-        }
-
-        /**
-         * Gets the service's name for display to the user, or null if none.
-         */
-        public @NonNull CharSequence getLabel(@NonNull PackageManager pm) {
-            if (mLabel == null) {
-                mLabel = mService.loadLabel(pm);
-            }
-            return mLabel;
-        }
-
-        /**
-         * Gets the icon drawable, or null if none.
-         */
-        public @Nullable Drawable getIcon(@NonNull PackageManager pm) {
-            if (mIcon == null) {
-                mIcon = mService.loadIcon(pm);
-            }
-            return mIcon;
-        }
-
-        // TODO: add service metadata
-
-        Drawable getDrawable(PackageManager pm, int resid) {
-            return pm.getDrawable(getPackageName(), resid, mService.applicationInfo);
-        }
-
-        @Override
-        public @NonNull String toString() {
-            return "ServiceInfo{ service=" + getComponentName().toShortString() + " }";
-        }
-    }
-
-    /**
-     * Describes a request to discover routes on behalf of an application.
-     */
-    public static final class DiscoveryRequest {
-        private final ArrayList<MediaRouteSelector> mSelectors =
-                new ArrayList<MediaRouteSelector>();
-        private int mFlags;
-
-        DiscoveryRequest(@NonNull List<MediaRouteSelector> selectors) {
-            setSelectors(selectors);
-        }
-
-        /**
-         * Sets the list of media route selectors to consider during discovery.
-         */
-        public void setSelectors(@NonNull List<MediaRouteSelector> selectors) {
-            if (selectors == null) {
-                throw new IllegalArgumentException("selectors");
-            }
-            mSelectors.clear();
-            mSelectors.addAll(selectors);
-        }
-
-        /**
-         * Gets the list of media route selectors to consider during discovery.
-         */
-        public @NonNull List<MediaRouteSelector> getSelectors() {
-            return mSelectors;
-        }
-
-        /**
-         * Gets discovery flags, such as {@link MediaRouter#DISCOVERY_FLAG_BACKGROUND}.
-         */
-        public @DiscoveryFlags int getFlags() {
-            return mFlags;
-        }
-
-        /**
-         * Sets discovery flags, such as {@link MediaRouter#DISCOVERY_FLAG_BACKGROUND}.
-         */
-        public void setFlags(@DiscoveryFlags int flags) {
-            mFlags = flags;
-        }
-
-        @Override
-        public @NonNull String toString() {
-            return "DiscoveryRequest{ selectors=" + mSelectors
-                    + ", flags=0x" + Integer.toHexString(mFlags)
-                    + " }";
-        }
-    }
-
-    /**
-     * Describes a request to connect to a previously discovered route on
-     * behalf of an application.
-     */
-    public static final class ConnectionRequest {
-        private RouteInfo mRoute;
-        private int mFlags;
-        private Bundle mExtras;
-
-        ConnectionRequest(@NonNull RouteInfo route) {
-            setRoute(route);
-        }
-
-        /**
-         * Gets the route to which to connect.
-         */
-        public @NonNull RouteInfo getRoute() {
-            return mRoute;
-        }
-
-        /**
-         * Sets the route to which to connect.
-         */
-        public void setRoute(@NonNull RouteInfo route) {
-            if (route == null) {
-                throw new IllegalArgumentException("route must not be null");
-            }
-            mRoute = route;
-        }
-
-        /**
-         * Gets connection flags, such as {@link MediaRouter#CONNECTION_FLAG_BARGE}.
-         */
-        public @ConnectionFlags int getFlags() {
-            return mFlags;
-        }
-
-        /**
-         * Sets connection flags, such as {@link MediaRouter#CONNECTION_FLAG_BARGE}.
-         */
-        public void setFlags(@ConnectionFlags int flags) {
-            mFlags = flags;
-        }
-
-        /**
-         * Gets optional extras supplied by the application as part of the call to
-         * connect, or null if none.  The media route service may use this
-         * information to configure the route during connection.
-         */
-        public @Nullable Bundle getExtras() {
-            return mExtras;
-        }
-
-        /**
-         * Sets optional extras supplied by the application as part of the call to
-         * connect, or null if none.  The media route service may use this
-         * information to configure the route during connection.
-         */
-        public void setExtras(@Nullable Bundle extras) {
-            mExtras = extras;
-        }
-
-        @Override
-        public @NonNull String toString() {
-            return "ConnectionRequest{ route=" + mRoute
-                    + ", flags=0x" + Integer.toHexString(mFlags)
-                    + ", extras=" + mExtras + " }";
-        }
-    }
-
-    /**
-     * Callback interface to specify policy for route discovery, filtering,
-     * and connection establishment as well as observe media router state changes.
-     */
-    public static abstract class RoutingCallback extends StateCallback {
-        /**
-         * Called to prepare a discovery request object to specify the desired
-         * media route selectors when the media router has been asked to start discovery.
-         * <p>
-         * By default, the discovery request contains all of the selectors which
-         * have been added to the media router.  Subclasses may override the list of
-         * selectors by modifying the discovery request object before returning.
-         * </p>
-         *
-         * @param request The discovery request object which may be modified by
-         * this method to alter how discovery will be performed.
-         * @param selectors The immutable list of media route selectors which were
-         * added to the media router.
-         * @return True to allow discovery to proceed or false to abort it.
-         * By default, this methods returns true.
-         */
-        public boolean onPrepareDiscoveryRequest(@NonNull DiscoveryRequest request,
-                @NonNull List<MediaRouteSelector> selectors) {
-            return true;
-        }
-
-        /**
-         * Called to prepare a connection request object to specify the desired
-         * route and connection parameters when the media router has been asked to
-         * connect to a particular destination.
-         * <p>
-         * By default, the connection request specifies the first available route
-         * to the destination.  Subclasses may override the route and destination
-         * or set additional connection parameters by modifying the connection request
-         * object before returning.
-         * </p>
-         *
-         * @param request The connection request object which may be modified by
-         * this method to alter how the connection will be established.
-         * @param destination The destination to which the media router was asked
-         * to connect.
-         * @param routes The list of routes that belong to that destination sorted
-         * in the same order as their matching media route selectors which were
-         * used during discovery.
-         * @return True to allow the connection to proceed or false to abort it.
-         * By default, this methods returns true.
-         */
-        public boolean onPrepareConnectionRequest(
-                @NonNull ConnectionRequest request,
-                @NonNull DestinationInfo destination, @NonNull List<RouteInfo> routes) {
-            return true;
-        }
-    }
-
-    /**
-     * Callback class to receive events from a {@link MediaRouter.Delegate}.
-     */
-    public static abstract class StateCallback {
-        /**
-         * Called when the media router has been released.
-         */
-        public void onReleased() { }
-
-        /**
-         * Called when the discovery state has changed.
-         *
-         * @param state The new discovery state: one of
-         * {@link #DISCOVERY_STATE_STOPPED} or {@link #DISCOVERY_STATE_STARTED}.
-         */
-        public void onDiscoveryStateChanged(@DiscoveryState int state) { }
-
-        /**
-         * Called when the connection state has changed.
-         *
-         * @param state The new connection state: one of
-         * {@link #CONNECTION_STATE_DISCONNECTED}, {@link #CONNECTION_STATE_CONNECTING}
-         * or {@link #CONNECTION_STATE_CONNECTED}.
-         */
-        public void onConnectionStateChanged(@ConnectionState int state) { }
-
-        /**
-         * Called when the selected destination has changed.
-         *
-         * @param destination The new selected destination, or null if none.
-         */
-        public void onSelectedDestinationChanged(@Nullable DestinationInfo destination) { }
-
-        /**
-         * Called when route discovery has started.
-         */
-        public void onDiscoveryStarted() { }
-
-        /**
-         * Called when route discovery has stopped normally.
-         * <p>
-         * Abnormal termination is reported via {@link #onDiscoveryFailed}.
-         * </p>
-         */
-        public void onDiscoveryStopped() { }
-
-        /**
-         * Called when discovery has failed in a non-recoverable manner.
-         *
-         * @param error The error code: one of
-         * {@link MediaRouter#DISCOVERY_ERROR_UNKNOWN},
-         * {@link MediaRouter#DISCOVERY_ERROR_ABORTED},
-         * or {@link MediaRouter#DISCOVERY_ERROR_NO_CONNECTIVITY}.
-         * @param message The localized error message, or null if none.  This message
-         * may be shown to the user.
-         * @param extras Additional information about the error which a client
-         * may use, or null if none.
-         */
-        public void onDiscoveryFailed(@DiscoveryError int error, @Nullable CharSequence message,
-                @Nullable Bundle extras) { }
-
-        /**
-         * Called when a new destination is found or has changed during discovery.
-         * <p>
-         * Certain destinations may be omitted because they have been filtered
-         * out by the media router's routing callback.
-         * </p>
-         *
-         * @param destination The destination that was found.
-         */
-        public void onDestinationFound(@NonNull DestinationInfo destination) { }
-
-        /**
-         * Called when a destination is no longer reachable or is no longer
-         * offering any routes that satisfy the discovery request.
-         *
-         * @param destination The destination that went away.
-         */
-        public void onDestinationLost(@NonNull DestinationInfo destination) { }
-
-        /**
-         * Called when a connection attempt begins.
-         */
-        public void onConnecting() { }
-
-        /**
-         * Called when the connection succeeds.
-         */
-        public void onConnected() { }
-
-        /**
-         * Called when the connection is terminated normally.
-         * <p>
-         * Abnormal termination is reported via {@link #onConnectionFailed}.
-         * </p>
-         */
-        public void onDisconnected() { }
-
-        /**
-         * Called when a connection attempt or connection in
-         * progress has failed in a non-recoverable manner.
-         *
-         * @param error The error code: one of
-         * {@link MediaRouter#CONNECTION_ERROR_ABORTED},
-         * {@link MediaRouter#CONNECTION_ERROR_UNAUTHORIZED},
-         * {@link MediaRouter#CONNECTION_ERROR_UNREACHABLE},
-         * {@link MediaRouter#CONNECTION_ERROR_BUSY},
-         * {@link MediaRouter#CONNECTION_ERROR_TIMEOUT},
-         * {@link MediaRouter#CONNECTION_ERROR_BROKEN},
-         * or {@link MediaRouter#CONNECTION_ERROR_BARGED}.
-         * @param message The localized error message, or null if none.  This message
-         * may be shown to the user.
-         * @param extras Additional information about the error which a client
-         * may use, or null if none.
-         */
-        public void onConnectionFailed(@ConnectionError int error,
-                @Nullable CharSequence message, @Nullable Bundle extras) { }
-    }
-}
diff --git a/media/java/android/media/routing/ParcelableConnectionInfo.aidl b/media/java/android/media/routing/ParcelableConnectionInfo.aidl
deleted file mode 100644
index 4a9ec94..0000000
--- a/media/java/android/media/routing/ParcelableConnectionInfo.aidl
+++ /dev/null
@@ -1,18 +0,0 @@
-/* Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.media.routing;
-
-parcelable ParcelableConnectionInfo;
diff --git a/media/java/android/media/routing/ParcelableConnectionInfo.java b/media/java/android/media/routing/ParcelableConnectionInfo.java
deleted file mode 100644
index 45cfe9f..0000000
--- a/media/java/android/media/routing/ParcelableConnectionInfo.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.media.routing;
-
-import android.media.AudioAttributes;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Internal parcelable representation of a media route connection.
- */
-class ParcelableConnectionInfo implements Parcelable {
-    public AudioAttributes audioAttributes;
-    public int presentationDisplayId = -1;
-    // todo: volume
-    public IBinder[] protocolBinders;
-    public Bundle extras;
-
-    public static final Parcelable.Creator<ParcelableConnectionInfo> CREATOR =
-            new Parcelable.Creator<ParcelableConnectionInfo>() {
-        @Override
-        public ParcelableConnectionInfo createFromParcel(Parcel source) {
-            ParcelableConnectionInfo info = new ParcelableConnectionInfo();
-            if (source.readInt() != 0) {
-                info.audioAttributes = AudioAttributes.CREATOR.createFromParcel(source);
-            }
-            info.presentationDisplayId = source.readInt();
-            info.protocolBinders = source.createBinderArray();
-            info.extras = source.readBundle();
-            return info;
-        }
-
-        @Override
-        public ParcelableConnectionInfo[] newArray(int size) {
-            return new ParcelableConnectionInfo[size];
-        }
-    };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        if (audioAttributes != null) {
-            dest.writeInt(1);
-            audioAttributes.writeToParcel(dest, flags);
-        } else {
-            dest.writeInt(0);
-        }
-        dest.writeInt(presentationDisplayId);
-        dest.writeBinderArray(protocolBinders);
-        dest.writeBundle(extras);
-    }
-}
diff --git a/media/java/android/media/routing/ParcelableDestinationInfo.aidl b/media/java/android/media/routing/ParcelableDestinationInfo.aidl
deleted file mode 100644
index bf1c198..0000000
--- a/media/java/android/media/routing/ParcelableDestinationInfo.aidl
+++ /dev/null
@@ -1,18 +0,0 @@
-/* Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.media.routing;
-
-parcelable ParcelableDestinationInfo;
diff --git a/media/java/android/media/routing/ParcelableDestinationInfo.java b/media/java/android/media/routing/ParcelableDestinationInfo.java
deleted file mode 100644
index eca5eec..0000000
--- a/media/java/android/media/routing/ParcelableDestinationInfo.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.media.routing;
-
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-
-/**
- * Internal parcelable representation of a media destination.
- */
-class ParcelableDestinationInfo implements Parcelable {
-    public String id;
-    public CharSequence name;
-    public CharSequence description;
-    public int iconResourceId;
-    public Bundle extras;
-
-    public static final Parcelable.Creator<ParcelableDestinationInfo> CREATOR =
-            new Parcelable.Creator<ParcelableDestinationInfo>() {
-        @Override
-        public ParcelableDestinationInfo createFromParcel(Parcel source) {
-            ParcelableDestinationInfo info = new ParcelableDestinationInfo();
-            info.id = source.readString();
-            info.name = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
-            info.description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
-            info.iconResourceId = source.readInt();
-            info.extras = source.readBundle();
-            return info;
-        }
-
-        @Override
-        public ParcelableDestinationInfo[] newArray(int size) {
-            return new ParcelableDestinationInfo[size];
-        }
-    };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeString(id);
-        TextUtils.writeToParcel(name, dest, flags);
-        TextUtils.writeToParcel(description, dest, flags);
-        dest.writeInt(iconResourceId);
-        dest.writeBundle(extras);
-    }
-}
diff --git a/media/java/android/media/routing/ParcelableRouteInfo.aidl b/media/java/android/media/routing/ParcelableRouteInfo.aidl
deleted file mode 100644
index 126afaa..0000000
--- a/media/java/android/media/routing/ParcelableRouteInfo.aidl
+++ /dev/null
@@ -1,18 +0,0 @@
-/* Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.media.routing;
-
-parcelable ParcelableRouteInfo;
diff --git a/media/java/android/media/routing/ParcelableRouteInfo.java b/media/java/android/media/routing/ParcelableRouteInfo.java
deleted file mode 100644
index fb1a547..0000000
--- a/media/java/android/media/routing/ParcelableRouteInfo.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.media.routing;
-
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Internal parcelable representation of a media route.
- */
-class ParcelableRouteInfo implements Parcelable {
-    public String id;
-    public int selectorIndex; // index of selector within list used for discovery
-    public int features;
-    public String[] protocols;
-    public Bundle extras;
-
-    public static final Parcelable.Creator<ParcelableRouteInfo> CREATOR =
-            new Parcelable.Creator<ParcelableRouteInfo>() {
-        @Override
-        public ParcelableRouteInfo createFromParcel(Parcel source) {
-            ParcelableRouteInfo info = new ParcelableRouteInfo();
-            info.id = source.readString();
-            info.selectorIndex = source.readInt();
-            info.features = source.readInt();
-            info.protocols = source.createStringArray();
-            info.extras = source.readBundle();
-            return info;
-        }
-
-        @Override
-        public ParcelableRouteInfo[] newArray(int size) {
-            return new ParcelableRouteInfo[size];
-        }
-    };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeString(id);
-        dest.writeInt(selectorIndex);
-        dest.writeInt(features);
-        dest.writeStringArray(protocols);
-        dest.writeBundle(extras);
-    }
-}
diff --git a/media/java/android/media/session/ISession.aidl b/media/java/android/media/session/ISession.aidl
index af3b72e..bd0019f 100644
--- a/media/java/android/media/session/ISession.aidl
+++ b/media/java/android/media/session/ISession.aidl
@@ -19,7 +19,6 @@
 import android.content.pm.ParceledListSlice;
 import android.media.AudioAttributes;
 import android.media.MediaMetadata;
-import android.media.routing.IMediaRouter;
 import android.media.session.ISessionController;
 import android.media.session.PlaybackState;
 import android.media.session.MediaSession;
@@ -35,7 +34,6 @@
     ISessionController getController();
     void setFlags(int flags);
     void setActive(boolean active);
-    void setMediaRouter(in IMediaRouter router);
     void setMediaButtonReceiver(in PendingIntent mbr);
     void setLaunchPendingIntent(in PendingIntent pi);
     void destroy();
diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl
index 5764bd1..6b80477 100644
--- a/media/java/android/media/session/ISessionController.aidl
+++ b/media/java/android/media/session/ISessionController.aidl
@@ -20,8 +20,6 @@
 import android.content.pm.ParceledListSlice;
 import android.media.MediaMetadata;
 import android.media.Rating;
-import android.media.routing.IMediaRouterDelegate;
-import android.media.routing.IMediaRouterStateCallback;
 import android.media.session.ISessionControllerCallback;
 import android.media.session.ParcelableVolumeInfo;
 import android.media.session.PlaybackState;
@@ -51,8 +49,6 @@
     void adjustVolume(int direction, int flags, String packageName);
     void setVolumeTo(int value, int flags, String packageName);
 
-    IMediaRouterDelegate createMediaRouterDelegate(IMediaRouterStateCallback callback);
-
     // These commands are for the TransportControls
     void play();
     void playUri(in Uri uri, in Bundle extras);
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 074e5ad..d7baaa9 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -26,7 +26,6 @@
 import android.media.MediaMetadata;
 import android.media.Rating;
 import android.media.VolumeProvider;
-import android.media.routing.MediaRouter;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
@@ -119,17 +118,6 @@
     }
 
     /**
-     * Creates a media router delegate through which the destination of the media
-     * router may be observed and controlled.
-     *
-     * @return The media router delegate, or null if the media session does
-     * not support media routing.
-     */
-    public @Nullable MediaRouter.Delegate createMediaRouterDelegate() {
-        return new MediaRouter.Delegate();
-    }
-
-    /**
      * Send the specified media button event to the session. Only media keys can
      * be sent by this method, other keys will be ignored.
      *
@@ -259,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) {
@@ -281,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) {
@@ -305,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 {
@@ -326,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.
      */
@@ -577,7 +566,7 @@
          *
          * @param info The current audio info for this session.
          */
-        public void onAudioInfoChanged(AudioInfo info) {
+        public void onAudioInfoChanged(PlaybackInfo info) {
         }
     }
 
@@ -785,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;
@@ -797,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;
@@ -806,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.
@@ -932,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);
             }
@@ -970,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 2cd161c..eac6809 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -28,7 +28,6 @@
 import android.media.MediaMetadata;
 import android.media.Rating;
 import android.media.VolumeProvider;
-import android.media.routing.MediaRouter;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
@@ -102,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;
@@ -216,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) {
@@ -225,23 +214,6 @@
     }
 
     /**
-     * Associates a {@link MediaRouter} with this session to control the destination
-     * of media content.
-     * <p>
-     * A media router may only be associated with at most one session at a time.
-     * </p>
-     *
-     * @param router The media router, or null to remove the current association.
-     */
-    public void setMediaRouter(@Nullable MediaRouter router) {
-        try {
-            mBinder.setMediaRouter(router != null ? router.getBinder() : null);
-        } catch (RemoteException e) {
-            Log.wtf(TAG, "Failure in setMediaButtonReceiver.", e);
-        }
-    }
-
-    /**
      * Set a pending intent for your media button receiver to allow restarting
      * playback after the session has been stopped. If your app is started in
      * this way an {@link Intent#ACTION_MEDIA_BUTTON} intent will be sent via
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/media/java/android/media/tv/TvTrackInfo.java b/media/java/android/media/tv/TvTrackInfo.java
index 6ddb2a2..e0aacd6 100644
--- a/media/java/android/media/tv/TvTrackInfo.java
+++ b/media/java/android/media/tv/TvTrackInfo.java
@@ -46,10 +46,12 @@
     private final int mAudioSampleRate;
     private final int mVideoWidth;
     private final int mVideoHeight;
+    private final float mVideoFrameRate;
     private final Bundle mExtra;
 
     private TvTrackInfo(int type, String id, String language, int audioChannelCount,
-            int audioSampleRate, int videoWidth, int videoHeight, Bundle extra) {
+            int audioSampleRate, int videoWidth, int videoHeight, float videoFrameRate,
+            Bundle extra) {
         mType = type;
         mId = id;
         mLanguage = language;
@@ -57,6 +59,7 @@
         mAudioSampleRate = audioSampleRate;
         mVideoWidth = videoWidth;
         mVideoHeight = videoHeight;
+        mVideoFrameRate = videoFrameRate;
         mExtra = extra;
     }
 
@@ -68,6 +71,7 @@
         mAudioSampleRate = in.readInt();
         mVideoWidth = in.readInt();
         mVideoHeight = in.readInt();
+        mVideoFrameRate = in.readFloat();
         mExtra = in.readBundle();
     }
 
@@ -137,6 +141,17 @@
     }
 
     /**
+     * Returns the frame rate of the video, in the unit of fps (frames per second). Valid only for
+     * {@link #TYPE_VIDEO} tracks.
+     */
+    public final float getVideoFrameRate() {
+        if (mType != TYPE_VIDEO) {
+            throw new IllegalStateException("Not a video track");
+        }
+        return mVideoFrameRate;
+    }
+
+    /**
      * Returns the extra information about the current track.
      */
     public final Bundle getExtra() {
@@ -163,6 +178,7 @@
         dest.writeInt(mAudioSampleRate);
         dest.writeInt(mVideoWidth);
         dest.writeInt(mVideoHeight);
+        dest.writeFloat(mVideoFrameRate);
         dest.writeBundle(mExtra);
     }
 
@@ -190,6 +206,7 @@
         private int mAudioSampleRate;
         private int mVideoWidth;
         private int mVideoHeight;
+        private float mVideoFrameRate;
         private Bundle mExtra;
 
         /**
@@ -279,6 +296,20 @@
         }
 
         /**
+         * Sets the frame rate of the video, in the unit fps (frames per rate). Valid only for
+         * {@link #TYPE_VIDEO} tracks.
+         *
+         * @param videoFrameRate The frame rate of the video.
+         */
+        public final Builder setVideoFrameRate(float videoFrameRate) {
+            if (mType != TYPE_VIDEO) {
+                throw new IllegalStateException("Not a video track");
+            }
+            mVideoFrameRate = videoFrameRate;
+            return this;
+        }
+
+        /**
          * Sets the extra information about the current track.
          *
          * @param extra The extra information.
@@ -295,7 +326,7 @@
          */
         public TvTrackInfo build() {
             return new TvTrackInfo(mType, mId, mLanguage, mAudioChannelCount, mAudioSampleRate,
-                    mVideoWidth, mVideoHeight, mExtra);
+                    mVideoWidth, mVideoHeight, mVideoFrameRate, mExtra);
         }
     }
 }
\ No newline at end of file
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/PrintSpooler/res/values/themes.xml b/packages/PrintSpooler/res/values/themes.xml
index db319e9..08702291 100644
--- a/packages/PrintSpooler/res/values/themes.xml
+++ b/packages/PrintSpooler/res/values/themes.xml
@@ -16,7 +16,10 @@
 
 <resources>
 
-    <style name="PrintActivity" parent="@android:style/Theme.Material.Settings">
+    <style name="PrintActivity" parent="@android:style/Theme.Material">
+        <item name="android:colorPrimary">@*android:color/material_blue_grey_900</item>
+        <item name="android:colorPrimaryDark">@*android:color/material_blue_grey_950</item>
+        <item name="android:colorAccent">@*android:color/material_deep_teal_A500</item>
         <item name="android:windowIsTranslucent">true</item>
         <item name="android:windowBackground">@android:color/transparent</item>
         <item name="android:windowContentOverlay">@null</item>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java b/packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java
index 3134e93..5233c79 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java
@@ -124,7 +124,9 @@
                 .setContentText(printJob.getPrinterName())
                 .setWhen(System.currentTimeMillis())
                 .setOngoing(true)
-                .setShowWhen(true);
+                .setShowWhen(true)
+                .setColor(mContext.getResources().getColor(
+                        com.android.internal.R.color.system_notification_accent_color));
         mNotificationManager.notify(0, builder.build());
     }
 
@@ -140,7 +142,9 @@
                 .setContentText(printJob.getPrinterName())
                 .setWhen(System.currentTimeMillis())
                 .setOngoing(true)
-                .setShowWhen(true);
+                .setShowWhen(true)
+                .setColor(mContext.getResources().getColor(
+                        com.android.internal.R.color.system_notification_accent_color));
         mNotificationManager.notify(0, builder.build());
     }
 
@@ -154,7 +158,9 @@
                 .setContentText(printJob.getPrinterName())
                 .setWhen(System.currentTimeMillis())
                 .setOngoing(true)
-                .setShowWhen(true);
+                .setShowWhen(true)
+                .setColor(mContext.getResources().getColor(
+                        com.android.internal.R.color.system_notification_accent_color));
            mNotificationManager.notify(0, builder.build());
     }
 
@@ -166,7 +172,9 @@
                 .setContentText(printJob.getPrinterName())
                 .setWhen(System.currentTimeMillis())
                 .setOngoing(true)
-                .setShowWhen(true);
+                .setShowWhen(true)
+                .setColor(mContext.getResources().getColor(
+                        com.android.internal.R.color.system_notification_accent_color));
         mNotificationManager.notify(0, builder.build());
     }
 
@@ -198,6 +206,8 @@
 
         builder.setNumber(printJobCount);
         builder.setStyle(inboxStyle);
+        builder.setColor(mContext.getResources().getColor(
+                com.android.internal.R.color.system_notification_accent_color));
 
         mNotificationManager.notify(0, builder.build());
     }
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/packages/Shell/src/com/android/shell/BugreportReceiver.java b/packages/Shell/src/com/android/shell/BugreportReceiver.java
index 7a659ee..02a3aeb 100644
--- a/packages/Shell/src/com/android/shell/BugreportReceiver.java
+++ b/packages/Shell/src/com/android/shell/BugreportReceiver.java
@@ -84,14 +84,17 @@
         }
         notifIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 
-        final Notification.Builder builder = new Notification.Builder(context);
-        builder.setSmallIcon(com.android.internal.R.drawable.stat_sys_adb);
-        builder.setContentTitle(context.getString(R.string.bugreport_finished_title));
-        builder.setTicker(context.getString(R.string.bugreport_finished_title));
-        builder.setContentText(context.getString(R.string.bugreport_finished_text));
-        builder.setContentIntent(PendingIntent.getActivity(
-                context, 0, notifIntent, PendingIntent.FLAG_CANCEL_CURRENT));
-        builder.setAutoCancel(true);
+        final Notification.Builder builder = new Notification.Builder(context)
+                .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
+                .setContentTitle(context.getString(R.string.bugreport_finished_title))
+                .setTicker(context.getString(R.string.bugreport_finished_title))
+                .setContentText(context.getString(R.string.bugreport_finished_text))
+                .setContentIntent(PendingIntent.getActivity(
+                        context, 0, notifIntent, PendingIntent.FLAG_CANCEL_CURRENT))
+                .setAutoCancel(true)
+                .setColor(context.getResources().getColor(
+                        com.android.internal.R.color.system_notification_accent_color));
+
         NotificationManager.from(context).notify(TAG, 0, builder.build());
 
         // Clean up older bugreports in background
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/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/colors.xml b/packages/SystemUI/res/values/colors.xml
index e9c7deb..40870bf 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -23,7 +23,6 @@
     <color name="system_bar_background_opaque">#ff000000</color>
     <color name="system_bar_background_semi_transparent">#66000000</color> <!-- 40% black -->
     <color name="system_bar_background_transparent">#00000000</color>
-    <color name="system_bar_background_warning">#fff4511e</color><!-- deep orange 600 -->
     <color name="notification_panel_solid_background">#ff000000</color>
     <drawable name="status_bar_recents_app_thumbnail_background">#88000000</drawable>
     <color name="status_bar_recents_app_label_color">#ffffffff</color>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index f628039..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 -->
@@ -111,7 +111,7 @@
     <bool name="config_show4GForLTE">true</bool>
 
     <!-- milliseconds before the heads up notification auto-dismisses. -->
-    <integer name="heads_up_notification_decay">3700</integer>
+    <integer name="heads_up_notification_decay">10000</integer>
 
     <!-- milliseconds before the heads up notification accepts touches. -->
     <integer name="heads_up_sensitivity_delay">700</integer>
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..1d33d7a 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -306,15 +306,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 +399,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 +515,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/power/PowerDialogWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerDialogWarnings.java
deleted file mode 100644
index 8420dc0c..0000000
--- a/packages/SystemUI/src/com/android/systemui/power/PowerDialogWarnings.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.power;
-
-import android.app.AlertDialog;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.media.AudioManager;
-import android.media.Ringtone;
-import android.media.RingtoneManager;
-import android.net.Uri;
-import android.os.SystemClock;
-import android.provider.Settings;
-import android.util.Slog;
-import android.view.ContextThemeWrapper;
-import android.view.WindowManager;
-
-import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.PhoneStatusBar;
-
-import java.io.PrintWriter;
-
-public class PowerDialogWarnings implements PowerUI.WarningsUI {
-    private static final String TAG = PowerUI.TAG + ".Dialog";
-    private static final boolean DEBUG = PowerUI.DEBUG;
-
-    private final Context mContext;
-    private final PhoneStatusBar mPhoneStatusBar;
-
-    private int mBatteryLevel;
-    private int mBucket;
-    private long mScreenOffTime;
-    private boolean mSaver;
-
-    private AlertDialog mInvalidChargerDialog;
-    private AlertDialog mLowBatteryDialog;
-
-    public PowerDialogWarnings(Context context, PhoneStatusBar phoneStatusBar) {
-        mContext = new ContextThemeWrapper(context, android.R.style.Theme_DeviceDefault_Light);
-        mPhoneStatusBar = phoneStatusBar;
-    }
-
-    @Override
-    public void dump(PrintWriter pw) {
-        pw.print("mInvalidChargerDialog=");
-        pw.println(mInvalidChargerDialog == null ? "null" : mInvalidChargerDialog.toString());
-        pw.print("mLowBatteryDialog=");
-        pw.println(mLowBatteryDialog == null ? "null" : mLowBatteryDialog.toString());
-    }
-
-    @Override
-    public void update(int batteryLevel, int bucket, long screenOffTime) {
-        mBatteryLevel = batteryLevel;
-        mBucket = bucket;
-        mScreenOffTime = screenOffTime;
-    }
-
-    @Override
-    public boolean isInvalidChargerWarningShowing() {
-        return mInvalidChargerDialog != null;
-    }
-
-    @Override
-    public void updateLowBatteryWarning() {
-        if (mLowBatteryDialog != null) {
-            showLowBatteryWarning(false /*playSound*/);
-        }
-    }
-
-    @Override
-    public void dismissLowBatteryWarning() {
-        if (mLowBatteryDialog != null) {
-            Slog.i(TAG, "closing low battery warning: level=" + mBatteryLevel);
-            mLowBatteryDialog.dismiss();
-        }
-    }
-
-    @Override
-    public void showLowBatteryWarning(boolean playSound) {
-        Slog.i(TAG,
-                ((mLowBatteryDialog == null) ? "showing" : "updating")
-                + " low battery warning: level=" + mBatteryLevel
-                + " [" + mBucket + "]");
-
-        final int textRes = mSaver ? R.string.battery_low_percent_format_saver_started
-                : R.string.battery_low_percent_format;
-        final CharSequence levelText = mContext.getString(textRes, mBatteryLevel);
-
-        if (mLowBatteryDialog != null) {
-            mLowBatteryDialog.setMessage(levelText);
-        } else {
-            AlertDialog.Builder b = new AlertDialog.Builder(mContext);
-            b.setCancelable(true);
-            b.setTitle(R.string.battery_low_title);
-            b.setMessage(levelText);
-            b.setPositiveButton(android.R.string.ok, null);
-
-            final Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                    | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
-                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
-                    | Intent.FLAG_ACTIVITY_NO_HISTORY);
-            if (intent.resolveActivity(mContext.getPackageManager()) != null) {
-                b.setNegativeButton(R.string.battery_low_why,
-                        new DialogInterface.OnClickListener() {
-                    @Override
-                    public void onClick(DialogInterface dialog, int which) {
-                        mPhoneStatusBar.startActivity(intent, true /* dismissShade */);
-                        dismissLowBatteryWarning();
-                    }
-                });
-            }
-
-            AlertDialog d = b.create();
-            d.setOnDismissListener(new DialogInterface.OnDismissListener() {
-                    @Override
-                    public void onDismiss(DialogInterface dialog) {
-                        mLowBatteryDialog = null;
-                    }
-                });
-            d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
-            d.getWindow().getAttributes().privateFlags |=
-                    WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
-            d.show();
-            mLowBatteryDialog = d;
-            if (playSound) {
-                playLowBatterySound();
-            }
-        }
-    }
-
-    private void playLowBatterySound() {
-        final ContentResolver cr = mContext.getContentResolver();
-
-        final int silenceAfter = Settings.Global.getInt(cr,
-                Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0);
-        final long offTime = SystemClock.elapsedRealtime() - mScreenOffTime;
-        if (silenceAfter > 0
-                && mScreenOffTime > 0
-                && offTime > silenceAfter) {
-            Slog.i(TAG, "screen off too long (" + offTime + "ms, limit " + silenceAfter
-                    + "ms): not waking up the user with low battery sound");
-            return;
-        }
-
-        if (DEBUG) {
-            Slog.d(TAG, "playing low battery sound. pick-a-doop!"); // WOMP-WOMP is deprecated
-        }
-
-        if (Settings.Global.getInt(cr, Settings.Global.POWER_SOUNDS_ENABLED, 1) == 1) {
-            final String soundPath = Settings.Global.getString(cr,
-                    Settings.Global.LOW_BATTERY_SOUND);
-            if (soundPath != null) {
-                final Uri soundUri = Uri.parse("file://" + soundPath);
-                if (soundUri != null) {
-                    final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
-                    if (sfx != null) {
-                        sfx.setStreamType(AudioManager.STREAM_SYSTEM);
-                        sfx.play();
-                    }
-                }
-            }
-        }
-    }
-
-    @Override
-    public void dismissInvalidChargerWarning() {
-        if (mInvalidChargerDialog != null) {
-            mInvalidChargerDialog.dismiss();
-        }
-    }
-
-    @Override
-    public void showInvalidChargerWarning() {
-        Slog.d(TAG, "showing invalid charger dialog");
-
-        dismissLowBatteryWarning();
-
-        AlertDialog.Builder b = new AlertDialog.Builder(mContext);
-        b.setCancelable(true);
-        b.setTitle(R.string.invalid_charger_title);
-        b.setMessage(R.string.invalid_charger_text);
-        b.setPositiveButton(android.R.string.ok, null);
-
-        AlertDialog d = b.create();
-            d.setOnDismissListener(new DialogInterface.OnDismissListener() {
-                    public void onDismiss(DialogInterface dialog) {
-                        mInvalidChargerDialog = null;
-                    }
-                });
-
-        d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
-        d.getWindow().getAttributes().privateFlags |=
-                WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
-        d.show();
-        mInvalidChargerDialog = d;
-    }
-
-    @Override
-    public void showSaverMode(boolean mode) {
-        mSaver = mode;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index d455cec..bd1ef7a 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -49,7 +49,6 @@
 
     private static final String TAG_NOTIFICATION = "low_battery";
     private static final int ID_NOTIFICATION = 100;
-    private static final int AUTO_DISMISS_MS = 10000;
 
     private static final int SHOWING_NOTHING = 0;
     private static final int SHOWING_WARNING = 1;
@@ -62,8 +61,6 @@
         "SHOWING_INVALID_CHARGER",
     };
 
-    private static final String ACTION_SHOW_FALLBACK_WARNING = "PNW.warningFallback";
-    private static final String ACTION_SHOW_FALLBACK_CHARGER = "PNW.chargerFallback";
     private static final String ACTION_SHOW_BATTERY_SETTINGS = "PNW.batterySettings";
     private static final String ACTION_START_SAVER = "PNW.startSaver";
     private static final String ACTION_STOP_SAVER = "PNW.stopSaver";
@@ -76,7 +73,6 @@
     private final Context mContext;
     private final NotificationManager mNoMan;
     private final Handler mHandler = new Handler();
-    private final PowerDialogWarnings mFallbackDialogs;
     private final Receiver mReceiver = new Receiver();
     private final Intent mOpenBatterySettings = settings(Intent.ACTION_POWER_USAGE_SUMMARY);
     private final Intent mOpenSaverSettings = settings(Settings.ACTION_BATTERY_SAVER_SETTINGS);
@@ -97,7 +93,6 @@
     public PowerNotificationWarnings(Context context, PhoneStatusBar phoneStatusBar) {
         mContext = context;
         mNoMan = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
-        mFallbackDialogs = new PowerDialogWarnings(context, phoneStatusBar);
         mReceiver.init();
     }
 
@@ -121,7 +116,6 @@
         }
         mBucket = bucket;
         mScreenOffTime = screenOffTime;
-        mFallbackDialogs.update(batteryLevel, bucket, screenOffTime);
     }
 
     @Override
@@ -134,8 +128,8 @@
     }
 
     private void updateNotification() {
-        if (DEBUG) Slog.d(TAG, "updateNotification mWarning=" + mWarning
-                + " mSaver=" + mSaver + " mInvalidCharger=" + mInvalidCharger);
+        if (DEBUG) Slog.d(TAG, "updateNotification mWarning=" + mWarning + " mPlaySound="
+                + mPlaySound + " mSaver=" + mSaver + " mInvalidCharger=" + mInvalidCharger);
         if (mInvalidCharger) {
             showInvalidChargerNotification();
             mShowing = SHOWING_INVALID_CHARGER;
@@ -162,7 +156,8 @@
                 .setPriority(Notification.PRIORITY_MAX)
                 .setCategory(Notification.CATEGORY_SYSTEM)
                 .setVisibility(Notification.VISIBILITY_PUBLIC)
-                .setFullScreenIntent(pendingBroadcast(ACTION_SHOW_FALLBACK_CHARGER), true);
+                .setColor(mContext.getResources().getColor(
+                        com.android.internal.R.color.system_notification_accent_color));
         final Notification n = nb.build();
         if (n.headsUpContentView != null) {
             n.headsUpContentView.setViewVisibility(com.android.internal.R.id.right_icon, View.GONE);
@@ -180,12 +175,12 @@
                 .setShowWhen(false)
                 .setContentTitle(mContext.getString(R.string.battery_low_title))
                 .setContentText(mContext.getString(textRes, mBatteryLevel))
-                .setOngoing(true)
                 .setOnlyAlertOnce(true)
                 .setPriority(Notification.PRIORITY_MAX)
                 .setCategory(Notification.CATEGORY_SYSTEM)
                 .setVisibility(Notification.VISIBILITY_PUBLIC)
-                .setFullScreenIntent(pendingBroadcast(ACTION_SHOW_FALLBACK_WARNING), true);
+                .setColor(mContext.getResources().getColor(
+                        com.android.internal.R.color.battery_saver_mode_color));
         if (hasBatterySettings()) {
             nb.setContentIntent(pendingBroadcast(ACTION_SHOW_BATTERY_SETTINGS));
         }
@@ -214,7 +209,9 @@
                 .setOngoing(true)
                 .setShowWhen(false)
                 .setCategory(Notification.CATEGORY_SYSTEM)
-                .setVisibility(Notification.VISIBILITY_PUBLIC);
+                .setVisibility(Notification.VISIBILITY_PUBLIC)
+                .setColor(mContext.getResources().getColor(
+                        com.android.internal.R.color.battery_saver_mode_color));
         addStopSaverAction(nb);
         if (hasSaverSettings()) {
             nb.setContentIntent(pendingActivity(mOpenSaverSettings));
@@ -260,14 +257,12 @@
     @Override
     public void updateLowBatteryWarning() {
         updateNotification();
-        mFallbackDialogs.updateLowBatteryWarning();
     }
 
     @Override
     public void dismissLowBatteryWarning() {
         if (DEBUG) Slog.d(TAG, "dismissing low battery warning: level=" + mBatteryLevel);
         dismissLowBatteryNotification();
-        mFallbackDialogs.dismissLowBatteryWarning();
     }
 
     private void dismissLowBatteryNotification() {
@@ -292,8 +287,6 @@
         mPlaySound = playSound;
         mWarning = true;
         updateNotification();
-        mHandler.removeCallbacks(mDismissLowBatteryNotification);
-        mHandler.postDelayed(mDismissLowBatteryNotification, AUTO_DISMISS_MS);
     }
 
     private void attachLowBatterySound(Notification.Builder b) {
@@ -330,7 +323,6 @@
     @Override
     public void dismissInvalidChargerWarning() {
         dismissInvalidChargerNotification();
-        mFallbackDialogs.dismissInvalidChargerWarning();
     }
 
     private void dismissInvalidChargerNotification() {
@@ -372,8 +364,6 @@
 
         public void init() {
             IntentFilter filter = new IntentFilter();
-            filter.addAction(ACTION_SHOW_FALLBACK_WARNING);
-            filter.addAction(ACTION_SHOW_FALLBACK_CHARGER);
             filter.addAction(ACTION_SHOW_BATTERY_SETTINGS);
             filter.addAction(ACTION_START_SAVER);
             filter.addAction(ACTION_STOP_SAVER);
@@ -384,13 +374,7 @@
         public void onReceive(Context context, Intent intent) {
             final String action = intent.getAction();
             Slog.i(TAG, "Received " + action);
-            if (action.equals(ACTION_SHOW_FALLBACK_WARNING)) {
-                dismissLowBatteryNotification();
-                mFallbackDialogs.showLowBatteryWarning(false /*playSound*/);
-            } else if (action.equals(ACTION_SHOW_FALLBACK_CHARGER)) {
-                dismissInvalidChargerNotification();
-                mFallbackDialogs.showInvalidChargerWarning();
-            } else if (action.equals(ACTION_SHOW_BATTERY_SETTINGS)) {
+            if (action.equals(ACTION_SHOW_BATTERY_SETTINGS)) {
                 dismissLowBatteryNotification();
                 mContext.startActivityAsUser(mOpenBatterySettings, UserHandle.CURRENT);
             } else if (action.equals(ACTION_START_SAVER)) {
@@ -415,11 +399,4 @@
             });
         }
     };
-
-    private final Runnable mDismissLowBatteryNotification = new Runnable() {
-        @Override
-        public void run() {
-            dismissLowBatteryNotification();
-        }
-    };
 }
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/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
index f04a7b6..bfbc56c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
@@ -51,6 +51,10 @@
     private QSTileHost mHost;
     private Handler mHandler;
 
+    private boolean mIsVisible;
+    private boolean mIsIconVisible;
+    private int mFooterTextId;
+
     public QSFooter(QSPanel qsPanel, Context context) {
         mRootView = LayoutInflater.from(context)
                 .inflate(R.layout.quick_settings_footer, qsPanel, false);
@@ -99,16 +103,17 @@
 
     private void handleRefreshState() {
         if (mSecurityController.hasDeviceOwner()) {
-            mFooterText.setText(R.string.device_owned_footer);
-            mRootView.setVisibility(View.VISIBLE);
-            mFooterIcon.setVisibility(View.INVISIBLE);
+            mFooterTextId = R.string.device_owned_footer;
+            mIsVisible = true;
+            mIsIconVisible = false;
         } else if (mSecurityController.isVpnEnabled()) {
-            mFooterText.setText(R.string.vpn_footer);
-            mRootView.setVisibility(View.VISIBLE);
-            mFooterIcon.setVisibility(View.VISIBLE);
+            mFooterTextId = R.string.vpn_footer;
+            mIsVisible = true;
+            mIsIconVisible = true;
         } else {
-            mRootView.setVisibility(View.GONE);
+            mIsVisible = false;
         }
+        mRootView.post(mUpdateDisplayState);
     }
 
     @Override
@@ -181,6 +186,17 @@
         return R.string.monitoring_title;
     }
 
+    private final Runnable mUpdateDisplayState = new Runnable() {
+        @Override
+        public void run() {
+            if (mFooterTextId != 0) {
+                mFooterText.setText(mFooterTextId);
+            }
+            mRootView.setVisibility(mIsVisible ? View.VISIBLE : View.GONE);
+            mFooterIcon.setVisibility(mIsIconVisible ? View.VISIBLE : View.INVISIBLE);
+        }
+    };
+
     private class Callback implements VpnCallback {
         @Override
         public void onVpnStateChanged() {
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 531ac31..6cd0f39 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -37,8 +37,8 @@
 
 /** Quick settings tile: Cast **/
 public class CastTile extends QSTile<QSTile.BooleanState> {
-    private static final Intent WIFI_DISPLAY_SETTINGS =
-            new Intent(Settings.ACTION_WIFI_DISPLAY_SETTINGS);
+    private static final Intent CAST_SETTINGS =
+            new Intent(Settings.ACTION_CAST_SETTINGS);
 
     private final CastController mController;
     private final CastDetailAdapter mDetailAdapter;
@@ -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);
@@ -144,7 +153,7 @@
 
         @Override
         public Intent getSettingsIntent() {
-            return WIFI_DISPLAY_SETTINGS;
+            return CAST_SETTINGS;
         }
 
         @Override
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/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index d4c8ce3..d9fea47 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -164,7 +164,8 @@
             .setContentTitle(r.getString(R.string.screenshot_saving_title))
             .setContentText(r.getString(R.string.screenshot_saving_text))
             .setSmallIcon(R.drawable.stat_notify_image)
-            .setWhen(now);
+            .setWhen(now)
+            .setColor(r.getColor(com.android.internal.R.color.system_notification_accent_color));
 
         mNotificationStyle = new Notification.BigPictureStyle()
             .bigPicture(preview);
@@ -177,7 +178,9 @@
                 .setContentText(r.getString(R.string.screenshot_saving_text))
                 .setSmallIcon(R.drawable.stat_notify_image)
                 .setCategory(Notification.CATEGORY_PROGRESS)
-                .setWhen(now);
+                .setWhen(now)
+                .setColor(r.getColor(
+                        com.android.internal.R.color.system_notification_accent_color));
 
         mNotificationBuilder.setPublicVersion(mPublicNotificationBuilder.build());
 
@@ -304,7 +307,9 @@
                 .setContentText(r.getString(R.string.screenshot_saved_text))
                 .setContentIntent(PendingIntent.getActivity(params.context, 0, launchIntent, 0))
                 .setWhen(now)
-                .setAutoCancel(true);
+                .setAutoCancel(true)
+                .setColor(r.getColor(
+                        com.android.internal.R.color.system_notification_accent_color));;
 
             // Update the text in the public version as well
             mPublicNotificationBuilder
@@ -312,7 +317,9 @@
                 .setContentText(r.getString(R.string.screenshot_saved_text))
                 .setContentIntent(PendingIntent.getActivity(params.context, 0, launchIntent, 0))
                 .setWhen(now)
-                .setAutoCancel(true);
+                .setAutoCancel(true)
+                .setColor(r.getColor(
+                        com.android.internal.R.color.system_notification_accent_color));
 
             mNotificationBuilder.setPublicVersion(mPublicNotificationBuilder.build());
 
@@ -717,7 +724,9 @@
             .setWhen(System.currentTimeMillis())
             .setVisibility(Notification.VISIBILITY_PUBLIC) // ok to show outside lockscreen
             .setCategory(Notification.CATEGORY_ERROR)
-            .setAutoCancel(true);
+            .setAutoCancel(true)
+            .setColor(context.getResources().getColor(
+                        com.android.internal.R.color.system_notification_accent_color));
         Notification n =
             new Notification.BigTextStyle(b)
                 .bigText(r.getString(R.string.screenshot_failed_text))
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index f3aba0e..a030f61 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -66,6 +66,12 @@
     }
 
     public void reset() {
+        if (mContractedChild != null) {
+            mContractedChild.animate().cancel();
+        }
+        if (mExpandedChild != null) {
+            mExpandedChild.animate().cancel();
+        }
         removeAllViews();
         mContractedChild = null;
         mExpandedChild = null;
@@ -76,6 +82,7 @@
 
     public void setContractedChild(View child) {
         if (mContractedChild != null) {
+            mContractedChild.animate().cancel();
             removeView(mContractedChild);
         }
         sanitizeContractedLayoutParams(child);
@@ -86,6 +93,7 @@
 
     public void setExpandedChild(View child) {
         if (mExpandedChild != null) {
+            mExpandedChild.animate().cancel();
             removeView(mExpandedChild);
         }
         addView(child);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index 152bfdc..32fb567 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -139,7 +139,7 @@
                 mOpaque = res.getColor(R.color.system_bar_background_opaque);
                 mSemiTransparent = res.getColor(R.color.system_bar_background_semi_transparent);
                 mTransparent = res.getColor(R.color.system_bar_background_transparent);
-                mWarning = res.getColor(R.color.system_bar_background_warning);
+                mWarning = res.getColor(com.android.internal.R.color.battery_saver_mode_color);
             }
             mGradient = res.getDrawable(gradientResourceId);
             mInterpolator = new LinearInterpolator();
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..61246b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -80,23 +80,25 @@
     private FlashlightController mFlashlightController;
     private PreviewInflater mPreviewInflater;
     private KeyguardIndicationController mIndicationController;
-    private boolean mFaceUnlockRunning;
+
+    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);
     }
 
     @Override
@@ -120,6 +122,7 @@
         mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext));
         inflatePreviews();
         mLockIcon.setOnClickListener(this);
+        mLockIcon.setBackground(mTrustDrawable);
     }
 
     @Override
@@ -267,27 +270,45 @@
     @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);
+        mTrustDrawable.setTrustManaged(trustManaged);
         mLockIcon.setClickable(trustManaged);
     }
 
+
+
     public KeyguardAffordanceView getPhoneView() {
         return mPhoneImageView;
     }
@@ -355,8 +376,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/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index d398bc1..9188457 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -375,6 +375,7 @@
 
     public void setQsExpansionEnabled(boolean qsExpansionEnabled) {
         mQsExpansionEnabled = qsExpansionEnabled;
+        mHeader.setClickable(qsExpansionEnabled);
     }
 
     @Override
@@ -571,7 +572,8 @@
             return true;
         }
         if (event.getActionMasked() == MotionEvent.ACTION_DOWN && getExpandedFraction() == 1f
-                && mStatusBar.getBarState() != StatusBarState.KEYGUARD && !mQsExpanded) {
+                && mStatusBar.getBarState() != StatusBarState.KEYGUARD && !mQsExpanded
+                && mQsExpansionEnabled) {
 
             // Down in the empty area while fully expanded - go to QS.
             mQsTracking = true;
@@ -594,7 +596,8 @@
                 || event.getActionMasked() == MotionEvent.ACTION_UP) {
             mConflictingQsExpansionGesture = false;
         }
-        if (event.getActionMasked() == MotionEvent.ACTION_DOWN && mExpandedHeight == 0) {
+        if (event.getActionMasked() == MotionEvent.ACTION_DOWN && mExpandedHeight == 0
+                && mQsExpansionEnabled) {
             mTwoFingerQsExpandPossible = true;
         }
         if (mTwoFingerQsExpandPossible && event.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN
@@ -724,6 +727,9 @@
     @Override
     public void onOverscrollTopChanged(float amount, boolean isRubberbanded) {
         cancelAnimation();
+        if (!mQsExpansionEnabled) {
+            amount = 0f;
+        }
         float rounded = amount >= 1f ? amount : 0f;
         mStackScrollerOverscrolling = rounded != 0f && isRubberbanded;
         mQsExpansionFromOverscroll = rounded != 0f;
@@ -734,8 +740,10 @@
 
     @Override
     public void flingTopOverscroll(float velocity, boolean open) {
+        mLastOverscroll = 0f;
         setQsExpansion(mQsExpansionHeight);
-        flingSettings(velocity, open, new Runnable() {
+        flingSettings(!mQsExpansionEnabled && open ? 0f : velocity, open && mQsExpansionEnabled,
+                new Runnable() {
             @Override
             public void run() {
                 mStackScrollerOverscrolling = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index decaeb6..b175fd5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -58,7 +58,7 @@
     private boolean mHasLayoutedSinceDown;
     private float mUpdateFlingVelocity;
     private boolean mUpdateFlingOnLayout;
-    private boolean mTouching;
+    private boolean mPeekTouching;
     private boolean mJustPeeked;
     private boolean mClosing;
     protected boolean mTracking;
@@ -233,7 +233,7 @@
                 mPanelClosedOnDown = mExpandedHeight == 0.0f;
                 mHasLayoutedSinceDown = false;
                 mUpdateFlingOnLayout = false;
-                mTouching = true;
+                mPeekTouching = mPanelClosedOnDown;
                 if (mVelocityTracker == null) {
                     initVelocityTracker();
                 }
@@ -337,7 +337,7 @@
                     mVelocityTracker.recycle();
                     mVelocityTracker = null;
                 }
-                mTouching = false;
+                mPeekTouching = false;
                 break;
         }
         return !waitForTouchSlop || mTracking;
@@ -399,7 +399,6 @@
                 mPanelClosedOnDown = mExpandedHeight == 0.0f;
                 mHasLayoutedSinceDown = false;
                 mUpdateFlingOnLayout = false;
-                mTouching = true;
                 initVelocityTracker();
                 trackMovement(event);
                 break;
@@ -434,7 +433,6 @@
                 break;
             case MotionEvent.ACTION_CANCEL:
             case MotionEvent.ACTION_UP:
-                mTouching = false;
                 break;
         }
         return false;
@@ -571,7 +569,7 @@
                 && currentMaxPanelHeight != mExpandedHeight
                 && !mPeekPending
                 && mPeekAnimator == null
-                && !mTouching) {
+                && !mPeekTouching) {
             setExpandedHeight(currentMaxPanelHeight);
         }
     }
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 23b55ee..eae64ca 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;
@@ -361,9 +362,6 @@
 
             if (userSetup != mUserSetup) {
                 mUserSetup = userSetup;
-                if (mNotificationPanel != null) {
-                    mNotificationPanel.setQsExpansionEnabled(isDeviceProvisioned() && userSetup);
-                }
                 if (!mUserSetup && mStatusBarView != null)
                     animateCollapseQuickSettings();
             }
@@ -848,6 +846,8 @@
         mUserInfoController.reloadUserInfo();
 
         mHeader.setBatteryController(mBatteryController);
+        ((BatteryMeterView) mStatusBarView.findViewById(R.id.battery)).setBatteryController(
+                mBatteryController);
         mKeyguardStatusBar.setBatteryController(mBatteryController);
         mHeader.setNextAlarmController(mNextAlarmController);
 
@@ -1349,7 +1349,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) {
@@ -1458,7 +1458,7 @@
         updateClearAll();
         updateEmptyShadeView();
 
-        mNotificationPanel.setQsExpansionEnabled(isDeviceProvisioned() && mUserSetup);
+        mNotificationPanel.setQsExpansionEnabled(isDeviceProvisioned());
         mShadeUpdates.check();
     }
 
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/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index e9581fc..10f457a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -22,6 +22,7 @@
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
 import android.hardware.input.InputManager;
+import android.os.Bundle;
 import android.os.SystemClock;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -33,10 +34,14 @@
 import android.view.SoundEffectConstants;
 import android.view.ViewConfiguration;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.ImageView;
 
 import com.android.systemui.R;
 
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK;
+
 public class KeyButtonView extends ImageView {
     private static final String TAG = "StatusBar.KeyButtonView";
     private static final boolean DEBUG = false;
@@ -95,6 +100,35 @@
         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
     }
 
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        if (mCode != 0) {
+            info.addAction(new AccessibilityNodeInfo.AccessibilityAction(ACTION_CLICK, null));
+            if (mSupportsLongpress) {
+                info.addAction(
+                        new AccessibilityNodeInfo.AccessibilityAction(ACTION_LONG_CLICK, null));
+            }
+        }
+    }
+
+    @Override
+    public boolean performAccessibilityAction(int action, Bundle arguments) {
+        if (action == ACTION_CLICK && mCode != 0) {
+            sendEvent(KeyEvent.ACTION_DOWN, 0, SystemClock.uptimeMillis());
+            sendEvent(KeyEvent.ACTION_UP, 0);
+            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
+            playSoundEffect(SoundEffectConstants.CLICK);
+            return true;
+        } else if (action == ACTION_LONG_CLICK && mCode != 0 && mSupportsLongpress) {
+            sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.FLAG_LONG_PRESS);
+            sendEvent(KeyEvent.ACTION_UP, 0);
+            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
+            return true;
+        }
+        return super.performAccessibilityAction(action, arguments);
+    }
+
     public void setQuiescentAlpha(float alpha, boolean animate) {
         mAnimateToQuiescent.cancel();
         alpha = Math.min(Math.max(alpha, 0), 1);
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index 481266b..dce5c37 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -309,7 +309,8 @@
                 pi = PendingIntent.getBroadcastAsUser(mContext, 0, intent, 0,
                         UserHandle.CURRENT);
             }
-
+            mUsbStorageNotification.color = mContext.getResources().getColor(
+                    com.android.internal.R.color.system_notification_accent_color);
             mUsbStorageNotification.setLatestEventInfo(mContext, title, message, pi);
             mUsbStorageNotification.visibility = Notification.VISIBILITY_PUBLIC;
             mUsbStorageNotification.category = Notification.CATEGORY_SYSTEM;
@@ -403,6 +404,8 @@
             }
 
             mMediaStorageNotification.icon = icon;
+            mMediaStorageNotification.color = mContext.getResources().getColor(
+                    com.android.internal.R.color.system_notification_accent_color);
             mMediaStorageNotification.setLatestEventInfo(mContext, title, message, pi);
             mMediaStorageNotification.visibility = Notification.VISIBILITY_PUBLIC;
             mMediaStorageNotification.category = Notification.CATEGORY_SYSTEM;
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/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index da8ec2a..ae94654 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -272,15 +272,19 @@
                 mItems.add(new PowerAction());
             } else if (GLOBAL_ACTION_KEY_AIRPLANE.equals(actionKey)) {
                 mItems.add(mAirplaneModeOn);
-            } else if (GLOBAL_ACTION_KEY_BUGREPORT.equals(actionKey)
-                    && (Settings.Global.getInt(mContext.getContentResolver(),
-                        Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0 && isCurrentUserOwner())) {
-                mItems.add(getBugReportAction());
-            } else if (GLOBAL_ACTION_KEY_SILENT.equals(actionKey) && mShowSilentToggle) {
-                mItems.add(mSilentModeAction);
-            } else if (GLOBAL_ACTION_KEY_USERS.equals(actionKey)
-                    && SystemProperties.getBoolean("fw.power_user_switcher", false)) {
-                addUsersToMenu(mItems);
+            } else if (GLOBAL_ACTION_KEY_BUGREPORT.equals(actionKey)) {
+                if (Settings.Global.getInt(mContext.getContentResolver(),
+                        Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0 && isCurrentUserOwner()) {
+                    mItems.add(getBugReportAction());
+                }
+            } else if (GLOBAL_ACTION_KEY_SILENT.equals(actionKey)) {
+                if (mShowSilentToggle) {
+                    mItems.add(mSilentModeAction);
+                }
+            } else if (GLOBAL_ACTION_KEY_USERS.equals(actionKey)) {
+                if (SystemProperties.getBoolean("fw.power_user_switcher", false)) {
+                    addUsersToMenu(mItems);
+                }
             } else if (GLOBAL_ACTION_KEY_SETTINGS.equals(actionKey)) {
                 mItems.add(getSettingsAction());
             } else if (GLOBAL_ACTION_KEY_LOCKDOWN.equals(actionKey)) {
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/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 5bef4bf..67c01e5 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -3602,6 +3602,8 @@
             notification.icon = icon;
             notification.flags = Notification.FLAG_AUTO_CANCEL;
             notification.tickerText = title;
+            notification.color = mContext.getResources().getColor(
+                    com.android.internal.R.color.system_notification_accent_color);
             notification.setLatestEventInfo(mContext, title, details, notification.contentIntent);
             notification.contentIntent = intent;
 
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 2e7b745..122786f 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -1588,6 +1588,8 @@
                     final CharSequence summary = InputMethodUtils.getImeAndSubtypeDisplayName(
                             mContext, imi, mCurrentSubtype);
 
+                    mImeSwitcherNotification.color = mContext.getResources().getColor(
+                            com.android.internal.R.color.system_notification_accent_color);
                     mImeSwitcherNotification.setLatestEventInfo(
                             mContext, title, summary, mImeSwitchPendingIntent);
                     if ((mNotificationManager != null)
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 6ab52c6..d1b4569 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -599,6 +599,8 @@
                 n.defaults = Notification.DEFAULT_LIGHTS;
                 n.flags = Notification.FLAG_ONGOING_EVENT;
                 n.when = 0;
+                n.color = context.getResources().getColor(
+                        com.android.internal.R.color.system_notification_accent_color);
                 n.setLatestEventInfo(
                         context,
                         context.getString(R.string.car_mode_disable_notification_title),
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 2a66baf..94d979e 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -1700,6 +1700,8 @@
             subtitle = titleAndSubtitle.substring(index + 1);
         }
         UserHandle user = new UserHandle(userId);
+        n.color = mContext.getResources().getColor(
+                com.android.internal.R.color.system_notification_accent_color);
         n.setLatestEventInfo(mContext, title, subtitle,
                 PendingIntent.getActivityAsUser(mContext, 0, intent,
                         PendingIntent.FLAG_CANCEL_CURRENT, null, user));
@@ -2968,6 +2970,8 @@
                 UserHandle user = new UserHandle(userId);
                 final String notificationTitleFormat =
                         mContext.getText(R.string.notification_title).toString();
+                n.color = mContext.getResources().getColor(
+                        com.android.internal.R.color.system_notification_accent_color);
                 n.setLatestEventInfo(mContext,
                         String.format(notificationTitleFormat, account.name),
                         message, PendingIntent.getActivityAsUser(
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 9162b3d..b1d84f58 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1472,6 +1472,8 @@
                     notification.defaults = 0; // please be quiet
                     notification.sound = null;
                     notification.vibrate = null;
+                    notification.color = mContext.getResources().getColor(
+                            com.android.internal.R.color.system_notification_accent_color);
                     notification.setLatestEventInfo(context, text,
                             mContext.getText(R.string.heavy_weight_notification_detail),
                             PendingIntent.getActivityAsUser(mContext, 0, root.intent,
@@ -3461,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/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index e528d57..abacb2d 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -575,6 +575,10 @@
 
     void makeFinishing() {
         if (!finishing) {
+            if (this == task.stack.getVisibleBehindActivity()) {
+                // A finishing activity should not remain as visible in the background
+                mStackSupervisor.requestVisibleBehindLocked(this, false);
+            }
             finishing = true;
             if (stopped) {
                 clearOptionsLocked();
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 1107139..931f448 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2659,13 +2659,20 @@
         }
 
         // A non-top activity is reporting a visibility change.
-        if (top.fullscreen || top.state != ActivityState.RESUMED || top.app == null ||
-                top.app.thread == null) {
+        if ((visible && (top.fullscreen || top.state != ActivityState.RESUMED)) ||
+                top.app == null || top.app.thread == null) {
             // Can't carry out this request.
             if (DEBUG_VISIBLE_BEHIND) Slog.d(TAG, "requestVisibleBehind: returning top.fullscreen="
-                    + top.fullscreen+ " top.state=" + top.state + " top.app=" + top.app +
+                    + top.fullscreen + " top.state=" + top.state + " top.app=" + top.app +
                     " top.app.thread=" + top.app.thread);
             return false;
+        } else if (!visible && stack.getVisibleBehindActivity() != r) {
+            // Only the activity set as currently visible behind should actively reset its
+            // visible behind state.
+            if (DEBUG_VISIBLE_BEHIND) Slog.d(TAG, "requestVisibleBehind: returning visible="
+                    + visible + " stack.getVisibleBehindActivity()=" +
+                    stack.getVisibleBehindActivity() + " r=" + r);
+            return false;
         }
 
         stack.setVisibleBehindActivity(visible ? r : null);
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index f79c026..0a66a5c 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -450,6 +450,9 @@
                                         appInfo.packageName, null));
                                 PendingIntent pi = PendingIntent.getActivity(ams.mContext, 0,
                                         runningIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+                                localForegroundNoti.color = ams.mContext.getResources().getColor(
+                                        com.android.internal
+                                                .R.color.system_notification_accent_color);
                                 localForegroundNoti.setLatestEventInfo(ctx,
                                         ams.mContext.getString(
                                                 com.android.internal.R.string
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index fa8626f..1fd114c 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -471,6 +471,8 @@
         mTetheredNotification.flags = Notification.FLAG_ONGOING_EVENT;
         mTetheredNotification.tickerText = title;
         mTetheredNotification.visibility = Notification.VISIBILITY_PUBLIC;
+        mTetheredNotification.color = mContext.getResources().getColor(
+                com.android.internal.R.color.system_notification_accent_color);
         mTetheredNotification.setLatestEventInfo(mContext, title, message, pi);
         mTetheredNotification.category = Notification.CATEGORY_STATUS;
 
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index eddf414..0f6b3ad 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -735,6 +735,8 @@
                         .setContentIntent(mStatusIntent)
                         .setDefaults(0)
                         .setOngoing(true)
+                        .setColor(mContext.getResources().getColor(
+                                com.android.internal.R.color.system_notification_accent_color))
                         .build();
                 nm.notifyAsUser(null, R.drawable.vpn_connected, notification, new UserHandle(user));
             }
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 08d6fc9..949019e 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -3064,6 +3064,8 @@
                 new Notification(R.drawable.stat_notify_sync_error,
                         mContext.getString(R.string.contentServiceSync),
                         System.currentTimeMillis());
+            notification.color = mContext.getResources().getColor(
+                    com.android.internal.R.color.system_notification_accent_color);
             notification.setLatestEventInfo(mContext,
                     mContext.getString(R.string.contentServiceSyncNotificationTitle),
                     String.format(tooManyDeletesDescFormat.toString(), authorityName),
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/display/WifiDisplayAdapter.java b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
index a05bf2c..9d008b9 100644
--- a/services/core/java/com/android/server/display/WifiDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
@@ -502,6 +502,8 @@
                         .addAction(android.R.drawable.ic_menu_close_clear_cancel,
                                 r.getString(R.string.wifi_display_notification_disconnect),
                                 mDisconnectPendingIntent)
+                        .setColor(r.getColor(
+                                com.android.internal.R.color.system_notification_accent_color))
                         .build();
             } else {
                 notification = new Notification.Builder(context)
@@ -516,6 +518,8 @@
                         .addAction(android.R.drawable.ic_menu_close_clear_cancel,
                                 r.getString(R.string.wifi_display_notification_disconnect),
                                 mDisconnectPendingIntent)
+                        .setColor(r.getColor(
+                                com.android.internal.R.color.system_notification_accent_color))
                         .build();
             }
             mNotificationManager.notifyAsUser(null,
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 126a56d..73f5cfd 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -178,7 +178,6 @@
             invokeCallback(callback, HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
             return;
         }
-        // TODO: Handle MHL device
         int targetAddress = targetDevice.getLogicalAddress();
         ActiveSource active = getActiveSource();
         if (active.isValid() && targetAddress == active.logicalAddress) {
@@ -419,17 +418,25 @@
     @ServiceThreadOnly
     protected boolean handleGetMenuLanguage(HdmiCecMessage message) {
         assertRunOnServiceThread();
-        HdmiCecMessage command = HdmiCecMessageBuilder.buildSetMenuLanguageCommand(
-                mAddress, Locale.getDefault().getISO3Language());
         // TODO: figure out how to handle failed to get language code.
-        if (command != null) {
-            mService.sendCecCommand(command);
-        } else {
+        if (!broadcastMenuLanguage(Locale.getDefault().getISO3Language())) {
             Slog.w(TAG, "Failed to respond to <Get Menu Language>: " + message.toString());
         }
         return true;
     }
 
+    @ServiceThreadOnly
+    boolean broadcastMenuLanguage(String language) {
+        assertRunOnServiceThread();
+        HdmiCecMessage command = HdmiCecMessageBuilder.buildSetMenuLanguageCommand(
+                mAddress, language);
+        if (command != null) {
+            mService.sendCecCommand(command);
+            return true;
+        }
+        return false;
+    }
+
     @Override
     @ServiceThreadOnly
     protected boolean handleReportPhysicalAddress(HdmiCecMessage message) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 32d97ba..5b99f14 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -78,6 +78,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Locale;
 
 /**
  * Provides a service for sending and processing HDMI control messages,
@@ -123,7 +124,7 @@
         void onPollingFinished(List<Integer> ackedAddress);
     }
 
-    private class PowerStateReceiver extends BroadcastReceiver {
+    private class HdmiControlBroadcastReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
             switch (intent.getAction()) {
@@ -137,6 +138,12 @@
                         onWakeUp();
                     }
                     break;
+                case Intent.ACTION_CONFIGURATION_CHANGED:
+                    String language = Locale.getDefault().getISO3Language();
+                    if (!mLanguage.equals(language)) {
+                        onLanguageChanged(language);
+                    }
+                    break;
             }
         }
     }
@@ -238,12 +245,16 @@
 
     private HdmiCecMessageValidator mMessageValidator;
 
-    private final PowerStateReceiver mPowerStateReceiver = new PowerStateReceiver();
+    private final HdmiControlBroadcastReceiver
+            mHdmiControlBroadcastReceiver = new HdmiControlBroadcastReceiver();
 
     @ServiceThreadOnly
     private int mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY;
 
     @ServiceThreadOnly
+    private String mLanguage = Locale.getDefault().getISO3Language();
+
+    @ServiceThreadOnly
     private boolean mStandbyMessageReceived = false;
 
     @ServiceThreadOnly
@@ -307,7 +318,8 @@
             IntentFilter filter = new IntentFilter();
             filter.addAction(Intent.ACTION_SCREEN_OFF);
             filter.addAction(Intent.ACTION_SCREEN_ON);
-            getContext().registerReceiver(mPowerStateReceiver, filter);
+            filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
+            getContext().registerReceiver(mHdmiControlBroadcastReceiver, filter);
         }
     }
 
@@ -356,7 +368,7 @@
                     break;
                 case Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED:
                     tv().setAutoWakeup(enabled);
-                    setOption(OPTION_CEC_AUTO_WAKEUP, toInt(enabled));
+                    setCecOption(OPTION_CEC_AUTO_WAKEUP, toInt(enabled));
                     break;
                 case Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED:
                     tv().setAutoDeviceOff(enabled);
@@ -495,6 +507,10 @@
         }
     }
 
+    List<HdmiPortInfo> getPortInfo() {
+        return mPortInfo;
+    }
+
     /**
      * Returns HDMI port information for the given port id.
      *
@@ -1001,6 +1017,17 @@
                         invokeCallback(callback, HdmiControlManager.RESULT_SOURCE_NOT_AVAILABLE);
                         return;
                     }
+                    if (mMhlController != null) {
+                        HdmiMhlLocalDevice device = mMhlController.getLocalDeviceById(deviceId);
+                        if (device != null) {
+                            // Upon selecting MHL device, we send RAP[Content On] to wake up
+                            // the connected mobile device, start routing control to switch ports.
+                            // callback is handled by MHL action.
+                            device.turnOn(callback);
+                            tv.doManualPortSwitching(device.getInfo().getPortId(), null);
+                            return;
+                        }
+                    }
                     tv.deviceSelect(deviceId, callback);
                 }
             });
@@ -1110,7 +1137,7 @@
         @Override
         public List<HdmiPortInfo> getPortInfo() {
             enforceAccessPermission();
-            return mPortInfo;
+            return HdmiControlService.this.getPortInfo();
         }
 
         @Override
@@ -1682,12 +1709,28 @@
         });
     }
 
-    private void disableDevices(PendingActionClearedCallback callback) {
-        for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) {
-            device.disableDevice(mStandbyMessageReceived, callback);
-        }
+    @ServiceThreadOnly
+    private void onLanguageChanged(String language) {
+        assertRunOnServiceThread();
+        mLanguage = language;
+
         if (isTvDevice()) {
-            unregisterSettingsObserver();
+            tv().broadcastMenuLanguage(language);
+        }
+    }
+
+    private void disableDevices(PendingActionClearedCallback callback) {
+        if (mCecController != null) {
+            for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) {
+                device.disableDevice(mStandbyMessageReceived, callback);
+            }
+            if (isTvDevice()) {
+                unregisterSettingsObserver();
+            }
+        }
+
+        if (mMhlController != null) {
+            mMhlController.clearAllLocalDevices();
         }
     }
 
@@ -1759,7 +1802,7 @@
     }
 
     @ServiceThreadOnly
-    void setOption(int key, int value) {
+    void setCecOption(int key, int value) {
         assertRunOnServiceThread();
         mCecController.setOption(key, value);
     }
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 7c1681c..93dceff 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -774,6 +774,8 @@
                     .setContentIntent(mKeyboardLayoutIntent)
                     .setSmallIcon(R.drawable.ic_settings_language)
                     .setPriority(Notification.PRIORITY_LOW)
+                    .setColor(mContext.getResources().getColor(
+                            com.android.internal.R.color.system_notification_accent_color))
                     .build();
             mNotificationManager.notifyAsUser(null,
                     R.string.select_keyboard_layout_notification_title,
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index f820a3c..978a9f4 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -26,14 +26,12 @@
 import android.media.MediaMetadata;
 import android.media.Rating;
 import android.media.VolumeProvider;
-import android.media.routing.IMediaRouter;
-import android.media.routing.IMediaRouterDelegate;
-import android.media.routing.IMediaRouterStateCallback;
 import android.media.session.ISession;
 import android.media.session.ISessionCallback;
 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;
@@ -96,7 +94,6 @@
             new ArrayList<ISessionControllerCallback>();
 
     private long mFlags;
-    private IMediaRouter mMediaRouter;
     private PendingIntent mMediaButtonReceiver;
     private PendingIntent mLaunchIntent;
 
@@ -115,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;
@@ -241,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);
@@ -269,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 {
@@ -692,12 +689,6 @@
         }
 
         @Override
-        public void setMediaRouter(IMediaRouter router) {
-            mMediaRouter = router;
-            mHandler.post(MessageHandler.MSG_UPDATE_SESSION_STATE);
-        }
-
-        @Override
         public void setMediaButtonReceiver(PendingIntent pi) {
             mMediaButtonReceiver = pi;
         }
@@ -758,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 {
@@ -775,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;
             }
@@ -1008,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
@@ -1147,13 +1138,6 @@
         public boolean isTransportControlEnabled() {
             return MediaSessionRecord.this.isTransportControlEnabled();
         }
-
-        @Override
-        public IMediaRouterDelegate createMediaRouterDelegate(
-                IMediaRouterStateCallback callback) {
-            // todo
-            return null;
-        }
     }
 
     private class MessageHandler extends Handler {
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/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java
index a2e9d676..52e741b 100644
--- a/services/core/java/com/android/server/net/LockdownVpnTracker.java
+++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java
@@ -304,16 +304,18 @@
     }
 
     private void showNotification(int titleRes, int iconRes) {
-        final Notification.Builder builder = new Notification.Builder(mContext);
-        builder.setWhen(0);
-        builder.setSmallIcon(iconRes);
-        builder.setContentTitle(mContext.getString(titleRes));
-        builder.setContentText(mContext.getString(R.string.vpn_lockdown_config));
-        builder.setContentIntent(mConfigIntent);
-        builder.setPriority(Notification.PRIORITY_LOW);
-        builder.setOngoing(true);
-        builder.addAction(
-                R.drawable.ic_menu_refresh, mContext.getString(R.string.reset), mResetIntent);
+        final Notification.Builder builder = new Notification.Builder(mContext)
+                .setWhen(0)
+                .setSmallIcon(iconRes)
+                .setContentTitle(mContext.getString(titleRes))
+                .setContentText(mContext.getString(R.string.vpn_lockdown_config))
+                .setContentIntent(mConfigIntent)
+                .setPriority(Notification.PRIORITY_LOW)
+                .setOngoing(true)
+                .addAction(R.drawable.ic_menu_refresh, mContext.getString(R.string.reset),
+                        mResetIntent)
+                .setColor(mContext.getResources().getColor(
+                        com.android.internal.R.color.system_notification_accent_color));
 
         NotificationManager.from(mContext).notify(TAG, 0, builder.build());
     }
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index bb5243c..9e5fa41 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -791,6 +791,8 @@
         final Notification.Builder builder = new Notification.Builder(mContext);
         builder.setOnlyAlertOnce(true);
         builder.setWhen(0L);
+        builder.setColor(mContext.getResources().getColor(
+                com.android.internal.R.color.system_notification_accent_color));
 
         final Resources res = mContext.getResources();
         switch (type) {
@@ -916,6 +918,8 @@
         builder.setTicker(title);
         builder.setContentTitle(title);
         builder.setContentText(body);
+        builder.setColor(mContext.getResources().getColor(
+                com.android.internal.R.color.system_notification_accent_color));
 
         final Intent intent = buildAllowBackgroundDataIntent();
         builder.setContentIntent(
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/core/java/com/android/server/storage/DeviceStorageMonitorService.java b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
index eb38f4a..468a344 100644
--- a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
+++ b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
@@ -453,6 +453,8 @@
         notification.icon = com.android.internal.R.drawable.stat_notify_disk_full;
         notification.tickerText = title;
         notification.flags |= Notification.FLAG_NO_CLEAR;
+        notification.color = context.getResources().getColor(
+                com.android.internal.R.color.system_notification_accent_color);
         notification.setLatestEventInfo(context, title, details, intent);
         notification.visibility = Notification.VISIBILITY_PUBLIC;
         notification.category = Notification.CATEGORY_SYSTEM;
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 425eff3..fa991c2 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -958,7 +958,7 @@
                 Object obj = null;
                 switch (status) {
                     case HdmiControlManager.DEVICE_EVENT_ADD_DEVICE: {
-                        if (!mHdmiDeviceList.contains(deviceInfo)) {
+                        if (findHdmiDeviceInfo(deviceInfo.getId()) == null) {
                             mHdmiDeviceList.add(deviceInfo);
                         } else {
                             Slog.w(TAG, "The list already contains " + deviceInfo + "; ignoring.");
@@ -969,7 +969,8 @@
                         break;
                     }
                     case HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE: {
-                        if (!mHdmiDeviceList.remove(deviceInfo)) {
+                        HdmiDeviceInfo originalDeviceInfo = findHdmiDeviceInfo(deviceInfo.getId());
+                        if (!mHdmiDeviceList.remove(originalDeviceInfo)) {
                             Slog.w(TAG, "The list doesn't contain " + deviceInfo + "; ignoring.");
                             return;
                         }
@@ -978,13 +979,14 @@
                         break;
                     }
                     case HdmiControlManager.DEVICE_EVENT_UPDATE_DEVICE: {
-                        if (!mHdmiDeviceList.remove(deviceInfo)) {
+                        HdmiDeviceInfo originalDeviceInfo = findHdmiDeviceInfo(deviceInfo.getId());
+                        if (!mHdmiDeviceList.remove(originalDeviceInfo)) {
                             Slog.w(TAG, "The list doesn't contain " + deviceInfo + "; ignoring.");
                             return;
                         }
                         mHdmiDeviceList.add(deviceInfo);
                         messageType = ListenerHandler.HDMI_DEVICE_UPDATED;
-                        String inputId = mHdmiInputIdMap.get(deviceInfo.getLogicalAddress());
+                        String inputId = mHdmiInputIdMap.get(deviceInfo.getId());
                         SomeArgs args = SomeArgs.obtain();
                         args.arg1 = inputId;
                         args.arg2 = deviceInfo;
@@ -1001,6 +1003,15 @@
                 }
             }
         }
+
+        private HdmiDeviceInfo findHdmiDeviceInfo(int id) {
+            for (HdmiDeviceInfo info : mHdmiDeviceList) {
+                if (info.getId() == id) {
+                    return info;
+                }
+            }
+            return null;
+        }
     }
 
     private final class HdmiSystemAudioModeChangeListener extends
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 958cb6d..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;
@@ -1517,6 +1531,8 @@
             .setContentIntent(notifyIntent)
             .setPriority(Notification.PRIORITY_HIGH)
             .setShowWhen(false)
+            .setColor(mContext.getResources().getColor(
+                    com.android.internal.R.color.system_notification_accent_color))
             .build();
 
         // If this is a boot intent, this will fire for each user. But if this is a storage changed
@@ -4044,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/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java
index 7400dde..6a56de0 100644
--- a/services/print/java/com/android/server/print/PrintManagerService.java
+++ b/services/print/java/com/android/server/print/PrintManagerService.java
@@ -783,7 +783,9 @@
                     .setContentIntent(pendingIntent)
                     .setWhen(System.currentTimeMillis())
                     .setAutoCancel(true)
-                    .setShowWhen(true);
+                    .setShowWhen(true)
+                    .setColor(mContext.getResources().getColor(
+                            com.android.internal.R.color.system_notification_accent_color));
 
             NotificationManager notificationManager = (NotificationManager) mContext
                     .getSystemService(Context.NOTIFICATION_SERVICE);
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index c0923ca..c078cb2 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -732,6 +732,8 @@
                                     "com.android.settings.UsbSettings"));
                     PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,
                             intent, 0, null, UserHandle.CURRENT);
+                    notification.color = mContext.getResources().getColor(
+                            com.android.internal.R.color.system_notification_accent_color);
                     notification.setLatestEventInfo(mContext, title, message, pi);
                     notification.visibility = Notification.VISIBILITY_PUBLIC;
                     mNotificationManager.notifyAsUser(null, id, notification,
@@ -768,6 +770,8 @@
                                     "com.android.settings.DevelopmentSettings"));
                     PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,
                             intent, 0, null, UserHandle.CURRENT);
+                    notification.color = mContext.getResources().getColor(
+                            com.android.internal.R.color.system_notification_accent_color);
                     notification.setLatestEventInfo(mContext, title, message, pi);
                     notification.visibility = Notification.VISIBILITY_PUBLIC;
                     mAdbNotificationShown = true;
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/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/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/tests/OneMedia/Android.mk b/tests/OneMedia/Android.mk
index 4feac68..4d39728 100644
--- a/tests/OneMedia/Android.mk
+++ b/tests/OneMedia/Android.mk
@@ -9,9 +9,6 @@
 LOCAL_PACKAGE_NAME := OneMedia
 LOCAL_CERTIFICATE := platform
 
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    android-support-media-protocols
-
 LOCAL_PROGUARD_ENABLED := disabled
 
 include $(BUILD_PACKAGE)
diff --git a/tests/OneMedia/AndroidManifest.xml b/tests/OneMedia/AndroidManifest.xml
index 95072a4..beafeb4 100644
--- a/tests/OneMedia/AndroidManifest.xml
+++ b/tests/OneMedia/AndroidManifest.xml
@@ -25,15 +25,6 @@
             android:name="com.android.onemedia.OnePlayerService"
             android:exported="true"
             android:process="com.android.onemedia.service" />
-        <service
-            android:name=".provider.OneMediaRouteProvider"
-            android:permission="android.permission.BIND_MEDIA_ROUTE_SERVICE"
-            android:exported="true"
-            android:process="com.android.onemedia.provider">
-            <intent-filter>
-                <action android:name="android.media.routing.MediaRouteService" />
-            </intent-filter>
-          </service>
     </application>
 
 </manifest>
diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerSession.java b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
index 9afcf24..8b7c883 100644
--- a/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
+++ b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
@@ -19,24 +19,16 @@
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.media.MediaMetadata;
-import android.media.routing.MediaRouteSelector;
-import android.media.routing.MediaRouter;
-import android.media.routing.MediaRouter.ConnectionRequest;
-import android.media.routing.MediaRouter.DestinationInfo;
-import android.media.routing.MediaRouter.RouteInfo;
 import android.media.session.MediaSession;
 import android.media.session.MediaSessionManager;
 import android.media.session.PlaybackState;
 import android.os.Bundle;
-import android.support.media.protocols.MediaPlayerProtocol;
-import android.support.media.protocols.MediaPlayerProtocol.MediaStatus;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.util.Log;
 import android.view.KeyEvent;
 
 import com.android.onemedia.playback.LocalRenderer;
-import com.android.onemedia.playback.OneMRPRenderer;
 import com.android.onemedia.playback.Renderer;
 import com.android.onemedia.playback.RequestUtils;
 
@@ -47,7 +39,6 @@
     private static final String TAG = "PlayerSession";
 
     protected MediaSession mSession;
-    protected MediaRouter mRouter;
     protected Context mContext;
     protected Renderer mRenderer;
     protected MediaSession.Callback mCallback;
@@ -80,22 +71,11 @@
                 .getSystemService(Context.MEDIA_SESSION_SERVICE);
         Log.d(TAG, "Creating session for package " + mContext.getBasePackageName());
 
-        mRouter = new MediaRouter(mContext);
-        mRouter.addSelector(new MediaRouteSelector.Builder()
-                .addRequiredProtocol(MediaPlayerProtocol.class)
-                .build());
-        mRouter.addSelector(new MediaRouteSelector.Builder()
-                .setRequiredFeatures(MediaRouter.ROUTE_FEATURE_LIVE_AUDIO)
-                .setOptionalFeatures(MediaRouter.ROUTE_FEATURE_LIVE_VIDEO)
-                .build());
-        mRouter.setRoutingCallback(new RoutingCallback(), null);
-
         mSession = new MediaSession(mContext, "OneMedia");
         mSession.setCallback(mCallback);
         mSession.setPlaybackState(mPlaybackState);
         mSession.setFlags(MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS
                 | MediaSession.FLAG_HANDLES_MEDIA_BUTTONS);
-        mSession.setMediaRouter(mRouter);
         mSession.setActive(true);
         updateMetadata();
     }
@@ -113,10 +93,6 @@
             mSession.release();
             mSession = null;
         }
-        if (mRouter != null) {
-            mRouter.release();
-            mRouter = null;
-        }
     }
 
     public void setListener(Listener listener) {
@@ -266,63 +242,4 @@
             mRenderer.onPause();
         }
     }
-
-    private class RoutingCallback extends MediaRouter.RoutingCallback {
-        @Override
-        public void onConnectionStateChanged(int state) {
-            if (state == MediaRouter.CONNECTION_STATE_CONNECTING) {
-                if (mRenderer != null) {
-                    mRenderer.onStop();
-                }
-                mRenderer = null;
-                updateState(PlaybackState.STATE_CONNECTING);
-                return;
-            }
-
-            MediaRouter.ConnectionInfo connection = mRouter.getConnection();
-            if (connection != null) {
-                MediaPlayerProtocol protocol =
-                        connection.getProtocolObject(MediaPlayerProtocol.class);
-                if (protocol != null) {
-                    Log.d(TAG, "Connected to route using media player protocol");
-
-                    protocol.setCallback(new PlayerCallback(), null);
-                    mRenderer = new OneMRPRenderer(protocol);
-                    updateState(PlaybackState.STATE_NONE);
-                    return;
-                }
-            }
-
-            // Use local route
-            mRenderer = new LocalRenderer(mContext, null);
-            mRenderer.registerListener(mRenderListener);
-            updateState(PlaybackState.STATE_NONE);
-        }
-    }
-
-    private class PlayerCallback extends MediaPlayerProtocol.Callback {
-        @Override
-        public void onStatusUpdated(MediaStatus status, Bundle extras) {
-            if (status != null) {
-                Log.d(TAG, "Received status update: " + status.toBundle());
-                switch (status.getPlayerState()) {
-                    case MediaStatus.PLAYER_STATE_BUFFERING:
-                        updateState(PlaybackState.STATE_BUFFERING);
-                        break;
-                    case MediaStatus.PLAYER_STATE_IDLE:
-                        updateState(PlaybackState.STATE_STOPPED);
-                        break;
-                    case MediaStatus.PLAYER_STATE_PAUSED:
-                        updateState(PlaybackState.STATE_PAUSED);
-                        break;
-                    case MediaStatus.PLAYER_STATE_PLAYING:
-                        updateState(PlaybackState.STATE_PLAYING);
-                        break;
-                    case MediaStatus.PLAYER_STATE_UNKNOWN:
-                        updateState(PlaybackState.STATE_NONE);
-                        break;
-                }
-            }
-        }
-    }
 }
diff --git a/tests/OneMedia/src/com/android/onemedia/playback/OneMRPRenderer.java b/tests/OneMedia/src/com/android/onemedia/playback/OneMRPRenderer.java
deleted file mode 100644
index 55eb92c..0000000
--- a/tests/OneMedia/src/com/android/onemedia/playback/OneMRPRenderer.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.android.onemedia.playback;
-
-import android.os.Bundle;
-import android.support.media.protocols.MediaPlayerProtocol;
-import android.support.media.protocols.MediaPlayerProtocol.MediaInfo;
-
-/**
- * Renderer for communicating with the OneMRP route
- */
-public class OneMRPRenderer extends Renderer {
-    private final MediaPlayerProtocol mProtocol;
-
-    public OneMRPRenderer(MediaPlayerProtocol protocol) {
-        super(null, null);
-        mProtocol = protocol;
-    }
-
-    @Override
-    public void setContent(Bundle request) {
-        MediaInfo mediaInfo = new MediaInfo(request.getString(RequestUtils.EXTRA_KEY_SOURCE),
-                MediaInfo.STREAM_TYPE_BUFFERED, "audio/mp3");
-        mProtocol.load(mediaInfo, true, 0, null);
-    }
-
-    @Override
-    public boolean onStop() {
-        mProtocol.stop(null);
-        return true;
-    }
-
-    @Override
-    public boolean onPlay() {
-        mProtocol.play(null);
-        return true;
-    }
-
-    @Override
-    public boolean onPause() {
-        mProtocol.pause(null);
-        return true;
-    }
-
-    @Override
-    public long getSeekPosition() {
-        return -1;
-    }
-}
diff --git a/tests/OneMedia/src/com/android/onemedia/provider/OneMediaRouteProvider.java b/tests/OneMedia/src/com/android/onemedia/provider/OneMediaRouteProvider.java
deleted file mode 100644
index 5845e48..0000000
--- a/tests/OneMedia/src/com/android/onemedia/provider/OneMediaRouteProvider.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.onemedia.provider;
-
-import android.media.routing.MediaRouteSelector;
-import android.media.routing.MediaRouteService;
-import android.media.routing.MediaRouter.ConnectionInfo;
-import android.media.routing.MediaRouter.ConnectionRequest;
-import android.media.routing.MediaRouter.DestinationInfo;
-import android.media.routing.MediaRouter.DiscoveryRequest;
-import android.media.routing.MediaRouter.RouteInfo;
-import android.media.session.PlaybackState;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Process;
-import android.support.media.protocols.MediaPlayerProtocol;
-import android.support.media.protocols.MediaPlayerProtocol.MediaInfo;
-import android.support.media.protocols.MediaPlayerProtocol.MediaStatus;
-import android.os.Looper;
-import android.os.ResultReceiver;
-import android.os.SystemClock;
-import android.util.Log;
-
-import com.android.onemedia.playback.LocalRenderer;
-import com.android.onemedia.playback.Renderer;
-import com.android.onemedia.playback.RequestUtils;
-
-import java.util.ArrayList;
-
-/**
- * Test of MediaRouteProvider. Show a dummy provider with a simple interface for
- * playing music.
- */
-public class OneMediaRouteProvider extends MediaRouteService {
-    private static final String TAG = "OneMRP";
-    private static final boolean DEBUG = true;
-
-    private static final String TEST_DESTINATION_ID = "testDestination";
-    private static final String TEST_ROUTE_ID = "testRoute";
-
-    private Renderer mRenderer;
-    private RenderListener mRenderListener;
-    private PlaybackState mPlaybackState;
-    private Handler mHandler;
-
-    private OneStub mStub;
-
-    @Override
-    public void onCreate() {
-        mHandler = new Handler();
-        mRenderer = new LocalRenderer(this, null);
-        mRenderListener = new RenderListener();
-        PlaybackState.Builder bob = new PlaybackState.Builder();
-        bob.setActions(PlaybackState.ACTION_PAUSE | PlaybackState.ACTION_PLAY);
-        mPlaybackState = bob.build();
-
-        mRenderer.registerListener(mRenderListener);
-    }
-
-    @Override
-    public ClientSession onCreateClientSession(ClientInfo client) {
-        if (client.getUid() != Process.myUid()) {
-            // for testing purposes, only allow connections from this application
-            // since this provider is not fully featured
-            return null;
-        }
-        return new OneSession(client);
-    }
-
-    private final class OneSession extends ClientSession {
-        private final ClientInfo mClient;
-
-        public OneSession(ClientInfo client) {
-            mClient = client;
-        }
-
-        @Override
-        public boolean onStartDiscovery(DiscoveryRequest req, DiscoveryCallback callback) {
-            for (MediaRouteSelector selector : req.getSelectors()) {
-                if (isMatch(selector)) {
-                    DestinationInfo destination = new DestinationInfo.Builder(
-                            TEST_DESTINATION_ID, getServiceMetadata(), "OneMedia")
-                            .setDescription("Test route from OneMedia app.")
-                            .build();
-                    ArrayList<RouteInfo> routes = new ArrayList<RouteInfo>();
-                    routes.add(new RouteInfo.Builder(
-                            TEST_ROUTE_ID, destination, selector).build());
-                    callback.onDestinationFound(destination, routes);
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        @Override
-        public void onStopDiscovery() {
-        }
-
-        @Override
-        public boolean onConnect(ConnectionRequest req, ConnectionCallback callback) {
-            if (req.getRoute().getId().equals(TEST_ROUTE_ID)) {
-                mStub = new OneStub();
-                ConnectionInfo connection = new ConnectionInfo.Builder(req.getRoute())
-                        .setProtocolStub(MediaPlayerProtocol.class, mStub)
-                        .build();
-                callback.onConnected(connection);
-                return true;
-            }
-            return false;
-        }
-
-        @Override
-        public void onDisconnect() {
-            mStub = null;
-        }
-
-        private boolean isMatch(MediaRouteSelector selector) {
-            if (!selector.containsProtocol(MediaPlayerProtocol.class)) {
-                return false;
-            }
-            for (String protocol : selector.getRequiredProtocols()) {
-                if (!protocol.equals(MediaPlayerProtocol.class.getName())) {
-                    return false;
-                }
-            }
-            return true;
-        }
-    }
-
-    private final class OneStub extends MediaPlayerProtocol.Stub {
-        MediaInfo mMediaInfo;
-
-        public OneStub() {
-            super(mHandler);
-        }
-
-        @Override
-        public void onLoad(MediaInfo mediaInfo, boolean autoplay, long playPosition,
-                Bundle extras) {
-            if (DEBUG) {
-                Log.d(TAG, "Attempting to play " + mediaInfo.getContentId());
-            }
-            // look up the route and send a play command to it
-            mMediaInfo = mediaInfo;
-            Bundle bundle = new Bundle();
-            bundle.putString(RequestUtils.EXTRA_KEY_SOURCE, mediaInfo.getContentId());
-            mRenderer.setContent(bundle);
-        }
-
-        @Override
-        public void onPlay(Bundle extras) {
-            mRenderer.onPlay();
-        }
-
-        @Override
-        public void onPause(Bundle extras) {
-            mRenderer.onPause();
-        }
-    }
-
-    private class RenderListener implements Renderer.Listener {
-
-        @Override
-        public void onError(int type, int extra, Bundle extras, Throwable error) {
-            Log.d(TAG, "Sending onError with type " + type + " and extra " + extra);
-            sendStatusUpdate(PlaybackState.STATE_ERROR);
-        }
-
-        @Override
-        public void onStateChanged(int newState) {
-            long position = -1;
-            if (mRenderer != null) {
-                position = mRenderer.getSeekPosition();
-            }
-            int pbState;
-            float rate = 0;
-            String errorMsg = null;
-            switch (newState) {
-                case Renderer.STATE_ENDED:
-                case Renderer.STATE_STOPPED:
-                    pbState = PlaybackState.STATE_STOPPED;
-                    break;
-                case Renderer.STATE_INIT:
-                case Renderer.STATE_PREPARING:
-                    pbState = PlaybackState.STATE_BUFFERING;
-                    break;
-                case Renderer.STATE_ERROR:
-                    pbState = PlaybackState.STATE_ERROR;
-                    break;
-                case Renderer.STATE_PAUSED:
-                    pbState = PlaybackState.STATE_PAUSED;
-                    break;
-                case Renderer.STATE_PLAYING:
-                    pbState = PlaybackState.STATE_PLAYING;
-                    rate = 1;
-                    break;
-                default:
-                    pbState = PlaybackState.STATE_ERROR;
-                    errorMsg = "unknown state";
-                    break;
-            }
-            PlaybackState.Builder bob = new PlaybackState.Builder(mPlaybackState);
-            bob.setState(pbState, position, rate, SystemClock.elapsedRealtime());
-            bob.setErrorMessage(errorMsg);
-            mPlaybackState = bob.build();
-
-            sendStatusUpdate(mPlaybackState.getState());
-        }
-
-        @Override
-        public void onBufferingUpdate(int percent) {
-        }
-
-        @Override
-        public void onFocusLost() {
-            Log.d(TAG, "Focus lost, pausing");
-            // Don't update state here, we'll get a separate call to
-            // onStateChanged when it pauses
-            mRenderer.onPause();
-        }
-
-        @Override
-        public void onNextStarted() {
-        }
-
-        private void sendStatusUpdate(int state) {
-            if (mStub != null) {
-                MediaStatus status = new MediaStatus(1, mStub.mMediaInfo);
-                switch (state) {
-                    case PlaybackState.STATE_BUFFERING:
-                    case PlaybackState.STATE_FAST_FORWARDING:
-                    case PlaybackState.STATE_REWINDING:
-                    case PlaybackState.STATE_SKIPPING_TO_NEXT:
-                    case PlaybackState.STATE_SKIPPING_TO_PREVIOUS:
-                        status.setPlayerState(MediaStatus.PLAYER_STATE_BUFFERING);
-                        break;
-                    case PlaybackState.STATE_CONNECTING:
-                    case PlaybackState.STATE_STOPPED:
-                        status.setPlayerState(MediaStatus.PLAYER_STATE_IDLE);
-                        break;
-                    case PlaybackState.STATE_PAUSED:
-                        status.setPlayerState(MediaStatus.PLAYER_STATE_PAUSED);
-                        break;
-                    case PlaybackState.STATE_PLAYING:
-                        status.setPlayerState(MediaStatus.PLAYER_STATE_PLAYING);
-                        break;
-                    case PlaybackState.STATE_NONE:
-                    case PlaybackState.STATE_ERROR:
-                    default:
-                        status.setPlayerState(MediaStatus.PLAYER_STATE_UNKNOWN);
-                        break;
-                }
-                mStub.sendStatusUpdatedEvent(status, null);
-            }
-        }
-    }
-}
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index cf1d4fd..c98808f 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -484,15 +484,6 @@
                 attr.hasErrors = true;
             }
 
-            // Make sure an id is defined for this enum/flag identifier...
-            if (!attr.hasErrors && !outTable->hasBagOrEntry(itemIdent, &id16, &myPackage)) {
-                err = outTable->startBag(SourcePos(in->getPrintableSource(), block.getLineNumber()),
-                                         myPackage, id16, itemIdent, String16(), NULL);
-                if (err != NO_ERROR) {
-                    attr.hasErrors = true;
-                }
-            }
-
             if (!attr.hasErrors) {
                 if (enumOrFlagsComment.size() == 0) {
                     enumOrFlagsComment.append(mayOrMust(attr.type,
@@ -2508,11 +2499,13 @@
         sp<Type> attr = p->getType(String16("attr"), unknown);
 
         // Assign indices...
-        for (ti=0; ti<N; ti++) {
+        const size_t typeCount = p->getOrderedTypes().size();
+        for (size_t ti = 0; ti < typeCount; ti++) {
             sp<Type> t = p->getOrderedTypes().itemAt(ti);
             if (t == NULL) {
                 continue;
             }
+
             err = t->applyPublicEntryOrder();
             if (err != NO_ERROR && firstError == NO_ERROR) {
                 firstError = err;
@@ -2534,7 +2527,7 @@
         }
 
         // Assign resource IDs to keys in bags...
-        for (ti=0; ti<N; ti++) {
+        for (size_t ti = 0; ti < typeCount; ti++) {
             sp<Type> t = p->getOrderedTypes().itemAt(ti);
             if (t == NULL) {
                 continue;
@@ -3296,11 +3289,16 @@
     Item item(sourcePos, false, value, style);
 
     if (mType == TYPE_BAG) {
-        const Item& item(mBag.valueAt(0));
-        sourcePos.error("Resource entry %s is already defined as a bag.\n"
-                        "%s:%d: Originally defined here.\n",
-                        String8(mName).string(),
-                        item.sourcePos.file.string(), item.sourcePos.line);
+        if (mBag.size() == 0) {
+            sourcePos.error("Resource entry %s is already defined as a bag.",
+                    String8(mName).string());
+        } else {
+            const Item& item(mBag.valueAt(0));
+            sourcePos.error("Resource entry %s is already defined as a bag.\n"
+                            "%s:%d: Originally defined here.\n",
+                            String8(mName).string(),
+                            item.sourcePos.file.string(), item.sourcePos.line);
+        }
         return UNKNOWN_ERROR;
     }
     if ( (mType != TYPE_UNKNOWN) && (overwrite == false) ) {
@@ -3374,6 +3372,9 @@
         if (it.isId) {
             if (!table->hasBagOrEntry(key, &id16, &package)) {
                 String16 value("false");
+                NOISY(fprintf(stderr, "Generating %s:id/%s\n",
+                        String8(package).string(),
+                        String8(key).string()));
                 status_t err = table->addEntry(SourcePos(String8("<generated>"), 0), package,
                                                id16, key, value);
                 if (err != NO_ERROR) {
diff --git a/tools/layoutlib/bridge/resources/bars/status_bar.xml b/tools/layoutlib/bridge/resources/bars/status_bar.xml
index 75bfb6e..04571e1 100644
--- a/tools/layoutlib/bridge/resources/bars/status_bar.xml
+++ b/tools/layoutlib/bridge/resources/bars/status_bar.xml
@@ -1,17 +1,27 @@
 <?xml version="1.0" encoding="utf-8"?>
 <merge xmlns:android="http://schemas.android.com/apk/res/android">
-	<TextView
-			android:layout_width="wrap_content"
-			android:layout_height="wrap_content"
-			android:layout_weight="1"/>
-	<ImageView
-			android:layout_height="wrap_content"
-			android:layout_width="wrap_content"
-			android:layout_marginTop="1dp"/>
-	<ImageView
-			android:layout_height="wrap_content"
-			android:layout_width="wrap_content"
-			android:layout_marginLeft="3dp"
-			android:layout_marginRight="5dp"
-			android:layout_marginTop="2dp"/>
+    <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"/>
+    <!-- The exact size of the wifi icon is specified in order to scale it properly.
+    Without scaling, it appeared huge. This is currently, 70% of the actual size. -->
+    <ImageView
+            android:layout_height="22.4dp"
+            android:layout_width="20.65dp"
+            android:layout_marginTop="1dp"/>
+    <ImageView
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:layout_marginLeft="3dp"
+            android:layout_marginRight="5dp"
+            android:layout_marginTop="4dp"/>
+    <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="4dp"
+            android:layout_marginRight="5dp"
+            android:gravity="center_vertical"
+            android:textSize="16dp"
+            android:fontFamily="sans-serif-medium"/>
 </merge>
diff --git a/tools/layoutlib/bridge/resources/bars/v21/hdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/v21/hdpi/stat_sys_wifi_signal_4_fully.png
deleted file mode 100644
index 931daed..0000000
--- a/tools/layoutlib/bridge/resources/bars/v21/hdpi/stat_sys_wifi_signal_4_fully.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v21/mdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/v21/mdpi/stat_sys_wifi_signal_4_fully.png
deleted file mode 100644
index 6e1ac91..0000000
--- a/tools/layoutlib/bridge/resources/bars/v21/mdpi/stat_sys_wifi_signal_4_fully.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v21/xhdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/v21/xhdpi/stat_sys_wifi_signal_4_fully.png
deleted file mode 100644
index 625c61d..0000000
--- a/tools/layoutlib/bridge/resources/bars/v21/xhdpi/stat_sys_wifi_signal_4_fully.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v21/xhdpi/stat_sys_wifi_signal_4_fully.xml b/tools/layoutlib/bridge/resources/bars/v21/xhdpi/stat_sys_wifi_signal_4_fully.xml
new file mode 100644
index 0000000..0498b6c
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/v21/xhdpi/stat_sys_wifi_signal_4_fully.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32.0dp"
+        android:height="29.5dp"
+        android:viewportWidth="26.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
+</vector>
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index f939678..5b69681 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -91,7 +91,7 @@
         // first count the array size
         int count = 0;
         for (ResourceValue data : mResourceData) {
-            if (data != null) {
+            if (data != null && !RenderResources.REFERENCE_NULL.equals(data.getValue())) {
                 count++;
             }
         }
@@ -103,7 +103,8 @@
         // fill the array with the indices.
         int index = 1;
         for (int i = 0 ; i < mResourceData.length ; i++) {
-            if (mResourceData[i] != null) {
+            if (mResourceData[i] != null
+                    && !RenderResources.REFERENCE_NULL.equals(mResourceData[i].getValue())) {
                 mIndices[index++] = i;
             }
         }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java
index 9b814f5..16b54f1 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java
@@ -20,10 +20,7 @@
 import java.util.Collections;
 import java.util.List;
 
-import static android.os.Build.VERSION_CODES.GINGERBREAD;
-import static android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH;
-import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR2;
-import static android.os.Build.VERSION_CODES.KITKAT;
+import static android.os.Build.VERSION_CODES.*;
 
 /**
  * Various helper methods to simulate older versions of platform.
@@ -39,13 +36,16 @@
     private static final List<String> sDefaultResourceDir =
             Collections.singletonList(DEFAULT_RESOURCE_DIR);
 
+    private static final int WHITE = 0xFFFFFFFF;
+    private static final int BLACK = 0xFF000000;
+
     public static boolean showOnScreenNavBar(int platformVersion) {
         return platformVersion == 0 || platformVersion >= ICE_CREAM_SANDWICH;
     }
 
     public static int getStatusBarColor(int platformVersion) {
         // return white for froyo and earlier; black otherwise.
-        return platformVersion == 0 || platformVersion >= GINGERBREAD ? 0xFF000000 : 0xFFFFFFFF;
+        return platformVersion == 0 || platformVersion >= GINGERBREAD ? BLACK : WHITE;
     }
 
     public static List<String> getResourceDirs(int platformVersion) {
@@ -70,4 +70,49 @@
 
         return Collections.unmodifiableList(list);
     }
+
+    public static String getTime(int platformVersion) {
+        if (platformVersion == 0) {
+            // TODO: revisit when the version is selected.
+            return "4:57";
+        }
+        if (platformVersion < GINGERBREAD) {
+            return "2:20";
+        }
+        if (platformVersion < ICE_CREAM_SANDWICH) {
+            return "2:30";
+        }
+        if (platformVersion < JELLY_BEAN) {
+            return "4:00";
+        }
+        if (platformVersion < KITKAT) {
+            return "4:30";
+        }
+        if (platformVersion <= KITKAT_WATCH) {
+            return "4:40";
+        }
+        // Should never happen.
+        return "4:04";
+    }
+
+    public static int getTimeColor(int platformVersion) {
+        if (platformVersion == 0 || platformVersion >= KITKAT ||
+                platformVersion > FROYO && platformVersion < HONEYCOMB) {
+            // Gingerbread and KitKat onwards.
+            return WHITE;
+        }
+        // Black for froyo.
+        if (platformVersion < GINGERBREAD) {
+            return BLACK;
+        } else if (platformVersion < KITKAT) {
+            // Honeycomb to JB-mr2: Holo blue light.
+            return 0xff33b5e5;
+        }
+        // Should never happen.
+        return WHITE;
+    }
+
+    public static String getWifiIconType(int platformVersion) {
+        return platformVersion == 0 ? "xml" : "png";
+    }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
index bed232ab..13ddf07 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
@@ -127,24 +127,25 @@
         }
     }
 
-    protected TextView setText(int index, String stringReference) {
+    protected TextView setText(int index, String string, boolean reference) {
         View child = getChildAt(index);
         if (child instanceof TextView) {
             TextView textView = (TextView) child;
-            setText(textView, stringReference);
+            setText(textView, string, reference);
             return textView;
         }
 
         return null;
     }
 
-    private void setText(TextView textView, String stringReference) {
-        ResourceValue value = getResourceValue(stringReference);
-        if (value != null) {
-            textView.setText(value.getValue());
-        } else {
-            textView.setText(stringReference);
+    private void setText(TextView textView, String string, boolean reference) {
+        if (reference) {
+            ResourceValue value = getResourceValue(string);
+            if (value != null) {
+                string = value.getValue();
+            }
         }
+        textView.setText(string);
     }
 
     protected void setStyle(String themeEntryName) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
index 1795db9..c7c62d6 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
@@ -16,22 +16,38 @@
 
 package com.android.layoutlib.bridge.bars;
 
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
+import com.android.layoutlib.bridge.impl.ParserFactory;
 import com.android.resources.Density;
 
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.content.Context;
+import android.graphics.drawable.Drawable;
 import android.view.Gravity;
+import android.view.View;
+import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import java.io.IOException;
+import java.io.InputStream;
+
 public class StatusBar extends CustomBar {
 
+    private final Context mContext;
+    private final int mSimulatedPlatformVersion;
+
     public StatusBar(Context context, Density density, int direction, boolean RtlEnabled,
             int simulatedPlatformVersion) throws XmlPullParserException {
         // FIXME: if direction is RTL but it's not enabled in application manifest, mirror this bar.
         super(context, LinearLayout.HORIZONTAL, "/bars/status_bar.xml", "status_bar.xml",
                 simulatedPlatformVersion);
+        mContext = context;
+        mSimulatedPlatformVersion = simulatedPlatformVersion;
 
         // FIXME: use FILL_H?
         setGravity(Gravity.START | Gravity.TOP | Gravity.RIGHT);
@@ -41,8 +57,44 @@
         // created for them.
         // We do know the order though.
         // 0 is the spacer
-        loadIcon(1, "stat_sys_wifi_signal_4_fully.png", density);
+        loadIcon(1, "stat_sys_wifi_signal_4_fully."
+                        + Config.getWifiIconType(simulatedPlatformVersion), density);
         loadIcon(2, "stat_sys_battery_100.png", density);
+        setText(3, Config.getTime(simulatedPlatformVersion), false)
+                .setTextColor(Config.getTimeColor(simulatedPlatformVersion));
+    }
+
+    @Override
+    protected void loadIcon(int index, String iconName, Density density) {
+        if (!iconName.endsWith(".xml")) {
+            super.loadIcon(index, iconName, density);
+            return;
+        }
+        View child = getChildAt(index);
+        if (child instanceof ImageView) {
+            ImageView imageView = (ImageView) child;
+            // The xml is stored only in xhdpi.
+            IconLoader iconLoader = new IconLoader(iconName, Density.XHIGH,
+                    mSimulatedPlatformVersion, null);
+            InputStream stream = iconLoader.getIcon();
+
+            if (stream != null) {
+                try {
+                    BridgeXmlBlockParser parser = new BridgeXmlBlockParser(
+                            ParserFactory.create(stream, null), (BridgeContext) mContext, true);
+                    Drawable drawable = Drawable.createFromXml(mContext.getResources(), parser);
+                    if (drawable != null) {
+                        imageView.setImageDrawable(drawable);
+                    }
+                } catch (XmlPullParserException e) {
+                    Bridge.getLog().error(LayoutLog.TAG_BROKEN, "Unable to draw wifi icon", e,
+                            null);
+                } catch (IOException e) {
+                    Bridge.getLog().error(LayoutLog.TAG_BROKEN, "Unable to draw wifi icon", e,
+                            null);
+                }
+            }
+        }
     }
 
     @Override
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java
index ff952bd..10f1383 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java
@@ -34,7 +34,7 @@
         // Cannot access the inside items through id because no R.id values have been
         // created for them.
         // We do know the order though.
-        mTextView = setText(0, label);
+        mTextView = setText(0, label, true);
 
         setStyle("windowTitleBackgroundStyle");
     }
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/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index e27bd7e..3d976e7 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1696,6 +1696,7 @@
      *
      * @hide
      */
+    @SystemApi
     public void connect(WifiConfiguration config, ActionListener listener) {
         if (config == null) throw new IllegalArgumentException("config cannot be null");
         validateChannel();
@@ -1718,6 +1719,7 @@
      * initialized again
      * @hide
      */
+    @SystemApi
     public void connect(int networkId, ActionListener listener) {
         if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative");
         validateChannel();
@@ -1742,6 +1744,7 @@
      * initialized again
      * @hide
      */
+    @SystemApi
     public void save(WifiConfiguration config, ActionListener listener) {
         if (config == null) throw new IllegalArgumentException("config cannot be null");
         validateChannel();
@@ -1761,6 +1764,7 @@
      * initialized again
      * @hide
      */
+    @SystemApi
     public void forget(int netId, ActionListener listener) {
         if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
         validateChannel();
@@ -1776,6 +1780,7 @@
      * initialized again
      * @hide
      */
+    @SystemApi
     public void disable(int netId, ActionListener listener) {
         if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
         validateChannel();
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);
 }