Merge "Add warning if an in-use Bitmap is reconfigured" into mnc-dev
diff --git a/Android.mk b/Android.mk
index b71f08c..27dedd9 100644
--- a/Android.mk
+++ b/Android.mk
@@ -348,12 +348,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 \
@@ -460,7 +454,6 @@
 	frameworks/base/location/java/android/location/Criteria.aidl \
 	frameworks/base/media/java/android/media/MediaMetadata.aidl \
 	frameworks/base/media/java/android/media/MediaDescription.aidl \
-	frameworks/base/media/java/android/media/routing/MediaRouteSelector.aidl \
 	frameworks/base/media/java/android/media/Rating.aidl \
 	frameworks/base/media/java/android/media/AudioAttributes.aidl \
 	frameworks/base/media/java/android/media/AudioFocusInfo.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index c812b6a..667ed02 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -233,6 +233,7 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/symbols/system/lib/libinputflingerhost.so $(PRODUCT_OUT)/symbols/system/lib64/libinputflingerhost.so)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/lib/libinputflingerhost.so $(PRODUCT_OUT)/obj_arm/lib/libinputflingerhost.so)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libinputflingerhost_intermediates $(PRODUCT_OUT)/obj_arm/SHARED_LIBRARIES/libinputflingerhost_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/target/common/obj/framework.aidl)
 
 # ******************************************************************
 # 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 8716381..7df09a1 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -28,7 +28,6 @@
     field public static final java.lang.String BIND_DREAM_SERVICE = "android.permission.BIND_DREAM_SERVICE";
     field public static final java.lang.String BIND_INCALL_SERVICE = "android.permission.BIND_INCALL_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";
@@ -1049,6 +1048,7 @@
     field public static final int screenOrientation = 16842782; // 0x101001e
     field public static final int screenSize = 16843466; // 0x10102ca
     field public static final int scrollHorizontally = 16843099; // 0x101015b
+    field public static final int scrollIndicators = 16844023; // 0x10104f7
     field public static final int scrollViewStyle = 16842880; // 0x1010080
     field public static final int scrollX = 16842962; // 0x10100d2
     field public static final int scrollY = 16842963; // 0x10100d3
@@ -5791,8 +5791,8 @@
     method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
     method public boolean setDeviceInitializer(android.content.ComponentName, android.content.ComponentName, java.lang.String) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
     method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
+    method public boolean setKeyguardDisabled(android.content.ComponentName, boolean);
     method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
-    method public boolean setKeyguardEnabledState(android.content.ComponentName, boolean);
     method public void setLockTaskPackages(android.content.ComponentName, java.lang.String[]) throws java.lang.SecurityException;
     method public void setMasterVolumeMuted(android.content.ComponentName, boolean);
     method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
@@ -5818,7 +5818,7 @@
     method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName);
     method public void setScreenCaptureDisabled(android.content.ComponentName, boolean);
     method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
-    method public void setStatusBarEnabledState(android.content.ComponentName, boolean);
+    method public boolean setStatusBarDisabled(android.content.ComponentName, boolean);
     method public int setStorageEncryption(android.content.ComponentName, boolean);
     method public void setSystemUpdatePolicy(android.content.ComponentName, android.app.admin.SystemUpdatePolicy);
     method public void setTrustAgentConfiguration(android.content.ComponentName, android.content.ComponentName, android.os.PersistableBundle);
@@ -8281,6 +8281,7 @@
     field public static final java.lang.String EXTRA_ALARM_COUNT = "android.intent.extra.ALARM_COUNT";
     field public static final java.lang.String EXTRA_ALLOW_MULTIPLE = "android.intent.extra.ALLOW_MULTIPLE";
     field public static final deprecated java.lang.String EXTRA_ALLOW_REPLACE = "android.intent.extra.ALLOW_REPLACE";
+    field public static final java.lang.String EXTRA_ALTERNATE_INTENTS = "android.intent.extra.ALTERNATE_INTENTS";
     field public static final java.lang.String EXTRA_ASSIST_CONTEXT = "android.intent.extra.ASSIST_CONTEXT";
     field public static final java.lang.String EXTRA_ASSIST_INPUT_HINT_KEYBOARD = "android.intent.extra.ASSIST_INPUT_HINT_KEYBOARD";
     field public static final java.lang.String EXTRA_ASSIST_PACKAGE = "android.intent.extra.ASSIST_PACKAGE";
@@ -8292,6 +8293,7 @@
     field public static final java.lang.String EXTRA_CHANGED_COMPONENT_NAME_LIST = "android.intent.extra.changed_component_name_list";
     field public static final java.lang.String EXTRA_CHANGED_PACKAGE_LIST = "android.intent.extra.changed_package_list";
     field public static final java.lang.String EXTRA_CHANGED_UID_LIST = "android.intent.extra.changed_uid_list";
+    field public static final java.lang.String EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER = "android.intent.extra.CHOOSER_REFINEMENT_INTENT_SENDER";
     field public static final java.lang.String EXTRA_CHOOSER_TARGETS = "android.intent.extra.CHOOSER_TARGETS";
     field public static final java.lang.String EXTRA_CHOSEN_COMPONENT = "android.intent.extra.CHOSEN_COMPONENT";
     field public static final java.lang.String EXTRA_CHOSEN_COMPONENT_INTENT_SENDER = "android.intent.extra.CHOSEN_COMPONENT_INTENT_SENDER";
@@ -8324,6 +8326,7 @@
     field public static final java.lang.String EXTRA_RESTRICTIONS_BUNDLE = "android.intent.extra.restrictions_bundle";
     field public static final java.lang.String EXTRA_RESTRICTIONS_INTENT = "android.intent.extra.restrictions_intent";
     field public static final java.lang.String EXTRA_RESTRICTIONS_LIST = "android.intent.extra.restrictions_list";
+    field public static final java.lang.String EXTRA_RESULT_RECEIVER = "android.intent.extra.RESULT_RECEIVER";
     field public static final java.lang.String EXTRA_RETURN_RESULT = "android.intent.extra.RETURN_RESULT";
     field public static final java.lang.String EXTRA_SHORTCUT_ICON = "android.intent.extra.shortcut.ICON";
     field public static final java.lang.String EXTRA_SHORTCUT_ICON_RESOURCE = "android.intent.extra.shortcut.ICON_RESOURCE";
@@ -17423,248 +17426,11 @@
 
 }
 
-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<android.media.routing.MediaRouteSelector> 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 {
     ctor public MediaController(android.content.Context, android.media.session.MediaSession.Token);
     method public void adjustVolume(int, int);
-    method public android.media.routing.MediaRouter.Delegate createMediaRouterDelegate();
     method public boolean dispatchMediaButtonEvent(android.view.KeyEvent);
     method public android.os.Bundle getExtras();
     method public long getFlags();
@@ -17738,7 +17504,6 @@
     method public void setExtras(android.os.Bundle);
     method public void setFlags(int);
     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);
@@ -30446,7 +30211,7 @@
     method public void handleCallSessionEvent(int);
     method public abstract void onRequestCameraCapabilities();
     method public abstract void onRequestConnectionDataUsage();
-    method public abstract void onSendSessionModifyRequest(android.telecom.VideoProfile);
+    method public abstract void onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile);
     method public abstract void onSendSessionModifyResponse(android.telecom.VideoProfile);
     method public abstract void onSetCamera(java.lang.String);
     method public abstract void onSetDeviceOrientation(int);
@@ -34186,14 +33951,6 @@
   }
 
   public deprecated class FloatMath {
-    method public static float ceil(float);
-    method public static float cos(float);
-    method public static float exp(float);
-    method public static float floor(float);
-    method public static float hypot(float, float);
-    method public static float pow(float, float);
-    method public static float sin(float);
-    method public static float sqrt(float);
   }
 
   public final class JsonReader implements java.io.Closeable {
@@ -36200,6 +35957,7 @@
     method public int getScrollBarFadeDuration();
     method public int getScrollBarSize();
     method public int getScrollBarStyle();
+    method public int getScrollIndicators();
     method public final int getScrollX();
     method public final int getScrollY();
     method public int getSolidColor();
@@ -36281,6 +36039,7 @@
     method public boolean isSaveEnabled();
     method public boolean isSaveFromParentEnabled();
     method public boolean isScrollContainer();
+    method public boolean isScrollIndicatorEnabled(int);
     method public boolean isScrollbarFadingEnabled();
     method public boolean isSelected();
     method public boolean isShown();
@@ -36480,6 +36239,8 @@
     method public void setScrollBarSize(int);
     method public void setScrollBarStyle(int);
     method public void setScrollContainer(boolean);
+    method public void setScrollIndicators(int);
+    method public void setScrollIndicators(int, int);
     method public void setScrollX(int);
     method public void setScrollY(int);
     method public void setScrollbarFadingEnabled(boolean);
@@ -36605,6 +36366,12 @@
     field public static final int SCROLL_AXIS_HORIZONTAL = 1; // 0x1
     field public static final int SCROLL_AXIS_NONE = 0; // 0x0
     field public static final int SCROLL_AXIS_VERTICAL = 2; // 0x2
+    field public static final int SCROLL_INDICATOR_BOTTOM = 2; // 0x2
+    field public static final int SCROLL_INDICATOR_END = 32; // 0x20
+    field public static final int SCROLL_INDICATOR_LEFT = 4; // 0x4
+    field public static final int SCROLL_INDICATOR_RIGHT = 8; // 0x8
+    field public static final int SCROLL_INDICATOR_START = 16; // 0x10
+    field public static final int SCROLL_INDICATOR_TOP = 1; // 0x1
     field protected static final int[] SELECTED_STATE_SET;
     field protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
     field public static final int SOUND_EFFECTS_ENABLED = 134217728; // 0x8000000
@@ -40647,6 +40414,7 @@
     method public void setSoftInputMode(int);
     method public void setVerticalOffset(int);
     method public void setWidth(int);
+    method public void setWindowLayoutType(int);
     method public void show();
     field public static final int INPUT_METHOD_FROM_FOCUSABLE = 0; // 0x0
     field public static final int INPUT_METHOD_NEEDED = 1; // 0x1
diff --git a/api/removed.txt b/api/removed.txt
index 5e77e15..0046a70 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -108,6 +108,21 @@
 
 }
 
+package android.util {
+
+  public deprecated class FloatMath {
+    method public static float ceil(float);
+    method public static float cos(float);
+    method public static float exp(float);
+    method public static float floor(float);
+    method public static float hypot(float, float);
+    method public static float pow(float, float);
+    method public static float sin(float);
+    method public static float sqrt(float);
+  }
+
+}
+
 package android.view {
 
   public class View implements android.view.accessibility.AccessibilityEventSource android.graphics.drawable.Drawable.Callback android.view.KeyEvent.Callback {
diff --git a/api/system-current.txt b/api/system-current.txt
index f11e113..0662d93 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -39,7 +39,6 @@
     field public static final java.lang.String BIND_INCALL_SERVICE = "android.permission.BIND_INCALL_SERVICE";
     field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD";
     field public static final java.lang.String BIND_KEYGUARD_APPWIDGET = "android.permission.BIND_KEYGUARD_APPWIDGET";
-    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";
@@ -1121,6 +1120,7 @@
     field public static final int screenOrientation = 16842782; // 0x101001e
     field public static final int screenSize = 16843466; // 0x10102ca
     field public static final int scrollHorizontally = 16843099; // 0x101015b
+    field public static final int scrollIndicators = 16844023; // 0x10104f7
     field public static final int scrollViewStyle = 16842880; // 0x1010080
     field public static final int scrollX = 16842962; // 0x10100d2
     field public static final int scrollY = 16842963; // 0x10100d3
@@ -5897,8 +5897,8 @@
     method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
     method public boolean setDeviceInitializer(android.content.ComponentName, android.content.ComponentName, java.lang.String) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
     method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
+    method public boolean setKeyguardDisabled(android.content.ComponentName, boolean);
     method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
-    method public boolean setKeyguardEnabledState(android.content.ComponentName, boolean);
     method public void setLockTaskPackages(android.content.ComponentName, java.lang.String[]) throws java.lang.SecurityException;
     method public void setMasterVolumeMuted(android.content.ComponentName, boolean);
     method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
@@ -5924,7 +5924,7 @@
     method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName);
     method public void setScreenCaptureDisabled(android.content.ComponentName, boolean);
     method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
-    method public void setStatusBarEnabledState(android.content.ComponentName, boolean);
+    method public boolean setStatusBarDisabled(android.content.ComponentName, boolean);
     method public int setStorageEncryption(android.content.ComponentName, boolean);
     method public void setSystemUpdatePolicy(android.content.ComponentName, android.app.admin.SystemUpdatePolicy);
     method public void setTrustAgentConfiguration(android.content.ComponentName, android.content.ComponentName, android.os.PersistableBundle);
@@ -8507,6 +8507,7 @@
     field public static final java.lang.String EXTRA_ALARM_COUNT = "android.intent.extra.ALARM_COUNT";
     field public static final java.lang.String EXTRA_ALLOW_MULTIPLE = "android.intent.extra.ALLOW_MULTIPLE";
     field public static final deprecated java.lang.String EXTRA_ALLOW_REPLACE = "android.intent.extra.ALLOW_REPLACE";
+    field public static final java.lang.String EXTRA_ALTERNATE_INTENTS = "android.intent.extra.ALTERNATE_INTENTS";
     field public static final java.lang.String EXTRA_ASSIST_CONTEXT = "android.intent.extra.ASSIST_CONTEXT";
     field public static final java.lang.String EXTRA_ASSIST_INPUT_HINT_KEYBOARD = "android.intent.extra.ASSIST_INPUT_HINT_KEYBOARD";
     field public static final java.lang.String EXTRA_ASSIST_PACKAGE = "android.intent.extra.ASSIST_PACKAGE";
@@ -8518,6 +8519,7 @@
     field public static final java.lang.String EXTRA_CHANGED_COMPONENT_NAME_LIST = "android.intent.extra.changed_component_name_list";
     field public static final java.lang.String EXTRA_CHANGED_PACKAGE_LIST = "android.intent.extra.changed_package_list";
     field public static final java.lang.String EXTRA_CHANGED_UID_LIST = "android.intent.extra.changed_uid_list";
+    field public static final java.lang.String EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER = "android.intent.extra.CHOOSER_REFINEMENT_INTENT_SENDER";
     field public static final java.lang.String EXTRA_CHOOSER_TARGETS = "android.intent.extra.CHOOSER_TARGETS";
     field public static final java.lang.String EXTRA_CHOSEN_COMPONENT = "android.intent.extra.CHOSEN_COMPONENT";
     field public static final java.lang.String EXTRA_CHOSEN_COMPONENT_INTENT_SENDER = "android.intent.extra.CHOSEN_COMPONENT_INTENT_SENDER";
@@ -8553,6 +8555,7 @@
     field public static final java.lang.String EXTRA_RESTRICTIONS_BUNDLE = "android.intent.extra.restrictions_bundle";
     field public static final java.lang.String EXTRA_RESTRICTIONS_INTENT = "android.intent.extra.restrictions_intent";
     field public static final java.lang.String EXTRA_RESTRICTIONS_LIST = "android.intent.extra.restrictions_list";
+    field public static final java.lang.String EXTRA_RESULT_RECEIVER = "android.intent.extra.RESULT_RECEIVER";
     field public static final java.lang.String EXTRA_RETURN_RESULT = "android.intent.extra.RETURN_RESULT";
     field public static final java.lang.String EXTRA_SHORTCUT_ICON = "android.intent.extra.shortcut.ICON";
     field public static final java.lang.String EXTRA_SHORTCUT_ICON_RESOURCE = "android.intent.extra.shortcut.ICON_RESOURCE";
@@ -18716,248 +18719,11 @@
 
 }
 
-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<android.media.routing.MediaRouteSelector> 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 {
     ctor public MediaController(android.content.Context, android.media.session.MediaSession.Token);
     method public void adjustVolume(int, int);
-    method public android.media.routing.MediaRouter.Delegate createMediaRouterDelegate();
     method public boolean dispatchMediaButtonEvent(android.view.KeyEvent);
     method public android.os.Bundle getExtras();
     method public long getFlags();
@@ -19031,7 +18797,6 @@
     method public void setExtras(android.os.Bundle);
     method public void setFlags(int);
     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);
@@ -32567,7 +32332,7 @@
     method public void handleCallSessionEvent(int);
     method public abstract void onRequestCameraCapabilities();
     method public abstract void onRequestConnectionDataUsage();
-    method public abstract void onSendSessionModifyRequest(android.telecom.VideoProfile);
+    method public abstract void onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile);
     method public abstract void onSendSessionModifyResponse(android.telecom.VideoProfile);
     method public abstract void onSetCamera(java.lang.String);
     method public abstract void onSetDeviceOrientation(int);
@@ -36397,14 +36162,6 @@
   }
 
   public deprecated class FloatMath {
-    method public static float ceil(float);
-    method public static float cos(float);
-    method public static float exp(float);
-    method public static float floor(float);
-    method public static float hypot(float, float);
-    method public static float pow(float, float);
-    method public static float sin(float);
-    method public static float sqrt(float);
   }
 
   public final class JsonReader implements java.io.Closeable {
@@ -38411,6 +38168,7 @@
     method public int getScrollBarFadeDuration();
     method public int getScrollBarSize();
     method public int getScrollBarStyle();
+    method public int getScrollIndicators();
     method public final int getScrollX();
     method public final int getScrollY();
     method public int getSolidColor();
@@ -38492,6 +38250,7 @@
     method public boolean isSaveEnabled();
     method public boolean isSaveFromParentEnabled();
     method public boolean isScrollContainer();
+    method public boolean isScrollIndicatorEnabled(int);
     method public boolean isScrollbarFadingEnabled();
     method public boolean isSelected();
     method public boolean isShown();
@@ -38691,6 +38450,8 @@
     method public void setScrollBarSize(int);
     method public void setScrollBarStyle(int);
     method public void setScrollContainer(boolean);
+    method public void setScrollIndicators(int);
+    method public void setScrollIndicators(int, int);
     method public void setScrollX(int);
     method public void setScrollY(int);
     method public void setScrollbarFadingEnabled(boolean);
@@ -38816,6 +38577,12 @@
     field public static final int SCROLL_AXIS_HORIZONTAL = 1; // 0x1
     field public static final int SCROLL_AXIS_NONE = 0; // 0x0
     field public static final int SCROLL_AXIS_VERTICAL = 2; // 0x2
+    field public static final int SCROLL_INDICATOR_BOTTOM = 2; // 0x2
+    field public static final int SCROLL_INDICATOR_END = 32; // 0x20
+    field public static final int SCROLL_INDICATOR_LEFT = 4; // 0x4
+    field public static final int SCROLL_INDICATOR_RIGHT = 8; // 0x8
+    field public static final int SCROLL_INDICATOR_START = 16; // 0x10
+    field public static final int SCROLL_INDICATOR_TOP = 1; // 0x1
     field protected static final int[] SELECTED_STATE_SET;
     field protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
     field public static final int SOUND_EFFECTS_ENABLED = 134217728; // 0x8000000
@@ -43169,6 +42936,7 @@
     method public void setSoftInputMode(int);
     method public void setVerticalOffset(int);
     method public void setWidth(int);
+    method public void setWindowLayoutType(int);
     method public void show();
     field public static final int INPUT_METHOD_FROM_FOCUSABLE = 0; // 0x0
     field public static final int INPUT_METHOD_NEEDED = 1; // 0x1
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 5e77e15..0046a70 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -108,6 +108,21 @@
 
 }
 
+package android.util {
+
+  public deprecated class FloatMath {
+    method public static float ceil(float);
+    method public static float cos(float);
+    method public static float exp(float);
+    method public static float floor(float);
+    method public static float hypot(float, float);
+    method public static float pow(float, float);
+    method public static float sin(float);
+    method public static float sqrt(float);
+  }
+
+}
+
 package android.view {
 
   public class View implements android.view.accessibility.AccessibilityEventSource android.graphics.drawable.Drawable.Callback android.view.KeyEvent.Callback {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 7260d102..9968dbb 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -89,7 +89,7 @@
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.MotionEvent;
-import android.view.PhoneWindow;
+import com.android.internal.policy.PhoneWindow;
 import android.view.SearchEvent;
 import android.view.View;
 import android.view.View.OnCreateContextMenuListener;
diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java
index 75e4bab..1174387 100644
--- a/core/java/android/app/Application.java
+++ b/core/java/android/app/Application.java
@@ -18,6 +18,7 @@
 
 import java.util.ArrayList;
 
+import android.annotation.CallSuper;
 import android.content.ComponentCallbacks;
 import android.content.ComponentCallbacks2;
 import android.content.Context;
@@ -89,6 +90,7 @@
      * service, or receiver in a process.
      * If you override this method, be sure to call super.onCreate().
      */
+    @CallSuper
     public void onCreate() {
     }
 
@@ -98,9 +100,11 @@
      * removed by simply killing them; no user code (including this callback)
      * is executed when doing so.
      */
+    @CallSuper
     public void onTerminate() {
     }
 
+    @CallSuper
     public void onConfigurationChanged(Configuration newConfig) {
         Object[] callbacks = collectComponentCallbacks();
         if (callbacks != null) {
@@ -110,6 +114,7 @@
         }
     }
 
+    @CallSuper
     public void onLowMemory() {
         Object[] callbacks = collectComponentCallbacks();
         if (callbacks != null) {
@@ -119,6 +124,7 @@
         }
     }
 
+    @CallSuper
     public void onTrimMemory(int level) {
         Object[] callbacks = collectComponentCallbacks();
         if (callbacks != null) {
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index d049104..f6e0e1e 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -48,7 +48,7 @@
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.MotionEvent;
-import android.view.PhoneWindow;
+import com.android.internal.policy.PhoneWindow;
 import android.view.SearchEvent;
 import android.view.View;
 import android.view.View.OnCreateContextMenuListener;
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 46da025..391131a 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -91,7 +91,6 @@
 import android.os.IUserManager;
 import android.os.PowerManager;
 import android.os.Process;
-import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemVibrator;
 import android.os.UserHandle;
@@ -111,7 +110,7 @@
 import android.util.Log;
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
-import android.view.PhoneLayoutInflater;
+import com.android.internal.policy.PhoneLayoutInflater;
 import android.view.WindowManager;
 import android.view.WindowManagerImpl;
 import android.view.accessibility.AccessibilityManager;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 4b72dc3..8009b6c 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -4294,14 +4294,14 @@
      * being disabled.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
-     * @param enabled New state of the keyguard.
+     * @param disabled {@code true} disables the keyguard, {@code false} reenables it.
      *
      * @return {@code false} if attempting to disable the keyguard while a lock password was in
-     * place. {@code true} otherwise."
+     * place. {@code true} otherwise.
      */
-    public boolean setKeyguardEnabledState(ComponentName admin, boolean enabled) {
+    public boolean setKeyguardDisabled(ComponentName admin, boolean disabled) {
         try {
-            return mService.setKeyguardEnabledState(admin, enabled);
+            return mService.setKeyguardDisabled(admin, disabled);
         } catch (RemoteException re) {
             Log.w(TAG, "Failed talking with device policy service", re);
             return false;
@@ -4309,18 +4309,22 @@
     }
 
     /**
-     * Called by device owner to set the enabled state of the status bar. Disabling the status
-     * bar blocks notifications, quick settings and other screen overlays that allow escaping from
+     * Called by device owner to disable the status bar. Disabling the status bar blocks
+     * notifications, quick settings and other screen overlays that allow escaping from
      * a single use device.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
-     * @param enabled New state of the status bar.
+     * @param disabled {@code true} disables the status bar, {@code false} reenables it.
+     *
+     * @return {@code false} if attempting to disable the status bar failed.
+     * {@code true} otherwise.
      */
-    public void setStatusBarEnabledState(ComponentName admin, boolean enabled) {
+    public boolean setStatusBarDisabled(ComponentName admin, boolean disabled) {
         try {
-            mService.setStatusBarEnabledState(admin, enabled);
+            return mService.setStatusBarDisabled(admin, disabled);
         } catch (RemoteException re) {
             Log.w(TAG, "Failed talking with device policy service", re);
+            return false;
         }
     }
 
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 833bc00..e81e7c1 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -224,8 +224,8 @@
     void setSystemUpdatePolicy(in ComponentName who, in PersistableBundle policy);
     PersistableBundle getSystemUpdatePolicy();
 
-    boolean setKeyguardEnabledState(in ComponentName admin, boolean enabled);
-    void setStatusBarEnabledState(in ComponentName who, boolean enabled);
+    boolean setKeyguardDisabled(in ComponentName admin, boolean disabled);
+    boolean setStatusBarDisabled(in ComponentName who, boolean disabled);
     boolean getDoNotAskCredentialsOnBoot();
 
     void notifyPendingSystemUpdate(in long updateReceivedTime);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 54fe786..d0298cd 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -17,6 +17,7 @@
 package android.content;
 
 import android.content.pm.ApplicationInfo;
+import android.os.ResultReceiver;
 import android.provider.MediaStore;
 import android.util.ArraySet;
 
@@ -3291,11 +3292,79 @@
 
     /**
      * An Intent describing the choices you would like shown with
-     * {@link #ACTION_PICK_ACTIVITY}.
+     * {@link #ACTION_PICK_ACTIVITY} or {@link #ACTION_CHOOSER}.
      */
     public static final String EXTRA_INTENT = "android.intent.extra.INTENT";
 
     /**
+     * An Intent[] describing additional, alternate choices you would like shown with
+     * {@link #ACTION_CHOOSER}.
+     *
+     * <p>An app may be capable of providing several different payload types to complete a
+     * user's intended action. For example, an app invoking {@link #ACTION_SEND} to share photos
+     * with another app may use EXTRA_ALTERNATE_INTENTS to have the chooser transparently offer
+     * several different supported sending mechanisms for sharing, such as the actual "image/*"
+     * photo data or a hosted link where the photos can be viewed.</p>
+     *
+     * <p>The intent present in {@link #EXTRA_INTENT} will be treated as the
+     * first/primary/preferred intent in the set. Additional intents specified in
+     * this extra are ordered; by default intents that appear earlier in the array will be
+     * preferred over intents that appear later in the array as matches for the same
+     * target component. To alter this preference, a calling app may also supply
+     * {@link #EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER}.</p>
+     */
+    public static final String EXTRA_ALTERNATE_INTENTS = "android.intent.extra.ALTERNATE_INTENTS";
+
+    /**
+     * An {@link IntentSender} for an Activity that will be invoked when the user makes a selection
+     * from the chooser activity presented by {@link #ACTION_CHOOSER}.
+     *
+     * <p>An app preparing an action for another app to complete may wish to allow the user to
+     * disambiguate between several options for completing the action based on the chosen target
+     * or otherwise refine the action before it is invoked.
+     * </p>
+     *
+     * <p>When sent, this IntentSender may be filled in with the following extras:</p>
+     * <ul>
+     *     <li>{@link #EXTRA_INTENT} The first intent that matched the user's chosen target</li>
+     *     <li>{@link #EXTRA_ALTERNATE_INTENTS} Any additional intents that also matched the user's
+     *     chosen target beyond the first</li>
+     *     <li>{@link #EXTRA_RESULT_RECEIVER} A {@link ResultReceiver} that the refinement activity
+     *     should fill in and send once the disambiguation is complete</li>
+     * </ul>
+     */
+    public static final String EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER
+            = "android.intent.extra.CHOOSER_REFINEMENT_INTENT_SENDER";
+
+    /**
+     * A {@link ResultReceiver} used to return data back to the sender.
+     *
+     * <p>Used to complete an app-specific
+     * {@link #EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER refinement} for {@link #ACTION_CHOOSER}.</p>
+     *
+     * <p>If {@link #EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER} is present in the intent
+     * used to start a {@link #ACTION_CHOOSER} activity this extra will be
+     * {@link #fillIn(Intent, int) filled in} to that {@link IntentSender} and sent
+     * when the user selects a target component from the chooser. It is up to the recipient
+     * to send a result to this ResultReceiver to signal that disambiguation is complete
+     * and that the chooser should invoke the user's choice.</p>
+     *
+     * <p>The disambiguator should provide a Bundle to the ResultReceiver with an intent
+     * assigned to the key {@link #EXTRA_INTENT}. This supplied intent will be used by the chooser
+     * to match and fill in the final Intent or ChooserTarget before starting it.
+     * The supplied intent must {@link #filterEquals(Intent) match} one of the intents from
+     * {@link #EXTRA_INTENT} or {@link #EXTRA_ALTERNATE_INTENTS} passed to
+     * {@link #EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER} to be accepted.</p>
+     *
+     * <p>The result code passed to the ResultReceiver should be
+     * {@link android.app.Activity#RESULT_OK} if the refinement succeeded and the supplied intent's
+     * target in the chooser should be started, or {@link android.app.Activity#RESULT_CANCELED} if
+     * the chooser should finish without starting a target.</p>
+     */
+    public static final String EXTRA_RESULT_RECEIVER
+            = "android.intent.extra.RESULT_RECEIVER";
+
+    /**
      * A CharSequence dialog title to provide to the user when used with a
      * {@link #ACTION_CHOOSER}.
      */
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index a4d6be09..691798f 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -326,9 +326,6 @@
         }
 
         try {
-            startPreview(); // If preview is not running (i.e. after a JPEG capture), we need to
-                            // explicitely start and stop preview before setting preview surface.
-                            // null.
             stopPreview();
         }  catch (RuntimeException e) {
             Log.e(TAG, "Received device exception in configure call: ", e);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 293cf6f..a7af838 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -324,23 +324,7 @@
             "android.settings.BLUETOOTH_SETTINGS";
 
     /**
-     * Activity Action: Show settings to allow configuration of Wifi Displays.
-     * <p>
-     * In some cases, a matching Activity may not exist, so ensure you
-     * safeguard against this.
-     * <p>
-     * Input: Nothing.
-     * <p>
-     * Output: Nothing.
-     * @hide
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ACTION_WIFI_DISPLAY_SETTINGS =
-            "android.settings.WIFI_DISPLAY_SETTINGS";
-
-    /**
-     * Activity Action: Show settings to allow configuration of
-     * {@link android.media.routing.MediaRouteService media route providers}.
+     * Activity Action: Show settings to allow configuration of cast endpoints.
      * <p>
      * In some cases, a matching Activity may not exist, so ensure you
      * safeguard against this.
@@ -5951,6 +5935,12 @@
                 "wireless_charging_started_sound";
 
         /**
+         * Whether to play a sound for charging events.
+         * @hide
+         */
+        public static final String CHARGING_SOUNDS_ENABLED = "charging_sounds_enabled";
+
+        /**
          * Whether we keep the device on while the device is plugged in.
          * Supported values are:
          * <ul>
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 29aaf30..0171869 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -40,7 +40,7 @@
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.MotionEvent;
-import android.view.PhoneWindow;
+import com.android.internal.policy.PhoneWindow;
 import android.view.SearchEvent;
 import android.view.View;
 import android.view.ViewGroup;
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 451abea..59c7c6d 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -91,6 +91,7 @@
             b.mEllipsizedWidth = width;
             b.mEllipsize = null;
             b.mMaxLines = Integer.MAX_VALUE;
+            b.mBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE;
 
             b.mMeasuredText = MeasuredText.obtain();
             return b;
@@ -100,6 +101,8 @@
             b.mPaint = null;
             b.mText = null;
             MeasuredText.recycle(b.mMeasuredText);
+            b.mMeasuredText = null;
+            nFinishBuilder(b.mNativePtr);
             sPool.release(b);
         }
 
diff --git a/core/java/android/util/FloatMath.java b/core/java/android/util/FloatMath.java
index 8f488af..bb7d15f 100644
--- a/core/java/android/util/FloatMath.java
+++ b/core/java/android/util/FloatMath.java
@@ -25,6 +25,8 @@
  * {@link java.lang.Math}. {@link java.lang.Math} should be used in
  * preference.
  *
+ * <p>All methods were removed from the public API in version 23.
+ *
  * @deprecated Use {@link java.lang.Math} instead.
  */
 @Deprecated
@@ -39,6 +41,7 @@
      *
      * @param value to be converted
      * @return the floor of value
+     * @removed
      */
     public static float floor(float value) {
         return (float) Math.floor(value);
@@ -50,6 +53,7 @@
      *
      * @param value to be converted
      * @return the ceiling of value
+     * @removed
      */
     public static float ceil(float value) {
         return (float) Math.ceil(value);
@@ -60,6 +64,7 @@
      *
      * @param angle to compute the cosine of, in radians
      * @return the sine of angle
+     * @removed
      */
     public static float sin(float angle) {
         return (float) Math.sin(angle);
@@ -70,6 +75,7 @@
      *
      * @param angle to compute the cosine of, in radians
      * @return the cosine of angle
+     * @removed
      */
     public static float cos(float angle) {
         return (float) Math.cos(angle);
@@ -81,6 +87,7 @@
      *
      * @param value to compute sqrt of
      * @return the square root of value
+     * @removed
      */
     public static float sqrt(float value) {
         return (float) Math.sqrt(value);
@@ -92,6 +99,7 @@
      *
      * @param value to compute the exponential of
      * @return the exponential of value
+     * @removed
      */
     public static float exp(float value) {
         return (float) Math.exp(value);
@@ -104,6 +112,7 @@
      * @param x the base of the operation.
      * @param y the exponent of the operation.
      * @return {@code x} to the power of {@code y}.
+     * @removed
      */
     public static float pow(float x, float y) {
         return (float) Math.pow(x, y);
@@ -116,6 +125,7 @@
      * @param x a float number
      * @param y a float number
      * @return the hypotenuse
+     * @removed
      */
     public static float hypot(float x, float y) {
         return (float) Math.hypot(x, y);
diff --git a/core/java/android/view/GhostView.java b/core/java/android/view/GhostView.java
index bc38e1a..9f46f45 100644
--- a/core/java/android/view/GhostView.java
+++ b/core/java/android/view/GhostView.java
@@ -40,8 +40,7 @@
         mView.mGhostView = this;
         final ViewGroup parent = (ViewGroup) mView.getParent();
         setGhostedVisibility(View.INVISIBLE);
-        parent.mRecreateDisplayList = true;
-        parent.updateDisplayListIfDirty();
+        parent.invalidate();
     }
 
     @Override
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 75dc0a2..f62e6a2 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2395,10 +2395,143 @@
      */
     static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
 
+    /**
+     * Flag indicating that the bottom scroll indicator should be displayed
+     * when this view can scroll up.
+     */
+    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
+
+    /**
+     * Flag indicating that the bottom scroll indicator should be displayed
+     * when this view can scroll down.
+     */
+    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
+
+    /**
+     * Flag indicating that the left scroll indicator should be displayed
+     * when this view can scroll left.
+     */
+    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
+
+    /**
+     * Flag indicating that the right scroll indicator should be displayed
+     * when this view can scroll right.
+     */
+    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
+
+    /**
+     * Flag indicating that the start scroll indicator should be displayed
+     * when this view can scroll in the start direction.
+     */
+    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
+
+    /**
+     * Flag indicating that the end scroll indicator should be displayed
+     * when this view can scroll in the end direction.
+     */
+    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
+
     /* End of masks for mPrivateFlags3 */
 
     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
 
+    static final int SCROLL_INDICATORS_NONE = 0x0000;
+
+    /**
+     * Mask for use with setFlags indicating bits used for indicating which
+     * scroll indicators are enabled.
+     */
+    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
+            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
+            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
+            | PFLAG3_SCROLL_INDICATOR_END;
+
+    /**
+     * Left-shift required to translate between public scroll indicator flags
+     * and internal PFLAGS3 flags. When used as a right-shift, translates
+     * PFLAGS3 flags to public flags.
+     */
+    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(flag = true,
+            value = {
+                    SCROLL_INDICATOR_TOP,
+                    SCROLL_INDICATOR_BOTTOM,
+                    SCROLL_INDICATOR_LEFT,
+                    SCROLL_INDICATOR_RIGHT,
+                    SCROLL_INDICATOR_START,
+                    SCROLL_INDICATOR_END,
+            })
+    public @interface ScrollIndicators {}
+
+    /**
+     * Scroll indicator direction for the top edge of the view.
+     *
+     * @see #setScrollIndicators(int)
+     * @see #setScrollIndicators(int, int)
+     * @see #getScrollIndicators()
+     */
+    public static final int SCROLL_INDICATOR_TOP =
+            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
+
+    /**
+     * Scroll indicator direction for the bottom edge of the view.
+     *
+     * @see #setScrollIndicators(int)
+     * @see #setScrollIndicators(int, int)
+     * @see #getScrollIndicators()
+     */
+    public static final int SCROLL_INDICATOR_BOTTOM =
+            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
+
+    /**
+     * Scroll indicator direction for the left edge of the view.
+     *
+     * @see #setScrollIndicators(int)
+     * @see #setScrollIndicators(int, int)
+     * @see #getScrollIndicators()
+     */
+    public static final int SCROLL_INDICATOR_LEFT =
+            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
+
+    /**
+     * Scroll indicator direction for the right edge of the view.
+     *
+     * @see #setScrollIndicators(int)
+     * @see #setScrollIndicators(int, int)
+     * @see #getScrollIndicators()
+     */
+    public static final int SCROLL_INDICATOR_RIGHT =
+            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
+
+    /**
+     * Scroll indicator direction for the starting edge of the view.
+     * <p>
+     * Resolved according to the view's layout direction, see
+     * {@link #getLayoutDirection()} for more information.
+     *
+     * @see #setScrollIndicators(int)
+     * @see #setScrollIndicators(int, int)
+     * @see #getScrollIndicators()
+     */
+    public static final int SCROLL_INDICATOR_START =
+            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
+
+    /**
+     * Scroll indicator direction for the ending edge of the view.
+     * <p>
+     * Resolved according to the view's layout direction, see
+     * {@link #getLayoutDirection()} for more information.
+     *
+     * @see #setScrollIndicators(int)
+     * @see #setScrollIndicators(int, int)
+     * @see #getScrollIndicators()
+     */
+    public static final int SCROLL_INDICATOR_END =
+            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
+
     /**
      * <p>Indicates that we are allowing {@link android.view.ViewAssistStructure} to traverse
      * into this view.<p>
@@ -3217,6 +3350,8 @@
     @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
     private ForegroundInfo mForegroundInfo;
 
+    private Drawable mScrollIndicatorDrawable;
+
     /**
      * RenderNode used for backgrounds.
      * <p>
@@ -3769,6 +3904,7 @@
         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
         int overScrollMode = mOverScrollMode;
         boolean initializeScrollbars = false;
+        boolean initializeScrollIndicators = false;
 
         boolean startPaddingDefined = false;
         boolean endPaddingDefined = false;
@@ -4135,6 +4271,14 @@
                     }
                     mForegroundInfo.mInsidePadding = a.getBoolean(attr,
                             mForegroundInfo.mInsidePadding);
+                case R.styleable.View_scrollIndicators:
+                    final int scrollIndicators =
+                            a.getInt(attr, SCROLL_INDICATORS_NONE) & SCROLL_INDICATORS_PFLAG3_MASK;
+                    if (scrollIndicators != 0) {
+                        viewFlagValues |= scrollIndicators;
+                        viewFlagMasks |= SCROLL_INDICATORS_PFLAG3_MASK;
+                        initializeScrollIndicators = true;
+                    }
                     break;
             }
         }
@@ -4211,6 +4355,10 @@
             initializeScrollbarsInternal(a);
         }
 
+        if (initializeScrollIndicators) {
+            initializeScrollIndicatorsInternal();
+        }
+
         a.recycle();
 
         // Needs to be called after mViewFlags is set
@@ -4682,6 +4830,15 @@
         resolvePadding();
     }
 
+    private void initializeScrollIndicatorsInternal() {
+        // Some day maybe we'll break this into top/left/start/etc. and let the
+        // client control it. Until then, you can have any scroll indicator you
+        // want as long as it's a 1dp foreground-colored rectangle.
+        if (mScrollIndicatorDrawable == null) {
+            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
+        }
+    }
+
     /**
      * <p>
      * Initalizes the scrollability cache if necessary.
@@ -4721,6 +4878,118 @@
         return mVerticalScrollbarPosition;
     }
 
+    /**
+     * Sets the state of all scroll indicators.
+     * <p>
+     * See {@link #setScrollIndicators(int, int)} for usage information.
+     *
+     * @param indicators a bitmask of indicators that should be enabled, or
+     *                   {@code 0} to disable all indicators
+     * @see #setScrollIndicators(int, int)
+     * @see #getScrollIndicators()
+     * @attr ref android.R.styleable#View_scrollIndicators
+     */
+    public void setScrollIndicators(@ScrollIndicators int indicators) {
+        setScrollIndicators(indicators, SCROLL_INDICATORS_PFLAG3_MASK);
+    }
+
+    /**
+     * Sets the state of the scroll indicators specified by the mask. To change
+     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
+     * <p>
+     * When a scroll indicator is enabled, it will be displayed if the view
+     * can scroll in the direction of the indicator.
+     * <p>
+     * Multiple indicator types may be enabled or disabled by passing the
+     * logical OR of the desired types. If multiple types are specified, they
+     * will all be set to the same enabled state.
+     * <p>
+     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
+     *
+     * @param indicators the indicator direction, or the logical OR of multiple
+     *             indicator directions. One or more of:
+     *             <ul>
+     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
+     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
+     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
+     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
+     *               <li>{@link #SCROLL_INDICATOR_START}</li>
+     *               <li>{@link #SCROLL_INDICATOR_END}</li>
+     *             </ul>
+     * @see #setScrollIndicators(int)
+     * @see #getScrollIndicators()
+     * @attr ref android.R.styleable#View_scrollIndicators
+     */
+    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
+        // Shift and sanitize mask.
+        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
+        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
+
+        // Shift and mask indicators.
+        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
+        indicators &= mask;
+
+        // Merge with non-masked flags.
+        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
+
+        if (mPrivateFlags3 != updatedFlags) {
+            mPrivateFlags3 = updatedFlags;
+
+            if (indicators != 0) {
+                initializeScrollIndicatorsInternal();
+            }
+            invalidate();
+        }
+    }
+
+    /**
+     * Returns a bitmask representing the enabled scroll indicators.
+     * <p>
+     * For example, if the top and left scroll indicators are enabled and all
+     * other indicators are disabled, the return value will be
+     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
+     * <p>
+     * To check whether the bottom scroll indicator is enabled, use the value
+     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
+     *
+     * @return a bitmask representing the enabled scroll indicators
+     */
+    @ScrollIndicators
+    public int getScrollIndicators() {
+        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
+                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
+    }
+
+    /**
+     * Returns whether the specified scroll indicator is enabled.
+     * <p>
+     * Multiple indicator types may be queried by passing the logical OR of the
+     * desired types. If multiple types are specified, the return value
+     * represents whether they are all enabled.
+     *
+     * @param direction the indicator direction, or the logical OR of multiple
+     *             indicator directions. One or more of:
+     *             <ul>
+     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
+     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
+     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
+     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
+     *               <li>{@link #SCROLL_INDICATOR_START}</li>
+     *               <li>{@link #SCROLL_INDICATOR_END}</li>
+     *             </ul>
+     * @return {@code true} if the specified indicator(s) are enabled,
+     *         {@code false} otherwise
+     * @attr ref android.R.styleable#View_scrollIndicators
+     */
+    public boolean isScrollIndicatorEnabled(int direction) {
+        // Shift and sanitize input.
+        direction <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
+        direction &= SCROLL_INDICATORS_PFLAG3_MASK;
+
+        // All of the flags must be set.
+        return (mPrivateFlags3 & direction) == direction;
+    }
+
     ListenerInfo getListenerInfo() {
         if (mListenerInfo != null) {
             return mListenerInfo;
@@ -13444,6 +13713,75 @@
         }
     }
 
+    void getScrollIndicatorBounds(@NonNull Rect out) {
+        out.left = mScrollX;
+        out.right = mScrollX + mRight - mLeft;
+        out.top = mScrollY;
+        out.bottom = mScrollY + mBottom - mTop;
+    }
+
+    private void onDrawScrollIndicators(Canvas c) {
+        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
+            // No scroll indicators enabled.
+            return;
+        }
+
+        final Drawable dr = mScrollIndicatorDrawable;
+        if (dr == null) {
+            // Scroll indicators aren't supported here.
+            return;
+        }
+
+        final int h = dr.getIntrinsicHeight();
+        final int w = dr.getIntrinsicWidth();
+        final Rect rect = mAttachInfo.mTmpInvalRect;
+        getScrollIndicatorBounds(rect);
+
+        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
+            final boolean canScrollUp = canScrollVertically(-1);
+            if (canScrollUp) {
+                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
+                dr.draw(c);
+            }
+        }
+
+        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
+            final boolean canScrollDown = canScrollVertically(1);
+            if (canScrollDown) {
+                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
+                dr.draw(c);
+            }
+        }
+
+        final int leftRtl;
+        final int rightRtl;
+        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
+            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
+            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
+        } else {
+            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
+            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
+        }
+
+        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
+        if ((mPrivateFlags3 & leftMask) != 0) {
+            final boolean canScrollLeft = canScrollHorizontally(-1);
+            if (canScrollLeft) {
+                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
+                dr.draw(c);
+            }
+        }
+
+        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
+        if ((mPrivateFlags3 & rightMask) != 0) {
+            final boolean canScrollRight = canScrollHorizontally(1);
+            if (canScrollRight) {
+                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
+                dr.draw(c);
+            }
+        }
+    }
+
     /**
      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
      * scrollbars are painted only if they have been awakened first.</p>
@@ -17272,6 +17610,7 @@
      * @param canvas canvas to draw into
      */
     public void onDrawForeground(Canvas canvas) {
+        onDrawScrollIndicators(canvas);
         onDrawScrollBars(canvas);
 
         final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index f240fd6..babb4e9 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -18,6 +18,7 @@
 
 import android.animation.LayoutTransition;
 import android.annotation.IdRes;
+import android.annotation.NonNull;
 import android.annotation.UiThread;
 import android.content.Context;
 import android.content.Intent;
@@ -3547,6 +3548,21 @@
         return child.draw(canvas, this, drawingTime);
     }
 
+    @Override
+    void getScrollIndicatorBounds(@NonNull Rect out) {
+        super.getScrollIndicatorBounds(out);
+
+        // If we have padding and we're supposed to clip children to that
+        // padding, offset the scroll indicators to match our clip bounds.
+        final boolean clipToPadding = (mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK;
+        if (clipToPadding) {
+            out.left += mPaddingLeft;
+            out.right -= mPaddingRight;
+            out.top += mPaddingTop;
+            out.bottom -= mPaddingBottom;
+        }
+    }
+
     /**
      * Returns whether this group's children are clipped to their bounds before drawing.
      * The default value is true.
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index fda6e63..c9c2a82 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -76,6 +76,7 @@
 
 import com.android.internal.R;
 import com.android.internal.os.SomeArgs;
+import com.android.internal.policy.PhoneFallbackEventHandler;
 import com.android.internal.util.ScreenShapeHelper;
 import com.android.internal.view.BaseSurfaceHolder;
 import com.android.internal.view.RootViewSurfaceTaker;
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 78604bf..040fd37 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -247,6 +247,13 @@
     /** @hide */
     public static final int DISPATCH_HANDLED = 1;
 
+    /** @hide */
+    public static final int SHOW_IM_PICKER_MODE_AUTO = 0;
+    /** @hide */
+    public static final int SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES = 1;
+    /** @hide */
+    public static final int SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES = 2;
+
     final IInputMethodManager mService;
     final Looper mMainLooper;
     
@@ -1890,9 +1897,28 @@
         }
     }
 
+    /**
+     * Shows the input method chooser dialog.
+     *
+     * @param showAuxiliarySubtypes Set true to show auxiliary input methods.
+     * @hide
+     */
+    public void showInputMethodPicker(boolean showAuxiliarySubtypes) {
+        synchronized (mH) {
+            try {
+                final int mode = showAuxiliarySubtypes ?
+                        SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES:
+                        SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES;
+                mService.showInputMethodPickerFromClient(mClient, mode);
+            } catch (RemoteException e) {
+                Log.w(TAG, "IME died: " + mCurId, e);
+            }
+        }
+    }
+
     private void showInputMethodPickerLocked() {
         try {
-            mService.showInputMethodPickerFromClient(mClient);
+            mService.showInputMethodPickerFromClient(mClient, SHOW_IM_PICKER_MODE_AUTO);
         } catch (RemoteException e) {
             Log.w(TAG, "IME died: " + mCurId, e);
         }
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 8d35b83..712fdba 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -2421,7 +2421,8 @@
         public PinnedPopupWindow() {
             createPopupWindow();
 
-            mPopupWindow.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL);
+            mPopupWindow.setWindowLayoutType(
+                    WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL);
             mPopupWindow.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
             mPopupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
 
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 310412f9..05866f0 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -39,6 +39,7 @@
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.ViewParent;
+import android.view.WindowManager;
 import android.view.animation.AccelerateDecelerateInterpolator;
 
 import com.android.internal.R;
@@ -77,6 +78,7 @@
     private int mDropDownWidth = ViewGroup.LayoutParams.WRAP_CONTENT;
     private int mDropDownHorizontalOffset;
     private int mDropDownVerticalOffset;
+    private int mDropDownWindowLayoutType = WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
     private boolean mDropDownVerticalOffsetSet;
 
     private int mDropDownGravity = Gravity.NO_GRAVITY;
@@ -515,6 +517,19 @@
     }
 
     /**
+     * Set the layout type for this popup window.
+     * <p>
+     * See {@link WindowManager.LayoutParams#type} for possible values.
+     *
+     * @param layoutType Layout type for this window.
+     *
+     * @see WindowManager.LayoutParams#type
+     */
+    public void setWindowLayoutType(int layoutType) {
+        mDropDownWindowLayoutType = layoutType;
+    }
+
+    /**
      * Sets a listener to receive events when a list item is clicked.
      * 
      * @param clickListener Listener to register
@@ -567,8 +582,9 @@
     public void show() {
         int height = buildDropDown();
 
-        boolean noInputMethod = isInputMethodNotNeeded();
+        final boolean noInputMethod = isInputMethodNotNeeded();
         mPopup.setAllowScrollingAnchorParent(!noInputMethod);
+        mPopup.setWindowLayoutType(mDropDownWindowLayoutType);
 
         if (mPopup.isShowing()) {
             final int widthSpec;
diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java
index 8d8b3a3..97348e30 100644
--- a/core/java/android/widget/MediaController.java
+++ b/core/java/android/widget/MediaController.java
@@ -28,7 +28,7 @@
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
-import android.view.PhoneWindow;
+import com.android.internal.policy.PhoneWindow;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.Window;
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index c3ac278..b4cbf35 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -829,9 +829,9 @@
     }
 
     /**
-     * Set the layout type for this window. This value will be passed through to
-     * {@link WindowManager.LayoutParams#type} therefore the value should match any value
-     * {@link WindowManager.LayoutParams#type} accepts.
+     * Set the layout type for this window.
+     * <p>
+     * See {@link WindowManager.LayoutParams#type} for possible values.
      *
      * @param layoutType Layout type for this window.
      *
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index b8110e3..61ee00c 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -526,11 +526,15 @@
             mWindow.setCloseOnTouchOutsideIfNotSet(true);
         }
 
-        // Only display the divider if we have a title and a custom view or a
-        // message.
         if (hasTopPanel) {
+            // Only clip scrolling content to padding if we have a title.
+            if (mScrollView != null) {
+                mScrollView.setClipToPadding(true);
+            }
+
+            // Only show the divider if we have a title.
             final View divider;
-            if (mMessage != null || hasCustomPanel || mListView != null) {
+            if (mMessage != null || mListView != null || hasCustomPanel) {
                 divider = topPanel.findViewById(R.id.titleDivider);
             } else {
                 divider = topPanel.findViewById(R.id.titleDividerTop);
@@ -541,6 +545,17 @@
             }
         }
 
+        // Update scroll indicators as needed.
+        if (!hasCustomPanel) {
+            final View content = mListView != null ? mListView : mScrollView;
+            if (content != null) {
+                final int indicators = (hasTopPanel ? View.SCROLL_INDICATOR_TOP : 0)
+                        | (hasButtonPanel ? View.SCROLL_INDICATOR_BOTTOM : 0);
+                content.setScrollIndicators(indicators,
+                        View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_BOTTOM);
+            }
+        }
+
         final TypedArray a = mContext.obtainStyledAttributes(
                 null, R.styleable.AlertDialog, R.attr.alertDialogStyle, 0);
         setBackground(a, topPanel, contentPanel, customPanel, buttonPanel,
@@ -654,59 +669,6 @@
                 contentPanel.setVisibility(View.GONE);
             }
         }
-
-        // Set up scroll indicators (if present).
-        final View indicatorUp = contentPanel.findViewById(R.id.scrollIndicatorUp);
-        final View indicatorDown = contentPanel.findViewById(R.id.scrollIndicatorDown);
-        if (indicatorUp != null || indicatorDown != null) {
-            if (mMessage != null) {
-                // We're just showing the ScrollView, set up listener.
-                mScrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
-                        @Override
-                        public void onScrollChange(View v, int scrollX, int scrollY,
-                                int oldScrollX, int oldScrollY) {
-                            manageScrollIndicators(v, indicatorUp, indicatorDown);
-                        }
-                    });
-                // Set up the indicators following layout.
-                mScrollView.post(new Runnable() {
-                     @Override
-                     public void run() {
-                             manageScrollIndicators(mScrollView, indicatorUp, indicatorDown);
-                         }
-                     });
-
-            } else if (mListView != null) {
-                // We're just showing the AbsListView, set up listener.
-                mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
-                        @Override
-                        public void onScrollStateChanged(AbsListView view, int scrollState) {
-                            // That's cool, I guess?
-                        }
-
-                        @Override
-                        public void onScroll(AbsListView v, int firstVisibleItem,
-                                int visibleItemCount, int totalItemCount) {
-                            manageScrollIndicators(v, indicatorUp, indicatorDown);
-                        }
-                    });
-                // Set up the indicators following layout.
-                mListView.post(new Runnable() {
-                        @Override
-                        public void run() {
-                            manageScrollIndicators(mListView, indicatorUp, indicatorDown);
-                        }
-                    });
-            } else {
-                // We don't have any content to scroll, remove the indicators.
-                if (indicatorUp != null) {
-                    contentPanel.removeView(indicatorUp);
-                }
-                if (indicatorDown != null) {
-                    contentPanel.removeView(indicatorDown);
-                }
-            }
-        }
     }
 
     private static void manageScrollIndicators(View v, View upIndicator, View downIndicator) {
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index e347faa..62ca1f0 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
+import android.content.IntentSender.SendIntentException;
 import android.content.ServiceConnection;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
@@ -34,6 +35,7 @@
 import android.os.Message;
 import android.os.Parcelable;
 import android.os.RemoteException;
+import android.os.ResultReceiver;
 import android.os.UserHandle;
 import android.service.chooser.ChooserTarget;
 import android.service.chooser.ChooserTargetService;
@@ -53,11 +55,13 @@
 
     private static final boolean DEBUG = false;
 
-    private static final int QUERY_TARGET_LIMIT = 5;
+    private static final int QUERY_TARGET_SERVICE_LIMIT = 5;
     private static final int WATCHDOG_TIMEOUT_MILLIS = 5000;
 
     private Bundle mReplacementExtras;
     private IntentSender mChosenComponentSender;
+    private IntentSender mRefinementIntentSender;
+    private RefinementResultReceiver mRefinementResultReceiver;
 
     private ChooserTarget[] mCallerChooserTargets;
 
@@ -113,6 +117,32 @@
         if (target != null) {
             modifyTargetIntent(target);
         }
+        Parcelable[] targetsParcelable
+                = intent.getParcelableArrayExtra(Intent.EXTRA_ALTERNATE_INTENTS);
+        if (targetsParcelable != null) {
+            final boolean offset = target == null;
+            Intent[] additionalTargets =
+                    new Intent[offset ? targetsParcelable.length - 1 : targetsParcelable.length];
+            for (int i = 0; i < targetsParcelable.length; i++) {
+                if (!(targetsParcelable[i] instanceof Intent)) {
+                    Log.w(TAG, "EXTRA_ALTERNATE_INTENTS array entry #" + i + " is not an Intent: "
+                            + targetsParcelable[i]);
+                    finish();
+                    super.onCreate(null);
+                    return;
+                }
+                final Intent additionalTarget = (Intent) targetsParcelable[i];
+                if (i == 0 && target == null) {
+                    target = additionalTarget;
+                    modifyTargetIntent(target);
+                } else {
+                    additionalTargets[offset ? i - 1 : i] = additionalTarget;
+                    modifyTargetIntent(additionalTarget);
+                }
+            }
+            setAdditionalTargets(additionalTargets);
+        }
+
         mReplacementExtras = intent.getBundleExtra(Intent.EXTRA_REPLACEMENT_EXTRAS);
         CharSequence title = intent.getCharSequenceExtra(Intent.EXTRA_TITLE);
         int defaultTitleRes = 0;
@@ -125,7 +155,7 @@
             initialIntents = new Intent[pa.length];
             for (int i=0; i<pa.length; i++) {
                 if (!(pa[i] instanceof Intent)) {
-                    Log.w("ChooserActivity", "Initial intent #" + i + " not an Intent: " + pa[i]);
+                    Log.w(TAG, "Initial intent #" + i + " not an Intent: " + pa[i]);
                     finish();
                     super.onCreate(null);
                     return;
@@ -141,8 +171,7 @@
             final ChooserTarget[] targets = new ChooserTarget[pa.length];
             for (int i = 0; i < pa.length; i++) {
                 if (!(pa[i] instanceof ChooserTarget)) {
-                    Log.w("ChooserActivity", "Chooser target #" + i + " is not a ChooserTarget: " +
-                            pa[i]);
+                    Log.w(TAG, "Chooser target #" + i + " is not a ChooserTarget: " + pa[i]);
                     finish();
                     super.onCreate(null);
                     return;
@@ -153,12 +182,23 @@
         }
         mChosenComponentSender = intent.getParcelableExtra(
                 Intent.EXTRA_CHOSEN_COMPONENT_INTENT_SENDER);
+        mRefinementIntentSender = intent.getParcelableExtra(
+                Intent.EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER);
         setSafeForwardingMode(true);
         super.onCreate(savedInstanceState, target, title, defaultTitleRes, initialIntents,
                 null, false);
     }
 
     @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        if (mRefinementResultReceiver != null) {
+            mRefinementResultReceiver.destroy();
+            mRefinementResultReceiver = null;
+        }
+    }
+
+    @Override
     public Intent getReplacementIntent(ActivityInfo aInfo, Intent defIntent) {
         Intent result = defIntent;
         if (mReplacementExtras != null) {
@@ -211,6 +251,37 @@
         }
     }
 
+    @Override
+    protected boolean onTargetSelected(TargetInfo target, boolean alwaysCheck) {
+        if (mRefinementIntentSender != null) {
+            final Intent fillIn = new Intent();
+            final List<Intent> sourceIntents = target.getAllSourceIntents();
+            if (!sourceIntents.isEmpty()) {
+                fillIn.putExtra(Intent.EXTRA_INTENT, sourceIntents.get(0));
+                if (sourceIntents.size() > 1) {
+                    final Intent[] alts = new Intent[sourceIntents.size() - 1];
+                    for (int i = 1, N = sourceIntents.size(); i < N; i++) {
+                        alts[i - 1] = sourceIntents.get(i);
+                    }
+                    fillIn.putExtra(Intent.EXTRA_ALTERNATE_INTENTS, alts);
+                }
+                if (mRefinementResultReceiver != null) {
+                    mRefinementResultReceiver.destroy();
+                }
+                mRefinementResultReceiver = new RefinementResultReceiver(this, target, null);
+                fillIn.putExtra(Intent.EXTRA_RESULT_RECEIVER,
+                        mRefinementResultReceiver);
+                try {
+                    mRefinementIntentSender.sendIntent(this, 0, fillIn, null, null);
+                    return false;
+                } catch (SendIntentException e) {
+                    Log.e(TAG, "Refinement IntentSender failed to send", e);
+                }
+            }
+        }
+        return super.onTargetSelected(target, alwaysCheck);
+    }
+
     void queryTargetServices(ChooserListAdapter adapter) {
         final PackageManager pm = getPackageManager();
         int targetsToQuery = 0;
@@ -258,8 +329,9 @@
                     targetsToQuery++;
                 }
             }
-            if (targetsToQuery >= QUERY_TARGET_LIMIT) {
-                if (DEBUG) Log.d(TAG, "queryTargets hit query target limit " + QUERY_TARGET_LIMIT);
+            if (targetsToQuery >= QUERY_TARGET_SERVICE_LIMIT) {
+                if (DEBUG) Log.d(TAG, "queryTargets hit query target limit "
+                        + QUERY_TARGET_SERVICE_LIMIT);
                 break;
             }
         }
@@ -303,6 +375,43 @@
         mTargetResultHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT);
     }
 
+    void onRefinementResult(TargetInfo selectedTarget, Intent matchingIntent) {
+        if (mRefinementResultReceiver != null) {
+            mRefinementResultReceiver.destroy();
+            mRefinementResultReceiver = null;
+        }
+
+        if (selectedTarget == null) {
+            Log.e(TAG, "Refinement result intent did not match any known targets; canceling");
+        } else if (!checkTargetSourceIntent(selectedTarget, matchingIntent)) {
+            Log.e(TAG, "onRefinementResult: Selected target " + selectedTarget
+                    + " cannot match refined source intent " + matchingIntent);
+        } else if (super.onTargetSelected(selectedTarget.cloneFilledIn(matchingIntent, 0), false)) {
+            finish();
+            return;
+        }
+        onRefinementCanceled();
+    }
+
+    void onRefinementCanceled() {
+        if (mRefinementResultReceiver != null) {
+            mRefinementResultReceiver.destroy();
+            mRefinementResultReceiver = null;
+        }
+        finish();
+    }
+
+    boolean checkTargetSourceIntent(TargetInfo target, Intent matchingIntent) {
+        final List<Intent> targetIntents = target.getAllSourceIntents();
+        for (int i = 0, N = targetIntents.size(); i < N; i++) {
+            final Intent targetIntent = targetIntents.get(i);
+            if (targetIntent.filterEquals(matchingIntent)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     @Override
     ResolveListAdapter createAdapter(Context context, Intent[] initialIntents,
             List<ResolveInfo> rList, int launchedFromUid, boolean filterLastUsed) {
@@ -313,17 +422,19 @@
         return adapter;
     }
 
-    class ChooserTargetInfo implements TargetInfo {
-        private final TargetInfo mSourceInfo;
+    final class ChooserTargetInfo implements TargetInfo {
+        private final DisplayResolveInfo mSourceInfo;
         private final ResolveInfo mBackupResolveInfo;
         private final ChooserTarget mChooserTarget;
         private final Drawable mDisplayIcon;
+        private final Intent mFillInIntent;
+        private final int mFillInFlags;
 
         public ChooserTargetInfo(ChooserTarget target) {
             this(null, target);
         }
 
-        public ChooserTargetInfo(TargetInfo sourceInfo, ChooserTarget chooserTarget) {
+        public ChooserTargetInfo(DisplayResolveInfo sourceInfo, ChooserTarget chooserTarget) {
             mSourceInfo = sourceInfo;
             mChooserTarget = chooserTarget;
             mDisplayIcon = new BitmapDrawable(getResources(), chooserTarget.getIcon());
@@ -333,6 +444,18 @@
             } else {
                 mBackupResolveInfo = getPackageManager().resolveActivity(getResolvedIntent(), 0);
             }
+
+            mFillInIntent = null;
+            mFillInFlags = 0;
+        }
+
+        private ChooserTargetInfo(ChooserTargetInfo other, Intent fillInIntent, int flags) {
+            mSourceInfo = other.mSourceInfo;
+            mBackupResolveInfo = other.mBackupResolveInfo;
+            mChooserTarget = other.mChooserTarget;
+            mDisplayIcon = other.mDisplayIcon;
+            mFillInIntent = fillInIntent;
+            mFillInFlags = flags;
         }
 
         @Override
@@ -358,22 +481,42 @@
         }
 
         private Intent getFillInIntent() {
-            return mSourceInfo != null ? mSourceInfo.getResolvedIntent() : getTargetIntent();
+            Intent result = mSourceInfo != null
+                    ? mSourceInfo.getResolvedIntent() : getTargetIntent();
+            if (result == null) {
+                Log.e(TAG, "ChooserTargetInfo#getFillInIntent: no fillIn intent available");
+            } else if (mFillInIntent != null) {
+                result = new Intent(result);
+                result.fillIn(mFillInIntent, mFillInFlags);
+            }
+            return result;
         }
 
         @Override
         public boolean start(Activity activity, Bundle options) {
-            return mChooserTarget.sendIntent(activity, getFillInIntent());
+            final Intent intent = getFillInIntent();
+            if (intent == null) {
+                return false;
+            }
+            return mChooserTarget.sendIntent(activity, intent);
         }
 
         @Override
         public boolean startAsCaller(Activity activity, Bundle options, int userId) {
-            return mChooserTarget.sendIntentAsCaller(activity, getFillInIntent(), userId);
+            final Intent intent = getFillInIntent();
+            if (intent == null) {
+                return false;
+            }
+            return mChooserTarget.sendIntentAsCaller(activity, intent, userId);
         }
 
         @Override
         public boolean startAsUser(Activity activity, Bundle options, UserHandle user) {
-            return mChooserTarget.sendIntentAsUser(activity, getFillInIntent(), user);
+            final Intent intent = getFillInIntent();
+            if (intent == null) {
+                return false;
+            }
+            return mChooserTarget.sendIntentAsUser(activity, intent, user);
         }
 
         @Override
@@ -395,6 +538,21 @@
         public Drawable getDisplayIcon() {
             return mDisplayIcon;
         }
+
+        @Override
+        public TargetInfo cloneFilledIn(Intent fillInIntent, int flags) {
+            return new ChooserTargetInfo(this, fillInIntent, flags);
+        }
+
+        @Override
+        public List<Intent> getAllSourceIntents() {
+            final List<Intent> results = new ArrayList<>();
+            if (mSourceInfo != null) {
+                // We only queried the service for the first one in our sourceinfo.
+                results.add(mSourceInfo.getAllSourceIntents().get(0));
+            }
+            return results;
+        }
     }
 
     public class ChooserListAdapter extends ResolveListAdapter {
@@ -542,4 +700,53 @@
             connection = c;
         }
     }
+
+    static class RefinementResultReceiver extends ResultReceiver {
+        private ChooserActivity mChooserActivity;
+        private TargetInfo mSelectedTarget;
+
+        public RefinementResultReceiver(ChooserActivity host, TargetInfo target,
+                Handler handler) {
+            super(handler);
+            mChooserActivity = host;
+            mSelectedTarget = target;
+        }
+
+        @Override
+        protected void onReceiveResult(int resultCode, Bundle resultData) {
+            if (mChooserActivity == null) {
+                Log.e(TAG, "Destroyed RefinementResultReceiver received a result");
+                return;
+            }
+            if (resultData == null) {
+                Log.e(TAG, "RefinementResultReceiver received null resultData");
+                return;
+            }
+
+            switch (resultCode) {
+                case RESULT_CANCELED:
+                    mChooserActivity.onRefinementCanceled();
+                    break;
+                case RESULT_OK:
+                    Parcelable intentParcelable = resultData.getParcelable(Intent.EXTRA_INTENT);
+                    if (intentParcelable instanceof Intent) {
+                        mChooserActivity.onRefinementResult(mSelectedTarget,
+                                (Intent) intentParcelable);
+                    } else {
+                        Log.e(TAG, "RefinementResultReceiver received RESULT_OK but no Intent"
+                                + " in resultData with key Intent.EXTRA_INTENT");
+                    }
+                    break;
+                default:
+                    Log.w(TAG, "Unknown result code " + resultCode
+                            + " sent to RefinementResultReceiver");
+                    break;
+            }
+        }
+
+        public void destroy() {
+            mChooserActivity = null;
+            mSelectedTarget = null;
+        }
+    }
 }
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 8dd7836..20486643 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -102,7 +102,7 @@
     private int mLastSelected = AbsListView.INVALID_POSITION;
     private boolean mResolvingHome = false;
     private int mProfileSwitchMessageId = -1;
-    private Intent mIntent;
+    private final ArrayList<Intent> mIntents = new ArrayList<>();
 
     private UsageStatsManager mUsm;
     private Map<String, UsageStats> mStats;
@@ -229,7 +229,7 @@
         final ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
         mIconDpi = am.getLauncherLargeIconDensity();
 
-        mIntent = new Intent(intent);
+        mIntents.add(0, new Intent(intent));
         mAdapter = createAdapter(this, initialIntents, rList, mLaunchedFromUid, alwaysUseOption);
 
         final int layoutId;
@@ -250,7 +250,7 @@
             return;
         }
 
-        int count = mAdapter.mList.size();
+        int count = mAdapter.mDisplayList.size();
         if (count > 1 || (count == 1 && mAdapter.getOtherProfile() != null)) {
             setContentView(layoutId);
             mAdapterView = (AbsListView) findViewById(R.id.resolver_list);
@@ -376,8 +376,16 @@
         }
     }
 
+    protected final void setAdditionalTargets(Intent[] intents) {
+        if (intents != null) {
+            for (Intent intent : intents) {
+                mIntents.add(intent);
+            }
+        }
+    }
+
     public Intent getTargetIntent() {
-        return mIntent;
+        return mIntents.isEmpty() ? null : mIntents.get(0);
     }
 
     private String getReferrerPackageName() {
@@ -630,8 +638,9 @@
         }
 
         TargetInfo target = mAdapter.targetInfoForPosition(which, filtered);
-        onTargetSelected(target, always);
-        finish();
+        if (onTargetSelected(target, always)) {
+            finish();
+        }
     }
 
     /**
@@ -641,7 +650,7 @@
         return defIntent;
     }
 
-    protected void onTargetSelected(TargetInfo target, boolean alwaysCheck) {
+    protected boolean onTargetSelected(TargetInfo target, boolean alwaysCheck) {
         final ResolveInfo ri = target.getResolveInfo();
         final Intent intent = target != null ? target.getResolvedIntent() : null;
 
@@ -728,7 +737,7 @@
                 ComponentName[] set = new ComponentName[N];
                 int bestMatch = 0;
                 for (int i=0; i<N; i++) {
-                    ResolveInfo r = mAdapter.mOrigResolveList.get(i);
+                    ResolveInfo r = mAdapter.mOrigResolveList.get(i).getResolveInfoAt(0);
                     set[i] = new ComponentName(r.activityInfo.packageName,
                             r.activityInfo.name);
                     if (r.match > bestMatch) bestMatch = r.match;
@@ -774,6 +783,7 @@
         if (target != null) {
             safelyStartActivity(target);
         }
+        return true;
     }
 
     void safelyStartActivity(TargetInfo cti) {
@@ -837,15 +847,17 @@
         private Drawable mDisplayIcon;
         private final CharSequence mExtendedInfo;
         private final Intent mResolvedIntent;
+        private final List<Intent> mSourceIntents = new ArrayList<>();
 
-        DisplayResolveInfo(ResolveInfo pri, CharSequence pLabel,
+        DisplayResolveInfo(Intent originalIntent, ResolveInfo pri, CharSequence pLabel,
                 CharSequence pInfo, Intent pOrigIntent) {
+            mSourceIntents.add(originalIntent);
             mResolveInfo = pri;
             mDisplayLabel = pLabel;
             mExtendedInfo = pInfo;
 
             final Intent intent = new Intent(pOrigIntent != null ? pOrigIntent :
-                    getReplacementIntent(pri.activityInfo, mIntent));
+                    getReplacementIntent(pri.activityInfo, getTargetIntent()));
             intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT
                     | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
             final ActivityInfo ai = mResolveInfo.activityInfo;
@@ -854,6 +866,16 @@
             mResolvedIntent = intent;
         }
 
+        private DisplayResolveInfo(DisplayResolveInfo other, Intent fillInIntent, int flags) {
+            mSourceIntents.addAll(other.getAllSourceIntents());
+            mResolveInfo = other.mResolveInfo;
+            mDisplayLabel = other.mDisplayLabel;
+            mDisplayIcon = other.mDisplayIcon;
+            mExtendedInfo = other.mExtendedInfo;
+            mResolvedIntent = new Intent(other.mResolvedIntent);
+            mResolvedIntent.fillIn(fillInIntent, flags);
+        }
+
         public ResolveInfo getResolveInfo() {
             return mResolveInfo;
         }
@@ -866,6 +888,20 @@
             return mDisplayIcon;
         }
 
+        @Override
+        public TargetInfo cloneFilledIn(Intent fillInIntent, int flags) {
+            return new DisplayResolveInfo(this, fillInIntent, flags);
+        }
+
+        @Override
+        public List<Intent> getAllSourceIntents() {
+            return mSourceIntents;
+        }
+
+        public void addAlternateSourceIntent(Intent alt) {
+            mSourceIntents.add(alt);
+        }
+
         public void setDisplayIcon(Drawable icon) {
             mDisplayIcon = icon;
         }
@@ -986,6 +1022,16 @@
          * @return The drawable that should be used to represent this target
          */
         public Drawable getDisplayIcon();
+
+        /**
+         * Clone this target with the given fill-in information.
+         */
+        public TargetInfo cloneFilledIn(Intent fillInIntent, int flags);
+
+        /**
+         * @return the list of supported source intents deduped against this single target
+         */
+        public List<Intent> getAllSourceIntents();
     }
 
     class ResolveListAdapter extends BaseAdapter {
@@ -998,8 +1044,8 @@
 
         protected final LayoutInflater mInflater;
 
-        List<DisplayResolveInfo> mList;
-        List<ResolveInfo> mOrigResolveList;
+        List<DisplayResolveInfo> mDisplayList;
+        List<ResolvedComponentInfo> mOrigResolveList;
 
         private int mLastChosenPosition = -1;
         private boolean mFilterLastUsed;
@@ -1010,7 +1056,7 @@
             mBaseResolveList = rList;
             mLaunchedFromUid = launchedFromUid;
             mInflater = LayoutInflater.from(context);
-            mList = new ArrayList<>();
+            mDisplayList = new ArrayList<>();
             mFilterLastUsed = filterLastUsed;
             rebuildList();
         }
@@ -1027,7 +1073,7 @@
         public DisplayResolveInfo getFilteredItem() {
             if (mFilterLastUsed && mLastChosenPosition >= 0) {
                 // Not using getItem since it offsets to dodge this position for the list
-                return mList.get(mLastChosenPosition);
+                return mDisplayList.get(mLastChosenPosition);
             }
             return null;
         }
@@ -1048,11 +1094,12 @@
         }
 
         private void rebuildList() {
-            List<ResolveInfo> currentResolveList;
+            List<ResolvedComponentInfo> currentResolveList = null;
 
             try {
+                final Intent primaryIntent = getTargetIntent();
                 mLastChosen = AppGlobals.getPackageManager().getLastChosenActivity(
-                        mIntent, mIntent.resolveTypeIfNeeded(getContentResolver()),
+                        primaryIntent, primaryIntent.resolveTypeIfNeeded(getContentResolver()),
                         PackageManager.MATCH_DEFAULT_ONLY);
             } catch (RemoteException re) {
                 Log.d(TAG, "Error calling setLastChosenActivity\n" + re);
@@ -1060,15 +1107,27 @@
 
             // Clear the value of mOtherProfile from previous call.
             mOtherProfile = null;
-            mList.clear();
+            mDisplayList.clear();
             if (mBaseResolveList != null) {
-                currentResolveList = mOrigResolveList = mBaseResolveList;
+                currentResolveList = mOrigResolveList = new ArrayList<>();
+                addResolveListDedupe(currentResolveList, getTargetIntent(), mBaseResolveList);
             } else {
-                currentResolveList = mOrigResolveList = mPm.queryIntentActivities(mIntent,
-                        PackageManager.MATCH_DEFAULT_ONLY
-                        | (shouldGetResolvedFilter() ? PackageManager.GET_RESOLVED_FILTER : 0)
-                        | (shouldGetActivityMetadata() ? PackageManager.GET_META_DATA : 0)
-                );
+                final boolean shouldGetResolvedFilter = shouldGetResolvedFilter();
+                final boolean shouldGetActivityMetadata = shouldGetActivityMetadata();
+                for (int i = 0, N = mIntents.size(); i < N; i++) {
+                    final Intent intent = mIntents.get(i);
+                    final List<ResolveInfo> infos = mPm.queryIntentActivities(intent,
+                            PackageManager.MATCH_DEFAULT_ONLY
+                            | (shouldGetResolvedFilter ? PackageManager.GET_RESOLVED_FILTER : 0)
+                            | (shouldGetActivityMetadata ? PackageManager.GET_META_DATA : 0));
+                    if (infos != null) {
+                        if (currentResolveList == null) {
+                            currentResolveList = mOrigResolveList = new ArrayList<>();
+                        }
+                        addResolveListDedupe(currentResolveList, intent, infos);
+                    }
+                }
+
                 // Filter out any activities that the launched uid does not
                 // have permission for.  We don't do this when we have an explicit
                 // list of resolved activities, because that only happens when
@@ -1076,14 +1135,15 @@
                 // they gave us.
                 if (currentResolveList != null) {
                     for (int i=currentResolveList.size()-1; i >= 0; i--) {
-                        ActivityInfo ai = currentResolveList.get(i).activityInfo;
+                        ActivityInfo ai = currentResolveList.get(i)
+                                .getResolveInfoAt(0).activityInfo;
                         int granted = ActivityManager.checkComponentPermission(
                                 ai.permission, mLaunchedFromUid,
                                 ai.applicationInfo.uid, ai.exported);
                         if (granted != PackageManager.PERMISSION_GRANTED) {
                             // Access not allowed!
                             if (mOrigResolveList == currentResolveList) {
-                                mOrigResolveList = new ArrayList<ResolveInfo>(mOrigResolveList);
+                                mOrigResolveList = new ArrayList<>(mOrigResolveList);
                             }
                             currentResolveList.remove(i);
                         }
@@ -1094,9 +1154,10 @@
             if ((currentResolveList != null) && ((N = currentResolveList.size()) > 0)) {
                 // Only display the first matches that are either of equal
                 // priority or have asked to be default options.
-                ResolveInfo r0 = currentResolveList.get(0);
+                ResolvedComponentInfo rci0 = currentResolveList.get(0);
+                ResolveInfo r0 = rci0.getResolveInfoAt(0);
                 for (int i=1; i<N; i++) {
-                    ResolveInfo ri = currentResolveList.get(i);
+                    ResolveInfo ri = currentResolveList.get(i).getResolveInfoAt(0);
                     if (DEBUG) Log.v(
                         TAG,
                         r0.activityInfo.name + "=" +
@@ -1107,7 +1168,7 @@
                         r0.isDefault != ri.isDefault) {
                         while (i < N) {
                             if (mOrigResolveList == currentResolveList) {
-                                mOrigResolveList = new ArrayList<ResolveInfo>(mOrigResolveList);
+                                mOrigResolveList = new ArrayList<>(mOrigResolveList);
                             }
                             currentResolveList.remove(i);
                             N--;
@@ -1115,9 +1176,8 @@
                     }
                 }
                 if (N > 1) {
-                    Comparator<ResolveInfo> rComparator =
-                            new ResolverComparator(ResolverActivity.this, mIntent);
-                    Collections.sort(currentResolveList, rComparator);
+                    Collections.sort(currentResolveList,
+                            new ResolverComparator(ResolverActivity.this, getTargetIntent()));
                 }
                 // First put the initial items at the top.
                 if (mInitialIntents != null) {
@@ -1146,14 +1206,15 @@
                             ri.nonLocalizedLabel = li.getNonLocalizedLabel();
                             ri.icon = li.getIconResource();
                         }
-                        addResolveInfo(new DisplayResolveInfo(ri,
+                        addResolveInfo(new DisplayResolveInfo(ii, ri,
                                 ri.loadLabel(getPackageManager()), null, ii));
                     }
                 }
 
                 // Check for applications with same name and use application name or
                 // package name if necessary
-                r0 = currentResolveList.get(0);
+                rci0 = currentResolveList.get(0);
+                r0 = rci0.getResolveInfoAt(0);
                 int start = 0;
                 CharSequence r0Label =  r0.loadLabel(mPm);
                 mHasExtendedInfo = false;
@@ -1161,7 +1222,8 @@
                     if (r0Label == null) {
                         r0Label = r0.activityInfo.packageName;
                     }
-                    ResolveInfo ri = currentResolveList.get(i);
+                    ResolvedComponentInfo rci = currentResolveList.get(i);
+                    ResolveInfo ri = rci.getResolveInfoAt(0);
                     CharSequence riLabel = ri.loadLabel(mPm);
                     if (riLabel == null) {
                         riLabel = ri.activityInfo.packageName;
@@ -1169,13 +1231,14 @@
                     if (riLabel.equals(r0Label)) {
                         continue;
                     }
-                    processGroup(currentResolveList, start, (i-1), r0, r0Label);
+                    processGroup(currentResolveList, start, (i-1), rci0, r0Label);
+                    rci0 = rci;
                     r0 = ri;
                     r0Label = riLabel;
                     start = i;
                 }
                 // Process last group
-                processGroup(currentResolveList, start, (N-1), r0, r0Label);
+                processGroup(currentResolveList, start, (N-1), rci0, r0Label);
             }
 
             // Layout doesn't handle both profile button and last chosen
@@ -1188,6 +1251,36 @@
             onListRebuilt();
         }
 
+        private void addResolveListDedupe(List<ResolvedComponentInfo> into, Intent intent,
+                List<ResolveInfo> from) {
+            final int fromCount = from.size();
+            final int intoCount = into.size();
+            for (int i = 0; i < fromCount; i++) {
+                final ResolveInfo newInfo = from.get(i);
+                boolean found = false;
+                // Only loop to the end of into as it was before we started; no dupes in from.
+                for (int j = 0; j < intoCount; j++) {
+                    final ResolvedComponentInfo rci = into.get(i);
+                    if (isSameResolvedComponent(newInfo, rci)) {
+                        found = true;
+                        rci.add(intent, newInfo);
+                        break;
+                    }
+                }
+                if (!found) {
+                    into.add(new ResolvedComponentInfo(new ComponentName(
+                            newInfo.activityInfo.packageName, newInfo.activityInfo.name),
+                            intent, newInfo));
+                }
+            }
+        }
+
+        private boolean isSameResolvedComponent(ResolveInfo a, ResolvedComponentInfo b) {
+            final ActivityInfo ai = a.activityInfo;
+            return ai.packageName.equals(b.name.getPackageName())
+                    && ai.name.equals(b.name.getClassName());
+        }
+
         public void onListRebuilt() {
             // This space for rent
         }
@@ -1196,18 +1289,18 @@
             return mFilterLastUsed;
         }
 
-        private void processGroup(List<ResolveInfo> rList, int start, int end, ResolveInfo ro,
-                CharSequence roLabel) {
+        private void processGroup(List<ResolvedComponentInfo> rList, int start, int end,
+                ResolvedComponentInfo ro, CharSequence roLabel) {
             // Process labels from start to i
             int num = end - start+1;
             if (num == 1) {
                 // No duplicate labels. Use label for entry at start
-                addResolveInfo(new DisplayResolveInfo(ro, roLabel, null, null));
-                updateLastChosenPosition(ro);
+                addResolveInfoWithAlternates(ro, null, roLabel);
             } else {
                 mHasExtendedInfo = true;
                 boolean usePkg = false;
-                CharSequence startApp = ro.activityInfo.applicationInfo.loadLabel(mPm);
+                CharSequence startApp = ro.getResolveInfoAt(0).activityInfo.applicationInfo
+                        .loadLabel(mPm);
                 if (startApp == null) {
                     usePkg = true;
                 }
@@ -1217,7 +1310,7 @@
                         new HashSet<CharSequence>();
                     duplicates.add(startApp);
                     for (int j = start+1; j <= end ; j++) {
-                        ResolveInfo jRi = rList.get(j);
+                        ResolveInfo jRi = rList.get(j).getResolveInfoAt(0);
                         CharSequence jApp = jRi.activityInfo.applicationInfo.loadLabel(mPm);
                         if ( (jApp == null) || (duplicates.contains(jApp))) {
                             usePkg = true;
@@ -1230,26 +1323,46 @@
                     duplicates.clear();
                 }
                 for (int k = start; k <= end; k++) {
-                    ResolveInfo add = rList.get(k);
+                    final ResolvedComponentInfo rci = rList.get(k);
+                    final ResolveInfo add = rci.getResolveInfoAt(0);
+                    final CharSequence extraInfo;
                     if (usePkg) {
-                        // Use application name for all entries from start to end-1
-                        addResolveInfo(new DisplayResolveInfo(add, roLabel,
-                                add.activityInfo.packageName, null));
-                    } else {
                         // Use package name for all entries from start to end-1
-                        addResolveInfo(new DisplayResolveInfo(add, roLabel,
-                                add.activityInfo.applicationInfo.loadLabel(mPm), null));
+                        extraInfo = add.activityInfo.packageName;
+                    } else {
+                        // Use application name for all entries from start to end-1
+                        extraInfo = add.activityInfo.applicationInfo.loadLabel(mPm);
                     }
-                    updateLastChosenPosition(add);
+                    addResolveInfoWithAlternates(rci, extraInfo, roLabel);
                 }
             }
         }
 
+        private void addResolveInfoWithAlternates(ResolvedComponentInfo rci,
+                CharSequence extraInfo, CharSequence roLabel) {
+            final int count = rci.getCount();
+            final Intent intent = rci.getIntentAt(0);
+            final ResolveInfo add = rci.getResolveInfoAt(0);
+            final Intent replaceIntent = getReplacementIntent(add.activityInfo, intent);
+            final DisplayResolveInfo dri = new DisplayResolveInfo(intent, add, roLabel,
+                    extraInfo, replaceIntent);
+            addResolveInfo(dri);
+            if (replaceIntent == intent) {
+                // Only add alternates if we didn't get a specific replacement from
+                // the caller. If we have one it trumps potential alternates.
+                for (int i = 1, N = count; i < N; i++) {
+                    final Intent altIntent = rci.getIntentAt(i);
+                    dri.addAlternateSourceIntent(altIntent);
+                }
+            }
+            updateLastChosenPosition(add);
+        }
+
         private void updateLastChosenPosition(ResolveInfo info) {
             if (mLastChosen != null
                     && mLastChosen.activityInfo.packageName.equals(info.activityInfo.packageName)
                     && mLastChosen.activityInfo.name.equals(info.activityInfo.name)) {
-                mLastChosenPosition = mList.size() - 1;
+                mLastChosenPosition = mDisplayList.size() - 1;
             }
         }
 
@@ -1259,20 +1372,21 @@
                 // The first one we see gets special treatment.
                 mOtherProfile = dri;
             } else {
-                mList.add(dri);
+                mDisplayList.add(dri);
             }
         }
 
         public ResolveInfo resolveInfoForPosition(int position, boolean filtered) {
-            return (filtered ? getItem(position) : mList.get(position)).getResolveInfo();
+            return (filtered ? getItem(position) : mDisplayList.get(position))
+                    .getResolveInfo();
         }
 
         public TargetInfo targetInfoForPosition(int position, boolean filtered) {
-            return filtered ? getItem(position) : mList.get(position);
+            return filtered ? getItem(position) : mDisplayList.get(position);
         }
 
         public int getCount() {
-            int result = mList.size();
+            int result = mDisplayList.size();
             if (mFilterLastUsed && mLastChosenPosition >= 0) {
                 result--;
             }
@@ -1283,7 +1397,7 @@
             if (mFilterLastUsed && mLastChosenPosition >= 0 && position >= mLastChosenPosition) {
                 position++;
             }
-            return mList.get(position);
+            return mDisplayList.get(position);
         }
 
         public long getItemId(int position) {
@@ -1295,8 +1409,8 @@
         }
 
         public boolean hasResolvedTarget(ResolveInfo info) {
-            for (int i = 0, N = mList.size(); i < N; i++) {
-                if (info.equals(mList.get(i).getResolveInfo())) {
+            for (int i = 0, N = mDisplayList.size(); i < N; i++) {
+                if (info.equals(mDisplayList.get(i).getResolveInfo())) {
                     return true;
                 }
             }
@@ -1304,11 +1418,12 @@
         }
 
         protected int getDisplayResolveInfoCount() {
-            return mList.size();
+            return mDisplayList.size();
         }
 
         protected DisplayResolveInfo getDisplayResolveInfo(int index) {
-            return mList.get(index);
+            // Used to query services. We only query services for primary targets, not alternates.
+            return mDisplayList.get(index);
         }
 
         public final View getView(int position, View convertView, ViewGroup parent) {
@@ -1349,6 +1464,52 @@
         }
     }
 
+    static final class ResolvedComponentInfo {
+        public final ComponentName name;
+        private final List<Intent> mIntents = new ArrayList<>();
+        private final List<ResolveInfo> mResolveInfos = new ArrayList<>();
+
+        public ResolvedComponentInfo(ComponentName name, Intent intent, ResolveInfo info) {
+            this.name = name;
+            add(intent, info);
+        }
+
+        public void add(Intent intent, ResolveInfo info) {
+            mIntents.add(intent);
+            mResolveInfos.add(info);
+        }
+
+        public int getCount() {
+            return mIntents.size();
+        }
+
+        public Intent getIntentAt(int index) {
+            return index >= 0 ? mIntents.get(index) : null;
+        }
+
+        public ResolveInfo getResolveInfoAt(int index) {
+            return index >= 0 ? mResolveInfos.get(index) : null;
+        }
+
+        public int findIntent(Intent intent) {
+            for (int i = 0, N = mIntents.size(); i < N; i++) {
+                if (intent.equals(mIntents.get(i))) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+
+        public int findResolveInfo(ResolveInfo info) {
+            for (int i = 0, N = mResolveInfos.size(); i < N; i++) {
+                if (info.equals(mResolveInfos.get(i))) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+    }
+
     static class ViewHolder {
         public TextView text;
         public TextView text2;
@@ -1435,7 +1596,7 @@
                 && match <= IntentFilter.MATCH_CATEGORY_PATH;
     }
 
-    class ResolverComparator implements Comparator<ResolveInfo> {
+    class ResolverComparator implements Comparator<ResolvedComponentInfo> {
         private final Collator mCollator;
         private final boolean mHttp;
 
@@ -1446,7 +1607,10 @@
         }
 
         @Override
-        public int compare(ResolveInfo lhs, ResolveInfo rhs) {
+        public int compare(ResolvedComponentInfo lhsp, ResolvedComponentInfo rhsp) {
+            final ResolveInfo lhs = lhsp.getResolveInfoAt(0);
+            final ResolveInfo rhs = rhsp.getResolveInfoAt(0);
+
             // We want to put the one targeted to another user at the end of the dialog.
             if (lhs.targetUserId != UserHandle.USER_CURRENT) {
                 return 1;
@@ -1487,7 +1651,6 @@
                 if (stats != null) {
                     return stats.getTotalTimeInForeground();
                 }
-
             }
             return 0;
         }
diff --git a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
index 52485dd..ce94727 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
@@ -196,7 +196,7 @@
         }
 
         public List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeList(
-                boolean showSubtypes, boolean inputShown, boolean isScreenLocked) {
+                boolean showSubtypes, boolean includeAuxiliarySubtypes, boolean isScreenLocked) {
             final ArrayList<ImeSubtypeListItem> imList =
                     new ArrayList<ImeSubtypeListItem>();
             final HashMap<InputMethodInfo, List<InputMethodSubtype>> immis =
@@ -205,6 +205,12 @@
             if (immis == null || immis.size() == 0) {
                 return Collections.emptyList();
             }
+            if (isScreenLocked && includeAuxiliarySubtypes) {
+                if (DEBUG) {
+                    Slog.w(TAG, "Auxiliary subtypes are not allowed to be shown in lock screen.");
+                }
+                includeAuxiliarySubtypes = false;
+            }
             mSortedImmis.clear();
             mSortedImmis.putAll(immis);
             for (InputMethodInfo imi : mSortedImmis.keySet()) {
@@ -227,7 +233,7 @@
                         final String subtypeHashCode = String.valueOf(subtype.hashCode());
                         // We show all enabled IMEs and subtypes when an IME is shown.
                         if (enabledSubtypeSet.contains(subtypeHashCode)
-                                && ((inputShown && !isScreenLocked) || !subtype.isAuxiliary())) {
+                                && (includeAuxiliarySubtypes || !subtype.isAuxiliary())) {
                             final CharSequence subtypeLabel =
                                     subtype.overridesImplicitlyEnabledSubtype() ? null : subtype
                                             .getDisplayName(mContext, imi.getPackageName(),
@@ -516,8 +522,8 @@
     }
 
     public List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeListLocked(boolean showSubtypes,
-            boolean inputShown, boolean isScreenLocked) {
+            boolean includingAuxiliarySubtypes, boolean isScreenLocked) {
         return mSubtypeList.getSortedInputMethodAndSubtypeList(
-                showSubtypes, inputShown, isScreenLocked);
+                showSubtypes, includingAuxiliarySubtypes, isScreenLocked);
     }
 }
diff --git a/core/java/android/view/PhoneFallbackEventHandler.java b/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java
similarity index 98%
rename from core/java/android/view/PhoneFallbackEventHandler.java
rename to core/java/com/android/internal/policy/PhoneFallbackEventHandler.java
index 350650d..2cb9c25 100644
--- a/core/java/android/view/PhoneFallbackEventHandler.java
+++ b/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.view;
+package com.android.internal.policy;
 
 import android.app.KeyguardManager;
 import android.app.SearchManager;
@@ -28,10 +28,11 @@
 import android.provider.Settings;
 import android.telephony.TelephonyManager;
 import android.util.Log;
-import android.view.View;
-import android.view.HapticFeedbackConstants;
 import android.view.FallbackEventHandler;
+import android.view.HapticFeedbackConstants;
 import android.view.KeyEvent;
+import android.view.View;
+import com.android.internal.policy.PhoneWindow;
 
 /**
  * @hide
diff --git a/core/java/android/view/PhoneLayoutInflater.java b/core/java/com/android/internal/policy/PhoneLayoutInflater.java
similarity index 95%
rename from core/java/android/view/PhoneLayoutInflater.java
rename to core/java/com/android/internal/policy/PhoneLayoutInflater.java
index 7d89a0b..991b6bb 100644
--- a/core/java/android/view/PhoneLayoutInflater.java
+++ b/core/java/com/android/internal/policy/PhoneLayoutInflater.java
@@ -14,10 +14,12 @@
  * limitations under the License.
  */
 
-package android.view;
+package com.android.internal.policy;
 
 import android.content.Context;
 import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
 
 /**
  * @hide
diff --git a/core/java/android/view/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
similarity index 98%
rename from core/java/android/view/PhoneWindow.java
rename to core/java/com/android/internal/policy/PhoneWindow.java
index a3e7a10..a578a6e 100644
--- a/core/java/android/view/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.view;
+package com.android.internal.policy;
 
 import static android.view.View.MeasureSpec.AT_MOST;
 import static android.view.View.MeasureSpec.EXACTLY;
@@ -27,6 +27,34 @@
 import android.app.SearchManager;
 import android.os.UserHandle;
 
+import android.view.ActionMode;
+import android.view.ContextThemeWrapper;
+import android.view.Display;
+import android.view.Gravity;
+import android.view.IRotationWatcher.Stub;
+import android.view.IWindowManager;
+import android.view.InputDevice;
+import android.view.InputEvent;
+import android.view.InputQueue;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.SearchEvent;
+import android.view.SurfaceHolder.Callback2;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.ViewManager;
+import android.view.ViewParent;
+import android.view.ViewRootImpl;
+import android.view.ViewStub;
+import android.view.ViewTreeObserver.OnPreDrawListener;
+import android.view.Window;
+import android.view.WindowInsets;
+import android.view.WindowManager;
 import com.android.internal.R;
 import com.android.internal.util.ScreenShapeHelper;
 import com.android.internal.view.FloatingActionMode;
@@ -67,7 +95,6 @@
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.SystemProperties;
 import android.transition.Scene;
 import android.transition.Transition;
 import android.transition.TransitionInflater;
@@ -140,7 +167,7 @@
 
     private ViewGroup mContentRoot;
 
-    SurfaceHolder.Callback2 mTakeSurfaceCallback;
+    Callback2 mTakeSurfaceCallback;
 
     InputQueue.Callback mTakeInputQueueCallback;
 
@@ -427,7 +454,7 @@
     }
 
     @Override
-    public void takeSurface(SurfaceHolder.Callback2 callback) {
+    public void takeSurface(Callback2 callback) {
         mTakeSurfaceCallback = callback;
     }
 
@@ -2181,7 +2208,7 @@
         private ActionBarContextView mPrimaryActionModeView;
         private PopupWindow mPrimaryActionModePopup;
         private Runnable mShowPrimaryActionModePopup;
-        private ViewTreeObserver.OnPreDrawListener mFloatingToolbarPreDrawListener;
+        private OnPreDrawListener mFloatingToolbarPreDrawListener;
         private View mFloatingActionModeOriginatingView;
         private FloatingToolbar mFloatingToolbar;
 
@@ -3354,7 +3381,7 @@
                     mContext, callback, originatingView, mFloatingToolbar);
             mFloatingActionModeOriginatingView = originatingView;
             mFloatingToolbarPreDrawListener =
-                new ViewTreeObserver.OnPreDrawListener() {
+                new OnPreDrawListener() {
                     @Override
                     public boolean onPreDraw() {
                         mode.updateViewLocationInWindow();
@@ -4718,7 +4745,7 @@
 
     }
 
-    static class RotationWatcher extends IRotationWatcher.Stub {
+    static class RotationWatcher extends Stub {
         private Handler mHandler;
         private final Runnable mRotationChanged = new Runnable() {
             public void run() {
diff --git a/core/java/com/android/internal/util/AsyncChannel.java b/core/java/com/android/internal/util/AsyncChannel.java
index 34f62ba..bd0e6ce 100644
--- a/core/java/com/android/internal/util/AsyncChannel.java
+++ b/core/java/com/android/internal/util/AsyncChannel.java
@@ -462,10 +462,8 @@
         } catch(Exception e) {
         }
         // Tell source we're disconnected.
-        if (mSrcHandler != null) {
-            replyDisconnected(STATUS_SUCCESSFUL);
-            mSrcHandler = null;
-        }
+        replyDisconnected(STATUS_SUCCESSFUL);
+        mSrcHandler = null;
         // Unlink only when bindService isn't used
         if (mConnection == null && mDstMessenger != null && mDeathMonitor!= null) {
             mDstMessenger.getBinder().unlinkToDeath(mDeathMonitor, 0);
@@ -871,6 +869,8 @@
      * @param status to be stored in msg.arg1
      */
     private void replyDisconnected(int status) {
+        // Can't reply if already disconnected. Avoid NullPointerException.
+        if (mSrcHandler == null) return;
         Message msg = mSrcHandler.obtainMessage(CMD_CHANNEL_DISCONNECTED);
         msg.arg1 = status;
         msg.obj = this;
diff --git a/core/java/com/android/internal/util/CallbackRegistry.java b/core/java/com/android/internal/util/CallbackRegistry.java
new file mode 100644
index 0000000..0f228d4
--- /dev/null
+++ b/core/java/com/android/internal/util/CallbackRegistry.java
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 2015 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.internal.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tracks callbacks for the event. This class supports reentrant modification
+ * of the callbacks during notification without adversely disrupting notifications.
+ * A common pattern for callbacks is to receive a notification and then remove
+ * themselves. This class handles this behavior with constant memory under
+ * most circumstances.
+ *
+ * <p>A subclass of {@link CallbackRegistry.NotifierCallback} must be passed to
+ * the constructor to define how notifications should be called. That implementation
+ * does the actual notification on the listener.</p>
+ *
+ * <p>This class supports only callbacks with at most two parameters.
+ * Typically, these are the notification originator and a parameter, but these may
+ * be used as required. If more than two parameters are required or primitive types
+ * must be used, <code>A</code> should be some kind of containing structure that
+ * the subclass may reuse between notifications.</p>
+ *
+ * @param <C> The callback type.
+ * @param <T> The notification sender type. Typically this is the containing class.
+ * @param <A> Opaque argument used to pass additional data beyond an int.
+ */
+public class CallbackRegistry<C, T, A> implements Cloneable {
+    private static final String TAG = "CallbackRegistry";
+
+    /** An ordered collection of listeners waiting to be notified. */
+    private List<C> mCallbacks = new ArrayList<C>();
+
+    /**
+     * A bit flag for the first 64 listeners that are removed during notification.
+     * The lowest significant bit corresponds to the 0th index into mCallbacks.
+     * For a small number of callbacks, no additional array of objects needs to
+     * be allocated.
+     */
+    private long mFirst64Removed = 0x0;
+
+    /**
+     * Bit flags for the remaining callbacks that are removed during notification.
+     * When there are more than 64 callbacks and one is marked for removal, a dynamic
+     * array of bits are allocated for the callbacks.
+     */
+    private long[] mRemainderRemoved;
+
+    /**
+     * The reentrancy level of the notification. When we notify a callback, it may cause
+     * further notifications. The reentrancy level must be tracked to let us clean up
+     * the callback state when all notifications have been processed.
+     */
+    private int mNotificationLevel;
+
+    /** The notification mechanism for notifying an event. */
+    private final NotifierCallback<C, T, A> mNotifier;
+
+    /**
+     * Creates an EventRegistry that notifies the event with notifier.
+     * @param notifier The class to use to notify events.
+     */
+    public CallbackRegistry(NotifierCallback<C, T, A> notifier) {
+        mNotifier = notifier;
+    }
+
+    /**
+     * Notify all callbacks.
+     *
+     * @param sender The originator. This is an opaque parameter passed to
+     *      {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, A)}
+     * @param arg An opaque parameter passed to
+     *      {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, A)}
+     * @param arg2 An opaque parameter passed to
+     *      {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, A)}
+     */
+    public synchronized void notifyCallbacks(T sender, int arg, A arg2) {
+        mNotificationLevel++;
+        notifyRecurseLocked(sender, arg, arg2);
+        mNotificationLevel--;
+        if (mNotificationLevel == 0) {
+            if (mRemainderRemoved != null) {
+                for (int i = mRemainderRemoved.length - 1; i >= 0; i--) {
+                    final long removedBits = mRemainderRemoved[i];
+                    if (removedBits != 0) {
+                        removeRemovedCallbacks((i + 1) * Long.SIZE, removedBits);
+                        mRemainderRemoved[i] = 0;
+                    }
+                }
+            }
+            if (mFirst64Removed != 0) {
+                removeRemovedCallbacks(0, mFirst64Removed);
+                mFirst64Removed = 0;
+            }
+        }
+    }
+
+    /**
+     * Notify up to the first Long.SIZE callbacks that don't have a bit set in <code>removed</code>.
+     *
+     * @param sender The originator. This is an opaque parameter passed to
+     *      {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, A)}
+     * @param arg An opaque parameter passed to
+     *      {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, A)}
+     * @param arg2 An opaque parameter passed to
+     *      {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, A)}
+     */
+    private void notifyFirst64Locked(T sender, int arg, A arg2) {
+        final int maxNotified = Math.min(Long.SIZE, mCallbacks.size());
+        notifyCallbacksLocked(sender, arg, arg2, 0, maxNotified, mFirst64Removed);
+    }
+
+    /**
+     * Notify all callbacks using a recursive algorithm to avoid allocating on the heap.
+     * This part captures the callbacks beyond Long.SIZE that have no bits allocated for
+     * removal before it recurses into {@link #notifyRemainderLocked(Object, int, A, int)}.
+     * <p>
+     * Recursion is used to avoid allocating temporary state on the heap. Each stack has one
+     * long (64 callbacks) worth of information of which has been removed.
+     *
+     * @param sender The originator. This is an opaque parameter passed to
+     *      {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, A)}
+     * @param arg An opaque parameter passed to
+     *      {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, A)}
+     * @param arg2 An opaque parameter passed to
+     *      {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, A)}
+     */
+    private void notifyRecurseLocked(T sender, int arg, A arg2) {
+        final int callbackCount = mCallbacks.size();
+        final int remainderIndex = mRemainderRemoved == null ? -1 : mRemainderRemoved.length - 1;
+
+        // Now we've got all callbacks that have no mRemainderRemoved value, so notify the
+        // others.
+        notifyRemainderLocked(sender, arg, arg2, remainderIndex);
+
+        // notifyRemainderLocked notifies all at maxIndex, so we'd normally start at maxIndex + 1
+        // However, we must also keep track of those in mFirst64Removed, so we add 2 instead:
+        final int startCallbackIndex = (remainderIndex + 2) * Long.SIZE;
+
+        // The remaining have no bit set
+        notifyCallbacksLocked(sender, arg, arg2, startCallbackIndex, callbackCount, 0);
+    }
+
+    /**
+     * Notify callbacks that have mRemainderRemoved bits set for remainderIndex. If
+     * remainderIndex is -1, the first 64 will be notified instead.
+     *
+     * @param sender The originator. This is an opaque parameter passed to
+     *      {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, A)}
+     * @param arg An opaque parameter passed to
+     *      {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, A)}
+     * @param arg2 An opaque parameter passed to
+     *      {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, A)}
+     * @param remainderIndex The index into mRemainderRemoved that should be notified.
+     */
+    private void notifyRemainderLocked(T sender, int arg, A arg2, int remainderIndex) {
+        if (remainderIndex < 0) {
+            notifyFirst64Locked(sender, arg, arg2);
+        } else {
+            final long bits = mRemainderRemoved[remainderIndex];
+            final int startIndex = (remainderIndex + 1) * Long.SIZE;
+            final int endIndex = Math.min(mCallbacks.size(), startIndex + Long.SIZE);
+            notifyRemainderLocked(sender, arg, arg2, remainderIndex - 1);
+            notifyCallbacksLocked(sender, arg, arg2, startIndex, endIndex, bits);
+        }
+    }
+
+    /**
+     * Notify callbacks from startIndex to endIndex, using bits as the bit status
+     * for whether they have been removed or not. bits should be from mRemainderRemoved or
+     * mFirst64Removed. bits set to 0 indicates that all callbacks from startIndex to
+     * endIndex should be notified.
+     *
+     * @param sender The originator. This is an opaque parameter passed to
+     *      {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, A)}
+     * @param arg An opaque parameter passed to
+     *      {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, A)}
+     * @param arg2 An opaque parameter passed to
+     *      {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, A)}
+     * @param startIndex The index into the mCallbacks to start notifying.
+     * @param endIndex One past the last index into mCallbacks to notify.
+     * @param bits A bit field indicating which callbacks have been removed and shouldn't
+     *             be notified.
+     */
+    private void notifyCallbacksLocked(T sender, int arg, A arg2, final int startIndex,
+            final int endIndex, final long bits) {
+        long bitMask = 1;
+        for (int i = startIndex; i < endIndex; i++) {
+            if ((bits & bitMask) == 0) {
+                mNotifier.onNotifyCallback(mCallbacks.get(i), sender, arg, arg2);
+            }
+            bitMask <<= 1;
+        }
+    }
+
+    /**
+     * Add a callback to be notified. If the callback is already in the list, another won't
+     * be added. This does not affect current notifications.
+     * @param callback The callback to add.
+     */
+    public synchronized void add(C callback) {
+        int index = mCallbacks.lastIndexOf(callback);
+        if (index < 0 || isRemovedLocked(index)) {
+            mCallbacks.add(callback);
+        }
+    }
+
+    /**
+     * Returns true if the callback at index has been marked for removal.
+     *
+     * @param index The index into mCallbacks to check.
+     * @return true if the callback at index has been marked for removal.
+     */
+    private boolean isRemovedLocked(int index) {
+        if (index < Long.SIZE) {
+            // It is in the first 64 callbacks, just check the bit.
+            final long bitMask = 1L << index;
+            return (mFirst64Removed & bitMask) != 0;
+        } else if (mRemainderRemoved == null) {
+            // It is after the first 64 callbacks, but nothing else was marked for removal.
+            return false;
+        } else {
+            final int maskIndex = (index / Long.SIZE) - 1;
+            if (maskIndex >= mRemainderRemoved.length) {
+                // There are some items in mRemainderRemoved, but nothing at the given index.
+                return false;
+            } else {
+                // There is something marked for removal, so we have to check the bit.
+                final long bits = mRemainderRemoved[maskIndex];
+                final long bitMask = 1L << (index % Long.SIZE);
+                return (bits & bitMask) != 0;
+            }
+        }
+    }
+
+    /**
+     * Removes callbacks from startIndex to startIndex + Long.SIZE, based
+     * on the bits set in removed.
+     * @param startIndex The index into the mCallbacks to start removing callbacks.
+     * @param removed The bits indicating removal, where each bit is set for one callback
+     *                to be removed.
+     */
+    private void removeRemovedCallbacks(int startIndex, long removed) {
+        // The naive approach should be fine. There may be a better bit-twiddling approach.
+        final int endIndex = startIndex + Long.SIZE;
+
+        long bitMask = 1L << (Long.SIZE - 1);
+        for (int i = endIndex - 1; i >= startIndex; i--) {
+            if ((removed & bitMask) != 0) {
+                mCallbacks.remove(i);
+            }
+            bitMask >>>= 1;
+        }
+    }
+
+    /**
+     * Remove a callback. This callback won't be notified after this call completes.
+     * @param callback The callback to remove.
+     */
+    public synchronized void remove(C callback) {
+        if (mNotificationLevel == 0) {
+            mCallbacks.remove(callback);
+        } else {
+            int index = mCallbacks.lastIndexOf(callback);
+            if (index >= 0) {
+                setRemovalBitLocked(index);
+            }
+        }
+    }
+
+    private void setRemovalBitLocked(int index) {
+        if (index < Long.SIZE) {
+            // It is in the first 64 callbacks, just check the bit.
+            final long bitMask = 1L << index;
+            mFirst64Removed |= bitMask;
+        } else {
+            final int remainderIndex = (index / Long.SIZE) - 1;
+            if (mRemainderRemoved == null) {
+                mRemainderRemoved = new long[mCallbacks.size() / Long.SIZE];
+            } else if (mRemainderRemoved.length < remainderIndex) {
+                // need to make it bigger
+                long[] newRemainders = new long[mCallbacks.size() / Long.SIZE];
+                System.arraycopy(mRemainderRemoved, 0, newRemainders, 0, mRemainderRemoved.length);
+                mRemainderRemoved = newRemainders;
+            }
+            final long bitMask = 1L << (index % Long.SIZE);
+            mRemainderRemoved[remainderIndex] |= bitMask;
+        }
+    }
+
+    /**
+     * Makes a copy of the registered callbacks and returns it.
+     *
+     * @return a copy of the registered callbacks.
+     */
+    public synchronized ArrayList<C> copyListeners() {
+        ArrayList<C> callbacks = new ArrayList<C>(mCallbacks.size());
+        int numListeners = mCallbacks.size();
+        for (int i = 0; i < numListeners; i++) {
+            if (!isRemovedLocked(i)) {
+                callbacks.add(mCallbacks.get(i));
+            }
+        }
+        return callbacks;
+    }
+
+    /**
+     * Returns true if there are no registered callbacks or false otherwise.
+     *
+     * @return true if there are no registered callbacks or false otherwise.
+     */
+    public synchronized boolean isEmpty() {
+        if (mCallbacks.isEmpty()) {
+            return true;
+        } else if (mNotificationLevel == 0) {
+            return false;
+        } else {
+            int numListeners = mCallbacks.size();
+            for (int i = 0; i < numListeners; i++) {
+                if (!isRemovedLocked(i)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
+    /**
+     * Removes all callbacks from the list.
+     */
+    public synchronized void clear() {
+        if (mNotificationLevel == 0) {
+            mCallbacks.clear();
+        } else if (!mCallbacks.isEmpty()) {
+            for (int i = mCallbacks.size() - 1; i >= 0; i--) {
+                setRemovalBitLocked(i);
+            }
+        }
+    }
+
+    public synchronized CallbackRegistry<C, T, A> clone() {
+        CallbackRegistry<C, T, A> clone = null;
+        try {
+            clone = (CallbackRegistry<C, T, A>) super.clone();
+            clone.mFirst64Removed = 0;
+            clone.mRemainderRemoved = null;
+            clone.mNotificationLevel = 0;
+            clone.mCallbacks = new ArrayList<C>();
+            final int numListeners = mCallbacks.size();
+            for (int i = 0; i < numListeners; i++) {
+                if (!isRemovedLocked(i)) {
+                    clone.mCallbacks.add(mCallbacks.get(i));
+                }
+            }
+        } catch (CloneNotSupportedException e) {
+            e.printStackTrace();
+        }
+        return clone;
+    }
+
+    /**
+     * Class used to notify events from CallbackRegistry.
+     *
+     * @param <C> The callback type.
+     * @param <T> The notification sender type. Typically this is the containing class.
+     * @param <A> An opaque argument to pass to the notifier
+     */
+    public abstract static class NotifierCallback<C, T, A> {
+        /**
+         * Used to notify the callback.
+         *
+         * @param callback The callback to notify.
+         * @param sender The opaque sender object.
+         * @param arg The opaque notification parameter.
+         * @param arg2 An opaque argument passed in
+         *        {@link CallbackRegistry#notifyCallbacks}
+         * @see CallbackRegistry#CallbackRegistry(CallbackRegistry.NotifierCallback)
+         */
+        public abstract void onNotifyCallback(C callback, T sender, int arg, A arg2);
+    }
+}
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 6f104dd..60c5e42 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -59,7 +59,8 @@
             int controlFlags, int softInputMode, int windowFlags,
             in EditorInfo attribute, IInputContext inputContext);
 
-    void showInputMethodPickerFromClient(in IInputMethodClient client);
+    void showInputMethodPickerFromClient(in IInputMethodClient client,
+            int auxiliarySubtypeMode);
     void showInputMethodAndSubtypeEnablerFromClient(in IInputMethodClient client, String topId);
     void setInputMethod(in IBinder token, String id);
     void setInputMethodAndSubtype(in IBinder token, String id, in InputMethodSubtype subtype);
diff --git a/core/java/com/android/internal/widget/ButtonBarLayout.java b/core/java/com/android/internal/widget/ButtonBarLayout.java
index 64e6c69..f58ab03 100644
--- a/core/java/com/android/internal/widget/ButtonBarLayout.java
+++ b/core/java/com/android/internal/widget/ButtonBarLayout.java
@@ -17,6 +17,7 @@
 package com.android.internal.widget;
 
 import android.content.Context;
+import android.content.res.TypedArray;
 import android.util.AttributeSet;
 import android.view.Gravity;
 import android.view.View;
@@ -29,37 +30,39 @@
  * orientation when it can't fit its child views horizontally.
  */
 public class ButtonBarLayout extends LinearLayout {
-    /** Spacer used in horizontal orientation. */
-    private final View mSpacer;
-
     /** Whether the current configuration allows stacking. */
-    private final boolean mAllowStacked;
+    private final boolean mAllowStacking;
 
     /** Whether the layout is currently stacked. */
     private boolean mStacked;
 
+    private int mLastWidthSize = -1;
+
     public ButtonBarLayout(Context context, AttributeSet attrs) {
         super(context, attrs);
 
-        mAllowStacked = context.getResources().getBoolean(R.bool.allow_stacked_button_bar);
-        mSpacer = findViewById(R.id.spacer);
-    }
+        final TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ButtonBarLayout);
+        mAllowStacking = ta.getBoolean(R.styleable.ButtonBarLayout_allowStacking, false);
+        ta.recycle();
 
-    @Override
-    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-        super.onSizeChanged(w, h, oldw, oldh);
-
-        // Maybe we can fit the content now?
-        if (w > oldw && mStacked) {
-            setStacked(false);
-        }
+        mStacked = getOrientation() == VERTICAL;
     }
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        if (mAllowStacking) {
+            final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+            if (widthSize > mLastWidthSize && mStacked) {
+                // We're being measured wider this time, try un-stacking.
+                setStacked(false);
+            }
+
+            mLastWidthSize = widthSize;
+        }
+
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 
-        if (mAllowStacked && getOrientation() == LinearLayout.HORIZONTAL) {
+        if (mAllowStacking && !mStacked) {
             final int measuredWidth = getMeasuredWidthAndState();
             final int measuredWidthState = measuredWidth & MEASURED_STATE_MASK;
             if (measuredWidthState == MEASURED_STATE_TOO_SMALL) {
@@ -75,8 +78,9 @@
         setOrientation(stacked ? LinearLayout.VERTICAL : LinearLayout.HORIZONTAL);
         setGravity(stacked ? Gravity.RIGHT : Gravity.BOTTOM);
 
-        if (mSpacer != null) {
-            mSpacer.setVisibility(stacked ? View.GONE : View.INVISIBLE);
+        final View spacer = findViewById(R.id.spacer);
+        if (spacer != null) {
+            spacer.setVisibility(stacked ? View.GONE : View.INVISIBLE);
         }
 
         // Reverse the child order. This is specific to the Material button
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index bbdd860..5448214 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -132,6 +132,7 @@
     android_media_AudioRecord.cpp \
     android_media_AudioSystem.cpp \
     android_media_AudioTrack.cpp \
+    android_media_DeviceCallback.cpp \
     android_media_JetPlayer.cpp \
     android_media_RemoteDisplay.cpp \
     android_media_ToneGenerator.cpp \
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 8b65fd1..87b81d5 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -30,6 +30,7 @@
 
 #include "android_media_AudioFormat.h"
 #include "android_media_AudioErrors.h"
+#include "android_media_DeviceCallback.h"
 
 // ----------------------------------------------------------------------------
 
@@ -44,6 +45,7 @@
     jmethodID postNativeEventInJava; //... event post callback method
     jfieldID  nativeRecorderInJavaObj; // provides access to the C++ AudioRecord object
     jfieldID  nativeCallbackCookie;    // provides access to the AudioRecord callback data
+    jfieldID  nativeDeviceCallback;    // provides access to the JNIDeviceCallback instance
 };
 struct audio_attributes_fields_t {
     jfieldID  fieldRecSource;    // AudioAttributes.mSource
@@ -120,6 +122,33 @@
     }
 }
 
+static sp<JNIDeviceCallback> getJniDeviceCallback(JNIEnv* env, jobject thiz)
+{
+    Mutex::Autolock l(sLock);
+    JNIDeviceCallback* const cb =
+            (JNIDeviceCallback*)env->GetLongField(thiz,
+                                                  javaAudioRecordFields.nativeDeviceCallback);
+    return sp<JNIDeviceCallback>(cb);
+}
+
+static sp<JNIDeviceCallback> setJniDeviceCallback(JNIEnv* env,
+                                                  jobject thiz,
+                                                  const sp<JNIDeviceCallback>& cb)
+{
+    Mutex::Autolock l(sLock);
+    sp<JNIDeviceCallback> old =
+            (JNIDeviceCallback*)env->GetLongField(thiz,
+                                                  javaAudioRecordFields.nativeDeviceCallback);
+    if (cb.get()) {
+        cb->incStrong((void*)setJniDeviceCallback);
+    }
+    if (old != 0) {
+        old->decStrong((void*)setJniDeviceCallback);
+    }
+    env->SetLongField(thiz, javaAudioRecordFields.nativeDeviceCallback, (jlong)cb.get());
+    return old;
+}
+
 // ----------------------------------------------------------------------------
 static sp<AudioRecord> getAudioRecord(JNIEnv* env, jobject thiz)
 {
@@ -593,9 +622,63 @@
         JNIEnv *env,  jobject thiz, jint device_id) {
 
     sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
+    if (lpRecorder == 0) {
+        return 0;
+    }
     return lpRecorder->setInputDevice(device_id) == NO_ERROR;
 }
 
+static jint android_media_AudioRecord_getRoutedDeviceId(
+                JNIEnv *env,  jobject thiz) {
+
+    sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
+    if (lpRecorder == 0) {
+        return 0;
+    }
+    return (jint)lpRecorder->getRoutedDeviceId();
+}
+
+static void android_media_AudioRecord_enableDeviceCallback(
+                JNIEnv *env,  jobject thiz) {
+
+    sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
+    if (lpRecorder == 0) {
+        return;
+    }
+    sp<JNIDeviceCallback> cb = getJniDeviceCallback(env, thiz);
+    if (cb != 0) {
+        return;
+    }
+    audiorecord_callback_cookie *cookie =
+            (audiorecord_callback_cookie *)env->GetLongField(thiz,
+                                                     javaAudioRecordFields.nativeCallbackCookie);
+    if (cookie == NULL) {
+        return;
+    }
+
+    cb = new JNIDeviceCallback(env, thiz, cookie->audioRecord_ref,
+                               javaAudioRecordFields.postNativeEventInJava);
+    status_t status = lpRecorder->addAudioDeviceCallback(cb);
+    if (status == NO_ERROR) {
+        setJniDeviceCallback(env, thiz, cb);
+    }
+}
+
+static void android_media_AudioRecord_disableDeviceCallback(
+                JNIEnv *env,  jobject thiz) {
+
+    sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
+    if (lpRecorder == 0) {
+        return;
+    }
+    sp<JNIDeviceCallback> cb = setJniDeviceCallback(env, thiz, 0);
+    if (cb != 0) {
+        lpRecorder->removeAudioDeviceCallback(cb);
+    }
+}
+
+
+
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 static JNINativeMethod gMethods[] = {
@@ -628,12 +711,17 @@
     {"native_get_min_buff_size",
                              "(III)I",   (void *)android_media_AudioRecord_get_min_buff_size},
     {"native_setInputDevice", "(I)Z", (void *)android_media_AudioRecord_setInputDevice},
+    {"native_getRoutedDeviceId", "()I", (void *)android_media_AudioRecord_getRoutedDeviceId},
+    {"native_enableDeviceCallback", "()V", (void *)android_media_AudioRecord_enableDeviceCallback},
+    {"native_disableDeviceCallback", "()V",
+                                        (void *)android_media_AudioRecord_disableDeviceCallback},
 };
 
 // field names found in android/media/AudioRecord.java
 #define JAVA_POSTEVENT_CALLBACK_NAME  "postEventFromNative"
 #define JAVA_NATIVERECORDERINJAVAOBJ_FIELD_NAME  "mNativeRecorderInJavaObj"
 #define JAVA_NATIVECALLBACKINFO_FIELD_NAME       "mNativeCallbackCookie"
+#define JAVA_NATIVEDEVICECALLBACK_FIELD_NAME       "mNativeDeviceCallback"
 
 // ----------------------------------------------------------------------------
 int register_android_media_AudioRecord(JNIEnv *env)
@@ -641,6 +729,7 @@
     javaAudioRecordFields.postNativeEventInJava = NULL;
     javaAudioRecordFields.nativeRecorderInJavaObj = NULL;
     javaAudioRecordFields.nativeCallbackCookie = NULL;
+    javaAudioRecordFields.nativeDeviceCallback = NULL;
 
 
     // Get the AudioRecord class
@@ -658,6 +747,9 @@
     javaAudioRecordFields.nativeCallbackCookie = GetFieldIDOrDie(env,
             audioRecordClass, JAVA_NATIVECALLBACKINFO_FIELD_NAME, "J");
 
+    javaAudioRecordFields.nativeDeviceCallback = GetFieldIDOrDie(env,
+            audioRecordClass, JAVA_NATIVEDEVICECALLBACK_FIELD_NAME, "J");
+
     // Get the AudioAttributes class and fields
     jclass audioAttrClass = FindClassOrDie(env, kAudioAttributesClassPathName);
     javaAudioAttrFields.fieldRecSource = GetFieldIDOrDie(env, audioAttrClass, "mSource", "I");
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 3655adc..eab5668 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -937,7 +937,8 @@
     } else if (nAudioPort->type == AUDIO_PORT_TYPE_MIX) {
         ALOGV("convertAudioPortFromNative is a mix");
         *jAudioPort = env->NewObject(gAudioMixPortClass, gAudioMixPortCstor,
-                                     jHandle, nAudioPort->role, jDeviceName,
+                                     jHandle, nAudioPort->ext.mix.handle,
+                                     nAudioPort->role, jDeviceName,
                                      jSamplingRates, jChannelMasks,
                                      jFormats, jGains);
     } else {
@@ -1670,7 +1671,7 @@
     jclass audioMixPortClass = FindClassOrDie(env, "android/media/AudioMixPort");
     gAudioMixPortClass = MakeGlobalRefOrDie(env, audioMixPortClass);
     gAudioMixPortCstor = GetMethodIDOrDie(env, audioMixPortClass, "<init>",
-            "(Landroid/media/AudioHandle;ILjava/lang/String;[I[I[I[Landroid/media/AudioGain;)V");
+            "(Landroid/media/AudioHandle;IILjava/lang/String;[I[I[I[Landroid/media/AudioGain;)V");
 
     jclass audioGainClass = FindClassOrDie(env, "android/media/AudioGain");
     gAudioGainClass = MakeGlobalRefOrDie(env, audioGainClass);
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 26b82c5..662ecd3 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -36,6 +36,7 @@
 #include "android_media_AudioFormat.h"
 #include "android_media_AudioErrors.h"
 #include "android_media_PlaybackSettings.h"
+#include "android_media_DeviceCallback.h"
 
 // ----------------------------------------------------------------------------
 
@@ -79,6 +80,7 @@
         sp<MemoryHeapBase>         mMemHeap;
         sp<MemoryBase>             mMemBase;
         audiotrack_callback_cookie mCallbackData;
+        sp<JNIDeviceCallback>      mDeviceCallback;
 
     AudioTrackJniStorage() {
         mCallbackData.audioTrack_class = 0;
@@ -977,6 +979,51 @@
     return lpTrack->setOutputDevice(device_id) == NO_ERROR;
 }
 
+static jint android_media_AudioTrack_getRoutedDeviceId(
+                JNIEnv *env,  jobject thiz) {
+
+    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
+    if (lpTrack == NULL) {
+        return 0;
+    }
+    return (jint)lpTrack->getRoutedDeviceId();
+}
+
+static void android_media_AudioTrack_enableDeviceCallback(
+                JNIEnv *env,  jobject thiz) {
+
+    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
+    if (lpTrack == NULL) {
+        return;
+    }
+    AudioTrackJniStorage* pJniStorage = (AudioTrackJniStorage *)env->GetLongField(
+        thiz, javaAudioTrackFields.jniData);
+    if (pJniStorage == NULL || pJniStorage->mDeviceCallback != 0) {
+        return;
+    }
+    pJniStorage->mDeviceCallback =
+    new JNIDeviceCallback(env, thiz, pJniStorage->mCallbackData.audioTrack_ref,
+                          javaAudioTrackFields.postNativeEventInJava);
+    lpTrack->addAudioDeviceCallback(pJniStorage->mDeviceCallback);
+}
+
+static void android_media_AudioTrack_disableDeviceCallback(
+                JNIEnv *env,  jobject thiz) {
+
+    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
+    if (lpTrack == NULL) {
+        return;
+    }
+    AudioTrackJniStorage* pJniStorage = (AudioTrackJniStorage *)env->GetLongField(
+        thiz, javaAudioTrackFields.jniData);
+    if (pJniStorage == NULL || pJniStorage->mDeviceCallback == 0) {
+        return;
+    }
+    lpTrack->removeAudioDeviceCallback(pJniStorage->mDeviceCallback);
+    pJniStorage->mDeviceCallback.clear();
+}
+
+
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 static JNINativeMethod gMethods[] = {
@@ -1030,6 +1077,9 @@
                              "(I)I",     (void *)android_media_AudioTrack_attachAuxEffect},
     {"native_setOutputDevice", "(I)Z",
                              (void *)android_media_AudioTrack_setOutputDevice},
+    {"native_getRoutedDeviceId", "()I", (void *)android_media_AudioTrack_getRoutedDeviceId},
+    {"native_enableDeviceCallback", "()V", (void *)android_media_AudioTrack_enableDeviceCallback},
+    {"native_disableDeviceCallback", "()V", (void *)android_media_AudioTrack_disableDeviceCallback},
 };
 
 
diff --git a/core/jni/android_media_DeviceCallback.cpp b/core/jni/android_media_DeviceCallback.cpp
new file mode 100644
index 0000000..e159373
--- /dev/null
+++ b/core/jni/android_media_DeviceCallback.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+//#define LOG_NDEBUG 0
+
+#define LOG_TAG "AudioDeviceCallback-JNI"
+
+#include <utils/Log.h>
+#include <JNIHelp.h>
+#include <JniConstants.h>
+#include "core_jni_helpers.h"
+#include <media/AudioSystem.h>
+
+#include "android_media_DeviceCallback.h"
+
+
+// ----------------------------------------------------------------------------
+
+using namespace android;
+
+JNIDeviceCallback::JNIDeviceCallback(JNIEnv* env, jobject thiz, jobject weak_thiz,
+                                     jmethodID postEventFromNative)
+{
+
+    // Hold onto the AudioTrack/AudioRecord class for use in calling the static method
+    // that posts events to the application thread.
+    jclass clazz = env->GetObjectClass(thiz);
+    if (clazz == NULL) {
+        return;
+    }
+    mClass = (jclass)env->NewGlobalRef(clazz);
+
+    // We use a weak reference so the AudioTrack/AudioRecord object can be garbage collected.
+    // The reference is only used as a proxy for callbacks.
+    mObject  = env->NewGlobalRef(weak_thiz);
+
+    mPostEventFromNative = postEventFromNative;
+}
+
+JNIDeviceCallback::~JNIDeviceCallback()
+{
+    // remove global references
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    if (env == NULL) {
+        return;
+    }
+    env->DeleteGlobalRef(mObject);
+    env->DeleteGlobalRef(mClass);
+}
+
+void JNIDeviceCallback::onAudioDeviceUpdate(audio_io_handle_t audioIo,
+                                            audio_port_handle_t deviceId)
+{
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    if (env == NULL) {
+        return;
+    }
+
+    ALOGV("%s audioIo %d deviceId %d", __FUNCTION__, audioIo, deviceId);
+    env->CallStaticVoidMethod(mClass,
+                              mPostEventFromNative,
+                              mObject,
+                              AUDIO_NATIVE_EVENT_ROUTING_CHANGE, deviceId, 0, NULL);
+    if (env->ExceptionCheck()) {
+        ALOGW("An exception occurred while notifying an event.");
+        env->ExceptionClear();
+    }
+}
+
diff --git a/core/jni/android_media_DeviceCallback.h b/core/jni/android_media_DeviceCallback.h
new file mode 100644
index 0000000..7ae788e
--- /dev/null
+++ b/core/jni/android_media_DeviceCallback.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ANDROID_MEDIA_DEVICE_CALLBACK_H
+#define ANDROID_MEDIA_DEVICE_CALLBACK_H
+
+#include <system/audio.h>
+#include <media/AudioSystem.h>
+
+namespace android {
+
+// keep in sync with AudioSystem.java
+#define AUDIO_NATIVE_EVENT_ROUTING_CHANGE      1000
+
+class JNIDeviceCallback: public AudioSystem::AudioDeviceCallback
+{
+public:
+    JNIDeviceCallback(JNIEnv* env, jobject thiz, jobject weak_thiz, jmethodID postEventFromNative);
+    ~JNIDeviceCallback();
+
+    virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo,
+                                     audio_port_handle_t deviceId);
+
+private:
+    void sendEvent(int event);
+
+    jclass      mClass;     // Reference to AudioTrack/AudioRecord class
+    jobject     mObject;    // Weak ref to AudioTrack/AudioRecord Java object to call on
+    jmethodID   mPostEventFromNative; // postEventFromNative method ID.
+};
+
+}; // namespace android
+
+#endif // ANDROID_MEDIA_DEVICE_CALLBACK_H
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a162b4a..5669b91 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2352,11 +2352,6 @@
     <permission android:name="android.permission.BIND_CONDITION_PROVIDER_SERVICE"
         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: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"
@@ -2451,7 +2446,8 @@
                  android:backupAgent="com.android.server.backup.SystemBackupAgent"
                  android:killAfterRestore="false"
                  android:icon="@drawable/ic_launcher_android"
-                 android:supportsRtl="true">
+                 android:supportsRtl="true"
+                 android:theme="@style/Theme.Material.DayNight.DarkActionBar">
         <activity android:name="com.android.internal.app.ChooserActivity"
                 android:theme="@style/Theme.DeviceDefault.Resolver"
                 android:finishOnCloseSystemDialogs="true"
@@ -2484,7 +2480,7 @@
                 android:label="@string/managed_profile_label">
         </activity-alias>
         <activity android:name="com.android.internal.app.HeavyWeightSwitcherActivity"
-                android:theme="@style/Theme.Material.Light.Dialog"
+                android:theme="@style/Theme.Material.DayNight.Dialog"
                 android:label="@string/heavy_weight_switcher_title"
                 android:finishOnCloseSystemDialogs="true"
                 android:excludeFromRecents="true"
@@ -2517,7 +2513,7 @@
         <activity android:name="android.accounts.ChooseAccountActivity"
                 android:excludeFromRecents="true"
                 android:exported="true"
-                android:theme="@style/Theme.Material.Light.Dialog"
+                android:theme="@style/Theme.Material.DayNight.Dialog"
                 android:label="@string/choose_account_label"
                 android:process=":ui">
         </activity>
@@ -2525,14 +2521,14 @@
         <activity android:name="android.accounts.ChooseTypeAndAccountActivity"
                 android:excludeFromRecents="true"
                 android:exported="true"
-                android:theme="@style/Theme.Material.Light.Dialog"
+                android:theme="@style/Theme.Material.DayNight.Dialog"
                 android:label="@string/choose_account_label"
                 android:process=":ui">
         </activity>
 
         <activity android:name="android.accounts.ChooseAccountTypeActivity"
                 android:excludeFromRecents="true"
-                android:theme="@style/Theme.Material.Light.Dialog"
+                android:theme="@style/Theme.Material.DayNight.Dialog"
                 android:label="@string/choose_account_label"
                 android:process=":ui">
         </activity>
@@ -2540,19 +2536,19 @@
         <activity android:name="android.accounts.CantAddAccountActivity"
                 android:excludeFromRecents="true"
                 android:exported="true"
-                android:theme="@style/Theme.Material.Light.Dialog.NoActionBar"
+                android:theme="@style/Theme.Material.DayNight.Dialog.NoActionBar"
                 android:process=":ui">
         </activity>
 
         <activity android:name="android.accounts.GrantCredentialsPermissionActivity"
                 android:excludeFromRecents="true"
                 android:exported="true"
-                android:theme="@style/Theme.Material.Light.DialogWhenLarge"
+                android:theme="@style/Theme.Material.DayNight.DialogWhenLarge"
                 android:process=":ui">
         </activity>
 
         <activity android:name="android.content.SyncActivityTooManyDeletes"
-               android:theme="@style/Theme.Material.Light.Dialog"
+               android:theme="@style/Theme.Material.DayNight.Dialog"
                android:label="@string/sync_too_many_deletes"
                android:process=":ui">
         </activity>
@@ -2572,13 +2568,13 @@
         </activity>
 
         <activity android:name="com.android.internal.app.NetInitiatedActivity"
-                android:theme="@style/Theme.Material.Light.Dialog.Alert"
+                android:theme="@style/Theme.Material.DayNight.Dialog.Alert"
                 android:excludeFromRecents="true"
                 android:process=":ui">
         </activity>
 
         <activity android:name="com.android.internal.app.RestrictionsPinActivity"
-                android:theme="@style/Theme.Material.Light.Dialog.Alert"
+                android:theme="@style/Theme.Material.DayNight.Dialog.Alert"
                 android:excludeFromRecents="true"
                 android:windowSoftInputMode="adjustPan"
                 android:process=":ui">
diff --git a/core/res/res/drawable/scroll_indicator_material.xml b/core/res/res/drawable/scroll_indicator_material.xml
new file mode 100644
index 0000000..63cd584
--- /dev/null
+++ b/core/res/res/drawable/scroll_indicator_material.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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:tint="?attr/colorForeground">
+    <solid android:color="#1f000000" />
+    <size
+        android:height="1dp"
+        android:width="1dp" />
+</shape>
diff --git a/core/res/res/layout/alert_dialog_button_bar_material.xml b/core/res/res/layout/alert_dialog_button_bar_material.xml
index 1eea4e1..6e102f3 100644
--- a/core/res/res/layout/alert_dialog_button_bar_material.xml
+++ b/core/res/res/layout/alert_dialog_button_bar_material.xml
@@ -27,6 +27,7 @@
     android:paddingTop="4dp"
     android:paddingBottom="4dp"
     android:gravity="bottom"
+    android:allowStacking="@bool/allow_stacked_button_bar"
     style="?attr/buttonBarStyle">
 
     <Button
@@ -53,4 +54,4 @@
         style="?attr/buttonBarPositiveButtonStyle"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
-</com.android.internal.widget.ButtonBarLayout>
\ No newline at end of file
+</com.android.internal.widget.ButtonBarLayout>
diff --git a/core/res/res/layout/alert_dialog_material.xml b/core/res/res/layout/alert_dialog_material.xml
index bf1e383..95c2459 100644
--- a/core/res/res/layout/alert_dialog_material.xml
+++ b/core/res/res/layout/alert_dialog_material.xml
@@ -24,52 +24,51 @@
 
     <include layout="@layout/alert_dialog_title_material" />
 
-    <FrameLayout android:id="@+id/contentPanel"
+    <FrameLayout
+        android:id="@+id/contentPanel"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_weight="1"
         android:minHeight="48dp">
-        <View android:id="@+id/scrollIndicatorUp"
-            android:visibility="gone"
-            android:layout_width="match_parent"
-            android:layout_height="1dp"
-            android:layout_gravity="top"
-            android:background="@drawable/list_divider_material"/>
-        <ScrollView android:id="@+id/scrollView"
+
+        <ScrollView
+            android:id="@+id/scrollView"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:paddingTop="@dimen/dialog_padding_top_material"
             android:clipToPadding="false">
+
             <LinearLayout
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:orientation="vertical">
-                <TextView android:id="@+id/message"
-                          style="@style/TextAppearance.Material.Subhead"
-                          android:layout_width="match_parent"
-                          android:layout_height="wrap_content"
-                          android:paddingStart="?attr/dialogPreferredPadding"
-                          android:paddingTop="@dimen/dialog_padding_top_material"
-                          android:paddingEnd="?attr/dialogPreferredPadding" />
-                <Space android:id="@+id/textSpacerNoButtons"
-                       android:visibility="gone"
-                       android:layout_width="0dp"
-                       android:layout_height="@dimen/dialog_padding_top_material" />
+
+                <TextView
+                    android:id="@+id/message"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:paddingEnd="?attr/dialogPreferredPadding"
+                    android:paddingStart="?attr/dialogPreferredPadding"
+                    style="@style/TextAppearance.Material.Subhead" />
+
+                <Space
+                    android:id="@+id/textSpacerNoButtons"
+                    android:visibility="gone"
+                    android:layout_width="0dp"
+                    android:layout_height="@dimen/dialog_padding_top_material" />
             </LinearLayout>
         </ScrollView>
-        <View android:id="@+id/scrollIndicatorDown"
-            android:visibility="gone"
-            android:layout_width="match_parent"
-            android:layout_height="1dp"
-            android:layout_gravity="bottom"
-            android:background="@drawable/list_divider_material"/>
     </FrameLayout>
 
-    <FrameLayout android:id="@+id/customPanel"
+    <FrameLayout
+        android:id="@+id/customPanel"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_weight="1"
         android:minHeight="48dp">
-        <FrameLayout android:id="@+id/custom"
+
+        <FrameLayout
+            android:id="@+id/custom"
             android:layout_width="match_parent"
             android:layout_height="wrap_content" />
     </FrameLayout>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 29148178..1c4b5f7 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1998,6 +1998,13 @@
         <attr name="needsDefaultBackgrounds" format="boolean" />
     </declare-styleable>
 
+    <!-- @hide -->
+    <declare-styleable name="ButtonBarLayout">
+        <!-- Whether to automatically stack the buttons when there is not
+             enough space to lay them out side-by-side. -->
+        <attr name="allowStacking" format="boolean" />
+    </declare-styleable>
+
     <!-- Fragment animation class attributes. -->
     <declare-styleable name="FragmentAnimation">
         <attr name="fragmentOpenEnterAnimation" format="reference" />
@@ -2715,6 +2722,28 @@
             <enum name="add" value="16" />
         </attr>
 
+        <!-- Defines which scroll indicators should be displayed when the view
+             can be scrolled. Multiple values may be combined using logical OR,
+             for example "top|bottom". -->
+        <attr name="scrollIndicators">
+            <!-- No scroll indicators are displayed. -->
+            <flag name="none" value="0x0000" />
+            <!-- Displays top scroll indicator when view can be scrolled up. -->
+            <flag name="top" value="0x0100" />
+            <!-- Displays bottom scroll indicator when vew can be scrolled down. -->
+            <flag name="bottom" value="0x0200" />
+            <!-- Displays left scroll indicator when vew can be scrolled left. -->
+            <flag name="left" value="0x0400" />
+            <!-- Displays right scroll indicator when vew can be scrolled right. -->
+            <flag name="right" value="0x0800" />
+            <!-- Displays right scroll indicator when vew can be scrolled in the
+                 start direction. -->
+            <flag name="start" value="0x1000" />
+            <!-- Displays right scroll indicator when vew can be scrolled in the
+                 end direction. -->
+            <flag name="end" value="0x2000" />
+        </attr>
+
     </declare-styleable>
 
     <!-- Attributes that can be assigned to a tag for a particular View. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 83ac6c1..297b302 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2623,7 +2623,6 @@
   <public type="attr" name="fullBackupContent" />
 
   <public type="style" name="Widget.Material.Button.Colored" />
-
   <public type="style" name="Theme.Material.DayNight" />
   <public type="style" name="Theme.Material.DayNight.DarkActionBar" />
   <public type="style" name="Theme.Material.DayNight.Dialog" />
@@ -2686,4 +2685,5 @@
   <public type="attr" name="assistBlocked" />
   <public type="attr" name="stylusButtonPressable" />
   <public type="attr" name="supportsLaunchVoiceAssistFromKeyguard" />
+  <public type="attr" name="scrollIndicators" />
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index a57b3b8..28ffbfa 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2180,8 +2180,6 @@
   <java-symbol type="bool" name="config_defaultWindowFeatureContextMenu" />
 
   <java-symbol type="layout" name="simple_account_item" />
-  <java-symbol type="id" name="scrollIndicatorUp" />
-  <java-symbol type="id" name="scrollIndicatorDown" />
   <java-symbol type="array" name="config_sms_convert_destination_number_support" />
   <java-symbol type="string" name="prohibit_manual_network_selection_in_gobal_mode" />
   <java-symbol type="id" name="profile_button" />
@@ -2204,7 +2202,6 @@
   <java-symbol type="string" name="usb_midi_peripheral_manufacturer_name" />
   <java-symbol type="string" name="usb_midi_peripheral_product_name" />
 
-  <java-symbol type="bool" name="allow_stacked_button_bar" />
   <java-symbol type="id" name="spacer" />
 
   <java-symbol type="xml" name="bookmarks" />
@@ -2258,4 +2255,5 @@
   <java-symbol type="id" name="title_icon" />
   <java-symbol type="id" name="day_picker_view_pager" />
   <java-symbol type="layout" name="day_picker_content_material" />
+  <java-symbol type="drawable" name="scroll_indicator_material" />
 </resources>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index e679e0a..f02fed1 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -207,8 +207,8 @@
 
         <!-- Scrollbar attributes -->
         <item name="scrollbarFadeDuration">250</item>
-        <item name="scrollbarDefaultDelayBeforeFade">300</item>
-        <item name="scrollbarSize">10dip</item>
+        <item name="scrollbarDefaultDelayBeforeFade">400</item>
+        <item name="scrollbarSize">10dp</item>
         <item name="scrollbarThumbHorizontal">@drawable/scrollbar_handle_material</item>
         <item name="scrollbarThumbVertical">@drawable/scrollbar_handle_material</item>
         <item name="scrollbarTrackHorizontal">@null</item>
@@ -563,8 +563,8 @@
 
         <!-- Scrollbar attributes -->
         <item name="scrollbarFadeDuration">250</item>
-        <item name="scrollbarDefaultDelayBeforeFade">300</item>
-        <item name="scrollbarSize">10dip</item>
+        <item name="scrollbarDefaultDelayBeforeFade">400</item>
+        <item name="scrollbarSize">10dp</item>
         <item name="scrollbarThumbHorizontal">@drawable/scrollbar_handle_material</item>
         <item name="scrollbarThumbVertical">@drawable/scrollbar_handle_material</item>
         <item name="scrollbarTrackHorizontal">@null</item>
diff --git a/core/tests/coretests/src/android/util/FloatMathTest.java b/core/tests/coretests/src/android/util/FloatMathTest.java
deleted file mode 100644
index f479e2b..0000000
--- a/core/tests/coretests/src/android/util/FloatMathTest.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2007 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.util;
-
-import junit.framework.TestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-public class FloatMathTest extends TestCase {
-
-    @SmallTest
-    public void testSqrt() {
-        assertEquals(7, FloatMath.sqrt(49), 0);
-        assertEquals(10, FloatMath.sqrt(100), 0);
-        assertEquals(0, FloatMath.sqrt(0), 0);
-        assertEquals(1, FloatMath.sqrt(1), 0);
-    }
-
-    @SmallTest
-    public void testFloor() {
-        assertEquals(78, FloatMath.floor(78.89f), 0);
-        assertEquals(-79, FloatMath.floor(-78.89f), 0);
-    }
-
-    @SmallTest
-    public void testCeil() {
-        assertEquals(79, FloatMath.ceil(78.89f), 0);
-        assertEquals(-78, FloatMath.ceil(-78.89f), 0);
-    }
-
-    @SmallTest
-    public void testSin() {
-        assertEquals(0.0, FloatMath.sin(0), 0);
-        assertEquals(0.8414709848078965f, FloatMath.sin(1), 0);
-    }
-
-    @SmallTest
-    public void testCos() {
-        assertEquals(1.0f, FloatMath.cos(0), 0);
-        assertEquals(0.5403023058681398f, FloatMath.cos(1), 0);
-    }
-}
diff --git a/core/tests/coretests/src/com/android/internal/util/CallbackRegistryTest.java b/core/tests/coretests/src/com/android/internal/util/CallbackRegistryTest.java
new file mode 100644
index 0000000..c53f4cc
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/util/CallbackRegistryTest.java
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2015 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.internal.util;
+
+import junit.framework.TestCase;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class CallbackRegistryTest extends TestCase {
+
+    final Integer callback1 = 1;
+    final Integer callback2 = 2;
+    final Integer callback3 = 3;
+    CallbackRegistry<Integer, CallbackRegistryTest, Integer> registry;
+    int notify1;
+    int notify2;
+    int notify3;
+    int[] deepNotifyCount = new int[300];
+    Integer argValue;
+
+    private void addNotifyCount(Integer callback) {
+        if (callback == callback1) {
+            notify1++;
+        } else if (callback == callback2) {
+            notify2++;
+        } else if (callback == callback3) {
+            notify3++;
+        }
+        deepNotifyCount[callback]++;
+    }
+
+    public void testAddListener() {
+        CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier =
+                new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() {
+                    @Override
+                    public void onNotifyCallback(Integer callback, CallbackRegistryTest sender,
+                            int arg, Integer arg2) {
+                    }
+                };
+        registry = new CallbackRegistry<Integer, CallbackRegistryTest, Integer>(notifier);
+        Integer callback = 0;
+
+        assertNotNull(registry.copyListeners());
+        assertEquals(0, registry.copyListeners().size());
+
+        registry.add(callback);
+        ArrayList<Integer> callbacks = registry.copyListeners();
+        assertEquals(1, callbacks.size());
+        assertEquals(callback, callbacks.get(0));
+
+        registry.add(callback);
+        callbacks = registry.copyListeners();
+        assertEquals(1, callbacks.size());
+        assertEquals(callback, callbacks.get(0));
+
+        Integer otherListener = 1;
+        registry.add(otherListener);
+        callbacks = registry.copyListeners();
+        assertEquals(2, callbacks.size());
+        assertEquals(callback, callbacks.get(0));
+        assertEquals(otherListener, callbacks.get(1));
+
+        registry.remove(callback);
+        registry.add(callback);
+        callbacks = registry.copyListeners();
+        assertEquals(2, callbacks.size());
+        assertEquals(callback, callbacks.get(1));
+        assertEquals(otherListener, callbacks.get(0));
+    }
+
+    public void testSimpleNotify() {
+        CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier =
+                new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() {
+                    @Override
+                    public void onNotifyCallback(Integer callback, CallbackRegistryTest sender,
+                            int arg1, Integer arg) {
+                        assertEquals(arg1, (int) arg);
+                        addNotifyCount(callback);
+                        argValue = arg;
+                    }
+                };
+        registry = new CallbackRegistry<Integer, CallbackRegistryTest, Integer>(notifier);
+        registry.add(callback2);
+        Integer arg = 1;
+        registry.notifyCallbacks(this, arg, arg);
+        assertEquals(arg, argValue);
+        assertEquals(1, notify2);
+    }
+
+    public void testRemoveWhileNotifying() {
+        CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier =
+                new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() {
+                    @Override
+                    public void onNotifyCallback(Integer callback, CallbackRegistryTest sender,
+                            int arg1, Integer arg) {
+                        addNotifyCount(callback);
+                        if (callback == callback1) {
+                            registry.remove(callback1);
+                            registry.remove(callback2);
+                        }
+                    }
+                };
+        registry = new CallbackRegistry<Integer, CallbackRegistryTest, Integer>(notifier);
+        registry.add(callback1);
+        registry.add(callback2);
+        registry.add(callback3);
+        registry.notifyCallbacks(this, 0, null);
+        assertEquals(1, notify1);
+        assertEquals(1, notify2);
+        assertEquals(1, notify3);
+
+        ArrayList<Integer> callbacks = registry.copyListeners();
+        assertEquals(1, callbacks.size());
+        assertEquals(callback3, callbacks.get(0));
+    }
+
+    public void testDeepRemoveWhileNotifying() {
+        CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier =
+                new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() {
+                    @Override
+                    public void onNotifyCallback(Integer callback, CallbackRegistryTest sender,
+                            int arg1, Integer arg) {
+                        addNotifyCount(callback);
+                        registry.remove(callback);
+                        registry.notifyCallbacks(CallbackRegistryTest.this, arg1, null);
+                    }
+                };
+        registry = new CallbackRegistry<Integer, CallbackRegistryTest, Integer>(notifier);
+        registry.add(callback1);
+        registry.add(callback2);
+        registry.add(callback3);
+        registry.notifyCallbacks(this, 0, null);
+        assertEquals(1, notify1);
+        assertEquals(2, notify2);
+        assertEquals(3, notify3);
+
+        ArrayList<Integer> callbacks = registry.copyListeners();
+        assertEquals(0, callbacks.size());
+    }
+
+    public void testAddRemovedListener() {
+
+        CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier =
+                new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() {
+                    @Override
+                    public void onNotifyCallback(Integer callback, CallbackRegistryTest sender,
+                            int arg1, Integer arg) {
+                        addNotifyCount(callback);
+                        if (callback == callback1) {
+                            registry.remove(callback2);
+                        } else if (callback == callback3) {
+                            registry.add(callback2);
+                        }
+                    }
+                };
+        registry = new CallbackRegistry<Integer, CallbackRegistryTest, Integer>(notifier);
+
+        registry.add(callback1);
+        registry.add(callback2);
+        registry.add(callback3);
+        registry.notifyCallbacks(this, 0, null);
+
+        ArrayList<Integer> callbacks = registry.copyListeners();
+        assertEquals(3, callbacks.size());
+        assertEquals(callback1, callbacks.get(0));
+        assertEquals(callback3, callbacks.get(1));
+        assertEquals(callback2, callbacks.get(2));
+        assertEquals(1, notify1);
+        assertEquals(1, notify2);
+        assertEquals(1, notify3);
+    }
+
+    public void testVeryDeepRemoveWhileNotifying() {
+        final Integer[] callbacks = new Integer[deepNotifyCount.length];
+        for (int i = 0; i < callbacks.length; i++) {
+            callbacks[i] = i;
+        }
+        CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier =
+                new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() {
+                    @Override
+                    public void onNotifyCallback(Integer callback, CallbackRegistryTest sender,
+                            int arg1, Integer arg) {
+                        addNotifyCount(callback);
+                        registry.remove(callback);
+                        registry.remove(callbacks[callbacks.length - callback - 1]);
+                        registry.notifyCallbacks(CallbackRegistryTest.this, arg1, null);
+                    }
+                };
+        registry = new CallbackRegistry<Integer, CallbackRegistryTest, Integer>(notifier);
+        for (int i = 0; i < callbacks.length; i++) {
+            registry.add(callbacks[i]);
+        }
+        registry.notifyCallbacks(this, 0, null);
+        for (int i = 0; i < deepNotifyCount.length; i++) {
+            int expectedCount = Math.min(i + 1, deepNotifyCount.length - i);
+            assertEquals(expectedCount, deepNotifyCount[i]);
+        }
+
+        ArrayList<Integer> callbackList = registry.copyListeners();
+        assertEquals(0, callbackList.size());
+    }
+
+    public void testClear() {
+        CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier =
+                new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() {
+                    @Override
+                    public void onNotifyCallback(Integer callback, CallbackRegistryTest sender,
+                            int arg1, Integer arg) {
+                        addNotifyCount(callback);
+                    }
+                };
+        registry = new CallbackRegistry<Integer, CallbackRegistryTest, Integer>(notifier);
+        for (int i = 0; i < deepNotifyCount.length; i++) {
+            registry.add(i);
+        }
+        registry.clear();
+
+        ArrayList<Integer> callbackList = registry.copyListeners();
+        assertEquals(0, callbackList.size());
+
+        registry.notifyCallbacks(this, 0, null);
+        for (int i = 0; i < deepNotifyCount.length; i++) {
+            assertEquals(0, deepNotifyCount[i]);
+        }
+    }
+
+    public void testNestedClear() {
+        CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier =
+                new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() {
+                    @Override
+                    public void onNotifyCallback(Integer callback, CallbackRegistryTest sender,
+                            int arg1, Integer arg) {
+                        addNotifyCount(callback);
+                        registry.clear();
+                    }
+                };
+        registry = new CallbackRegistry<Integer, CallbackRegistryTest, Integer>(notifier);
+        for (int i = 0; i < deepNotifyCount.length; i++) {
+            registry.add(i);
+        }
+        registry.notifyCallbacks(this, 0, null);
+        for (int i = 0; i < deepNotifyCount.length; i++) {
+            assertEquals(1, deepNotifyCount[i]);
+        }
+
+        ArrayList<Integer> callbackList = registry.copyListeners();
+        assertEquals(0, callbackList.size());
+    }
+
+    public void testIsEmpty() throws Exception {
+        CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier =
+                new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() {
+                    @Override
+                    public void onNotifyCallback(Integer callback, CallbackRegistryTest sender,
+                            int arg, Integer arg2) {
+                    }
+                };
+        registry = new CallbackRegistry<Integer, CallbackRegistryTest, Integer>(notifier);
+        Integer callback = 0;
+
+        assertTrue(registry.isEmpty());
+        registry.add(callback);
+        assertFalse(registry.isEmpty());
+    }
+
+    public void testClone() throws Exception {
+        CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier =
+                new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() {
+                    @Override
+                    public void onNotifyCallback(Integer callback, CallbackRegistryTest sender,
+                            int arg, Integer arg2) {
+                    }
+                };
+        registry = new CallbackRegistry<Integer, CallbackRegistryTest, Integer>(notifier);
+
+        assertTrue(registry.isEmpty());
+        CallbackRegistry<Integer, CallbackRegistryTest, Integer> registry2 = registry.clone();
+        Integer callback = 0;
+        registry.add(callback);
+        assertFalse(registry.isEmpty());
+        assertTrue(registry2.isEmpty());
+        registry2 = registry.clone();
+        assertFalse(registry2.isEmpty());
+    }
+}
diff --git a/docs/html/jd_collections.js b/docs/html/jd_collections.js
index b28f978..8538671 100644
--- a/docs/html/jd_collections.js
+++ b/docs/html/jd_collections.js
@@ -1221,6 +1221,14 @@
       "https://support.google.com/googleplay/answer/2651410"
     ]
   },
+  "preview/landing/resources": {
+    "title": "",
+    "resources": [
+      "preview/api-overview.html",
+      "preview/setup-sdk.html",
+      "preview/samples.html"
+    ]
+  },
   "autolanding": {
     "title": "",
     "resources": [
diff --git a/docs/html/jd_tag_helpers.js b/docs/html/jd_tag_helpers.js
index 7538e4d..f03b1d7 100644
--- a/docs/html/jd_tag_helpers.js
+++ b/docs/html/jd_tag_helpers.js
@@ -13,6 +13,7 @@
   GOOGLE_RESOURCES,
   GUIDE_RESOURCES,
   SAMPLES_RESOURCES,
+  PREVIEW_RESOURCES,
   TOOLS_RESOURCES,
   TRAINING_RESOURCES,
   YOUTUBE_RESOURCES,
@@ -70,6 +71,7 @@
   'google': GOOGLE_RESOURCES,
   'guide': GUIDE_RESOURCES,
   'samples': SAMPLES_RESOURCES,
+  'preview': PREVIEW_RESOURCES,
   'tools': TOOLS_RESOURCES,
   'training': TRAINING_RESOURCES,
   'youtube': YOUTUBE_RESOURCES,
@@ -86,6 +88,7 @@
   {map:GOOGLE_BY_TAG,arr:GOOGLE_RESOURCES},
   {map:GUIDE_BY_TAG,arr:GUIDE_RESOURCES},
   {map:SAMPLES_BY_TAG,arr:SAMPLES_RESOURCES},
+  {map:PREVIEW_BY_TAG,arr:PREVIEW_RESOURCES},
   {map:TOOLS_BY_TAG,arr:TOOLS_RESOURCES},
   {map:TRAINING_BY_TAG,arr:TRAINING_RESOURCES},
   {map:YOUTUBE_BY_TAG,arr:YOUTUBE_RESOURCES},
diff --git a/docs/html/preview/api-overview.jd b/docs/html/preview/api-overview.jd
index f72ffbb..dde3c7be 100644
--- a/docs/html/preview/api-overview.jd
+++ b/docs/html/preview/api-overview.jd
@@ -1,5 +1,5 @@
 page.title=API Overview
-excludeFromSuggestions=true
+page.keywords=preview,sdk,compatibility
 sdk.platform.apiLevel=22
 @jd:body
 
diff --git a/docs/html/preview/index.jd b/docs/html/preview/index.jd
new file mode 100644
index 0000000..a2d0b18
--- /dev/null
+++ b/docs/html/preview/index.jd
@@ -0,0 +1,60 @@
+page.title=M Developer Preview
+page.tags=preview
+meta.tags="preview"
+fullpage=true
+page.viewport_width=970
+section.landing=true
+header.hide=1
+footer.hide=1
+@jd:body
+
+<section class="dac-expand dac-hero dac-light">
+  <div class="wrap">
+    <div class="cols dac-hero-content">
+      <div class="col-1of2 col-push-1of2 dac-hero-figure">
+        <img class="dac-hero-image" src="/design/media/hero-material-design.png">
+      </div>
+      <div class="col-1of2 col-pull-1of2">
+        <h1 class="dac-hero-title">M Developer Preview</h1>
+        <p class="dac-hero-description">
+          Get ready for the next official release of the platform. Test your apps
+          and give us feedback!
+        </p>
+        <a class="dac-hero-cta" href="{@docRoot}preview/setup-sdk.html">
+          <span class="dac-sprite dac-auto-chevron"></span>
+          Set up the Preview SDK
+        </a><br>
+        <a class="dac-hero-cta" href="{@docRoot}preview/api-overview.html">
+          <span class="dac-sprite dac-auto-chevron"></span>
+          Review the API changes
+        </a><br>
+        <a class="dac-hero-cta" href="https://code.google.com/p/android-developer-preview/">
+          <span class="dac-sprite dac-auto-chevron"></span>
+          Report issues
+        </a><br>
+      </div>
+    </div>
+  </div>
+</section>
+
+<section class="dac-section dac-gray dac-small dac-invert"><div class="wrap">
+  <h2 class="norule">Latest</h2>
+  <div class="resource-widget resource-flow-layout col-16"
+       data-query="collection:develop/landing/latest"
+       data-cardSizes="6x6"
+       data-maxResults="3"></div>
+</div></section>
+
+
+<section class="dac-section"><div class="wrap">
+  <h1 class="dac-section-title">Resources</h1>
+  <div class="dac-section-subtitle">
+    Check out these resources to help you get started with the M Developer Preview.
+  </div>
+  <div class="resource-widget resource-flow-layout col-16"
+       data-query="collection:preview/landing/resources"
+       data-cardSizes="6x6"
+       data-maxResults="6"></div>
+</div></section>
+
+
diff --git a/docs/html/preview/overview.jd b/docs/html/preview/overview.jd
new file mode 100644
index 0000000..00f1cfe
--- /dev/null
+++ b/docs/html/preview/overview.jd
@@ -0,0 +1,7 @@
+page.title=Preview Program Overview
+
+@jd:body
+
+<p>
+  This is an overview of the program. Bacon.
+</p>
\ No newline at end of file
diff --git a/docs/html/preview/preview_toc.cs b/docs/html/preview/preview_toc.cs
index bea4914..fbf73f6 100644
--- a/docs/html/preview/preview_toc.cs
+++ b/docs/html/preview/preview_toc.cs
@@ -1,6 +1,11 @@
 <ul id="nav">
 
   <li class="nav-section">
+    <div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/overview.html">
+      Program Overview</a></div>
+  </li>
+
+  <li class="nav-section">
     <div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/setup-sdk.html">
       Set up the SDK</a></div>
   </li>
@@ -29,9 +34,4 @@
       License Agreement</a></div>
   </li>
 
-  <li class="nav-section" style="margin: 20px 0 0 -10px;">
-    <div class="nav-section-header empty"><a href="<?cs var:toroot ?>index.html" class="back-link">
-      Developer Home</a></div>
-  </li>
-
 </ul>
diff --git a/docs/html/preview/reference.jd b/docs/html/preview/reference.jd
index ee1f24d..2d30c62 100644
--- a/docs/html/preview/reference.jd
+++ b/docs/html/preview/reference.jd
@@ -9,7 +9,7 @@
 
 <ul>
   <li>
-    <a href="http://storage.googleapis.com/androiddevelopers/preview/l-developer-preview-reference.zip">
+    <a href="http://storage.googleapis.com/androiddevelopers/preview/m-developer-preview-reference.zip">
       M Developer Preview reference</a>
   </li>
 </ul>
\ No newline at end of file
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index b03fe3a..4a06805 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -295,9 +295,9 @@
     @Override
     public void setHotspotBounds(int left, int top, int right, int bottom) {
         if (mHotspotBounds == null) {
-            mHotspotBounds = new Rect(left, top, bottom, right);
+            mHotspotBounds = new Rect(left, top, right, bottom);
         } else {
-            mHotspotBounds.set(left, top, bottom, right);
+            mHotspotBounds.set(left, top, right, bottom);
         }
 
         if (mCurrDrawable != null) {
diff --git a/keystore/java/android/security/AndroidKeyStoreProvider.java b/keystore/java/android/security/AndroidKeyStoreProvider.java
index 518067b..257ab54 100644
--- a/keystore/java/android/security/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/AndroidKeyStoreProvider.java
@@ -104,13 +104,13 @@
      *
      * <p>The following primitives are supported: {@link Cipher} and {@link Mac}.
      *
-     * @return KeyStore operation handle or {@code null} if the provided primitive's KeyStore
-     *         operation is not in progress.
+     * @return KeyStore operation handle or {@code 0} if the provided primitive's KeyStore operation
+     *         is not in progress.
      *
      * @throws IllegalArgumentException if the provided primitive is not supported or is not backed
      *         by AndroidKeyStore provider.
      */
-    public static Long getKeyStoreOperationHandle(Object cryptoPrimitive) {
+    public static long getKeyStoreOperationHandle(Object cryptoPrimitive) {
         if (cryptoPrimitive == null) {
             throw new NullPointerException();
         }
diff --git a/keystore/java/android/security/KeyStoreCipherSpi.java b/keystore/java/android/security/KeyStoreCipherSpi.java
index 20dd524..094aa75 100644
--- a/keystore/java/android/security/KeyStoreCipherSpi.java
+++ b/keystore/java/android/security/KeyStoreCipherSpi.java
@@ -134,7 +134,7 @@
      * error conditions in between.
      */
     private IBinder mOperationToken;
-    private Long mOperationHandle;
+    private long mOperationHandle;
     private KeyStoreCryptoOperationChunkedStreamer mMainDataStreamer;
 
     /**
@@ -247,7 +247,7 @@
         mIvHasBeenUsed = false;
         mAdditionalEntropyForBegin = null;
         mOperationToken = null;
-        mOperationHandle = null;
+        mOperationHandle = 0;
         mMainDataStreamer = null;
         mCachedException = null;
     }
@@ -258,7 +258,7 @@
             mOperationToken = null;
             mKeyStore.abort(operationToken);
         }
-        mOperationHandle = null;
+        mOperationHandle = 0;
         mMainDataStreamer = null;
         mAdditionalEntropyForBegin = null;
         mCachedException = null;
@@ -322,6 +322,9 @@
         if (mOperationToken == null) {
             throw new IllegalStateException("Keystore returned null operation token");
         }
+        if (mOperationHandle == 0) {
+            throw new IllegalStateException("Keystore returned invalid operation handle");
+        }
 
         loadAlgorithmSpecificParametersFromBeginResult(keymasterOutputArgs);
         mFirstOperationInitiated = true;
@@ -471,7 +474,7 @@
     }
 
     @Override
-    public Long getOperationHandle() {
+    public long getOperationHandle() {
         return mOperationHandle;
     }
 
diff --git a/keystore/java/android/security/KeyStoreCryptoOperation.java b/keystore/java/android/security/KeyStoreCryptoOperation.java
index 19abd05..c5cf211 100644
--- a/keystore/java/android/security/KeyStoreCryptoOperation.java
+++ b/keystore/java/android/security/KeyStoreCryptoOperation.java
@@ -25,7 +25,7 @@
     /**
      * Gets the KeyStore operation handle of this crypto operation.
      *
-     * @return handle or {@code null} if the KeyStore operation is not in progress.
+     * @return handle or {@code 0} if the KeyStore operation is not in progress.
      */
-    Long getOperationHandle();
+    long getOperationHandle();
 }
diff --git a/keystore/java/android/security/KeyStoreHmacSpi.java b/keystore/java/android/security/KeyStoreHmacSpi.java
index e993b50..0dbe788 100644
--- a/keystore/java/android/security/KeyStoreHmacSpi.java
+++ b/keystore/java/android/security/KeyStoreHmacSpi.java
@@ -75,7 +75,7 @@
     // Fields below are reset when engineDoFinal succeeds.
     private KeyStoreCryptoOperationChunkedStreamer mChunkedStreamer;
     private IBinder mOperationToken;
-    private Long mOperationHandle;
+    private long mOperationHandle;
 
     protected KeyStoreHmacSpi(int keymasterDigest) {
         mKeymasterDigest = keymasterDigest;
@@ -128,7 +128,7 @@
             mOperationToken = null;
             mKeyStore.abort(operationToken);
         }
-        mOperationHandle = null;
+        mOperationHandle = 0;
         mChunkedStreamer = null;
     }
 
@@ -138,7 +138,7 @@
             mOperationToken = null;
             mKeyStore.abort(operationToken);
         }
-        mOperationHandle = null;
+        mOperationHandle = 0;
         mChunkedStreamer = null;
     }
 
@@ -187,6 +187,9 @@
         if (mOperationToken == null) {
             throw new IllegalStateException("Keystore returned null operation token");
         }
+        if (mOperationHandle == 0) {
+            throw new IllegalStateException("Keystore returned invalid operation handle");
+        }
 
         mChunkedStreamer = new KeyStoreCryptoOperationChunkedStreamer(
                 new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
@@ -249,7 +252,7 @@
     }
 
     @Override
-    public Long getOperationHandle() {
+    public long getOperationHandle() {
         return mOperationHandle;
     }
 }
diff --git a/libs/hwui/tests/main.cpp b/libs/hwui/tests/main.cpp
index aca7c52..2f79c58 100644
--- a/libs/hwui/tests/main.cpp
+++ b/libs/hwui/tests/main.cpp
@@ -58,13 +58,20 @@
 class TreeContentAnimation {
 public:
     virtual ~TreeContentAnimation() {}
-    virtual int getFrameCount() { return 150; }
+    int frameCount = 150;
+    virtual int getFrameCount() { return frameCount; }
+    virtual void setFrameCount(int fc) {
+        if (fc > 0) {
+            frameCount = fc;
+        }
+    }
     virtual void createContent(int width, int height, DisplayListCanvas* renderer) = 0;
     virtual void doFrame(int frameNr) = 0;
 
     template <class T>
-    static void run() {
+    static void run(int frameCount) {
         T animation;
+        animation.setFrameCount(frameCount);
 
         TestContext testContext;
 
@@ -137,9 +144,10 @@
         renderer->insertReorderBarrier(false);
     }
     void doFrame(int frameNr) override {
+        int curFrame = frameNr % 150;
         for (size_t ci = 0; ci < cards.size(); ci++) {
-            cards[ci]->mutateStagingProperties().setTranslationX(frameNr);
-            cards[ci]->mutateStagingProperties().setTranslationY(frameNr);
+            cards[ci]->mutateStagingProperties().setTranslationX(curFrame);
+            cards[ci]->mutateStagingProperties().setTranslationY(curFrame);
             cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
         }
     }
@@ -159,6 +167,47 @@
     }
 };
 
+class ShadowGrid2Animation : public TreeContentAnimation {
+public:
+    std::vector< sp<RenderNode> > cards;
+    void createContent(int width, int height, DisplayListCanvas* renderer) override {
+        renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
+        renderer->insertReorderBarrier(true);
+
+        for (int x = dp(8); x < (width - dp(58)); x += dp(58)) {
+            for (int y = dp(8); y < (height - dp(58)); y += dp(58)) {
+                sp<RenderNode> card = createCard(x, y, dp(50), dp(50));
+                renderer->drawRenderNode(card.get());
+                cards.push_back(card);
+            }
+        }
+
+        renderer->insertReorderBarrier(false);
+    }
+    void doFrame(int frameNr) override {
+        int curFrame = frameNr % 150;
+        for (size_t ci = 0; ci < cards.size(); ci++) {
+            cards[ci]->mutateStagingProperties().setTranslationX(curFrame);
+            cards[ci]->mutateStagingProperties().setTranslationY(curFrame);
+            cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+        }
+    }
+private:
+    sp<RenderNode> createCard(int x, int y, int width, int height) {
+        sp<RenderNode> node = new RenderNode();
+        node->mutateStagingProperties().setLeftTopRightBottom(x, y, x + width, y + height);
+        node->mutateStagingProperties().setElevation(dp(16));
+        node->mutateStagingProperties().mutableOutline().setRoundRect(0, 0, width, height, dp(6), 1);
+        node->mutateStagingProperties().mutableOutline().setShouldClip(true);
+        node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y | RenderNode::Z);
+
+        DisplayListCanvas* renderer = startRecording(node.get());
+        renderer->drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode);
+        endRecording(renderer, node.get());
+        return node;
+    }
+};
+
 class RectGridAnimation : public TreeContentAnimation {
 public:
     sp<RenderNode> card;
@@ -172,8 +221,9 @@
         renderer->insertReorderBarrier(false);
     }
     void doFrame(int frameNr) override {
-        card->mutateStagingProperties().setTranslationX(frameNr);
-        card->mutateStagingProperties().setTranslationY(frameNr);
+        int curFrame = frameNr % 150;
+        card->mutateStagingProperties().setTranslationX(curFrame);
+        card->mutateStagingProperties().setTranslationY(curFrame);
         card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
     }
 private:
@@ -220,8 +270,9 @@
     }
 
     void doFrame(int frameNr) override {
-        card->mutateStagingProperties().setTranslationX(frameNr);
-        card->mutateStagingProperties().setTranslationY(frameNr);
+        int curFrame = frameNr % 150;
+        card->mutateStagingProperties().setTranslationX(curFrame);
+        card->mutateStagingProperties().setTranslationY(curFrame);
         card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
     }
 private:
@@ -248,10 +299,11 @@
     }
 };
 
-typedef void (*testProc)();
+typedef void (*testProc)(int);
 
 std::map<const char*, testProc, cstr_cmp> gTestMap {
     {"shadowgrid", TreeContentAnimation::run<ShadowGridAnimation>},
+    {"shadowgrid2", TreeContentAnimation::run<ShadowGrid2Animation>},
     {"rectgrid", TreeContentAnimation::run<RectGridAnimation> },
     {"oval", TreeContentAnimation::run<OvalAnimation> },
 };
@@ -263,7 +315,28 @@
         printf("Error: couldn't find test %s\n", testName);
         return 1;
     }
-    proc();
+    int loopCount = 1;
+    if (argc > 2) {
+        loopCount = atoi(argv[2]);
+        if (!loopCount) {
+            printf("Invalid loop count!\n");
+            return 1;
+        }
+    }
+    int frameCount = 150;
+    if (argc > 3) {
+        frameCount = atoi(argv[3]);
+        if (frameCount < 1) {
+            printf("Invalid frame count!\n");
+            return 1;
+        }
+    }
+    if (loopCount < 0) {
+        loopCount = INT_MAX;
+    }
+    for (int i = 0; i < loopCount; i++) {
+        proc(frameCount);
+    }
     printf("Success!\n");
     return 0;
 }
diff --git a/media/java/android/media/AudioDevicePort.java b/media/java/android/media/AudioDevicePort.java
index 82da27d..c078260 100644
--- a/media/java/android/media/AudioDevicePort.java
+++ b/media/java/android/media/AudioDevicePort.java
@@ -83,6 +83,16 @@
         if (o == null || !(o instanceof AudioDevicePort)) {
             return false;
         }
+        AudioDevicePort other = (AudioDevicePort)o;
+        if (mType != other.type()) {
+            return false;
+        }
+        if (mAddress == null && other.address() != null) {
+            return false;
+        }
+        if (!mAddress.equals(other.address())) {
+            return false;
+        }
         return super.equals(o);
     }
 
diff --git a/media/java/android/media/AudioDevicesManager.java b/media/java/android/media/AudioDevicesManager.java
index ca238d7..8b83c17 100644
--- a/media/java/android/media/AudioDevicesManager.java
+++ b/media/java/android/media/AudioDevicesManager.java
@@ -96,7 +96,7 @@
      * @param flags A set of bitflags specifying the criteria to test.
      * @see {@link LIST_DEVICES_OUTPUTS} and {@link LIST_DEVICES_INPUTS}
      **/
-    private boolean checkFlags(AudioDevicePort port, int flags) {
+    private static boolean checkFlags(AudioDevicePort port, int flags) {
         return port.role() == AudioPort.ROLE_SINK && (flags & LIST_DEVICES_OUTPUTS) != 0 ||
                port.role() == AudioPort.ROLE_SOURCE && (flags & LIST_DEVICES_INPUTS) != 0;
     }
@@ -110,8 +110,21 @@
      * @return A (possibly zero-length) array of AudioDeviceInfo objects.
      */
     public AudioDeviceInfo[] listDevices(int flags) {
+        return listDevicesStatic(flags);
+    }
+
+    /**
+     * Generates a list of AudioDeviceInfo objects corresponding to the audio devices currently
+     * connected to the system and meeting the criteria specified in the <code>flags</code>
+     * parameter.
+     * @param flags A set of bitflags specifying the criteria to test.
+     * @see {@link LIST_DEVICES_OUTPUTS}, {@link LIST_DEVICES_INPUTS} and {@link LIST_DEVICES_ALL}.
+     * @return A (possibly zero-length) array of AudioDeviceInfo objects.
+     * @hide
+     */
+    public static AudioDeviceInfo[] listDevicesStatic(int flags) {
         ArrayList<AudioDevicePort> ports = new ArrayList<AudioDevicePort>();
-        int status = mAudioManager.listAudioDevicePorts(ports);
+        int status = AudioManager.listAudioDevicePorts(ports);
         if (status != AudioManager.SUCCESS) {
             // fail and bail!
             return new AudioDeviceInfo[0];
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 6eaf812..19900d0 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3401,7 +3401,7 @@
      * @param ports An AudioPort ArrayList where the list will be returned.
      * @hide
      */
-    public int listAudioPorts(ArrayList<AudioPort> ports) {
+    public static int listAudioPorts(ArrayList<AudioPort> ports) {
         return updateAudioPortCache(ports, null);
     }
 
@@ -3410,7 +3410,7 @@
      * @see listAudioPorts(ArrayList<AudioPort>)
      * @hide
      */
-    public int listAudioDevicePorts(ArrayList<AudioDevicePort> devices) {
+    public static int listAudioDevicePorts(ArrayList<AudioDevicePort> devices) {
         ArrayList<AudioPort> ports = new ArrayList<AudioPort>();
         int status = updateAudioPortCache(ports, null);
         if (status == SUCCESS) {
@@ -3447,7 +3447,7 @@
      *         patch[0] contains the newly created patch
      * @hide
      */
-    public int createAudioPatch(AudioPatch[] patch,
+    public static int createAudioPatch(AudioPatch[] patch,
                                  AudioPortConfig[] sources,
                                  AudioPortConfig[] sinks) {
         return AudioSystem.createAudioPatch(patch, sources, sinks);
@@ -3464,7 +3464,7 @@
      *         - {@link #ERROR} if patch cannot be released for any other reason.
      * @hide
      */
-    public int releaseAudioPatch(AudioPatch patch) {
+    public static int releaseAudioPatch(AudioPatch patch) {
         return AudioSystem.releaseAudioPatch(patch);
     }
 
@@ -3473,7 +3473,7 @@
      * @param patches An AudioPatch array where the list will be returned.
      * @hide
      */
-    public int listAudioPatches(ArrayList<AudioPatch> patches) {
+    public static int listAudioPatches(ArrayList<AudioPatch> patches) {
         return updateAudioPortCache(null, patches);
     }
 
@@ -3482,7 +3482,7 @@
      * AudioGain.buildConfig()
      * @hide
      */
-    public int setAudioPortGain(AudioPort port, AudioGainConfig gain) {
+    public static int setAudioPortGain(AudioPort port, AudioGainConfig gain) {
         if (port == null || gain == null) {
             return ERROR_BAD_VALUE;
         }
diff --git a/media/java/android/media/AudioMixPort.java b/media/java/android/media/AudioMixPort.java
index 9fac8d1..ab55c8d 100644
--- a/media/java/android/media/AudioMixPort.java
+++ b/media/java/android/media/AudioMixPort.java
@@ -20,16 +20,21 @@
  * The AudioMixPort is a specialized type of AudioPort
  * describing an audio mix or stream at an input or output stream of the audio
  * framework.
+ * In addition to base audio port attributes, the mix descriptor contains:
+ * - the unique audio I/O handle assigned by AudioFlinger to this mix.
  * @see AudioPort
  * @hide
  */
 
 public class AudioMixPort extends AudioPort {
 
-    AudioMixPort(AudioHandle handle, int role, String deviceName,
+    private final int mIoHandle;
+
+    AudioMixPort(AudioHandle handle, int ioHandle, int role, String deviceName,
             int[] samplingRates, int[] channelMasks,
             int[] formats, AudioGain[] gains) {
         super(handle, role, deviceName, samplingRates, channelMasks, formats, gains);
+        mIoHandle = ioHandle;
     }
 
     /**
@@ -41,11 +46,23 @@
         return new AudioMixPortConfig(this, samplingRate, channelMask, format, gain);
     }
 
+    /**
+     * Get the device type (e.g AudioManager.DEVICE_OUT_SPEAKER)
+     */
+    public int ioHandle() {
+        return mIoHandle;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (o == null || !(o instanceof AudioMixPort)) {
             return false;
         }
+        AudioMixPort other = (AudioMixPort)o;
+        if (mIoHandle != other.ioHandle()) {
+            return false;
+        }
+
         return super.equals(o);
     }
 
diff --git a/media/java/android/media/AudioPort.java b/media/java/android/media/AudioPort.java
index 88e784a..7328d7a 100644
--- a/media/java/android/media/AudioPort.java
+++ b/media/java/android/media/AudioPort.java
@@ -93,6 +93,14 @@
     }
 
     /**
+     * Get the system unique device ID.
+     */
+    public int id() {
+        return mHandle.id();
+    }
+
+
+    /**
      * Get the audio port role
      */
     public int role() {
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 472da02..11671d8 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -116,11 +116,6 @@
      */
     private static final int NATIVE_EVENT_NEW_POS = 3;
 
-    /**
-     * Event id denotes when the routing changes.
-     */
-    private final static int NATIVE_EVENT_ROUTING_CHANGE = 1000;
-
     private final static String TAG = "android.media.AudioRecord";
 
     /** @hide */
@@ -161,6 +156,12 @@
     @SuppressWarnings("unused")
     private long mNativeCallbackCookie;
 
+    /**
+     * Accessed by native methods: provides access to the JNIDeviceCallback instance.
+     */
+    @SuppressWarnings("unused")
+    private long mNativeDeviceCallback;
+
 
     //---------------------------------------------------------
     // Member variables
@@ -1205,6 +1206,17 @@
      * Returns an {@link AudioDeviceInfo} identifying the current routing of this AudioRecord.
      */
     public AudioDeviceInfo getRoutedDevice() {
+        int deviceId = native_getRoutedDeviceId();
+        if (deviceId == 0) {
+            return null;
+        }
+        AudioDeviceInfo[] devices =
+                AudioDevicesManager.listDevicesStatic(AudioDevicesManager.LIST_DEVICES_INPUTS);
+        for (int i = 0; i < devices.length; i++) {
+            if (devices[i].getId() == deviceId) {
+                return devices[i];
+            }
+        }
         return null;
     }
 
@@ -1224,6 +1236,9 @@
             android.os.Handler handler) {
         if (listener != null && !mRoutingChangeListeners.containsKey(listener)) {
             synchronized (mRoutingChangeListeners) {
+                if (mRoutingChangeListeners.size() == 0) {
+                    native_enableDeviceCallback();
+                }
                 mRoutingChangeListeners.put(
                     listener, new NativeRoutingEventHandlerDelegate(this, listener, handler));
             }
@@ -1238,6 +1253,9 @@
         synchronized (mRoutingChangeListeners) {
             if (mRoutingChangeListeners.containsKey(listener)) {
                 mRoutingChangeListeners.remove(listener);
+                if (mRoutingChangeListeners.size() == 0) {
+                    native_disableDeviceCallback();
+                }
             }
         }
     }
@@ -1271,7 +1289,7 @@
                             return;
                         }
                         switch(msg.what) {
-                        case NATIVE_EVENT_ROUTING_CHANGE:
+                        case AudioSystem.NATIVE_EVENT_ROUTING_CHANGE:
                             if (listener != null) {
                                 listener.onAudioRecordRouting(record);
                             }
@@ -1299,10 +1317,11 @@
         synchronized (mRoutingChangeListeners) {
             values = mRoutingChangeListeners.values();
         }
+        AudioManager.resetAudioPortGeneration();
         for(NativeRoutingEventHandlerDelegate delegate : values) {
             Handler handler = delegate.getHandler();
             if (handler != null) {
-                handler.sendEmptyMessage(NATIVE_EVENT_ROUTING_CHANGE);
+                handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE);
             }
         }
     }
@@ -1341,10 +1360,14 @@
             return false;
         }
 
-        mPreferredDevice = deviceInfo;
-        int preferredDeviceId = mPreferredDevice != null ? deviceInfo.getId() : 0;
-
-        return native_setInputDevice(preferredDeviceId);
+        int preferredDeviceId = deviceInfo != null ? deviceInfo.getId() : 0;
+        boolean status = native_setInputDevice(preferredDeviceId);
+        if (status == true) {
+            synchronized (this) {
+                mPreferredDevice = deviceInfo;
+            }
+        }
+        return status;
     }
 
     /**
@@ -1352,7 +1375,9 @@
      * is not guarenteed to correspond to the actual device being used for recording.
      */
     public AudioDeviceInfo getPreferredInputDevice() {
-        return mPreferredDevice;
+        synchronized (this) {
+            return mPreferredDevice;
+        }
     }
 
     //---------------------------------------------------------
@@ -1435,6 +1460,11 @@
             return;
         }
 
+        if (what == AudioSystem.NATIVE_EVENT_ROUTING_CHANGE) {
+            recorder.broadcastRoutingChange();
+            return;
+        }
+
         if (recorder.mEventHandler != null) {
             Message m =
                 recorder.mEventHandler.obtainMessage(what, arg1, arg2, obj);
@@ -1486,7 +1516,9 @@
             int sampleRateInHz, int channelCount, int audioFormat);
 
     private native final boolean native_setInputDevice(int deviceId);
-
+    private native final int native_getRoutedDeviceId();
+    private native final void native_enableDeviceCallback();
+    private native final void native_disableDeviceCallback();
 
     //---------------------------------------------------------
     // Utility methods
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 3dae543..ee12374 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -721,5 +721,11 @@
             (1 << STREAM_RING) |
             (1 << STREAM_NOTIFICATION) |
             (1 << STREAM_SYSTEM);
+
+    /**
+     * Event posted by AudioTrack and AudioRecord JNI (JNIDeviceCallback) when routing changes.
+     * Keep in sync with core/jni/android_media_DeviceCallback.h.
+     */
+    final static int NATIVE_EVENT_ROUTING_CHANGE = 1000;
 }
 
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index cb05cc5..a66a1e5 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -178,12 +178,6 @@
      */
     private static final int NATIVE_EVENT_NEW_POS = 4;
 
-    /**
-     * Event id denotes when the routing changes.
-     */
-    private final static int NATIVE_EVENT_ROUTING_CHANGE = 1000;
-
-
     private final static String TAG = "android.media.AudioTrack";
 
 
@@ -2057,11 +2051,14 @@
         if (deviceInfo != null && !deviceInfo.isSink()) {
             return false;
         }
-
-        mPreferredDevice = deviceInfo;
-        int preferredDeviceId = mPreferredDevice != null ? deviceInfo.getId() : 0;
-
-        return native_setOutputDevice(preferredDeviceId);
+        int preferredDeviceId = deviceInfo != null ? deviceInfo.getId() : 0;
+        boolean status = native_setOutputDevice(preferredDeviceId);
+        if (status == true) {
+            synchronized (this) {
+                mPreferredDevice = deviceInfo;
+            }
+        }
+        return status;
     }
 
     /**
@@ -2069,7 +2066,9 @@
      * is not guaranteed to correspond to the actual device being used for playback.
      */
     public AudioDeviceInfo getPreferredOutputDevice() {
-        return mPreferredDevice;
+        synchronized (this) {
+            return mPreferredDevice;
+        }
     }
 
     //--------------------------------------------------------------------------
@@ -2079,6 +2078,17 @@
      * Returns an {@link AudioDeviceInfo} identifying the current routing of this AudioTrack.
      */
     public AudioDeviceInfo getRoutedDevice() {
+        int deviceId = native_getRoutedDeviceId();
+        if (deviceId == 0) {
+            return null;
+        }
+        AudioDeviceInfo[] devices =
+                AudioDevicesManager.listDevicesStatic(AudioDevicesManager.LIST_DEVICES_OUTPUTS);
+        for (int i = 0; i < devices.length; i++) {
+            if (devices[i].getId() == deviceId) {
+                return devices[i];
+            }
+        }
         return null;
     }
 
@@ -2098,6 +2108,9 @@
             android.os.Handler handler) {
         if (listener != null && !mRoutingChangeListeners.containsKey(listener)) {
             synchronized (mRoutingChangeListeners) {
+                if (mRoutingChangeListeners.size() == 0) {
+                    native_enableDeviceCallback();
+                }
                 mRoutingChangeListeners.put(
                     listener, new NativeRoutingEventHandlerDelegate(this, listener, handler));
             }
@@ -2113,6 +2126,9 @@
             if (mRoutingChangeListeners.containsKey(listener)) {
                 mRoutingChangeListeners.remove(listener);
             }
+            if (mRoutingChangeListeners.size() == 0) {
+                native_disableDeviceCallback();
+            }
         }
     }
 
@@ -2124,10 +2140,11 @@
         synchronized (mRoutingChangeListeners) {
             values = mRoutingChangeListeners.values();
         }
+        AudioManager.resetAudioPortGeneration();
         for(NativeRoutingEventHandlerDelegate delegate : values) {
             Handler handler = delegate.getHandler();
             if (handler != null) {
-                handler.sendEmptyMessage(NATIVE_EVENT_ROUTING_CHANGE);
+                handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE);
             }
         }
     }
@@ -2240,7 +2257,7 @@
                             return;
                         }
                         switch(msg.what) {
-                        case NATIVE_EVENT_ROUTING_CHANGE:
+                        case AudioSystem.NATIVE_EVENT_ROUTING_CHANGE:
                             if (listener != null) {
                                 listener.onAudioTrackRouting(track);
                             }
@@ -2273,6 +2290,10 @@
             return;
         }
 
+        if (what == AudioSystem.NATIVE_EVENT_ROUTING_CHANGE) {
+            track.broadcastRoutingChange();
+            return;
+        }
         NativePositionEventHandlerDelegate delegate = track.mEventHandlerDelegate;
         if (delegate != null) {
             Handler handler = delegate.getHandler();
@@ -2281,7 +2302,6 @@
                 handler.sendMessage(m);
             }
         }
-
     }
 
 
@@ -2362,6 +2382,9 @@
     private native final int native_setAuxEffectSendLevel(float level);
 
     private native final boolean native_setOutputDevice(int deviceId);
+    private native final int native_getRoutedDeviceId();
+    private native final void native_enableDeviceCallback();
+    private native final void native_disableDeviceCallback();
 
     //---------------------------------------------------------
     // Utility methods
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 8220a74..6f7b583 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -918,9 +918,9 @@
         }
 
         /**
-         * This indicates that no key has been set to perform the requested
-         * decrypt operation.  The operation can be retried after adding
-         * a decryption key.
+         * This indicates that the requested key was not found when trying to
+         * perform a decrypt operation.  The operation can be retried after adding
+         * the correct decryption key.
          */
         public static final int ERROR_NO_KEY = 1;
 
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 0bfc796..0000000
--- a/media/java/android/media/routing/MediaRouteSelector.java
+++ /dev/null
@@ -1,356 +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.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 8d58a60..285e5f7 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.MediaSession;
 import android.media.session.ParcelableVolumeInfo;
@@ -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 playFromMediaId(String mediaId, in Bundle extras);
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index dd81a22..2acee04 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;
@@ -120,17 +119,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.
      *
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index cee82b4..e1e9b79 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -29,7 +29,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;
@@ -225,23 +224,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/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java b/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java
index e2df77c..4d3edb8 100644
--- a/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java
+++ b/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java
@@ -287,7 +287,7 @@
      */
     public PendingIntent getSettingsPendingIntent() {
         if (mSettingsPendingIntent == null) {
-            Intent settingsIntent = new Intent(Settings.ACTION_WIFI_DISPLAY_SETTINGS);
+            Intent settingsIntent = new Intent(Settings.ACTION_CAST_SETTINGS);
             settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                     | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
                     | Intent.FLAG_ACTIVITY_CLEAR_TOP);
diff --git a/packages/Keyguard/res/values/strings.xml b/packages/Keyguard/res/values/strings.xml
index e060b4a..49ce427 100644
--- a/packages/Keyguard/res/values/strings.xml
+++ b/packages/Keyguard/res/values/strings.xml
@@ -96,8 +96,6 @@
     <string name="keyguard_widget_24_hours_format" translatable="false">kk\uee01mm</string>
 
     <string name="keyguard_accessibility_pattern_unlock">Pattern unlock.</string>
-    <!-- Accessibility description of the face unlock. [CHAR_LIMIT=none] -->
-    <string name="keyguard_accessibility_face_unlock">Face unlock.</string>
     <!-- Accessibility description of the pin lock. [CHAR_LIMIT=none] -->
     <string name="keyguard_accessibility_pin_unlock">Pin unlock.</string>
     <!-- Accessibility description of the password lock. [CHAR_LIMIT=none] -->
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
index 845d53a..929258d 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
@@ -162,7 +162,8 @@
             switchImeButton.setOnClickListener(new OnClickListener() {
                 public void onClick(View v) {
                     mCallback.userActivity(); // Leave the screen on a bit longer
-                    mImm.showInputMethodPicker();
+                    // Do not show auxiliary subtypes in password lock screen.
+                    mImm.showInputMethodPicker(false /* showAuxiliarySubtypes */);
                 }
             });
         }
diff --git a/packages/PrintSpooler/res/values/themes.xml b/packages/PrintSpooler/res/values/themes.xml
index 532b01f..db319e9 100644
--- a/packages/PrintSpooler/res/values/themes.xml
+++ b/packages/PrintSpooler/res/values/themes.xml
@@ -16,10 +16,7 @@
 
 <resources>
 
-    <style name="PrintActivity" parent="@android:style/Theme.Material">
-        <item name="android:colorPrimary">@*android:color/material_blue_grey_900</item>
-        <item name="android:colorPrimaryDark">@*android:color/material_blue_grey_950</item>
-        <item name="android:colorAccent">@*android:color/material_deep_teal_500</item>
+    <style name="PrintActivity" parent="@android:style/Theme.Material.Settings">
         <item name="android:windowIsTranslucent">true</item>
         <item name="android:windowBackground">@android:color/transparent</item>
         <item name="android:windowContentOverlay">@null</item>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 4082bf5..b702e35 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -64,6 +64,8 @@
     <string name="wifi_not_in_range">Not in range</string>
     <!-- Summary for the remembered network but no internet connection was detected. -->
     <string name="wifi_no_internet">No Internet Access Detected, won\'t automatically reconnect.</string>
+    <!-- Summary for saved networks -->
+    <string name="saved_network">Saved by <xliff:g id="name">%1$s</xliff:g></string>
 
     <!-- Status message of Wi-Fi when it is connected by a Wi-Fi assistant application. [CHAR LIMIT=NONE] -->
     <string name="connected_via_wfa">Connected via Wi\u2011Fi assistant</string>
@@ -71,6 +73,10 @@
     <string name="connected_via_passpoint">Connected via %1$s</string>
     <!-- Status message of Wi-Fi when network has matching passpoint credentials. [CHAR LIMIT=NONE] -->
     <string name="available_via_passpoint">Available via %1$s</string>
+    <!-- Package name for Settings app-->
+    <string name="settings_package" translatable="false">com.android.settings</string>
+    <!-- Package name for Certinstaller app-->
+    <string name="certinstaller_package" translatable="false">com.android.certinstaller</string>
 
     <!-- Summary for Connected wifi network without internet -->
     <string name="wifi_connected_no_internet">Connected, no Internet</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 53e69e3..7eaa728 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -35,6 +35,12 @@
 import android.os.ServiceManager;
 import android.util.Log;
 import android.util.LruCache;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.os.UserHandle;
+import android.os.RemoteException;
+import android.app.AppGlobals;
 
 import com.android.settingslib.R;
 
@@ -288,12 +294,28 @@
     }
 
     public String getSavedNetworkSummary() {
-        // Update to new summary
-        if (mConfig != null && mConfig.isPasspoint()) {
-            return "";
-        } else {
-            return getSettingsSummary();
+        if (mConfig != null) {
+            PackageManager pm = mContext.getPackageManager();
+            String systemName = pm.getNameForUid(android.os.Process.SYSTEM_UID);
+            int userId = UserHandle.getUserId(mConfig.creatorUid);
+            ApplicationInfo appInfo = null;
+            if (mConfig.creatorName != null && mConfig.creatorName.equals(systemName)) {
+                appInfo = mContext.getApplicationInfo();
+            } else {
+                try {
+                    IPackageManager ipm = AppGlobals.getPackageManager();
+                    appInfo = ipm.getApplicationInfo(mConfig.creatorName, 0 /* flags */, userId);
+                } catch (RemoteException rex) {
+                }
+            }
+            if (appInfo != null &&
+                    !appInfo.packageName.equals(mContext.getString(R.string.settings_package)) &&
+                    !appInfo.packageName.equals(
+                    mContext.getString(R.string.certinstaller_package))) {
+                return mContext.getString(R.string.saved_network, appInfo.loadLabel(pm));
+            }
         }
+        return "";
     }
 
     public String getSummary() {
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 5b4b4fd..dda9358 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -121,7 +121,7 @@
 
         <activity
             android:name=".BugreportWarningActivity"
-            android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
+            android:theme="@*android:style/Theme.Material.DayNight.Dialog.Alert"
             android:finishOnCloseSystemDialogs="true"
             android:excludeFromRecents="true"
             android:exported="false" />
diff --git a/packages/SystemUI/res/layout/zen_mode_panel.xml b/packages/SystemUI/res/layout/zen_mode_panel.xml
index 595c9ed..0264f3d 100644
--- a/packages/SystemUI/res/layout/zen_mode_panel.xml
+++ b/packages/SystemUI/res/layout/zen_mode_panel.xml
@@ -52,7 +52,7 @@
             android:layout_alignParentEnd="true"
             android:background="@drawable/btn_borderless_rect"
             android:clickable="true"
-            android:contentDescription="@string/accessibility_desc_confirm"
+            android:contentDescription="@string/accessibility_desc_close"
             android:scaleType="center"
             android:src="@drawable/ic_close"
             android:tint="@android:color/white" />
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 8466a5a..8606a59 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -424,8 +424,8 @@
     <string name="accessibility_desc_settings">Settings</string>
     <!-- Content description for the recent apps panel (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_desc_recent_apps">Overview.</string>
-    <!-- Content description for the confirm button in the zen mode panel introduction message. [CHAR LIMIT=NONE] -->
-    <string name="accessibility_desc_confirm">Confirm</string>
+    <!-- Content description for the close button in the zen mode panel introduction message. [CHAR LIMIT=NONE] -->
+    <string name="accessibility_desc_close">Close</string>
 
     <!-- Content description of the user tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_quick_settings_user">User <xliff:g id="user" example="John Doe">%s</xliff:g>.</string>
diff --git a/packages/SystemUI/src/com/android/systemui/EventLogConstants.java b/packages/SystemUI/src/com/android/systemui/EventLogConstants.java
index c8af2d4..43a1be1 100644
--- a/packages/SystemUI/src/com/android/systemui/EventLogConstants.java
+++ b/packages/SystemUI/src/com/android/systemui/EventLogConstants.java
@@ -34,4 +34,10 @@
     public static final int SYSUI_LOCKSCREEN_GESTURE_TAP_LOCK = 6;
     /** The user tapped a notification, needs to tap again to launch. */
     public static final int SYSUI_LOCKSCREEN_GESTURE_TAP_NOTIFICATION_ACTIVATE = 7;
+    /** The user swiped down to open quick settings, from keyguard. */
+    public static final int SYSUI_LOCKSCREEN_GESTURE_SWIPE_DOWN_QS = 8;
+    /** The user swiped down to open quick settings, from shade. */
+    public static final int SYSUI_SHADE_GESTURE_SWIPE_DOWN_QS = 9;
+    /** The user tapped on the status bar to open quick settings, from shade. */
+    public static final int SYSUI_TAP_TO_OPEN_QS = 10;
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index c62ad66..7077a17 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -144,7 +144,7 @@
         @Override
         public void onClick(View view) {
             ((InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE))
-                    .showInputMethodPicker();
+                    .showInputMethodPicker(true /* showAuxiliarySubtypes */);
         }
     };
 
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 c3ede75..f77ac4b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -39,6 +39,7 @@
 import android.widget.FrameLayout;
 import android.widget.TextView;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.keyguard.KeyguardStatusView;
 import com.android.systemui.EventLogConstants;
 import com.android.systemui.EventLogTags;
@@ -73,6 +74,10 @@
     private static final float HEADER_RUBBERBAND_FACTOR = 2.05f;
     private static final float LOCK_ICON_ACTIVE_SCALE = 1.2f;
 
+    private static final String COUNTER_PANEL_OPEN = "panel_open";
+    private static final String COUNTER_PANEL_OPEN_QS = "panel_open_qs";
+    private static final String COUNTER_PANEL_OPEN_PEEK = "panel_open_peek";
+
     public static final long DOZE_ANIMATION_DURATION = 700;
 
     private KeyguardAffordanceHelper mAfforanceHelper;
@@ -541,6 +546,8 @@
         initDownStates(event);
         if (mHeadsUpTouchHelper.onInterceptTouchEvent(event)) {
             mIsExpansionFromHeadsUp = true;
+            MetricsLogger.count(mContext, COUNTER_PANEL_OPEN, 1);
+            MetricsLogger.count(mContext, COUNTER_PANEL_OPEN_PEEK, 1);
             return true;
         }
         if (!isFullyCollapsed() && onQsIntercept(event)) {
@@ -617,7 +624,7 @@
             case MotionEvent.ACTION_UP:
                 trackMovement(event);
                 if (mQsTracking) {
-                    flingQsWithCurrentVelocity(
+                    flingQsWithCurrentVelocity(y,
                             event.getActionMasked() == MotionEvent.ACTION_CANCEL);
                     mQsTracking = false;
                 }
@@ -655,9 +662,24 @@
         super.requestDisallowInterceptTouchEvent(disallowIntercept);
     }
 
-    private void flingQsWithCurrentVelocity(boolean isCancelMotionEvent) {
+    private void flingQsWithCurrentVelocity(float y, boolean isCancelMotionEvent) {
         float vel = getCurrentVelocity();
-        flingSettings(vel, flingExpandsQs(vel) && !isCancelMotionEvent);
+        final boolean expandsQs = flingExpandsQs(vel);
+        if (expandsQs) {
+            logQsSwipeDown(y);
+        }
+        flingSettings(vel, expandsQs && !isCancelMotionEvent);
+    }
+
+    private void logQsSwipeDown(float y) {
+        float vel = getCurrentVelocity();
+        final int gesture = mStatusBarState == StatusBarState.KEYGUARD
+                ? EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_DOWN_QS
+                : EventLogConstants.SYSUI_SHADE_GESTURE_SWIPE_DOWN_QS;
+        EventLogTags.writeSysuiLockscreenGesture(
+                gesture,
+                (int) ((y - mInitialTouchY) / mStatusBar.getDisplayDensity()),
+                (int) (vel / mStatusBar.getDisplayDensity()));
     }
 
     private boolean flingExpandsQs(float vel) {
@@ -699,6 +721,7 @@
             return true;
         }
         if (event.getActionMasked() == MotionEvent.ACTION_DOWN && isFullyCollapsed()) {
+            MetricsLogger.count(mContext, COUNTER_PANEL_OPEN, 1);
             updateVerticalPanelPosition(event.getX());
         }
         super.onTouchEvent(event);
@@ -738,6 +761,7 @@
         if (mTwoFingerQsExpandPossible && event.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN
                 && event.getPointerCount() == 2
                 && event.getY(event.getActionIndex()) < mStatusBarMinHeight) {
+            MetricsLogger.count(mContext, COUNTER_PANEL_OPEN_QS, 1);
             mQsExpandImmediate = true;
             requestPanelHeightUpdate();
 
@@ -799,6 +823,7 @@
         }
         final float y = event.getY(pointerIndex);
         final float x = event.getX(pointerIndex);
+        final float h = y - mInitialTouchY;
 
         switch (event.getActionMasked()) {
             case MotionEvent.ACTION_DOWN:
@@ -826,7 +851,6 @@
                 break;
 
             case MotionEvent.ACTION_MOVE:
-                final float h = y - mInitialTouchY;
                 setQsExpansion(h + mInitialHeightOnTouch);
                 if (h >= getFalsingThreshold()) {
                     mQsTouchAboveFalsingThreshold = true;
@@ -842,9 +866,10 @@
                 float fraction = getQsExpansionFraction();
                 if ((fraction != 0f || y >= mInitialTouchY)
                         && (fraction != 1f || y <= mInitialTouchY)) {
-                    flingQsWithCurrentVelocity(
+                    flingQsWithCurrentVelocity(y,
                             event.getActionMasked() == MotionEvent.ACTION_CANCEL);
                 } else {
+                    logQsSwipeDown(y);
                     mScrollYOverride = -1;
                 }
                 if (mVelocityTracker != null) {
@@ -1819,6 +1844,9 @@
             if (mQsExpanded) {
                 flingSettings(0 /* vel */, false /* expand */);
             } else if (mQsExpansionEnabled) {
+                EventLogTags.writeSysuiLockscreenGesture(
+                        EventLogConstants.SYSUI_TAP_TO_OPEN_QS,
+                        0, 0);
                 flingSettings(0 /* vel */, true /* expand */);
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
index 23a65e8..ca32567 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
@@ -93,7 +93,7 @@
     }
 
     @Override
-    protected void onTargetSelected(TargetInfo target, boolean alwaysCheck) {
+    protected boolean onTargetSelected(TargetInfo target, boolean alwaysCheck) {
         final ResolveInfo ri = target.getResolveInfo();
         try {
             IBinder b = ServiceManager.getService(USB_SERVICE);
@@ -129,5 +129,6 @@
         } catch (RemoteException e) {
             Log.e(TAG, "onIntentSelected failed", e);
         }
+        return true;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index 7115897..1e34663 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -788,6 +788,7 @@
         public void onConfigurationChanged() {
             updateWindowWidthH();
             mSpTexts.update();
+            mZenFooter.onConfigurationChanged();
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
index 8aded45..ccb2b5a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
@@ -36,10 +36,11 @@
     private static final String TAG = Util.logTag(ZenFooter.class);
 
     private final Context mContext;
+    private final SpTexts mSpTexts;
 
     private TextView mSummaryLine1;
     private TextView mSummaryLine2;
-    private View mEndNowButton;
+    private TextView mEndNowButton;
     private int mZen = -1;
     private ZenModeConfig mConfig;
     private ZenModeController mController;
@@ -47,6 +48,7 @@
     public ZenFooter(Context context, AttributeSet attrs) {
         super(context, attrs);
         mContext = context;
+        mSpTexts = new SpTexts(mContext);
         setLayoutTransition(new LayoutTransition());
     }
 
@@ -55,7 +57,10 @@
         super.onFinishInflate();
         mSummaryLine1 = (TextView) findViewById(R.id.volume_zen_summary_line_1);
         mSummaryLine2 = (TextView) findViewById(R.id.volume_zen_summary_line_2);
-        mEndNowButton = findViewById(R.id.volume_zen_end_now);
+        mEndNowButton = (TextView) findViewById(R.id.volume_zen_end_now);
+        mSpTexts.add(mSummaryLine1);
+        mSpTexts.add(mSummaryLine2);
+        mSpTexts.add(mEndNowButton);
     }
 
     public void init(final ZenModeController controller) {
@@ -122,4 +127,8 @@
         Util.setText(mSummaryLine2, line2);
     }
 
+    public void onConfigurationChanged() {
+        mSpTexts.update();
+    }
+
 }
diff --git a/packages/VpnDialogs/AndroidManifest.xml b/packages/VpnDialogs/AndroidManifest.xml
index 375c5d8..32e1e6d 100644
--- a/packages/VpnDialogs/AndroidManifest.xml
+++ b/packages/VpnDialogs/AndroidManifest.xml
@@ -24,7 +24,7 @@
     <application android:label="VpnDialogs"
             android:allowBackup="false" >
         <activity android:name=".ConfirmDialog"
-                android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert">
+                android:theme="@*android:style/Theme.Material.DayNight.Dialog.Alert">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.intent.category.DEFAULT"/>
@@ -32,7 +32,7 @@
         </activity>
 
         <activity android:name=".ManageDialog"
-                android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
+                android:theme="@*android:style/Theme.Material.DayNight.Dialog.Alert"
                 android:noHistory="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
diff --git a/packages/WallpaperCropper/res/values/styles.xml b/packages/WallpaperCropper/res/values/styles.xml
index a34b25a..e438c84 100644
--- a/packages/WallpaperCropper/res/values/styles.xml
+++ b/packages/WallpaperCropper/res/values/styles.xml
@@ -15,13 +15,13 @@
 -->
 
 <resources>
-    <style name="Theme.WallpaperCropper" parent="@android:style/Theme.DeviceDefault">
+    <style name="Theme.WallpaperCropper" parent="@android:style/Theme.Material.DayNight">
         <item name="android:actionBarStyle">@style/WallpaperCropperActionBar</item>
         <item name="android:windowFullscreen">true</item>
         <item name="android:windowActionBarOverlay">true</item>
     </style>
 
-    <style name="WallpaperCropperActionBar" parent="android:style/Widget.DeviceDefault.ActionBar">
+    <style name="WallpaperCropperActionBar" parent="@android:style/Widget.Material.ActionBar">
         <item name="android:displayOptions">showCustom</item>
         <item name="android:background">#88000000</item>
     </style>
diff --git a/rs/java/android/renderscript/Script.java b/rs/java/android/renderscript/Script.java
index 6a1efee..7cd6d09 100644
--- a/rs/java/android/renderscript/Script.java
+++ b/rs/java/android/renderscript/Script.java
@@ -182,9 +182,9 @@
         mRS.validateObject(ain);
         mRS.validateObject(aout);
 
-        if (ain == null && aout == null) {
+        if (ain == null && aout == null && sc == null) {
             throw new RSIllegalArgumentException(
-                "At least one of ain or aout is required to be non-null.");
+                "At least one of input allocation, output allocation, or LaunchOptions is required to be non-null.");
         }
 
         long[] in_ids = null;
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 80d6515..58d0fce 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "libRS_jni"
+#define LOG_TAG "RenderScript_jni"
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -1857,7 +1857,7 @@
                jintArray limits)
 {
     if (kLogApi) {
-        ALOGD("nScriptForEach, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
+        ALOGD("nScriptForEach, con(%p), s(%p), slot(%i) ains(%p) aout(%lli)", (RsContext)con, (void *)script, slot, ains, aout);
     }
 
     jint   in_len = 0;
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index bfe8b5c..6c1023c 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -9368,44 +9368,47 @@
                 throw new SecurityException("No permission to restore other packages");
             }
 
-            // So far so good; we're allowed to try to restore this package.  Now
-            // check whether there is data for it in the current dataset, falling back
-            // to the ancestral dataset if not.
-            long token = getAvailableRestoreToken(packageName);
-            if (DEBUG) Slog.v(TAG, "restorePackage pkg=" + packageName
-                    + " token=" + Long.toHexString(token));
-
-            // If we didn't come up with a place to look -- no ancestral dataset and
-            // the app has never been backed up from this device -- there's nothing
-            // to do but return failure.
-            if (token == 0) {
-                if (DEBUG) Slog.w(TAG, "No data available for this package; not restoring");
-                return -1;
-            }
-
-            String dirName;
-            try {
-                dirName = mRestoreTransport.transportDirName();
-            } catch (RemoteException e) {
-                // Transport went AWOL; fail.
-                Slog.e(TAG, "Unable to contact transport for restore");
-                return -1;
-            }
-
-            // Stop the session timeout until we finalize the restore
-            mBackupHandler.removeMessages(MSG_RESTORE_TIMEOUT);
-
-            // Ready to go:  enqueue the restore request and claim success
+            // So far so good; we're allowed to try to restore this package.
             long oldId = Binder.clearCallingIdentity();
-            mWakelock.acquire();
-            if (MORE_DEBUG) {
-                Slog.d(TAG, "restorePackage() : " + packageName);
+            try {
+                // Check whether there is data for it in the current dataset, falling back
+                // to the ancestral dataset if not.
+                long token = getAvailableRestoreToken(packageName);
+                if (DEBUG) Slog.v(TAG, "restorePackage pkg=" + packageName
+                        + " token=" + Long.toHexString(token));
+
+                // If we didn't come up with a place to look -- no ancestral dataset and
+                // the app has never been backed up from this device -- there's nothing
+                // to do but return failure.
+                if (token == 0) {
+                    if (DEBUG) Slog.w(TAG, "No data available for this package; not restoring");
+                    return -1;
+                }
+
+                String dirName;
+                try {
+                    dirName = mRestoreTransport.transportDirName();
+                } catch (RemoteException e) {
+                    // Transport went AWOL; fail.
+                    Slog.e(TAG, "Unable to contact transport for restore");
+                    return -1;
+                }
+
+                // Stop the session timeout until we finalize the restore
+                mBackupHandler.removeMessages(MSG_RESTORE_TIMEOUT);
+
+                // Ready to go:  enqueue the restore request and claim success
+                mWakelock.acquire();
+                if (MORE_DEBUG) {
+                    Slog.d(TAG, "restorePackage() : " + packageName);
+                }
+                Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
+                msg.obj = new RestoreParams(mRestoreTransport, dirName,
+                        observer, token, app, 0);
+                mBackupHandler.sendMessage(msg);
+            } finally {
+                Binder.restoreCallingIdentity(oldId);
             }
-            Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
-            msg.obj = new RestoreParams(mRestoreTransport, dirName,
-                    observer, token, app, 0);
-            mBackupHandler.sendMessage(msg);
-            Binder.restoreCallingIdentity(oldId);
             return 0;
         }
 
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 1019faa..32b91d2 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -512,7 +512,8 @@
     private void onBluetoothGattServiceUp() {
         if (DBG) Log.d(TAG,"BluetoothGatt Service is Up");
         try{
-            if (isBleAppPresent() == false && mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) {
+            if (isBleAppPresent() == false && mBluetooth != null
+                  && mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) {
                 mBluetooth.onLeServiceUp();
 
                 // waive WRITE_SECURE_SETTINGS permission check
@@ -531,32 +532,26 @@
      */
     private void sendBrEdrDownCallback() {
         if (DBG) Log.d(TAG,"Calling sendBrEdrDownCallback callbacks");
-        int n = mCallbacks.beginBroadcast();
+
+        if(mBluetooth == null) {
+            Log.w(TAG, "Bluetooth handle is null");
+            return;
+        }
 
         if (isBleAppPresent() == false) {
             try {
                 mBluetooth.onBrEdrDown();
             } catch(RemoteException e) {
-                Log.e(TAG,"Unable to call onBrEdrDown", e);
+                Log.e(TAG, "Call to onBrEdrDown() failed.", e);
             }
-        }
-        else{//need to stay at BLE ON. disconnect all Gatt connections
+        } else {
+            // Need to stay at BLE ON. Disconnect all Gatt connections
             try{
-                mBluetoothGatt.unregAll();//disconnectAll();
+                mBluetoothGatt.unregAll();
             } catch(RemoteException e) {
-                Log.e(TAG,"Unable to disconn all", e);
+                Log.e(TAG, "Unable to disconnect all apps.", e);
             }
         }
-
-        Log.d(TAG,"Broadcasting onBrEdrDown() to " + n + " receivers.");
-        for (int i=0; i <n; i++) {
-            try {
-                mCallbacks.getBroadcastItem(i).onBrEdrDown();
-            }  catch (RemoteException e) {
-                Log.e(TAG, "Unable to call sendBrEdrDownCallback() on callback #" + i, e);
-            }
-        }
-        mCallbacks.finishBroadcast();
     }
 
     /** @hide*/
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 45909db..9511f54 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -2038,11 +2038,9 @@
                         if (!mIWindowManager.inputMethodClientHasFocus(client)) {
                             if (DEBUG) Slog.w(TAG, "Ignoring hideSoftInput of uid "
                                     + uid + ": " + client);
-                            setImeWindowVisibilityStatusHiddenLocked();
                             return false;
                         }
                     } catch (RemoteException e) {
-                        setImeWindowVisibilityStatusHiddenLocked();
                         return false;
                     }
                 }
@@ -2238,7 +2236,8 @@
     }
 
     @Override
-    public void showInputMethodPickerFromClient(IInputMethodClient client) {
+    public void showInputMethodPickerFromClient(
+            IInputMethodClient client, int auxiliarySubtypeMode) {
         if (!calledFromValidUser()) {
             return;
         }
@@ -2251,7 +2250,8 @@
 
             // Always call subtype picker, because subtype picker is a superset of input method
             // picker.
-            mHandler.sendEmptyMessage(MSG_SHOW_IM_SUBTYPE_PICKER);
+            mHandler.sendMessage(mCaller.obtainMessageI(
+                    MSG_SHOW_IM_SUBTYPE_PICKER, auxiliarySubtypeMode));
         }
     }
 
@@ -2597,7 +2597,25 @@
         SomeArgs args;
         switch (msg.what) {
             case MSG_SHOW_IM_SUBTYPE_PICKER:
-                showInputMethodMenu();
+                final boolean showAuxSubtypes;
+                switch (msg.arg1) {
+                    case InputMethodManager.SHOW_IM_PICKER_MODE_AUTO:
+                        // This is undocumented so far, but IMM#showInputMethodPicker() has been
+                        // implemented so that auxiliary subtypes will be excluded when the soft
+                        // keyboard is invisible.
+                        showAuxSubtypes = mInputShown;
+                        break;
+                    case InputMethodManager.SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES:
+                        showAuxSubtypes = true;
+                        break;
+                    case InputMethodManager.SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES:
+                        showAuxSubtypes = false;
+                        break;
+                    default:
+                        Slog.e(TAG, "Unknown subtype picker mode = " + msg.arg1);
+                        return false;
+                }
+                showInputMethodMenu(showAuxSubtypes);
                 return true;
 
             case MSG_SHOW_IM_SUBTYPE_ENABLER:
@@ -2880,8 +2898,8 @@
                 && mKeyguardManager.isKeyguardLocked() && mKeyguardManager.isKeyguardSecure();
     }
 
-    private void showInputMethodMenu() {
-        if (DEBUG) Slog.v(TAG, "Show switching menu");
+    private void showInputMethodMenu(boolean showAuxSubtypes) {
+        if (DEBUG) Slog.v(TAG, "Show switching menu. showAuxSubtypes=" + showAuxSubtypes);
 
         final Context context = mContext;
         final boolean isScreenLocked = isScreenLocked();
@@ -2902,7 +2920,7 @@
 
             final List<ImeSubtypeListItem> imList =
                     mSwitchingController.getSortedInputMethodAndSubtypeListLocked(
-                            true /* showSubtypes */, mInputShown, isScreenLocked);
+                            true /* showSubtypes */, showAuxSubtypes, isScreenLocked);
 
             if (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID) {
                 final InputMethodSubtype currentSubtype = getCurrentInputMethodSubtypeLocked();
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index a07591c9..ac55292 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -488,7 +488,8 @@
         try {
             // Restricted users are not allowed to create VPNs, they are tied to Owner
             UserInfo user = mgr.getUserInfo(mUserHandle);
-            if (user.isRestricted() || mgr.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) {
+            if (user.isRestricted() || mgr.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN,
+                    new UserHandle(mUserHandle))) {
                 throw new SecurityException("Restricted users cannot establish VPNs");
             }
 
@@ -896,7 +897,8 @@
         }
         UserManager mgr = UserManager.get(mContext);
         UserInfo user = mgr.getUserInfo(mUserHandle);
-        if (user.isRestricted() || mgr.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) {
+        if (user.isRestricted() || mgr.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN,
+                    new UserHandle(mUserHandle))) {
             throw new SecurityException("Restricted users cannot establish VPNs");
         }
 
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 7cccef2..3dc282b 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -52,6 +52,7 @@
 import android.content.pm.RegisteredServicesCacheListener;
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
+import android.database.ContentObserver;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.os.BatteryStats;
@@ -99,6 +100,7 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Random;
@@ -157,7 +159,19 @@
     /**
      * How long to wait before considering an active sync to have timed-out, and cancelling it.
      */
-    private static final long ACTIVE_SYNC_TIMEOUT_MILLIS = 30L * 60 * 1000;  // 30 mins.
+    private static final long ACTIVE_SYNC_TIMEOUT_MILLIS = 30L * 60 * 1000;  // 30 mins
+
+    /**
+     * How long to delay each queued {@link SyncHandler} message that may have occurred before boot
+     * or befor the device became provisioned.
+     */
+    private static final long PER_SYNC_BOOT_DELAY_MILLIS = 3000L;  // 3 seconds
+
+    /**
+     * The maximum amount of time we're willing to delay syncs out of boot, after device has been
+     * provisioned, etc.
+     */
+    private static final long MAX_SYNC_BOOT_DELAY_MILLIS = 120000L;  // 2 minutes
 
     private static final String SYNC_WAKE_LOCK_PREFIX = "*sync*/";
     private static final String HANDLE_SYNC_ALARM_WAKE_LOCK = "SyncManagerHandleSyncAlarm";
@@ -198,6 +212,9 @@
     // its accessor, getConnManager().
     private ConnectivityManager mConnManagerDoNotUseDirectly;
 
+    /** Track whether the device has already been provisioned. */
+    private boolean mProvisioned;
+
     protected SyncAdaptersCache mSyncAdapters;
 
     private final AppIdleMonitor mAppIdleMonitor;
@@ -242,6 +259,7 @@
     private BroadcastReceiver mBootCompletedReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
+            mBootCompleted = true;
             mSyncHandler.onBootCompleted();
         }
     };
@@ -491,12 +509,41 @@
 
         mSyncStorageEngine.addStatusChangeListener(
                 ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, new ISyncStatusObserver.Stub() {
-            @Override
-            public void onStatusChanged(int which) {
-                // force the sync loop to run if the settings change
-                sendCheckAlarmsMessage();
+                    @Override
+                    public void onStatusChanged(int which) {
+                        // force the sync loop to run if the settings change
+                        sendCheckAlarmsMessage();
+                    }
+                });
+
+        mProvisioned = isDeviceProvisioned();
+        if (!mProvisioned) {
+            final ContentResolver resolver = context.getContentResolver();
+            ContentObserver provisionedObserver =
+                    new ContentObserver(null /* current thread */) {
+                        public void onChange(boolean selfChange) {
+                            mProvisioned |= isDeviceProvisioned();
+                            if (mProvisioned) {
+                                mSyncHandler.onDeviceProvisioned();
+                                resolver.unregisterContentObserver(this);
+                            }
+                        }
+                    };
+
+            synchronized (mSyncHandler) {
+                resolver.registerContentObserver(
+                        Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
+                        false /* notifyForDescendents */,
+                        provisionedObserver);
+
+                // The device *may* have been provisioned while we were registering above observer.
+                // Check again to make sure.
+                mProvisioned |= isDeviceProvisioned();
+                if (mProvisioned) {
+                    resolver.unregisterContentObserver(provisionedObserver);
+                }
             }
-        });
+        }
 
         if (!factoryTest) {
             // Register for account list updates for all users
@@ -510,6 +557,10 @@
         mSyncRandomOffsetMillis = mSyncStorageEngine.getSyncRandomOffset() * 1000;
     }
 
+    private boolean isDeviceProvisioned() {
+        final ContentResolver resolver = mContext.getContentResolver();
+        return (Settings.Global.getInt(resolver, Settings.Global.DEVICE_PROVISIONED, 0) != 0);
+    }
     /**
      * Return a random value v that satisfies minValue <= v < maxValue. The difference between
      * maxValue and minValue must be less than Integer.MAX_VALUE.
@@ -2000,20 +2051,36 @@
         public final SyncTimeTracker mSyncTimeTracker = new SyncTimeTracker();
         private final HashMap<String, PowerManager.WakeLock> mWakeLocks = Maps.newHashMap();
 
-        private List<Message> mBootQueue = new ArrayList<Message>();
+        private List<Message> mUnreadyQueue = new ArrayList<Message>();
 
-      public void onBootCompleted() {
+        void onBootCompleted() {
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
                 Log.v(TAG, "Boot completed, clearing boot queue.");
             }
             doDatabaseCleanup();
             synchronized(this) {
                 // Dispatch any stashed messages.
-                for (Message message : mBootQueue) {
-                    sendMessage(message);
+                maybeEmptyUnreadyQueueLocked();
+            }
+        }
+
+        void onDeviceProvisioned() {
+            if (Log.isLoggable(TAG, Log.DEBUG)) {
+                Log.d(TAG, "mProvisioned=" + mProvisioned);
+            }
+            synchronized (this) {
+                maybeEmptyUnreadyQueueLocked();
+            }
+        }
+
+        private void maybeEmptyUnreadyQueueLocked() {
+            if (mProvisioned && mBootCompleted) {
+                // Dispatch any stashed messages.
+                for (int i=0; i<mUnreadyQueue.size(); i++) {
+                    sendMessageDelayed(mUnreadyQueue.get(i),
+                            Math.max(PER_SYNC_BOOT_DELAY_MILLIS * i, MAX_SYNC_BOOT_DELAY_MILLIS));
                 }
-                mBootQueue = null;
-                mBootCompleted = true;
+                mUnreadyQueue = null;
             }
         }
 
@@ -2030,20 +2097,23 @@
         }
 
         /**
-         * Stash any messages that come to the handler before boot is complete.
-         * {@link #onBootCompleted()} will disable this and dispatch all the messages collected.
+         * Stash any messages that come to the handler before boot is complete or before the device
+         * is properly provisioned (i.e. out of set-up wizard).
+         * {@link #onBootCompleted()} and {@link #onDeviceProvisioned(boolean)} both need to come
+         * in before we start syncing.
          * @param msg Message to dispatch at a later point.
          * @return true if a message was enqueued, false otherwise. This is to avoid losing the
          * message if we manage to acquire the lock but by the time we do boot has completed.
          */
         private boolean tryEnqueueMessageUntilReadyToRun(Message msg) {
             synchronized (this) {
-                if (!mBootCompleted) {
+                if (!mBootCompleted || !mProvisioned) {
                     // Need to copy the message bc looper will recycle it.
-                    mBootQueue.add(Message.obtain(msg));
+                    mUnreadyQueue.add(Message.obtain(msg));
                     return true;
+                } else {
+                    return false;
                 }
-                return false;
             }
         }
 
@@ -2100,7 +2170,7 @@
                         }
                         cancelActiveSync(expiredContext.mSyncOperation.target,
                                 expiredContext.mSyncOperation.extras);
-                        nextPendingSyncTime = maybeStartNextSyncLocked();
+                        nextPendingSyncTime = maybeStartNextSyncH();
                         break;
 
                     case SyncHandler.MESSAGE_CANCEL: {
@@ -2111,7 +2181,7 @@
                                     + payload + " bundle: " + extras);
                         }
                         cancelActiveSyncLocked(payload, extras);
-                        nextPendingSyncTime = maybeStartNextSyncLocked();
+                        nextPendingSyncTime = maybeStartNextSyncH();
                         break;
                     }
 
@@ -2120,17 +2190,17 @@
                             Log.v(TAG, "handleSyncHandlerMessage: MESSAGE_SYNC_FINISHED");
                         }
                         SyncHandlerMessagePayload payload = (SyncHandlerMessagePayload) msg.obj;
-                        if (!isSyncStillActive(payload.activeSyncContext)) {
+                        if (!isSyncStillActiveH(payload.activeSyncContext)) {
                             Log.d(TAG, "handleSyncHandlerMessage: dropping since the "
                                     + "sync is no longer active: "
                                     + payload.activeSyncContext);
                             break;
                         }
-                        runSyncFinishedOrCanceledLocked(payload.syncResult,
+                        runSyncFinishedOrCanceledH(payload.syncResult,
                                 payload.activeSyncContext);
 
                         // since a sync just finished check if it is time to start a new sync
-                        nextPendingSyncTime = maybeStartNextSyncLocked();
+                        nextPendingSyncTime = maybeStartNextSyncH();
                         break;
 
                     case SyncHandler.MESSAGE_SERVICE_CONNECTED: {
@@ -2140,7 +2210,7 @@
                                     + msgData.activeSyncContext);
                         }
                         // check that this isn't an old message
-                        if (isSyncStillActive(msgData.activeSyncContext)) {
+                        if (isSyncStillActiveH(msgData.activeSyncContext)) {
                             runBoundToAdapter(
                                     msgData.activeSyncContext,
                                     msgData.adapter);
@@ -2156,7 +2226,7 @@
                                     + currentSyncContext);
                         }
                         // check that this isn't an old message
-                        if (isSyncStillActive(currentSyncContext)) {
+                        if (isSyncStillActiveH(currentSyncContext)) {
                             // cancel the sync if we have a syncadapter, which means one is
                             // outstanding
                             try {
@@ -2174,10 +2244,10 @@
                             // which is a soft error
                             SyncResult syncResult = new SyncResult();
                             syncResult.stats.numIoExceptions++;
-                            runSyncFinishedOrCanceledLocked(syncResult, currentSyncContext);
+                            runSyncFinishedOrCanceledH(syncResult, currentSyncContext);
 
                             // since a sync just finished check if it is time to start a new sync
-                            nextPendingSyncTime = maybeStartNextSyncLocked();
+                            nextPendingSyncTime = maybeStartNextSyncH();
                         }
 
                         break;
@@ -2190,7 +2260,7 @@
                         }
                         mAlarmScheduleTime = null;
                         try {
-                            nextPendingSyncTime = maybeStartNextSyncLocked();
+                            nextPendingSyncTime = maybeStartNextSyncH();
                         } finally {
                             mHandleAlarmWakeLock.release();
                         }
@@ -2201,7 +2271,7 @@
                         if (Log.isLoggable(TAG, Log.VERBOSE)) {
                             Log.v(TAG, "handleSyncHandlerMessage: MESSAGE_CHECK_ALARMS");
                         }
-                        nextPendingSyncTime = maybeStartNextSyncLocked();
+                        nextPendingSyncTime = maybeStartNextSyncH();
                         break;
                 }
             } finally {
@@ -2393,7 +2463,7 @@
                     0 : (earliestFuturePollTime - nowAbsolute));
         }
 
-        private long maybeStartNextSyncLocked() {
+        private long maybeStartNextSyncH() {
             final boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
             if (isLoggable) Log.v(TAG, "maybeStartNextSync");
 
@@ -2612,7 +2682,7 @@
                 }
 
                 if (toReschedule != null) {
-                    runSyncFinishedOrCanceledLocked(null, toReschedule);
+                    runSyncFinishedOrCanceledH(null, toReschedule);
                     scheduleSyncOperation(toReschedule.mSyncOperation);
                 }
                 synchronized (mSyncQueue) {
@@ -2845,14 +2915,14 @@
                                     false /* no config settings */)) {
                         continue;
                     }
-                    runSyncFinishedOrCanceledLocked(null /* no result since this is a cancel */,
+                    runSyncFinishedOrCanceledH(null /* no result since this is a cancel */,
                             activeSyncContext);
                 }
             }
         }
 
-        private void runSyncFinishedOrCanceledLocked(SyncResult syncResult,
-                ActiveSyncContext activeSyncContext) {
+        private void runSyncFinishedOrCanceledH(SyncResult syncResult,
+                                                ActiveSyncContext activeSyncContext) {
             boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
 
             final SyncOperation syncOperation = activeSyncContext.mSyncOperation;
@@ -3257,7 +3327,7 @@
         }
     }
 
-    private boolean isSyncStillActive(ActiveSyncContext activeSyncContext) {
+    private boolean isSyncStillActiveH(ActiveSyncContext activeSyncContext) {
         for (ActiveSyncContext sync : mActiveSyncContexts) {
             if (sync == activeSyncContext) {
                 return true;
diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java
index e434f39..8c12060 100644
--- a/services/core/java/com/android/server/hdmi/Constants.java
+++ b/services/core/java/com/android/server/hdmi/Constants.java
@@ -214,6 +214,10 @@
     //     values which denotes the device type in HDMI Spec 1.4.
     static final String PROPERTY_DEVICE_TYPE = "ro.hdmi.device_type";
 
+    // TODO(OEM): Set this to false to keep the playback device in sleep upon hotplug event.
+    //            True by default.
+    static final String PROPERTY_WAKE_ON_HOTPLUG = "ro.hdmi.wake_on_hotplug";
+
     // Set to false to allow playback device to go to suspend mode even
     // when it's an active source. True by default.
     static final String PROPERTY_KEEP_AWAKE = "persist.sys.hdmi.keep_awake";
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index 89ffe45..fd3364a 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -34,6 +34,9 @@
 final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice {
     private static final String TAG = "HdmiCecLocalDevicePlayback";
 
+    private static final boolean WAKE_ON_HOTPLUG =
+            SystemProperties.getBoolean(Constants.PROPERTY_WAKE_ON_HOTPLUG, true);
+
     private boolean mIsActiveSource = false;
 
     // Used to keep the device awake while it is the active source. For devices that
@@ -130,7 +133,7 @@
         assertRunOnServiceThread();
         mCecMessageCache.flushAll();
         // We'll not clear mIsActiveSource on the hotplug event to pass CETC 11.2.2-2 ~ 3.
-        if (connected && mService.isPowerStandbyOrTransient()) {
+        if (WAKE_ON_HOTPLUG && connected && mService.isPowerStandbyOrTransient()) {
             mService.wakeUp();
         }
         if (!connected) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 5ac027d..e650456 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -486,6 +486,7 @@
             HdmiLogger.debug("Input not ready for device: %X; buffering the command", info.getId());
             mDelayedMessageBuffer.add(message);
         } else {
+            updateDevicePowerStatus(logicalAddress, HdmiControlManager.POWER_STATUS_ON);
             ActiveSource activeSource = ActiveSource.of(logicalAddress, physicalAddress);
             ActiveSourceHandler.create(this, null).process(activeSource, info.getDeviceType());
         }
@@ -1613,6 +1614,8 @@
 
         super.disableDevice(initiatedByCec, callback);
         clearDeviceInfoList();
+        getActiveSource().invalidate();
+        setActivePath(Constants.INVALID_PHYSICAL_ADDRESS);
         checkIfPendingActionsCleared();
     }
 
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 09d0501..dca762c 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -27,9 +27,6 @@
 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;
@@ -718,11 +715,6 @@
         }
 
         @Override
-        public void setMediaRouter(IMediaRouter router) {
-            mHandler.post(MessageHandler.MSG_UPDATE_SESSION_STATE);
-        }
-
-        @Override
         public void setMediaButtonReceiver(PendingIntent pi) {
             mMediaButtonReceiver = pi;
         }
@@ -1209,13 +1201,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/notification/CalendarTracker.java b/services/core/java/com/android/server/notification/CalendarTracker.java
index c82df48..28da73c 100644
--- a/services/core/java/com/android/server/notification/CalendarTracker.java
+++ b/services/core/java/com/android/server/notification/CalendarTracker.java
@@ -47,6 +47,7 @@
         Instances.EVENT_ID,
         Instances.OWNER_ACCOUNT,
         Instances.CALENDAR_ID,
+        Instances.AVAILABILITY,
     };
 
     private static final String INSTANCE_ORDER_BY = Instances.BEGIN + " ASC";
@@ -143,11 +144,14 @@
                 final int eventId = cursor.getInt(4);
                 final String owner = cursor.getString(5);
                 final long calendarId = cursor.getLong(6);
-                if (DEBUG) Log.d(TAG, String.format("%s %s-%s v=%s eid=%s o=%s cid=%s", title,
-                        new Date(begin), new Date(end), visible, eventId, owner, calendarId));
+                final int availability = cursor.getInt(7);
+                if (DEBUG) Log.d(TAG, String.format("%s %s-%s v=%s a=%s eid=%s o=%s cid=%s", title,
+                        new Date(begin), new Date(end), visible, availabilityToString(availability),
+                        eventId, owner, calendarId));
                 final boolean meetsTime = time >= begin && time < end;
                 final boolean meetsCalendar = visible
-                        && (filter.calendar == 0 || filter.calendar == calendarId);
+                        && (filter.calendar == 0 || filter.calendar == calendarId)
+                        && availability != Instances.AVAILABILITY_FREE;
                 if (meetsCalendar) {
                     if (DEBUG) Log.d(TAG, "  MEETS CALENDAR");
                     final boolean meetsAttendee = meetsAttendee(filter, eventId, owner);
@@ -228,6 +232,15 @@
         }
     }
 
+    private static String availabilityToString(int availability) {
+        switch (availability) {
+            case Instances.AVAILABILITY_BUSY: return "AVAILABILITY_BUSY";
+            case Instances.AVAILABILITY_FREE: return "AVAILABILITY_FREE";
+            case Instances.AVAILABILITY_TENTATIVE: return "AVAILABILITY_TENTATIVE";
+            default: return "AVAILABILITY_UNKNOWN_" + availability;
+        }
+    }
+
     private static boolean meetsReply(int reply, int attendeeStatus) {
         switch (reply) {
             case EventInfo.REPLY_YES:
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 51503ec..dbd3676 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -93,7 +93,7 @@
 import android.view.KeyCharacterMap.FallbackAction;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
-import android.view.PhoneWindow;
+import com.android.internal.policy.PhoneWindow;
 import android.view.Surface;
 import android.view.View;
 import android.view.ViewConfiguration;
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index c48367e..fd98010 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -539,9 +539,11 @@
     };
 
     private void playWirelessChargingStartedSound() {
+        final boolean enabled = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.CHARGING_SOUNDS_ENABLED, 1) != 0;
         final String soundPath = Settings.Global.getString(mContext.getContentResolver(),
                 Settings.Global.WIRELESS_CHARGING_STARTED_SOUND);
-        if (soundPath != null) {
+        if (enabled && soundPath != null) {
             final Uri soundUri = Uri.parse("file://" + soundPath);
             if (soundUri != null) {
                 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index a8ec867..6f01ca0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -161,7 +161,7 @@
 
     private static final String TAG_STATUS_BAR = "statusbar";
 
-    private static final String ATTR_ENABLED = "enabled";
+    private static final String ATTR_DISABLED = "disabled";
 
     private static final String DO_NOT_ASK_CREDENTIALS_ON_BOOT_XML =
             "do-not-ask-credentials-on-boot";
@@ -313,7 +313,7 @@
         // This is the list of component allowed to start lock task mode.
         List<String> mLockTaskPackages = new ArrayList<>();
 
-        boolean mStatusBarEnabledState = true;
+        boolean mStatusBarDisabled = false;
 
         ComponentName mRestrictionsProvider;
 
@@ -1476,9 +1476,9 @@
                 out.endTag(null, TAG_LOCK_TASK_COMPONENTS);
             }
 
-            if (!policy.mStatusBarEnabledState) {
+            if (policy.mStatusBarDisabled) {
                 out.startTag(null, TAG_STATUS_BAR);
-                out.attribute(null, ATTR_ENABLED, Boolean.toString(policy.mStatusBarEnabledState));
+                out.attribute(null, ATTR_DISABLED, Boolean.toString(policy.mStatusBarDisabled));
                 out.endTag(null, TAG_STATUS_BAR);
             }
 
@@ -1615,8 +1615,8 @@
                 } else if (TAG_LOCK_TASK_COMPONENTS.equals(tag)) {
                     policy.mLockTaskPackages.add(parser.getAttributeValue(null, "name"));
                 } else if (TAG_STATUS_BAR.equals(tag)) {
-                    policy.mStatusBarEnabledState = Boolean.parseBoolean(
-                            parser.getAttributeValue(null, ATTR_ENABLED));
+                    policy.mStatusBarDisabled = Boolean.parseBoolean(
+                            parser.getAttributeValue(null, ATTR_DISABLED));
                 } else if (DO_NOT_ASK_CREDENTIALS_ON_BOOT_XML.equals(tag)) {
                     policy.doNotAskCredentialsOnBoot = true;
                 } else {
@@ -1678,8 +1678,8 @@
         updateMaximumTimeToLockLocked(policy);
         addDeviceInitializerToLockTaskPackagesLocked(userHandle);
         updateLockTaskPackagesLocked(policy.mLockTaskPackages, userHandle);
-        if (!policy.mStatusBarEnabledState) {
-            setStatusBarEnabledStateInternal(policy.mStatusBarEnabledState, userHandle);
+        if (policy.mStatusBarDisabled) {
+            setStatusBarDisabledInternal(policy.mStatusBarDisabled, userHandle);
         }
         updatePreferredSetupActivityLocked(userHandle);
     }
@@ -4275,7 +4275,7 @@
             DevicePolicyData policy = getUserData(userId);
             policy.mPermissionPolicy = DevicePolicyManager.PERMISSION_POLICY_PROMPT;
             policy.mDelegatedCertInstallerPackage = null;
-            policy.mStatusBarEnabledState = true;
+            policy.mStatusBarDisabled = false;
             saveSettingsLocked(userId);
 
             long ident = Binder.clearCallingIdentity();
@@ -6026,7 +6026,7 @@
     }
 
     @Override
-    public boolean setKeyguardEnabledState(ComponentName who, boolean enabled) {
+    public boolean setKeyguardDisabled(ComponentName who, boolean disabled) {
         Preconditions.checkNotNull(who, "ComponentName is null");
         synchronized (this) {
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
@@ -6037,10 +6037,10 @@
         long ident = Binder.clearCallingIdentity();
         try {
             // disallow disabling the keyguard if a password is currently set
-            if (!enabled && utils.isSecure(userId)) {
+            if (disabled && utils.isSecure(userId)) {
                 return false;
             }
-            utils.setLockScreenDisabled(!enabled, userId);
+            utils.setLockScreenDisabled(disabled, userId);
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
@@ -6048,35 +6048,40 @@
     }
 
     @Override
-    public void setStatusBarEnabledState(ComponentName who, boolean enabled) {
+    public boolean setStatusBarDisabled(ComponentName who, boolean disabled) {
         int userId = UserHandle.getCallingUserId();
         synchronized (this) {
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
             DevicePolicyData policy = getUserData(userId);
-            if (policy.mStatusBarEnabledState != enabled) {
-                policy.mStatusBarEnabledState = enabled;
-                setStatusBarEnabledStateInternal(enabled, userId);
+            if (policy.mStatusBarDisabled != disabled) {
+                if (!setStatusBarDisabledInternal(disabled, userId)) {
+                    return false;
+                }
+                policy.mStatusBarDisabled = disabled;
                 saveSettingsLocked(userId);
             }
         }
+        return true;
     }
 
-    private void setStatusBarEnabledStateInternal(boolean enabled, int userId) {
+    private boolean setStatusBarDisabledInternal(boolean disabled, int userId) {
         long ident = Binder.clearCallingIdentity();
         try {
             IStatusBarService statusBarService = IStatusBarService.Stub.asInterface(
                     ServiceManager.checkService(Context.STATUS_BAR_SERVICE));
             if (statusBarService != null) {
-                int flags1 = enabled ? StatusBarManager.DISABLE_NONE : STATUS_BAR_DISABLE_MASK;
-                int flags2 = enabled ? StatusBarManager.DISABLE2_NONE : STATUS_BAR_DISABLE2_MASK;
+                int flags1 = disabled ? STATUS_BAR_DISABLE_MASK : StatusBarManager.DISABLE_NONE;
+                int flags2 = disabled ? STATUS_BAR_DISABLE2_MASK : StatusBarManager.DISABLE2_NONE;
                 statusBarService.disableForUser(flags1, mToken, mContext.getPackageName(), userId);
                 statusBarService.disable2ForUser(flags2, mToken, mContext.getPackageName(), userId);
+                return true;
             }
         } catch (RemoteException e) {
             Slog.e(LOG_TAG, "Failed to disable the status bar", e);
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
+        return false;
     }
 
     /**
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index fee6495..adab00b 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -1000,9 +1000,9 @@
         }
 
         boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged() &&
-                !Objects.equals(mVideoCall, parcelableCall.getVideoCall());
+                !Objects.equals(mVideoCall, parcelableCall.getVideoCall(this));
         if (videoCallChanged) {
-            mVideoCall = parcelableCall.getVideoCall();
+            mVideoCall = parcelableCall.getVideoCall(this);
         }
 
         int state = parcelableCall.getState();
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 3060f40..4bc639b 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -16,6 +16,7 @@
 
 package android.telecom;
 
+import com.android.internal.os.SomeArgs;
 import com.android.internal.telecom.IVideoCallback;
 import com.android.internal.telecom.IVideoProvider;
 
@@ -471,9 +472,16 @@
                     case MSG_SET_ZOOM:
                         onSetZoom((Float) msg.obj);
                         break;
-                    case MSG_SEND_SESSION_MODIFY_REQUEST:
-                        onSendSessionModifyRequest((VideoProfile) msg.obj);
+                    case MSG_SEND_SESSION_MODIFY_REQUEST: {
+                        SomeArgs args = (SomeArgs) msg.obj;
+                        try {
+                            onSendSessionModifyRequest((VideoProfile) args.arg1,
+                                    (VideoProfile) args.arg2);
+                        } finally {
+                            args.recycle();
+                        }
                         break;
+                    }
                     case MSG_SEND_SESSION_MODIFY_RESPONSE:
                         onSendSessionModifyResponse((VideoProfile) msg.obj);
                         break;
@@ -527,9 +535,11 @@
                 mMessageHandler.obtainMessage(MSG_SET_ZOOM, value).sendToTarget();
             }
 
-            public void sendSessionModifyRequest(VideoProfile requestProfile) {
-                mMessageHandler.obtainMessage(
-                        MSG_SEND_SESSION_MODIFY_REQUEST, requestProfile).sendToTarget();
+            public void sendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile) {
+                SomeArgs args = SomeArgs.obtain();
+                args.arg1 = fromProfile;
+                args.arg2 = toProfile;
+                mMessageHandler.obtainMessage(MSG_SEND_SESSION_MODIFY_REQUEST, args).sendToTarget();
             }
 
             public void sendSessionModifyResponse(VideoProfile responseProfile) {
@@ -606,9 +616,11 @@
          * Some examples of session modification requests: upgrade connection from audio to video,
          * downgrade connection from video to audio, pause video.
          *
-         * @param requestProfile The requested connection video properties.
+         * @param fromProfile The video properties prior to the request.
+         * @param toProfile The video properties with the requested changes made.
          */
-        public abstract void onSendSessionModifyRequest(VideoProfile requestProfile);
+        public abstract void onSendSessionModifyRequest(VideoProfile fromProfile,
+                VideoProfile toProfile);
 
         /**te
          * Provides a response to a request to change the current connection session video
diff --git a/telecomm/java/android/telecom/ParcelableCall.java b/telecomm/java/android/telecom/ParcelableCall.java
index 1a30910..bb65ce9a 100644
--- a/telecomm/java/android/telecom/ParcelableCall.java
+++ b/telecomm/java/android/telecom/ParcelableCall.java
@@ -178,10 +178,10 @@
      * Returns an object for remotely communicating through the video call provider's binder.
      * @return The video call.
      */
-    public InCallService.VideoCall getVideoCall() {
+    public InCallService.VideoCall getVideoCall(Call call) {
         if (mVideoCall == null && mVideoCallProvider != null) {
             try {
-                mVideoCall = new VideoCallImpl(mVideoCallProvider);
+                mVideoCall = new VideoCallImpl(mVideoCallProvider, call);
             } catch (RemoteException ignored) {
                 // Ignore RemoteException.
             }
diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java
index 1493b20..9ca9f316 100644
--- a/telecomm/java/android/telecom/RemoteConnection.java
+++ b/telecomm/java/android/telecom/RemoteConnection.java
@@ -350,9 +350,9 @@
             }
         }
 
-        public void sendSessionModifyRequest(VideoProfile reqProfile) {
+        public void sendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile) {
             try {
-                mVideoProviderBinder.sendSessionModifyRequest(reqProfile);
+                mVideoProviderBinder.sendSessionModifyRequest(fromProfile, toProfile);
             } catch (RemoteException e) {
             }
         }
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 1431eb8..ebd3f12 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1143,8 +1143,12 @@
     public void placeCall(Uri address, Bundle extras) {
         ITelecomService service = getTelecomService();
         if (service != null) {
+            if (address == null) {
+                Log.w(TAG, "Cannot place call to empty address.");
+            }
             try {
-                service.placeCall(address, extras, mContext.getOpPackageName());
+                service.placeCall(address, extras == null ? new Bundle() : extras,
+                        mContext.getOpPackageName());
             } catch (RemoteException e) {
                 Log.e(TAG, "Error calling ITelecomService#placeCall", e);
             }
diff --git a/telecomm/java/android/telecom/VideoCallImpl.java b/telecomm/java/android/telecom/VideoCallImpl.java
index 7a82c1b..331f57e 100644
--- a/telecomm/java/android/telecom/VideoCallImpl.java
+++ b/telecomm/java/android/telecom/VideoCallImpl.java
@@ -40,6 +40,8 @@
     private final IVideoProvider mVideoProvider;
     private final VideoCallListenerBinder mBinder;
     private VideoCall.Callback mCallback;
+    private int mVideoQuality = VideoProfile.QUALITY_UNKNOWN;
+    private Call mCall;
 
     private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
         @Override
@@ -161,6 +163,7 @@
                             (CameraCapabilities) msg.obj);
                     break;
                 case MSG_CHANGE_VIDEO_QUALITY:
+                    mVideoQuality = msg.arg1;
                     mCallback.onVideoQualityChanged(msg.arg1);
                     break;
                 default:
@@ -171,12 +174,13 @@
 
     private Handler mHandler;
 
-    VideoCallImpl(IVideoProvider videoProvider) throws RemoteException {
+    VideoCallImpl(IVideoProvider videoProvider, Call call) throws RemoteException {
         mVideoProvider = videoProvider;
         mVideoProvider.asBinder().linkToDeath(mDeathRecipient, 0);
 
         mBinder = new VideoCallListenerBinder();
         mVideoProvider.addVideoCallback(mBinder);
+        mCall = call;
     }
 
     public void destroy() {
@@ -251,10 +255,24 @@
         }
     }
 
-    /** {@inheritDoc} */
+    /**
+     * Sends a session modification request to the video provider.
+     * <p>
+     * The {@link InCallService} will create the {@code requestProfile} based on the current
+     * video state (i.e. {@link Call.Details#getVideoState()}).  It is, however, possible that the
+     * video state maintained by the {@link InCallService} could get out of sync with what is known
+     * by the {@link android.telecom.Connection.VideoProvider}.  To remove ambiguity, the
+     * {@link VideoCallImpl} passes along the pre-modify video profile to the {@code VideoProvider}
+     * to ensure it has full context of the requested change.
+     *
+     * @param requestProfile The requested video profile.
+     */
     public void sendSessionModifyRequest(VideoProfile requestProfile) {
         try {
-            mVideoProvider.sendSessionModifyRequest(requestProfile);
+            VideoProfile originalProfile = new VideoProfile(mCall.getDetails().getVideoState(),
+                    mVideoQuality);
+
+            mVideoProvider.sendSessionModifyRequest(originalProfile, requestProfile);
         } catch (RemoteException e) {
         }
     }
diff --git a/telecomm/java/com/android/internal/telecom/IVideoProvider.aidl b/telecomm/java/com/android/internal/telecom/IVideoProvider.aidl
index bff3865..d095744 100644
--- a/telecomm/java/com/android/internal/telecom/IVideoProvider.aidl
+++ b/telecomm/java/com/android/internal/telecom/IVideoProvider.aidl
@@ -39,7 +39,7 @@
 
     void setZoom(float value);
 
-    void sendSessionModifyRequest(in VideoProfile reqProfile);
+    void sendSessionModifyRequest(in VideoProfile fromProfile, in VideoProfile toProfile);
 
     void sendSessionModifyResponse(in VideoProfile responseProfile);
 
diff --git a/telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl b/telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl
index 1fd88e7..4ff0b43 100644
--- a/telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl
+++ b/telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl
@@ -52,7 +52,7 @@
 
     void setZoom(float value);
 
-    void sendSessionModifyRequest(in VideoProfile reqProfile);
+    void sendSessionModifyRequest(in VideoProfile fromProfile, in VideoProfile toProfile);
 
     void sendSessionModifyResponse(in VideoProfile responseProfile);
 
diff --git a/tests/OneMedia/Android.mk b/tests/OneMedia/Android.mk
index b7d7f98..9fc6403 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_JAVA_LIBRARIES += org.apache.http.legacy
 
 LOCAL_PROGUARD_ENABLED := disabled
diff --git a/tests/OneMedia/AndroidManifest.xml b/tests/OneMedia/AndroidManifest.xml
index ef3fad5..c6824ec 100644
--- a/tests/OneMedia/AndroidManifest.xml
+++ b/tests/OneMedia/AndroidManifest.xml
@@ -27,15 +27,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 141a209..2455c9c 100644
--- a/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
+++ b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
@@ -19,25 +19,17 @@
 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.MediaSession.QueueItem;
 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;
 
@@ -48,7 +40,6 @@
     private static final String TAG = "PlayerSession";
 
     protected MediaSession mSession;
-    protected MediaRouter mRouter;
     protected Context mContext;
     protected Renderer mRenderer;
     protected MediaSession.Callback mCallback;
@@ -84,22 +75,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();
     }
@@ -117,10 +97,6 @@
             mSession.release();
             mSession = null;
         }
-        if (mRouter != null) {
-            mRouter.release();
-            mRouter = null;
-        }
     }
 
     public void setListener(Listener listener) {
@@ -278,63 +254,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/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
index 9eea663..87762a6 100644
--- a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
+++ b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
@@ -16,19 +16,15 @@
 
 package android.view;
 
-import com.android.ide.common.rendering.api.LayoutlibCallback;
 import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.ide.common.rendering.api.LayoutlibCallback;
 import com.android.ide.common.rendering.api.MergeCookie;
 import com.android.ide.common.rendering.api.ResourceReference;
 import com.android.ide.common.rendering.api.ResourceValue;
 import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.BridgeConstants;
 import com.android.layoutlib.bridge.android.BridgeContext;
 import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
-import com.android.layoutlib.bridge.android.support.RecyclerViewUtil;
-import com.android.layoutlib.bridge.android.support.RecyclerViewUtil.LayoutManagerType;
 import com.android.layoutlib.bridge.impl.ParserFactory;
-import com.android.layoutlib.bridge.impl.RenderSessionImpl;
 import com.android.resources.ResourceType;
 import com.android.util.Pair;
 
@@ -233,22 +229,6 @@
             if (viewKey != null) {
                 bc.addViewKey(view, viewKey);
             }
-            if (RenderSessionImpl.isInstanceOf(view, RecyclerViewUtil.CN_RECYCLER_VIEW)) {
-                String type = attrs.getAttributeValue(BridgeConstants.NS_RESOURCES,
-                                BridgeConstants.ATTR_LAYOUT_MANAGER_TYPE);
-                if (type != null) {
-                    LayoutManagerType layoutManagerType = LayoutManagerType.getByLogicalName(type);
-                    if (layoutManagerType == null) {
-                        layoutManagerType = LayoutManagerType.getByClassName(type);
-                    }
-                    if (layoutManagerType == null) {
-                        // add the classname itself.
-                        bc.addCookie(view, type);
-                    } else {
-                        bc.addCookie(view, layoutManagerType);
-                    }
-                }
-            }
         }
     }
 
diff --git a/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java b/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java
index ec3a8d6..30512aa 100644
--- a/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java
+++ b/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java
@@ -19,6 +19,7 @@
 import com.android.layoutlib.bridge.impl.ResourceHelper;
 
 import android.graphics.Canvas;
+import android.graphics.Canvas_Delegate;
 import android.graphics.LinearGradient;
 import android.graphics.Outline;
 import android.graphics.Paint;
@@ -125,6 +126,9 @@
 
     private static void sideShadow(Canvas canvas, Paint edgePaint,
             RectF edgeShadowRect, float dx, float dy, int rotations) {
+        if (isRectEmpty(edgeShadowRect)) {
+            return;
+        }
         int saved = canvas.save();
         canvas.translate(dx, dy);
         canvas.rotate(rotations * PERPENDICULAR_ANGLE);
@@ -153,4 +157,15 @@
         canvas.drawPath(path, paint);
         canvas.restoreToCount(saved);
     }
+
+    /**
+     * Differs from {@link RectF#isEmpty()} as this first converts the rect to int and then checks.
+     * <p/>
+     * This is required because {@link Canvas_Delegate#native_drawRect(long, float, float, float,
+     * float, long)} casts the co-ordinates to int and we want to ensure that it doesn't end up
+     * drawing empty rectangles, which results in IllegalArgumentException.
+     */
+    private static boolean isRectEmpty(RectF rect) {
+        return (int) rect.left >= (int) rect.right || (int) rect.top >= (int) rect.bottom;
+    }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 094778d..eb5f597 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -93,6 +93,8 @@
 import java.util.List;
 import java.util.Map;
 
+import static com.android.layoutlib.bridge.android.RenderParamsFlags.FLAG_KEY_APPLICATION_PACKAGE;
+
 /**
  * Custom implementation of Context/Activity to handle non compiled resources.
  */
@@ -306,7 +308,7 @@
         // check if this is a style resource
         if (value instanceof StyleResourceValue) {
             // get the id that will represent this style.
-            outValue.resourceId = getDynamicIdByStyle((StyleResourceValue)value);
+            outValue.resourceId = getDynamicIdByStyle((StyleResourceValue) value);
             return true;
         }
 
@@ -812,6 +814,14 @@
     }
 
 
+    @Override
+    public String getPackageName() {
+        if (mApplicationInfo.packageName == null) {
+            mApplicationInfo.packageName = mLayoutlibCallback.getFlag(FLAG_KEY_APPLICATION_PACKAGE);
+        }
+        return mApplicationInfo.packageName;
+    }
+
     // ------------- private new methods
 
     /**
@@ -1225,12 +1235,6 @@
     }
 
     @Override
-    public String getPackageName() {
-        // pass
-        return null;
-    }
-
-    @Override
     public String getBasePackageName() {
         // pass
         return null;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
index c44a57c..8899e53 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
@@ -164,7 +164,8 @@
     }
 
     @Override
-    public void showInputMethodPickerFromClient(IInputMethodClient arg0) throws RemoteException {
+    public void showInputMethodPickerFromClient(IInputMethodClient arg0,
+            int arg1) throws RemoteException {
         // TODO Auto-generated method stub
 
     }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java
index 2f45473..b98f96f 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java
@@ -16,6 +16,7 @@
 
 package com.android.layoutlib.bridge.android;
 
+import com.android.ide.common.rendering.api.RenderParams;
 import com.android.ide.common.rendering.api.SessionParams.Key;
 
 /**
@@ -31,10 +32,21 @@
             new Key<String>("rootTag", String.class);
     public static final Key<Boolean> FLAG_KEY_DISABLE_BITMAP_CACHING =
             new Key<Boolean>("disableBitmapCaching", Boolean.class);
-    public static final Key<Boolean> FLAG_KEY_RECYCLER_VIEW_SUPPORT =
-            new Key<Boolean>("recyclerViewSupport", Boolean.class);
     public static final Key<Boolean> FLAG_KEY_RENDER_ALL_DRAWABLE_STATES =
             new Key<Boolean>("renderAllDrawableStates", Boolean.class);
+    /**
+     * To tell LayoutLib that the IDE supports RecyclerView.
+     * <p/>
+     * Default is false.
+     */
+    public static final Key<Boolean> FLAG_KEY_RECYCLER_VIEW_SUPPORT =
+            new Key<Boolean>("recyclerViewSupport", Boolean.class);
+    /**
+     * The application package name. Used via
+     * {@link com.android.ide.common.rendering.api.LayoutlibCallback#getFlag(Key)}
+     */
+    public static final Key<String> FLAG_KEY_APPLICATION_PACKAGE =
+            new Key<String>("applicationPackage", String.class);
 
     // Disallow instances.
     private RenderParamsFlags() {}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java
index 9273ac2..e4c7288 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java
@@ -27,11 +27,12 @@
 
 import android.content.Context;
 import android.view.View;
-import android.widget.LinearLayout;
 
 import java.lang.reflect.Method;
 
-import static com.android.layoutlib.bridge.util.ReflectionUtils.*;
+import static com.android.layoutlib.bridge.util.ReflectionUtils.ReflectionException;
+import static com.android.layoutlib.bridge.util.ReflectionUtils.getMethod;
+import static com.android.layoutlib.bridge.util.ReflectionUtils.invoke;
 
 /**
  * Utility class for working with android.support.v7.widget.RecyclerView
@@ -39,17 +40,15 @@
 @SuppressWarnings("SpellCheckingInspection")  // for "recycler".
 public class RecyclerViewUtil {
 
-    /**
-     * Used by {@link LayoutManagerType}.
-     * <p/>
-     * Not declared inside the enum, since it needs to be accessible in the constructor.
-     */
-    private static final Object CONTEXT = new Object();
-
-    public static final String CN_RECYCLER_VIEW = "android.support.v7.widget.RecyclerView";
+    private static final String RV_PKG_PREFIX = "android.support.v7.widget.";
+    public static final String CN_RECYCLER_VIEW = RV_PKG_PREFIX + "RecyclerView";
     private static final String CN_LAYOUT_MANAGER = CN_RECYCLER_VIEW + "$LayoutManager";
     private static final String CN_ADAPTER = CN_RECYCLER_VIEW + "$Adapter";
 
+    // LinearLayoutManager related constants.
+    private static final String CN_LINEAR_LAYOUT_MANAGER = RV_PKG_PREFIX + "LinearLayoutManager";
+    private static final Class<?>[] LLM_CONSTRUCTOR_SIGNATURE = new Class<?>[]{Context.class};
+
     /**
      * Tries to create an Adapter ({@code android.support.v7.widget.RecyclerView.Adapter} and a
      * LayoutManager {@code RecyclerView.LayoutManager} and assign these to the {@code RecyclerView}
@@ -71,37 +70,33 @@
 
     private static void setLayoutManager(@NonNull View recyclerView, @NonNull BridgeContext context,
             @NonNull LayoutlibCallback callback) throws ReflectionException {
-        Object cookie = context.getCookie(recyclerView);
-        assert cookie == null || cookie instanceof LayoutManagerType || cookie instanceof String;
-        if (!(cookie instanceof LayoutManagerType)) {
-            if (cookie != null) {
-                // TODO: When layoutlib API is updated, try to load the class with a null
-                // constructor or a constructor taking one argument - the context.
-                Bridge.getLog().warning(LayoutLog.TAG_UNSUPPORTED,
-                        "LayoutManager (" + cookie + ") not found, falling back to " +
-                                "LinearLayoutManager", null);
-            }
-            cookie = LayoutManagerType.getDefault();
+        if (getLayoutManager(recyclerView) == null) {
+            // Only set the layout manager if not already set by the recycler view.
+            Object layoutManager = createLayoutManager(context, callback);
+            setProperty(recyclerView, CN_LAYOUT_MANAGER, layoutManager, "setLayoutManager");
         }
-        Object layoutManager = createLayoutManager((LayoutManagerType) cookie, context, callback);
-        setProperty(recyclerView, CN_LAYOUT_MANAGER, layoutManager, "setLayoutManager");
     }
 
+    /** Creates a LinearLayoutManager using the provided context. */
     @Nullable
-    private static Object createLayoutManager(@Nullable LayoutManagerType type,
-            @NonNull Context context, @NonNull LayoutlibCallback callback)
+    private static Object createLayoutManager(@NonNull Context context,
+            @NonNull LayoutlibCallback callback)
             throws ReflectionException {
-        if (type == null) {
-            type = LayoutManagerType.getDefault();
-        }
         try {
-            return callback.loadView(type.getClassName(), type.getSignature(), type.getArgs(context));
+            return callback.loadView(CN_LINEAR_LAYOUT_MANAGER, LLM_CONSTRUCTOR_SIGNATURE,
+                    new Object[]{ context});
         } catch (Exception e) {
             throw new ReflectionException(e);
         }
     }
 
     @Nullable
+    private static Object getLayoutManager(View recyclerview) throws ReflectionException {
+        Method getLayoutManager = getMethod(recyclerview.getClass(), "getLayoutManager");
+        return getLayoutManager != null ? invoke(getLayoutManager, recyclerview) : null;
+    }
+
+    @Nullable
     private static Object createAdapter(@NonNull SessionParams params) throws ReflectionException {
         Boolean ideSupport = params.getFlag(RenderParamsFlags.FLAG_KEY_RECYCLER_VIEW_SUPPORT);
         if (ideSupport != Boolean.TRUE) {
@@ -145,74 +140,4 @@
         }
         throw new RuntimeException("invalid object/classname combination.");
     }
-
-    /** Supported LayoutManagers. */
-    public enum LayoutManagerType {
-        LINEAR_LAYOUT_MANGER("Linear",
-                "android.support.v7.widget.LinearLayoutManager",
-                new Class[]{Context.class}, new Object[]{CONTEXT}),
-        GRID_LAYOUT_MANAGER("Grid",
-                "android.support.v7.widget.GridLayoutManager",
-                new Class[]{Context.class, int.class}, new Object[]{CONTEXT, 2}),
-        STAGGERED_GRID_LAYOUT_MANAGER("StaggeredGrid",
-                "android.support.v7.widget.StaggeredGridLayoutManager",
-                new Class[]{int.class, int.class}, new Object[]{2, LinearLayout.VERTICAL});
-
-        private String mLogicalName;
-        private String mClassName;
-        private Class[] mSignature;
-        private Object[] mArgs;
-
-        LayoutManagerType(String logicalName, String className, Class[] signature, Object[] args) {
-            mLogicalName = logicalName;
-            mClassName = className;
-            mSignature = signature;
-            mArgs = args;
-        }
-
-        String getClassName() {
-            return mClassName;
-        }
-
-        Class[] getSignature() {
-            return mSignature;
-        }
-
-        @NonNull
-        Object[] getArgs(Context context) {
-            Object[] args = new Object[mArgs.length];
-            System.arraycopy(mArgs, 0, args, 0, mArgs.length);
-            for (int i = 0; i < args.length; i++) {
-                if (args[i] == CONTEXT) {
-                    args[i] = context;
-                }
-            }
-            return args;
-        }
-
-        @NonNull
-        public static LayoutManagerType getDefault() {
-            return LINEAR_LAYOUT_MANGER;
-        }
-
-        @Nullable
-        public static LayoutManagerType getByLogicalName(@NonNull String logicalName) {
-            for (LayoutManagerType type : values()) {
-                if (logicalName.equals(type.mLogicalName)) {
-                    return type;
-                }
-            }
-            return null;
-        }
-
-        @Nullable
-        public static LayoutManagerType getByClassName(@NonNull String className) {
-            for (LayoutManagerType type : values()) {
-                if (className.equals(type.mClassName)) {
-                    return type;
-                }
-            }
-            return null;
-        }
-    }
 }
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 9f9b968..dc89d0c 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
@@ -74,7 +74,7 @@
     }
 
     public static String getTime(int platformVersion) {
-        if (platformVersion == 0) {
+        if (isGreaterOrEqual(platformVersion, LOLLIPOP_MR1)) {
             return "5:10";
         }
         if (platformVersion < GINGERBREAD) {
@@ -117,7 +117,7 @@
     }
 
     public static String getWifiIconType(int platformVersion) {
-        return platformVersion == 0 ? "xml" : "png";
+        return isGreaterOrEqual(platformVersion, LOLLIPOP) ? "xml" : "png";
     }
 
     /**
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
index 9450b6c..04aadff 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
@@ -21,6 +21,10 @@
 
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.util.AttributeSet;
+import android.view.View;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
@@ -29,6 +33,21 @@
     /** Navigation bar background color attribute name. */
     private static final String ATTR_COLOR = "navigationBarColor";
 
+    /**
+     * Constructor to be used when creating the {@link NavigationBar} as a regular control.
+     * This is currently used by the theme editor.
+     */
+    public NavigationBar(Context context, AttributeSet attrs)
+            throws XmlPullParserException {
+        this((BridgeContext) context,
+                Density.getEnum(((BridgeContext) context).getMetrics().densityDpi),
+                LinearLayout.HORIZONTAL, // In this mode, it doesn't need to be render vertically
+                ((BridgeContext) context).getConfiguration().getLayoutDirection() ==
+                        View.LAYOUT_DIRECTION_RTL,
+                (context.getApplicationInfo().flags & ApplicationInfo.FLAG_SUPPORTS_RTL) != 0,
+                context.getApplicationInfo().targetSdkVersion);
+    }
+
     public NavigationBar(BridgeContext context, Density density, int orientation, boolean isRtl,
             boolean rtlEnabled, int simulatedPlatformVersion) throws XmlPullParserException {
         super(context, orientation, "/bars/navigation_bar.xml", "navigation_bar.xml",
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 e5f1f68..a0ed0e8 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
@@ -25,7 +25,9 @@
 
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.content.Context;
 import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
 import android.view.Gravity;
 import android.view.View;
 import android.widget.ImageView;
@@ -39,7 +41,20 @@
 
     private final int mSimulatedPlatformVersion;
     /** Status bar background color attribute name. */
-    private static final String ATTR_COLOR = "colorPrimaryDark";
+    private static final String ATTR_COLOR = "statusBarColor";
+
+    /**
+     * Constructor to be used when creating the {@link StatusBar} as a regular control. This
+     * is currently used by the theme editor.
+     */
+    public StatusBar(Context context, AttributeSet attrs) throws XmlPullParserException {
+        this((BridgeContext) context,
+                Density.getEnum(((BridgeContext) context).getMetrics().densityDpi),
+                LinearLayout.HORIZONTAL, // In this mode, it doesn't need to be render vertically
+                ((BridgeContext) context).getConfiguration().getLayoutDirection() ==
+                        View.LAYOUT_DIRECTION_RTL,
+                context.getApplicationInfo().targetSdkVersion);
+    }
 
     public StatusBar(BridgeContext context, Density density, int direction, boolean RtlEnabled,
             int simulatedPlatformVersion) throws XmlPullParserException {
@@ -50,6 +65,7 @@
 
         // FIXME: use FILL_H?
         setGravity(Gravity.START | Gravity.TOP | Gravity.RIGHT);
+
         int color = getThemeAttrColor(ATTR_COLOR, true);
         setBackgroundColor(color == 0 ? Config.getStatusBarColor(simulatedPlatformVersion) : color);
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java
index 3dee1e2..26f9000 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java
@@ -42,6 +42,10 @@
 import java.util.Collections;
 import java.util.List;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
 /**
  * Action to render a given Drawable provided through {@link DrawableParams#getDrawable()}.
  *
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index d9572591..f6e5ef1 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -1075,7 +1075,7 @@
 
     private void findStatusBar(RenderResources resources, DisplayMetrics metrics) {
         boolean windowFullscreen = getBooleanThemeValue(resources,
-                "windowFullscreen", false, !isThemeAppCompat(resources));
+                "windowFullscreen", false, true);
 
         if (!windowFullscreen && !mWindowIsFloating) {
             // default value
@@ -1210,15 +1210,15 @@
           // between Theme.AppCompat.Light and Theme.AppCompat is Theme.Material (for v21).
             boolean isThemeAppCompat = false;
             for (int i = 0; i < 50; i++) {
+                if (defaultTheme == null) {
+                    break;
+                }
                 // for loop ensures that we don't run into cyclic theme inheritance.
                 if (defaultTheme.getName().startsWith("Theme.AppCompat")) {
                     isThemeAppCompat = true;
                     break;
                 }
                 defaultTheme = resources.getParent(defaultTheme);
-                if (defaultTheme == null) {
-                    break;
-                }
             }
             mIsThemeAppCompat = isThemeAppCompat;
         }
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/MyActivity.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/MyActivity.class
index d252462..8af93eb 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/MyActivity.class
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/MyActivity.class
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$id.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$id.class
index d109302..069f9f7 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$id.class
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$id.class
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$layout.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$layout.class
index 816ecc8..36e2688 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$layout.class
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$layout.class
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$menu.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$menu.class
index b034b75..ca438ad 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$menu.class
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$menu.class
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$string.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$string.class
index f86b1d3..a98abf5 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$string.class
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$string.class
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$style.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$style.class
index 8bbae90..7d8cc84 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$style.class
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$style.class
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R.class
index 8af745d..7e6113b 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R.class
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R.class
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
new file mode 100644
index 0000000..c9b76be
--- /dev/null
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml
new file mode 100644
index 0000000..2da2cb9
--- /dev/null
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml
@@ -0,0 +1,393 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:ignore="HardcodedText,LabelFor,TextFields,ContentDescription,RtlHardcoded">
+
+    <FrameLayout
+        android:id="@id/frameLayout"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentEnd="true"
+        android:layout_alignParentTop="true"
+        android:layout_marginEnd="311dp">
+
+        <TextView
+            android:id="@id/textView"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="left|top"
+            android:text="New Text" />
+    </FrameLayout>
+
+    <TextView
+        android:id="@id/textView2"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentStart="true"
+        android:layout_below="@id/frameLayout"
+        android:text="Large Text"
+        android:textAppearance="?android:attr/textAppearanceLarge" />
+
+    <TextView
+        android:id="@id/textView3"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentTop="true"
+        android:layout_toEndOf="@id/textView2"
+        android:text="Medium Text"
+        android:textAppearance="?android:attr/textAppearanceMedium" />
+
+    <TextView
+        android:id="@id/textView4"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignTop="@id/textView2"
+        android:layout_toEndOf="@id/textView2"
+        android:text="Small Text"
+        android:textAppearance="?android:attr/textAppearanceSmall" />
+
+    <Button
+        android:id="@id/button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/textView3"
+        android:layout_toEndOf="@id/textView4"
+        android:text="New Button" />
+
+    <Button
+        android:id="@id/button2"
+        style="?android:attr/buttonStyleSmall"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentTop="true"
+        android:layout_toEndOf="@id/button"
+        android:text="New Button" />
+
+    <CheckBox
+        android:id="@id/checkBox"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignEnd="@id/button"
+        android:layout_below="@id/button"
+        android:text="New CheckBox" />
+
+    <Switch
+        android:id="@id/switch1"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentStart="true"
+        android:layout_below="@id/textView2"
+        android:text="New Switch" />
+
+    <ImageButton
+        android:id="@id/imageButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/button"
+        android:layout_toEndOf="@id/switch1" />
+
+    <ImageView
+        android:id="@id/imageView"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:src="@drawable/ic_launcher"
+        android:layout_below="@id/button"
+        android:layout_toEndOf="@id/imageButton" />
+
+    <GridLayout
+        android:id="@id/gridLayout"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentStart="true"
+        android:layout_below="@id/imageButton"
+        android:columnCount="2"
+        android:rowCount="2">
+
+        <ProgressBar
+            android:id="@id/progressBar"
+            style="?android:attr/progressBarStyleLarge"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_column="0"
+            android:layout_row="0" />
+
+        <ProgressBar
+            android:id="@id/progressBar2"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_column="1"
+            android:layout_row="0" />
+
+        <ProgressBar
+            android:id="@id/progressBar3"
+            style="?android:attr/progressBarStyleSmall"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_column="0"
+            android:layout_row="1" />
+
+        <ProgressBar
+            android:id="@id/progressBar4"
+            style="?android:attr/progressBarStyleHorizontal"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_column="1"
+            android:layout_row="1" />
+    </GridLayout>
+
+    <SeekBar
+        android:id="@id/seekBar"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignTop="@id/gridLayout"
+        android:layout_toEndOf="@id/gridLayout" />
+
+    <RatingBar
+        android:id="@id/ratingBar"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/switch2"
+        android:layout_toEndOf="@id/gridLayout" />
+
+    <Switch
+        android:id="@id/switch2"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/seekBar"
+        android:layout_toEndOf="@id/switch1"
+        android:checked="true" />
+
+    <EditText
+        android:id="@id/editText"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignBottom="@id/ratingBar"
+        android:layout_alignParentStart="true"
+        android:text="plain text" />
+
+    <EditText
+        android:id="@id/editText2"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentStart="true"
+        android:layout_below="@id/ratingBar"
+        android:ems="3"
+        android:inputType="textPersonName"
+        android:text="Name" />
+
+    <EditText
+        android:id="@id/editText3"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerVertical="true"
+        android:layout_toEndOf="@id/editText2"
+        android:ems="2"
+        android:inputType="textPassword"
+        android:text="password" />
+
+    <EditText
+        android:id="@id/editText4"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignTop="@id/editText3"
+        android:layout_toEndOf="@id/editText3"
+        android:ems="3"
+        android:inputType="numberPassword"
+        android:text="numeric password" />
+
+    <EditText
+        android:id="@id/editText5"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/editText3"
+        android:layout_toStartOf="@id/editText6"
+        android:ems="7"
+        android:inputType="textEmailAddress"
+        android:text="email@domain.com" />
+
+    <EditText
+        android:id="@id/editText6"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentEnd="true"
+        android:layout_below="@id/editText4"
+        android:ems="7"
+        android:inputType="phone"
+        android:text="+11235554344" />
+
+    <EditText
+        android:id="@id/editText7"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/editText"
+        android:layout_toEndOf="@id/editText4"
+        android:ems="10"
+        android:inputType="textPostalAddress"
+        android:text="1600 Amphitheatre" />
+
+    <EditText
+        android:id="@id/editText9"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/editText5"
+        android:layout_alignParentStart="true"
+        android:ems="3"
+        android:inputType="time"
+        android:text="12:12" />
+
+    <RadioGroup
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/editText5"
+        android:layout_toEndOf="@id/editText9"
+        android:orientation="horizontal">
+
+        <RadioButton
+            android:id="@id/radioButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="New RadioButton" />
+
+        <RadioButton
+            android:id="@id/radioButton2"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="New RadioButton" />
+
+    </RadioGroup>
+
+    <CheckedTextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="CheckedTextView"
+        android:id="@id/checkedTextView"
+        android:layout_below="@id/button2"
+        android:layout_alignParentEnd="true"
+        android:layout_alignStart="@id/button2" />
+
+    <DialerFilter
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/checkBox"
+        android:layout_toStartOf="@id/quickContactBadge"
+        android:id="@id/dialerFilter"
+        android:layout_above="@id/ratingBar"
+        android:layout_toEndOf="@id/seekBar">
+
+        <EditText
+            android:id="@android:id/hint"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="Hint" />
+
+        <EditText
+            android:id="@android:id/primary"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_below="@android:id/hint"
+            android:text="Primary" />
+    </DialerFilter>
+
+    <QuickContactBadge
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@id/quickContactBadge"
+        android:layout_below="@id/checkedTextView"
+        android:layout_alignParentEnd="true" />
+
+    <android.inputmethodservice.ExtractEditText
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="ExtractEditText"
+        android:id="@id/extractEditText"
+        android:layout_below="@id/editText9"
+        android:layout_alignParentEnd="true"
+        android:layout_alignStart="@id/checkedTextView" />
+
+    <ZoomControls
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@id/zoomControls"
+        android:layout_below="@id/editText9"
+        android:layout_alignParentStart="true" />
+
+    <TextureView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@id/textureView"
+        android:layout_below="@id/zoomControls"
+        android:layout_alignParentStart="true"
+        android:layout_alignBottom="@id/extractEditText"
+        android:layout_toStartOf="@id/editText3" />
+
+    <ListView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@id/listView"
+        android:layout_below="@id/textureView"
+        android:layout_alignParentStart="true"
+        android:layout_alignEnd="@id/textureView" />
+
+    <GridView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@id/gridView"
+        android:layout_below="@id/extractEditText"
+        android:layout_alignParentEnd="true"
+        android:layout_alignStart="@id/extractEditText" />
+
+    <ScrollView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@id/scrollView"
+        android:layout_below="@id/zoomControls"
+        android:layout_toRightOf="@id/listView"
+        android:layout_toLeftOf="@id/extractEditText">
+
+    <TabHost
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:id="@id/tabHost">
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:orientation="vertical">
+
+            <TabWidget
+                android:id="@android:id/tabs"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+
+            <FrameLayout
+                android:id="@android:id/tabcontent"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent">
+
+                <LinearLayout
+                    android:id="@id/linearLayout"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:orientation="vertical"/>
+
+                <LinearLayout
+                    android:id="@id/linearLayout2"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:orientation="vertical"/>
+
+            </FrameLayout>
+        </LinearLayout>
+    </TabHost>
+</ScrollView>
+
+    <SearchView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@id/searchView"
+        android:layout_alignBottom="@id/zoomControls"
+        android:layout_toEndOf="@id/seekBar" />
+
+</RelativeLayout>
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/values/ids.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/values/ids.xml
new file mode 100644
index 0000000..1dc2fa0
--- /dev/null
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/values/ids.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <item type="id" name="button" />
+    <item type="id" name="button2" />
+    <item type="id" name="checkBox" />
+    <item type="id" name="checkedTextView" />
+    <item type="id" name="dialerFilter" />
+    <item type="id" name="editText" />
+    <item type="id" name="editText2" />
+    <item type="id" name="editText3" />
+    <item type="id" name="editText4" />
+    <item type="id" name="editText5" />
+    <item type="id" name="editText6" />
+    <item type="id" name="editText7" />
+    <item type="id" name="editText8" />
+    <item type="id" name="editText9" />
+    <item type="id" name="extractEditText" />
+    <item type="id" name="frameLayout" />
+    <item type="id" name="gridLayout" />
+    <item type="id" name="gridView" />
+    <item type="id" name="imageButton" />
+    <item type="id" name="imageView" />
+    <item type="id" name="linearLayout" />
+    <item type="id" name="linearLayout2" />
+    <item type="id" name="listView" />
+    <item type="id" name="progressBar" />
+    <item type="id" name="progressBar2" />
+    <item type="id" name="progressBar3" />
+    <item type="id" name="progressBar4" />
+    <item type="id" name="quickContactBadge" />
+    <item type="id" name="radioButton" />
+    <item type="id" name="radioButton2" />
+    <item type="id" name="ratingBar" />
+    <item type="id" name="scrollView" />
+    <item type="id" name="searchView" />
+    <item type="id" name="seekBar" />
+    <item type="id" name="spinner" />
+    <item type="id" name="switch1" />
+    <item type="id" name="switch2" />
+    <item type="id" name="tabHost" />
+    <item type="id" name="textView" />
+    <item type="id" name="textView2" />
+    <item type="id" name="textView3" />
+    <item type="id" name="textView4" />
+    <item type="id" name="textureView" />
+    <item type="id" name="zoomControls" />
+</resources>
\ No newline at end of file
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
index ac23564..f2a039e 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
@@ -261,7 +261,7 @@
                 new ResourceRepository(new FolderWrapper(TEST_RES_DIR + APP_TEST_RES), false) {
             @NonNull
             @Override
-            protected ResourceItem createResourceItem(String name) {
+            protected ResourceItem createResourceItem(@NonNull String name) {
                 return new ResourceItem(name);
             }
         };
@@ -275,14 +275,27 @@
                 ConfigGenerator.getEnumMap(attrs), getLayoutLog());
     }
 
-    /**
-     * Create a new rendering session and test that rendering /layout/activity.xml on nexus 5
-     * doesn't throw any exceptions.
-     */
+    /** Text activity.xml */
     @Test
-    public void testRendering() throws ClassNotFoundException {
+    public void testActivity() throws ClassNotFoundException {
+        renderAndVerify("activity.xml", "activity.png");
+
+    }
+
+    /** Test allwidgets.xml */
+    @Test
+    public void testAllWidgets() throws ClassNotFoundException {
+        renderAndVerify("allwidgets.xml", "allwidgets.png");
+    }
+
+    /**
+     * Create a new rendering session and test that rendering given layout on nexus 5
+     * doesn't throw any exceptions and matches the provided image.
+     */
+    private void renderAndVerify(String layoutFileName, String goldenFileName)
+            throws ClassNotFoundException {
         // Create the layout pull parser.
-        LayoutPullParser parser = new LayoutPullParser(APP_TEST_RES + "/layout/activity.xml");
+        LayoutPullParser parser = new LayoutPullParser(APP_TEST_RES + "/layout/" + layoutFileName);
         // Create LayoutLibCallback.
         LayoutLibTestCallback layoutLibCallback = new LayoutLibTestCallback(getLogger());
         layoutLibCallback.initResources();
@@ -301,7 +314,7 @@
                     session.getResult().getErrorMessage());
         }
         try {
-            String goldenImagePath = APP_TEST_DIR + "/golden/activity.png";
+            String goldenImagePath = APP_TEST_DIR + "/golden/" + goldenFileName;
             ImageUtils.requireSimilar(goldenImagePath, session.getImage());
         } catch (IOException e) {
             getLogger().error(e, e.getMessage());
@@ -309,7 +322,7 @@
     }
 
     /**
-     * Uses Theme.Material and Target sdk version as 21.
+     * Uses Theme.Material and Target sdk version as 22.
      */
     private SessionParams getSessionParams(LayoutPullParser layoutParser,
             ConfigGenerator configGenerator, LayoutLibTestCallback layoutLibCallback) {
@@ -327,7 +340,7 @@
                 resourceResolver,
                 layoutLibCallback,
                 0,
-                21, // TODO: Make it more configurable to run tests for various versions.
+                22, // TODO: Make it more configurable to run tests for various versions.
                 getLayoutLog());
     }
 
@@ -381,17 +394,17 @@
                 }
 
                 @Override
-                public void warning(String msgFormat, Object... args) {
+                public void warning(@NonNull String msgFormat, Object... args) {
                     failWithMsg(msgFormat, args);
                 }
 
                 @Override
-                public void info(String msgFormat, Object... args) {
+                public void info(@NonNull String msgFormat, Object... args) {
                     // pass.
                 }
 
                 @Override
-                public void verbose(String msgFormat, Object... args) {
+                public void verbose(@NonNull String msgFormat, Object... args) {
                     // pass.
                 }
             };
@@ -399,7 +412,7 @@
         return mLogger;
     }
 
-    private static void failWithMsg(String msgFormat, Object... args) {
-        fail(msgFormat == null || args == null ? "" : String.format(msgFormat, args));
+    private static void failWithMsg(@NonNull String msgFormat, Object... args) {
+        fail(args == null ? "" : String.format(msgFormat, args));
     }
 }
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/ConfigGenerator.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/ConfigGenerator.java
index a5c3202..1191df6 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/ConfigGenerator.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/ConfigGenerator.java
@@ -21,12 +21,11 @@
 import com.android.ide.common.resources.configuration.DensityQualifier;
 import com.android.ide.common.resources.configuration.FolderConfiguration;
 import com.android.ide.common.resources.configuration.KeyboardStateQualifier;
-import com.android.ide.common.resources.configuration.LanguageQualifier;
 import com.android.ide.common.resources.configuration.LayoutDirectionQualifier;
+import com.android.ide.common.resources.configuration.LocaleQualifier;
 import com.android.ide.common.resources.configuration.NavigationMethodQualifier;
 import com.android.ide.common.resources.configuration.NetworkCodeQualifier;
 import com.android.ide.common.resources.configuration.NightModeQualifier;
-import com.android.ide.common.resources.configuration.RegionQualifier;
 import com.android.ide.common.resources.configuration.ScreenDimensionQualifier;
 import com.android.ide.common.resources.configuration.ScreenOrientationQualifier;
 import com.android.ide.common.resources.configuration.ScreenRatioQualifier;
@@ -158,10 +157,9 @@
         config.setUiModeQualifier(new UiModeQualifier(UiMode.NORMAL));
         config.setNightModeQualifier(new NightModeQualifier(NightMode.NOTNIGHT));
         config.setCountryCodeQualifier(new CountryCodeQualifier());
-        config.setLanguageQualifier(new LanguageQualifier());
         config.setLayoutDirectionQualifier(new LayoutDirectionQualifier());
         config.setNetworkCodeQualifier(new NetworkCodeQualifier());
-        config.setRegionQualifier(new RegionQualifier());
+        config.setLocaleQualifier(new LocaleQualifier());
         config.setVersionQualifier(new VersionQualifier());
         return config;
     }
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/LayoutLibTestCallback.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/LayoutLibTestCallback.java
index 0a5e798..5b648ef 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/LayoutLibTestCallback.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/LayoutLibTestCallback.java
@@ -23,8 +23,8 @@
 import com.android.ide.common.rendering.api.LayoutlibCallback;
 import com.android.ide.common.rendering.api.ResourceReference;
 import com.android.ide.common.rendering.api.ResourceValue;
-import com.android.resources.ResourceType;
 import com.android.ide.common.resources.IntArrayWrapper;
+import com.android.resources.ResourceType;
 import com.android.util.Pair;
 import com.android.utils.ILogger;
 
@@ -36,6 +36,8 @@
 
 import com.google.android.collect.Maps;
 
+import static org.junit.Assert.fail;
+
 @SuppressWarnings("deprecation") // For Pair
 public class LayoutLibTestCallback extends LayoutlibCallback {
 
@@ -121,7 +123,7 @@
 
     @Override
     public ILayoutPullParser getParser(String layoutName) {
-        org.junit.Assert.fail("This method shouldn't be called by this version of LayoutLib.");
+        fail("This method shouldn't be called by this version of LayoutLib.");
         return null;
     }