Merge "Annotate @SystemApi on some WifiManager methods." into lmp-dev
diff --git a/Android.mk b/Android.mk
index b419231..1cdc709 100644
--- a/Android.mk
+++ b/Android.mk
@@ -329,6 +329,7 @@
 	media/java/android/media/projection/IMediaProjection.aidl \
 	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 \
diff --git a/api/current.txt b/api/current.txt
index 0154dd2..b2106d2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2047,6 +2047,8 @@
     field public static final int TextAppearance_Material_Widget_TextView = 16974381; // 0x103022d
     field public static final int TextAppearance_Material_Widget_TextView_PopupMenu = 16974382; // 0x103022e
     field public static final int TextAppearance_Material_Widget_TextView_SpinnerItem = 16974383; // 0x103022f
+    field public static final int TextAppearance_Material_Widget_Toolbar_Subtitle = 16974569; // 0x10302e9
+    field public static final int TextAppearance_Material_Widget_Toolbar_Title = 16974568; // 0x10302e8
     field public static final int TextAppearance_Material_WindowTitle = 16974361; // 0x1030219
     field public static final int TextAppearance_Medium = 16973892; // 0x1030044
     field public static final int TextAppearance_Medium_Inverse = 16973893; // 0x1030045
@@ -8595,19 +8597,26 @@
   }
 
   public class LauncherApps {
+    method public void addCallback(android.content.pm.LauncherApps.Callback);
+    method public void addCallback(android.content.pm.LauncherApps.Callback, android.os.Handler);
     method public void addOnAppsChangedCallback(android.content.pm.LauncherApps.OnAppsChangedCallback);
     method public void addOnAppsChangedCallback(android.content.pm.LauncherApps.OnAppsChangedCallback, android.os.Handler);
     method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
+    method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
     method public boolean isActivityEnabledForProfile(android.content.ComponentName, android.os.UserHandle);
+    method public boolean isPackageEnabled(java.lang.String, android.os.UserHandle);
     method public boolean isPackageEnabledForProfile(java.lang.String, android.os.UserHandle);
+    method public void removeCallback(android.content.pm.LauncherApps.Callback);
     method public void removeOnAppsChangedCallback(android.content.pm.LauncherApps.OnAppsChangedCallback);
     method public android.content.pm.LauncherActivityInfo resolveActivity(android.content.Intent, android.os.UserHandle);
     method public void showAppDetailsForProfile(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
     method public void startActivityForProfile(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
+    method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
+    method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
   }
 
-  public static abstract class LauncherApps.OnAppsChangedCallback {
-    ctor public LauncherApps.OnAppsChangedCallback();
+  public static abstract class LauncherApps.Callback {
+    ctor public LauncherApps.Callback();
     method public abstract void onPackageAdded(java.lang.String, android.os.UserHandle);
     method public abstract void onPackageChanged(java.lang.String, android.os.UserHandle);
     method public abstract void onPackageRemoved(java.lang.String, android.os.UserHandle);
@@ -8615,6 +8624,10 @@
     method public abstract void onPackagesUnavailable(java.lang.String[], android.os.UserHandle, boolean);
   }
 
+  public static abstract class LauncherApps.OnAppsChangedCallback extends android.content.pm.LauncherApps.Callback {
+    ctor public LauncherApps.OnAppsChangedCallback();
+  }
+
   public class PackageInfo implements android.os.Parcelable {
     ctor public PackageInfo();
     method public int describeContents();
@@ -13304,85 +13317,6 @@
 
 }
 
-package android.hardware.location {
-
-  public final class GeofenceHardware {
-    method public boolean addGeofence(int, int, android.hardware.location.GeofenceHardwareRequest, android.hardware.location.GeofenceHardwareCallback);
-    method public int[] getMonitoringTypes();
-    method public int getStatusOfMonitoringType(int);
-    method public boolean pauseGeofence(int, int);
-    method public boolean registerForMonitorStateChangeCallback(int, android.hardware.location.GeofenceHardwareMonitorCallback);
-    method public boolean removeGeofence(int, int);
-    method public boolean resumeGeofence(int, int, int);
-    method public boolean unregisterForMonitorStateChangeCallback(int, android.hardware.location.GeofenceHardwareMonitorCallback);
-    field public static final int GEOFENCE_ENTERED = 1; // 0x1
-    field public static final int GEOFENCE_ERROR_ID_EXISTS = 2; // 0x2
-    field public static final int GEOFENCE_ERROR_ID_UNKNOWN = 3; // 0x3
-    field public static final int GEOFENCE_ERROR_INSUFFICIENT_MEMORY = 6; // 0x6
-    field public static final int GEOFENCE_ERROR_INVALID_TRANSITION = 4; // 0x4
-    field public static final int GEOFENCE_ERROR_TOO_MANY_GEOFENCES = 1; // 0x1
-    field public static final int GEOFENCE_EXITED = 2; // 0x2
-    field public static final int GEOFENCE_FAILURE = 5; // 0x5
-    field public static final int GEOFENCE_SUCCESS = 0; // 0x0
-    field public static final int GEOFENCE_UNCERTAIN = 4; // 0x4
-    field public static final int MONITORING_TYPE_FUSED_HARDWARE = 1; // 0x1
-    field public static final int MONITORING_TYPE_GPS_HARDWARE = 0; // 0x0
-    field public static final int MONITOR_CURRENTLY_AVAILABLE = 0; // 0x0
-    field public static final int MONITOR_CURRENTLY_UNAVAILABLE = 1; // 0x1
-    field public static final int MONITOR_UNSUPPORTED = 2; // 0x2
-    field public static final int SOURCE_TECHNOLOGY_BLUETOOTH = 16; // 0x10
-    field public static final int SOURCE_TECHNOLOGY_CELL = 8; // 0x8
-    field public static final int SOURCE_TECHNOLOGY_GNSS = 1; // 0x1
-    field public static final int SOURCE_TECHNOLOGY_SENSORS = 4; // 0x4
-    field public static final int SOURCE_TECHNOLOGY_WIFI = 2; // 0x2
-  }
-
-  public abstract class GeofenceHardwareCallback {
-    ctor public GeofenceHardwareCallback();
-    method public void onGeofenceAdd(int, int);
-    method public void onGeofencePause(int, int);
-    method public void onGeofenceRemove(int, int);
-    method public void onGeofenceResume(int, int);
-    method public void onGeofenceTransition(int, int, android.location.Location, long, int);
-  }
-
-  public abstract class GeofenceHardwareMonitorCallback {
-    ctor public GeofenceHardwareMonitorCallback();
-    method public deprecated void onMonitoringSystemChange(int, boolean, android.location.Location);
-    method public void onMonitoringSystemChange(android.hardware.location.GeofenceHardwareMonitorEvent);
-  }
-
-  public class GeofenceHardwareMonitorEvent implements android.os.Parcelable {
-    ctor public GeofenceHardwareMonitorEvent(int, int, int, android.location.Location);
-    method public int describeContents();
-    method public android.location.Location getLocation();
-    method public int getMonitoringStatus();
-    method public int getMonitoringType();
-    method public int getSourceTechnologies();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator CREATOR;
-  }
-
-  public final class GeofenceHardwareRequest {
-    ctor public GeofenceHardwareRequest();
-    method public static android.hardware.location.GeofenceHardwareRequest createCircularGeofence(double, double, double);
-    method public int getLastTransition();
-    method public double getLatitude();
-    method public double getLongitude();
-    method public int getMonitorTransitions();
-    method public int getNotificationResponsiveness();
-    method public double getRadius();
-    method public int getSourceTechnologies();
-    method public int getUnknownTimer();
-    method public void setLastTransition(int);
-    method public void setMonitorTransitions(int);
-    method public void setNotificationResponsiveness(int);
-    method public void setSourceTechnologies(int);
-    method public void setUnknownTimer(int);
-  }
-
-}
-
 package android.hardware.usb {
 
   public class UsbAccessory implements android.os.Parcelable {
@@ -16691,33 +16625,41 @@
     method public void adjustVolume(int, int);
     method public android.media.routing.MediaRouter.Delegate createMediaRouterDelegate();
     method public boolean dispatchMediaButtonEvent(android.view.KeyEvent);
+    method public android.media.session.MediaController.AudioInfo getAudioInfo();
     method public android.os.Bundle getExtras();
     method public long getFlags();
     method public android.app.PendingIntent getLaunchActivity();
     method public android.media.MediaMetadata getMetadata();
     method public java.lang.String getPackageName();
     method public android.media.session.PlaybackState getPlaybackState();
-    method public java.util.List<android.media.session.MediaSession.Track> getQueue();
+    method public java.util.List<android.media.session.MediaSession.Item> getQueue();
     method public java.lang.CharSequence getQueueTitle();
     method public int getRatingType();
     method public android.media.session.MediaSession.Token getSessionToken();
     method public android.media.session.MediaController.TransportControls getTransportControls();
-    method public android.media.session.MediaController.VolumeInfo getVolumeInfo();
     method public void removeCallback(android.media.session.MediaController.Callback);
     method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
     method public void setVolumeTo(int, int);
   }
 
+  public static final class MediaController.AudioInfo {
+    method public android.media.AudioAttributes getAudioAttributes();
+    method public int getCurrentVolume();
+    method public int getMaxVolume();
+    method public int getVolumeControl();
+    method public int getVolumeType();
+  }
+
   public static abstract class MediaController.Callback {
     ctor public MediaController.Callback();
+    method public void onAudioInfoChanged(android.media.session.MediaController.AudioInfo);
     method public void onExtrasChanged(android.os.Bundle);
     method public void onMetadataChanged(android.media.MediaMetadata);
     method public void onPlaybackStateChanged(android.media.session.PlaybackState);
-    method public void onQueueChanged(java.util.List<android.media.session.MediaSession.Track>);
+    method public void onQueueChanged(java.util.List<android.media.session.MediaSession.Item>);
     method public void onQueueTitleChanged(java.lang.CharSequence);
     method public void onSessionDestroyed();
     method public void onSessionEvent(java.lang.String, android.os.Bundle);
-    method public void onVolumeInfoChanged(android.media.session.MediaController.VolumeInfo);
   }
 
   public final class MediaController.TransportControls {
@@ -16731,20 +16673,12 @@
     method public void sendCustomAction(android.media.session.PlaybackState.CustomAction, android.os.Bundle);
     method public void sendCustomAction(java.lang.String, android.os.Bundle);
     method public void setRating(android.media.Rating);
+    method public void skipToItem(long);
     method public void skipToNext();
     method public void skipToPrevious();
-    method public void skipToTrack(long);
     method public void stop();
   }
 
-  public static final class MediaController.VolumeInfo {
-    method public android.media.AudioAttributes getAudioAttributes();
-    method public int getCurrentVolume();
-    method public int getMaxVolume();
-    method public int getVolumeControl();
-    method public int getVolumeType();
-  }
-
   public final class MediaSession {
     ctor public MediaSession(android.content.Context, java.lang.String);
     method public android.media.session.MediaController getController();
@@ -16764,7 +16698,7 @@
     method public void setPlaybackState(android.media.session.PlaybackState);
     method public void setPlaybackToLocal(android.media.AudioAttributes);
     method public void setPlaybackToRemote(android.media.VolumeProvider);
-    method public void setQueue(java.util.List<android.media.session.MediaSession.Track>);
+    method public void setQueue(java.util.List<android.media.session.MediaSession.Item>);
     method public void setQueueTitle(java.lang.CharSequence);
     field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
     field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
@@ -16785,19 +16719,13 @@
     method public void onRewind();
     method public void onSeekTo(long);
     method public void onSetRating(android.media.Rating);
+    method public void onSkipToItem(long);
     method public void onSkipToNext();
     method public void onSkipToPrevious();
-    method public void onSkipToTrack(long);
     method public void onStop();
   }
 
-  public static final class MediaSession.Token implements android.os.Parcelable {
-    method public int describeContents();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator CREATOR;
-  }
-
-  public static final class MediaSession.Track implements android.os.Parcelable {
+  public static final class MediaSession.Item implements android.os.Parcelable {
     method public int describeContents();
     method public android.os.Bundle getExtras();
     method public long getId();
@@ -16808,20 +16736,25 @@
     field public static final int UNKNOWN_ID = -1; // 0xffffffff
   }
 
-  public static final class MediaSession.Track.Builder {
-    ctor public MediaSession.Track.Builder(android.media.MediaMetadata, long, android.net.Uri);
-    method public android.media.session.MediaSession.Track build();
-    method public android.media.session.MediaSession.Track.Builder setExtras(android.os.Bundle);
+  public static final class MediaSession.Item.Builder {
+    ctor public MediaSession.Item.Builder(android.media.MediaMetadata, long, android.net.Uri);
+    method public android.media.session.MediaSession.Item build();
+    method public android.media.session.MediaSession.Item.Builder setExtras(android.os.Bundle);
+  }
+
+  public static final class MediaSession.Token implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
   }
 
   public final class MediaSessionManager {
-    method public void addActiveSessionsListener(android.media.session.MediaSessionManager.SessionListener, android.content.ComponentName);
+    method public void addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName);
     method public java.util.List<android.media.session.MediaController> getActiveSessions(android.content.ComponentName);
-    method public void removeActiveSessionsListener(android.media.session.MediaSessionManager.SessionListener);
+    method public void removeOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener);
   }
 
-  public static abstract class MediaSessionManager.SessionListener {
-    ctor public MediaSessionManager.SessionListener(android.content.Context);
+  public static abstract interface MediaSessionManager.OnActiveSessionsChangedListener {
     method public abstract void onActiveSessionsChanged(java.util.List<android.media.session.MediaController>);
   }
 
@@ -16845,9 +16778,9 @@
     field public static final long ACTION_REWIND = 8L; // 0x8L
     field public static final long ACTION_SEEK_TO = 256L; // 0x100L
     field public static final long ACTION_SET_RATING = 128L; // 0x80L
+    field public static final long ACTION_SKIP_TO_ITEM = 4096L; // 0x1000L
     field public static final long ACTION_SKIP_TO_NEXT = 32L; // 0x20L
     field public static final long ACTION_SKIP_TO_PREVIOUS = 16L; // 0x10L
-    field public static final long ACTION_SKIP_TO_TRACK = 4096L; // 0x1000L
     field public static final long ACTION_STOP = 1L; // 0x1L
     field public static final android.os.Parcelable.Creator CREATOR;
     field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL
@@ -16871,7 +16804,7 @@
     method public android.media.session.PlaybackState.Builder addCustomAction(android.media.session.PlaybackState.CustomAction);
     method public android.media.session.PlaybackState build();
     method public android.media.session.PlaybackState.Builder setActions(long);
-    method public android.media.session.PlaybackState.Builder setActiveTrack(long);
+    method public android.media.session.PlaybackState.Builder setActiveItem(long);
     method public android.media.session.PlaybackState.Builder setBufferPosition(long);
     method public android.media.session.PlaybackState.Builder setErrorMessage(java.lang.CharSequence);
     method public android.media.session.PlaybackState.Builder setState(int, long, float, long);
@@ -17139,6 +17072,7 @@
     method public final java.lang.String getId();
     method public final java.lang.String getLanguage();
     method public final int getType();
+    method public final float getVideoFrameRate();
     method public final int getVideoHeight();
     method public final int getVideoWidth();
     method public void writeToParcel(android.os.Parcel, int);
@@ -17155,6 +17089,7 @@
     method public final android.media.tv.TvTrackInfo.Builder setAudioSampleRate(int);
     method public final android.media.tv.TvTrackInfo.Builder setExtra(android.os.Bundle);
     method public final android.media.tv.TvTrackInfo.Builder setLanguage(java.lang.String);
+    method public final android.media.tv.TvTrackInfo.Builder setVideoFrameRate(float);
     method public final android.media.tv.TvTrackInfo.Builder setVideoHeight(int);
     method public final android.media.tv.TvTrackInfo.Builder setVideoWidth(int);
   }
@@ -17175,8 +17110,6 @@
     method public void setStreamVolume(float);
     method public void setTvInputListener(android.media.tv.TvView.TvInputListener);
     method public void tune(java.lang.String, android.net.Uri);
-    field public static final int ERROR_INPUT_DISCONNECTED = 1; // 0x1
-    field public static final int ERROR_INPUT_NOT_CONNECTED = 0; // 0x0
   }
 
   public static abstract interface TvView.OnUnhandledInputEventListener {
@@ -17186,9 +17119,10 @@
   public static abstract class TvView.TvInputListener {
     ctor public TvView.TvInputListener();
     method public void onChannelRetuned(java.lang.String, android.net.Uri);
+    method public void onConnectionFailed(java.lang.String);
     method public void onContentAllowed(java.lang.String);
     method public void onContentBlocked(java.lang.String, android.media.tv.TvContentRating);
-    method public void onError(java.lang.String, int);
+    method public void onDisconnected(java.lang.String);
     method public void onTrackSelected(java.lang.String, int, java.lang.String);
     method public void onTracksChanged(java.lang.String, java.util.List<android.media.tv.TvTrackInfo>);
     method public void onVideoAvailable(java.lang.String);
@@ -28897,12 +28831,10 @@
     method public final void setAudioModeIsVoip(boolean);
     method public final void setCallCapabilities(int);
     method public final void setCallerDisplayName(java.lang.String, int);
-    method public final void setCanceled();
     method public final void setConferenceableConnections(java.util.List<android.telecomm.Connection>);
     method public final void setConnectionService(android.telecomm.ConnectionService);
     method public final void setDialing();
     method public final void setDisconnected(int, java.lang.String);
-    method public final void setFailed(int, java.lang.String);
     method public final void setHandle(android.net.Uri, int);
     method public final void setInitialized();
     method public final void setInitializing();
@@ -28916,10 +28848,8 @@
     method public final void startActivityFromInCall(android.app.PendingIntent);
     method public static java.lang.String stateToString(int);
     field public static final int STATE_ACTIVE = 4; // 0x4
-    field public static final int STATE_CANCELED = 8; // 0x8
     field public static final int STATE_DIALING = 3; // 0x3
     field public static final int STATE_DISCONNECTED = 6; // 0x6
-    field public static final int STATE_FAILED = 7; // 0x7
     field public static final int STATE_HOLDING = 5; // 0x5
     field public static final int STATE_INITIALIZING = 0; // 0x0
     field public static final int STATE_NEW = 1; // 0x1
@@ -29709,6 +29639,7 @@
     method public int hasCarrierPrivileges();
     method public boolean hasIccCard();
     method public boolean iccCloseLogicalChannel(int);
+    method public byte[] iccExchangeSimIO(int, int, int, int, int, java.lang.String);
     method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String);
     method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, java.lang.String);
     method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
@@ -32310,6 +32241,8 @@
     method public void captureEndValues(android.transition.TransitionValues);
     method public void captureStartValues(android.transition.TransitionValues);
     method public int getOrdering();
+    method public android.transition.Transition getTransitionAt(int);
+    method public int getTransitionCount();
     method public android.transition.TransitionSet removeTransition(android.transition.Transition);
     method public android.transition.TransitionSet setOrdering(int);
     field public static final int ORDERING_SEQUENTIAL = 1; // 0x1
diff --git a/cmds/appops/Android.mk b/cmds/appops/Android.mk
new file mode 100644
index 0000000..1e15204
--- /dev/null
+++ b/cmds/appops/Android.mk
@@ -0,0 +1,16 @@
+# Copyright 2014 The Android Open Source Project
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_MODULE := appops
+include $(BUILD_JAVA_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := appops
+LOCAL_SRC_FILES := appops
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_PREBUILT)
+
diff --git a/cmds/appops/MODULE_LICENSE_APACHE2 b/cmds/appops/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cmds/appops/MODULE_LICENSE_APACHE2
diff --git a/cmds/appops/NOTICE b/cmds/appops/NOTICE
new file mode 100644
index 0000000..06a9081
--- /dev/null
+++ b/cmds/appops/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2005-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.
+
+   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.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/cmds/appops/appops b/cmds/appops/appops
new file mode 100755
index 0000000..407e551
--- /dev/null
+++ b/cmds/appops/appops
@@ -0,0 +1,5 @@
+# Script to start "appwidget" on the device, which has a very rudimentary shell.
+base=/system
+export CLASSPATH=$base/framework/appops.jar
+exec app_process $base/bin com.android.commands.appops.AppOpsCommand "$@"
+
diff --git a/cmds/appops/src/com/android/commands/appops/AppOpsCommand.java b/cmds/appops/src/com/android/commands/appops/AppOpsCommand.java
new file mode 100644
index 0000000..c414f58
--- /dev/null
+++ b/cmds/appops/src/com/android/commands/appops/AppOpsCommand.java
@@ -0,0 +1,137 @@
+/*
+** 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 com.android.commands.appops;
+
+import android.app.ActivityManager;
+import android.app.ActivityThread;
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.IPackageManager;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+
+import com.android.internal.app.IAppOpsService;
+import com.android.internal.os.BaseCommand;
+
+import java.io.PrintStream;
+
+/**
+ * This class is a command line utility for manipulating AppOps permissions.
+ */
+public class AppOpsCommand extends BaseCommand {
+
+    public static void main(String[] args) {
+        new AppOpsCommand().run(args);
+    }
+
+    @Override
+    public void onShowUsage(PrintStream out) {
+        out.println("usage: adb shell appops set <PACKAGE> <OP> "
+                + "<allow|ignore|deny|default> [--user <USER_ID>]\n"
+                + "  <PACKAGE> an Android package name.\n"
+                + "  <OP>      an AppOps operation.\n"
+                + "  <USER_ID> the user id under which the package is installed. If --user is not\n"
+                + "            specified, the current user is assumed.\n");
+    }
+
+    private static final String COMMAND_SET = "set";
+
+    @Override
+    public void onRun() throws Exception {
+        String command = nextArgRequired();
+        switch (command) {
+            case COMMAND_SET:
+                runSet();
+                break;
+
+            default:
+                throw new IllegalArgumentException("Unknown command '" + command + "'.");
+        }
+    }
+
+    private static final String ARGUMENT_USER = "--user";
+
+    // Modes
+    private static final String MODE_ALLOW = "allow";
+    private static final String MODE_DENY = "deny";
+    private static final String MODE_IGNORE = "ignore";
+    private static final String MODE_DEFAULT = "default";
+
+    private void runSet() throws Exception {
+        String packageName = null;
+        String op = null;
+        String mode = null;
+        int userId = UserHandle.USER_CURRENT;
+        for (String argument; (argument = nextArg()) != null;) {
+            if (ARGUMENT_USER.equals(argument)) {
+                userId = Integer.parseInt(nextArgRequired());
+            } else {
+                if (packageName == null) {
+                    packageName = argument;
+                } else if (op == null) {
+                    op = argument;
+                } else if (mode == null) {
+                    mode = argument;
+                } else {
+                    throw new IllegalArgumentException("Unsupported argument: " + argument);
+                }
+            }
+        }
+
+        if (packageName == null) {
+            throw new IllegalArgumentException("Package name not specified.");
+        } else if (op == null) {
+            throw new IllegalArgumentException("Operation not specified.");
+        } else if (mode == null) {
+            throw new IllegalArgumentException("Mode not specified.");
+        }
+
+        final int opInt = AppOpsManager.strOpToOp(op);
+        final int modeInt;
+        switch (mode) {
+            case MODE_ALLOW:
+                modeInt = AppOpsManager.MODE_ALLOWED;
+                break;
+            case MODE_DENY:
+                modeInt = AppOpsManager.MODE_ERRORED;
+                break;
+            case MODE_IGNORE:
+                modeInt = AppOpsManager.MODE_IGNORED;
+                break;
+            case MODE_DEFAULT:
+                modeInt = AppOpsManager.MODE_DEFAULT;
+                break;
+            default:
+                throw new IllegalArgumentException("Mode is invalid.");
+        }
+
+        // Parsing complete, let's execute the command.
+
+        if (userId == UserHandle.USER_CURRENT) {
+            userId = ActivityManager.getCurrentUser();
+        }
+
+        final IPackageManager pm = ActivityThread.getPackageManager();
+        final IAppOpsService appOpsService = IAppOpsService.Stub.asInterface(
+                ServiceManager.getService(Context.APP_OPS_SERVICE));
+        final int uid = pm.getPackageUid(packageName, userId);
+        if (uid < 0) {
+            throw new Exception("No UID for " + packageName + " for user " + userId);
+        }
+        appOpsService.setMode(opInt, uid, packageName, modeInt);
+    }
+}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index d9ea671..2136209 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3494,6 +3494,20 @@
         synchronized (mResourcesManager) {
             mCoreSettings = coreSettings;
         }
+        onCoreSettingsChange();
+    }
+
+    private void onCoreSettingsChange() {
+        boolean debugViewAttributes =
+                mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0;
+        if (debugViewAttributes != View.mDebugViewAttributes) {
+            View.mDebugViewAttributes = debugViewAttributes;
+
+            // request all activities to relaunch for the changes to take place
+            for (Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) {
+                requestRelaunchActivity(entry.getKey(), null, null, 0, false, null, false);
+            }
+        }
     }
 
     private void handleUpdatePackageCompatibilityInfo(UpdateCompatibilityData data) {
@@ -4324,6 +4338,9 @@
         final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24));
         DateFormat.set24HourTimePref(is24Hr);
 
+        View.mDebugViewAttributes =
+                mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0;
+
         /**
          * For system applications on userdebug/eng builds, log stack
          * traces of disk and network access to dropbox for analysis.
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index a6b3608..0d2ad08 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1046,7 +1046,10 @@
         return packageName + " from uid " + uid + " not allowed to perform " + sOpNames[op];
     }
 
-    private int strOpToOp(String op) {
+    /**
+     * {@hide}
+     */
+    public static int strOpToOp(String op) {
         Integer val = sOpStrToOp.get(op);
         if (val == null) {
             throw new IllegalArgumentException("Unknown operation string: " + op);
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 0ca800f..b13792b 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1612,7 +1612,7 @@
      * @see #requestSync(android.accounts.Account, String, android.os.Bundle)
      */
     public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
-        notifyChange(uri, observer, syncToNetwork, UserHandle.getCallingUserId());
+        notifyChange(uri, observer, syncToNetwork, UserHandle.myUserId());
     }
 
     /**
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 5f046c5..a13a928 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -45,6 +45,7 @@
 import android.util.AttributeSet;
 import android.view.DisplayAdjustments;
 import android.view.Display;
+import android.view.ViewDebug;
 import android.view.WindowManager;
 
 import java.io.File;
@@ -420,6 +421,7 @@
     /**
      * Return the Theme object associated with this Context.
      */
+    @ViewDebug.ExportedProperty(deepExport = true)
     public abstract Resources.Theme getTheme();
 
     /**
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 268919c..f9370b3 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -64,7 +64,7 @@
     /**
      * Callbacks for package changes to this and related managed profiles.
      */
-    public static abstract class OnAppsChangedCallback {
+    public static abstract class Callback {
         /**
          * Indicates that a package was removed from the specified profile.
          *
@@ -207,17 +207,17 @@
     }
 
     /**
-     * Starts an activity in the specified profile.
+     * Starts a Main activity in the specified profile.
      *
      * @param component The ComponentName of the activity to launch
      * @param user The UserHandle of the profile
      * @param sourceBounds The Rect containing the source bounds of the clicked icon
      * @param opts Options to pass to startActivity
      */
-    public void startActivityForProfile(ComponentName component, UserHandle user, Rect sourceBounds,
+    public void startMainActivity(ComponentName component, UserHandle user, Rect sourceBounds,
             Bundle opts) {
         if (DEBUG) {
-            Log.i(TAG, "StartActivityForProfile " + component + " " + user.getIdentifier());
+            Log.i(TAG, "StartMainActivity " + component + " " + user.getIdentifier());
         }
         try {
             mService.startActivityAsUser(component, sourceBounds, opts, user);
@@ -235,7 +235,7 @@
      * @param sourceBounds The Rect containing the source bounds of the clicked icon
      * @param opts Options to pass to startActivity
      */
-    public void showAppDetailsForProfile(ComponentName component, UserHandle user,
+    public void startAppDetailsActivity(ComponentName component, UserHandle user,
             Rect sourceBounds, Bundle opts) {
         try {
             mService.showAppDetailsAsUser(component, sourceBounds, opts, user);
@@ -252,7 +252,7 @@
      *
      * @return true if the package exists and is enabled.
      */
-    public boolean isPackageEnabledForProfile(String packageName, UserHandle user) {
+    public boolean isPackageEnabled(String packageName, UserHandle user) {
         try {
             return mService.isPackageEnabled(packageName, user);
         } catch (RemoteException re) {
@@ -268,7 +268,7 @@
      *
      * @return true if the activity exists and is enabled.
      */
-    public boolean isActivityEnabledForProfile(ComponentName component, UserHandle user) {
+    public boolean isActivityEnabled(ComponentName component, UserHandle user) {
         try {
             return mService.isActivityEnabled(component, user);
         } catch (RemoteException re) {
@@ -282,8 +282,8 @@
      *
      * @param callback The callback to add.
      */
-    public void addOnAppsChangedCallback(OnAppsChangedCallback callback) {
-        addOnAppsChangedCallback(callback, null);
+    public void addCallback(Callback callback) {
+        addCallback(callback, null);
     }
 
     /**
@@ -292,7 +292,7 @@
      * @param callback The callback to add.
      * @param handler that should be used to post callbacks on, may be null.
      */
-    public void addOnAppsChangedCallback(OnAppsChangedCallback callback, Handler handler) {
+    public void addCallback(Callback callback, Handler handler) {
         synchronized (this) {
             if (callback != null && !mCallbacks.contains(callback)) {
                 boolean addedFirstCallback = mCallbacks.size() == 0;
@@ -311,9 +311,9 @@
      * Removes a callback that was previously added.
      *
      * @param callback The callback to remove.
-     * @see #addOnAppsChangedListener(OnAppsChangedCallback)
+     * @see #addCallback(Callback)
      */
-    public void removeOnAppsChangedCallback(OnAppsChangedCallback callback) {
+    public void removeCallback(Callback callback) {
         synchronized (this) {
             removeCallbackLocked(callback);
             if (mCallbacks.size() == 0) {
@@ -325,7 +325,7 @@
         }
     }
 
-    private void removeCallbackLocked(OnAppsChangedCallback callback) {
+    private void removeCallbackLocked(Callback callback) {
         if (callback == null) {
             throw new IllegalArgumentException("Callback cannot be null");
         }
@@ -338,7 +338,7 @@
         }
     }
 
-    private void addCallbackLocked(OnAppsChangedCallback callback, Handler handler) {
+    private void addCallbackLocked(Callback callback, Handler handler) {
         // Remove if already present.
         removeCallbackLocked(callback);
         if (handler == null) {
@@ -421,7 +421,7 @@
         private static final int MSG_AVAILABLE = 4;
         private static final int MSG_UNAVAILABLE = 5;
 
-        private OnAppsChangedCallback mCallback;
+        private LauncherApps.Callback mCallback;
 
         private static class CallbackInfo {
             String[] packageNames;
@@ -430,7 +430,7 @@
             UserHandle user;
         }
 
-        public CallbackMessageHandler(Looper looper, OnAppsChangedCallback callback) {
+        public CallbackMessageHandler(Looper looper, LauncherApps.Callback callback) {
             super(looper, null, true);
             mCallback = callback;
         }
@@ -499,4 +499,45 @@
             obtainMessage(MSG_UNAVAILABLE, info).sendToTarget();
         }
     }
+
+    /** Remove after unbundled apps have migrated STOP SHIP */
+    public static abstract class OnAppsChangedCallback extends Callback {
+    }
+
+    /** Remove after unbundled apps have migrated STOP SHIP */
+    public void addOnAppsChangedCallback(OnAppsChangedCallback callback) {
+        addCallback(callback, null);
+    }
+
+    /** Remove after unbundled apps have migrated STOP SHIP */
+    public void addOnAppsChangedCallback(OnAppsChangedCallback callback, Handler handler) {
+        addCallback(callback, handler);
+    }
+
+    /** Remove after unbundled apps have migrated STOP SHIP */
+    public void removeOnAppsChangedCallback(OnAppsChangedCallback callback) {
+        removeCallback(callback);
+    }
+
+    /** Remove after unbundled apps have migrated STOP SHIP */
+    public void startActivityForProfile(ComponentName component, UserHandle user, Rect sourceBounds,
+            Bundle opts) {
+        startMainActivity(component, user, sourceBounds, opts);
+    }
+
+    /** Remove after unbundled apps have migrated STOP SHIP */
+    public void showAppDetailsForProfile(ComponentName component, UserHandle user,
+            Rect sourceBounds, Bundle opts) {
+        startAppDetailsActivity(component, user, sourceBounds, opts);
+    }
+
+    /** Remove after unbundled apps have migrated STOP SHIP */
+    public boolean isPackageEnabledForProfile(String packageName, UserHandle user) {
+        return isPackageEnabled(packageName, user);
+    }
+
+    /** Remove after unbundled apps have migrated STOP SHIP */
+    public boolean isActivityEnabledForProfile(ComponentName component, UserHandle user) {
+        return isActivityEnabled(component, user);
+    }
 }
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index fff21aa..31813c10 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -16,6 +16,7 @@
 
 package android.content.res;
 
+import android.view.ViewDebug;
 import com.android.internal.util.XmlUtils;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -1638,12 +1639,41 @@
         /*package*/ String getKey() {
             return mKey;
         }
+
+        private String getResourceNameFromHexString(String hexString) {
+            return getResourceName(Integer.parseInt(hexString, 16));
+        }
+
+        /**
+         * Parses {@link #mKey} and returns a String array that holds pairs of adjacent Theme data:
+         * resource name followed by whether or not it was forced, as specified by
+         * {@link #applyStyle(int, boolean)}.
+         *
+         * @hide
+         */
+        @ViewDebug.ExportedProperty(category = "theme", hasAdjacentMapping = true)
+        public String[] getTheme() {
+            String[] themeData = mKey.split(" ");
+            String[] themes = new String[themeData.length * 2];
+            String theme;
+            boolean forced;
+
+            for (int i = 0, j = themeData.length - 1; i < themes.length; i += 2, --j) {
+                theme = themeData[j];
+                forced = theme.endsWith("!");
+                themes[i] = forced ?
+                        getResourceNameFromHexString(theme.substring(0, theme.length() - 1)) :
+                        getResourceNameFromHexString(theme);
+                themes[i + 1] = forced ? "forced" : "not forced";
+            }
+            return themes;
+        }
     }
 
     /**
      * Generate a new Theme object for this set of Resources.  It initially
      * starts out empty.
-     * 
+     *
      * @return Theme The newly created Theme container.
      */
     public final Theme newTheme() {
@@ -1653,7 +1683,7 @@
     /**
      * Retrieve a set of basic attribute values from an AttributeSet, not
      * performing styling of them using a theme and/or style resources.
-     * 
+     *
      * @param set The current attribute values to retrieve.
      * @param attrs The specific attributes to be retrieved.
      * @return Returns a TypedArray holding an array of the attribute values.
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index eadfa73..310ab76 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -1558,6 +1558,26 @@
         return _enableShutterSound(enabled);
     }
 
+    /**
+     * Disable the shutter sound unconditionally.
+     *
+     * <p>
+     * This is only guaranteed to work for legacy cameras
+     * (i.e. initialized with {@link #cameraInitUnspecified}). Trying to call this on
+     * a regular camera will force a conditional check in the camera service.
+     * </p>
+     *
+     * @return {@code true} if the shutter sound state was successfully
+     *         changed. {@code false} if the shutter sound state could not be
+     *         changed. {@code true} is also returned if shutter sound playback
+     *         is already set to the requested state.
+     *
+     * @hide
+     */
+    public final boolean disableShutterSound() {
+        return _enableShutterSound(/*enabled*/false);
+    }
+
     private native final boolean _enableShutterSound(boolean enabled);
 
     /**
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
index c68d8c3..5cbf109 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
@@ -56,6 +56,7 @@
  * Keep up to date with ICameraDeviceUser.aidl.
  * </p>
  */
+@SuppressWarnings("deprecation")
 public class CameraDeviceUserShim implements ICameraDeviceUser {
     private static final String TAG = "CameraDeviceUserShim";
 
@@ -259,6 +260,7 @@
                 super(l);
             }
 
+            @Override
             public void handleMessage(Message msg) {
                 try {
                     switch (msg.what) {
@@ -320,6 +322,9 @@
         // Check errors old HAL initialization
         CameraBinderDecorator.throwOnError(initErrors);
 
+        // Disable shutter sounds (this will work unconditionally) for api2 clients
+        legacyCamera.disableShutterSound();
+
         CameraInfo info = new CameraInfo();
         Camera.getCameraInfo(cameraId, info);
 
diff --git a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
index fbe26e5..ee0ca9c 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
@@ -1207,6 +1207,9 @@
             m.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, bestRange);
         }
 
+        // control.sceneMode -- DISABLED is always available
+        m.set(CaptureRequest.CONTROL_SCENE_MODE, CONTROL_SCENE_MODE_DISABLED);
+
         /*
          * statistics.*
          */
diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
index 2e6b9ae..c0b7967 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -339,6 +339,11 @@
      * @see #isOutputSupportedFor(Class)
      */
     public <T> Size[] getOutputSizes(Class<T> klass) {
+        // Image reader is "supported", but never for implementation-defined formats; return empty
+        if (android.media.ImageReader.class.isAssignableFrom(klass)) {
+            return new Size[0];
+        }
+
         if (isOutputSupportedFor(klass) == false) {
             return null;
         }
diff --git a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
index 97da3a2..d8da80e 100644
--- a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
+++ b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
@@ -230,7 +230,7 @@
         mDeviceType = DEVICE_RESERVED;
         mVendorId = 0;
         mDevicePowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN;
-        mDisplayName = "MHL";
+        mDisplayName = "Mobile";
 
         mDeviceId = adopterId;
         mAdopterId = deviceId;
diff --git a/core/java/android/hardware/location/GeofenceHardware.java b/core/java/android/hardware/location/GeofenceHardware.java
index 2d82cba..7dd105a 100644
--- a/core/java/android/hardware/location/GeofenceHardware.java
+++ b/core/java/android/hardware/location/GeofenceHardware.java
@@ -15,6 +15,7 @@
  */
 package android.hardware.location;
 
+import android.annotation.SystemApi;
 import android.location.Location;
 import android.os.Build;
 import android.os.RemoteException;
@@ -43,7 +44,10 @@
  * an appropriate transition would be triggered. The "reasonably confident" parameter
  * depends on the hardware system and the positioning algorithms used.
  * For instance, {@link #MONITORING_TYPE_GPS_HARDWARE} uses 95% as a confidence level.
+ *
+ * @hide
  */
+@SystemApi
 public final class GeofenceHardware {
     private IGeofenceHardware mService;
 
@@ -162,9 +166,7 @@
     private HashMap<GeofenceHardwareMonitorCallback, GeofenceHardwareMonitorCallbackWrapper>
             mMonitorCallbacks = new HashMap<GeofenceHardwareMonitorCallback,
                     GeofenceHardwareMonitorCallbackWrapper>();
-    /**
-     * @hide
-     */
+
     public GeofenceHardware(IGeofenceHardware service) {
         mService = service;
     }
diff --git a/core/java/android/hardware/location/GeofenceHardwareCallback.java b/core/java/android/hardware/location/GeofenceHardwareCallback.java
index 6cad3da..a2a7ed0 100644
--- a/core/java/android/hardware/location/GeofenceHardwareCallback.java
+++ b/core/java/android/hardware/location/GeofenceHardwareCallback.java
@@ -16,11 +16,15 @@
 
 package android.hardware.location;
 
+import android.annotation.SystemApi;
 import android.location.Location;
 
 /**
  * The callback class associated with the APIs in {@link GeofenceHardware}
+ *
+ * @hide
  */
+@SystemApi
 public abstract class GeofenceHardwareCallback {
     /**
      * The callback called when there is a transition to report for the specific
diff --git a/core/java/android/hardware/location/GeofenceHardwareMonitorCallback.java b/core/java/android/hardware/location/GeofenceHardwareMonitorCallback.java
index f927027..d7daa10 100644
--- a/core/java/android/hardware/location/GeofenceHardwareMonitorCallback.java
+++ b/core/java/android/hardware/location/GeofenceHardwareMonitorCallback.java
@@ -16,12 +16,16 @@
 
 package android.hardware.location;
 
+import android.annotation.SystemApi;
 import android.location.Location;
 
 /**
  * The callback class associated with the status change of hardware monitors
  * in {@link GeofenceHardware}
+ *
+ * @hide
  */
+@SystemApi
 public abstract class GeofenceHardwareMonitorCallback {
     /**
      * The callback called when the state of a monitoring system changes.
diff --git a/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.java b/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.java
index 9c460d2..7079237 100644
--- a/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.java
+++ b/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.java
@@ -16,13 +16,17 @@
 
 package android.hardware.location;
 
+import android.annotation.SystemApi;
 import android.location.Location;
 import android.os.Parcel;
 import android.os.Parcelable;
 
 /**
  * A class that represents an event for each change in the state of a monitoring system.
+ *
+ * @hide
  */
+@SystemApi
 public class GeofenceHardwareMonitorEvent implements Parcelable {
     private final int mMonitoringType;
     private final int mMonitoringStatus;
diff --git a/core/java/android/hardware/location/GeofenceHardwareRequest.java b/core/java/android/hardware/location/GeofenceHardwareRequest.java
index 887c4ad..68545a8 100644
--- a/core/java/android/hardware/location/GeofenceHardwareRequest.java
+++ b/core/java/android/hardware/location/GeofenceHardwareRequest.java
@@ -16,12 +16,16 @@
 
 package android.hardware.location;
 
+import android.annotation.SystemApi;
+
 /**
  * This class represents the characteristics of the geofence.
  *
  * <p> Use this in conjunction with {@link GeofenceHardware} APIs.
+ *
+ * @hide
  */
-
+@SystemApi
 public final class GeofenceHardwareRequest {
     static final int GEOFENCE_TYPE_CIRCLE = 0;
     private int mType;
diff --git a/core/java/android/net/DhcpResults.java b/core/java/android/net/DhcpResults.java
index 49a307e..71df60a 100644
--- a/core/java/android/net/DhcpResults.java
+++ b/core/java/android/net/DhcpResults.java
@@ -16,13 +16,15 @@
 
 package android.net;
 
+import android.net.NetworkUtils;
 import android.os.Parcelable;
 import android.os.Parcel;
 import android.text.TextUtils;
 import android.util.Log;
 
 import java.net.InetAddress;
-import java.net.UnknownHostException;
+import java.net.Inet4Address;
+import java.util.Objects;
 
 /**
  * A simple object for retrieving the results of a DHCP request.
@@ -30,38 +32,34 @@
  * TODO - remove when DhcpInfo is deprecated.  Move the remaining api to LinkProperties.
  * @hide
  */
-public class DhcpResults implements Parcelable {
+public class DhcpResults extends StaticIpConfiguration {
     private static final String TAG = "DhcpResults";
 
-    public final LinkProperties linkProperties;
-
     public InetAddress serverAddress;
 
-    /**
-     * Vendor specific information (from RFC 2132).
-     */
+    /** Vendor specific information (from RFC 2132). */
     public String vendorInfo;
 
     public int leaseDuration;
 
     public DhcpResults() {
-        linkProperties = new LinkProperties();
+        super();
+    }
+
+    public DhcpResults(StaticIpConfiguration source) {
+        super(source);
     }
 
     /** copy constructor */
     public DhcpResults(DhcpResults source) {
-        if (source != null) {
-            linkProperties = new LinkProperties(source.linkProperties);
-            serverAddress = source.serverAddress;
-            leaseDuration = source.leaseDuration;
-            vendorInfo = source.vendorInfo;
-        } else {
-            linkProperties = new LinkProperties();
-        }
-    }
+        super(source);
 
-    public DhcpResults(LinkProperties lp) {
-        linkProperties = new LinkProperties(lp);
+        if (source != null) {
+            // All these are immutable, so no need to make copies.
+            serverAddress = source.serverAddress;
+            vendorInfo = source.vendorInfo;
+            leaseDuration = source.leaseDuration;
+        }
     }
 
     /**
@@ -70,14 +68,10 @@
      * being empty.
      */
     public void updateFromDhcpRequest(DhcpResults orig) {
-        if (orig == null || orig.linkProperties == null) return;
-        if (linkProperties.getRoutes().size() == 0) {
-            for (RouteInfo r : orig.linkProperties.getRoutes()) linkProperties.addRoute(r);
-        }
-        if (linkProperties.getDnsServers().size() == 0) {
-            for (InetAddress d : orig.linkProperties.getDnsServers()) {
-                linkProperties.addDnsServer(d);
-            }
+        if (orig == null) return;
+        if (gateway == null) gateway = orig.gateway;
+        if (dnsServers.size() == 0) {
+            dnsServers.addAll(orig.dnsServers);
         }
     }
 
@@ -94,15 +88,14 @@
     }
 
     public void clear() {
-        linkProperties.clear();
-        serverAddress = null;
+        super.clear();
         vendorInfo = null;
         leaseDuration = 0;
     }
 
     @Override
     public String toString() {
-        StringBuffer str = new StringBuffer(linkProperties.toString());
+        StringBuffer str = new StringBuffer(super.toString());
 
         str.append(" DHCP server ").append(serverAddress);
         str.append(" Vendor info ").append(vendorInfo);
@@ -119,58 +112,19 @@
 
         DhcpResults target = (DhcpResults)obj;
 
-        if (linkProperties == null) {
-            if (target.linkProperties != null) return false;
-        } else if (!linkProperties.equals(target.linkProperties)) return false;
-        if (serverAddress == null) {
-            if (target.serverAddress != null) return false;
-        } else if (!serverAddress.equals(target.serverAddress)) return false;
-        if (vendorInfo == null) {
-            if (target.vendorInfo != null) return false;
-        } else if (!vendorInfo.equals(target.vendorInfo)) return false;
-        if (leaseDuration != target.leaseDuration) return false;
-
-        return true;
-    }
-
-    /** Implement the Parcelable interface */
-    public int describeContents() {
-        return 0;
-    }
-
-    /** Implement the Parcelable interface */
-    public void writeToParcel(Parcel dest, int flags) {
-        linkProperties.writeToParcel(dest, flags);
-
-        dest.writeInt(leaseDuration);
-
-        if (serverAddress != null) {
-            dest.writeByte((byte)1);
-            dest.writeByteArray(serverAddress.getAddress());
-        } else {
-            dest.writeByte((byte)0);
-        }
-
-        dest.writeString(vendorInfo);
+        return super.equals((StaticIpConfiguration) obj) &&
+                Objects.equals(serverAddress, target.serverAddress) &&
+                Objects.equals(vendorInfo, target.vendorInfo) &&
+                leaseDuration == target.leaseDuration;
     }
 
     /** Implement the Parcelable interface */
     public static final Creator<DhcpResults> CREATOR =
         new Creator<DhcpResults>() {
             public DhcpResults createFromParcel(Parcel in) {
-                DhcpResults prop = new DhcpResults((LinkProperties)in.readParcelable(null));
-
-                prop.leaseDuration = in.readInt();
-
-                if (in.readByte() == 1) {
-                    try {
-                        prop.serverAddress = InetAddress.getByAddress(in.createByteArray());
-                    } catch (UnknownHostException e) {}
-                }
-
-                prop.vendorInfo = in.readString();
-
-                return prop;
+                DhcpResults dhcpResults = new DhcpResults();
+                readFromParcel(dhcpResults, in);
+                return dhcpResults;
             }
 
             public DhcpResults[] newArray(int size) {
@@ -178,33 +132,39 @@
             }
         };
 
-    // Utils for jni population - false on success
-    public void setInterfaceName(String interfaceName) {
-        linkProperties.setInterfaceName(interfaceName);
+    /** Implement the Parcelable interface */
+    public void writeToParcel(Parcel dest, int flags) {
+        super.writeToParcel(dest, flags);
+        dest.writeInt(leaseDuration);
+        NetworkUtils.parcelInetAddress(dest, serverAddress, flags);
+        dest.writeString(vendorInfo);
     }
 
-    public boolean addLinkAddress(String addrString, int prefixLength) {
-        InetAddress addr;
+    private static void readFromParcel(DhcpResults dhcpResults, Parcel in) {
+        StaticIpConfiguration.readFromParcel(dhcpResults, in);
+        dhcpResults.leaseDuration = in.readInt();
+        dhcpResults.serverAddress = NetworkUtils.unparcelInetAddress(in);
+        dhcpResults.vendorInfo = in.readString();
+    }
+
+    // Utils for jni population - false on success
+    // Not part of the superclass because they're only used by the JNI iterface to the DHCP daemon.
+    public boolean setIpAddress(String addrString, int prefixLength) {
         try {
-            addr = NetworkUtils.numericToInetAddress(addrString);
-        } catch (IllegalArgumentException e) {
-            Log.e(TAG, "addLinkAddress failed with addrString " + addrString);
+            Inet4Address addr = (Inet4Address) NetworkUtils.numericToInetAddress(addrString);
+            ipAddress = new LinkAddress(addr, prefixLength);
+        } catch (IllegalArgumentException|ClassCastException e) {
+            Log.e(TAG, "setIpAddress failed with addrString " + addrString + "/" + prefixLength);
             return true;
         }
-
-        LinkAddress linkAddress = new LinkAddress(addr, prefixLength);
-        linkProperties.addLinkAddress(linkAddress);
-
-        RouteInfo routeInfo = new RouteInfo(linkAddress);
-        linkProperties.addRoute(routeInfo);
         return false;
     }
 
-    public boolean addGateway(String addrString) {
+    public boolean setGateway(String addrString) {
         try {
-            linkProperties.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(addrString)));
+            gateway = NetworkUtils.numericToInetAddress(addrString);
         } catch (IllegalArgumentException e) {
-            Log.e(TAG, "addGateway failed with addrString " + addrString);
+            Log.e(TAG, "setGateway failed with addrString " + addrString);
             return true;
         }
         return false;
@@ -213,7 +173,7 @@
     public boolean addDns(String addrString) {
         if (TextUtils.isEmpty(addrString) == false) {
             try {
-                linkProperties.addDnsServer(NetworkUtils.numericToInetAddress(addrString));
+                dnsServers.add(NetworkUtils.numericToInetAddress(addrString));
             } catch (IllegalArgumentException e) {
                 Log.e(TAG, "addDns failed with addrString " + addrString);
                 return true;
@@ -241,6 +201,6 @@
     }
 
     public void setDomains(String domains) {
-        linkProperties.setDomains(domains);
+        domains = domains;
     }
 }
diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
index 608ca28..d965f27 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/core/java/android/net/EthernetManager.java
@@ -21,7 +21,6 @@
 import android.net.IpConfiguration;
 import android.net.IpConfiguration.IpAssignment;
 import android.net.IpConfiguration.ProxySettings;
-import android.net.LinkProperties;
 import android.os.RemoteException;
 
 /**
@@ -52,16 +51,12 @@
      */
     public IpConfiguration getConfiguration() {
         if (mService == null) {
-            return new IpConfiguration(IpAssignment.UNASSIGNED,
-                                       ProxySettings.UNASSIGNED,
-                                       new LinkProperties());
+            return new IpConfiguration();
         }
         try {
             return mService.getConfiguration();
         } catch (RemoteException e) {
-            return new IpConfiguration(IpAssignment.UNASSIGNED,
-                                       ProxySettings.UNASSIGNED,
-                                       new LinkProperties());
+            return new IpConfiguration();
         }
     }
 
diff --git a/core/java/android/net/IpConfiguration.java b/core/java/android/net/IpConfiguration.java
index 4730bab..fe69f296 100644
--- a/core/java/android/net/IpConfiguration.java
+++ b/core/java/android/net/IpConfiguration.java
@@ -16,7 +16,7 @@
 
 package android.net;
 
-import android.net.LinkProperties;
+import android.net.StaticIpConfiguration;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -31,7 +31,7 @@
 
     public enum IpAssignment {
         /* Use statically configured IP settings. Configuration can be accessed
-         * with linkProperties */
+         * with staticIpConfiguration */
         STATIC,
         /* Use dynamically configured IP settigns */
         DHCP,
@@ -42,12 +42,14 @@
 
     public IpAssignment ipAssignment;
 
+    public StaticIpConfiguration staticIpConfiguration;
+
     public enum ProxySettings {
         /* No proxy is to be used. Any existing proxy settings
          * should be cleared. */
         NONE,
         /* Use statically configured proxy. Configuration can be accessed
-         * with linkProperties */
+         * with httpProxy. */
         STATIC,
         /* no proxy details are assigned, this is used to indicate
          * that any existing proxy settings should be retained */
@@ -59,30 +61,69 @@
 
     public ProxySettings proxySettings;
 
-    public LinkProperties linkProperties;
+    public ProxyInfo httpProxy;
 
-    public IpConfiguration(IpConfiguration source) {
-        if (source != null) {
-            ipAssignment = source.ipAssignment;
-            proxySettings = source.proxySettings;
-            linkProperties = new LinkProperties(source.linkProperties);
-        } else {
-            ipAssignment = IpAssignment.UNASSIGNED;
-            proxySettings = ProxySettings.UNASSIGNED;
-            linkProperties = new LinkProperties();
-        }
+    private void init(IpAssignment ipAssignment,
+                      ProxySettings proxySettings,
+                      StaticIpConfiguration staticIpConfiguration,
+                      ProxyInfo httpProxy) {
+        this.ipAssignment = ipAssignment;
+        this.proxySettings = proxySettings;
+        this.staticIpConfiguration = (staticIpConfiguration == null) ?
+                null : new StaticIpConfiguration(staticIpConfiguration);
+        this.httpProxy = (httpProxy == null) ?
+                null : new ProxyInfo(httpProxy);
     }
 
     public IpConfiguration() {
-         this(null);
+        init(IpAssignment.UNASSIGNED, ProxySettings.UNASSIGNED, null, null);
     }
 
     public IpConfiguration(IpAssignment ipAssignment,
                            ProxySettings proxySettings,
-                           LinkProperties linkProperties) {
+                           StaticIpConfiguration staticIpConfiguration,
+                           ProxyInfo httpProxy) {
+        init(ipAssignment, proxySettings, staticIpConfiguration, httpProxy);
+    }
+
+    public IpConfiguration(IpConfiguration source) {
+        this();
+        if (source != null) {
+            init(source.ipAssignment, source.proxySettings,
+                 source.staticIpConfiguration, source.httpProxy);
+        }
+    }
+
+    public IpAssignment getIpAssignment() {
+        return ipAssignment;
+    }
+
+    public void setIpAssignment(IpAssignment ipAssignment) {
         this.ipAssignment = ipAssignment;
+    }
+
+    public StaticIpConfiguration getStaticIpConfiguration() {
+        return staticIpConfiguration;
+    }
+
+    public void setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration) {
+        this.staticIpConfiguration = staticIpConfiguration;
+    }
+
+    public ProxySettings getProxySettings() {
+        return proxySettings;
+    }
+
+    public void setProxySettings(ProxySettings proxySettings) {
         this.proxySettings = proxySettings;
-        this.linkProperties = new LinkProperties(linkProperties);
+    }
+
+    public ProxyInfo getHttpProxy() {
+        return httpProxy;
+    }
+
+    public void setHttpProxy(ProxyInfo httpProxy) {
+        this.httpProxy = httpProxy;
     }
 
     @Override
@@ -90,10 +131,16 @@
         StringBuilder sbuf = new StringBuilder();
         sbuf.append("IP assignment: " + ipAssignment.toString());
         sbuf.append("\n");
+        if (staticIpConfiguration != null) {
+            sbuf.append("Static configuration: " + staticIpConfiguration.toString());
+            sbuf.append("\n");
+        }
         sbuf.append("Proxy settings: " + proxySettings.toString());
         sbuf.append("\n");
-        sbuf.append(linkProperties.toString());
-        sbuf.append("\n");
+        if (httpProxy != null) {
+            sbuf.append("HTTP proxy: " + httpProxy.toString());
+            sbuf.append("\n");
+        }
 
         return sbuf.toString();
     }
@@ -111,14 +158,16 @@
         IpConfiguration other = (IpConfiguration) o;
         return this.ipAssignment == other.ipAssignment &&
                 this.proxySettings == other.proxySettings &&
-                Objects.equals(this.linkProperties, other.linkProperties);
+                Objects.equals(this.staticIpConfiguration, other.staticIpConfiguration) &&
+                Objects.equals(this.httpProxy, other.httpProxy);
     }
 
     @Override
     public int hashCode() {
-        return 13 + (linkProperties != null ? linkProperties.hashCode() : 0) +
+        return 13 + (staticIpConfiguration != null ? staticIpConfiguration.hashCode() : 0) +
                17 * ipAssignment.ordinal() +
-               47 * proxySettings.ordinal();
+               47 * proxySettings.ordinal() +
+               83 * httpProxy.hashCode();
     }
 
     /** Implement the Parcelable interface */
@@ -130,7 +179,8 @@
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeString(ipAssignment.name());
         dest.writeString(proxySettings.name());
-        dest.writeParcelable(linkProperties, flags);
+        dest.writeParcelable(staticIpConfiguration, flags);
+        dest.writeParcelable(httpProxy, flags);
     }
 
     /** Implement the Parcelable interface */
@@ -140,7 +190,8 @@
                 IpConfiguration config = new IpConfiguration();
                 config.ipAssignment = IpAssignment.valueOf(in.readString());
                 config.proxySettings = ProxySettings.valueOf(in.readString());
-                config.linkProperties = in.readParcelable(null);
+                config.staticIpConfiguration = in.readParcelable(null);
+                config.httpProxy = in.readParcelable(null);
                 return config;
             }
 
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 663aa15..54d8676 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -23,6 +23,7 @@
 import java.util.Collection;
 import java.util.Locale;
 
+import android.os.Parcel;
 import android.util.Log;
 import android.util.Pair;
 
@@ -203,6 +204,32 @@
     }
 
     /**
+     * Writes an InetAddress to a parcel. The address may be null. This is likely faster than
+     * calling writeSerializable.
+     */
+    protected static void parcelInetAddress(Parcel parcel, InetAddress address, int flags) {
+        byte[] addressArray = (address != null) ? address.getAddress() : null;
+        parcel.writeByteArray(addressArray);
+    }
+
+    /**
+     * Reads an InetAddress from a parcel. Returns null if the address that was written was null
+     * or if the data is invalid.
+     */
+    protected static InetAddress unparcelInetAddress(Parcel in) {
+        byte[] addressArray = in.createByteArray();
+        if (addressArray == null) {
+            return null;
+        }
+        try {
+            return InetAddress.getByAddress(addressArray);
+        } catch (UnknownHostException e) {
+            return null;
+        }
+    }
+
+
+    /**
      *  Masks a raw IP address byte array with the specified prefix length.
      */
     public static void maskRawAddress(byte[] array, int prefixLength) {
diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java
new file mode 100644
index 0000000..5a273cf
--- /dev/null
+++ b/core/java/android/net/StaticIpConfiguration.java
@@ -0,0 +1,194 @@
+/*
+ * 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.net;
+
+import android.net.LinkAddress;
+import android.os.Parcelable;
+import android.os.Parcel;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Class that describes static IP configuration.
+ *
+ * This class is different from LinkProperties because it represents
+ * configuration intent. The general contract is that if we can represent
+ * a configuration here, then we should be able to configure it on a network.
+ * The intent is that it closely match the UI we have for configuring networks.
+ *
+ * In contrast, LinkProperties represents current state. It is much more
+ * expressive. For example, it supports multiple IP addresses, multiple routes,
+ * stacked interfaces, and so on. Because LinkProperties is so expressive,
+ * using it to represent configuration intent as well as current state causes
+ * problems. For example, we could unknowingly save a configuration that we are
+ * not in fact capable of applying, or we could save a configuration that the
+ * UI cannot display, which has the potential for malicious code to hide
+ * hostile or unexpected configuration from the user: see, for example,
+ * http://b/12663469 and http://b/16893413 .
+ *
+ * @hide
+ */
+public class StaticIpConfiguration implements Parcelable {
+    public LinkAddress ipAddress;
+    public InetAddress gateway;
+    public final ArrayList<InetAddress> dnsServers;
+    public String domains;
+
+    public StaticIpConfiguration() {
+        dnsServers = new ArrayList<InetAddress>();
+    }
+
+    public StaticIpConfiguration(StaticIpConfiguration source) {
+        this();
+        if (source != null) {
+            // All of these except dnsServers are immutable, so no need to make copies.
+            ipAddress = source.ipAddress;
+            gateway = source.gateway;
+            dnsServers.addAll(source.dnsServers);
+            domains = source.domains;
+        }
+    }
+
+    public void clear() {
+        ipAddress = null;
+        gateway = null;
+        dnsServers.clear();
+        domains = null;
+    }
+
+    /**
+     * Returns the network routes specified by this object. Will typically include a
+     * directly-connected route for the IP address's local subnet and a default route.
+     */
+    public List<RouteInfo> getRoutes(String iface) {
+        List<RouteInfo> routes = new ArrayList<RouteInfo>(2);
+        if (ipAddress != null) {
+            routes.add(new RouteInfo(ipAddress, null, iface));
+        }
+        if (gateway != null) {
+            routes.add(new RouteInfo((LinkAddress) null, gateway, iface));
+        }
+        return routes;
+    }
+
+    /**
+     * Returns a LinkProperties object expressing the data in this object. Note that the information
+     * contained in the LinkProperties will not be a complete picture of the link's configuration,
+     * because any configuration information that is obtained dynamically by the network (e.g.,
+     * IPv6 configuration) will not be included.
+     */
+    public LinkProperties toLinkProperties(String iface) {
+        LinkProperties lp = new LinkProperties();
+        lp.setInterfaceName(iface);
+        if (ipAddress != null) {
+            lp.addLinkAddress(ipAddress);
+        }
+        for (RouteInfo route : getRoutes(iface)) {
+            lp.addRoute(route);
+        }
+        for (InetAddress dns : dnsServers) {
+            lp.addDnsServer(dns);
+        }
+        return lp;
+    }
+
+    public String toString() {
+        StringBuffer str = new StringBuffer();
+
+        str.append("IP address ");
+        if (ipAddress != null ) str.append(ipAddress).append(" ");
+
+        str.append("Gateway ");
+        if (gateway != null) str.append(gateway.getHostAddress()).append(" ");
+
+        str.append(" DNS servers: [");
+        for (InetAddress dnsServer : dnsServers) {
+            str.append(" ").append(dnsServer.getHostAddress());
+        }
+
+        str.append(" ] Domains");
+        if (domains != null) str.append(domains);
+        return str.toString();
+    }
+
+    public int hashCode() {
+        int result = 13;
+        result = 47 * result + (ipAddress == null ? 0 : ipAddress.hashCode());
+        result = 47 * result + (gateway == null ? 0 : gateway.hashCode());
+        result = 47 * result + (domains == null ? 0 : domains.hashCode());
+        result = 47 * result + dnsServers.hashCode();
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+
+        if (!(obj instanceof StaticIpConfiguration)) return false;
+
+        StaticIpConfiguration other = (StaticIpConfiguration) obj;
+
+        return other != null &&
+                Objects.equals(ipAddress, other.ipAddress) &&
+                Objects.equals(gateway, other.gateway) &&
+                dnsServers.equals(other.dnsServers) &&
+                Objects.equals(domains, other.domains);
+    }
+
+    /** Implement the Parcelable interface */
+    public static Creator<StaticIpConfiguration> CREATOR =
+        new Creator<StaticIpConfiguration>() {
+            public StaticIpConfiguration createFromParcel(Parcel in) {
+                StaticIpConfiguration s = new StaticIpConfiguration();
+                readFromParcel(s, in);
+                return s;
+            }
+
+            public StaticIpConfiguration[] newArray(int size) {
+                return new StaticIpConfiguration[size];
+            }
+        };
+
+    /** Implement the Parcelable interface */
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeParcelable(ipAddress, flags);
+        NetworkUtils.parcelInetAddress(dest, gateway, flags);
+        dest.writeInt(dnsServers.size());
+        for (InetAddress dnsServer : dnsServers) {
+            NetworkUtils.parcelInetAddress(dest, dnsServer, flags);
+        }
+    }
+
+    protected static void readFromParcel(StaticIpConfiguration s, Parcel in) {
+        s.ipAddress = in.readParcelable(null);
+        s.gateway = NetworkUtils.unparcelInetAddress(in);
+        s.dnsServers.clear();
+        int size = in.readInt();
+        for (int i = 0; i < size; i++) {
+            s.dnsServers.add(NetworkUtils.unparcelInetAddress(in));
+        }
+    }
+}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index be46bc7..fe9f79b 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -3065,7 +3065,7 @@
                             "partial", which, linePrefix);
                     linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime,
                             "window", which, linePrefix);
-                    if (!linePrefix.equals(": ")) {
+                    if (true || !linePrefix.equals(": ")) {
                         sb.append(" realtime");
                         // Only print out wake locks that were held
                         pw.println(sb.toString());
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 20e26e6..5e77d28 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3546,6 +3546,13 @@
         public static final String DISABLED_SYSTEM_INPUT_METHODS = "disabled_system_input_methods";
 
         /**
+         * Whether to show the IME when a hard keyboard is connected. This is a boolean that
+         * determines if the IME should be shown when a hard keyboard is attached.
+         * @hide
+         */
+        public static final String SHOW_IME_WITH_HARD_KEYBOARD = "show_ime_with_hard_keyboard";
+
+        /**
          * Host name and port for global http proxy. Uses ':' seperator for
          * between host and port.
          *
@@ -5183,6 +5190,12 @@
         public static final String ADB_ENABLED = "adb_enabled";
 
         /**
+         * Whether Views are allowed to save their attribute data.
+         * @hide
+         */
+        public static final String DEBUG_VIEW_ATTRIBUTES = "debug_view_attributes";
+
+        /**
          * Whether assisted GPS should be enabled or not.
          * @hide
          */
diff --git a/core/java/android/transition/ChangeBounds.java b/core/java/android/transition/ChangeBounds.java
index efcbdb3..6246cbe 100644
--- a/core/java/android/transition/ChangeBounds.java
+++ b/core/java/android/transition/ChangeBounds.java
@@ -16,13 +16,11 @@
 
 package android.transition;
 
-import android.animation.TypeConverter;
 import android.content.Context;
 import android.graphics.PointF;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
 import android.animation.RectEvaluator;
@@ -119,9 +117,11 @@
         values.values.put(PROPNAME_BOUNDS, new Rect(view.getLeft(), view.getTop(),
                 view.getRight(), view.getBottom()));
         values.values.put(PROPNAME_PARENT, values.view.getParent());
-        values.view.getLocationInWindow(tempLocation);
-        values.values.put(PROPNAME_WINDOW_X, tempLocation[0]);
-        values.values.put(PROPNAME_WINDOW_Y, tempLocation[1]);
+        if (mReparent) {
+            values.view.getLocationInWindow(tempLocation);
+            values.values.put(PROPNAME_WINDOW_X, tempLocation[0]);
+            values.values.put(PROPNAME_WINDOW_Y, tempLocation[1]);
+        }
     }
 
     @Override
@@ -134,6 +134,19 @@
         captureValues(transitionValues);
     }
 
+    private boolean parentMatches(View startParent, View endParent) {
+        boolean parentMatches = true;
+        if (mReparent) {
+            TransitionValues endValues = getMatchedTransitionValues(startParent, true);
+            if (endValues == null) {
+                parentMatches = startParent == endParent;
+            } else {
+                parentMatches = endParent == endValues.view;
+            }
+        }
+        return parentMatches;
+    }
+
     @Override
     public Animator createAnimator(final ViewGroup sceneRoot, TransitionValues startValues,
             TransitionValues endValues) {
@@ -148,13 +161,7 @@
             return null;
         }
         final View view = endValues.view;
-        boolean parentsEqual = (startParent == endParent) ||
-                (startParent.getId() == endParent.getId());
-        // TODO: Might want reparenting to be separate/subclass transition, or at least
-        // triggered by a property on ChangeBounds. Otherwise, we're forcing the requirement that
-        // all parents in layouts have IDs to avoid layout-inflation resulting in a side-effect
-        // of reparenting the views.
-        if (!mReparent || parentsEqual) {
+        if (parentMatches(startParent, endParent)) {
             Rect startBounds = (Rect) startValues.values.get(PROPNAME_BOUNDS);
             Rect endBounds = (Rect) endValues.values.get(PROPNAME_BOUNDS);
             int startLeft = startBounds.left;
diff --git a/core/java/android/transition/ChangeImageTransform.java b/core/java/android/transition/ChangeImageTransform.java
index 2b26756..4b230eb 100644
--- a/core/java/android/transition/ChangeImageTransform.java
+++ b/core/java/android/transition/ChangeImageTransform.java
@@ -182,6 +182,7 @@
             if (endMatrix == null) {
                 endMatrix = Matrix.IDENTITY_MATRIX;
             }
+            ANIMATED_TRANSFORM_PROPERTY.set(imageView, startMatrix);
             animator = createMatrixAnimator(imageView, startMatrix, endMatrix);
         }
         return animator;
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index 2fa8d2a..0d32d40 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -192,6 +192,8 @@
     private TransitionValuesMaps mEndValues = new TransitionValuesMaps();
     TransitionSet mParent = null;
     private int[] mMatchOrder = DEFAULT_MATCH_ORDER;
+    ArrayList<TransitionValues> mStartValuesList; // only valid after playTransition starts
+    ArrayList<TransitionValues> mEndValuesList; // only valid after playTransitions starts
 
     // Per-animator information used for later canceling when future transitions overlap
     private static ThreadLocal<ArrayMap<Animator, AnimationInfo>> sRunningAnimators =
@@ -518,32 +520,28 @@
     }
 
     /**
-     * Match start/end values by View instance. Adds matched values to startValuesList
-     * and endValuesList and removes them from unmatchedStart and unmatchedEnd.
+     * Match start/end values by View instance. Adds matched values to mStartValuesList
+     * and mEndValuesList and removes them from unmatchedStart and unmatchedEnd.
      */
-    private void matchInstances(ArrayList<TransitionValues> startValuesList,
-            ArrayList<TransitionValues> endValuesList,
-            ArrayMap<View, TransitionValues> unmatchedStart,
+    private void matchInstances(ArrayMap<View, TransitionValues> unmatchedStart,
             ArrayMap<View, TransitionValues> unmatchedEnd) {
         for (int i = unmatchedStart.size() - 1; i >= 0; i--) {
             View view = unmatchedStart.keyAt(i);
             TransitionValues end = unmatchedEnd.remove(view);
             if (end != null) {
                 TransitionValues start = unmatchedStart.removeAt(i);
-                startValuesList.add(start);
-                endValuesList.add(end);
+                mStartValuesList.add(start);
+                mEndValuesList.add(end);
             }
         }
     }
 
     /**
-     * Match start/end values by Adapter item ID. Adds matched values to startValuesList
-     * and endValuesList and removes them from unmatchedStart and unmatchedEnd, using
+     * Match start/end values by Adapter item ID. Adds matched values to mStartValuesList
+     * and mEndValuesList and removes them from unmatchedStart and unmatchedEnd, using
      * startItemIds and endItemIds as a guide for which Views have unique item IDs.
      */
-    private void matchItemIds(ArrayList<TransitionValues> startValuesList,
-            ArrayList<TransitionValues> endValuesList,
-            ArrayMap<View, TransitionValues> unmatchedStart,
+    private void matchItemIds(ArrayMap<View, TransitionValues> unmatchedStart,
             ArrayMap<View, TransitionValues> unmatchedEnd,
             LongSparseArray<View> startItemIds, LongSparseArray<View> endItemIds) {
         int numStartIds = startItemIds.size();
@@ -555,8 +553,8 @@
                     TransitionValues startValues = unmatchedStart.get(startView);
                     TransitionValues endValues = unmatchedEnd.get(endView);
                     if (startValues != null && endValues != null) {
-                        startValuesList.add(startValues);
-                        endValuesList.add(endValues);
+                        mStartValuesList.add(startValues);
+                        mEndValuesList.add(endValues);
                         unmatchedStart.remove(startView);
                         unmatchedEnd.remove(endView);
                     }
@@ -566,13 +564,11 @@
     }
 
     /**
-     * Match start/end values by Adapter view ID. Adds matched values to startValuesList
-     * and endValuesList and removes them from unmatchedStart and unmatchedEnd, using
+     * Match start/end values by Adapter view ID. Adds matched values to mStartValuesList
+     * and mEndValuesList and removes them from unmatchedStart and unmatchedEnd, using
      * startIds and endIds as a guide for which Views have unique IDs.
      */
-    private void matchIds(ArrayList<TransitionValues> startValuesList,
-            ArrayList<TransitionValues> endValuesList,
-            ArrayMap<View, TransitionValues> unmatchedStart,
+    private void matchIds(ArrayMap<View, TransitionValues> unmatchedStart,
             ArrayMap<View, TransitionValues> unmatchedEnd,
             SparseArray<View> startIds, SparseArray<View> endIds) {
         int numStartIds = startIds.size();
@@ -584,8 +580,8 @@
                     TransitionValues startValues = unmatchedStart.get(startView);
                     TransitionValues endValues = unmatchedEnd.get(endView);
                     if (startValues != null && endValues != null) {
-                        startValuesList.add(startValues);
-                        endValuesList.add(endValues);
+                        mStartValuesList.add(startValues);
+                        mEndValuesList.add(endValues);
                         unmatchedStart.remove(startView);
                         unmatchedEnd.remove(endView);
                     }
@@ -595,13 +591,11 @@
     }
 
     /**
-     * Match start/end values by Adapter transitionName. Adds matched values to startValuesList
-     * and endValuesList and removes them from unmatchedStart and unmatchedEnd, using
+     * Match start/end values by Adapter transitionName. Adds matched values to mStartValuesList
+     * and mEndValuesList and removes them from unmatchedStart and unmatchedEnd, using
      * startNames and endNames as a guide for which Views have unique transitionNames.
      */
-    private void matchNames(ArrayList<TransitionValues> startValuesList,
-            ArrayList<TransitionValues> endValuesList,
-            ArrayMap<View, TransitionValues> unmatchedStart,
+    private void matchNames(ArrayMap<View, TransitionValues> unmatchedStart,
             ArrayMap<View, TransitionValues> unmatchedEnd,
             ArrayMap<String, View> startNames, ArrayMap<String, View> endNames) {
         int numStartNames = startNames.size();
@@ -613,8 +607,8 @@
                     TransitionValues startValues = unmatchedStart.get(startView);
                     TransitionValues endValues = unmatchedEnd.get(endView);
                     if (startValues != null && endValues != null) {
-                        startValuesList.add(startValues);
-                        endValuesList.add(endValues);
+                        mStartValuesList.add(startValues);
+                        mEndValuesList.add(endValues);
                         unmatchedStart.remove(startView);
                         unmatchedEnd.remove(endView);
                     }
@@ -624,30 +618,26 @@
     }
 
     /**
-     * Adds all values from unmatchedStart and unmatchedEnd to startValuesList and endValuesList,
+     * Adds all values from unmatchedStart and unmatchedEnd to mStartValuesList and mEndValuesList,
      * assuming that there is no match between values in the list.
      */
-    private void addUnmatched(ArrayList<TransitionValues> startValuesList,
-            ArrayList<TransitionValues> endValuesList,
-            ArrayMap<View, TransitionValues> unmatchedStart,
+    private void addUnmatched(ArrayMap<View, TransitionValues> unmatchedStart,
             ArrayMap<View, TransitionValues> unmatchedEnd) {
         // Views that only exist in the start Scene
         for (int i = 0; i < unmatchedStart.size(); i++) {
-            startValuesList.add(unmatchedStart.valueAt(i));
-            endValuesList.add(null);
+            mStartValuesList.add(unmatchedStart.valueAt(i));
+            mEndValuesList.add(null);
         }
 
         // Views that only exist in the end Scene
         for (int i = 0; i < unmatchedEnd.size(); i++) {
-            endValuesList.add(unmatchedEnd.valueAt(i));
-            startValuesList.add(null);
+            mEndValuesList.add(unmatchedEnd.valueAt(i));
+            mStartValuesList.add(null);
         }
     }
 
     private void matchStartAndEnd(TransitionValuesMaps startValues,
-            TransitionValuesMaps endValues,
-            ArrayList<TransitionValues> startValuesList,
-            ArrayList<TransitionValues> endValuesList) {
+            TransitionValuesMaps endValues) {
         ArrayMap<View, TransitionValues> unmatchedStart =
                 new ArrayMap<View, TransitionValues>(startValues.viewValues);
         ArrayMap<View, TransitionValues> unmatchedEnd =
@@ -656,23 +646,23 @@
         for (int i = 0; i < mMatchOrder.length; i++) {
             switch (mMatchOrder[i]) {
                 case MATCH_INSTANCE:
-                    matchInstances(startValuesList, endValuesList, unmatchedStart, unmatchedEnd);
+                    matchInstances(unmatchedStart, unmatchedEnd);
                     break;
                 case MATCH_NAME:
-                    matchNames(startValuesList, endValuesList, unmatchedStart, unmatchedEnd,
+                    matchNames(unmatchedStart, unmatchedEnd,
                             startValues.nameValues, endValues.nameValues);
                     break;
                 case MATCH_ID:
-                    matchIds(startValuesList, endValuesList, unmatchedStart, unmatchedEnd,
+                    matchIds(unmatchedStart, unmatchedEnd,
                             startValues.idValues, endValues.idValues);
                     break;
                 case MATCH_ITEM_ID:
-                    matchItemIds(startValuesList, endValuesList, unmatchedStart, unmatchedEnd,
+                    matchItemIds(unmatchedStart, unmatchedEnd,
                             startValues.itemIdValues, endValues.itemIdValues);
                     break;
             }
         }
-        addUnmatched(startValuesList, endValuesList, unmatchedStart, unmatchedEnd);
+        addUnmatched(unmatchedStart, unmatchedEnd);
     }
 
     /**
@@ -687,19 +677,17 @@
      * @hide
      */
     protected void createAnimators(ViewGroup sceneRoot, TransitionValuesMaps startValues,
-            TransitionValuesMaps endValues) {
+            TransitionValuesMaps endValues, ArrayList<TransitionValues> startValuesList,
+            ArrayList<TransitionValues> endValuesList) {
         if (DBG) {
             Log.d(LOG_TAG, "createAnimators() for " + this);
         }
-        ArrayList<TransitionValues> startValuesList = new ArrayList<TransitionValues>();
-        ArrayList<TransitionValues> endValuesList = new ArrayList<TransitionValues>();
-        matchStartAndEnd(startValues, endValues, startValuesList, endValuesList);
-
         ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
         long minStartDelay = Long.MAX_VALUE;
         int minAnimator = mAnimators.size();
         SparseLongArray startDelays = new SparseLongArray();
-        for (int i = 0; i < startValuesList.size(); ++i) {
+        int startValuesListCount = startValuesList.size();
+        for (int i = 0; i < startValuesListCount; ++i) {
             TransitionValues start = startValuesList.get(i);
             TransitionValues end = endValuesList.get(i);
             // Only bother trying to animate with valid values that differ between start/end
@@ -1523,11 +1511,13 @@
             mStartValues.idValues.clear();
             mStartValues.itemIdValues.clear();
             mStartValues.nameValues.clear();
+            mStartValuesList = null;
         } else {
             mEndValues.viewValues.clear();
             mEndValues.idValues.clear();
             mEndValues.itemIdValues.clear();
             mEndValues.nameValues.clear();
+            mEndValuesList = null;
         }
     }
 
@@ -1613,6 +1603,45 @@
     }
 
     /**
+     * Find the matched start or end value for a given View. This is only valid
+     * after playTransition starts. For example, it will be valid in
+     * {@link #createAnimator(android.view.ViewGroup, TransitionValues, TransitionValues)}, but not
+     * in {@link #captureStartValues(TransitionValues)}.
+     *
+     * @param view The view to find the match for.
+     * @param viewInStart Is View from the start values or end values.
+     * @return The matching TransitionValues for view in either start or end values, depending
+     * on viewInStart or null if there is no match for the given view.
+     */
+    TransitionValues getMatchedTransitionValues(View view, boolean viewInStart) {
+        if (mParent != null) {
+            return mParent.getMatchedTransitionValues(view, viewInStart);
+        }
+        ArrayList<TransitionValues> lookIn = viewInStart ? mStartValuesList : mEndValuesList;
+        if (lookIn == null) {
+            return null;
+        }
+        int count = lookIn.size();
+        int index = -1;
+        for (int i = 0; i < count; i++) {
+            TransitionValues values = lookIn.get(i);
+            if (values == null) {
+                return null;
+            }
+            if (values.view == view) {
+                index = i;
+                break;
+            }
+        }
+        TransitionValues values = null;
+        if (index >= 0) {
+            ArrayList<TransitionValues> matchIn = viewInStart ? mEndValuesList : mStartValuesList;
+            values = matchIn.get(index);
+        }
+        return values;
+    }
+
+    /**
      * Pauses this transition, sending out calls to {@link
      * TransitionListener#onTransitionPause(Transition)} to all listeners
      * and pausing all running animators started by this transition.
@@ -1684,6 +1713,10 @@
      * runAnimations() to actually start the animations.
      */
     void playTransition(ViewGroup sceneRoot) {
+        mStartValuesList = new ArrayList<TransitionValues>();
+        mEndValuesList = new ArrayList<TransitionValues>();
+        matchStartAndEnd(mStartValues, mEndValues);
+
         ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
         int numOldAnims = runningAnimators.size();
         WindowId windowId = sceneRoot.getWindowId();
@@ -1694,7 +1727,7 @@
                 if (oldInfo != null && oldInfo.view != null && oldInfo.windowId == windowId) {
                     TransitionValues oldValues = oldInfo.values;
                     View oldView = oldInfo.view;
-                    TransitionValues newValues = mEndValues.viewValues.get(oldView);
+                    TransitionValues newValues = getMatchedTransitionValues(oldView, true);
                     boolean cancel = oldInfo.transition.areValuesChanged(oldValues, newValues);
                     if (cancel) {
                         if (anim.isRunning() || anim.isStarted()) {
@@ -1713,7 +1746,7 @@
             }
         }
 
-        createAnimators(sceneRoot, mStartValues, mEndValues);
+        createAnimators(sceneRoot, mStartValues, mEndValues, mStartValuesList, mEndValuesList);
         runAnimators();
     }
 
@@ -2055,6 +2088,8 @@
             clone.mAnimators = new ArrayList<Animator>();
             clone.mStartValues = new TransitionValuesMaps();
             clone.mEndValues = new TransitionValuesMaps();
+            clone.mStartValuesList = null;
+            clone.mEndValuesList = null;
         } catch (CloneNotSupportedException e) {}
 
         return clone;
diff --git a/core/java/android/transition/TransitionSet.java b/core/java/android/transition/TransitionSet.java
index 83c60af..f6499ae 100644
--- a/core/java/android/transition/TransitionSet.java
+++ b/core/java/android/transition/TransitionSet.java
@@ -151,6 +151,31 @@
     }
 
     /**
+     * Returns the number of child transitions in the TransitionSet.
+     *
+     * @return The number of child transitions in the TransitionSet.
+     * @see #addTransition(Transition)
+     * @see #getTransitionAt(int)
+     */
+    public int getTransitionCount() {
+        return mTransitions.size();
+    }
+
+    /**
+     * Returns the child Transition at the specified position in the TransitionSet.
+     *
+     * @param index The position of the Transition to retrieve.
+     * @see #addTransition(Transition)
+     * @see #getTransitionCount()
+     */
+    public Transition getTransitionAt(int index) {
+        if (index < 0 || index >= mTransitions.size()) {
+            return null;
+        }
+        return mTransitions.get(index);
+    }
+
+    /**
      * Setting a non-negative duration on a TransitionSet causes all of the child
      * transitions (current and future) to inherit this duration.
      *
@@ -361,11 +386,13 @@
      */
     @Override
     protected void createAnimators(ViewGroup sceneRoot, TransitionValuesMaps startValues,
-            TransitionValuesMaps endValues) {
+            TransitionValuesMaps endValues, ArrayList<TransitionValues> startValuesList,
+            ArrayList<TransitionValues> endValuesList) {
         startValues = removeExcludes(startValues);
         endValues = removeExcludes(endValues);
         for (Transition childTransition : mTransitions) {
-            childTransition.createAnimators(sceneRoot, startValues, endValues);
+            childTransition.createAnimators(sceneRoot, startValues, endValues, startValuesList,
+                    endValuesList);
         }
     }
 
diff --git a/core/java/android/view/MenuItem.java b/core/java/android/view/MenuItem.java
index 2dfbcb5..e706c9c 100644
--- a/core/java/android/view/MenuItem.java
+++ b/core/java/android/view/MenuItem.java
@@ -258,8 +258,8 @@
     /**
      * Change both the numeric and alphabetic shortcut associated with this
      * item. Note that the shortcut will be triggered when the key that
-     * generates the given character is pressed alone or along with with the alt
-     * key. Also note that case is not significant and that alphabetic shortcut
+     * generates the given character is pressed along with the ctrl key.
+     * Also note that case is not significant and that alphabetic shortcut
      * characters will be displayed in lower case.
      * <p>
      * See {@link Menu} for the menu types that support shortcuts.
@@ -293,9 +293,9 @@
     /**
      * Change the alphabetic shortcut associated with this item. The shortcut
      * will be triggered when the key that generates the given character is
-     * pressed alone or along with with the alt key. Case is not significant and
-     * shortcut characters will be displayed in lower case. Note that menu items
-     * with the characters '\b' or '\n' as shortcuts will get triggered by the
+     * pressed along with the ctrl key. Case is not significant and shortcut
+     * characters will be displayed in lower case. Note that menu items with
+     * the characters '\b' or '\n' as shortcuts will get triggered by the
      * Delete key or Carriage Return key, respectively.
      * <p>
      * See {@link Menu} for the menu types that support shortcuts.
@@ -596,4 +596,4 @@
      * @return This menu item instance for call chaining
      */
     public MenuItem setOnActionExpandListener(OnActionExpandListener listener);
-}
\ No newline at end of file
+}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index e56581b..3adc41a 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -700,6 +700,13 @@
     public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
 
     /**
+     * When set to true, this view will save its attribute data.
+     *
+     * @hide
+     */
+    public static boolean mDebugViewAttributes = false;
+
+    /**
      * Used to mark a View that has no ID.
      */
     public static final int NO_ID = -1;
@@ -3254,6 +3261,7 @@
      * This field should be made private, so it is hidden from the SDK.
      * {@hide}
      */
+    @ViewDebug.ExportedProperty(deepExport = true)
     protected Context mContext;
 
     private final Resources mResources;
@@ -3524,6 +3532,18 @@
     GhostView mGhostView;
 
     /**
+     * Holds pairs of adjacent attribute data: attribute name followed by its value.
+     * @hide
+     */
+    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
+    public String[] mAttributes;
+
+    /**
+     * Maps a Resource id to its name.
+     */
+    private static SparseArray<String> mAttributeMap;
+
+    /**
      * Simple constructor to use when creating a view from code.
      *
      * @param context The Context the view is running in, through which it can
@@ -3641,6 +3661,10 @@
         final TypedArray a = context.obtainStyledAttributes(
                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
 
+        if (mDebugViewAttributes) {
+            saveAttributeData(attrs, a);
+        }
+
         Drawable background = null;
 
         int leftPadding = -1;
@@ -4136,6 +4160,51 @@
         mRenderNode = RenderNode.create(getClass().getName());
     }
 
+    private static SparseArray<String> getAttributeMap() {
+        if (mAttributeMap == null) {
+            mAttributeMap = new SparseArray<String>();
+        }
+        return mAttributeMap;
+    }
+
+    private void saveAttributeData(AttributeSet attrs, TypedArray a) {
+        int length = ((attrs == null ? 0 : attrs.getAttributeCount()) + a.getIndexCount()) * 2;
+        mAttributes = new String[length];
+
+        int i = 0;
+        if (attrs != null) {
+            for (i = 0; i < attrs.getAttributeCount(); i += 2) {
+                mAttributes[i] = attrs.getAttributeName(i);
+                mAttributes[i + 1] = attrs.getAttributeValue(i);
+            }
+
+        }
+
+        SparseArray<String> attributeMap = getAttributeMap();
+        for (int j = 0; j < a.length(); ++j) {
+            if (a.hasValue(j)) {
+                try {
+                    int resourceId = a.getResourceId(j, 0);
+                    if (resourceId == 0) {
+                        continue;
+                    }
+
+                    String resourceName = attributeMap.get(resourceId);
+                    if (resourceName == null) {
+                        resourceName = a.getResources().getResourceName(resourceId);
+                        attributeMap.put(resourceId, resourceName);
+                    }
+
+                    mAttributes[i] = resourceName;
+                    mAttributes[i + 1] = a.getText(j).toString();
+                    i += 2;
+                } catch (Resources.NotFoundException e) {
+                    // if we can't get the resource name, we just ignore it
+                }
+            }
+        }
+    }
+
     public String toString() {
         StringBuilder out = new StringBuilder(128);
         out.append(getClass().getName());
@@ -13762,6 +13831,7 @@
                     } else {
                         draw(canvas);
                     }
+                    drawAccessibilityFocus(canvas);
                 }
             } finally {
                 renderNode.end(canvas);
@@ -14056,6 +14126,7 @@
             } else {
                 draw(canvas);
             }
+            drawAccessibilityFocus(canvas);
 
             canvas.restoreToCount(restoreCount);
             canvas.setBitmap(null);
@@ -14130,6 +14201,7 @@
         } else {
             draw(canvas);
         }
+        drawAccessibilityFocus(canvas);
 
         mPrivateFlags = flags;
 
@@ -14723,9 +14795,13 @@
                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
                         mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                         dispatchDraw(canvas);
+                        if (mOverlay != null && !mOverlay.isEmpty()) {
+                            mOverlay.getOverlayView().draw(canvas);
+                        }
                     } else {
                         draw(canvas);
                     }
+                    drawAccessibilityFocus(canvas);
                 } else {
                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                     ((HardwareCanvas) canvas).drawRenderNode(renderNode, null, flags);
@@ -14977,6 +15053,45 @@
     }
 
     /**
+     * Draws the accessibility focus rect onto the specified canvas.
+     *
+     * @param canvas Canvas on which to draw the focus rect
+     */
+    private void drawAccessibilityFocus(Canvas canvas) {
+        if (mAttachInfo == null) {
+            return;
+        }
+
+        final Rect bounds = mAttachInfo.mTmpInvalRect;
+        final ViewRootImpl viewRoot = getViewRootImpl();
+        if (viewRoot == null || viewRoot.getAccessibilityFocusedHost() != this) {
+            return;
+        }
+
+        final AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
+        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
+            return;
+        }
+
+        final Drawable drawable = viewRoot.getAccessibilityFocusedDrawable();
+        if (drawable == null) {
+            return;
+        }
+
+        final AccessibilityNodeInfo virtualView = viewRoot.getAccessibilityFocusedVirtualView();
+        if (virtualView != null) {
+            virtualView.getBoundsInParent(bounds);
+        } else {
+            bounds.set(0, 0, mRight - mLeft, mBottom - mTop);
+        }
+
+        canvas.translate(mScrollX, mScrollY);
+        drawable.setBounds(bounds);
+        drawable.draw(canvas);
+        canvas.translate(-mScrollX, -mScrollY);
+    }
+
+    /**
      * Draws the background onto the specified canvas.
      *
      * @param canvas Canvas on which to draw the background
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 4d9a8cc..6c66eb0 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -187,6 +187,15 @@
          * @return true if the supported values should be formatted as a hex string.
          */
         boolean formatToHexString() default false;
+
+        /**
+         * Indicates whether or not the key to value mappings are held in adjacent indices.
+         *
+         * Note: Applies only to fields and methods that return String[].
+         *
+         * @return true if the key to value mappings are held in adjacent indices.
+         */
+        boolean hasAdjacentMapping() default false;
     }
 
     /**
@@ -1056,7 +1065,6 @@
             Class<?> klass, String prefix) throws IOException {
 
         final Method[] methods = getExportedPropertyMethods(klass);
-
         int count = methods.length;
         for (int i = 0; i < count; i++) {
             final Method method = methods[i];
@@ -1108,6 +1116,19 @@
                     exportUnrolledArray(context, out, property, array, valuePrefix, suffix);
 
                     continue;
+                } else if (returnType == String[].class) {
+                    final String[] array = (String[]) methodValue;
+                    if (property.hasAdjacentMapping() && array != null) {
+                        for (int j = 0; j < array.length; j += 2) {
+                            if (array[j] != null) {
+                                writeEntry(out, categoryPrefix + prefix, array[j], "()",
+                                        array[j + 1] == null ? "null" : array[j + 1]);
+                            }
+
+                        }
+                    }
+
+                    continue;
                 } else if (!returnType.isPrimitive()) {
                     if (property.deepExport()) {
                         dumpViewProperties(context, methodValue, out, prefix + property.prefix());
@@ -1187,6 +1208,18 @@
                     exportUnrolledArray(context, out, property, array, valuePrefix, suffix);
 
                     continue;
+                } else if (type == String[].class) {
+                    final String[] array = (String[]) field.get(view);
+                    if (property.hasAdjacentMapping() && array != null) {
+                        for (int j = 0; j < array.length; j += 2) {
+                            if (array[j] != null) {
+                                writeEntry(out, categoryPrefix + prefix, array[j], "",
+                                        array[j + 1] == null ? "null" : array[j + 1]);
+                            }
+                        }
+                    }
+
+                    continue;
                 } else if (!type.isPrimitive()) {
                     if (property.deepExport()) {
                         dumpViewProperties(context, field.get(view), out, prefix +
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 92e0245..bb469a3 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2244,7 +2244,6 @@
             canvas.drawHardwareLayer(mResizeBuffer, mHardwareXOffset, mHardwareYOffset,
                     mResizePaint);
         }
-        drawAccessibilityFocusedDrawableIfNeeded(canvas);
     }
 
     /**
@@ -2462,25 +2461,9 @@
                 if (mHardwareYOffset != yOffset || mHardwareXOffset != xOffset) {
                     mHardwareYOffset = yOffset;
                     mHardwareXOffset = xOffset;
-                    invalidateRoot = true;
-                }
-                mResizeAlpha = resizeAlpha;
-
-                if (!invalidateRoot) {
-                    // If accessibility focus moved, invalidate the root.
-                    final Drawable drawable = mAttachInfo.mAccessibilityFocusDrawable;
-                    if (drawable != null) {
-                        final Rect bounds = mAttachInfo.mTmpInvalRect;
-                        if (getAccessibilityFocusedRect(bounds)
-                                && !bounds.equals(drawable.getBounds())) {
-                            invalidateRoot = true;
-                        }
-                    }
-                }
-
-                if (invalidateRoot) {
                     mAttachInfo.mHardwareRenderer.invalidateRoot();
                 }
+                mResizeAlpha = resizeAlpha;
 
                 dirty.setEmpty();
 
@@ -2600,8 +2583,6 @@
                 attachInfo.mSetIgnoreDirtyState = false;
 
                 mView.draw(canvas);
-
-                drawAccessibilityFocusedDrawableIfNeeded(canvas);
             } finally {
                 if (!attachInfo.mSetIgnoreDirtyState) {
                     // Only clear the flag if it was not set during the mView.draw() call
@@ -2625,54 +2606,7 @@
         return true;
     }
 
-    /**
-     * We want to draw a highlight around the current accessibility focused.
-     * Since adding a style for all possible view is not a viable option we
-     * have this specialized drawing method.
-     *
-     * Note: We are doing this here to be able to draw the highlight for
-     *       virtual views in addition to real ones.
-     *
-     * @param canvas The canvas on which to draw.
-     */
-    private void drawAccessibilityFocusedDrawableIfNeeded(Canvas canvas) {
-        final Rect bounds = mAttachInfo.mTmpInvalRect;
-        if (getAccessibilityFocusedRect(bounds)) {
-            final Drawable drawable = getAccessibilityFocusedDrawable();
-            if (drawable != null) {
-                drawable.setBounds(bounds);
-                drawable.draw(canvas);
-            }
-        }
-    }
-
-    private boolean getAccessibilityFocusedRect(Rect bounds) {
-        final AccessibilityManager manager = AccessibilityManager.getInstance(mView.mContext);
-        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
-            return false;
-        }
-
-        final View host = mAccessibilityFocusedHost;
-        if (host == null || host.mAttachInfo == null) {
-            return false;
-        }
-
-        final AccessibilityNodeProvider provider = host.getAccessibilityNodeProvider();
-        if (provider == null) {
-            host.getBoundsOnScreen(bounds);
-        } else if (mAccessibilityFocusedVirtualView != null) {
-            mAccessibilityFocusedVirtualView.getBoundsInScreen(bounds);
-        } else {
-            return false;
-        }
-
-        final AttachInfo attachInfo = mAttachInfo;
-        bounds.offset(-attachInfo.mWindowLeft, -attachInfo.mWindowTop);
-        bounds.intersect(0, 0, attachInfo.mViewRootImpl.mWidth, attachInfo.mViewRootImpl.mHeight);
-        return true;
-    }
-
-    private Drawable getAccessibilityFocusedDrawable() {
+    Drawable getAccessibilityFocusedDrawable() {
         // Lazily load the accessibility focus drawable.
         if (mAttachInfo.mAccessibilityFocusDrawable == null) {
             final TypedValue value = new TypedValue();
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index b37ee06..3f5f045 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -3158,6 +3158,7 @@
         // Offset from touch position to mPosition
         private float mTouchToWindowOffsetX, mTouchToWindowOffsetY;
         protected int mHotspotX;
+        protected int mHorizontalGravity;
         // Offsets the hotspot point up, so that cursor is not hidden by the finger when moving up
         private float mTouchOffsetY;
         // Where the touch position should be on the handle to ensure a maximum cursor visibility
@@ -3172,6 +3173,8 @@
         private boolean mPositionHasChanged = true;
         // Used to delay the appearance of the action popup window
         private Runnable mActionPopupShower;
+        // Minimum touch target size for handles
+        private int mMinSize;
 
         public HandleView(Drawable drawableLtr, Drawable drawableRtl) {
             super(mTextView.getContext());
@@ -3184,10 +3187,12 @@
 
             mDrawableLtr = drawableLtr;
             mDrawableRtl = drawableRtl;
+            mMinSize = mTextView.getContext().getResources().getDimensionPixelSize(
+                    com.android.internal.R.dimen.text_handle_min_size);
 
             updateDrawable();
 
-            final int handleHeight = mDrawable.getIntrinsicHeight();
+            final int handleHeight = getPreferredHeight();
             mTouchOffsetY = -0.3f * handleHeight;
             mIdealVerticalOffset = 0.7f * handleHeight;
         }
@@ -3197,9 +3202,11 @@
             final boolean isRtlCharAtOffset = mTextView.getLayout().isRtlCharAt(offset);
             mDrawable = isRtlCharAtOffset ? mDrawableRtl : mDrawableLtr;
             mHotspotX = getHotspotX(mDrawable, isRtlCharAtOffset);
+            mHorizontalGravity = getHorizontalGravity(isRtlCharAtOffset);
         }
 
         protected abstract int getHotspotX(Drawable drawable, boolean isRtlRun);
+        protected abstract int getHorizontalGravity(boolean isRtlRun);
 
         // Touch-up filter: number of previous positions remembered
         private static final int HISTORY_SIZE = 5;
@@ -3244,7 +3251,15 @@
 
         @Override
         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-            setMeasuredDimension(mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight());
+            setMeasuredDimension(getPreferredWidth(), getPreferredHeight());
+        }
+
+        private int getPreferredWidth() {
+            return Math.max(mDrawable.getIntrinsicWidth(), mMinSize);
+        }
+
+        private int getPreferredHeight() {
+            return Math.max(mDrawable.getIntrinsicHeight(), mMinSize);
         }
 
         public void show() {
@@ -3336,7 +3351,8 @@
                 }
                 final int line = layout.getLineForOffset(offset);
 
-                mPositionX = (int) (layout.getPrimaryHorizontal(offset) - 0.5f - mHotspotX);
+                mPositionX = (int) (layout.getPrimaryHorizontal(offset) - 0.5f - mHotspotX -
+                        getHorizontalOffset() + getCursorOffset());
                 mPositionY = layout.getLineBottom(line);
 
                 // Take TextView's padding and scroll into account.
@@ -3385,10 +3401,36 @@
 
         @Override
         protected void onDraw(Canvas c) {
-            mDrawable.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
+            final int drawWidth = mDrawable.getIntrinsicWidth();
+            final int left = getHorizontalOffset();
+
+            mDrawable.setBounds(left, 0, left + drawWidth, mDrawable.getIntrinsicHeight());
             mDrawable.draw(c);
         }
 
+        private int getHorizontalOffset() {
+            final int width = getPreferredWidth();
+            final int drawWidth = mDrawable.getIntrinsicWidth();
+            final int left;
+            switch (mHorizontalGravity) {
+                case Gravity.LEFT:
+                    left = 0;
+                    break;
+                default:
+                case Gravity.CENTER:
+                    left = (width - drawWidth) / 2;
+                    break;
+                case Gravity.RIGHT:
+                    left = width - drawWidth;
+                    break;
+            }
+            return left;
+        }
+
+        protected int getCursorOffset() {
+            return 0;
+        }
+
         @Override
         public boolean onTouchEvent(MotionEvent ev) {
             switch (ev.getActionMasked()) {
@@ -3508,6 +3550,22 @@
         }
 
         @Override
+        protected int getHorizontalGravity(boolean isRtlRun) {
+            return Gravity.CENTER_HORIZONTAL;
+        }
+
+        @Override
+        protected int getCursorOffset() {
+            int offset = super.getCursorOffset();
+            final Drawable cursor = mCursorCount > 0 ? mCursorDrawable[0] : null;
+            if (cursor != null) {
+                cursor.getPadding(mTempRect);
+                offset += (cursor.getIntrinsicWidth() - mTempRect.left - mTempRect.right) / 2;
+            }
+            return offset;
+        }
+
+        @Override
         public boolean onTouchEvent(MotionEvent ev) {
             final boolean result = super.onTouchEvent(ev);
 
@@ -3594,6 +3652,11 @@
         }
 
         @Override
+        protected int getHorizontalGravity(boolean isRtlRun) {
+            return isRtlRun ? Gravity.RIGHT : Gravity.LEFT;
+        }
+
+        @Override
         public int getCurrentCursorOffset() {
             return mTextView.getSelectionStart();
         }
@@ -3637,6 +3700,11 @@
         }
 
         @Override
+        protected int getHorizontalGravity(boolean isRtlRun) {
+            return isRtlRun ? Gravity.LEFT : Gravity.RIGHT;
+        }
+
+        @Override
         public int getCurrentCursorOffset() {
             return mTextView.getSelectionEnd();
         }
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 4dd7e07..23f911c 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -1501,7 +1501,7 @@
                     mRules[ALIGN_PARENT_START] = 0;
                 }
 
-                if (mRules[ALIGN_PARENT_RIGHT] == 0) {
+                if (mRules[ALIGN_PARENT_END] != 0) {
                     if (mRules[ALIGN_PARENT_RIGHT] == 0) {
                         // "right" rule is not defined but "end" rule is: use the "end" rule as the
                         // "right" rule
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index d801571..6eb0099 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -974,6 +974,16 @@
             }
         }
 
+        public boolean isShowImeWithHardKeyboardEnabled() {
+                return Settings.Secure.getIntForUser(mResolver,
+                        Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0, mCurrentUserId) == 1;
+        }
+
+        public void setShowImeWithHardKeyboard(boolean show) {
+            Settings.Secure.putIntForUser(mResolver, Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD,
+                    show ? 1 : 0, mCurrentUserId);
+        }
+
         public int getCurrentUserId() {
             return mCurrentUserId;
         }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 6c9766e..299b0e6 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -105,7 +105,7 @@
     // The maximum number of names wakelocks we will keep track of
     // per uid; once the limit is reached, we batch the remaining wakelocks
     // in to one common name.
-    private static final int MAX_WAKELOCKS_PER_UID = 50;
+    private static final int MAX_WAKELOCKS_PER_UID = 100;
 
     private static int sNumSpeedSteps;
 
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 32cf286..5bd38f3 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -69,9 +69,8 @@
  */
 static struct fieldIds {
     jmethodID clear;
-    jmethodID setInterfaceName;
-    jmethodID addLinkAddress;
-    jmethodID addGateway;
+    jmethodID setIpAddress;
+    jmethodID setGateway;
     jmethodID addDns;
     jmethodID setDomains;
     jmethodID setServerAddress;
@@ -130,21 +129,16 @@
     if (result == 0) {
         env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.clear);
 
-        // set mIfaceName
-        // dhcpResults->setInterfaceName(ifname)
-        env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setInterfaceName, ifname);
-
         // set the linkAddress
         // dhcpResults->addLinkAddress(inetAddress, prefixLength)
-        result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.addLinkAddress,
+        result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.setIpAddress,
                 env->NewStringUTF(ipaddr), prefixLength);
     }
 
     if (result == 0) {
         // set the gateway
-        // dhcpResults->addGateway(gateway)
         result = env->CallBooleanMethod(dhcpResults,
-                dhcpResultsFieldIds.addGateway, env->NewStringUTF(gateway));
+                dhcpResultsFieldIds.setGateway, env->NewStringUTF(gateway));
     }
 
     if (result == 0) {
@@ -279,12 +273,10 @@
     LOG_FATAL_IF(dhcpResultsClass == NULL, "Unable to find class android/net/DhcpResults");
     dhcpResultsFieldIds.clear =
             env->GetMethodID(dhcpResultsClass, "clear", "()V");
-    dhcpResultsFieldIds.setInterfaceName =
-            env->GetMethodID(dhcpResultsClass, "setInterfaceName", "(Ljava/lang/String;)V");
-    dhcpResultsFieldIds.addLinkAddress =
-            env->GetMethodID(dhcpResultsClass, "addLinkAddress", "(Ljava/lang/String;I)Z");
-    dhcpResultsFieldIds.addGateway =
-            env->GetMethodID(dhcpResultsClass, "addGateway", "(Ljava/lang/String;)Z");
+    dhcpResultsFieldIds.setIpAddress =
+            env->GetMethodID(dhcpResultsClass, "setIpAddress", "(Ljava/lang/String;I)Z");
+    dhcpResultsFieldIds.setGateway =
+            env->GetMethodID(dhcpResultsClass, "setGateway", "(Ljava/lang/String;)Z");
     dhcpResultsFieldIds.addDns =
             env->GetMethodID(dhcpResultsClass, "addDns", "(Ljava/lang/String;)Z");
     dhcpResultsFieldIds.setDomains =
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index aee3090..157147e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1249,13 +1249,13 @@
         android:description="@string/permdesc_use_sip"
         android:label="@string/permlab_use_sip" />
 
-    <!-- @SystemApi Allows an application to request CallHandlerService implementations.
+    <!-- @SystemApi Allows an application to bind to InCallService implementations.
          @hide -->
-    <permission android:name="android.permission.BIND_CALL_SERVICE"
+    <permission android:name="android.permission.BIND_INCALL_SERVICE"
         android:permissionGroup="android.permission-group.PHONE_CALLS"
         android:protectionLevel="system|signature"
-        android:description="@string/permdesc_bind_call_service"
-        android:label="@string/permlab_bind_call_service" />
+        android:description="@string/permdesc_bind_incall_service"
+        android:label="@string/permlab_bind_incall_service" />
 
     <!-- @SystemApi Allows an application to bind to ConnectionService implementations.
          @hide -->
@@ -1265,6 +1265,14 @@
                 android:description="@string/permdesc_bind_connection_service"
                 android:label="@string/permlab_bind_connection_service" />
 
+    <!-- @SystemApi Allows an application to control the in-call experience.
+         @hide -->
+    <permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE"
+                android:permissionGroup="android.permission-group.PHONE_CALLS"
+                android:protectionLevel="system|signature"
+                android:description="@string/permdesc_control_incall_experience"
+                android:label="@string/permlab_control_incall_experience" />
+
     <!-- ================================== -->
     <!-- Permissions for sdcard interaction -->
     <!-- ================================== -->
@@ -2811,11 +2819,11 @@
         android:description="@string/permdesc_accessDrmCertificates"
         android:protectionLevel="signature|system" />
 
-    <!-- Api Allows an application to create media projection sessions.
+    <!-- Api Allows an application to manage media projection sessions.
          @hide This is not a third-party API (intended for system apps). -->
-    <permission android:name="android.permission.CREATE_MEDIA_PROJECTION"
-        android:label="@string/permlab_createMediaProjection"
-        android:description="@string/permdesc_createMediaProjection"
+    <permission android:name="android.permission.MANAGE_MEDIA_PROJECTION"
+        android:label="@string/permlab_manageMediaProjection"
+        android:description="@string/permdesc_manageMediaProjection"
         android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to read install sessions
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00001.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00001.9.png
index 9076900..c31194e 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00001.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00002.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00002.9.png
index 3c72bf8..52ed6b2 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00002.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00003.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00003.9.png
index d31e113..7b7cde586 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00003.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00004.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00004.9.png
index d0c693e..859642a 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00004.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00005.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00005.9.png
index dfa19b4..5b71dda 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00005.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00006.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00006.9.png
index 151f205..378d82d 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00006.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00007.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00007.9.png
index ad3ee2c..43c995a 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00007.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00008.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00008.9.png
index 43d66d7..c937837 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00008.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00009.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00009.9.png
index 13e4f8b..a60a127 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00009.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00010.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00010.9.png
index a09b6b2..db0bf2d 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00010.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00011.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00011.9.png
index be02e53..4a6adbe 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00011.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00012.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00012.9.png
index 655d387..98983ef 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00012.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00001.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00001.9.png
index e870a0a..8e7b62f 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00001.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00002.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00002.9.png
index 1d8f805..479a26e 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00002.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00003.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00003.9.png
index d348871..77d3130 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00003.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00004.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00004.9.png
index 941e91e..cfe684f 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00004.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00005.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00005.9.png
index adee78d..4a64a36 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00005.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00006.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00006.9.png
index e6b4ca3..29591ff 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00006.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00007.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00007.9.png
index 6c2bc0d..cf7cf49 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00007.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00008.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00008.9.png
index 763833c..2a2a9af 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00008.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00009.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00009.9.png
index 9a87fbc..1f7fe5f 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00009.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00010.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00010.9.png
index 6ccf70b..f5d7093 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00010.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00011.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00011.9.png
index d1c14a5..3878386 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00011.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00012.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00012.9.png
index c2290f0..adcb9e9 100644
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00012.9.png
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00001.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00001.9.png
index 0238898..36ed954 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00001.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00002.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00002.9.png
index ada1be9..863eee1 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00002.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00003.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00003.9.png
index 82aec64..63e93a8 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00003.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00004.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00004.9.png
index 1c6ea9f..85c851d 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00004.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00005.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00005.9.png
index ac11400..8637636 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00005.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00006.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00006.9.png
index 2025972..2945c29 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00006.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00007.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00007.9.png
index 7420fd8..678a6c8 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00007.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00008.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00008.9.png
index 1f40832..238a6f1 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00008.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00009.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00009.9.png
index cf58e44..4a342a6 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00009.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00010.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00010.9.png
index 930a280..5842b19 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00010.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00011.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00011.9.png
index ed9bc37..3e1bd2d 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00011.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00012.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00012.9.png
index cddb5b0..73ed10b 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00012.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00001.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00001.9.png
index bc1f979..03d3dfb 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00001.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00002.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00002.9.png
index e6fdbcc..25085ce 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00002.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00003.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00003.9.png
index 3d60b43..9e4d2f3 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00003.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00004.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00004.9.png
index b9afdc2..ab5bd1e 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00004.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00005.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00005.9.png
index c3c8bf2..f5297ce 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00005.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00006.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00006.9.png
index 1c7e5e1..1ad56e9 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00006.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00007.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00007.9.png
index 6329b73..4bad055 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00007.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00008.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00008.9.png
index 424202c..d908034 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00008.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00009.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00009.9.png
index 313beca..8ed4fb4 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00009.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00010.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00010.9.png
index f18d86a..61d3ced 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00010.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00011.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00011.9.png
index 8ab48c0..dec2a82 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00011.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00012.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00012.9.png
index fbc2c16..6635830 100644
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00012.9.png
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00001.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00001.9.png
index 265aeb7..df73ef7 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00001.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00002.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00002.9.png
index 2f036ad..baf52ed 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00002.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00003.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00003.9.png
index bb26440..c8f3b1c 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00003.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00004.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00004.9.png
index 1b70047..fe715cf 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00004.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00005.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00005.9.png
index b544b98..8e66e11 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00005.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00006.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00006.9.png
index c461f3d..537496e 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00006.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00007.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00007.9.png
index f57da14..2722a98 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00007.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00008.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00008.9.png
index 22c6fbc..81fad09 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00008.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00009.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00009.9.png
index cd21ac9..cda20c8 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00009.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00010.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00010.9.png
index a38dc87..a61ad4b 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00010.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00011.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00011.9.png
index d84a342..d6e8e4c 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00011.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00012.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00012.9.png
index b82a2eb..785168e 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00012.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00001.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00001.9.png
index 6a33ebf..8a648b8 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00001.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00002.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00002.9.png
index dafc250..03063d4 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00002.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00003.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00003.9.png
index 27df6ff..6159dec 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00003.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00004.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00004.9.png
index cb4121c..6f1c96c 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00004.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00005.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00005.9.png
index c5cbb75..2eaff46 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00005.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00006.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00006.9.png
index c69ef41..c4d9db8 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00006.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00007.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00007.9.png
index aff03d1..f276f16 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00007.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00008.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00008.9.png
index fb56ae6..cf9133e 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00008.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00009.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00009.9.png
index 88b9d28..8f1a6a8 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00009.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00010.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00010.9.png
index 8451958..5080c46 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00010.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00011.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00011.9.png
index 6f57654..5e39408 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00011.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00012.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00012.9.png
index 21bfc28..435ce21 100644
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00012.9.png
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00001.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00001.9.png
index c30cb5a..1eca9a9 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00001.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00002.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00002.9.png
index eaba558..5427211 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00002.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00003.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00003.9.png
index 17c18c9..43c06ab 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00003.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00004.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00004.9.png
index 0fce07a..6db3f1e 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00004.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00005.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00005.9.png
index c29b837..53b3a62 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00005.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00006.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00006.9.png
index ae56a41..7add520 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00006.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00007.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00007.9.png
index 85290ac..a4d57de 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00007.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00008.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00008.9.png
index 1e8513b..4b3a023 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00008.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00009.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00009.9.png
index 8810a12..a4caa65 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00009.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00010.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00010.9.png
index 717207f..2ab46c0 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00010.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00011.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00011.9.png
index db046f3..5c06e44 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00011.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00012.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00012.9.png
index c5c07a4..60d8c11 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00012.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00001.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00001.9.png
index c9bdf1f..b149e47 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00001.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00002.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00002.9.png
index 6bfd943..6a12a1f 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00002.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00003.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00003.9.png
index a1d3fbb..2803c7c 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00003.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00004.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00004.9.png
index 40c3a5b..032f6ea 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00004.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00005.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00005.9.png
index 26b8736..ea83c35 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00005.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00006.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00006.9.png
index 88c027e..2801f29 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00006.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00007.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00007.9.png
index 02567c6..66b89b3 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00007.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00008.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00008.9.png
index 037d3bf..1f8770c 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00008.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00009.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00009.9.png
index 0252769..0d6a95b 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00009.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00010.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00010.9.png
index 3ae501d..8e602db 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00010.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00011.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00011.9.png
index ecf2831..3143c1f 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00011.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00012.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00012.9.png
index 0877749..00fb83e 100644
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00012.9.png
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00001.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00001.9.png
index bc21279..786f493 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00001.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00002.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00002.9.png
index b57b592..c6e1ac1f 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00002.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00003.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00003.9.png
index 0fb9277..2a65baa 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00003.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00004.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00004.9.png
index 340722d..efce521 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00004.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00005.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00005.9.png
index 8554a76..5566524 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00005.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00006.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00006.9.png
index a05e335..ee676a6 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00006.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00007.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00007.9.png
index a5ded14..e0bb175 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00007.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00008.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00008.9.png
index 0300a49..de9eada 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00008.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00009.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00009.9.png
index 37dd7ce..3c59ad8 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00009.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00010.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00010.9.png
index 6bc549a..d524098 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00010.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00011.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00011.9.png
index b026d5d..7c08d71 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00011.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00012.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00012.9.png
index 89238dc..017c2e1 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00012.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00001.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00001.9.png
index 1d309fe..d3f2a9a 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00001.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00002.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00002.9.png
index 2e58fa9..cb75295a 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00002.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00003.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00003.9.png
index 2ebe7a7..445644e 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00003.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00004.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00004.9.png
index 04bab76..5819f90 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00004.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00005.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00005.9.png
index 3497e48..91cb90f 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00005.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00006.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00006.9.png
index 42333b4..cf6147c 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00006.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00007.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00007.9.png
index 732e175..75fca7c 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00007.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00008.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00008.9.png
index 12eddd8..b71a0b4 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00008.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00009.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00009.9.png
index 95cbc61..edb7671 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00009.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00010.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00010.9.png
index 105ec07..5e0be17 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00010.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00011.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00011.9.png
index fac253a..b727eda 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00011.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00012.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00012.9.png
index 1b8d11c..a3caefb 100644
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00012.9.png
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable/stat_notify_disabled_data.xml b/core/res/res/drawable/stat_notify_disabled_data.xml
index 2f6ffaf..9089d08 100644
--- a/core/res/res/drawable/stat_notify_disabled_data.xml
+++ b/core/res/res/drawable/stat_notify_disabled_data.xml
@@ -18,17 +18,7 @@
         android:height="24dp"
         android:viewportWidth="48.0"
         android:viewportHeight="48.0">
-
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M40.709,4.5l-6.604,7.337 0.0,16.601 6.604,6.604z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M32.305,13.838l-6.0629997,6.7370005 6.0629997,6.0629997z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M15.498,40.5l0.0,-7.9869995 -7.205,7.9869995z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M10.265,9.72l-2.5460005,2.545 9.971001,9.971 3.7139988,3.7140007 -4.105999,4.5619984 0.0,9.988001 6.6019993,0.0 0.0,-12.054001 1.8029995,1.8030014 0.0,10.250999 6.602001,0.0 0.0,-3.6479988 1.7999992,1.7999992 1.8479996,1.8479996 4.670002,4.669998 2.5459976,-2.5459976z"/>
+        android:pathData="M26.000000,4.100000l0.000000,6.100000c6.800000,1.000000 12.000000,6.800000 12.000000,13.800000c0.000000,1.800000 -0.400000,3.500000 -1.000000,5.100000l5.200000,3.100000c1.100000,-2.500000 1.800000,-5.200000 1.800000,-8.100000C44.000000,13.600000 36.099998,5.100000 26.000000,4.100000zM24.000000,38.000000c-7.700000,0.000000 -14.000000,-6.300000 -14.000000,-14.000000c0.000000,-7.100000 5.200000,-12.900000 12.000000,-13.800000L22.000000,4.100000C11.900000,5.100000 4.000000,13.600000 4.000000,24.000000c0.000000,11.000000 8.900000,20.000000 20.000000,20.000000c6.600000,0.000000 12.500000,-3.200000 16.100000,-8.200000l-5.200000,-3.100000C32.299999,36.000000 28.400000,38.000000 24.000000,38.000000z"/>
 </vector>
diff --git a/core/res/res/layout/alert_dialog_material.xml b/core/res/res/layout/alert_dialog_material.xml
index c3f9c76..5f9066a 100644
--- a/core/res/res/layout/alert_dialog_material.xml
+++ b/core/res/res/layout/alert_dialog_material.xml
@@ -31,9 +31,9 @@
             android:layout_height="wrap_content"
             android:orientation="horizontal"
             android:gravity="center_vertical|start"
-            android:paddingStart="16dip"
-            android:paddingEnd="16dip"
-            android:paddingTop="16dip"
+            android:paddingStart="@dimen/alert_dialog_padding_material"
+            android:paddingEnd="@dimen/alert_dialog_padding_material"
+            android:paddingTop="@dimen/alert_dialog_padding_material"
             android:paddingBottom="8dip">
             <ImageView android:id="@+id/icon"
                 android:layout_width="32dip"
@@ -66,10 +66,10 @@
                 style="?attr/textAppearanceMedium"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:paddingStart="16dip"
-                android:paddingEnd="16dip"
-                android:paddingTop="16dip"
-                android:paddingBottom="16dip" />
+                android:paddingStart="@dimen/alert_dialog_padding_material"
+                android:paddingEnd="@dimen/alert_dialog_padding_material"
+                android:paddingTop="@dimen/alert_dialog_padding_material"
+                android:paddingBottom="@dimen/alert_dialog_padding_material" />
         </ScrollView>
     </LinearLayout>
 
@@ -87,35 +87,33 @@
         style="?attr/buttonBarStyle"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:orientation="vertical"
-        android:gravity="end">
-        <LinearLayout
-            android:layout_width="match_parent"
+        android:layoutDirection="locale"
+        android:orientation="horizontal"
+        android:paddingStart="6dp"
+        android:paddingEnd="6dp"
+        android:paddingBottom="6dp">
+        <Button android:id="@+id/button3"
+            style="?attr/buttonBarNeutralButtonStyle"
+            android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layoutDirection="locale">
-            <Button android:id="@+id/button3"
-                style="?attr/buttonBarNeutralButtonStyle"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:maxLines="2"
-                android:minHeight="@dimen/alert_dialog_button_bar_height" />
-            <Space
-                android:layout_width="0dp"
-                android:layout_height="0dp"
-                android:layout_weight="1"
-                android:visibility="invisible" />
-            <Button android:id="@+id/button2"
-                style="?attr/buttonBarNegativeButtonStyle"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:maxLines="2"
-                android:minHeight="@dimen/alert_dialog_button_bar_height" />
-            <Button android:id="@+id/button1"
-                style="?attr/buttonBarPositiveButtonStyle"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:maxLines="2"
-                android:minHeight="@dimen/alert_dialog_button_bar_height" />
-        </LinearLayout>
-     </LinearLayout>
+            android:maxLines="2"
+            android:minHeight="@dimen/alert_dialog_button_bar_height" />
+        <Space
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_weight="1"
+            android:visibility="invisible" />
+        <Button android:id="@+id/button2"
+            style="?attr/buttonBarNegativeButtonStyle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:maxLines="2"
+            android:minHeight="@dimen/alert_dialog_button_bar_height" />
+        <Button android:id="@+id/button1"
+            style="?attr/buttonBarPositiveButtonStyle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:maxLines="2"
+            android:minHeight="@dimen/alert_dialog_button_bar_height" />
+    </LinearLayout>
 </LinearLayout>
diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml
index e3d8420..1c83644 100644
--- a/core/res/res/values-mcc311-mnc480/config.xml
+++ b/core/res/res/values-mcc311-mnc480/config.xml
@@ -38,4 +38,9 @@
         be disabled) but individual Features can be disabled using ImsConfig.setFeatureValue() -->
     <bool name="imsServiceAllowTurnOff">false</bool>
 
+    <!-- Flag specifying whether VoLTE & VT should be allowed on device: independent of the
+         carrier provisioning. If false: hard disabled. If true: then depends on carrier
+         provisioning, availability etc -->
+    <bool name="config_mobile_allow_volte_vt">false</bool>
+
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f702b95..a59a489 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1641,6 +1641,11 @@
         be disabled) but individual Features can be disabled using ImsConfig.setFeatureValue() -->
     <bool name="imsServiceAllowTurnOff">true</bool>
 
+    <!-- Flag specifying whether VoLTE & VT should be allowed on device: independent of the
+         carrier provisioning. If false: hard disabled. If true: then depends on carrier
+         provisioning, availability etc -->
+    <bool name="config_mobile_allow_volte_vt">true</bool>
+
     <bool name="config_networkSamplingWakesDevice">true</bool>
 
     <string-array translatable="false" name="config_cdma_home_system" />
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index a29a34c..d170fd4 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -394,4 +394,7 @@
      <dimen name="lock_pattern_dot_line_width">3dp</dimen>
      <dimen name="lock_pattern_dot_size">12dp</dimen>
      <dimen name="lock_pattern_dot_size_activated">28dp</dimen>
+
+     <dimen name="text_handle_min_size">40dp</dimen>
+
 </resources>
diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml
index e5a3c17..972ae5e 100644
--- a/core/res/res/values/dimens_material.xml
+++ b/core/res/res/values/dimens_material.xml
@@ -42,6 +42,8 @@
     <dimen name="text_size_headline_material">24sp</dimen>
     <dimen name="text_size_title_material">20sp</dimen>
     <dimen name="text_size_subhead_material">16sp</dimen>
+    <dimen name="text_size_title_material_toolbar">20dp</dimen>
+    <dimen name="text_size_subtitle_material_toolbar">16dp</dimen>
     <dimen name="text_size_menu_material">16sp</dimen>
     <dimen name="text_size_body_2_material">14sp</dimen>
     <dimen name="text_size_body_1_material">14sp</dimen>
@@ -71,4 +73,6 @@
 
     <!-- Default alpha value for disabled elements. -->
     <item name="disabled_alpha_material" format="float" type="dimen">0.26</item>
+
+    <dimen name="alert_dialog_padding_material">12dp</dimen>
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 27c8207..7ade51d 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2530,6 +2530,9 @@
   <public type="style" name="Widget.Material.Spinner.Form" />
   <public type="style" name="Widget.Material.Light.Spinner.Form" />
 
+  <public type="style" name="TextAppearance.Material.Widget.Toolbar.Title" />
+  <public type="style" name="TextAppearance.Material.Widget.Toolbar.Subtitle" />
+
   <public-padding type="string" name="l_resource_pad" end="0x01040030" />
 
   <public type="string" name="config_webSettingsDefaultTextEncoding" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index c68f355..2936e2b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2112,9 +2112,9 @@
     <string name="permdesc_use_sip">Allows the app to make and receive SIP calls.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permlab_bind_call_service">interact with in-call screen</string>
+    <string name="permlab_bind_incall_service">interact with in-call screen</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permdesc_bind_call_service">Allows the app to control when and how the user sees the in-call screen.</string>
+    <string name="permdesc_bind_incall_service">Allows the app to control when and how the user sees the in-call screen.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_bind_connection_service">interact with telephony services</string>
@@ -2122,6 +2122,11 @@
     <string name="permdesc_bind_connection_service">Allows the app to interact with telephony services to make/receive calls.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_control_incall_experience">provide an in-call user experience</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_control_incall_experience">Allows the app to provide an in-call user experience.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_readNetworkUsageHistory">read historical network usage</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_readNetworkUsageHistory">Allows the app to read historical network usage for specific networks and apps.</string>
@@ -3899,10 +3904,10 @@
     <!-- Description of an application permission that lets it control keyguard. -->
     <string name="permdesc_recovery">Allows an application to interact with the recovery system and system updates.</string>
 
-    <!-- Title of an application permission that lets it create media projection sessions. -->
-    <string name="permlab_createMediaProjection">Create media projection sessions</string>
-    <!-- Description of an application permission that lets it create media projection sessions. -->
-    <string name="permdesc_createMediaProjection">Allows an application to create media projection sessions. These sessions can provide applications the ability to capture display and audio contents. Should never be needed by normal apps.</string>
+    <!-- Title of an application permission that lets it manage media projection sessions. -->
+    <string name="permlab_manageMediaProjection">Manage media projection sessions</string>
+    <!-- Description of an application permission that lets it manage media projection sessions. -->
+    <string name="permdesc_manageMediaProjection">Allows an application to manage media projection sessions. These sessions can provide applications the ability to capture display and audio contents. Should never be needed by normal apps.</string>
 
     <!-- Title of an application permission that lets it read install sessions. -->
     <string name="permlab_readInstallSessions">Read install sessions</string>
@@ -4245,15 +4250,15 @@
     <string name="data_usage_warning_body">Touch to view usage and settings.</string>
 
     <!-- Notification title when 2G-3G data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
-    <string name="data_usage_3g_limit_title">2G-3G data is off</string>
+    <string name="data_usage_3g_limit_title">2G-3G data limit reached</string>
     <!-- Notification title when 4G data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
-    <string name="data_usage_4g_limit_title">4G data is off</string>
+    <string name="data_usage_4g_limit_title">4G data limit reached</string>
     <!-- Notification title when mobile data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
-    <string name="data_usage_mobile_limit_title">Cellular data is off</string>
+    <string name="data_usage_mobile_limit_title">Cellular data limit reached</string>
     <!-- Notification title when Wi-Fi data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
-    <string name="data_usage_wifi_limit_title">Wi-Fi data is off</string>
+    <string name="data_usage_wifi_limit_title">Wi-Fi data limit reached</string>
     <!-- Notification body when data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
-    <string name="data_usage_limit_body">Limit reached</string>
+    <string name="data_usage_limit_body">Data paused for rest of cycle</string>
 
     <!-- Notification title when 2G-3G data usage has exceeded limit threshold. [CHAR LIMIT=32] -->
     <string name="data_usage_3g_limit_snoozed_title">2G-3G data limit exceeded</string>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 298fea3..c8ea699 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -313,15 +313,38 @@
     </style>
 
     <style name="TextAppearance.Material.Widget.ActionMode"/>
-    <style name="TextAppearance.Material.Widget.ActionMode.Title" parent="TextAppearance.Material.Title" />
-    <style name="TextAppearance.Material.Widget.ActionMode.Title.Inverse" parent="TextAppearance.Material.Title.Inverse" />
-    <style name="TextAppearance.Material.Widget.ActionMode.Subtitle" parent="TextAppearance.Material.Subhead" />
-    <style name="TextAppearance.Material.Widget.ActionMode.Subtitle.Inverse" parent="TextAppearance.Material.Subhead.Inverse" />
-
-    <style name="TextAppearance.Material.Widget.ActionBar.Title" parent="TextAppearance.Material.Title" />
-    <style name="TextAppearance.Material.Widget.ActionBar.Title.Inverse" parent="TextAppearance.Material.Title.Inverse" />
-    <style name="TextAppearance.Material.Widget.ActionBar.Subtitle" parent="TextAppearance.Material.Subhead" />
-    <style name="TextAppearance.Material.Widget.ActionBar.Subtitle.Inverse" parent="TextAppearance.Material.Subhead.Inverse" />
+    <style name="TextAppearance.Material.Widget.ActionMode.Title"
+           parent="TextAppearance.Material.Title">
+        <item name="textSize">@dimen/text_size_title_material_toolbar</item>
+    </style>
+    <style name="TextAppearance.Material.Widget.ActionMode.Title.Inverse"
+           parent="TextAppearance.Material.Title.Inverse">
+        <item name="textSize">@dimen/text_size_title_material_toolbar</item>
+    </style>
+    <style name="TextAppearance.Material.Widget.ActionMode.Subtitle"
+           parent="TextAppearance.Material.Subhead">
+        <item name="textSize">@dimen/text_size_subtitle_material_toolbar</item>
+    </style>
+    <style name="TextAppearance.Material.Widget.ActionMode.Subtitle.Inverse"
+           parent="TextAppearance.Material.Subhead.Inverse">
+        <item name="textSize">@dimen/text_size_subtitle_material_toolbar</item>
+    </style>
+    <style name="TextAppearance.Material.Widget.ActionBar.Title"
+           parent="TextAppearance.Material.Title">
+        <item name="textSize">@dimen/text_size_title_material_toolbar</item>
+    </style>
+    <style name="TextAppearance.Material.Widget.ActionBar.Title.Inverse"
+           parent="TextAppearance.Material.Title.Inverse">
+        <item name="textSize">@dimen/text_size_title_material_toolbar</item>
+    </style>
+    <style name="TextAppearance.Material.Widget.ActionBar.Subtitle"
+           parent="TextAppearance.Material.Subhead">
+        <item name="textSize">@dimen/text_size_subtitle_material_toolbar</item>
+    </style>
+    <style name="TextAppearance.Material.Widget.ActionBar.Subtitle.Inverse"
+           parent="TextAppearance.Material.Subhead.Inverse">
+        <item name="textSize">@dimen/text_size_subtitle_material_toolbar</item>
+    </style>
 
     <style name="TextAppearance.Material.Widget.ActionBar.Menu" parent="TextAppearance.Material.Menu">
         <item name="textColor">?attr/actionMenuTextColor</item>
@@ -333,6 +356,11 @@
         <item name="textAllCaps">@bool/config_actionMenuItemAllCaps</item>
     </style>
 
+    <style name="TextAppearance.Material.Widget.Toolbar.Title"
+           parent="TextAppearance.Material.Widget.ActionBar.Title" />
+    <style name="TextAppearance.Material.Widget.Toolbar.Subtitle"
+           parent="TextAppearance.Material.Widget.ActionBar.Subtitle" />
+
     <style name="TextAppearance.Material.WindowTitle" parent="TextAppearance.Material.Title" />
     <style name="TextAppearance.Material.DialogWindowTitle" parent="TextAppearance.Material.Title" />
 
@@ -423,12 +451,15 @@
     <style name="Widget.Material" parent="Widget" />
 
     <!-- Bordered ink button -->
-    <style name="Widget.Material.Button" parent="Widget.Button">
+    <style name="Widget.Material.Button">
         <item name="background">@drawable/btn_default_material</item>
         <item name="textAppearance">?attr/textAppearanceButton</item>
         <item name="minHeight">48dip</item>
         <item name="minWidth">88dip</item>
         <item name="stateListAnimator">@anim/button_state_list_anim_material</item>
+        <item name="focusable">true</item>
+        <item name="clickable">true</item>
+        <item name="gravity">center_vertical|center_horizontal</item>
     </style>
 
     <!-- Small bordered ink button -->
@@ -471,9 +502,6 @@
 
     <style name="Widget.Material.ButtonBar.AlertDialog">
         <item name="background">@null</item>
-        <item name="paddingStart">16dp</item>
-        <item name="paddingEnd">16dp</item>
-        <item name="paddingBottom">16dp</item>
         <item name="minHeight">@dimen/alert_dialog_button_bar_height</item>
     </style>
 
@@ -759,6 +787,8 @@
 
     <style name="Widget.Material.Toolbar" parent="Widget.Toolbar">
         <item name="navigationButtonStyle">@style/Widget.Material.Toolbar.Button.Navigation</item>
+        <item name="titleTextAppearance">@style/TextAppearance.Material.Widget.Toolbar.Title</item>
+        <item name="subtitleTextAppearance">@style/TextAppearance.Material.Widget.Toolbar.Subtitle</item>
     </style>
 
     <style name="Widget.Material.Toolbar.Button.Navigation" parent="Widget.Toolbar.Button.Navigation">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 1cb7b17..11e292e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1956,6 +1956,7 @@
   <java-symbol type="attr" name="preferenceFragmentStyle" />
   <java-symbol type="bool" name="skipHoldBeforeMerge" />
   <java-symbol type="bool" name="imsServiceAllowTurnOff" />
+  <java-symbol type="bool" name="config_mobile_allow_volte_vt" />
   <java-symbol type="bool" name="useImsAlwaysForEmergencyCall" />
   <java-symbol type="attr" name="touchscreenBlocksFocus" />
   <java-symbol type="layout" name="resolver_list_with_default" />
@@ -1983,4 +1984,5 @@
   <java-symbol type="layout" name="select_dialog_singlechoice_material" />
   <java-symbol type="layout" name="select_dialog_multichoice_material" />
   <java-symbol type="array" name="no_ems_support_sim_operators" />
+  <java-symbol type="dimen" name="text_handle_min_size" />
 </resources>
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
index 116a31e..93b16e7 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
@@ -26,8 +26,8 @@
 import android.net.IpConfiguration.IpAssignment;
 import android.net.IpConfiguration.ProxySettings;
 import android.net.LinkAddress;
-import android.net.LinkProperties;
 import android.net.RouteInfo;
+import android.net.StaticIpConfiguration;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiConfiguration.AuthAlgorithm;
 import android.net.wifi.WifiConfiguration.KeyMgmt;
@@ -116,7 +116,7 @@
         boolean usercert = false;
         WifiConfiguration config = null;
         int securityType = NONE;
-        LinkProperties mLinkProperties = null;
+        StaticIpConfiguration mStaticIpConfiguration = null;
         InetAddress mInetAddr = null;
 
         @Override
@@ -153,7 +153,7 @@
                 usercert = true;
             }
             if (tagName.equalsIgnoreCase("ip")) {
-                mLinkProperties = new LinkProperties();
+                mStaticIpConfiguration = new StaticIpConfiguration();
                 ip = true;
             }
             if (tagName.equalsIgnoreCase("gateway")) {
@@ -173,15 +173,15 @@
         @Override
         public void endElement(String uri, String localName, String tagName) throws SAXException {
             if (tagName.equalsIgnoreCase("accesspoint")) {
-                if (mLinkProperties != null) {
+                if (mStaticIpConfiguration != null) {
                     config.setIpAssignment(IpAssignment.STATIC);
-                    config.setLinkProperties(mLinkProperties);
+                    config.setStaticIpConfiguration(mStaticIpConfiguration);
                 } else {
                     config.setIpAssignment(IpAssignment.DHCP);
                 }
                 config.setProxySettings(ProxySettings.NONE);
                 networks.add(config);
-                mLinkProperties = null;
+                mStaticIpConfiguration = null;
             }
         }
 
@@ -312,7 +312,7 @@
                     if (!InetAddress.isNumeric(gwAddr)) {
                         throw new SAXException();
                     }
-                    mLinkProperties.addRoute(new RouteInfo(InetAddress.getByName(gwAddr)));
+                    mStaticIpConfiguration.gateway = InetAddress.getByName(gwAddr);
                 } catch (UnknownHostException e) {
                     throw new SAXException();
                 }
@@ -324,7 +324,7 @@
                     if ((nwPrefixLength < 0) || (nwPrefixLength > 32)) {
                         throw new SAXException();
                     }
-                    mLinkProperties.addLinkAddress(new LinkAddress(mInetAddr, nwPrefixLength));
+                    mStaticIpConfiguration.ipAddress = new LinkAddress(mInetAddr, nwPrefixLength);
                 } catch (NumberFormatException e) {
                     throw new SAXException();
                 }
@@ -336,7 +336,7 @@
                     if (!InetAddress.isNumeric(dnsAddr)) {
                         throw new SAXException();
                     }
-                    mLinkProperties.addDnsServer(InetAddress.getByName(dnsAddr));
+                    mStaticIpConfiguration.dnsServers.add(InetAddress.getByName(dnsAddr));
                 } catch (UnknownHostException e) {
                     throw new SAXException();
                 }
@@ -348,7 +348,7 @@
                     if (!InetAddress.isNumeric(dnsAddr)) {
                         throw new SAXException();
                     }
-                    mLinkProperties.addDnsServer(InetAddress.getByName(dnsAddr));
+                    mStaticIpConfiguration.dnsServers.add(InetAddress.getByName(dnsAddr));
                 } catch (UnknownHostException e) {
                     throw new SAXException();
                 }
diff --git a/docs/html/google/play/billing/billing_reference.jd b/docs/html/google/play/billing/billing_reference.jd
index e168d70..4f5e65c 100644
--- a/docs/html/google/play/billing/billing_reference.jd
+++ b/docs/html/google/play/billing/billing_reference.jd
@@ -102,15 +102,28 @@
   </tr>
   <tr>
     <td>{@code type}</td>
-    <td>Value must be “inapp” for an in-app product or "subs" for 
+    <td>Value must be “inapp” for an in-app product or "subs" for
 subscriptions.</td>
   </tr>
   <tr>
     <td>{@code price}</td>
-    <td>Formatted price of the item, including its currency sign. The price 
+    <td>Formatted price of the item, including its currency sign. The price
 does not include tax.</td>
   </tr>
   <tr>
+    <td>{@code price_amount_micros}</td>
+    <td>Price in micro-units, where 1,000,000 micro-units equal one unit of the
+    currency. For example, if {@code price} is {@code "€7.99"}, {@code
+    price_amount_micros} is {@code "7990000"}.</td>
+  </tr>
+  <tr>
+    <td>{@code price_currency_code}</td>
+    <td><a href="http://en.wikipedia.org/wiki/ISO_4217#Active_codes">ISO 4217
+    currency code</a> for {@code price}. For example, if {@code price} is
+    specified in British pounds sterling, {@code price_currency_code} is {@code
+    "GBP"}.</td>
+  </tr>
+  <tr>
     <td>{@code title}</td>
     <td>Title of the product.</td>
   </tr>
diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java
index 3177023..4bf0b71 100644
--- a/graphics/java/android/graphics/Outline.java
+++ b/graphics/java/android/graphics/Outline.java
@@ -18,15 +18,15 @@
 
 import android.annotation.NonNull;
 import android.graphics.drawable.Drawable;
-import android.view.View;
 
 /**
  * Defines a simple shape, used for bounding graphical regions.
  * <p>
- * Can be used with a View, or computed by a Drawable, to drive the shape of shadows cast by a
- * View, or to clip the contents of the View.
+ * Can be computed for a View, or computed by a Drawable, to drive the shape of
+ * shadows cast by a View, or to clip the contents of the View.
  *
- * @see View#setOutline(Outline)
+ * @see android.view.ViewOutlineProvider
+ * @see android.view.View#setOutlineProvider(android.view.ViewOutlineProvider)
  * @see Drawable#getOutline(Outline)
  */
 public final class Outline {
@@ -79,21 +79,27 @@
 
     /**
      * Returns whether the outline can be used to clip a View.
+     * <p>
+     * Currently, only Outlines that can be represented as a rectangle, circle,
+     * or round rect support clipping.
      *
-     * Currently, only outlines that can be represented as a rectangle, circle, or round rect
-     * support clipping.
-     *
-     * @see {@link View#setClipToOutline(boolean)}
+     * @see {@link android.view.View#setClipToOutline(boolean)}
      */
     public boolean canClip() {
         return !isEmpty() && mRect != null;
     }
 
     /**
-     * Sets the alpha represented by the Outline.
-     *
-     * Content producing a fully opaque (alpha = 1.0f) outline is assumed by the drawing system
-     * to fully cover content beneath it, meaning content beneath may be optimized away.
+     * Sets the alpha represented by the Outline - the degree to which the
+     * producer is guaranteed to be opaque over the Outline's shape.
+     * <p>
+     * An alpha value of <code>0.0f</code> either represents completely
+     * transparent content, or content that isn't guaranteed to fill the shape
+     * it publishes.
+     * <p>
+     * Content producing a fully opaque (alpha = <code>1.0f</code>) outline is
+     * assumed by the drawing system to fully cover content beneath it,
+     * meaning content beneath may be optimized away.
      */
     public void setAlpha(float alpha) {
         mAlpha = alpha;
@@ -130,7 +136,8 @@
     }
 
     /**
-     * Sets the Outline to the rounded rect defined by the input rect, and corner radius.
+     * Sets the Outline to the rounded rect defined by the input rect, and
+     * corner radius.
      */
     public void setRect(int left, int top, int right, int bottom) {
         setRoundRect(left, top, right, bottom, 0.0f);
@@ -145,7 +152,7 @@
 
     /**
      * Sets the Outline to the rounded rect defined by the input rect, and corner radius.
-     *
+     * <p>
      * Passing a zero radius is equivalent to calling {@link #setRect(int, int, int, int)}
      */
     public void setRoundRect(int left, int top, int right, int bottom, float radius) {
@@ -196,7 +203,8 @@
     }
 
     /**
-     * Sets the Constructs an Outline from a {@link android.graphics.Path#isConvex() convex path}.
+     * Sets the Constructs an Outline from a
+     * {@link android.graphics.Path#isConvex() convex path}.
      */
     public void setConvexPath(@NonNull Path convexPath) {
         if (convexPath.isEmpty()) {
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 1c76d9c..652fe64 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1109,9 +1109,16 @@
      * This draws a shadow layer below the main layer, with the specified
      * offset and color, and blur radius. If radius is 0, then the shadow
      * layer is removed.
+     * <p>
+     * Can be used to create a blurred shadow underneath text. Support for use
+     * with other drawing operations is constrained to the software rendering
+     * pipeline.
+     * <p>
+     * The alpha of the shadow will be the paint's alpha if the shadow color is
+     * opaque, or the alpha from the shadow color if not.
      */
-    public void setShadowLayer(float radius, float dx, float dy, int color) {
-      native_setShadowLayer(mNativePaint, radius, dx, dy, color);
+    public void setShadowLayer(float radius, float dx, float dy, int shadowColor) {
+      native_setShadowLayer(mNativePaint, radius, dx, dy, shadowColor);
     }
 
     /**
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index a383aab..29b9141 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -820,7 +820,7 @@
 
     @Override
     public int getOpacity() {
-        return (mAlpha == 255 && mGradientState.mOpaque) ?
+        return (mAlpha == 255 && mGradientState.mOpaqueOverBounds) ?
                 PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT;
     }
 
@@ -1413,7 +1413,8 @@
     public void getOutline(Outline outline) {
         final GradientState st = mGradientState;
         final Rect bounds = getBounds();
-        outline.setAlpha(mAlpha / 255.0f);
+        // only report non-zero alpha if shape being drawn is opaque
+        outline.setAlpha(st.mOpaqueOverShape ? (mAlpha / 255.0f) : 0.0f);
 
         switch (st.mShape) {
             case RECTANGLE:
@@ -1492,7 +1493,8 @@
         private int mGradientRadiusType = RADIUS_TYPE_PIXELS;
         private boolean mUseLevel;
         private boolean mUseLevelForShape;
-        private boolean mOpaque;
+        private boolean mOpaqueOverBounds;
+        private boolean mOpaqueOverShape;
 
         int[] mThemeAttrs;
         int[] mAttrSize;
@@ -1544,7 +1546,7 @@
             mGradientRadiusType = state.mGradientRadiusType;
             mUseLevel = state.mUseLevel;
             mUseLevelForShape = state.mUseLevelForShape;
-            mOpaque = state.mOpaque;
+            mOpaqueOverBounds = state.mOpaqueOverBounds;
             mThemeAttrs = state.mThemeAttrs;
             mAttrSize = state.mAttrSize;
             mAttrGradient = state.mAttrGradient;
@@ -1606,40 +1608,36 @@
         }
 
         private void computeOpacity() {
-            if (mShape != RECTANGLE) {
-                mOpaque = false;
-                return;
-            }
+            mOpaqueOverBounds = false;
+            mOpaqueOverShape = false;
 
-            if (mRadius > 0 || mRadiusArray != null) {
-                mOpaque = false;
-                return;
-            }
-
+            // First test opacity of all colors
             if (mStrokeWidth > 0) {
                 if (mStrokeColorStateList != null) {
                     if (!mStrokeColorStateList.isOpaque()) {
-                        mOpaque = false;
                         return;
                     }
                 }
             }
 
             if (mColorStateList != null && !mColorStateList.isOpaque()) {
-                mOpaque = false;
                 return;
             }
 
             if (mColors != null) {
                 for (int i = 0; i < mColors.length; i++) {
                     if (!isOpaque(mColors[i])) {
-                        mOpaque = false;
                         return;
                     }
                 }
             }
 
-            mOpaque = true;
+            // Colors are opaque, so opaqueOverShape=true,
+            mOpaqueOverShape = true;
+            // and opaqueOverBounds=true if shape fills bounds
+            mOpaqueOverBounds = mShape == RECTANGLE
+                    && mRadius <= 0
+                    && mRadiusArray == null;
         }
 
         private static boolean isOpaque(int color) {
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 0aa1b0d..c185a9e 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -446,19 +446,8 @@
                         ": <nine-patch> requires a valid 9-patch source image");
             }
 
-            // Hey, now might be a good time to actually load optical bounds!
             bitmap.getOpticalInsets(opticalInsets);
 
-            // Sanity check for valid padding when we have optical insets.
-            if (padding.left < opticalInsets.left) {
-                padding.left = opticalInsets.left;
-                padding.right = opticalInsets.right;
-            }
-            if (padding.top < opticalInsets.top) {
-                padding.top = opticalInsets.top;
-                padding.bottom = opticalInsets.bottom;
-            }
-
             state.mNinePatch = new NinePatch(bitmap, bitmap.getNinePatchChunk());
             state.mPadding = padding;
             state.mOpticalInsets = Insets.of(opticalInsets);
@@ -626,21 +615,6 @@
             mOpticalInsets = Insets.of(opticalInsets);
             mDither = dither;
             mAutoMirrored = autoMirror;
-
-            // Sanity check for valid padding when we have optical insets.
-            if (opticalInsets != null && !opticalInsets.isEmpty()) {
-                if (mPadding == null) {
-                    mPadding = new Rect();
-                }
-                if (mPadding.left < opticalInsets.left) {
-                    mPadding.left = opticalInsets.left;
-                    mPadding.right = opticalInsets.right;
-                }
-                if (mPadding.top < opticalInsets.top) {
-                    mPadding.top = opticalInsets.top;
-                    mPadding.bottom = opticalInsets.bottom;
-                }
-            }
         }
 
         // Copy constructor
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index c6d3db7..5f533a7 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -208,6 +208,8 @@
         // ensure that local bounds cover mapped bounds
         if (!state.mMatrix.isSimple()) return false;
 
+        if (state.mRoundRectClipState) return false;
+
         // check state/paint for transparency
         if (mPaint) {
             if (mPaint->getShader() && !mPaint->getShader()->isOpaque()) {
@@ -999,6 +1001,8 @@
 public:
     DrawStrokableOp(float left, float top, float right, float bottom, const SkPaint* paint)
             : DrawBoundedOp(left, top, right, bottom, paint) {};
+    DrawStrokableOp(const Rect& localBounds, const SkPaint* paint)
+            : DrawBoundedOp(localBounds, paint) {};
 
     virtual bool getLocalBounds(Rect& localBounds) {
         localBounds.set(mLocalBounds);
@@ -1337,11 +1341,11 @@
     const float* mPositions;
 };
 
-class DrawTextOp : public DrawBoundedOp {
+class DrawTextOp : public DrawStrokableOp {
 public:
     DrawTextOp(const char* text, int bytesCount, int count, float x, float y,
             const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds)
-            : DrawBoundedOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count),
+            : DrawStrokableOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count),
             mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) {
         mPrecacheTransform = SkMatrix::InvalidMatrix();
     }
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 94162fc..9a9c544 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -376,7 +376,7 @@
         float x, float y, const float* positions, const SkPaint* paint,
         float totalAdvance, const Rect& bounds, DrawOpMode drawOpMode) {
 
-    if (!text || count <= 0) return DrawGlInfo::kStatusDone;
+    if (!text || count <= 0 || paintWillNotDrawText(*paint)) return DrawGlInfo::kStatusDone;
 
     text = refText(text, bytesCount);
     positions = refBuffer<float>(positions, count * 2);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 721ab3d..bbf0551 100755
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2518,8 +2518,9 @@
 
 status_t OpenGLRenderer::drawRoundRect(float left, float top, float right, float bottom,
         float rx, float ry, const SkPaint* p) {
-    if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
-            (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
+    if (currentSnapshot()->isIgnored()
+            || quickRejectSetupScissor(left, top, right, bottom, p)
+            || paintWillNotDraw(*p)) {
         return DrawGlInfo::kStatusDone;
     }
 
@@ -2536,9 +2537,9 @@
 }
 
 status_t OpenGLRenderer::drawCircle(float x, float y, float radius, const SkPaint* p) {
-    if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(x - radius, y - radius,
-            x + radius, y + radius, p) ||
-            (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
+    if (currentSnapshot()->isIgnored()
+            || quickRejectSetupScissor(x - radius, y - radius, x + radius, y + radius, p)
+            || paintWillNotDraw(*p)) {
         return DrawGlInfo::kStatusDone;
     }
     if (p->getPathEffect() != 0) {
@@ -2558,8 +2559,9 @@
 
 status_t OpenGLRenderer::drawOval(float left, float top, float right, float bottom,
         const SkPaint* p) {
-    if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
-            (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
+    if (currentSnapshot()->isIgnored()
+            || quickRejectSetupScissor(left, top, right, bottom, p)
+            || paintWillNotDraw(*p)) {
         return DrawGlInfo::kStatusDone;
     }
 
@@ -2580,8 +2582,9 @@
 
 status_t OpenGLRenderer::drawArc(float left, float top, float right, float bottom,
         float startAngle, float sweepAngle, bool useCenter, const SkPaint* p) {
-    if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
-            (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
+    if (currentSnapshot()->isIgnored()
+            || quickRejectSetupScissor(left, top, right, bottom, p)
+            || paintWillNotDraw(*p)) {
         return DrawGlInfo::kStatusDone;
     }
 
@@ -2614,8 +2617,9 @@
 
 status_t OpenGLRenderer::drawRect(float left, float top, float right, float bottom,
         const SkPaint* p) {
-    if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
-            (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
+    if (currentSnapshot()->isIgnored()
+            || quickRejectSetupScissor(left, top, right, bottom, p)
+            || paintWillNotDraw(*p)) {
         return DrawGlInfo::kStatusDone;
     }
 
diff --git a/libs/hwui/Renderer.h b/libs/hwui/Renderer.h
index f5cd266..6d4bb4a 100644
--- a/libs/hwui/Renderer.h
+++ b/libs/hwui/Renderer.h
@@ -67,6 +67,18 @@
         return resultMode;
     }
 
+    // TODO: move to a method on android:Paint
+    static inline bool paintWillNotDraw(const SkPaint& paint) {
+        return paint.getAlpha() == 0
+                && getXfermode(paint.getXfermode()) != SkXfermode::kClear_Mode;
+    }
+
+    // TODO: move to a method on android:Paint
+    static inline bool paintWillNotDrawText(const SkPaint& paint) {
+        return paint.getAlpha() == 0
+                && paint.getLooper() == NULL
+                && getXfermode(paint.getXfermode()) == SkXfermode::kSrcOver_Mode;
+    }
 // ----------------------------------------------------------------------------
 // Frame state operations
 // ----------------------------------------------------------------------------
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 6a76a71..e69c456 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2332,18 +2332,21 @@
     }
 
     /**
-     * Registers a {@link RemoteController} instance for it to receive media metadata updates
-     * and playback state information from applications using {@link RemoteControlClient}, and
-     * control their playback.
-     * <p>Registration requires the {@link OnClientUpdateListener} listener to be one of the
-     * enabled notification listeners (see
+     * Registers a {@link RemoteController} instance for it to receive media
+     * metadata updates and playback state information from applications using
+     * {@link RemoteControlClient}, and control their playback.
+     * <p>
+     * Registration requires the {@link OnClientUpdateListener} listener to be
+     * one of the enabled notification listeners (see
      * {@link android.service.notification.NotificationListenerService}).
+     *
      * @param rctlr the object to register.
-     * @return true if the {@link RemoteController} was successfully registered, false if an
-     *     error occurred, due to an internal system error, or insufficient permissions.
+     * @return true if the {@link RemoteController} was successfully registered,
+     *         false if an error occurred, due to an internal system error, or
+     *         insufficient permissions.
      * @deprecated Use
-     * {@link MediaSessionManager#addActiveSessionsListener(android.media.session.MediaSessionManager.SessionListener, ComponentName)}
-     * and {@link MediaController} instead.
+     *             {@link MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, ComponentName)}
+     *             and {@link MediaController} instead.
      */
     @Deprecated
     public boolean registerRemoteController(RemoteController rctlr) {
@@ -2355,12 +2358,14 @@
     }
 
     /**
-     * Unregisters a {@link RemoteController}, causing it to no longer receive media metadata and
-     * playback state information, and no longer be capable of controlling playback.
+     * Unregisters a {@link RemoteController}, causing it to no longer receive
+     * media metadata and playback state information, and no longer be capable
+     * of controlling playback.
+     *
      * @param rctlr the object to unregister.
      * @deprecated Use
-     * {@link MediaSessionManager#removeActiveSessionsListener(android.media.session.MediaSessionManager.SessionListener)}
-     * instead.
+     *             {@link MediaSessionManager#removeOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener)}
+     *             instead.
      */
     @Deprecated
     public void unregisterRemoteController(RemoteController rctlr) {
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 2fa0c93..7c3b4fc 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1049,8 +1049,17 @@
     private void setDataSource(String path, String[] keys, String[] values)
             throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
         final Uri uri = Uri.parse(path);
-        if ("file".equals(uri.getScheme())) {
+        final String scheme = uri.getScheme();
+        if ("file".equals(scheme)) {
             path = uri.getPath();
+        } else if (scheme != null) {
+            // handle non-file sources
+            nativeSetDataSource(
+                MediaHTTPService.createHttpServiceBinderIfNecessary(path),
+                path,
+                keys,
+                values);
+            return;
         }
 
         final File file = new File(path);
@@ -1060,20 +1069,10 @@
             setDataSource(fd);
             is.close();
         } else {
-            _setDataSource(path, keys, values);
+            throw new IOException("setDataSource failed.");
         }
     }
 
-    private void _setDataSource(
-        String path, String[] keys, String[] values)
-        throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
-        nativeSetDataSource(
-                MediaHTTPService.createHttpServiceBinderIfNecessary(path),
-                path,
-                keys,
-                values);
-    }
-
     private native void nativeSetDataSource(
         IBinder httpServiceBinder, String path, String[] keys, String[] values)
         throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
diff --git a/media/java/android/media/RemoteController.java b/media/java/android/media/RemoteController.java
index adc8391..f378cef 100644
--- a/media/java/android/media/RemoteController.java
+++ b/media/java/android/media/RemoteController.java
@@ -74,7 +74,7 @@
     private MetadataEditor mMetadataEditor;
 
     private MediaSessionManager mSessionManager;
-    private MediaSessionManager.SessionListener mSessionListener;
+    private MediaSessionManager.OnActiveSessionsChangedListener mSessionListener;
     private MediaController.Callback mSessionCb = new MediaControllerCallback();
 
     /**
@@ -140,7 +140,7 @@
         mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
         mSessionManager = (MediaSessionManager) context
                 .getSystemService(Context.MEDIA_SESSION_SERVICE);
-        mSessionListener = new TopTransportSessionListener(context);
+        mSessionListener = new TopTransportSessionListener();
 
         if (ActivityManager.isLowRamDeviceStatic()) {
             mMaxBitmapDimension = MAX_BITMAP_DIMENSION;
@@ -710,11 +710,8 @@
      * Listens for changes to the active session stack and replaces the
      * currently tracked session if it has changed.
      */
-    private class TopTransportSessionListener extends MediaSessionManager.SessionListener {
-
-        public TopTransportSessionListener(Context context) {
-            super(context);
-        }
+    private class TopTransportSessionListener implements
+            MediaSessionManager.OnActiveSessionsChangedListener {
 
         @Override
         public void onActiveSessionsChanged(List<MediaController> controllers) {
@@ -792,7 +789,7 @@
     void startListeningToSessions() {
         final ComponentName listenerComponent = new ComponentName(mContext,
                 mOnClientUpdateListener.getClass());
-        mSessionManager.addActiveSessionsListener(mSessionListener, listenerComponent,
+        mSessionManager.addOnActiveSessionsChangedListener(mSessionListener, listenerComponent,
                 UserHandle.myUserId(), null);
         mSessionListener.onActiveSessionsChanged(mSessionManager
                 .getActiveSessions(listenerComponent));
@@ -806,7 +803,7 @@
      * @hide
      */
     void stopListeningToSessions() {
-        mSessionManager.removeActiveSessionsListener(mSessionListener);
+        mSessionManager.removeOnActiveSessionsChangedListener(mSessionListener);
         if (DEBUG) {
             Log.d(TAG, "Unregistered session listener for user "
                     + UserHandle.myUserId());
diff --git a/media/java/android/media/projection/IMediaProjectionManager.aidl b/media/java/android/media/projection/IMediaProjectionManager.aidl
index 6ed803a..7e10c51 100644
--- a/media/java/android/media/projection/IMediaProjectionManager.aidl
+++ b/media/java/android/media/projection/IMediaProjectionManager.aidl
@@ -17,6 +17,9 @@
 package android.media.projection;
 
 import android.media.projection.IMediaProjection;
+import android.media.projection.IMediaProjectionCallback;
+import android.media.projection.IMediaProjectionWatcherCallback;
+import android.media.projection.MediaProjectionInfo;
 import android.os.IBinder;
 
 /** {@hide} */
@@ -25,4 +28,8 @@
     IMediaProjection createProjection(int uid, String packageName, int type,
             boolean permanentGrant);
     boolean isValidMediaProjection(IMediaProjection projection);
+    MediaProjectionInfo getActiveProjectionInfo();
+    void stopActiveProjection();
+    void addCallback(IMediaProjectionWatcherCallback callback);
+    void removeCallback(IMediaProjectionWatcherCallback callback);
 }
diff --git a/media/java/android/media/projection/IMediaProjectionWatcherCallback.aidl b/media/java/android/media/projection/IMediaProjectionWatcherCallback.aidl
new file mode 100644
index 0000000..2231ce1
--- /dev/null
+++ b/media/java/android/media/projection/IMediaProjectionWatcherCallback.aidl
@@ -0,0 +1,25 @@
+/*
+ * 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.projection;
+
+import android.media.projection.MediaProjectionInfo;
+
+/** {@hide} */
+oneway interface IMediaProjectionWatcherCallback {
+    void onStart(in MediaProjectionInfo info);
+    void onStop(in MediaProjectionInfo info);
+}
diff --git a/media/java/android/media/projection/MediaProjectionInfo.aidl b/media/java/android/media/projection/MediaProjectionInfo.aidl
new file mode 100644
index 0000000..3c8f9b6
--- /dev/null
+++ b/media/java/android/media/projection/MediaProjectionInfo.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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.projection;
+
+parcelable MediaProjectionInfo;
diff --git a/media/java/android/media/projection/MediaProjectionInfo.java b/media/java/android/media/projection/MediaProjectionInfo.java
new file mode 100644
index 0000000..7ebc31f
--- /dev/null
+++ b/media/java/android/media/projection/MediaProjectionInfo.java
@@ -0,0 +1,76 @@
+/*
+ * 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.projection;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.UserHandle;
+
+/** @hide */
+public final class MediaProjectionInfo implements Parcelable {
+    private final String mPackageName;
+    private final UserHandle mUserHandle;
+
+    public MediaProjectionInfo(String packageName, UserHandle handle) {
+        mPackageName = packageName;
+        mUserHandle = handle;
+    }
+
+    public MediaProjectionInfo(Parcel in) {
+        mPackageName = in.readString();
+        mUserHandle = UserHandle.readFromParcel(in);
+    }
+
+    public String getPackageName() {
+        return mPackageName;
+    }
+
+    public UserHandle getUserHandle() {
+        return mUserHandle;
+    }
+
+    @Override
+    public String toString() {
+        return "MediaProjectionInfo{mPackageName="
+            + mPackageName + ", mUserHandle="
+            + mUserHandle + "}";
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(mPackageName);
+        UserHandle.writeToParcel(mUserHandle, out);
+    }
+
+    public static final Parcelable.Creator<MediaProjectionInfo> CREATOR =
+            new Parcelable.Creator<MediaProjectionInfo>() {
+        @Override
+        public MediaProjectionInfo createFromParcel(Parcel in) {
+            return new MediaProjectionInfo (in);
+        }
+
+        @Override
+        public MediaProjectionInfo[] newArray(int size) {
+            return new MediaProjectionInfo[size];
+        }
+    };
+}
diff --git a/media/java/android/media/projection/MediaProjectionManager.java b/media/java/android/media/projection/MediaProjectionManager.java
index aac8cf9..50d66c6 100644
--- a/media/java/android/media/projection/MediaProjectionManager.java
+++ b/media/java/android/media/projection/MediaProjectionManager.java
@@ -17,12 +17,20 @@
 package android.media.projection;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
 import android.media.projection.IMediaProjection;
 import android.os.Binder;
+import android.os.Handler;
 import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import java.util.Map;
 
 /**
  * Manages the retrieval of certain types of {@link MediaProjection} tokens.
@@ -35,6 +43,7 @@
  * </p>
  */
 public final class MediaProjectionManager {
+    private static final String TAG = "MediaProjectionManager";
     /** @hide */
     public static final String EXTRA_APP_TOKEN = "android.media.projection.extra.EXTRA_APP_TOKEN";
     /** @hide */
@@ -49,10 +58,15 @@
     public static final int TYPE_PRESENTATION = 2;
 
     private Context mContext;
+    private Map<Callback, CallbackDelegate> mCallbacks;
+    private IMediaProjectionManager mService;
 
     /** @hide */
     public MediaProjectionManager(Context context) {
         mContext = context;
+        IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE);
+        mService = IMediaProjectionManager.Stub.asInterface(b);
+        mCallbacks = new ArrayMap<>();
     }
 
     /**
@@ -88,4 +102,105 @@
         }
         return new MediaProjection(mContext, IMediaProjection.Stub.asInterface(projection));
     }
+
+    /**
+     * Get the {@link MediaProjectionInfo} for the active {@link MediaProjection}.
+     * @hide
+     */
+    public MediaProjectionInfo getActiveProjectionInfo() {
+        try {
+            return mService.getActiveProjectionInfo();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Unable to get the active projection info", e);
+        }
+        return null;
+    }
+
+    /**
+     * Stop the current projection if there is one.
+     * @hide
+     */
+    public void stopActiveProjection() {
+        try {
+            mService.stopActiveProjection();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Unable to stop the currently active media projection", e);
+        }
+    }
+
+    /**
+     * Add a callback to monitor all of the {@link MediaProjection}s activity.
+     * Not for use by regular applications, must have the MANAGE_MEDIA_PROJECTION permission.
+     * @hide
+     */
+    public void addCallback(@NonNull Callback callback, @Nullable Handler handler) {
+        if (callback == null) {
+            throw new IllegalArgumentException("callback must not be null");
+        }
+        CallbackDelegate delegate = new CallbackDelegate(callback, handler);
+        mCallbacks.put(callback, delegate);
+        try {
+            mService.addCallback(delegate);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Unable to add callbacks to MediaProjection service", e);
+        }
+    }
+
+    /**
+     * Remove a MediaProjection monitoring callback.
+     * @hide
+     */
+    public void removeCallback(@NonNull Callback callback) {
+        if (callback == null) {
+            throw new IllegalArgumentException("callback must not be null");
+        }
+        CallbackDelegate delegate = mCallbacks.remove(callback);
+        try {
+            if (delegate != null) {
+                mService.removeCallback(delegate);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Unable to add callbacks to MediaProjection service", e);
+        }
+    }
+
+    /** @hide */
+    public static abstract class Callback {
+        public abstract void onStart(MediaProjectionInfo info);
+        public abstract void onStop(MediaProjectionInfo info);
+    }
+
+    /** @hide */
+    private final static class CallbackDelegate extends IMediaProjectionWatcherCallback.Stub {
+        private Callback mCallback;
+        private Handler mHandler;
+
+        public CallbackDelegate(Callback callback, Handler handler) {
+            mCallback = callback;
+            if (handler == null) {
+                handler = new Handler();
+            }
+            mHandler = handler;
+        }
+
+        @Override
+        public void onStart(final MediaProjectionInfo info) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mCallback.onStart(info);
+                }
+            });
+        }
+
+        @Override
+        public void onStop(final MediaProjectionInfo info) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mCallback.onStop(info);
+                }
+            });
+        }
+    }
 }
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 63c85f8..074e5ad 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -185,7 +185,7 @@
      *
      * @return The current play queue or null.
      */
-    public @Nullable List<MediaSession.Track> getQueue() {
+    public @Nullable List<MediaSession.Item> getQueue() {
         try {
             ParceledListSlice queue = mSessionBinder.getQueue();
             if (queue != null) {
@@ -259,18 +259,18 @@
     }
 
     /**
-     * Get the current volume info for this session.
+     * Get the current audio info for this session.
      *
-     * @return The current volume info or null.
+     * @return The current audio info or null.
      */
-    public @Nullable VolumeInfo getVolumeInfo() {
+    public @Nullable AudioInfo getAudioInfo() {
         try {
             ParcelableVolumeInfo result = mSessionBinder.getVolumeAttributes();
-            return new VolumeInfo(result.volumeType, result.audioAttrs, result.controlType,
+            return new AudioInfo(result.volumeType, result.audioAttrs, result.controlType,
                     result.maxVolume, result.currentVolume);
 
         } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling getVolumeInfo.", e);
+            Log.wtf(TAG, "Error calling getAudioInfo.", e);
         }
         return null;
     }
@@ -305,7 +305,7 @@
      * {@link VolumeProvider#VOLUME_CONTROL_ABSOLUTE}. The flags in
      * {@link AudioManager} may be used to affect the handling.
      *
-     * @see #getVolumeInfo()
+     * @see #getAudioInfo()
      * @param value The value to set it to, between 0 and the reported max.
      * @param flags Any flags to pass with the command.
      */
@@ -326,7 +326,7 @@
      * {@link VolumeProvider#VOLUME_CONTROL_ABSOLUTE}. The flags in
      * {@link AudioManager} may be used to affect the handling.
      *
-     * @see #getVolumeInfo()
+     * @see #getAudioInfo()
      * @param direction The direction to adjust the volume in.
      * @param flags Any flags to pass with the command.
      */
@@ -544,13 +544,14 @@
         }
 
         /**
-         * Override to handle changes to tracks in the queue.
+         * Override to handle changes to items in the queue.
          *
-         * @param queue A list of tracks in the current play queue. It should include the currently
-         *              playing track as well as previous and upcoming tracks if applicable.
-         * @see MediaSession.Track
+         * @param queue A list of items in the current play queue. It should
+         *            include the currently playing item as well as previous and
+         *            upcoming items if applicable.
+         * @see MediaSession.Item
          */
-        public void onQueueChanged(@Nullable List<MediaSession.Track> queue) {
+        public void onQueueChanged(@Nullable List<MediaSession.Item> queue) {
         }
 
         /**
@@ -572,11 +573,11 @@
         }
 
         /**
-         * Override to handle changes to the volume info.
+         * Override to handle changes to the audio info.
          *
-         * @param info The current volume info for this session.
+         * @param info The current audio info for this session.
          */
-        public void onVolumeInfoChanged(VolumeInfo info) {
+        public void onAudioInfoChanged(AudioInfo info) {
         }
     }
 
@@ -638,14 +639,14 @@
         }
 
         /**
-         * Play a track with a specific id in the play queue.
-         * If you specify an id that is not in the play queue, the behavior is undefined.
+         * Play an item with a specific id in the play queue. If you specify an
+         * id that is not in the play queue, the behavior is undefined.
          */
-        public void skipToTrack(long id) {
+        public void skipToItem(long id) {
             try {
                 mSessionBinder.skipToTrack(id);
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling skipToTrack(" + id + ").", e);
+                Log.wtf(TAG, "Error calling skipToItem(" + id + ").", e);
             }
         }
 
@@ -784,9 +785,9 @@
     }
 
     /**
-     * Holds information about the way volume is handled for this session.
+     * Holds information about the way audio is handled for this session.
      */
-    public static final class VolumeInfo {
+    public static final class AudioInfo {
         private final int mVolumeType;
         private final int mVolumeControl;
         private final int mMaxVolume;
@@ -796,7 +797,7 @@
         /**
          * @hide
          */
-        public VolumeInfo(int type, AudioAttributes attrs, int control, int max, int current) {
+        public AudioInfo(int type, AudioAttributes attrs, int control, int max, int current) {
             mVolumeType = type;
             mAudioAttrs = attrs;
             mVolumeControl = control;
@@ -904,7 +905,7 @@
 
         @Override
         public void onQueueChanged(ParceledListSlice parceledQueue) {
-            List<MediaSession.Track> queue = parceledQueue.getList();
+            List<MediaSession.Item> queue = parceledQueue.getList();
             MediaController controller = mController.get();
             if (controller != null) {
                 controller.postMessage(MSG_UPDATE_QUEUE, queue, null);
@@ -931,7 +932,7 @@
         public void onVolumeInfoChanged(ParcelableVolumeInfo pvi) {
             MediaController controller = mController.get();
             if (controller != null) {
-                VolumeInfo info = new VolumeInfo(pvi.volumeType, pvi.audioAttrs, pvi.controlType,
+                AudioInfo info = new AudioInfo(pvi.volumeType, pvi.audioAttrs, pvi.controlType,
                         pvi.maxVolume, pvi.currentVolume);
                 controller.postMessage(MSG_UPDATE_VOLUME, info, null);
             }
@@ -960,7 +961,7 @@
                     mCallback.onMetadataChanged((MediaMetadata) msg.obj);
                     break;
                 case MSG_UPDATE_QUEUE:
-                    mCallback.onQueueChanged((List<MediaSession.Track>) msg.obj);
+                    mCallback.onQueueChanged((List<MediaSession.Item>) msg.obj);
                     break;
                 case MSG_UPDATE_QUEUE_TITLE:
                     mCallback.onQueueTitleChanged((CharSequence) msg.obj);
@@ -969,7 +970,7 @@
                     mCallback.onExtrasChanged((Bundle) msg.obj);
                     break;
                 case MSG_UPDATE_VOLUME:
-                    mCallback.onVolumeInfoChanged((VolumeInfo) msg.obj);
+                    mCallback.onAudioInfoChanged((AudioInfo) msg.obj);
                     break;
                 case MSG_DESTROYED:
                     mCallback.onSessionDestroyed();
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index cf73c2a..2cd161c 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -435,18 +435,19 @@
     }
 
     /**
-     * Update the list of tracks in the play queue. It is an ordered list and should contain the
-     * current track, and previous or upcoming tracks if they exist.
-     * Specify null if there is no current play queue.
+     * Update the list of items in the play queue. It is an ordered list and
+     * should contain the current item, and previous or upcoming items if they
+     * exist. Specify null if there is no current play queue.
      * <p>
-     * The queue should be of reasonable size. If the play queue is unbounded within your
-     * app, it is better to send a reasonable amount in a sliding window instead.
+     * The queue should be of reasonable size. If the play queue is unbounded
+     * within your app, it is better to send a reasonable amount in a sliding
+     * window instead.
      *
-     * @param queue A list of tracks in the play queue.
+     * @param queue A list of items in the play queue.
      */
-    public void setQueue(@Nullable List<Track> queue) {
+    public void setQueue(@Nullable List<Item> queue) {
         try {
-            mBinder.setQueue(new ParceledListSlice<Track>(queue));
+            mBinder.setQueue(new ParceledListSlice<Item>(queue));
         } catch (RemoteException e) {
             Log.wtf("Dead object in setQueue.", e);
         }
@@ -512,8 +513,8 @@
         postToCallback(CallbackMessageHandler.MSG_PLAY_SEARCH, query, extras);
     }
 
-    private void dispatchSkipToTrack(long id) {
-        postToCallback(CallbackMessageHandler.MSG_SKIP_TO_TRACK, id);
+    private void dispatchSkipToItem(long id) {
+        postToCallback(CallbackMessageHandler.MSG_SKIP_TO_ITEM, id);
     }
 
     private void dispatchPause() {
@@ -782,9 +783,10 @@
         }
 
         /**
-         * Override to handle requests to play a track with a given id from the play queue.
+         * Override to handle requests to play an item with a given id from the
+         * play queue.
          */
-        public void onSkipToTrack(long id) {
+        public void onSkipToItem(long id) {
         }
 
         /**
@@ -916,7 +918,7 @@
         public void onSkipToTrack(long id) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
-                session.dispatchSkipToTrack(id);
+                session.dispatchSkipToItem(id);
             }
         }
 
@@ -1015,12 +1017,12 @@
     }
 
     /**
-     * A single track that is part of the play queue. It contains information necessary to display
-     * a single track in the queue.
+     * A single item that is part of the play queue. It contains information
+     * necessary to display a single item in the queue.
      */
-    public static final class Track implements Parcelable {
+    public static final class Item implements Parcelable {
         /**
-         * This id is reserved. No tracks can be explicitly asigned this id.
+         * This id is reserved. No items can be explicitly asigned this id.
          */
         public static final int UNKNOWN_ID = -1;
 
@@ -1030,22 +1032,23 @@
         private final Bundle mExtras;
 
         /**
-         * Create a new {@link MediaSession.Track}.
+         * Create a new {@link MediaSession.Item}.
          *
-         * @param metadata The metadata for this track.
-         * @param id An identifier for this track. It must be unique within the play queue.
-         * @param uri The uri for this track.
-         * @param extras A bundle of extras that can be used to add extra information about the
-         *               track.
+         * @param metadata The metadata for this item.
+         * @param id An identifier for this item. It must be unique within the
+         *            play queue.
+         * @param uri The uri for this item.
+         * @param extras A bundle of extras that can be used to add extra
+         *            information about this item.
          */
-        private Track(MediaMetadata metadata, long id, Uri uri, Bundle extras) {
+        private Item(MediaMetadata metadata, long id, Uri uri, Bundle extras) {
             mMetadata = metadata;
             mId = id;
             mUri = uri;
             mExtras = extras;
         }
 
-        private Track(Parcel in) {
+        private Item(Parcel in) {
             mMetadata = MediaMetadata.CREATOR.createFromParcel(in);
             mId = in.readLong();
             mUri = Uri.CREATOR.createFromParcel(in);
@@ -1053,35 +1056,35 @@
         }
 
         /**
-         * Get the metadata for this track.
+         * Get the metadata for this item.
          */
         public MediaMetadata getMetadata() {
             return mMetadata;
         }
 
         /**
-         * Get the id for this track.
+         * Get the id for this item.
          */
         public long getId() {
             return mId;
         }
 
         /**
-         * Get the Uri for this track.
+         * Get the Uri for this item.
          */
         public Uri getUri() {
             return mUri;
         }
 
         /**
-         * Get the extras for this track.
+         * Get the extras for this item.
          */
         public Bundle getExtras() {
             return mExtras;
         }
 
         /**
-         * Builder for {@link MediaSession.Track} objects.
+         * Builder for {@link MediaSession.Item} objects.
          */
         public static final class Builder {
             private final MediaMetadata mMetadata;
@@ -1096,15 +1099,15 @@
             public Builder(MediaMetadata metadata, long id, Uri uri) {
                 if (metadata == null) {
                     throw new IllegalArgumentException(
-                            "You must specify a non-null MediaMetadata to build a Track.");
+                            "You must specify a non-null MediaMetadata to build an Item.");
                 }
                 if (uri == null) {
                     throw new IllegalArgumentException(
-                            "You must specify a non-null Uri to build a Track.");
+                            "You must specify a non-null Uri to build an Item.");
                 }
                 if (id == UNKNOWN_ID) {
                     throw new IllegalArgumentException(
-                            "You must specify an id other than UNKNOWN_ID to build a Track.");
+                            "You must specify an id other than UNKNOWN_ID to build an Item.");
                 }
                 mMetadata = metadata;
                 mId = id;
@@ -1112,18 +1115,18 @@
             }
 
             /**
-             * Set optional extras for the track.
+             * Set optional extras for the item.
              */
-            public MediaSession.Track.Builder setExtras(Bundle extras) {
+            public MediaSession.Item.Builder setExtras(Bundle extras) {
                 mExtras = extras;
                 return this;
             }
 
             /**
-             * Create the {@link Track}.
+             * Create the {@link Item}.
              */
-            public MediaSession.Track build() {
-                return new MediaSession.Track(mMetadata, mId, mUri, mExtras);
+            public MediaSession.Item build() {
+                return new MediaSession.Item(mMetadata, mId, mUri, mExtras);
             }
         }
 
@@ -1140,23 +1143,23 @@
             return 0;
         }
 
-        public static final Creator<MediaSession.Track> CREATOR
-                = new Creator<MediaSession.Track>() {
+        public static final Creator<MediaSession.Item> CREATOR
+                = new Creator<MediaSession.Item>() {
 
             @Override
-            public MediaSession.Track createFromParcel(Parcel p) {
-                return new MediaSession.Track(p);
+            public MediaSession.Item createFromParcel(Parcel p) {
+                return new MediaSession.Item(p);
             }
 
             @Override
-            public MediaSession.Track[] newArray(int size) {
-                return new MediaSession.Track[size];
+            public MediaSession.Item[] newArray(int size) {
+                return new MediaSession.Item[size];
             }
         };
 
         @Override
         public String toString() {
-            return "MediaSession.Track {" +
+            return "MediaSession.Item {" +
                     "Metadata=" + mMetadata +
                     ", Id=" + mId +
                     ", Uri=" + mUri +
@@ -1182,7 +1185,7 @@
         private static final int MSG_PLAY = 1;
         private static final int MSG_PLAY_URI = 2;
         private static final int MSG_PLAY_SEARCH = 3;
-        private static final int MSG_SKIP_TO_TRACK = 4;
+        private static final int MSG_SKIP_TO_ITEM = 4;
         private static final int MSG_PAUSE = 5;
         private static final int MSG_STOP = 6;
         private static final int MSG_NEXT = 7;
@@ -1232,8 +1235,8 @@
                 case MSG_PLAY_SEARCH:
                     mCallback.onPlayFromSearch((String) msg.obj, msg.getData());
                     break;
-                case MSG_SKIP_TO_TRACK:
-                    mCallback.onSkipToTrack((Long) msg.obj);
+                case MSG_SKIP_TO_ITEM:
+                    mCallback.onSkipToItem((Long) msg.obj);
                 case MSG_PAUSE:
                     mCallback.onPause();
                     break;
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index c2fb5a3..8a1e076 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -30,6 +30,7 @@
 import android.os.UserHandle;
 import android.service.notification.NotificationListenerService;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.Log;
 import android.view.KeyEvent;
 
@@ -50,6 +51,9 @@
 public final class MediaSessionManager {
     private static final String TAG = "SessionManager";
 
+    private final ArrayMap<OnActiveSessionsChangedListener, SessionsChangedWrapper> mListeners
+            = new ArrayMap<OnActiveSessionsChangedListener, SessionsChangedWrapper>();
+    private final Object mLock = new Object();
     private final ISessionManager mService;
 
     private Context mContext;
@@ -141,10 +145,11 @@
      * @param notificationListener The enabled notification listener component.
      *            May be null.
      */
-    public void addActiveSessionsListener(@NonNull SessionListener sessionListener,
+    public void addOnActiveSessionsChangedListener(
+            @NonNull OnActiveSessionsChangedListener sessionListener,
             @Nullable ComponentName notificationListener) {
-        addActiveSessionsListener(sessionListener, notificationListener, UserHandle.myUserId(),
-                null);
+        addOnActiveSessionsChangedListener(sessionListener, notificationListener,
+                UserHandle.myUserId(), null);
     }
 
     /**
@@ -163,7 +168,8 @@
      * @param handler The handler to post updates on.
      * @hide
      */
-    public void addActiveSessionsListener(@NonNull SessionListener sessionListener,
+    public void addOnActiveSessionsChangedListener(
+            @NonNull OnActiveSessionsChangedListener sessionListener,
             @Nullable ComponentName notificationListener, int userId, @Nullable Handler handler) {
         if (sessionListener == null) {
             throw new IllegalArgumentException("listener may not be null");
@@ -171,11 +177,18 @@
         if (handler == null) {
             handler = new Handler();
         }
-        sessionListener.setHandler(handler);
-        try {
-            mService.addSessionsListener(sessionListener.mStub, notificationListener, userId);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error in addActiveSessionsListener.", e);
+        synchronized (mLock) {
+            if (mListeners.get(sessionListener) != null) {
+                Log.w(TAG, "Attempted to add session listener twice, ignoring.");
+                return;
+            }
+            SessionsChangedWrapper wrapper = new SessionsChangedWrapper(sessionListener, handler);
+            try {
+                mService.addSessionsListener(wrapper.mStub, notificationListener, userId);
+                mListeners.put(sessionListener, wrapper);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error in addOnActiveSessionsChangedListener.", e);
+            }
         }
     }
 
@@ -184,14 +197,20 @@
      *
      * @param listener The listener to remove.
      */
-    public void removeActiveSessionsListener(@NonNull SessionListener listener) {
+    public void removeOnActiveSessionsChangedListener(
+            @NonNull OnActiveSessionsChangedListener listener) {
         if (listener == null) {
             throw new IllegalArgumentException("listener may not be null");
         }
-        try {
-            mService.removeSessionsListener(listener.mStub);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error in removeActiveSessionsListener.", e);
+        synchronized (mLock) {
+            SessionsChangedWrapper wrapper = mListeners.remove(listener);
+            if (wrapper != null) {
+                try {
+                    mService.removeSessionsListener(wrapper.mStub);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Error in removeOnActiveSessionsChangedListener.", e);
+                }
+            }
         }
     }
 
@@ -257,28 +276,18 @@
 
     /**
      * Listens for changes to the list of active sessions. This can be added
-     * using {@link #addActiveSessionsListener}.
+     * using {@link #addOnActiveSessionsChangedListener}.
      */
-    public static abstract class SessionListener {
-        private final Context mContext;
-        private Handler mHandler;
+    public interface OnActiveSessionsChangedListener {
+        public void onActiveSessionsChanged(@Nullable List<MediaController> controllers);
+    }
 
-        public SessionListener(Context context) {
-            mContext = context;
-        }
-        /**
-         * Called when the list of active sessions has changed. This can be due
-         * to a session being added or removed or the order of sessions
-         * changing. The controllers will be provided in priority order with the
-         * most important controller at index 0.
-         *
-         * @param controllers The updated list of controllers for the user that
-         *            changed.
-         */
-        public abstract void onActiveSessionsChanged(
-                @Nullable List<MediaController> controllers);
+    private final class SessionsChangedWrapper {
+        private final OnActiveSessionsChangedListener mListener;
+        private final Handler mHandler;
 
-        private final void setHandler(Handler handler) {
+        public SessionsChangedWrapper(OnActiveSessionsChangedListener listener, Handler handler) {
+            mListener = listener;
             mHandler = handler;
         }
 
@@ -295,7 +304,7 @@
                             for (int i = 0; i < size; i++) {
                                 controllers.add(new MediaController(mContext, tokens.get(i)));
                             }
-                            SessionListener.this.onActiveSessionsChanged(controllers);
+                            mListener.onActiveSessionsChanged(controllers);
                         }
                     });
                 }
diff --git a/media/java/android/media/session/ParcelableVolumeInfo.java b/media/java/android/media/session/ParcelableVolumeInfo.java
index e71b539..96a45d9b 100644
--- a/media/java/android/media/session/ParcelableVolumeInfo.java
+++ b/media/java/android/media/session/ParcelableVolumeInfo.java
@@ -21,7 +21,7 @@
 
 /**
  * Convenience class for passing information about the audio configuration of a
- * session. The public implementation is {@link MediaController.VolumeInfo}.
+ * session. The public implementation is {@link MediaController.AudioInfo}.
  *
  * @hide
  */
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index 2ad8eae..566e218 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -120,11 +120,11 @@
     public static final long ACTION_PLAY_FROM_SEARCH = 1 << 11;
 
     /**
-     * Indicates this performer supports the skip to track command.
+     * Indicates this performer supports the skip to item command.
      *
      * @see Builder#setActions(long)
      */
-    public static final long ACTION_SKIP_TO_TRACK = 1 << 12;
+    public static final long ACTION_SKIP_TO_ITEM = 1 << 12;
 
     /**
      * This is the default playback state and indicates that no media has been
@@ -223,11 +223,11 @@
     private List<PlaybackState.CustomAction> mCustomActions;
     private final CharSequence mErrorMessage;
     private final long mUpdateTime;
-    private final long mActiveTrackId;
+    private final long mActiveItemId;
 
     private PlaybackState(int state, long position, long updateTime, float speed,
             long bufferPosition, long transportControls,
-            List<PlaybackState.CustomAction> customActions, long activeTrackId,
+            List<PlaybackState.CustomAction> customActions, long activeItemId,
             CharSequence error) {
         mState = state;
         mPosition = position;
@@ -236,7 +236,7 @@
         mBufferPosition = bufferPosition;
         mActions = transportControls;
         mCustomActions = new ArrayList<>(customActions);
-        mActiveTrackId = activeTrackId;
+        mActiveItemId = activeItemId;
         mErrorMessage = error;
     }
 
@@ -248,7 +248,7 @@
         mBufferPosition = in.readLong();
         mActions = in.readLong();
         mCustomActions = in.createTypedArrayList(CustomAction.CREATOR);
-        mActiveTrackId = in.readLong();
+        mActiveItemId = in.readLong();
         mErrorMessage = in.readCharSequence();
 
     }
@@ -263,7 +263,7 @@
         bob.append(", updated=").append(mUpdateTime);
         bob.append(", actions=").append(mActions);
         bob.append(", custom actions=").append(mCustomActions);
-        bob.append(", active track id=").append(mActiveTrackId);
+        bob.append(", active item id=").append(mActiveItemId);
         bob.append(", error=").append(mErrorMessage);
         bob.append("}");
         return bob.toString();
@@ -283,7 +283,7 @@
         dest.writeLong(mBufferPosition);
         dest.writeLong(mActions);
         dest.writeTypedList(mCustomActions);
-        dest.writeLong(mActiveTrackId);
+        dest.writeLong(mActiveItemId);
         dest.writeCharSequence(mErrorMessage);
     }
 
@@ -716,7 +716,7 @@
         private long mActions;
         private CharSequence mErrorMessage;
         private long mUpdateTime;
-        private long mActiveTrackId = MediaSession.Track.UNKNOWN_ID;
+        private long mActiveItemId = MediaSession.Item.UNKNOWN_ID;
 
         /**
          * Creates an initially empty state builder.
@@ -744,14 +744,14 @@
             }
             mErrorMessage = from.mErrorMessage;
             mUpdateTime = from.mUpdateTime;
-            mActiveTrackId = from.mActiveTrackId;
+            mActiveItemId = from.mActiveItemId;
         }
 
         /**
          * Set the current state of playback.
          * <p>
          * The position must be in ms and indicates the current playback
-         * position within the track. If the position is unknown use
+         * position within the item. If the position is unknown use
          * {@link #PLAYBACK_POSITION_UNKNOWN}. When not using an unknown
          * position the time at which the position was updated must be provided.
          * It is okay to use {@link SystemClock#elapsedRealtime()} if the
@@ -773,7 +773,7 @@
          * </ul>
          *
          * @param state The current state of playback.
-         * @param position The position in the current track in ms.
+         * @param position The position in the current item in ms.
          * @param playbackSpeed The current speed of playback as a multiple of
          *            normal playback.
          * @param updateTime The time in the {@link SystemClock#elapsedRealtime}
@@ -792,7 +792,7 @@
          * Set the current state of playback.
          * <p>
          * The position must be in ms and indicates the current playback
-         * position within the track. If the position is unknown use
+         * position within the item. If the position is unknown use
          * {@link #PLAYBACK_POSITION_UNKNOWN}. The update time will be set to
          * the current {@link SystemClock#elapsedRealtime()}.
          * <p>
@@ -812,7 +812,7 @@
          * </ul>
          *
          * @param state The current state of playback.
-         * @param position The position in the current track in ms.
+         * @param position The position in the current item in ms.
          * @param playbackSpeed The current speed of playback as a multiple of
          *            normal playback.
          * @return this
@@ -902,14 +902,14 @@
         }
 
         /**
-         * Set the active track in the play queue by specifying its id.
-         * The default value is {@link MediaSession.Track#UNKNOWN_ID}
+         * Set the active item in the play queue by specifying its id. The
+         * default value is {@link MediaSession.Item#UNKNOWN_ID}
          *
-         * @param id The id of the active track.
+         * @param id The id of the active item.
          * @return this
          */
-        public Builder setActiveTrack(long id) {
-            mActiveTrackId = id;
+        public Builder setActiveItem(long id) {
+            mActiveItemId = id;
             return this;
         }
 
@@ -932,7 +932,7 @@
          */
         public PlaybackState build() {
             return new PlaybackState(mState, mPosition, mUpdateTime, mSpeed, mBufferPosition,
-                    mActions, mCustomActions, mActiveTrackId, mErrorMessage);
+                    mActions, mCustomActions, mActiveItemId, mErrorMessage);
         }
     }
 }
diff --git a/media/java/android/media/tv/ITvInputSession.aidl b/media/java/android/media/tv/ITvInputSession.aidl
index 99fb911..1aad2fa 100644
--- a/media/java/android/media/tv/ITvInputSession.aidl
+++ b/media/java/android/media/tv/ITvInputSession.aidl
@@ -29,7 +29,7 @@
 oneway interface ITvInputSession {
     void release();
 
-    void setMainSession(boolean isMainSession);
+    void setMain(boolean isMain);
     void setSurface(in Surface surface);
     void dispatchSurfaceChanged(int format, int width, int height);
     // TODO: Remove this once it becomes irrelevant for applications to handle audio focus. The plan
diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java
index 5022cc1..58e46f0 100644
--- a/media/java/android/media/tv/ITvInputSessionWrapper.java
+++ b/media/java/android/media/tv/ITvInputSessionWrapper.java
@@ -42,7 +42,7 @@
     private static final String TAG = "TvInputSessionWrapper";
 
     private static final int DO_RELEASE = 1;
-    private static final int DO_SET_MAIN_SESSION = 2;
+    private static final int DO_SET_MAIN = 2;
     private static final int DO_SET_SURFACE = 3;
     private static final int DO_DISPATCH_SURFACE_CHANGED = 4;
     private static final int DO_SET_STREAM_VOLUME = 5;
@@ -91,8 +91,8 @@
                 }
                 return;
             }
-            case DO_SET_MAIN_SESSION: {
-                mTvInputSessionImpl.setMainSession((Boolean) msg.obj);
+            case DO_SET_MAIN: {
+                mTvInputSessionImpl.setMain((Boolean) msg.obj);
                 return;
             }
             case DO_SET_SURFACE: {
@@ -162,8 +162,8 @@
     }
 
     @Override
-    public void setMainSession(boolean isMain) {
-        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_SET_MAIN_SESSION, isMain));
+    public void setMain(boolean isMain) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_SET_MAIN, isMain));
     }
 
     @Override
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index f76c78b..45aa6d6 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -1023,10 +1023,12 @@
         }
 
         /**
-         * Sets this as main session. See {@link TvView#setMainTvView} for about meaning of "main".
-         * @hide
+         * Sets this as the main session. The main session is a session whose corresponding TV
+         * input determines the HDMI-CEC active source device.
+         *
+         * @see TvView#setMain
          */
-        public void setMainSession() {
+        void setMain() {
             if (mToken == null) {
                 Log.w(TAG, "The session has been already released");
                 return;
@@ -1339,6 +1341,9 @@
                 Log.w(TAG, "The session has been already released");
                 return;
             }
+            if (unblockedRating == null) {
+                throw new IllegalArgumentException("unblockedRating cannot be null");
+            }
             try {
                 mService.requestUnblockContent(mToken, unblockedRating.flattenToString(), mUserId);
             } catch (RemoteException e) {
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index c93b261..e3292b6 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -94,6 +94,8 @@
     private final RemoteCallbackList<ITvInputServiceCallback> mCallbacks =
             new RemoteCallbackList<ITvInputServiceCallback>();
 
+    private TvInputManager mTvInputManager;
+
     @Override
     public final IBinder onBind(Intent intent) {
         return new ITvInputService.Stub() {
@@ -225,6 +227,17 @@
         return null;
     }
 
+    private boolean isPassthroughInput(String inputId) {
+        if (mTvInputManager == null) {
+            mTvInputManager = (TvInputManager) getSystemService(Context.TV_INPUT_SERVICE);
+        }
+        TvInputInfo info = mTvInputManager.getTvInputInfo(inputId);
+        if (info != null && info.isPassthroughInput()) {
+            return true;
+        }
+        return false;
+    }
+
     /**
      * Base class for derived classes to implement to provide a TV input session.
      */
@@ -538,29 +551,30 @@
         public abstract void onRelease();
 
         /**
-         * Set the current session as the "main" session. See {@link TvView#setMainTvView} for the
-         * meaning of "main".
+         * Sets the current session as the main session. The main session is a session whose
+         * corresponding TV input determines the HDMI-CEC active source device.
          * <p>
-         * This is primarily for HDMI-CEC active source management. TV input service that manages
-         * HDMI-CEC logical device should make sure not only to select the corresponding HDMI
-         * logical device as source device on {@code onSetMainSession(true)}, but also to select
-         * internal device on {@code onSetMainSession(false)}. Also, if surface is set to non-main
-         * session, it needs to select internal device after temporarily selecting corresponding
-         * HDMI logical device for set up.
+         * TV input service that manages HDMI-CEC logical device should implement {@link
+         * #onSetMain} to (1) select the corresponding HDMI logical device as the source device
+         * when {@code isMain} is {@code true}, and to (2) select the internal device (= TV itself)
+         * as the source device when {@code isMain} is {@code false} and the session is still main.
+         * Also, if a surface is passed to a non-main session and active source is changed to
+         * initiate the surface, the active source should be returned to the main session.
          * </p><p>
-         * It is guaranteed that {@code onSetMainSession(true)} for new session is called first,
-         * and {@code onSetMainSession(false)} for old session is called afterwards. This allows
-         * {@code onSetMainSession(false)} to be no-op when TV input service knows that the next
-         * main session corresponds to another HDMI logical device. Practically, this implies that
-         * one TV input service should handle all HDMI port and HDMI-CEC logical devices for smooth
-         * active source transition.
+         * {@link TvView} guarantees that, when tuning involves a session transition, {@code
+         * onSetMain(true)} for new session is called first, {@code onSetMain(false)} for old
+         * session is called afterwards. This allows {@code onSetMain(false)} to be no-op when TV
+         * input service knows that the next main session corresponds to another HDMI logical
+         * device. Practically, this implies that one TV input service should handle all HDMI port
+         * and HDMI-CEC logical devices for smooth active source transition.
          * </p>
          *
-         * @param isMainSession If true, session is main.
+         * @param isMain If true, session should become main.
+         * @see TvView#setMain
          * @hide
          */
         @SystemApi
-        public void onSetMainSession(boolean isMainSession) {
+        public void onSetMain(boolean isMain) {
         }
 
         /**
@@ -828,10 +842,10 @@
         }
 
         /**
-         * Calls {@link #onSetMainSession}.
+         * Calls {@link #onSetMain}.
          */
-        void setMainSession(boolean isMainSession) {
-            onSetMainSession(isMainSession);
+        void setMain(boolean isMain) {
+            onSetMain(isMain);
         }
 
         /**
@@ -1229,9 +1243,14 @@
                         HardwareSession proxySession =
                                 ((HardwareSession) sessionImpl);
                         String harewareInputId = proxySession.getHardwareInputId();
-                        if (TextUtils.isEmpty(harewareInputId)) {
+                        if (TextUtils.isEmpty(harewareInputId) ||
+                                !isPassthroughInput(harewareInputId)) {
+                            if (TextUtils.isEmpty(harewareInputId)) {
+                                Log.w(TAG, "Hardware input id is not setup yet.");
+                            } else {
+                                Log.w(TAG, "Invalid hardware input id : " + harewareInputId);
+                            }
                             sessionImpl.onRelease();
-                            Log.w(TAG, "Hardware input id is not setup yet.");
                             try {
                                 cb.onSessionCreated(null, null);
                             } catch (RemoteException e) {
@@ -1239,7 +1258,6 @@
                             }
                             return;
                         }
-                        // TODO: check if the given ID is really hardware TV input.
                         proxySession.mProxySession = stub;
                         proxySession.mProxySessionCallback = cb;
                         proxySession.mServiceHandler = mServiceHandler;
diff --git a/media/java/android/media/tv/TvTrackInfo.java b/media/java/android/media/tv/TvTrackInfo.java
index 6ddb2a2..e0aacd6 100644
--- a/media/java/android/media/tv/TvTrackInfo.java
+++ b/media/java/android/media/tv/TvTrackInfo.java
@@ -46,10 +46,12 @@
     private final int mAudioSampleRate;
     private final int mVideoWidth;
     private final int mVideoHeight;
+    private final float mVideoFrameRate;
     private final Bundle mExtra;
 
     private TvTrackInfo(int type, String id, String language, int audioChannelCount,
-            int audioSampleRate, int videoWidth, int videoHeight, Bundle extra) {
+            int audioSampleRate, int videoWidth, int videoHeight, float videoFrameRate,
+            Bundle extra) {
         mType = type;
         mId = id;
         mLanguage = language;
@@ -57,6 +59,7 @@
         mAudioSampleRate = audioSampleRate;
         mVideoWidth = videoWidth;
         mVideoHeight = videoHeight;
+        mVideoFrameRate = videoFrameRate;
         mExtra = extra;
     }
 
@@ -68,6 +71,7 @@
         mAudioSampleRate = in.readInt();
         mVideoWidth = in.readInt();
         mVideoHeight = in.readInt();
+        mVideoFrameRate = in.readFloat();
         mExtra = in.readBundle();
     }
 
@@ -137,6 +141,17 @@
     }
 
     /**
+     * Returns the frame rate of the video, in the unit of fps (frames per second). Valid only for
+     * {@link #TYPE_VIDEO} tracks.
+     */
+    public final float getVideoFrameRate() {
+        if (mType != TYPE_VIDEO) {
+            throw new IllegalStateException("Not a video track");
+        }
+        return mVideoFrameRate;
+    }
+
+    /**
      * Returns the extra information about the current track.
      */
     public final Bundle getExtra() {
@@ -163,6 +178,7 @@
         dest.writeInt(mAudioSampleRate);
         dest.writeInt(mVideoWidth);
         dest.writeInt(mVideoHeight);
+        dest.writeFloat(mVideoFrameRate);
         dest.writeBundle(mExtra);
     }
 
@@ -190,6 +206,7 @@
         private int mAudioSampleRate;
         private int mVideoWidth;
         private int mVideoHeight;
+        private float mVideoFrameRate;
         private Bundle mExtra;
 
         /**
@@ -279,6 +296,20 @@
         }
 
         /**
+         * Sets the frame rate of the video, in the unit fps (frames per rate). Valid only for
+         * {@link #TYPE_VIDEO} tracks.
+         *
+         * @param videoFrameRate The frame rate of the video.
+         */
+        public final Builder setVideoFrameRate(float videoFrameRate) {
+            if (mType != TYPE_VIDEO) {
+                throw new IllegalStateException("Not a video track");
+            }
+            mVideoFrameRate = videoFrameRate;
+            return this;
+        }
+
+        /**
          * Sets the extra information about the current track.
          *
          * @param extra The extra information.
@@ -295,7 +326,7 @@
          */
         public TvTrackInfo build() {
             return new TvTrackInfo(mType, mId, mLanguage, mAudioChannelCount, mAudioSampleRate,
-                    mVideoWidth, mVideoHeight, mExtra);
+                    mVideoWidth, mVideoHeight, mVideoFrameRate, mExtra);
         }
     }
 }
\ No newline at end of file
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index 591f543..f348b9b 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -59,19 +59,6 @@
     // STOPSHIP: Turn debugging off.
     private static final boolean DEBUG = true;
 
-    /**
-     * Passed with {@link TvInputListener#onError(String, int)}. Indicates that the connection to
-     * the requested TV input was not established thus the view is unable to handle the further
-     * operations.
-     */
-    public static final int ERROR_INPUT_NOT_CONNECTED = 0;
-
-    /**
-     * Passed with {@link TvInputListener#onError(String, int)}. Indicates that the underlying TV
-     * input has been disconnected.
-     */
-    public static final int ERROR_INPUT_DISCONNECTED = 1;
-
     private static final int VIDEO_SIZE_VALUE_UNKNOWN = 0;
 
     private static final int ZORDER_MEDIA = 0;
@@ -116,8 +103,10 @@
     private final SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback() {
         @Override
         public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
-            Log.d(TAG, "surfaceChanged(holder=" + holder + ", format=" + format + ", width=" + width
-                    + ", height=" + height + ")");
+            if (DEBUG) {
+                Log.d(TAG, "surfaceChanged(holder=" + holder + ", format=" + format + ", width="
+                    + width + ", height=" + height + ")");
+            }
             mSurfaceFormat = format;
             mSurfaceWidth = width;
             mSurfaceHeight = height;
@@ -188,24 +177,27 @@
     }
 
     /**
-     * Sets this as main TvView.
+     * Sets this as the main {@link TvView}.
      * <p>
-     * Main TvView is the TvView which user is watching and interacting mainly.  It is used for
-     * determining internal behavior of hardware TV input devices. For example, this influences
-     * how HDMI-CEC active source will be managed.
+     * The main {@link TvView} is a {@link TvView} whose corresponding TV input determines the
+     * HDMI-CEC active source device. For an HDMI port input, one of source devices that is
+     * connected to that HDMI port becomes the active source. For an HDMI-CEC logical device input,
+     * the corresponding HDMI-CEC logical device becomes the active source. For any non-HDMI input
+     * (including the tuner, composite, S-Video, etc.), the internal device (= TV itself) becomes
+     * the active source.
      * </p><p>
-     * First tuned TvView becomes main automatically, and keeps to be main until setMainTvView() is
-     * called for other TvView. Note that main TvView won't be reset even when current main TvView
-     * is removed from view hierarchy.
+     * First tuned {@link TvView} becomes main automatically, and keeps to be main until {@link
+     * #setMain} is called for other {@link TvView}. Note that main {@link TvView} won't be reset
+     * even when current main {@link TvView} is removed from view hierarchy.
      * </p>
      * @hide
      */
     @SystemApi
-    public void setMainTvView() {
+    public void setMain() {
         synchronized (sMainTvViewLock) {
             sMainTvView = this;
             if (hasWindowFocus() && mSession != null) {
-                mSession.setMainSession();
+                mSession.setMain();
             }
         }
     }
@@ -327,6 +319,7 @@
      * This method is primarily used to un-tune the current TvView.
      */
     public void reset() {
+        if (DEBUG) Log.d(TAG, "reset()");
         if (mSession != null) {
             release();
             resetSurfaceView();
@@ -538,7 +531,7 @@
         // Set main again to regain main session.
         synchronized (sMainTvViewLock) {
             if (hasFocus && this == sMainTvView && mSession != null) {
-                mSession.setMainSession();
+                mSession.setMain();
             }
         }
     }
@@ -596,6 +589,7 @@
             mSurfaceView.getHolder().removeCallback(mSurfaceHolderCallback);
             removeView(mSurfaceView);
         }
+        mSurface = null;
         mSurfaceView = new SurfaceView(getContext(), mAttrs, mDefStyleAttr) {
             @Override
             protected void updateWindow(boolean force, boolean redrawNeeded) {
@@ -679,13 +673,20 @@
     public abstract static class TvInputListener {
 
         /**
-         * This is invoked when an error occurred while handling requested operation.
+         * This is invoked when an error occurred while establishing a connection to the underlying
+         * TV input.
          *
          * @param inputId The ID of the TV input bound to this view.
-         * @param errorCode The error code. For the details of error code, please see
-         *         {@link TvView}.
          */
-        public void onError(String inputId, int errorCode) {
+        public void onConnectionFailed(String inputId) {
+        }
+
+        /**
+         * This is invoked when the existing connection to the underlying TV input is lost.
+         *
+         * @param inputId The ID of the TV input bound to this view.
+         */
+        public void onDisconnected(String inputId) {
         }
 
         /**
@@ -821,11 +822,14 @@
                 }
                 return;
             }
+            if (DEBUG) {
+                Log.d(TAG, "onSessionCreated()");
+            }
             mSession = session;
             if (session != null) {
                 synchronized (sMainTvViewLock) {
                     if (hasWindowFocus() && TvView.this == sMainTvView) {
-                        mSession.setMainSession();
+                        mSession.setMain();
                     }
                 }
                 // mSurface may not be ready yet as soon as starting an application.
@@ -847,7 +851,7 @@
                 }
             } else {
                 if (mListener != null) {
-                    mListener.onError(mInputId, ERROR_INPUT_NOT_CONNECTED);
+                    mListener.onConnectionFailed(mInputId);
                 }
             }
         }
@@ -860,7 +864,7 @@
             mSessionCallback = null;
             mSession = null;
             if (mListener != null) {
-                mListener.onError(mInputId, ERROR_INPUT_DISCONNECTED);
+                mListener.onDisconnected(mInputId);
             }
         }
 
diff --git a/packages/PrintSpooler/AndroidManifest.xml b/packages/PrintSpooler/AndroidManifest.xml
index 9a62864..055587a 100644
--- a/packages/PrintSpooler/AndroidManifest.xml
+++ b/packages/PrintSpooler/AndroidManifest.xml
@@ -46,7 +46,7 @@
         android:label="@string/app_label"
         android:allowBackup= "false"
         android:supportsRtl="true"
-        android:icon="@*android:drawable/ic_print">
+        android:icon="@drawable/ic_print">
 
         <service
             android:name=".model.PrintSpoolerService"
diff --git a/packages/PrintSpooler/res/drawable-hdpi/ic_menu_print.png b/packages/PrintSpooler/res/drawable-hdpi/ic_menu_print.png
deleted file mode 100644
index 09ab1a2..0000000
--- a/packages/PrintSpooler/res/drawable-hdpi/ic_menu_print.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-mdpi/ic_menu_print.png b/packages/PrintSpooler/res/drawable-mdpi/ic_menu_print.png
deleted file mode 100644
index 637d94e..0000000
--- a/packages/PrintSpooler/res/drawable-mdpi/ic_menu_print.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xhdpi/ic_menu_print.png b/packages/PrintSpooler/res/drawable-xhdpi/ic_menu_print.png
deleted file mode 100644
index 4d4b3cc..0000000
--- a/packages/PrintSpooler/res/drawable-xhdpi/ic_menu_print.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable/ic_print.xml b/packages/PrintSpooler/res/drawable/ic_print.xml
new file mode 100644
index 0000000..dc6e0fb
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable/ic_print.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@*android:drawable/ic_print"
+    android:tint="@color/promoted_action_background_color" />
diff --git a/packages/PrintSpooler/res/values/themes.xml b/packages/PrintSpooler/res/values/themes.xml
index db319e9..08702291 100644
--- a/packages/PrintSpooler/res/values/themes.xml
+++ b/packages/PrintSpooler/res/values/themes.xml
@@ -16,7 +16,10 @@
 
 <resources>
 
-    <style name="PrintActivity" parent="@android:style/Theme.Material.Settings">
+    <style name="PrintActivity" parent="@android:style/Theme.Material">
+        <item name="android:colorPrimary">@*android:color/material_blue_grey_900</item>
+        <item name="android:colorPrimaryDark">@*android:color/material_blue_grey_950</item>
+        <item name="android:colorAccent">@*android:color/material_deep_teal_A500</item>
         <item name="android:windowIsTranslucent">true</item>
         <item name="android:windowBackground">@android:color/transparent</item>
         <item name="android:windowContentOverlay">@null</item>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
index 7715579..3905bada 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
@@ -96,7 +96,7 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        getActionBar().setIcon(R.drawable.ic_menu_print);
+        getActionBar().setIcon(R.drawable.ic_print);
 
         setContentView(R.layout.select_printer_activity);
 
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 6f41565..f1d2bee3 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -90,6 +90,7 @@
     <uses-permission android:name="android.permission.RETRIEVE_WINDOW_TOKEN" />
     <uses-permission android:name="android.permission.FRAME_STATS" />
     <uses-permission android:name="android.permission.BIND_APPWIDGET" />
+    <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
 
     <application android:label="@string/app_label">
         <provider
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index b8836a0..cbea664 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -111,7 +111,7 @@
     <uses-permission android:name="android.permission.CAMERA" />
 
     <!-- Screen Capturing -->
-    <uses-permission android:name="android.permission.CREATE_MEDIA_PROJECTION" />
+    <uses-permission android:name="android.permission.MANAGE_MEDIA_PROJECTION" />
 
     <application
         android:name=".SystemUIApplication"
diff --git a/packages/SystemUI/res/drawable/ic_qs_bugreport.xml b/packages/SystemUI/res/drawable/ic_qs_bugreport.xml
deleted file mode 100644
index 0df1a96..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_bugreport.xml
+++ /dev/null
@@ -1,25 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="64dp"
-        android:height="64dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M20.0,8.0l-2.8,0.0c-0.5,-0.8 -1.1,-1.5 -1.8,-2.0L17.0,4.4L15.6,3.0l-2.2,2.2C13.0,5.1 12.5,5.0 12.0,5.0s-1.0,0.1 -1.4,0.2L8.4,3.0L7.0,4.4L8.6,6.0C7.9,6.5 7.3,7.2 6.8,8.0L4.0,8.0l0.0,2.0l2.1,0.0C6.0,10.3 6.0,10.7 6.0,11.0l0.0,1.0L4.0,12.0l0.0,2.0l2.0,0.0l0.0,1.0c0.0,0.3 0.0,0.7 0.1,1.0L4.0,16.0l0.0,2.0l2.8,0.0c1.0,1.8 3.0,3.0 5.2,3.0s4.2,-1.2 5.2,-3.0L20.0,18.0l0.0,-2.0l-2.1,0.0c0.1,-0.3 0.1,-0.7 0.1,-1.0l0.0,-1.0l2.0,0.0l0.0,-2.0l-2.0,0.0l0.0,-1.0c0.0,-0.3 0.0,-0.7 -0.1,-1.0L20.0,10.0L20.0,8.0zM14.0,16.0l-4.0,0.0l0.0,-2.0l4.0,0.0L14.0,16.0zM14.0,12.0l-4.0,0.0l0.0,-2.0l4.0,0.0L14.0,12.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/layout/keyguard_status_bar.xml b/packages/SystemUI/res/layout/keyguard_status_bar.xml
index fcc0f4a..faa2820 100644
--- a/packages/SystemUI/res/layout/keyguard_status_bar.xml
+++ b/packages/SystemUI/res/layout/keyguard_status_bar.xml
@@ -60,7 +60,8 @@
             android:paddingEnd="@dimen/battery_level_padding_end"
             android:textColor="#ffffff"
             android:visibility="gone"
-            android:textSize="@dimen/battery_level_text_size"/>
+            android:textSize="@dimen/battery_level_text_size"
+            android:importantForAccessibility="noHideDescendants"/>
     </LinearLayout>
 
     <com.android.keyguard.CarrierText
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index 828065b..5253ee0 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -69,6 +69,7 @@
         android:layout_gravity="bottom|right"
         android:layout_marginRight="15dp"
         android:layout_marginBottom="15dp"
+        android:translationZ="3dp"
         android:contentDescription="@string/recents_lock_to_app_button_label"
         android:background="@drawable/recents_lock_to_task_button_bg">
         <ImageView
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index 079b97b..aa276bc 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -72,7 +72,8 @@
             android:layout_marginStart="@dimen/header_battery_margin_expanded"
             android:paddingEnd="@dimen/battery_level_padding_end"
             android:textColor="#ffffff"
-            android:textSize="@dimen/battery_level_text_size"/>
+            android:textSize="@dimen/battery_level_text_size"
+            android:importantForAccessibility="noHideDescendants"/>
     </LinearLayout>
 
     <TextView
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 5415d19..1b8eeb2 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -205,10 +205,10 @@
     <dimen name="recents_task_view_rounded_corners_radius">2dp</dimen>
 
     <!-- The min translation in the Z index for the last task. -->
-    <dimen name="recents_task_view_z_min">5dp</dimen>
+    <dimen name="recents_task_view_z_min">25dp</dimen>
 
     <!-- The max translation in the Z index for the last task. -->
-    <dimen name="recents_task_view_z_max">65dp</dimen>
+    <dimen name="recents_task_view_z_max">100dp</dimen>
 
     <!-- The amount to translate when animating the removal of a task. -->
     <dimen name="recents_task_view_remove_anim_translation_x">100dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index d145172..d49312d 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -273,6 +273,13 @@
     <!-- Content description of the WIFI signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_wifi_signal_full">Wifi signal full.</string>
 
+    <!-- Content description of the wifi label showing what we are connected to. [CHAR LIMIT=NONE] -->
+    <string name="accessibility_wifi_name">Connected to <xliff:g id="wifi" example="Home Network">%s</xliff:g>.</string>
+
+    <!-- Content description of the bluetooth label showing what we are connected to. [CHAR LIMIT=NONE] -->
+    <string name="accessibility_bluetooth_name">Connected to <xliff:g id="bluetooth" example="Car Audio">%s</xliff:g>.</string>
+
+
     <!-- Content description of the WiMAX signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_no_wimax">No WiMAX.</string>
     <!-- Content description of the WiMAX signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
@@ -390,6 +397,8 @@
     <string name="accessibility_desc_notification_shade">Notification shade.</string>
     <!-- Content description for the quick settings panel (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_desc_quick_settings">Quick settings.</string>
+    <!-- Content description for the lock screen (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_desc_lock_screen">Lock screen.</string>
     <!-- Content description for the settings button in the status bar header. [CHAR LIMIT=NONE] -->
     <string name="accessibility_desc_settings">Settings</string>
     <!-- Content description for the recent apps panel (not shown on the screen). [CHAR LIMIT=NONE] -->
@@ -398,7 +407,7 @@
     <!-- 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>
     <!-- Content description of the wifi tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_quick_settings_wifi"><xliff:g id="signal" example="Three bars">%1$s</xliff:g>. <xliff:g id="network" example="MyWifiNetwork">%2$s</xliff:g></string>
+    <string name="accessibility_quick_settings_wifi"><xliff:g id="signal" example="Three bars">%1$s</xliff:g>.</string>
     <!-- Content description of the mobile data tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_quick_settings_mobile">Mobile <xliff:g id="signal" example="Three bars">%1$s</xliff:g>. <xliff:g id="type" example="4G">%2$s</xliff:g>. <xliff:g id="network" example="T-Mobile">%3$s</xliff:g>.</string>
     <!-- Content description of the battery tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
@@ -577,7 +586,7 @@
     <!-- QuickSettings: Cellular detail panel, remaining data title [CHAR LIMIT=NONE] -->
     <string name="quick_settings_cellular_detail_remaining_data">Remaining data</string>
     <!-- QuickSettings: Cellular detail panel, over limit title [CHAR LIMIT=NONE] -->
-    <string name="quick_settings_cellular_detail_over_limit">Over limit</string>
+    <string name="quick_settings_cellular_detail_over_limit">Limit reached &#8211; data usage paused</string>
     <!-- QuickSettings: Cellular detail panel, data used format string [CHAR LIMIT=NONE] -->
     <string name="quick_settings_cellular_detail_data_used"><xliff:g id="data_used" example="2.0 GB">%s</xliff:g> used</string>
     <!-- QuickSettings: Cellular detail panel, data limit format string [CHAR LIMIT=NONE] -->
@@ -659,8 +668,6 @@
     <!-- Shows when people have clicked at the right edge of the screen to explain how to open the phone. In right-to-left languages, this is the opposite direction. [CHAR LIMIT=60] -->
     <string name="camera_hint">Swipe left for camera</string>
 
-    <string name="bugreport_tile_extended" translatable="false">%s\n%s (%s)</string>
-
     <!-- Zen mode condition: no exit criteria. [CHAR LIMIT=NONE] -->
     <string name="zen_mode_forever">Indefinitely</string>
 
@@ -700,10 +707,13 @@
     <string name="guest_exit_guest">Remove guest</string>
 
     <!-- Title of the confirmation dialog when exiting guest session [CHAR LIMIT=NONE] -->
-    <string name="guest_exit_guest_dialog_title">Exiting guest session?</string>
+    <string name="guest_exit_guest_dialog_title">Remove guest?</string>
 
     <!-- Message of the confirmation dialog when exiting guest session [CHAR LIMIT=NONE] -->
-    <string name="guest_exit_guest_dialog_message">Exiting the guest session will remove local data.</string>
+    <string name="guest_exit_guest_dialog_message">All apps and data in this session will be deleted.</string>
+
+    <!-- Label for button in confirmation dialog when exiting guest session [CHAR LIMIT=35] -->
+    <string name="guest_exit_guest_dialog_remove">Remove</string>
 
     <!-- Title of the notification when resuming an existing guest session [CHAR LIMIT=NONE] -->
     <string name="guest_wipe_session_title">Welcome back, guest!</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 27e58a4..48a031a 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -21,11 +21,23 @@
     </style>
 
     <!-- Alternate Recents theme -->
-    <style name="RecentsTheme" parent="@android:style/Theme.DeviceDefault.Wallpaper.NoTitleBar">
+    <style name="RecentsTheme" parent="@android:style/Theme">
+        <!-- NoTitle -->
+        <item name="android:windowNoTitle">true</item>
+        <!-- Wallpaper -->
+        <item name="android:windowBackground">@color/transparent</item>
+        <item name="android:colorBackgroundCacheHint">@null</item>
+        <item name="android:windowShowWallpaper">true</item>
+        <!-- Misc -->
         <item name="android:statusBarColor">@android:color/transparent</item>
         <item name="android:navigationBarColor">@android:color/transparent</item>
         <item name="android:windowDrawsSystemBarBackgrounds">true</item>
         <item name="android:windowAnimationStyle">@style/Animation.RecentsActivity</item>
+        <item name="*android:lightingStyle">@style/RecentsLighting</item>
+    </style>
+
+    <style name="RecentsLighting" parent="@*android:style/Lighting">
+        <item name="*android:ambientShadowAlpha">0.30</item>
     </style>
 
     <!-- Animations for a non-full-screen window or activity. -->
diff --git a/packages/SystemUI/src/com/android/systemui/net/NetworkOverLimitActivity.java b/packages/SystemUI/src/com/android/systemui/net/NetworkOverLimitActivity.java
index fe7aa75..b3c0783 100644
--- a/packages/SystemUI/src/com/android/systemui/net/NetworkOverLimitActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/net/NetworkOverLimitActivity.java
@@ -33,6 +33,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.util.Log;
+import android.view.WindowManager;
 
 import com.android.systemui.R;
 
@@ -62,6 +63,7 @@
                 });
 
         final Dialog dialog = builder.create();
+        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
         dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
             public void onDismiss(DialogInterface dialog) {
                 finish();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 1fa97bd..bf01b7b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -347,8 +347,8 @@
         }
 
         for (TileRecord record : mRecords) {
-            if (record.tileView.getVisibility() == GONE) continue;
             record.tileView.setDual(record.tile.supportsDualTargets());
+            if (record.tileView.getVisibility() == GONE) continue;
             final int cw = record.row == 0 ? mLargeCellWidth : mCellWidth;
             final int ch = record.row == 0 ? mLargeCellHeight : mCellHeight;
             record.tileView.measure(exactly(cw), exactly(ch));
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 6975541..409cc46 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -286,6 +286,7 @@
         public Drawable icon;
         public String label;
         public String contentDescription;
+        public String dualLabelContentDescription;
 
         public boolean copyTo(State other) {
             if (other == null) throw new IllegalArgumentException();
@@ -294,12 +295,15 @@
                     || other.iconId != iconId
                     || !Objects.equals(other.icon, icon)
                     || !Objects.equals(other.label, label)
-                    || !Objects.equals(other.contentDescription, contentDescription);
+                    || !Objects.equals(other.contentDescription, contentDescription)
+                    || !Objects.equals(other.dualLabelContentDescription,
+                    dualLabelContentDescription);
             other.visible = visible;
             other.iconId = iconId;
             other.icon = icon;
             other.label = label;
             other.contentDescription = contentDescription;
+            other.dualLabelContentDescription = dualLabelContentDescription;
             return changed;
         }
 
@@ -315,6 +319,7 @@
             sb.append(",icon=").append(icon);
             sb.append(",label=").append(label);
             sb.append(",contentDescription=").append(contentDescription);
+            sb.append(",dualLabelContentDescription=").append(dualLabelContentDescription);
             return sb.append(']');
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
index 597bb93..2cc1f07 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
@@ -87,6 +87,7 @@
 
     private void recreateLabel() {
         CharSequence labelText = null;
+        CharSequence labelDescription = null;
         if (mLabel != null) {
             labelText = mLabel.getText();
             removeView(mLabel);
@@ -94,6 +95,7 @@
         }
         if (mDualLabel != null) {
             labelText = mDualLabel.getText();
+            labelDescription = mLabel.getContentDescription();
             removeView(mDualLabel);
             mDualLabel = null;
         }
@@ -113,6 +115,9 @@
             if (labelText != null) {
                 mDualLabel.setText(labelText);
             }
+            if (labelDescription != null) {
+                mDualLabel.setContentDescription(labelDescription);
+            }
             addView(mDualLabel);
         } else {
             mLabel = new TextView(mContext);
@@ -228,6 +233,7 @@
         }
         if (mDual) {
             mDualLabel.setText(state.label);
+            mDualLabel.setContentDescription(state.dualLabelContentDescription);
         } else {
             mLabel.setText(state.label);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 1b2c0b0..19b9ec1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -114,6 +114,12 @@
         }
         state.contentDescription = mContext.getString(
                 R.string.accessibility_quick_settings_bluetooth, stateContentDescription);
+        String bluetoothName = state.label;
+        if (connected) {
+            bluetoothName = state.dualLabelContentDescription = mContext.getString(
+                    R.string.accessibility_bluetooth_name, state.label);
+        }
+        state.dualLabelContentDescription = bluetoothName;
     }
 
     private final BluetoothController.Callback mCallback = new BluetoothController.Callback() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BugreportTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BugreportTile.java
deleted file mode 100644
index a308e84..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BugreportTile.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles;
-
-import android.app.ActivityManagerNative;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
-import android.os.Build;
-import android.os.RemoteException;
-import android.provider.Settings.Global;
-import android.view.WindowManager;
-import android.view.WindowManagerGlobal;
-
-import com.android.systemui.R;
-import com.android.systemui.qs.GlobalSetting;
-import com.android.systemui.qs.QSTile;
-
-/** Quick settings tile: Bug report **/
-public class BugreportTile extends QSTile<QSTile.State> {
-
-    private final GlobalSetting mSetting;
-
-    public BugreportTile(Host host) {
-        super(host);
-        mSetting = new GlobalSetting(mContext, mHandler, Global.BUGREPORT_IN_POWER_MENU) {
-            @Override
-            protected void handleValueChanged(int value) {
-                handleRefreshState(null);
-            }
-        };
-    }
-
-    @Override
-    protected State newTileState() {
-        return new State();
-    }
-
-    @Override
-    public void setListening(boolean listening) {
-        mSetting.setListening(listening);
-    }
-
-    @Override
-    protected void handleClick() {
-        mHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                mHost.collapsePanels();
-                mUiHandler.post(mShowDialog);
-            }
-        });
-    }
-
-    @Override
-    protected void handleUpdateState(State state, Object pushArg) {
-        state.visible = mSetting.getValue() != 0;
-        state.iconId = R.drawable.ic_qs_bugreport;
-        state.label = mContext.getString(
-                R.string.bugreport_tile_extended,
-                mContext.getString(com.android.internal.R.string.bugreport_title),
-                Build.VERSION.RELEASE,
-                Build.ID);
-    }
-
-    private final Runnable mShowDialog = new Runnable() {
-        @Override
-        public void run() {
-            final AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
-            builder.setPositiveButton(com.android.internal.R.string.report, new OnClickListener() {
-                @Override
-                public void onClick(DialogInterface dialog, int which) {
-                    if (which == DialogInterface.BUTTON_POSITIVE) {
-                        // Add a little delay before executing, to give the
-                        // dialog a chance to go away before it takes a
-                        // screenshot.
-                        mHandler.postDelayed(new Runnable() {
-                            @Override public void run() {
-                                try {
-                                    ActivityManagerNative.getDefault().requestBugReport();
-                                } catch (RemoteException e) {
-                                }
-                            }
-                        }, 500);
-                    }
-                }
-            });
-            builder.setMessage(com.android.internal.R.string.bugreport_message);
-            builder.setTitle(com.android.internal.R.string.bugreport_title);
-            builder.setCancelable(true);
-            final Dialog dialog = builder.create();
-            dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
-            try {
-                WindowManagerGlobal.getWindowManagerService().dismissKeyguard();
-            } catch (RemoteException e) {
-            }
-            dialog.show();
-        }
-    };
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index 21254d4..edb5932 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -29,6 +29,8 @@
     private final SecureSetting mSetting;
     private final UsageTracker mUsageTracker;
 
+    private boolean mListening;
+
     public ColorInversionTile(Host host) {
         super(host);
 
@@ -36,18 +38,25 @@
                 Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED) {
             @Override
             protected void handleValueChanged(int value) {
-                handleRefreshState(value);
                 mUsageTracker.trackUsage();
+                if (mListening) {
+                    handleRefreshState(value);
+                }
             }
         };
         mUsageTracker = new UsageTracker(host.getContext(), ColorInversionTile.class);
+        if (mSetting.getValue() != 0 && !mUsageTracker.isRecentlyUsed()) {
+            mUsageTracker.trackUsage();
+        }
         mUsageTracker.setListening(true);
+        mSetting.setListening(true);
     }
 
     @Override
     protected void handleDestroy() {
         super.handleDestroy();
         mUsageTracker.setListening(false);
+        mSetting.setListening(false);
     }
 
     @Override
@@ -57,7 +66,7 @@
 
     @Override
     public void setListening(boolean listening) {
-        mSetting.setListening(listening);
+        mListening = listening;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 5651d49..a8bf026 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -132,8 +132,12 @@
         }
         state.contentDescription = mContext.getString(
                 R.string.accessibility_quick_settings_wifi,
-                signalContentDescription,
-                state.connected ? state.label : "");
+                signalContentDescription);
+        String wifiName = state.label;
+        if (state.connected) {
+            wifiName = r.getString(R.string.accessibility_wifi_name, state.label);
+        }
+        state.dualLabelContentDescription = wifiName;
     }
 
     private static String removeDoubleQuotes(String string) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
index 667faa7..f0bdfa2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
@@ -53,7 +53,7 @@
 
     // Log function
     static final float XScale = 1.75f;  // The large the XScale, the longer the flat area of the curve
-    static final float LogBase = 300;
+    static final float LogBase = 3000;
     static final int PrecisionSteps = 250;
     static float[] xp;
     static float[] px;
@@ -84,7 +84,7 @@
                 left + size, mStackRect.top + size);
 
         // Update the affiliation offsets
-        float visibleTaskPct = 0.55f;
+        float visibleTaskPct = 0.5f;
         mWithinAffiliationOffset = mConfig.taskBarHeight;
         mBetweenAffiliationOffset = (int) (visibleTaskPct * mTaskRect.height());
     }
@@ -312,4 +312,4 @@
         }
         return px[xFloorIndex] + pFraction;
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 5914b39..e514c90 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -21,12 +21,14 @@
 import android.animation.ValueAnimator;
 import android.content.Context;
 import android.graphics.Color;
+import android.graphics.Outline;
 import android.graphics.Paint;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.View;
+import android.view.ViewOutlineProvider;
 import android.view.animation.AccelerateInterpolator;
 import android.widget.FrameLayout;
 import com.android.systemui.R;
@@ -57,7 +59,7 @@
     ObjectAnimator mDimAnimator;
     float mMaxDimScale;
     int mDim;
-    AccelerateInterpolator mDimInterpolator = new AccelerateInterpolator(1.25f);
+    AccelerateInterpolator mDimInterpolator = new AccelerateInterpolator(1f);
     PorterDuffColorFilter mDimColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.MULTIPLY);
 
     Task mTask;
@@ -129,6 +131,14 @@
         mHeaderView = (TaskViewHeader) findViewById(R.id.task_view_bar);
         mThumbnailView = (TaskViewThumbnail) findViewById(R.id.task_view_thumbnail);
         mActionButtonView = findViewById(R.id.lock_to_app_fab);
+        mActionButtonView.setOutlineProvider(new ViewOutlineProvider() {
+            @Override
+            public void getOutline(View view, Outline outline) {
+                // Set the outline to match the FAB background
+                outline.setOval(0, 0, mActionButtonView.getWidth(),
+                        mActionButtonView.getHeight());
+            }
+        });
         if (mFooterView != null) {
             mFooterView.setCallbacks(this);
         }
@@ -469,7 +479,8 @@
             boolean occludesLaunchTarget) {
         if (isLaunchingTask) {
             // Disable the thumbnail clip and animate the bar out for the window animation out
-            mHeaderView.startLaunchTaskAnimation(mThumbnailView.disableTaskBarClipAsRunnable(), r);
+            mHeaderView.startLaunchTaskAnimation(mThumbnailView.disableTaskBarClipAsRunnable(), r,
+                    mIsFocused);
             // Animate the thumbnail alpha back into full opacity for the window animation out
             mThumbnailView.startLaunchTaskAnimation();
 
@@ -624,7 +635,7 @@
     public void setDim(int dim) {
         mDim = dim;
         // Defer setting hardware layers if we have not yet measured, or there is no dim to draw
-        if (getMeasuredWidth() > 0 && getMeasuredHeight() > 0 && dim > 0) {
+        if (getMeasuredWidth() > 0 && getMeasuredHeight() > 0) {
             if (mDimAnimator != null) {
                 mDimAnimator.removeAllListeners();
                 mDimAnimator.cancel();
@@ -828,6 +839,10 @@
                 } else if (v == mHeaderView.mDismissButton) {
                     dismissTask();
                 } else {
+                    if (v == mActionButtonView) {
+                        // Reset the translation of the action button before we animate it out
+                        mActionButtonView.setTranslationZ(0f);
+                    }
                     mCb.onTaskViewClicked(tv, tv.getTask(),
                             (v == mFooterView || v == mActionButtonView));
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index 4b09549..c7198fe 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -18,7 +18,9 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
 import android.animation.ArgbEvaluator;
+import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.content.Context;
 import android.content.res.ColorStateList;
@@ -59,7 +61,8 @@
     ColorDrawable mBackgroundColor;
     Drawable mLightDismissDrawable;
     Drawable mDarkDismissDrawable;
-    ValueAnimator mBackgroundColorAnimator;
+    AnimatorSet mFocusAnimator;
+    ValueAnimator backgroundColorAnimator;
 
     boolean mIsFullscreen;
     boolean mCurrentPrimaryColorIsDark;
@@ -117,6 +120,14 @@
 
     @Override
     protected void onFinishInflate() {
+        // Set the outline provider
+        setOutlineProvider(new ViewOutlineProvider() {
+            @Override
+            public void getOutline(View view, Outline outline) {
+                outline.setRect(0, 0, getMeasuredWidth(), getMeasuredHeight());
+            }
+        });
+
         // Initialize the icon and description views
         mApplicationIcon = (ImageView) findViewById(R.id.application_icon);
         mActivityDescription = (TextView) findViewById(R.id.activity_description);
@@ -211,23 +222,29 @@
     void startEnterRecentsAnimation(int delay, Runnable postAnimRunnable) {
         // Animate the task bar of the first task view
         setVisibility(View.VISIBLE);
-        setTranslationY(-getMeasuredHeight());
+        setAlpha(0f);
         animate()
-                .translationY(0)
+                .alpha(1f)
                 .setStartDelay(delay)
-                .setInterpolator(mConfig.fastOutSlowInInterpolator)
+                .setInterpolator(mConfig.linearOutSlowInInterpolator)
                 .setDuration(mConfig.taskBarEnterAnimDuration)
                 .withEndAction(postAnimRunnable)
+                .withLayer()
                 .start();
     }
 
     /** Animates this task bar as it exits recents */
-    void startLaunchTaskAnimation(Runnable preAnimRunnable, final Runnable postAnimRunnable) {
+    void startLaunchTaskAnimation(Runnable preAnimRunnable, final Runnable postAnimRunnable,
+            boolean isFocused) {
+        if (isFocused) {
+            onTaskViewFocusChanged(false);
+        }
+
         // Animate the task bar out of the first task view
         animate()
-                .translationY(-getMeasuredHeight())
+                .alpha(0f)
                 .setStartDelay(0)
-                .setInterpolator(mConfig.fastOutLinearInInterpolator)
+                .setInterpolator(mConfig.linearOutSlowInInterpolator)
                 .setDuration(mConfig.taskBarExitAnimDuration)
                 .withStartAction(preAnimRunnable)
                 .withEndAction(new Runnable() {
@@ -236,6 +253,7 @@
                         post(postAnimRunnable);
                     }
                 })
+                .withLayer()
                 .start();
     }
 
@@ -278,10 +296,10 @@
     /** Notifies the associated TaskView has been focused. */
     void onTaskViewFocusChanged(boolean focused) {
         boolean isRunning = false;
-        if (mBackgroundColorAnimator != null) {
-            isRunning = mBackgroundColorAnimator.isRunning();
-            mBackgroundColorAnimator.removeAllUpdateListeners();
-            mBackgroundColorAnimator.cancel();
+        if (mFocusAnimator != null) {
+            isRunning = mFocusAnimator.isRunning();
+            mFocusAnimator.removeAllListeners();
+            mFocusAnimator.cancel();
         }
         if (focused) {
             int secondaryColor = getSecondaryColor(mCurrentPrimaryColor, mCurrentPrimaryColorIsDark);
@@ -302,42 +320,54 @@
             // Pulse the background color
             int currentColor = mBackgroundColor.getColor();
             int lightPrimaryColor = getSecondaryColor(mCurrentPrimaryColor, mCurrentPrimaryColorIsDark);
-            mBackgroundColorAnimator = ValueAnimator.ofObject(new ArgbEvaluator(), lightPrimaryColor,
-                    currentColor);
-            mBackgroundColorAnimator.addListener(new AnimatorListenerAdapter() {
+            ValueAnimator backgroundColor = ValueAnimator.ofObject(new ArgbEvaluator(),
+                    lightPrimaryColor, currentColor);
+            backgroundColor.addListener(new AnimatorListenerAdapter() {
                 @Override
                 public void onAnimationStart(Animator animation) {
-                    mBackground.setState(new int[] {});
+                    mBackground.setState(new int[]{});
                 }
             });
-            mBackgroundColorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            backgroundColor.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                 @Override
                 public void onAnimationUpdate(ValueAnimator animation) {
                     mBackgroundColor.setColor((Integer) animation.getAnimatedValue());
                 }
             });
-            mBackgroundColorAnimator.setRepeatCount(ValueAnimator.INFINITE);
-            mBackgroundColorAnimator.setRepeatMode(ValueAnimator.REVERSE);
-            mBackgroundColorAnimator.setStartDelay(750);
-            mBackgroundColorAnimator.setDuration(750);
-            mBackgroundColorAnimator.start();
+            backgroundColor.setRepeatCount(ValueAnimator.INFINITE);
+            backgroundColor.setRepeatMode(ValueAnimator.REVERSE);
+            // Pulse the translation
+            ObjectAnimator translation = ObjectAnimator.ofFloat(this, "translationZ", 15f);
+            translation.setRepeatCount(ValueAnimator.INFINITE);
+            translation.setRepeatMode(ValueAnimator.REVERSE);
+
+            mFocusAnimator = new AnimatorSet();
+            mFocusAnimator.playTogether(backgroundColor, translation);
+            mFocusAnimator.setStartDelay(750);
+            mFocusAnimator.setDuration(750);
+            mFocusAnimator.start();
         } else {
             if (isRunning) {
                 // Restore the background color
                 int currentColor = mBackgroundColor.getColor();
-                mBackgroundColorAnimator = ValueAnimator.ofObject(new ArgbEvaluator(), currentColor,
-                        mCurrentPrimaryColor);
-                mBackgroundColorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+                ValueAnimator backgroundColor = ValueAnimator.ofObject(new ArgbEvaluator(),
+                        currentColor, mCurrentPrimaryColor);
+                backgroundColor.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                     @Override
                     public void onAnimationUpdate(ValueAnimator animation) {
                         mBackgroundColor.setColor((Integer) animation.getAnimatedValue());
                     }
                 });
-                mBackgroundColorAnimator.setRepeatCount(0);
-                mBackgroundColorAnimator.setDuration(150);
-                mBackgroundColorAnimator.start();
+                // Restore the translation
+                ObjectAnimator translation = ObjectAnimator.ofFloat(this, "translationZ", 0f);
+
+                mFocusAnimator = new AnimatorSet();
+                mFocusAnimator.playTogether(backgroundColor, translation);
+                mFocusAnimator.setDuration(150);
+                mFocusAnimator.start();
             } else {
                 mBackground.setState(new int[] {});
+                setTranslationZ(0f);
             }
         }
     }
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 42ae0c9..d398bc1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -36,7 +36,6 @@
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 import android.widget.TextView;
-
 import com.android.systemui.R;
 import com.android.systemui.qs.QSPanel;
 import com.android.systemui.statusbar.ExpandableView;
@@ -160,6 +159,7 @@
     private boolean mShadeEmpty;
 
     private boolean mQsScrimEnabled = true;
+    private boolean mLastAnnouncementWasQuickSettings;
 
     public NotificationPanelView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -425,8 +425,8 @@
     @Override
     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
         if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
-            event.getText()
-                    .add(getContext().getString(R.string.accessibility_desc_notification_shade));
+            event.getText().add(getKeyguardOrLockScreenString());
+            mLastAnnouncementWasQuickSettings = false;
             return true;
         }
 
@@ -987,6 +987,10 @@
             setQsExpanded(true);
         } else if (height <= mQsMinExpansionHeight && mQsExpanded) {
             setQsExpanded(false);
+            if (mLastAnnouncementWasQuickSettings && !mTracking) {
+                announceForAccessibility(getKeyguardOrLockScreenString());
+                mLastAnnouncementWasQuickSettings = false;
+            }
         }
         mQsExpansionHeight = height;
         mHeader.setExpansion(getHeaderExpansionFraction());
@@ -1000,6 +1004,22 @@
                 && !mStackScrollerOverscrolling && mQsScrimEnabled) {
             mQsNavbarScrim.setAlpha(getQsExpansionFraction());
         }
+
+        // Upon initialisation when we are not layouted yet we don't want to announce that we are
+        // fully expanded, hence the != 0.0f check.
+        if (height != 0.0f && mQsFullyExpanded && !mLastAnnouncementWasQuickSettings) {
+            announceForAccessibility(getContext().getString(
+                    R.string.accessibility_desc_quick_settings));
+            mLastAnnouncementWasQuickSettings = true;
+        }
+    }
+
+    private String getKeyguardOrLockScreenString() {
+        if (mStatusBarState == StatusBarState.KEYGUARD) {
+            return getContext().getString(R.string.accessibility_desc_lock_screen);
+        } else {
+            return getContext().getString(R.string.accessibility_desc_notification_shade);
+        }
     }
 
     private void updateNotificationScrim(float height) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 4e9f37d..15a7047 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -602,6 +602,8 @@
             mPhoneSignalIconId = R.drawable.stat_sys_signal_null;
             mQSPhoneSignalIconId = R.drawable.ic_qs_signal_no_signal;
             mDataSignalIconId = R.drawable.stat_sys_signal_null;
+            mContentDescriptionPhoneSignal = mContext.getString(
+                    AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0]);
         } else {
             if (mSignalStrength == null) {
                 if (CHATTY) Log.d(TAG, "updateTelephonySignalStrength: mSignalStrength == null");
@@ -665,8 +667,7 @@
                         mDataIconList = TelephonyIcons.DATA_G[mInetCondition];
                         mDataTypeIconId = 0;
                         mQSDataTypeIconId = 0;
-                        mContentDescriptionDataType = mContext.getString(
-                                R.string.accessibility_data_connection_gprs);
+                        mContentDescriptionDataType = "";
                         break;
                     } else {
                         // fall through
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 47e3e73..d53aa47 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -508,9 +508,9 @@
             setTitle(R.string.guest_exit_guest_dialog_title);
             setMessage(context.getString(R.string.guest_exit_guest_dialog_message));
             setButton(DialogInterface.BUTTON_NEGATIVE,
-                    context.getString(android.R.string.no), this);
+                    context.getString(android.R.string.cancel), this);
             setButton(DialogInterface.BUTTON_POSITIVE,
-                    context.getString(android.R.string.yes), this);
+                    context.getString(R.string.guest_exit_guest_dialog_remove), this);
             setCanceledOnTouchOutside(false);
             mGuestId = guestId;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index b05c242..51876b8 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -37,7 +37,7 @@
 import android.media.ToneGenerator;
 import android.media.VolumeProvider;
 import android.media.session.MediaController;
-import android.media.session.MediaController.VolumeInfo;
+import android.media.session.MediaController.AudioInfo;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.Message;
@@ -537,8 +537,8 @@
             if (mStreamControls != null) {
                 StreamControl sc = mStreamControls.get(streamType);
                 if (sc != null && sc.controller != null) {
-                    VolumeInfo vi = sc.controller.getVolumeInfo();
-                    return vi.getMaxVolume();
+                    AudioInfo ai = sc.controller.getAudioInfo();
+                    return ai.getMaxVolume();
                 }
             }
             return -1;
@@ -554,8 +554,8 @@
             if (mStreamControls != null) {
                 StreamControl sc = mStreamControls.get(streamType);
                 if (sc != null && sc.controller != null) {
-                    VolumeInfo vi = sc.controller.getVolumeInfo();
-                    return vi.getCurrentVolume();
+                    AudioInfo ai = sc.controller.getAudioInfo();
+                    return ai.getCurrentVolume();
                 }
             }
             return -1;
@@ -990,7 +990,7 @@
                     // We still don't have one, ignore the command.
                     Log.w(mTag, "sent remote volume change without a controller!");
                 } else {
-                    VolumeInfo vi = controller.getVolumeInfo();
+                    AudioInfo vi = controller.getAudioInfo();
                     index = vi.getCurrentVolume();
                     max = vi.getMaxVolume();
                     if ((vi.getVolumeControl() & VolumeProvider.VOLUME_CONTROL_FIXED) != 0) {
@@ -1362,7 +1362,7 @@
     };
 
     private final MediaController.Callback mMediaControllerCb = new MediaController.Callback() {
-        public void onVolumeInfoChanged(VolumeInfo info) {
+        public void onAudioInfoChanged(AudioInfo info) {
             onRemoteVolumeUpdateIfShown();
         }
     };
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 964acbd..73358c8 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -3559,6 +3559,10 @@
         if (transitionId != -1 && transitionId != R.transition.no_transition) {
             TransitionInflater inflater = TransitionInflater.from(getContext());
             transition = inflater.inflateTransition(transitionId);
+            if (transition instanceof TransitionSet &&
+                    ((TransitionSet)transition).getTransitionCount() == 0) {
+                transition = null;
+            }
         }
         return transition;
     }
diff --git a/rs/java/android/renderscript/Allocation.java b/rs/java/android/renderscript/Allocation.java
index 7db85f2..3cda6de 100644
--- a/rs/java/android/renderscript/Allocation.java
+++ b/rs/java/android/renderscript/Allocation.java
@@ -1868,7 +1868,7 @@
         }
     }
 
-    static void sendBufferNotification(int id) {
+    static void sendBufferNotification(long id) {
         synchronized(mAllocationMap) {
             Allocation a = mAllocationMap.get(new Long(id));
 
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 340efef..6c5c508 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -1156,7 +1156,12 @@
                 }
 
                 if (msg == RS_MESSAGE_TO_CLIENT_NEW_BUFFER) {
-                    Allocation.sendBufferNotification(subID);
+                    if (mRS.nContextGetUserMessage(mRS.mContext, rbuf) !=
+                        RS_MESSAGE_TO_CLIENT_NEW_BUFFER) {
+                        throw new RSDriverException("Error processing message from RenderScript.");
+                    }
+                    long bufferID = ((long)rbuf[1] << 32L) + ((long)rbuf[0] & 0xffffffffL);
+                    Allocation.sendBufferNotification(bufferID);
                     continue;
                 }
 
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 16df377..13a649a 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -222,7 +222,7 @@
 nDeviceCreate(JNIEnv *_env, jobject _this)
 {
     LOG_API("nDeviceCreate");
-    return (jlong)rsDeviceCreate();
+    return (jlong)(uintptr_t)rsDeviceCreate();
 }
 
 static void
@@ -243,7 +243,7 @@
 nContextCreate(JNIEnv *_env, jobject _this, jlong dev, jint ver, jint sdkVer, jint ct)
 {
     LOG_API("nContextCreate");
-    return (jlong)rsContextCreate((RsDevice)dev, ver, sdkVer, (RsContextType)ct, 0);
+    return (jlong)(uintptr_t)rsContextCreate((RsDevice)dev, ver, sdkVer, (RsContextType)ct, 0);
 }
 
 static jlong
@@ -267,7 +267,7 @@
     sc.samplesQ = samplesQ;
 
     LOG_API("nContextCreateGL");
-    return (jlong)rsContextCreateGL((RsDevice)dev, ver, sdkVer, sc, dpi);
+    return (jlong)(uintptr_t)rsContextCreateGL((RsDevice)dev, ver, sdkVer, sc, dpi);
 }
 
 static void
@@ -409,7 +409,7 @@
 nElementCreate(JNIEnv *_env, jobject _this, jlong con, jlong type, jint kind, jboolean norm, jint size)
 {
     LOG_API("nElementCreate, con(%p), type(%i), kind(%i), norm(%i), size(%i)", (RsContext)con, type, kind, norm, size);
-    return (jlong)rsElementCreate((RsContext)con, (RsDataType)type, (RsDataKind)kind, norm, size);
+    return (jlong)(uintptr_t)rsElementCreate((RsContext)con, (RsDataType)type, (RsDataKind)kind, norm, size);
 }
 
 static jlong
@@ -435,7 +435,7 @@
     const char **nameArray = names.c_str();
     size_t *sizeArray = names.c_str_len();
 
-    jlong id = (jlong)rsElementCreate2((RsContext)con,
+    jlong id = (jlong)(uintptr_t)rsElementCreate2((RsContext)con,
                                      (const RsElement *)ids, fieldCount,
                                      nameArray, fieldCount * sizeof(size_t),  sizeArray,
                                      (const uint32_t *)arraySizes, fieldCount);
@@ -445,7 +445,7 @@
     _env->ReleaseLongArrayElements(_ids, jIds, JNI_ABORT);
     _env->ReleaseIntArrayElements(_arraySizes, jArraySizes, JNI_ABORT);
 
-    return (jlong)id;
+    return (jlong)(uintptr_t)id;
 }
 
 static void
@@ -483,7 +483,7 @@
     rsaElementGetSubElements((RsContext)con, (RsElement)id, ids, names, arraySizes, (uint32_t)dataSize);
 
     for(uint32_t i = 0; i < dataSize; i++) {
-        const jlong id = (jlong)ids[i];
+        const jlong id = (jlong)(uintptr_t)ids[i];
         const jint arraySize = (jint)arraySizes[i];
         _env->SetObjectArrayElement(_names, i, _env->NewStringUTF(names[i]));
         _env->SetLongArrayRegion(_IDs, i, 1, &id);
@@ -504,7 +504,7 @@
     LOG_API("nTypeCreate, con(%p) eid(%p), x(%i), y(%i), z(%i), mips(%i), faces(%i), yuv(%i)",
             (RsContext)con, eid, dimx, dimy, dimz, mips, faces, yuv);
 
-    return (jlong)rsTypeCreate((RsContext)con, (RsElement)eid, dimx, dimy, dimz, mips, faces, yuv);
+    return (jlong)(uintptr_t)rsTypeCreate((RsContext)con, (RsElement)eid, dimx, dimy, dimz, mips, faces, yuv);
 }
 
 static void
@@ -521,7 +521,7 @@
     rsaTypeGetNativeData((RsContext)con, (RsType)id, typeData, 6);
 
     for(jint i = 0; i < elementCount; i ++) {
-        const jlong data = (jlong)typeData[i];
+        const jlong data = (jlong)(uintptr_t)typeData[i];
         _env->SetLongArrayRegion(_typeData, i, 1, &data);
     }
 }
@@ -532,7 +532,7 @@
 nAllocationCreateTyped(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mips, jint usage, jlong pointer)
 {
     LOG_API("nAllocationCreateTyped, con(%p), type(%p), mip(%i), usage(%i), ptr(%p)", (RsContext)con, (RsElement)type, mips, usage, (void *)pointer);
-    return (jlong) rsAllocationCreateTyped((RsContext)con, (RsType)type, (RsAllocationMipmapControl)mips, (uint32_t)usage, (uintptr_t)pointer);
+    return (jlong)(uintptr_t) rsAllocationCreateTyped((RsContext)con, (RsType)type, (RsAllocationMipmapControl)mips, (uint32_t)usage, (uintptr_t)pointer);
 }
 
 static void
@@ -600,7 +600,7 @@
 
     bitmap.lockPixels();
     const void* ptr = bitmap.getPixels();
-    jlong id = (jlong)rsAllocationCreateFromBitmap((RsContext)con,
+    jlong id = (jlong)(uintptr_t)rsAllocationCreateFromBitmap((RsContext)con,
                                                   (RsType)type, (RsAllocationMipmapControl)mip,
                                                   ptr, bitmap.getSize(), usage);
     bitmap.unlockPixels();
@@ -616,7 +616,7 @@
 
     bitmap.lockPixels();
     const void* ptr = bitmap.getPixels();
-    jlong id = (jlong)rsAllocationCreateTyped((RsContext)con,
+    jlong id = (jlong)(uintptr_t)rsAllocationCreateTyped((RsContext)con,
                                             (RsType)type, (RsAllocationMipmapControl)mip,
                                             (uint32_t)usage, (uintptr_t)ptr);
     bitmap.unlockPixels();
@@ -632,7 +632,7 @@
 
     bitmap.lockPixels();
     const void* ptr = bitmap.getPixels();
-    jlong id = (jlong)rsAllocationCubeCreateFromBitmap((RsContext)con,
+    jlong id = (jlong)(uintptr_t)rsAllocationCubeCreateFromBitmap((RsContext)con,
                                                       (RsType)type, (RsAllocationMipmapControl)mip,
                                                       ptr, bitmap.getSize(), usage);
     bitmap.unlockPixels();
@@ -810,7 +810,7 @@
 nAllocationGetType(JNIEnv *_env, jobject _this, jlong con, jlong a)
 {
     LOG_API("nAllocationGetType, con(%p), a(%p)", (RsContext)con, (RsAllocation)a);
-    return (jlong) rsaAllocationGetType((RsContext)con, (RsAllocation)a);
+    return (jlong)(uintptr_t) rsaAllocationGetType((RsContext)con, (RsAllocation)a);
 }
 
 static void
@@ -828,7 +828,7 @@
     Asset* asset = reinterpret_cast<Asset*>(native_asset);
     ALOGV("______nFileA3D %p", asset);
 
-    jlong id = (jlong)rsaFileA3DCreateFromMemory((RsContext)con, asset->getBuffer(false), asset->getLength());
+    jlong id = (jlong)(uintptr_t)rsaFileA3DCreateFromMemory((RsContext)con, asset->getBuffer(false), asset->getLength());
     return id;
 }
 
@@ -846,7 +846,7 @@
         return 0;
     }
 
-    jlong id = (jlong)rsaFileA3DCreateFromAsset((RsContext)con, asset);
+    jlong id = (jlong)(uintptr_t)rsaFileA3DCreateFromAsset((RsContext)con, asset);
     return id;
 }
 
@@ -854,7 +854,7 @@
 nFileA3DCreateFromFile(JNIEnv *_env, jobject _this, jlong con, jstring fileName)
 {
     AutoJavaStringToUTF8 fileNameUTF(_env, fileName);
-    jlong id = (jlong)rsaFileA3DCreateFromFile((RsContext)con, fileNameUTF.c_str());
+    jlong id = (jlong)(uintptr_t)rsaFileA3DCreateFromFile((RsContext)con, fileNameUTF.c_str());
 
     return id;
 }
@@ -887,7 +887,7 @@
 nFileA3DGetEntryByIndex(JNIEnv *_env, jobject _this, jlong con, jlong fileA3D, jint index)
 {
     ALOGV("______nFileA3D %p", (RsFile) fileA3D);
-    jlong id = (jlong)rsaFileA3DGetEntryByIndex((RsContext)con, (uint32_t)index, (RsFile)fileA3D);
+    jlong id = (jlong)(uintptr_t)rsaFileA3DGetEntryByIndex((RsContext)con, (uint32_t)index, (RsFile)fileA3D);
     return id;
 }
 
@@ -898,7 +898,7 @@
                     jstring fileName, jfloat fontSize, jint dpi)
 {
     AutoJavaStringToUTF8 fileNameUTF(_env, fileName);
-    jlong id = (jlong)rsFontCreateFromFile((RsContext)con,
+    jlong id = (jlong)(uintptr_t)rsFontCreateFromFile((RsContext)con,
                                          fileNameUTF.c_str(), fileNameUTF.length(),
                                          fontSize, dpi);
 
@@ -912,7 +912,7 @@
     Asset* asset = reinterpret_cast<Asset*>(native_asset);
     AutoJavaStringToUTF8 nameUTF(_env, name);
 
-    jlong id = (jlong)rsFontCreateFromMemory((RsContext)con,
+    jlong id = (jlong)(uintptr_t)rsFontCreateFromMemory((RsContext)con,
                                            nameUTF.c_str(), nameUTF.length(),
                                            fontSize, dpi,
                                            asset->getBuffer(false), asset->getLength());
@@ -934,7 +934,7 @@
         return 0;
     }
 
-    jlong id = (jlong)rsFontCreateFromMemory((RsContext)con,
+    jlong id = (jlong)(uintptr_t)rsFontCreateFromMemory((RsContext)con,
                                            str.c_str(), str.length(),
                                            fontSize, dpi,
                                            asset->getBuffer(false), asset->getLength());
@@ -1283,7 +1283,7 @@
 
     //rsScriptCSetText((RsContext)con, (const char *)script_ptr, length);
 
-    ret = (jlong)rsScriptCCreate((RsContext)con,
+    ret = (jlong)(uintptr_t)rsScriptCCreate((RsContext)con,
                                 resNameUTF.c_str(), resNameUTF.length(),
                                 cacheDirUTF.c_str(), cacheDirUTF.length(),
                                 (const char *)script_ptr, length);
@@ -1294,28 +1294,28 @@
                 _exception ? JNI_ABORT: 0);
     }
 
-    return (jlong)ret;
+    return (jlong)(uintptr_t)ret;
 }
 
 static jlong
 nScriptIntrinsicCreate(JNIEnv *_env, jobject _this, jlong con, jint id, jlong eid)
 {
     LOG_API("nScriptIntrinsicCreate, con(%p) id(%i) element(%p)", (RsContext)con, id, (void *)eid);
-    return (jlong)rsScriptIntrinsicCreate((RsContext)con, id, (RsElement)eid);
+    return (jlong)(uintptr_t)rsScriptIntrinsicCreate((RsContext)con, id, (RsElement)eid);
 }
 
 static jlong
 nScriptKernelIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot, jint sig)
 {
     LOG_API("nScriptKernelIDCreate, con(%p) script(%p), slot(%i), sig(%i)", (RsContext)con, (void *)sid, slot, sig);
-    return (jlong)rsScriptKernelIDCreate((RsContext)con, (RsScript)sid, slot, sig);
+    return (jlong)(uintptr_t)rsScriptKernelIDCreate((RsContext)con, (RsScript)sid, slot, sig);
 }
 
 static jlong
 nScriptFieldIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot)
 {
     LOG_API("nScriptFieldIDCreate, con(%p) script(%p), slot(%i)", (RsContext)con, (void *)sid, slot);
-    return (jlong)rsScriptFieldIDCreate((RsContext)con, (RsScript)sid, slot);
+    return (jlong)(uintptr_t)rsScriptFieldIDCreate((RsContext)con, (RsScript)sid, slot);
 }
 
 static jlong
@@ -1359,7 +1359,7 @@
         typesPtr[i] = (RsType)jTypesPtr[i];
     }
 
-    jlong id = (jlong)rsScriptGroupCreate((RsContext)con,
+    jlong id = (jlong)(uintptr_t)rsScriptGroupCreate((RsContext)con,
                                (RsScriptKernelID *)kernelsPtr, kernelsLen * sizeof(RsScriptKernelID),
                                (RsScriptKernelID *)srcPtr, srcLen * sizeof(RsScriptKernelID),
                                (RsScriptKernelID *)dstkPtr, dstkLen * sizeof(RsScriptKernelID),
@@ -1412,7 +1412,7 @@
                     jint depthFunc)
 {
     LOG_API("nProgramStoreCreate, con(%p)", (RsContext)con);
-    return (jlong)rsProgramStoreCreate((RsContext)con, colorMaskR, colorMaskG, colorMaskB, colorMaskA,
+    return (jlong)(uintptr_t)rsProgramStoreCreate((RsContext)con, colorMaskR, colorMaskG, colorMaskB, colorMaskA,
                                       depthMask, ditherEnable, (RsBlendSrcFunc)srcFunc,
                                       (RsBlendDstFunc)destFunc, (RsDepthFunc)depthFunc);
 }
@@ -1461,7 +1461,7 @@
     for(int i = 0; i < paramLen; ++i) {
         paramPtr[i] = (uintptr_t)jParamPtr[i];
     }
-    jlong ret = (jlong)rsProgramFragmentCreate((RsContext)con, shaderUTF.c_str(), shaderUTF.length(),
+    jlong ret = (jlong)(uintptr_t)rsProgramFragmentCreate((RsContext)con, shaderUTF.c_str(), shaderUTF.length(),
                                              nameArray, texCount, sizeArray,
                                              paramPtr, paramLen);
 
@@ -1493,7 +1493,7 @@
         paramPtr[i] = (uintptr_t)jParamPtr[i];
     }
 
-    jlong ret = (jlong)rsProgramVertexCreate((RsContext)con, shaderUTF.c_str(), shaderUTF.length(),
+    jlong ret = (jlong)(uintptr_t)rsProgramVertexCreate((RsContext)con, shaderUTF.c_str(), shaderUTF.length(),
                                            nameArray, texCount, sizeArray,
                                            paramPtr, paramLen);
 
@@ -1508,7 +1508,7 @@
 nProgramRasterCreate(JNIEnv *_env, jobject _this, jlong con, jboolean pointSprite, jint cull)
 {
     LOG_API("nProgramRasterCreate, con(%p), pointSprite(%i), cull(%i)", (RsContext)con, pointSprite, cull);
-    return (jlong)rsProgramRasterCreate((RsContext)con, pointSprite, (RsCullMode)cull);
+    return (jlong)(uintptr_t)rsProgramRasterCreate((RsContext)con, pointSprite, (RsCullMode)cull);
 }
 
 
@@ -1557,7 +1557,7 @@
                jint wrapS, jint wrapT, jint wrapR, jfloat aniso)
 {
     LOG_API("nSamplerCreate, con(%p)", (RsContext)con);
-    return (jlong)rsSamplerCreate((RsContext)con,
+    return (jlong)(uintptr_t)rsSamplerCreate((RsContext)con,
                                  (RsSamplerValue)magFilter,
                                  (RsSamplerValue)minFilter,
                                  (RsSamplerValue)wrapS,
@@ -1572,7 +1572,7 @@
 nPathCreate(JNIEnv *_env, jobject _this, jlong con, jint prim, jboolean isStatic, jlong _vtx, jlong _loop, jfloat q) {
     LOG_API("nPathCreate, con(%p)", (RsContext)con);
 
-    jlong id = (jlong)rsPathCreate((RsContext)con, (RsPathPrimitive)prim, isStatic,
+    jlong id = (jlong)(uintptr_t)rsPathCreate((RsContext)con, (RsPathPrimitive)prim, isStatic,
                                    (RsAllocation)_vtx,
                                    (RsAllocation)_loop, q);
     return id;
@@ -1600,7 +1600,7 @@
     jint primLen = _env->GetArrayLength(_prim);
     jint *primPtr = _env->GetIntArrayElements(_prim, NULL);
 
-    jlong id = (jlong)rsMeshCreate((RsContext)con,
+    jlong id = (jlong)(uintptr_t)rsMeshCreate((RsContext)con,
                                (RsAllocation *)vtxPtr, vtxLen,
                                (RsAllocation *)idxPtr, idxLen,
                                (uint32_t *)primPtr, primLen);
@@ -1640,7 +1640,7 @@
     rsaMeshGetVertices((RsContext)con, (RsMesh)mesh, allocs, (uint32_t)numVtxIDs);
 
     for(jint i = 0; i < numVtxIDs; i ++) {
-        const jlong alloc = (jlong)allocs[i];
+        const jlong alloc = (jlong)(uintptr_t)allocs[i];
         _env->SetLongArrayRegion(_ids, i, 1, &alloc);
     }
 
@@ -1658,7 +1658,7 @@
     rsaMeshGetIndices((RsContext)con, (RsMesh)mesh, allocs, prims, (uint32_t)numIndices);
 
     for(jint i = 0; i < numIndices; i ++) {
-        const jlong alloc = (jlong)allocs[i];
+        const jlong alloc = (jlong)(uintptr_t)allocs[i];
         const jint prim = (jint)prims[i];
         _env->SetLongArrayRegion(_idxIds, i, 1, &alloc);
         _env->SetIntArrayRegion(_primitives, i, 1, &prim);
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index e0f9b9c..2e7b745 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -66,6 +66,7 @@
 import android.content.res.TypedArray;
 import android.database.ContentObserver;
 import android.inputmethodservice.InputMethodService;
+import android.net.Uri;
 import android.os.Binder;
 import android.os.Environment;
 import android.os.Handler;
@@ -392,6 +393,7 @@
     private InputMethodInfo[] mIms;
     private int[] mSubtypeIds;
     private Locale mLastSystemLocale;
+    private boolean mShowImeWithHardKeyboard;
     private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor();
     private final IPackageManager mIPackageManager;
 
@@ -407,17 +409,25 @@
                     Settings.Secure.ENABLED_INPUT_METHODS), false, this);
             resolver.registerContentObserver(Settings.Secure.getUriFor(
                     Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE), false, this);
+            resolver.registerContentObserver(Settings.Secure.getUriFor(
+                    Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD), false, this);
         }
 
-        @Override public void onChange(boolean selfChange) {
+        @Override public void onChange(boolean selfChange, Uri uri) {
+            final Uri showImeUri =
+                    Settings.Secure.getUriFor(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);
             synchronized (mMethodMap) {
-                boolean enabledChanged = false;
-                String newEnabled = mSettings.getEnabledInputMethodsStr();
-                if (!mLastEnabled.equals(newEnabled)) {
-                    mLastEnabled = newEnabled;
-                    enabledChanged = true;
+                if (showImeUri.equals(uri)) {
+                    updateKeyboardFromSettingsLocked();
+                } else {
+                    boolean enabledChanged = false;
+                    String newEnabled = mSettings.getEnabledInputMethodsStr();
+                    if (!mLastEnabled.equals(newEnabled)) {
+                        mLastEnabled = newEnabled;
+                        enabledChanged = true;
+                    }
+                    updateInputMethodsFromSettingsLocked(enabledChanged);
                 }
-                updateFromSettingsLocked(enabledChanged);
             }
         }
     }
@@ -598,16 +608,14 @@
     private class HardKeyboardListener
             implements WindowManagerService.OnHardKeyboardStatusChangeListener {
         @Override
-        public void onHardKeyboardStatusChange(boolean available, boolean enabled) {
-            mHandler.sendMessage(mHandler.obtainMessage(
-                    MSG_HARD_KEYBOARD_SWITCH_CHANGED, available ? 1 : 0, enabled ? 1 : 0));
+        public void onHardKeyboardStatusChange(boolean available) {
+            mHandler.sendMessage(mHandler.obtainMessage(MSG_HARD_KEYBOARD_SWITCH_CHANGED,
+                        available ? 1 : 0));
         }
 
-        public void handleHardKeyboardStatusChange(boolean available,
-                boolean showImeWithHardKeyboard) {
+        public void handleHardKeyboardStatusChange(boolean available) {
             if (DEBUG) {
-                Slog.w(TAG, "HardKeyboardStatusChanged: available = " + available
-                        + ", showImeWithHardKeyboard= " + showImeWithHardKeyboard);
+                Slog.w(TAG, "HardKeyboardStatusChanged: available=" + available);
             }
             synchronized(mMethodMap) {
                 if (mSwitchingDialog != null && mSwitchingDialogTitleView != null
@@ -1657,6 +1665,11 @@
     }
 
     void updateFromSettingsLocked(boolean enabledMayChange) {
+        updateInputMethodsFromSettingsLocked(enabledMayChange);
+        updateKeyboardFromSettingsLocked();
+    }
+
+    void updateInputMethodsFromSettingsLocked(boolean enabledMayChange) {
         if (enabledMayChange) {
             List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked();
             for (int i=0; i<enabled.size(); i++) {
@@ -1710,6 +1723,18 @@
         // TODO: Make sure that mSwitchingController and mSettings are sharing the
         // the same enabled IMEs list.
         mSwitchingController.resetCircularListLocked(mContext);
+
+    }
+
+    public void updateKeyboardFromSettingsLocked() {
+        mShowImeWithHardKeyboard = mSettings.isShowImeWithHardKeyboardEnabled();
+        if (mSwitchingDialog != null
+                && mSwitchingDialogTitleView != null
+                && mSwitchingDialog.isShowing()) {
+            final Switch hardKeySwitch = (Switch)mSwitchingDialogTitleView.findViewById(
+                    com.android.internal.R.id.hard_keyboard_switch);
+            hardKeySwitch.setChecked(mShowImeWithHardKeyboard);
+        }
     }
 
     /* package */ void setInputMethodLocked(String id, int subtypeId) {
@@ -2594,8 +2619,7 @@
 
             // --------------------------------------------------------------
             case MSG_HARD_KEYBOARD_SWITCH_CHANGED:
-                mHardKeyboardListener.handleHardKeyboardStatusChange(
-                        msg.arg1 == 1, msg.arg2 == 1);
+                mHardKeyboardListener.handleHardKeyboardStatusChange(msg.arg1 == 1);
                 return true;
         }
         return false;
@@ -2684,7 +2708,7 @@
             if (!map.containsKey(defaultImiId)) {
                 Slog.w(TAG, "Default IME is uninstalled. Choose new default IME.");
                 if (chooseNewDefaultIMELocked()) {
-                    updateFromSettingsLocked(true);
+                    updateInputMethodsFromSettingsLocked(true);
                 }
             } else {
                 // Double check that the default IME is certainly enabled.
@@ -2811,11 +2835,11 @@
                             ? View.VISIBLE : View.GONE);
             final Switch hardKeySwitch = (Switch)mSwitchingDialogTitleView.findViewById(
                     com.android.internal.R.id.hard_keyboard_switch);
-            hardKeySwitch.setChecked(mWindowManagerService.isShowImeWithHardKeyboardEnabled());
+            hardKeySwitch.setChecked(mShowImeWithHardKeyboard);
             hardKeySwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
                 @Override
                 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
-                    mWindowManagerService.setShowImeWithHardKeyboard(isChecked);
+                    mSettings.setShowImeWithHardKeyboard(isChecked);
                     // Ensure that the input method dialog is dismissed when changing
                     // the hardware keyboard state.
                     hideInputMethodMenu();
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index e528d57..abacb2d 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -575,6 +575,10 @@
 
     void makeFinishing() {
         if (!finishing) {
+            if (this == task.stack.getVisibleBehindActivity()) {
+                // A finishing activity should not remain as visible in the background
+                mStackSupervisor.requestVisibleBehindLocked(this, false);
+            }
             finishing = true;
             if (stopped) {
                 clearOptionsLocked();
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 1107139..931f448 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2659,13 +2659,20 @@
         }
 
         // A non-top activity is reporting a visibility change.
-        if (top.fullscreen || top.state != ActivityState.RESUMED || top.app == null ||
-                top.app.thread == null) {
+        if ((visible && (top.fullscreen || top.state != ActivityState.RESUMED)) ||
+                top.app == null || top.app.thread == null) {
             // Can't carry out this request.
             if (DEBUG_VISIBLE_BEHIND) Slog.d(TAG, "requestVisibleBehind: returning top.fullscreen="
-                    + top.fullscreen+ " top.state=" + top.state + " top.app=" + top.app +
+                    + top.fullscreen + " top.state=" + top.state + " top.app=" + top.app +
                     " top.app.thread=" + top.app.thread);
             return false;
+        } else if (!visible && stack.getVisibleBehindActivity() != r) {
+            // Only the activity set as currently visible behind should actively reset its
+            // visible behind state.
+            if (DEBUG_VISIBLE_BEHIND) Slog.d(TAG, "requestVisibleBehind: returning visible="
+                    + visible + " stack.getVisibleBehindActivity()=" +
+                    stack.getVisibleBehindActivity() + " r=" + r);
+            return false;
         }
 
         stack.setVisibleBehindActivity(visible ? r : null);
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 4c887dd..0dc163b 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -41,12 +41,17 @@
             String, Class<?>>();
     private static final Map<String, Class<?>> sSystemSettingToTypeMap = new HashMap<
             String, Class<?>>();
+    private static final Map<String, Class<?>> sGlobalSettingToTypeMap = new HashMap<
+            String, Class<?>>();
     static {
         sSecureSettingToTypeMap.put(Settings.Secure.LONG_PRESS_TIMEOUT, int.class);
         // add other secure settings here...
 
         sSystemSettingToTypeMap.put(Settings.System.TIME_12_24, String.class);
         // add other system settings here...
+
+        sGlobalSettingToTypeMap.put(Settings.Global.DEBUG_VIEW_ATTRIBUTES, int.class);
+        // add other global settings here...
     }
 
     private final Bundle mCoreSettings = new Bundle();
@@ -74,6 +79,7 @@
     private void sendCoreSettings() {
         populateSettings(mCoreSettings, sSecureSettingToTypeMap);
         populateSettings(mCoreSettings, sSystemSettingToTypeMap);
+        populateSettings(mCoreSettings, sGlobalSettingToTypeMap);
         mActivityManagerService.onCoreSettingsChange(mCoreSettings);
     }
 
@@ -89,6 +95,12 @@
             mActivityManagerService.mContext.getContentResolver().registerContentObserver(
                     uri, false, this);
         }
+
+        for (String setting : sGlobalSettingToTypeMap.keySet()) {
+            Uri uri = Settings.Global.getUriFor(setting);
+            mActivityManagerService.mContext.getContentResolver().registerContentObserver(
+                    uri, false, this);
+        }
     }
 
     private void populateSettings(Bundle snapshot, Map<String, Class<?>> map) {
@@ -101,32 +113,40 @@
                     final String value;
                     if (map == sSecureSettingToTypeMap) {
                         value = Settings.Secure.getString(context.getContentResolver(), setting);
-                    } else {
+                    } else if (map == sSystemSettingToTypeMap) {
                         value = Settings.System.getString(context.getContentResolver(), setting);
+                    } else {
+                        value = Settings.Global.getString(context.getContentResolver(), setting);
                     }
                     snapshot.putString(setting, value);
                 } else if (type == int.class) {
                     final int value;
                     if (map == sSecureSettingToTypeMap) {
                         value = Settings.Secure.getInt(context.getContentResolver(), setting);
-                    } else {
+                    } else if (map == sSystemSettingToTypeMap) {
                         value = Settings.System.getInt(context.getContentResolver(), setting);
+                    } else {
+                        value = Settings.Global.getInt(context.getContentResolver(), setting);
                     }
                     snapshot.putInt(setting, value);
                 } else if (type == float.class) {
                     final float value;
                     if (map == sSecureSettingToTypeMap) {
                         value = Settings.Secure.getFloat(context.getContentResolver(), setting);
-                    } else {
+                    } else if (map == sSystemSettingToTypeMap) {
                         value = Settings.System.getFloat(context.getContentResolver(), setting);
+                    } else {
+                        value = Settings.Global.getFloat(context.getContentResolver(), setting);
                     }
                     snapshot.putFloat(setting, value);
                 } else if (type == long.class) {
                     final long value;
                     if (map == sSecureSettingToTypeMap) {
                         value = Settings.Secure.getLong(context.getContentResolver(), setting);
-                    } else {
+                    } else if (map == sSystemSettingToTypeMap) {
                         value = Settings.System.getLong(context.getContentResolver(), setting);
+                    } else {
+                        value = Settings.Global.getLong(context.getContentResolver(), setting);
                     }
                     snapshot.putLong(setting, value);
                 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecKeycode.java b/services/core/java/com/android/server/hdmi/HdmiCecKeycode.java
index 46b2b3e..aed5dcc 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecKeycode.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecKeycode.java
@@ -155,7 +155,7 @@
     }
 
     /**
-     * A mapping between andorid and cec keycode.
+     * A mapping between Android and CEC keycode.
      *
      * <p>Normal implementation of this looks like
      * <pre>
@@ -174,43 +174,28 @@
     private static class KeycodeEntry {
         private final int mAndroidKeycode;
         private final int mCecKeycode;
-        private final int mParam;
         private final boolean mIsRepeatable;
 
-        private KeycodeEntry(int androidKeycode, int cecKeycode, int param, boolean isRepeatable) {
+        private KeycodeEntry(int androidKeycode, int cecKeycode, boolean isRepeatable) {
             mAndroidKeycode = androidKeycode;
             mCecKeycode = cecKeycode;
-            mParam = param;
             mIsRepeatable = isRepeatable;
         }
 
         private KeycodeEntry(int androidKeycode, int cecKeycode) {
-            this(androidKeycode, cecKeycode, NO_PARAM, true);
+            this(androidKeycode, cecKeycode, true);
         }
 
-        private KeycodeEntry(int androidKeycode, int cecKeycode, boolean isRepeatable) {
-            this(androidKeycode, cecKeycode, NO_PARAM, isRepeatable);
-        }
-
-        private byte[] toCecKeycodeIfMatched(int androidKeycode) {
+        private int toCecKeycodeIfMatched(int androidKeycode) {
             if (mAndroidKeycode == androidKeycode) {
-                if (mParam == NO_PARAM) {
-                    return new byte[] {
-                        (byte) (mCecKeycode & 0xFF)
-                    };
-                } else {
-                    return new byte[] {
-                        (byte) (mCecKeycode & 0xFF),
-                        (byte) (mParam & 0xFF)
-                    };
-                }
+                return mCecKeycode;
             } else {
-                return null;
+                return UNSUPPORTED_KEYCODE;
             }
         }
 
-        private int toAndroidKeycodeIfMatched(int cecKeycode, int param) {
-            if (cecKeycode == mCecKeycode && mParam == param) {
+        private int toAndroidKeycodeIfMatched(int cecKeycode) {
+            if (cecKeycode == mCecKeycode) {
                 return mAndroidKeycode;
             } else {
                 return UNSUPPORTED_KEYCODE;
@@ -365,29 +350,28 @@
      * Translate Android keycode to Hdmi Cec keycode.
      *
      * @param keycode Android keycode. For details, refer {@link KeyEvent}
-     * @return array of byte which contains cec keycode and param if it has;
-     *         return null if failed to find matched cec keycode
+     * @return single byte CEC keycode if matched.
      */
-    static byte[] androidKeyToCecKey(int keycode) {
+    static int androidKeyToCecKey(int keycode) {
         for (int i = 0; i < KEYCODE_ENTRIES.length; ++i) {
-            byte[] cecKeycode = KEYCODE_ENTRIES[i].toCecKeycodeIfMatched(keycode);
-            if (cecKeycode != null) {
+            int cecKeycode = KEYCODE_ENTRIES[i].toCecKeycodeIfMatched(keycode);
+            if (cecKeycode != UNSUPPORTED_KEYCODE) {
                 return cecKeycode;
             }
         }
-        return null;
+        return UNSUPPORTED_KEYCODE;
     }
 
     /**
      * Translate Hdmi CEC keycode to Android keycode.
      *
-     * @param keycode Cec keycode. If has no param, put {@link #NO_PARAM}
+     * @param keycode CEC keycode
      * @return cec keycode corresponding to the given android keycode.
      *         If finds no matched keycode, return {@link #UNSUPPORTED_KEYCODE}
      */
-    static int cecKeyToAndroidKey(int keycode, int param) {
+    static int cecKeyToAndroidKey(int keycode) {
         for (int i = 0; i < KEYCODE_ENTRIES.length; ++i) {
-            int androidKey = KEYCODE_ENTRIES[i].toAndroidKeycodeIfMatched(keycode, param);
+            int androidKey = KEYCODE_ENTRIES[i].toAndroidKeycodeIfMatched(keycode);
             if (androidKey != UNSUPPORTED_KEYCODE) {
                 return androidKey;
             }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index 4862f93..b43ad1b 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -405,8 +405,9 @@
 
         final long downTime = SystemClock.uptimeMillis();
         final byte[] params = message.getParams();
-        final int keycode = HdmiCecKeycode.cecKeyToAndroidKey(params[0],
-                params.length > 1 ? params[1] : HdmiCecKeycode.NO_PARAM);
+        // Note that we don't support parameterized keycode now.
+        // TODO: translate parameterized keycode as well.
+        final int keycode = HdmiCecKeycode.cecKeyToAndroidKey(params[0]);
         int keyRepeatCount = 0;
         if (mLastKeycode != HdmiCecKeycode.UNSUPPORTED_KEYCODE) {
             if (keycode == mLastKeycode) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 809fef4..126a56d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -1007,10 +1007,8 @@
     /**
      * Return external input devices.
      */
-    List<HdmiDeviceInfo> getSafeExternalInputs() {
-        synchronized (mLock) {
-            return mSafeExternalInputs;
-        }
+    List<HdmiDeviceInfo> getSafeExternalInputsLocked() {
+        return mSafeExternalInputs;
     }
 
     @ServiceThreadOnly
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 14c066e..4f4c723 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -16,6 +16,8 @@
 
 package com.android.server.hdmi;
 
+import static android.hardware.hdmi.HdmiControlManager.DEVICE_EVENT_ADD_DEVICE;
+import static android.hardware.hdmi.HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE;
 import static com.android.server.hdmi.Constants.DISABLED;
 import static com.android.server.hdmi.Constants.ENABLED;
 import static com.android.server.hdmi.Constants.OPTION_CEC_AUTO_WAKEUP;
@@ -202,6 +204,9 @@
     @GuardedBy("mLock")
     private boolean mMhlInputChangeEnabled;
 
+    @GuardedBy("mLock")
+    private List<HdmiDeviceInfo> mMhlDevices;
+
     // List of listeners registered by callers that want to get notified of
     // system audio mode changes.
     private final ArrayList<IHdmiSystemAudioModeChangeListener>
@@ -293,6 +298,7 @@
             Slog.i(TAG, "Device does not support MHL-control.");
         }
         initPortInfo();
+        mMhlDevices = Collections.emptyList();
         mMessageValidator = new HdmiCecMessageValidator(this);
         publishBinderService(Context.HDMI_CONTROL_SERVICE, new BinderService());
 
@@ -320,7 +326,6 @@
         }
     }
 
-
     private void registerContentObserver() {
         ContentResolver resolver = getContext().getContentResolver();
         String[] settings = new String[] {
@@ -330,7 +335,7 @@
                 Global.MHL_INPUT_SWITCHING_ENABLED,
                 Global.MHL_POWER_CHARGE_ENABLED
         };
-        for (String s: settings) {
+        for (String s : settings) {
             resolver.registerContentObserver(Global.getUriFor(s), false, mSettingsObserver,
                     UserHandle.USER_ALL);
         }
@@ -351,7 +356,7 @@
                     break;
                 case Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED:
                     tv().setAutoWakeup(enabled);
-                    setOption(OPTION_CEC_AUTO_WAKEUP, toInt(enabled));
+                    setCecOption(OPTION_CEC_AUTO_WAKEUP, toInt(enabled));
                     break;
                 case Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED:
                     tv().setAutoDeviceOff(enabled);
@@ -490,6 +495,10 @@
         }
     }
 
+    List<HdmiPortInfo> getPortInfo() {
+        return mPortInfo;
+    }
+
     /**
      * Returns HDMI port information for the given port id.
      *
@@ -684,16 +693,16 @@
     /**
      * Called when a new hotplug event is issued.
      *
-     * @param portNo hdmi port number where hot plug event issued.
+     * @param portId hdmi port number where hot plug event issued.
      * @param connected whether to be plugged in or not
      */
     @ServiceThreadOnly
-    void onHotplug(int portNo, boolean connected) {
+    void onHotplug(int portId, boolean connected) {
         assertRunOnServiceThread();
         for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) {
-            device.onHotplug(portNo, connected);
+            device.onHotplug(portId, connected);
         }
-        announceHotplugEvent(portNo, connected);
+        announceHotplugEvent(portId, connected);
     }
 
     /**
@@ -794,10 +803,15 @@
             HdmiMhlLocalDevice device = mMhlController.removeLocalDevice(portId);
             if (device != null) {
                 device.onDeviceRemoved();
+                // There is no explicit event for device removal unlike capability register event
+                // used for device addition . Hence we remove the device on hotplug event.
+                invokeDeviceEventListeners(device.getInfo(), DEVICE_EVENT_REMOVE_DEVICE);
+                updateSafeMhlInput();
             } else {
                 Slog.w(TAG, "No device to remove:[portId=" + portId);
             }
         }
+        announceHotplugEvent(portId, connected);
     }
 
     @ServiceThreadOnly
@@ -824,18 +838,45 @@
     }
 
     @ServiceThreadOnly
-    void handleCapabilityRegisterChanged(int portId, int adopterId, int deviceId) {
+    void handleMhlCapabilityRegisterChanged(int portId, int adopterId, int deviceId) {
         assertRunOnServiceThread();
         HdmiMhlLocalDevice device = mMhlController.getLocalDevice(portId);
-        // Hot plug event should be called before capability register change event.
+
+        // Hotplug event should already have been called before capability register change event.
         if (device != null) {
             device.setCapabilityRegister(adopterId, deviceId);
+            invokeDeviceEventListeners(device.getInfo(), DEVICE_EVENT_ADD_DEVICE);
+            updateSafeMhlInput();
         } else {
             Slog.w(TAG, "No mhl device exists for capability register change event[portId:"
                     + portId + ", adopterId:" + adopterId + ", deviceId:" + deviceId + "]");
         }
     }
 
+    @ServiceThreadOnly
+    private void updateSafeMhlInput() {
+        assertRunOnServiceThread();
+        List<HdmiDeviceInfo> inputs = Collections.emptyList();
+        SparseArray<HdmiMhlLocalDevice> devices = mMhlController.getAllLocalDevices();
+        for (int i = 0; i < devices.size(); ++i) {
+            HdmiMhlLocalDevice device = devices.valueAt(i);
+            HdmiDeviceInfo info = device.getInfo();
+            if (info != null) {
+                if (inputs.isEmpty()) {
+                    inputs = new ArrayList<>();
+                }
+                inputs.add(device.getInfo());
+            }
+        }
+        synchronized (mLock) {
+            mMhlDevices = inputs;
+        }
+    }
+
+    private List<HdmiDeviceInfo> getMhlDevicesLocked() {
+        return mMhlDevices;
+    }
+
     // Record class that monitors the event of the caller of being killed. Used to clean up
     // the listener list and record list accordingly.
     private final class HotplugEventListenerRecord implements IBinder.DeathRecipient {
@@ -1073,7 +1114,7 @@
         @Override
         public List<HdmiPortInfo> getPortInfo() {
             enforceAccessPermission();
-            return mPortInfo;
+            return HdmiControlService.this.getPortInfo();
         }
 
         @Override
@@ -1139,10 +1180,12 @@
             // No need to hold the lock for obtaining TV device as the local device instance
             // is preserved while the HDMI control is enabled.
             HdmiCecLocalDeviceTv tv = tv();
-            if (tv == null) {
-                return Collections.emptyList();
+            synchronized (mLock) {
+                List<HdmiDeviceInfo> cecDevices = (tv == null)
+                        ? Collections.<HdmiDeviceInfo>emptyList()
+                        : tv.getSafeExternalInputsLocked();
+                return HdmiUtils.mergeToUnmodifiableList(cecDevices, getMhlDevicesLocked());
             }
-            return tv.getSafeExternalInputs();
         }
 
         @Override
@@ -1644,11 +1687,17 @@
     }
 
     private void disableDevices(PendingActionClearedCallback callback) {
-        for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) {
-            device.disableDevice(mStandbyMessageReceived, callback);
+        if (mCecController != null) {
+            for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) {
+                device.disableDevice(mStandbyMessageReceived, callback);
+            }
+            if (isTvDevice()) {
+                unregisterSettingsObserver();
+            }
         }
-        if (isTvDevice()) {
-            unregisterSettingsObserver();
+
+        if (mMhlController != null) {
+            mMhlController.clearAllLocalDevices();
         }
     }
 
@@ -1720,7 +1769,7 @@
     }
 
     @ServiceThreadOnly
-    void setOption(int key, int value) {
+    void setCecOption(int key, int value) {
         assertRunOnServiceThread();
         mCecController.setOption(key, value);
     }
diff --git a/services/core/java/com/android/server/hdmi/HdmiUtils.java b/services/core/java/com/android/server/hdmi/HdmiUtils.java
index 23f19ff..22a519b 100644
--- a/services/core/java/com/android/server/hdmi/HdmiUtils.java
+++ b/services/core/java/com/android/server/hdmi/HdmiUtils.java
@@ -206,6 +206,22 @@
         return list;
     }
 
+    static <T> List<T> mergeToUnmodifiableList(List<T> a, List<T> b) {
+        if (a.isEmpty() && b.isEmpty()) {
+            return Collections.emptyList();
+        }
+        if (a.isEmpty()) {
+            return Collections.unmodifiableList(b);
+        }
+        if (b.isEmpty()) {
+            return Collections.unmodifiableList(a);
+        }
+        List<T> newList = new ArrayList<>();
+        newList.addAll(a);
+        newList.addAll(b);
+        return Collections.unmodifiableList(newList);
+    }
+
     /**
      * See if the new path is affecting the active path.
      *
diff --git a/services/core/java/com/android/server/hdmi/SendKeyAction.java b/services/core/java/com/android/server/hdmi/SendKeyAction.java
index 9f09eb4..ed978e0 100644
--- a/services/core/java/com/android/server/hdmi/SendKeyAction.java
+++ b/services/core/java/com/android/server/hdmi/SendKeyAction.java
@@ -109,12 +109,12 @@
     }
 
     private void sendKeyDown(int keycode) {
-        byte[] keycodeAndParam = getCecKeycodeAndParam(keycode);
-        if (keycodeAndParam == null) {
+        int cecKeycode = HdmiCecKeycode.androidKeyToCecKey(keycode);
+        if (cecKeycode == HdmiCecKeycode.UNSUPPORTED_KEYCODE) {
             return;
         }
         sendCommand(HdmiCecMessageBuilder.buildUserControlPressed(getSourceAddress(),
-                mTargetAddress, keycodeAndParam));
+                mTargetAddress, new byte[] { (byte) (cecKeycode & 0xFF) }));
     }
 
     private void sendKeyUp() {
@@ -141,13 +141,4 @@
         sendKeyDown(mLastKeycode);
         addTimer(mState, IRT_MS);
     }
-
-    // Converts the Android key code to corresponding CEC key code definition. Those CEC keys
-    // with additional parameters should be mapped from individual Android key code. 'Select
-    // Broadcast' with the parameter 'cable', for instance, shall have its counterpart such as
-    // KeyEvent.KEYCODE_TV_BROADCAST_CABLE.
-    // The return byte array contains both UI command (keycode) and optional parameter.
-    private byte[] getCecKeycodeAndParam(int keycode) {
-        return HdmiCecKeycode.androidKeyToCecKey(keycode);
-    }
 }
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index 289b5aa..69d1dc9 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -26,6 +26,8 @@
 import android.media.projection.IMediaProjectionManager;
 import android.media.projection.IMediaProjection;
 import android.media.projection.IMediaProjectionCallback;
+import android.media.projection.IMediaProjectionWatcherCallback;
+import android.media.projection.MediaProjectionInfo;
 import android.media.projection.MediaProjectionManager;
 import android.os.Binder;
 import android.os.Handler;
@@ -34,6 +36,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.Slog;
 
@@ -59,15 +62,20 @@
     private static final String TAG = "MediaProjectionManagerService";
 
     private final Object mLock = new Object(); // Protects the list of media projections
-    private final Map<IBinder, MediaProjection> mProjectionGrants;
+    private final Map<IBinder, IBinder.DeathRecipient> mDeathEaters;
+    private final CallbackDelegate mCallbackDelegate;
 
     private final Context mContext;
     private final AppOpsManager mAppOps;
 
+    private IBinder mProjectionToken;
+    private MediaProjection mProjectionGrant;
+
     public MediaProjectionManagerService(Context context) {
         super(context);
         mContext = context;
-        mProjectionGrants = new ArrayMap<IBinder, MediaProjection>();
+        mDeathEaters = new ArrayMap<IBinder, IBinder.DeathRecipient>();
+        mCallbackDelegate = new CallbackDelegate();
         mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
         Watchdog.getInstance().addMonitor(this);
     }
@@ -83,13 +91,97 @@
         synchronized (mLock) { /* check for deadlock */ }
     }
 
+    private void startProjectionLocked(final MediaProjection projection) {
+        if (mProjectionGrant != null) {
+            mProjectionGrant.stop();
+        }
+        mProjectionToken = projection.asBinder();
+        mProjectionGrant = projection;
+        dispatchStart(projection);
+    }
+
+    private void stopProjectionLocked(final MediaProjection projection) {
+        mProjectionToken = null;
+        mProjectionGrant = null;
+        dispatchStop(projection);
+    }
+
+    private void addCallback(final IMediaProjectionWatcherCallback callback) {
+        IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {
+            @Override
+            public void binderDied() {
+                synchronized (mLock) {
+                    unlinkDeathRecipientLocked(callback);
+                    removeCallback(callback);
+                }
+            }
+        };
+        synchronized (mLock) {
+            mCallbackDelegate.add(callback);
+            linkDeathRecipientLocked(callback, deathRecipient);
+        }
+    }
+
+    private void removeCallback(IMediaProjectionWatcherCallback callback) {
+        synchronized (mLock) {
+            unlinkDeathRecipientLocked(callback);
+            removeCallback(callback);
+        }
+    }
+
+    private void linkDeathRecipientLocked(IMediaProjectionWatcherCallback callback,
+            IBinder.DeathRecipient deathRecipient) {
+        try {
+            final IBinder token = callback.asBinder();
+            token.linkToDeath(deathRecipient, 0);
+            mDeathEaters.put(token, deathRecipient);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Unable to link to death for media projection monitoring callback", e);
+        }
+    }
+
+    private void unlinkDeathRecipientLocked(IMediaProjectionWatcherCallback callback) {
+        final IBinder token = callback.asBinder();
+        IBinder.DeathRecipient deathRecipient = mDeathEaters.remove(token);
+        if (deathRecipient != null) {
+            token.unlinkToDeath(deathRecipient, 0);
+        }
+    }
+
+    private void dispatchStart(MediaProjection projection) {
+        mCallbackDelegate.dispatchStart(projection);
+    }
+
+    private void dispatchStop(MediaProjection projection) {
+        mCallbackDelegate.dispatchStop(projection);
+    }
+
+    private boolean isValidMediaProjection(IBinder token) {
+        synchronized (mLock) {
+            if (mProjectionToken != null) {
+                return mProjectionToken.equals(token);
+            }
+            return false;
+        }
+    }
+
+    private MediaProjectionInfo getActiveProjectionInfo() {
+        synchronized (mLock) {
+            if (mProjectionGrant == null) {
+                return null;
+            }
+            return mProjectionGrant.getProjectionInfo();
+        }
+    }
+
     private void dump(final PrintWriter pw) {
         pw.println("MEDIA PROJECTION MANAGER (dumpsys media_projection)");
         synchronized (mLock) {
-            Collection<MediaProjection> projections = mProjectionGrants.values();
-            pw.println("Media Projections: size=" + projections.size());
-            for (MediaProjection mp : projections) {
-                mp.dump(pw, "  ");
+            pw.println("Media Projection: ");
+            if (mProjectionGrant != null ) {
+                mProjectionGrant.dump(pw);
+            } else {
+                pw.println("null");
             }
         }
     }
@@ -115,11 +207,14 @@
         @Override // Binder call
         public IMediaProjection createProjection(int uid, String packageName, int type,
                 boolean isPermanentGrant) {
-            if (mContext.checkCallingPermission(Manifest.permission.CREATE_MEDIA_PROJECTION)
+            if (mContext.checkCallingPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION)
                         != PackageManager.PERMISSION_GRANTED) {
-                throw new SecurityException("Requires CREATE_MEDIA_PROJECTION in order to grant "
+                throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to grant "
                         + "projection permission");
             }
+            if (packageName == null || packageName.isEmpty()) {
+                throw new IllegalArgumentException("package name must not be empty");
+            }
             long callingToken = Binder.clearCallingIdentity();
             MediaProjection projection;
             try {
@@ -136,7 +231,71 @@
 
         @Override // Binder call
         public boolean isValidMediaProjection(IMediaProjection projection) {
-            return mProjectionGrants.containsKey(projection.asBinder());
+            return MediaProjectionManagerService.this.isValidMediaProjection(
+                    projection.asBinder());
+        }
+
+        @Override // Binder call
+        public MediaProjectionInfo getActiveProjectionInfo() {
+            if (mContext.checkCallingPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION)
+                        != PackageManager.PERMISSION_GRANTED) {
+                throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to add "
+                        + "projection callbacks");
+            }
+            final long token = Binder.clearCallingIdentity();
+            try {
+                return MediaProjectionManagerService.this.getActiveProjectionInfo();
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override // Binder call
+        public void stopActiveProjection() {
+            if (mContext.checkCallingPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION)
+                        != PackageManager.PERMISSION_GRANTED) {
+                throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to add "
+                        + "projection callbacks");
+            }
+            final long token = Binder.clearCallingIdentity();
+            try {
+                if (mProjectionGrant != null) {
+                    mProjectionGrant.stop();
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+
+        }
+
+        @Override //Binder call
+        public void addCallback(final IMediaProjectionWatcherCallback callback) {
+            if (mContext.checkCallingPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION)
+                        != PackageManager.PERMISSION_GRANTED) {
+                throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to add "
+                        + "projection callbacks");
+            }
+            final long token = Binder.clearCallingIdentity();
+            try {
+                MediaProjectionManagerService.this.addCallback(callback);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void removeCallback(IMediaProjectionWatcherCallback callback) {
+            if (mContext.checkCallingPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION)
+                        != PackageManager.PERMISSION_GRANTED) {
+                throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to remove "
+                        + "projection callbacks");
+            }
+            final long token = Binder.clearCallingIdentity();
+            try {
+                MediaProjectionManagerService.this.removeCallback(callback);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
         }
 
         @Override // Binder call
@@ -157,25 +316,27 @@
             }
         }
 
+
         private boolean checkPermission(String packageName, String permission) {
             return mContext.getPackageManager().checkPermission(permission, packageName)
                     == PackageManager.PERMISSION_GRANTED;
         }
     }
 
-    private final class MediaProjection extends IMediaProjection.Stub implements DeathRecipient {
-        public int uid;
-        public String packageName;
+    private final class MediaProjection extends IMediaProjection.Stub {
+        public final int uid;
+        public final String packageName;
+        public final UserHandle userHandle;
 
         private IBinder mToken;
+        private IBinder.DeathRecipient mDeathEater;
         private int mType;
-        private CallbackDelegate mCallbackDelegate;
 
         public MediaProjection(int type, int uid, String packageName) {
             mType = type;
             this.uid = uid;
             this.packageName = packageName;
-            mCallbackDelegate = new CallbackDelegate();
+            userHandle = new UserHandle(UserHandle.getUserId(uid));
         }
 
         @Override // Binder call
@@ -220,49 +381,50 @@
         }
 
         @Override // Binder call
-        public void start(IMediaProjectionCallback callback) {
+        public void start(final IMediaProjectionCallback callback) {
             if (callback == null) {
                 throw new IllegalArgumentException("callback must not be null");
             }
             synchronized (mLock) {
-                if (mProjectionGrants.containsKey(asBinder())) {
+                if (isValidMediaProjection(asBinder())) {
                     throw new IllegalStateException(
                             "Cannot start already started MediaProjection");
                 }
                 addCallback(callback);
                 try {
                     mToken = callback.asBinder();
-                    mToken.linkToDeath(this, 0);
+                    mDeathEater = new IBinder.DeathRecipient() {
+                        @Override
+                        public void binderDied() {
+                            mCallbackDelegate.remove(callback);
+                            stop();
+                        }
+                    };
+                    mToken.linkToDeath(mDeathEater, 0);
                 } catch (RemoteException e) {
                     Slog.w(TAG,
                             "MediaProjectionCallbacks must be valid, aborting MediaProjection", e);
                     return;
                 }
-                mProjectionGrants.put(asBinder(), this);
+                startProjectionLocked(this);
             }
         }
 
         @Override // Binder call
         public void stop() {
             synchronized (mLock) {
-                if (!mProjectionGrants.containsKey(asBinder())) {
+                if (!isValidMediaProjection(asBinder())) {
                     Slog.w(TAG, "Attempted to stop inactive MediaProjection "
                             + "(uid=" + Binder.getCallingUid() + ", "
                             + "pid=" + Binder.getCallingPid() + ")");
                     return;
                 }
-                mToken.unlinkToDeath(this, 0);
-                mCallbackDelegate.dispatchStop();
-                mProjectionGrants.remove(asBinder());
+                mToken.unlinkToDeath(mDeathEater, 0);
+                stopProjectionLocked(this);
             }
         }
 
         @Override
-        public void binderDied() {
-            stop();
-        }
-
-        @Override
         public void addCallback(IMediaProjectionCallback callback) {
             if (callback == null) {
                 throw new IllegalArgumentException("callback must not be null");
@@ -278,52 +440,143 @@
             mCallbackDelegate.remove(callback);
         }
 
-        public void dump(PrintWriter pw, String prefix) {
-            pw.println(prefix + "(" + packageName + ", uid=" + uid + "): " + typeToString(mType));
+        public MediaProjectionInfo getProjectionInfo() {
+            return new MediaProjectionInfo(packageName, userHandle);
+        }
+
+        public void dump(PrintWriter pw) {
+            pw.println("(" + packageName + ", uid=" + uid + "): " + typeToString(mType));
         }
     }
 
+
     private static class CallbackDelegate {
-        private static final int MSG_ON_STOP = 0;
-        private List<IMediaProjectionCallback> mCallbacks;
+        private Map<IBinder, IMediaProjectionCallback> mClientCallbacks;
+        private Map<IBinder, IMediaProjectionWatcherCallback> mWatcherCallbacks;
         private Handler mHandler;
         private Object mLock = new Object();
 
         public CallbackDelegate() {
             mHandler = new Handler(Looper.getMainLooper(), null, true /*async*/);
-            mCallbacks = new ArrayList<IMediaProjectionCallback>();
+            mClientCallbacks = new ArrayMap<IBinder, IMediaProjectionCallback>();
+            mWatcherCallbacks = new ArrayMap<IBinder, IMediaProjectionWatcherCallback>();
         }
 
         public void add(IMediaProjectionCallback callback) {
             synchronized (mLock) {
-                mCallbacks.add(callback);
+                mClientCallbacks.put(callback.asBinder(), callback);
+            }
+        }
+
+        public void add(IMediaProjectionWatcherCallback callback) {
+            synchronized (mLock) {
+                mWatcherCallbacks.put(callback.asBinder(), callback);
             }
         }
 
         public void remove(IMediaProjectionCallback callback) {
             synchronized (mLock) {
-                mCallbacks.remove(callback);
+                mClientCallbacks.remove(callback.asBinder());
             }
         }
 
-        public void dispatchStop() {
+        public void remove(IMediaProjectionWatcherCallback callback) {
             synchronized (mLock) {
-                for (final IMediaProjectionCallback callback : mCallbacks) {
-                    mHandler.post(new Runnable() {
-                        @Override
-                        public void run() {
-                            try {
-                                callback.onStop();
-                            } catch (RemoteException e) {
-                                Slog.w(TAG, "Failed to notify media projection has stopped", e);
-                            }
-                        }
-                    });
+                mWatcherCallbacks.remove(callback.asBinder());
+            }
+        }
+
+        public void dispatchStart(MediaProjection projection) {
+            if (projection == null) {
+                Slog.e(TAG, "Tried to dispatch start notification for a null media projection."
+                        + " Ignoring!");
+                return;
+            }
+            synchronized (mLock) {
+                for (IMediaProjectionWatcherCallback callback : mWatcherCallbacks.values()) {
+                    MediaProjectionInfo info = projection.getProjectionInfo();
+                    mHandler.post(new WatcherStartCallback(info, callback));
+                }
+            }
+        }
+
+        public void dispatchStop(MediaProjection projection) {
+            if (projection == null) {
+                Slog.e(TAG, "Tried to dispatch stop notification for a null media projection."
+                        + " Ignoring!");
+                return;
+            }
+            synchronized (mLock) {
+                for (IMediaProjectionCallback callback : mClientCallbacks.values()) {
+                    mHandler.post(new ClientStopCallback(callback));
+                }
+
+                for (IMediaProjectionWatcherCallback callback : mWatcherCallbacks.values()) {
+                    MediaProjectionInfo info = projection.getProjectionInfo();
+                    mHandler.post(new WatcherStopCallback(info, callback));
                 }
             }
         }
     }
 
+    private static final class WatcherStartCallback implements Runnable {
+        private IMediaProjectionWatcherCallback mCallback;
+        private MediaProjectionInfo mInfo;
+
+        public WatcherStartCallback(MediaProjectionInfo info,
+                IMediaProjectionWatcherCallback callback) {
+            mInfo = info;
+            mCallback = callback;
+        }
+
+        @Override
+        public void run() {
+            try {
+                mCallback.onStart(mInfo);
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Failed to notify media projection has stopped", e);
+            }
+        }
+    }
+
+    private static final class WatcherStopCallback implements Runnable {
+        private IMediaProjectionWatcherCallback mCallback;
+        private MediaProjectionInfo mInfo;
+
+        public WatcherStopCallback(MediaProjectionInfo info,
+                IMediaProjectionWatcherCallback callback) {
+            mInfo = info;
+            mCallback = callback;
+        }
+
+        @Override
+        public void run() {
+            try {
+                mCallback.onStop(mInfo);
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Failed to notify media projection has stopped", e);
+            }
+        }
+    }
+
+    private static final class ClientStopCallback implements Runnable {
+        private IMediaProjectionCallback mCallback;
+
+        public ClientStopCallback(IMediaProjectionCallback callback) {
+            mCallback = callback;
+        }
+
+        @Override
+        public void run() {
+            try {
+                mCallback.onStop();
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Failed to notify media projection has stopped", e);
+            }
+        }
+    }
+
+
     private static String typeToString(int type) {
         switch (type) {
             case MediaProjectionManager.TYPE_SCREEN_CAPTURE:
diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java
index 907eeb2..857b9e9 100644
--- a/services/core/java/com/android/server/net/IpConfigStore.java
+++ b/services/core/java/com/android/server/net/IpConfigStore.java
@@ -20,10 +20,10 @@
 import android.net.IpConfiguration.IpAssignment;
 import android.net.IpConfiguration.ProxySettings;
 import android.net.LinkAddress;
-import android.net.LinkProperties;
 import android.net.NetworkUtils;
 import android.net.ProxyInfo;
 import android.net.RouteInfo;
+import android.net.StaticIpConfiguration;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.text.TextUtils;
@@ -41,6 +41,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.net.InetAddress;
+import java.net.Inet4Address;
 import java.util.Map;
 
 public class IpConfigStore {
@@ -69,40 +70,32 @@
     }
 
     private boolean writeConfig(DataOutputStream out, int configKey,
-                                  IpConfiguration config) throws IOException {
+                                IpConfiguration config) throws IOException {
         boolean written = false;
 
         try {
-            LinkProperties linkProperties = config.linkProperties;
             switch (config.ipAssignment) {
                 case STATIC:
                     out.writeUTF(IP_ASSIGNMENT_KEY);
                     out.writeUTF(config.ipAssignment.toString());
-                    for (LinkAddress linkAddr : linkProperties.getLinkAddresses()) {
-                        out.writeUTF(LINK_ADDRESS_KEY);
-                        out.writeUTF(linkAddr.getAddress().getHostAddress());
-                        out.writeInt(linkAddr.getPrefixLength());
-                    }
-                    for (RouteInfo route : linkProperties.getRoutes()) {
-                        out.writeUTF(GATEWAY_KEY);
-                        LinkAddress dest = route.getDestinationLinkAddress();
-                        if (dest != null) {
-                            out.writeInt(1);
-                            out.writeUTF(dest.getAddress().getHostAddress());
-                            out.writeInt(dest.getPrefixLength());
-                        } else {
-                            out.writeInt(0);
+                    StaticIpConfiguration staticIpConfiguration = config.staticIpConfiguration;
+                    if (staticIpConfiguration != null) {
+                        if (staticIpConfiguration.ipAddress != null) {
+                            LinkAddress ipAddress = staticIpConfiguration.ipAddress;
+                            out.writeUTF(LINK_ADDRESS_KEY);
+                            out.writeUTF(ipAddress.getAddress().getHostAddress());
+                            out.writeInt(ipAddress.getPrefixLength());
                         }
-                        if (route.getGateway() != null) {
-                            out.writeInt(1);
-                            out.writeUTF(route.getGateway().getHostAddress());
-                        } else {
-                            out.writeInt(0);
+                        if (staticIpConfiguration.gateway != null) {
+                            out.writeUTF(GATEWAY_KEY);
+                            out.writeInt(0);  // Default route.
+                            out.writeInt(1);  // Have a gateway.
+                            out.writeUTF(staticIpConfiguration.gateway.getHostAddress());
                         }
-                    }
-                    for (InetAddress inetAddr : linkProperties.getDnsServers()) {
-                        out.writeUTF(DNS_KEY);
-                        out.writeUTF(inetAddr.getHostAddress());
+                        for (InetAddress inetAddr : staticIpConfiguration.dnsServers) {
+                            out.writeUTF(DNS_KEY);
+                            out.writeUTF(inetAddr.getHostAddress());
+                        }
                     }
                     written = true;
                     break;
@@ -121,7 +114,7 @@
 
             switch (config.proxySettings) {
                 case STATIC:
-                    ProxyInfo proxyProperties = linkProperties.getHttpProxy();
+                    ProxyInfo proxyProperties = config.httpProxy;
                     String exclusionList = proxyProperties.getExclusionListAsString();
                     out.writeUTF(PROXY_SETTINGS_KEY);
                     out.writeUTF(config.proxySettings.toString());
@@ -134,7 +127,7 @@
                     written = true;
                     break;
                 case PAC:
-                    ProxyInfo proxyPacProperties = linkProperties.getHttpProxy();
+                    ProxyInfo proxyPacProperties = config.httpProxy;
                     out.writeUTF(PROXY_SETTINGS_KEY);
                     out.writeUTF(config.proxySettings.toString());
                     out.writeUTF(PROXY_PAC_FILE);
@@ -159,7 +152,7 @@
                 out.writeInt(configKey);
             }
         } catch (NullPointerException e) {
-            loge("Failure in writing " + config.linkProperties + e);
+            loge("Failure in writing " + config + e);
         }
         out.writeUTF(EOS);
 
@@ -196,7 +189,7 @@
                 // Default is DHCP with no proxy
                 IpAssignment ipAssignment = IpAssignment.DHCP;
                 ProxySettings proxySettings = ProxySettings.NONE;
-                LinkProperties linkProperties = new LinkProperties();
+                StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration();
                 String proxyHost = null;
                 String pacFileUrl = null;
                 int proxyPort = -1;
@@ -213,13 +206,23 @@
                         } else if (key.equals(LINK_ADDRESS_KEY)) {
                             LinkAddress linkAddr = new LinkAddress(
                                     NetworkUtils.numericToInetAddress(in.readUTF()), in.readInt());
-                            linkProperties.addLinkAddress(linkAddr);
+                            if (linkAddr.getAddress() instanceof Inet4Address &&
+                                    staticIpConfiguration.ipAddress == null) {
+                                staticIpConfiguration.ipAddress = linkAddr;
+                            } else {
+                                loge("Non-IPv4 or duplicate address: " + linkAddr);
+                            }
                         } else if (key.equals(GATEWAY_KEY)) {
                             LinkAddress dest = null;
                             InetAddress gateway = null;
                             if (version == 1) {
                                 // only supported default gateways - leave the dest/prefix empty
                                 gateway = NetworkUtils.numericToInetAddress(in.readUTF());
+                                if (staticIpConfiguration.gateway == null) {
+                                    staticIpConfiguration.gateway = gateway;
+                                } else {
+                                    loge("Duplicate gateway: " + gateway.getHostAddress());
+                                }
                             } else {
                                 if (in.readInt() == 1) {
                                     dest = new LinkAddress(
@@ -229,10 +232,16 @@
                                 if (in.readInt() == 1) {
                                     gateway = NetworkUtils.numericToInetAddress(in.readUTF());
                                 }
+                                RouteInfo route = new RouteInfo(dest, gateway);
+                                if (route.isIPv4Default() &&
+                                        staticIpConfiguration.gateway == null) {
+                                    staticIpConfiguration.gateway = gateway;
+                                } else {
+                                    loge("Non-IPv4 default or duplicate route: " + route);
+                                }
                             }
-                            linkProperties.addRoute(new RouteInfo(dest, gateway));
                         } else if (key.equals(DNS_KEY)) {
-                            linkProperties.addDnsServer(
+                            staticIpConfiguration.dnsServers.add(
                                     NetworkUtils.numericToInetAddress(in.readUTF()));
                         } else if (key.equals(PROXY_SETTINGS_KEY)) {
                             proxySettings = ProxySettings.valueOf(in.readUTF());
@@ -258,9 +267,11 @@
                     IpConfiguration config = new IpConfiguration();
                     networks.put(id, config);
 
-                    config.linkProperties = linkProperties;
                     switch (ipAssignment) {
                         case STATIC:
+                            config.staticIpConfiguration = staticIpConfiguration;
+                            config.ipAssignment = ipAssignment;
+                            break;
                         case DHCP:
                             config.ipAssignment = ipAssignment;
                             break;
@@ -276,16 +287,15 @@
 
                     switch (proxySettings) {
                         case STATIC:
-                            config.proxySettings = proxySettings;
-                            ProxyInfo ProxyInfo =
+                            ProxyInfo proxyInfo =
                                     new ProxyInfo(proxyHost, proxyPort, exclusionList);
-                            linkProperties.setHttpProxy(ProxyInfo);
+                            config.proxySettings = proxySettings;
+                            config.httpProxy = proxyInfo;
                             break;
                         case PAC:
+                            ProxyInfo proxyPacProperties = new ProxyInfo(pacFileUrl);
                             config.proxySettings = proxySettings;
-                            ProxyInfo proxyPacProperties =
-                                    new ProxyInfo(pacFileUrl);
-                            linkProperties.setHttpProxy(proxyPacProperties);
+                            config.httpProxy = proxyPacProperties;
                             break;
                         case NONE:
                             config.proxySettings = proxySettings;
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index 1b59f52..97f0a1e 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -16,8 +16,6 @@
 
 package com.android.server.notification;
 
-import android.os.IBinder;
-
 public interface NotificationDelegate {
     void onSetDisabled(int status);
     void onClearAll(int callingUid, int callingPid, int userId);
@@ -29,7 +27,6 @@
             int uid, int initialPid, String message, int userId);
     void onPanelRevealed();
     void onPanelHidden();
-    boolean allowDisable(int what, IBinder token, String pkg);
     void onNotificationVisibilityChanged(
             String[] newlyVisibleKeys, String[] noLongerVisibleKeys);
     void onNotificationExpansionChanged(String key, boolean userAction, boolean expanded);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index f2ac963..7117933 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -29,7 +29,6 @@
 import android.app.INotificationManager;
 import android.app.ITransientNotification;
 import android.app.Notification;
-import android.app.Notification.Builder;
 import android.app.PendingIntent;
 import android.app.StatusBarManager;
 import android.content.BroadcastReceiver;
@@ -50,7 +49,6 @@
 import android.media.IRingtonePlayer;
 import android.net.Uri;
 import android.os.Binder;
-import android.os.Build;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -585,11 +583,6 @@
         }
 
         @Override
-        public boolean allowDisable(int what, IBinder token, String pkg) {
-            return mZenModeHelper.allowDisable(what, token, pkg);
-        }
-
-        @Override
         public void onNotificationVisibilityChanged(
                 String[] newlyVisibleKeys, String[] noLongerVisibleKeys) {
             // Using ';' as separator since eventlogs uses ',' to separate
diff --git a/services/core/java/com/android/server/notification/ZenLog.java b/services/core/java/com/android/server/notification/ZenLog.java
index 525f5f8..f84409e 100644
--- a/services/core/java/com/android/server/notification/ZenLog.java
+++ b/services/core/java/com/android/server/notification/ZenLog.java
@@ -30,10 +30,7 @@
 
 import java.io.PrintWriter;
 import java.text.SimpleDateFormat;
-import java.util.Arrays;
 import java.util.Date;
-import java.util.HashSet;
-import java.util.Set;
 
 public class ZenLog {
     private static final String TAG = "ZenLog";
@@ -45,10 +42,6 @@
     private static final String[] MSGS = new String[SIZE];
 
     private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
-    private static final Set<String> SYSTEM_PACKAGES = new HashSet<String>(Arrays.asList(
-            "android",
-            "com.android.systemui"
-            ));
 
     private static final int TYPE_INTERCEPTED = 1;
     private static final int TYPE_ALLOW_DISABLE = 2;
@@ -76,11 +69,6 @@
         append(TYPE_NOT_INTERCEPTED, record.getKey() + "," + reason);
     }
 
-    public static void traceAllowDisable(String pkg, boolean allowDisable, String reason) {
-        if (SYSTEM_PACKAGES.contains(pkg)) return;
-        append(TYPE_ALLOW_DISABLE, allowDisable + "," + pkg + "," + reason);
-    }
-
     public static void traceSetRingerMode(int ringerMode) {
         append(TYPE_SET_RINGER_MODE, ringerModeToString(ringerMode));
     }
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 758f334..0b93690 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -35,7 +35,6 @@
 import android.media.AudioManager;
 import android.net.Uri;
 import android.os.Handler;
-import android.os.IBinder;
 import android.os.UserHandle;
 import android.provider.Settings.Global;
 import android.provider.Settings.Secure;
@@ -265,18 +264,6 @@
         dispatchOnZenModeChanged();
     }
 
-    public boolean allowDisable(int what, IBinder token, String pkg) {
-        // TODO(cwren): delete this API before the next release. Bug:15344099
-        boolean allowDisable = true;
-        String reason = null;
-        if (isDefaultPhoneApp(pkg)) {
-            allowDisable = mZenMode == Global.ZEN_MODE_OFF || mConfig.allowCalls;
-            reason = mZenMode == Global.ZEN_MODE_OFF ? "zenOff" : "allowCalls";
-        }
-        ZenLog.traceAllowDisable(pkg, allowDisable, reason);
-        return allowDisable;
-    }
-
     public void dump(PrintWriter pw, String prefix) {
         pw.print(prefix); pw.print("mZenMode=");
         pw.println(Global.zenModeToString(mZenMode));
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 51559aa..f47e64f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3292,6 +3292,7 @@
                         intent, resolvedType, flags, userId);
                 if (resolveInfo != null) {
                     result.add(resolveInfo);
+                    Collections.sort(result, mResolvePrioritySorter);
                 }
                 return result;
             }
@@ -11575,18 +11576,20 @@
                     }
                 }
 
-                if (DEBUG_PREFERRED) {
-                    Slog.i(TAG, existing.size() + " existing preferred matches for:");
-                    filter.dump(new LogPrinter(Log.INFO, TAG), "  ");
-                }
-                for (int i = 0; i < existing.size(); i++) {
-                    PreferredActivity pa = existing.get(i);
+                if (existing != null) {
                     if (DEBUG_PREFERRED) {
-                        Slog.i(TAG, "Removing existing preferred activity "
-                                + pa.mPref.mComponent + ":");
-                        pa.dump(new LogPrinter(Log.INFO, TAG), "  ");
+                        Slog.i(TAG, existing.size() + " existing preferred matches for:");
+                        filter.dump(new LogPrinter(Log.INFO, TAG), "  ");
                     }
-                    pir.removeFilter(pa);
+                    for (int i = 0; i < existing.size(); i++) {
+                        PreferredActivity pa = existing.get(i);
+                        if (DEBUG_PREFERRED) {
+                            Slog.i(TAG, "Removing existing preferred activity "
+                                    + pa.mPref.mComponent + ":");
+                            pa.dump(new LogPrinter(Log.INFO, TAG), "  ");
+                        }
+                        pir.removeFilter(pa);
+                    }
                 }
             }
             addPreferredActivityInternal(filter, match, set, activity, true, userId,
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 297dacf..f85e2d9 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -22,7 +22,6 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.service.notification.StatusBarNotification;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
@@ -39,9 +38,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 
 /**
@@ -187,10 +184,6 @@
 
     @Override
     public void disable(int what, IBinder token, String pkg) {
-        if (!mNotificationDelegate.allowDisable(what, token, pkg)) {
-            if (SPEW) Slog.d(TAG, "Blocking disable request from " + pkg);
-            return;
-        }
         disableInternal(mCurrentUserId, what, token, pkg);
     }
 
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 88ce860..a084cab 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -691,6 +691,10 @@
     private void releaseSessionLocked(IBinder sessionToken, int callingUid, int userId) {
         SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, userId);
         if (sessionState.mSession != null) {
+            UserState userState = getUserStateLocked(userId);
+            if (sessionToken == userState.mainSessionToken) {
+                setMainLocked(sessionToken, false, callingUid, userId);
+            }
             try {
                 sessionState.mSession.release();
             } catch (RemoteException e) {
@@ -704,6 +708,9 @@
     private void removeSessionStateLocked(IBinder sessionToken, int userId) {
         UserState userState = getUserStateLocked(userId);
         if (sessionToken == userState.mainSessionToken) {
+            if (DEBUG) {
+                Slog.d(TAG, "mainSessionToken=null");
+            }
             userState.mainSessionToken = null;
         }
 
@@ -740,6 +747,25 @@
         mWatchLogHandler.obtainMessage(WatchLogHandler.MSG_LOG_WATCH_END, args).sendToTarget();
     }
 
+    private void setMainLocked(IBinder sessionToken, boolean isMain, int callingUid, int userId) {
+        SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, userId);
+        if (sessionState.mHardwareSessionToken != null) {
+            sessionState = getSessionStateLocked(sessionState.mHardwareSessionToken,
+                    Process.SYSTEM_UID, userId);
+        }
+        ServiceState serviceState = getServiceStateLocked(sessionState.mInfo.getComponent(),
+                userId);
+        if (!serviceState.mIsHardware) {
+            return;
+        }
+        ITvInputSession session = getSessionLocked(sessionState);
+        try {
+            session.setMain(isMain);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "error in setMain", e);
+        }
+    }
+
     private void notifyInputAddedLocked(UserState userState, String inputId) {
         if (DEBUG) {
             Slog.d(TAG, "notifyInputAdded: inputId = " + inputId);
@@ -1050,6 +1076,9 @@
 
         @Override
         public void releaseSession(IBinder sessionToken, int userId) {
+            if (DEBUG) {
+                Slog.d(TAG, "releaseSession(): " + sessionToken);
+            }
             final int callingUid = Binder.getCallingUid();
             final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
                     userId, "releaseSession");
@@ -1065,6 +1094,9 @@
 
         @Override
         public void setMainSession(IBinder sessionToken, int userId) {
+            if (DEBUG) {
+                Slog.d(TAG, "setMainSession(): " + sessionToken);
+            }
             final int callingUid = Binder.getCallingUid();
             final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
                     userId, "setMainSession");
@@ -1075,50 +1107,19 @@
                     if (userState.mainSessionToken == sessionToken) {
                         return;
                     }
-
-                    SessionState newMainSessionState = getSessionStateLocked(
-                            sessionToken, callingUid, resolvedUserId);
-                    if (newMainSessionState.mHardwareSessionToken != null) {
-                        newMainSessionState = getSessionStateLocked(
-                                newMainSessionState.mHardwareSessionToken,
-                                Process.SYSTEM_UID, resolvedUserId);
+                    if (DEBUG) {
+                        Slog.d(TAG, "mainSessionToken=" + sessionToken);
                     }
-                    ServiceState newMainServiceState = getServiceStateLocked(
-                            newMainSessionState.mInfo.getComponent(), resolvedUserId);
-                    ITvInputSession newMainSession = getSessionLocked(newMainSessionState);
-
-                    ServiceState oldMainServiceState = null;
-                    ITvInputSession oldMainSession = null;
-                    if (userState.mainSessionToken != null) {
-                        SessionState oldMainSessionState = getSessionStateLocked(
-                                userState.mainSessionToken, Process.SYSTEM_UID, resolvedUserId);
-                        if (oldMainSessionState.mHardwareSessionToken != null) {
-                            oldMainSessionState = getSessionStateLocked(
-                                    oldMainSessionState.mHardwareSessionToken,
-                                    Process.SYSTEM_UID, resolvedUserId);
-                        }
-                        oldMainServiceState = getServiceStateLocked(
-                                oldMainSessionState.mInfo.getComponent(), resolvedUserId);
-                        oldMainSession = getSessionLocked(oldMainSessionState);
-                    }
-
+                    IBinder oldMainSessionToken = userState.mainSessionToken;
                     userState.mainSessionToken = sessionToken;
 
                     // Inform the new main session first.
-                    // See {@link TvInputService#onSetMainSession}.
-                    if (newMainServiceState.mIsHardware) {
-                        try {
-                            newMainSession.setMainSession(true);
-                        } catch (RemoteException e) {
-                            Slog.e(TAG, "error in setMainSession", e);
-                        }
+                    // See {@link TvInputService.Session#onSetMain}.
+                    if (sessionToken != null) {
+                        setMainLocked(sessionToken, true, callingUid, userId);
                     }
-                    if (oldMainSession != null && oldMainServiceState.mIsHardware) {
-                        try {
-                            oldMainSession.setMainSession(false);
-                        } catch (RemoteException e) {
-                            Slog.e(TAG, "error in setMainSession", e);
-                        }
+                    if (oldMainSessionToken != null) {
+                        setMainLocked(oldMainSessionToken, false, Process.SYSTEM_UID, userId);
                     }
                 }
             } finally {
@@ -1800,11 +1801,8 @@
                 UserState userState = getUserStateLocked(mUserId);
                 for (SessionState sessionState : userState.sessionStateMap.values()) {
                     if (mSessionToken == sessionState.mHardwareSessionToken) {
-                        try {
-                            sessionState.mSession.release();
-                        } catch (RemoteException e) {
-                            Slog.e(TAG, "error in release", e);
-                        }
+                        releaseSessionLocked(sessionState.mSessionToken, Process.SYSTEM_UID,
+                                mUserId);
                         try {
                             sessionState.mClient.onSessionReleased(sessionState.mSeq);
                         } catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index aa20892..b57a090 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -51,6 +51,7 @@
 import android.app.admin.DevicePolicyManager;
 import android.animation.ValueAnimator;
 import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -58,6 +59,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
+import android.database.ContentObserver;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
 import android.graphics.Canvas;
@@ -539,6 +541,21 @@
     boolean mHardKeyboardAvailable;
     boolean mShowImeWithHardKeyboard;
     OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
+    SettingsObserver mSettingsObserver;
+
+    private final class SettingsObserver extends ContentObserver {
+        public SettingsObserver() {
+            super(new Handler());
+            ContentResolver resolver = mContext.getContentResolver();
+            resolver.registerContentObserver(Settings.Secure.getUriFor(
+                    Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD), false, this);
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            updateShowImeWithHardKeyboard();
+        }
+    }
 
     final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
 
@@ -838,6 +855,9 @@
         filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
         mContext.registerReceiver(mBroadcastReceiver, filter);
 
+        mSettingsObserver = new SettingsObserver();
+        updateShowImeWithHardKeyboard();
+
         mHoldingScreenWakeLock = mPowerManager.newWakeLock(
                 PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG);
         mHoldingScreenWakeLock.setReferenceCounted(false);
@@ -7018,7 +7038,6 @@
             boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
             if (hardKeyboardAvailable != mHardKeyboardAvailable) {
                 mHardKeyboardAvailable = hardKeyboardAvailable;
-                mShowImeWithHardKeyboard = !hardKeyboardAvailable;
                 mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
                 mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
             }
@@ -7042,18 +7061,12 @@
         }
     }
 
-    public boolean isShowImeWithHardKeyboardEnabled() {
+    public void updateShowImeWithHardKeyboard() {
+        boolean showImeWithHardKeyboard = Settings.Secure.getIntForUser(
+                mContext.getContentResolver(), Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0,
+                mCurrentUserId) == 1;
         synchronized (mWindowMap) {
-            return mShowImeWithHardKeyboard;
-        }
-    }
-
-    public void setShowImeWithHardKeyboard(boolean enabled) {
-        synchronized (mWindowMap) {
-            if (mShowImeWithHardKeyboard != enabled) {
-                mShowImeWithHardKeyboard = enabled;
-                mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
-            }
+            mShowImeWithHardKeyboard = showImeWithHardKeyboard;
         }
     }
 
@@ -7065,15 +7078,14 @@
     }
 
     void notifyHardKeyboardStatusChange() {
-        final boolean available, showImeWithHardKeyboard;
+        final boolean available;
         final OnHardKeyboardStatusChangeListener listener;
         synchronized (mWindowMap) {
             listener = mHardKeyboardStatusChangeListener;
             available = mHardKeyboardAvailable;
-            showImeWithHardKeyboard = mShowImeWithHardKeyboard;
         }
         if (listener != null) {
-            listener.onHardKeyboardStatusChange(available, showImeWithHardKeyboard);
+            listener.onHardKeyboardStatusChange(available);
         }
     }
 
@@ -11056,7 +11068,7 @@
     }
 
     public interface OnHardKeyboardStatusChangeListener {
-        public void onHardKeyboardStatusChange(boolean available, boolean showIme);
+        public void onHardKeyboardStatusChange(boolean available);
     }
 
     void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
diff --git a/telecomm/java/android/telecomm/Connection.java b/telecomm/java/android/telecomm/Connection.java
index 27debde..c1d5715 100644
--- a/telecomm/java/android/telecomm/Connection.java
+++ b/telecomm/java/android/telecomm/Connection.java
@@ -36,6 +36,15 @@
 
 /**
  * Represents a connection to a remote endpoint that carries voice traffic.
+ * <p>
+ * Implementations create a custom subclass of {@code Connection} and return it to the framework
+ * as the return value of
+ * {@link ConnectionService#onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)}
+ * or
+ * {@link ConnectionService#onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
+ * Implementations are then responsible for updating the state of the {@code Connection}, and
+ * must call {@link #destroy()} to signal to the framework that the {@code Connection} is no
+ * longer used and associated resources may be recovered.
  */
 public abstract class Connection {
 
@@ -53,10 +62,6 @@
 
     public static final int STATE_DISCONNECTED = 6;
 
-    public static final int STATE_FAILED = 7;
-
-    public static final int STATE_CANCELED = 8;
-
     // Flag controlling whether PII is emitted into the logs
     private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
 
@@ -644,10 +649,6 @@
                 return "STATE_HOLDING";
             case STATE_DISCONNECTED:
                 return "DISCONNECTED";
-            case STATE_FAILED:
-                return "STATE_FAILED";
-            case STATE_CANCELED:
-                return "STATE_CANCELED";
             default:
                 Log.wtf(Connection.class, "Unknown state %d", state);
                 return "UNKNOWN";
@@ -694,33 +695,6 @@
     }
 
     /**
-     * Cancel the {@link Connection}. Once this is called, the {@link Connection} will not be used,
-     * and no subsequent {@link Connection}s will be attempted.
-     */
-    public final void setCanceled() {
-        Log.d(this, "setCanceled");
-        setState(STATE_CANCELED);
-    }
-
-    /**
-     * Move the {@link Connection} to the {@link #STATE_FAILED} state, with the given code
-     * ({@see DisconnectCause}) and message. This message is not shown to the user, but is useful
-     * for logging and debugging purposes.
-     * <p>
-     * After calling this, the {@link Connection} will not be used.
-     *
-     * @param code The {@link DisconnectCause} indicating why the connection
-     *             failed.
-     * @param message A message explaining why the {@link Connection} failed.
-     */
-    public final void setFailed(int code, String message) {
-        Log.d(this, "setFailed (%d: %s)", code, message);
-        mFailureCode = code;
-        mFailureMessage = message;
-        setState(STATE_FAILED);
-    }
-
-    /**
      * Set the video state for the connection.
      * Valid values: {@link VideoProfile.VideoState#AUDIO_ONLY},
      * {@link VideoProfile.VideoState#BIDIRECTIONAL},
@@ -1094,9 +1068,8 @@
     }
 
     private void setState(int state) {
-        if (mState == STATE_FAILED || mState == STATE_CANCELED) {
-            Log.d(this, "Connection already %s; cannot transition out of this state.",
-                    stateToString(mState));
+        if (mState == STATE_DISCONNECTED && mState != state) {
+            Log.d(this, "Connection already DISCONNECTED; cannot transition out of this state.");
             return;
         }
         if (mState != state) {
@@ -1109,33 +1082,41 @@
         }
     }
 
+    static class FailureSignalingConnection extends Connection {
+        public FailureSignalingConnection(int code, String message) {
+            setDisconnected(code, message);
+        }
+    }
+
     /**
-     * Return a {@link Connection} which represents a failed connection attempt. The returned
-     * {@link Connection} will have {@link #getFailureCode()}, {@link #getFailureMessage()}, and
-     * {@link #getState()} set appropriately, but the {@link Connection} itself should not be used
-     * for anything.
+     * Return a {@code Connection} which represents a failed connection attempt. The returned
+     * {@code Connection} will have a {@link #getFailureCode()} and {@link #getFailureMessage()}
+     * as specified, a {@link #getState()} of {@link #STATE_DISCONNECTED}.
+     * <p>
+     * The returned {@code Connection} can be assumed to {@link #destroy()} itself when appropriate,
+     * so users of this method need not maintain a reference to its return value to destroy it.
      *
      * @param code The failure code ({@see DisconnectCause}).
      * @param message A reason for why the connection failed (not intended to be shown to the user).
-     * @return A {@link Connection} which indicates failure.
+     * @return A {@code Connection} which indicates failure.
      */
     public static Connection createFailedConnection(final int code, final String message) {
-        return new Connection() {{
-            setFailed(code, message);
-        }};
+        return new FailureSignalingConnection(code, message);
     }
 
-    private static final Connection CANCELED_CONNECTION = new Connection() {{
-        setCanceled();
-    }};
+    private static final Connection CANCELED_CONNECTION =
+            new FailureSignalingConnection(DisconnectCause.OUTGOING_CANCELED, null);
 
     /**
-     * Return a {@link Connection} which represents a canceled a connection attempt. The returned
-     * {@link Connection} will have state {@link #STATE_CANCELED}, and cannot be moved out of that
-     * state. This connection should not be used for anything, and no other {@link Connection}s
-     * should be attempted.
+     * Return a {@code Connection} which represents a canceled connection attempt. The returned
+     * {@code Connection} will have state {@link #STATE_DISCONNECTED}, and cannot be moved out of
+     * that state. This connection should not be used for anything, and no other
+     * {@code Connection}s should be attempted.
+     * <p>
+     * The returned {@code Connection} can be assumed to {@link #destroy()} itself when appropriate,
+     * so users of this method need not maintain a reference to its return value to destroy it.
      *
-     * @return A {@link Connection} which indicates that the underlying call should be canceled.
+     * @return A {@code Connection} which indicates that the underlying call should be canceled.
      */
     public static Connection createCanceledConnection() {
         return CANCELED_CONNECTION;
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
index 97a3102..03b6c7b 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -500,81 +500,26 @@
             boolean isIncoming) {
         Log.d(this, "call %s", request);
 
-        final Connection createdConnection;
-        if (isIncoming) {
-            createdConnection = onCreateIncomingConnection(callManagerAccount, request);
-        } else {
-            createdConnection = onCreateOutgoingConnection(callManagerAccount, request);
-        }
+        Connection createdConnection = isIncoming
+                ? onCreateIncomingConnection(callManagerAccount, request)
+                : onCreateOutgoingConnection(callManagerAccount, request);
 
-        if (createdConnection != null) {
-            Log.d(this, "adapter handleCreateConnectionSuccessful %s", callId);
-            if (createdConnection.getState() == Connection.STATE_INITIALIZING) {
-                // Wait for the connection to become initialized.
-                createdConnection.addConnectionListener(new Connection.Listener() {
-                    @Override
-                    public void onStateChanged(Connection c, int state) {
-                        switch (state) {
-                            case Connection.STATE_FAILED:
-                                Log.d(this, "Connection (%s) failed (%d: %s)", request,
-                                        c.getFailureCode(), c.getFailureMessage());
-                                Log.d(this, "adapter handleCreateConnectionFailed %s",
-                                        callId);
-                                mAdapter.handleCreateConnectionFailed(
-                                        callId,
-                                        request,
-                                        c.getFailureCode(),
-                                        c.getFailureMessage());
-                                break;
-                            case Connection.STATE_CANCELED:
-                                Log.d(this, "adapter handleCreateConnectionCanceled %s",
-                                        callId);
-                                mAdapter.handleCreateConnectionCancelled(callId, request);
-                                break;
-                            case Connection.STATE_INITIALIZING:
-                                Log.d(this, "State changed to STATE_INITIALIZING; ignoring");
-                                return; // Don't want to stop listening on this state transition.
-                        }
-                        c.removeConnectionListener(this);
-                    }
-
-                    @Override
-                    public void onDestroyed(Connection c) {
-                        // Listen to onDestroy in case the connection is destroyed before
-                        // transitioning to another state.
-                        c.removeConnectionListener(this);
-                    }
-                });
-                Log.d(this, "Connection created in state INITIALIZING");
-                connectionCreated(callId, request, createdConnection);
-            } else if (createdConnection.getState() == Connection.STATE_CANCELED) {
-                // Tell telecomm not to attempt any more services.
-                mAdapter.handleCreateConnectionCancelled(callId, request);
-            } else if (createdConnection.getState() == Connection.STATE_FAILED) {
-                mAdapter.handleCreateConnectionFailed(
-                        callId,
-                        request,
-                        createdConnection.getFailureCode(),
-                        createdConnection.getFailureMessage());
-            } else {
-                connectionCreated(callId, request, createdConnection);
-            }
-        } else {
+        if (createdConnection == null) {
+            Log.d(this, "adapter handleCreateConnectionComplete CANCELED %s", callId);
             // Tell telecomm to try a different service.
-            Log.d(this, "adapter handleCreateConnectionFailed %s", callId);
-            mAdapter.handleCreateConnectionFailed(
-                    callId,
-                    request,
-                    DisconnectCause.ERROR_UNSPECIFIED,
-                    null);
+            createdConnection = Connection.createCanceledConnection();
         }
+        connectionCreated(callId, request, createdConnection);
     }
 
     private void connectionCreated(
             String callId,
             ConnectionRequest request,
             Connection connection) {
-        addConnection(callId, connection);
+        if (!(connection instanceof Connection.FailureSignalingConnection)) {
+            addConnection(callId, connection);
+        }
+
         Uri handle = connection.getHandle();
         String number = handle == null ? "null" : handle.getSchemeSpecificPart();
         Log.v(this, "connectionCreated, parcelableconnection: %s, %d, %s",
@@ -583,7 +528,7 @@
                 PhoneCapabilities.toString(connection.getCallCapabilities()));
 
         Log.d(this, "adapter handleCreateConnectionSuccessful %s", callId);
-        mAdapter.handleCreateConnectionSuccessful(
+        mAdapter.handleCreateConnectionComplete(
                 callId,
                 request,
                 new ParcelableConnection(
@@ -599,7 +544,9 @@
                         connection.getVideoState(),
                         connection.isRequestingRingback(),
                         connection.getAudioModeIsVoip(),
-                        connection.getStatusHints()));
+                        connection.getStatusHints(),
+                        connection.getFailureCode(),
+                        connection.getFailureMessage()));
     }
 
     private void abort(String callId) {
@@ -699,7 +646,8 @@
                     final List<ComponentName> componentNames,
                     final List<IBinder> services) {
                 mHandler.post(new Runnable() {
-                    @Override public void run() {
+                    @Override
+                    public void run() {
                         for (int i = 0; i < componentNames.size() && i < services.size(); i++) {
                             mRemoteConnectionManager.addConnectionService(
                                     componentNames.get(i),
@@ -714,7 +662,8 @@
             @Override
             public void onError() {
                 mHandler.post(new Runnable() {
-                    @Override public void run() {
+                    @Override
+                    public void run() {
                         mAreAccountsInitialized = true;
                     }
                 });
diff --git a/telecomm/java/android/telecomm/ConnectionServiceAdapter.java b/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
index 0188e62..41c6360 100644
--- a/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
@@ -76,37 +76,13 @@
         }
     }
 
-    void handleCreateConnectionSuccessful(
+    void handleCreateConnectionComplete(
             String id,
             ConnectionRequest request,
             ParcelableConnection connection) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.handleCreateConnectionSuccessful(id, request, connection);
-            } catch (RemoteException e) {
-            }
-        }
-    }
-
-    void handleCreateConnectionFailed(
-            String id,
-            ConnectionRequest request,
-            int errorCode,
-            String errorMsg) {
-        for (IConnectionServiceAdapter adapter : mAdapters) {
-            try {
-                adapter.handleCreateConnectionFailed(id, request, errorCode, errorMsg);
-            } catch (RemoteException e) {
-            }
-        }
-    }
-
-    void handleCreateConnectionCancelled(
-            String id,
-            ConnectionRequest request) {
-        for (IConnectionServiceAdapter adapter : mAdapters) {
-            try {
-                adapter.handleCreateConnectionCancelled(id, request);
+                adapter.handleCreateConnectionComplete(id, request, connection);
             } catch (RemoteException e) {
             }
         }
diff --git a/telecomm/java/android/telecomm/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecomm/ConnectionServiceAdapterServant.java
index 2654ace..0e1c516 100644
--- a/telecomm/java/android/telecomm/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecomm/ConnectionServiceAdapterServant.java
@@ -38,29 +38,27 @@
  * @hide
  */
 final class ConnectionServiceAdapterServant {
-    private static final int MSG_HANDLE_CREATE_CONNECTION_SUCCESSFUL = 1;
-    private static final int MSG_HANDLE_CREATE_CONNECTION_FAILED = 2;
-    private static final int MSG_HANDLE_CREATE_CONNECTION_CANCELLED = 3;
-    private static final int MSG_SET_ACTIVE = 4;
-    private static final int MSG_SET_RINGING = 5;
-    private static final int MSG_SET_DIALING = 6;
-    private static final int MSG_SET_DISCONNECTED = 7;
-    private static final int MSG_SET_ON_HOLD = 8;
-    private static final int MSG_SET_REQUESTING_RINGBACK = 9;
-    private static final int MSG_SET_CALL_CAPABILITIES = 10;
-    private static final int MSG_SET_IS_CONFERENCED = 11;
-    private static final int MSG_ADD_CONFERENCE_CALL = 12;
-    private static final int MSG_REMOVE_CALL = 13;
-    private static final int MSG_ON_POST_DIAL_WAIT = 14;
-    private static final int MSG_QUERY_REMOTE_CALL_SERVICES = 15;
-    private static final int MSG_SET_VIDEO_STATE = 16;
-    private static final int MSG_SET_VIDEO_CALL_PROVIDER = 17;
-    private static final int MSG_SET_AUDIO_MODE_IS_VOIP = 18;
-    private static final int MSG_SET_STATUS_HINTS = 19;
-    private static final int MSG_SET_HANDLE = 20;
-    private static final int MSG_SET_CALLER_DISPLAY_NAME = 21;
-    private static final int MSG_START_ACTIVITY_FROM_IN_CALL = 22;
-    private static final int MSG_SET_CONFERENCEABLE_CONNECTIONS = 23;
+    private static final int MSG_HANDLE_CREATE_CONNECTION_COMPLETE = 1;
+    private static final int MSG_SET_ACTIVE = 2;
+    private static final int MSG_SET_RINGING = 3;
+    private static final int MSG_SET_DIALING = 4;
+    private static final int MSG_SET_DISCONNECTED = 5;
+    private static final int MSG_SET_ON_HOLD = 6;
+    private static final int MSG_SET_REQUESTING_RINGBACK = 7;
+    private static final int MSG_SET_CALL_CAPABILITIES = 8;
+    private static final int MSG_SET_IS_CONFERENCED = 9;
+    private static final int MSG_ADD_CONFERENCE_CALL = 10;
+    private static final int MSG_REMOVE_CALL = 11;
+    private static final int MSG_ON_POST_DIAL_WAIT = 12;
+    private static final int MSG_QUERY_REMOTE_CALL_SERVICES = 13;
+    private static final int MSG_SET_VIDEO_STATE = 14;
+    private static final int MSG_SET_VIDEO_CALL_PROVIDER = 15;
+    private static final int MSG_SET_AUDIO_MODE_IS_VOIP = 16;
+    private static final int MSG_SET_STATUS_HINTS = 17;
+    private static final int MSG_SET_HANDLE = 18;
+    private static final int MSG_SET_CALLER_DISPLAY_NAME = 19;
+    private static final int MSG_START_ACTIVITY_FROM_IN_CALL = 20;
+    private static final int MSG_SET_CONFERENCEABLE_CONNECTIONS = 21;
 
     private final IConnectionServiceAdapter mDelegate;
 
@@ -76,10 +74,10 @@
         // Internal method defined to centralize handling of RemoteException
         private void internalHandleMessage(Message msg) throws RemoteException {
             switch (msg.what) {
-                case MSG_HANDLE_CREATE_CONNECTION_SUCCESSFUL: {
+                case MSG_HANDLE_CREATE_CONNECTION_COMPLETE: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.handleCreateConnectionSuccessful(
+                        mDelegate.handleCreateConnectionComplete(
                                 (String) args.arg1,
                                 (ConnectionRequest) args.arg2,
                                 (ParcelableConnection) args.arg3);
@@ -88,30 +86,6 @@
                     }
                     break;
                 }
-                case MSG_HANDLE_CREATE_CONNECTION_FAILED: {
-                    SomeArgs args = (SomeArgs) msg.obj;
-                    try {
-                        mDelegate.handleCreateConnectionFailed(
-                                (String) args.arg1,
-                                (ConnectionRequest) args.arg2,
-                                args.argi1,
-                                (String) args.arg3);
-                    } finally {
-                        args.recycle();
-                    }
-                    break;
-                }
-                case MSG_HANDLE_CREATE_CONNECTION_CANCELLED: {
-                    SomeArgs args = (SomeArgs) msg.obj;
-                    try {
-                        mDelegate.handleCreateConnectionCancelled(
-                                (String) args.arg1,
-                                (ConnectionRequest) args.arg2);
-                    } finally {
-                        args.recycle();
-                    }
-                    break;
-                }
                 case MSG_SET_ACTIVE:
                     mDelegate.setActive((String) msg.obj);
                     break;
@@ -244,7 +218,7 @@
 
     private final IConnectionServiceAdapter mStub = new IConnectionServiceAdapter.Stub() {
         @Override
-        public void handleCreateConnectionSuccessful(
+        public void handleCreateConnectionComplete(
                 String id,
                 ConnectionRequest request,
                 ParcelableConnection connection) {
@@ -252,31 +226,7 @@
             args.arg1 = id;
             args.arg2 = request;
             args.arg3 = connection;
-            mHandler.obtainMessage(MSG_HANDLE_CREATE_CONNECTION_SUCCESSFUL, args).sendToTarget();
-        }
-
-        @Override
-        public void handleCreateConnectionFailed(
-                String id,
-                ConnectionRequest request,
-                int errorCode,
-                String errorMessage) {
-            SomeArgs args = SomeArgs.obtain();
-            args.arg1 = id;
-            args.arg2 = request;
-            args.argi1 = errorCode;
-            args.arg3 = errorMessage;
-            mHandler.obtainMessage(MSG_HANDLE_CREATE_CONNECTION_FAILED, args).sendToTarget();
-        }
-
-        @Override
-        public void handleCreateConnectionCancelled(
-                String id,
-                ConnectionRequest request) {
-            SomeArgs args = SomeArgs.obtain();
-            args.arg1 = id;
-            args.arg2 = request;
-            mHandler.obtainMessage(MSG_HANDLE_CREATE_CONNECTION_CANCELLED, args).sendToTarget();
+            mHandler.obtainMessage(MSG_HANDLE_CREATE_CONNECTION_COMPLETE, args).sendToTarget();
         }
 
         @Override
diff --git a/telecomm/java/android/telecomm/InCallService.java b/telecomm/java/android/telecomm/InCallService.java
index de05d1c..5795e0e 100644
--- a/telecomm/java/android/telecomm/InCallService.java
+++ b/telecomm/java/android/telecomm/InCallService.java
@@ -16,6 +16,7 @@
 
 package android.telecomm;
 
+import android.annotation.SdkConstant;
 import android.app.PendingIntent;
 import android.app.Service;
 import android.content.Intent;
@@ -39,6 +40,13 @@
  * {@hide}
  */
 public abstract class InCallService extends Service {
+
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+    public static final String SERVICE_INTERFACE = "android.telecomm.InCallService";
+
     private static final int MSG_SET_IN_CALL_ADAPTER = 1;
     private static final int MSG_ADD_CALL = 2;
     private static final int MSG_UPDATE_CALL = 3;
diff --git a/telecomm/java/android/telecomm/ParcelableConnection.java b/telecomm/java/android/telecomm/ParcelableConnection.java
index 7a87b87..30ff5be 100644
--- a/telecomm/java/android/telecomm/ParcelableConnection.java
+++ b/telecomm/java/android/telecomm/ParcelableConnection.java
@@ -41,6 +41,8 @@
     private boolean mRequestingRingback;
     private boolean mAudioModeIsVoip;
     private StatusHints mStatusHints;
+    private int mFailureCode;
+    private String mFailureMessage;
 
     /** @hide */
     public ParcelableConnection(
@@ -55,7 +57,9 @@
             int videoState,
             boolean requestingRingback,
             boolean audioModeIsVoip,
-            StatusHints statusHints) {
+            StatusHints statusHints,
+            int failureCode,
+            String failureMessage) {
         mPhoneAccount = phoneAccount;
         mState = state;
         mCapabilities = capabilities;
@@ -68,6 +72,8 @@
         mRequestingRingback = requestingRingback;
         mAudioModeIsVoip = audioModeIsVoip;
         mStatusHints = statusHints;
+        mFailureCode = failureCode;
+        mFailureMessage = failureMessage;
     }
 
     public PhoneAccountHandle getPhoneAccount() {
@@ -119,6 +125,14 @@
         return mStatusHints;
     }
 
+    public final int getFailureCode() {
+        return mFailureCode;
+    }
+
+    public final String getFailureMessage() {
+        return mFailureMessage;
+    }
+
     @Override
     public String toString() {
         return new StringBuilder()
@@ -150,6 +164,8 @@
             boolean requestingRingback = source.readByte() == 1;
             boolean audioModeIsVoip = source.readByte() == 1;
             StatusHints statusHints = source.readParcelable(classLoader);
+            int disconnectCauseCode = source.readInt();
+            String disconnectCauseMessage = source.readString();
 
             return new ParcelableConnection(
                     phoneAccount,
@@ -163,7 +179,9 @@
                     videoState,
                     requestingRingback,
                     audioModeIsVoip,
-                    statusHints);
+                    statusHints,
+                    disconnectCauseCode,
+                    disconnectCauseMessage);
         }
 
         @Override
@@ -194,5 +212,7 @@
         destination.writeByte((byte) (mRequestingRingback ? 1 : 0));
         destination.writeByte((byte) (mAudioModeIsVoip ? 1 : 0));
         destination.writeParcelable(mStatusHints, 0);
+        destination.writeInt(mFailureCode);
+        destination.writeString(mFailureMessage);
     }
 }
diff --git a/telecomm/java/android/telecomm/RemoteConnection.java b/telecomm/java/android/telecomm/RemoteConnection.java
index f1cee10..30cfdde 100644
--- a/telecomm/java/android/telecomm/RemoteConnection.java
+++ b/telecomm/java/android/telecomm/RemoteConnection.java
@@ -233,9 +233,9 @@
     RemoteConnection(int failureCode, String failureMessage) {
         this("NULL", null, null);
         mConnected = false;
-        mState = Connection.STATE_FAILED;
-        mFailureCode = failureCode;
-        mFailureMessage = failureMessage;
+        mState = Connection.STATE_DISCONNECTED;
+        mFailureCode = DisconnectCause.OUTGOING_FAILURE;
+        mFailureMessage = failureMessage + " original code = " + failureCode;
     }
 
     /**
@@ -675,8 +675,9 @@
     }
 
     /**
-     * Create a RemoteConnection which is in the {@link Connection#STATE_FAILED} state. Attempting
-     * to use it for anything will almost certainly result in bad things happening. Do not do this.
+     * Create a RemoteConnection represents a failure, and which will be in
+     * {@link Connection#STATE_DISCONNECTED}. Attempting to use it for anything will almost
+     * certainly result in bad things happening. Do not do this.
      *
      * @return a failed {@link RemoteConnection}
      *
diff --git a/telecomm/java/android/telecomm/RemoteConnectionService.java b/telecomm/java/android/telecomm/RemoteConnectionService.java
index dedb10e..541df4e 100644
--- a/telecomm/java/android/telecomm/RemoteConnectionService.java
+++ b/telecomm/java/android/telecomm/RemoteConnectionService.java
@@ -48,7 +48,7 @@
 
     private final IConnectionServiceAdapter mServantDelegate = new IConnectionServiceAdapter() {
         @Override
-        public void handleCreateConnectionSuccessful(
+        public void handleCreateConnectionComplete(
                 String id,
                 ConnectionRequest request,
                 ParcelableConnection parcel) {
@@ -56,6 +56,7 @@
                     findConnectionForAction(id, "handleCreateConnectionSuccessful");
             if (connection != NULL_CONNECTION && mPendingConnections.contains(connection)) {
                 mPendingConnections.remove(connection);
+                // Unconditionally initialize the connection ...
                 connection.setState(parcel.getState());
                 connection.setCallCapabilities(parcel.getCapabilities());
                 connection.setHandle(
@@ -64,29 +65,15 @@
                         parcel.getCallerDisplayName(),
                         parcel.getCallerDisplayNamePresentation());
                 // TODO: Do we need to support video providers for remote connections?
+                if (connection.getState() == Connection.STATE_DISCONNECTED) {
+                    // ... then, if it was created in a disconnected state, that indicates
+                    // failure on the providing end, so immediately mark it destroyed
+                    connection.setDestroyed();
+                }
             }
         }
 
         @Override
-        public void handleCreateConnectionFailed(
-                String id,
-                ConnectionRequest request,
-                int errorCode,
-                String errorMessage) {
-            // TODO: How do we propagate the failure codes?
-            findConnectionForAction(id, "handleCreateConnectionFailed")
-                    .setDestroyed();
-        }
-
-        @Override
-        public void handleCreateConnectionCancelled(
-                String id,
-                ConnectionRequest request) {
-            findConnectionForAction(id, "handleCreateConnectionCancelled")
-                    .setDestroyed();
-        }
-
-        @Override
         public void setActive(String callId) {
             findConnectionForAction(callId, "setActive")
                     .setState(Connection.STATE_ACTIVE);
diff --git a/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl
index e6ebae5..ef1769f 100644
--- a/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl
@@ -34,20 +34,11 @@
  * {@hide}
  */
 oneway interface IConnectionServiceAdapter {
-    void handleCreateConnectionSuccessful(
+    void handleCreateConnectionComplete(
             String callId,
             in ConnectionRequest request,
             in ParcelableConnection connection);
 
-    void handleCreateConnectionFailed(
-            String callId,
-            in ConnectionRequest request,
-            int errorCode, String errorMessage);
-
-    void handleCreateConnectionCancelled(
-            String callId,
-            in ConnectionRequest request);
-
     void setActive(String callId);
 
     void setRinging(String callId);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index c50110a..d4f8362 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2459,7 +2459,7 @@
      * @param filePath
      * @return The APDU response.
      */
-    byte[] iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
+    public byte[] iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
             String filePath) {
         try {
             return getITelephony().iccExchangeSimIO(fileID, command, p1, p2,
diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk
index 700afa1..4ce5045 100644
--- a/tools/aapt/Android.mk
+++ b/tools/aapt/Android.mk
@@ -66,6 +66,8 @@
     libexpat \
     libziparchive-host
 
+aaptCFlags := -DAAPT_VERSION=\"$(BUILD_NUMBER)\"
+
 ifeq ($(HOST_OS),linux)
     aaptHostLdLibs += -lrt -ldl -lpthread
 endif
@@ -91,6 +93,7 @@
 
 LOCAL_CFLAGS += -Wno-format-y2k
 LOCAL_CFLAGS += -DSTATIC_ANDROIDFW_FOR_TOOLS
+LOCAL_CFLAGS += $(aaptCFlags)
 ifeq (darwin,$(HOST_OS))
 LOCAL_CFLAGS += -D_DARWIN_UNLIMITED_STREAMS
 endif
@@ -110,7 +113,9 @@
 LOCAL_STATIC_LIBRARIES += \
     libaapt \
     $(aaptHostStaticLibs)
+
 LOCAL_LDLIBS += $(aaptHostLdLibs)
+LOCAL_CFLAGS += $(aaptCFlags)
 
 include $(BUILD_HOST_EXECUTABLE)
 
@@ -128,7 +133,9 @@
 LOCAL_STATIC_LIBRARIES += \
     libaapt \
     $(aaptHostStaticLibs)
+
 LOCAL_LDLIBS += $(aaptHostLdLibs)
+LOCAL_CFLAGS += $(aaptCFlags)
 
 include $(BUILD_HOST_NATIVE_TEST)
 
@@ -159,6 +166,7 @@
     libstlport_static \
     libexpat_static
 
+LOCAL_CFLAGS += $(aaptCFlags)
 LOCAL_CPPFLAGS += -Wno-non-virtual-dtor
 
 include $(BUILD_EXECUTABLE)
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 5d146d6..bdbf47b 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -24,6 +24,10 @@
 
 using namespace android;
 
+#ifndef AAPT_VERSION
+    #define AAPT_VERSION ""
+#endif
+
 /*
  * Show version info.  All the cool kids do it.
  */
@@ -32,7 +36,7 @@
     if (bundle->getFileSpecCount() != 0) {
         printf("(ignoring extra arguments)\n");
     }
-    printf("Android Asset Packaging Tool, v0.2\n");
+    printf("Android Asset Packaging Tool, v0.2-" AAPT_VERSION "\n");
 
     return 0;
 }
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index cf1d4fd..c98808f 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -484,15 +484,6 @@
                 attr.hasErrors = true;
             }
 
-            // Make sure an id is defined for this enum/flag identifier...
-            if (!attr.hasErrors && !outTable->hasBagOrEntry(itemIdent, &id16, &myPackage)) {
-                err = outTable->startBag(SourcePos(in->getPrintableSource(), block.getLineNumber()),
-                                         myPackage, id16, itemIdent, String16(), NULL);
-                if (err != NO_ERROR) {
-                    attr.hasErrors = true;
-                }
-            }
-
             if (!attr.hasErrors) {
                 if (enumOrFlagsComment.size() == 0) {
                     enumOrFlagsComment.append(mayOrMust(attr.type,
@@ -2508,11 +2499,13 @@
         sp<Type> attr = p->getType(String16("attr"), unknown);
 
         // Assign indices...
-        for (ti=0; ti<N; ti++) {
+        const size_t typeCount = p->getOrderedTypes().size();
+        for (size_t ti = 0; ti < typeCount; ti++) {
             sp<Type> t = p->getOrderedTypes().itemAt(ti);
             if (t == NULL) {
                 continue;
             }
+
             err = t->applyPublicEntryOrder();
             if (err != NO_ERROR && firstError == NO_ERROR) {
                 firstError = err;
@@ -2534,7 +2527,7 @@
         }
 
         // Assign resource IDs to keys in bags...
-        for (ti=0; ti<N; ti++) {
+        for (size_t ti = 0; ti < typeCount; ti++) {
             sp<Type> t = p->getOrderedTypes().itemAt(ti);
             if (t == NULL) {
                 continue;
@@ -3296,11 +3289,16 @@
     Item item(sourcePos, false, value, style);
 
     if (mType == TYPE_BAG) {
-        const Item& item(mBag.valueAt(0));
-        sourcePos.error("Resource entry %s is already defined as a bag.\n"
-                        "%s:%d: Originally defined here.\n",
-                        String8(mName).string(),
-                        item.sourcePos.file.string(), item.sourcePos.line);
+        if (mBag.size() == 0) {
+            sourcePos.error("Resource entry %s is already defined as a bag.",
+                    String8(mName).string());
+        } else {
+            const Item& item(mBag.valueAt(0));
+            sourcePos.error("Resource entry %s is already defined as a bag.\n"
+                            "%s:%d: Originally defined here.\n",
+                            String8(mName).string(),
+                            item.sourcePos.file.string(), item.sourcePos.line);
+        }
         return UNKNOWN_ERROR;
     }
     if ( (mType != TYPE_UNKNOWN) && (overwrite == false) ) {
@@ -3374,6 +3372,9 @@
         if (it.isId) {
             if (!table->hasBagOrEntry(key, &id16, &package)) {
                 String16 value("false");
+                NOISY(fprintf(stderr, "Generating %s:id/%s\n",
+                        String8(package).string(),
+                        String8(key).string()));
                 status_t err = table->addEntry(SourcePos(String8("<generated>"), 0), package,
                                                id16, key, value);
                 if (err != NO_ERROR) {
diff --git a/tools/layoutlib/bridge/resources/bars/status_bar.xml b/tools/layoutlib/bridge/resources/bars/status_bar.xml
index 75bfb6e..04571e1 100644
--- a/tools/layoutlib/bridge/resources/bars/status_bar.xml
+++ b/tools/layoutlib/bridge/resources/bars/status_bar.xml
@@ -1,17 +1,27 @@
 <?xml version="1.0" encoding="utf-8"?>
 <merge xmlns:android="http://schemas.android.com/apk/res/android">
-	<TextView
-			android:layout_width="wrap_content"
-			android:layout_height="wrap_content"
-			android:layout_weight="1"/>
-	<ImageView
-			android:layout_height="wrap_content"
-			android:layout_width="wrap_content"
-			android:layout_marginTop="1dp"/>
-	<ImageView
-			android:layout_height="wrap_content"
-			android:layout_width="wrap_content"
-			android:layout_marginLeft="3dp"
-			android:layout_marginRight="5dp"
-			android:layout_marginTop="2dp"/>
+    <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"/>
+    <!-- The exact size of the wifi icon is specified in order to scale it properly.
+    Without scaling, it appeared huge. This is currently, 70% of the actual size. -->
+    <ImageView
+            android:layout_height="22.4dp"
+            android:layout_width="20.65dp"
+            android:layout_marginTop="1dp"/>
+    <ImageView
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:layout_marginLeft="3dp"
+            android:layout_marginRight="5dp"
+            android:layout_marginTop="4dp"/>
+    <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="4dp"
+            android:layout_marginRight="5dp"
+            android:gravity="center_vertical"
+            android:textSize="16dp"
+            android:fontFamily="sans-serif-medium"/>
 </merge>
diff --git a/tools/layoutlib/bridge/resources/bars/v21/hdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/v21/hdpi/stat_sys_wifi_signal_4_fully.png
deleted file mode 100644
index 931daed..0000000
--- a/tools/layoutlib/bridge/resources/bars/v21/hdpi/stat_sys_wifi_signal_4_fully.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v21/mdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/v21/mdpi/stat_sys_wifi_signal_4_fully.png
deleted file mode 100644
index 6e1ac91..0000000
--- a/tools/layoutlib/bridge/resources/bars/v21/mdpi/stat_sys_wifi_signal_4_fully.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v21/xhdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/v21/xhdpi/stat_sys_wifi_signal_4_fully.png
deleted file mode 100644
index 625c61d..0000000
--- a/tools/layoutlib/bridge/resources/bars/v21/xhdpi/stat_sys_wifi_signal_4_fully.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v21/xhdpi/stat_sys_wifi_signal_4_fully.xml b/tools/layoutlib/bridge/resources/bars/v21/xhdpi/stat_sys_wifi_signal_4_fully.xml
new file mode 100644
index 0000000..0498b6c
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/v21/xhdpi/stat_sys_wifi_signal_4_fully.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32.0dp"
+        android:height="29.5dp"
+        android:viewportWidth="26.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
+</vector>
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index f939678..5b69681 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -91,7 +91,7 @@
         // first count the array size
         int count = 0;
         for (ResourceValue data : mResourceData) {
-            if (data != null) {
+            if (data != null && !RenderResources.REFERENCE_NULL.equals(data.getValue())) {
                 count++;
             }
         }
@@ -103,7 +103,8 @@
         // fill the array with the indices.
         int index = 1;
         for (int i = 0 ; i < mResourceData.length ; i++) {
-            if (mResourceData[i] != null) {
+            if (mResourceData[i] != null
+                    && !RenderResources.REFERENCE_NULL.equals(mResourceData[i].getValue())) {
                 mIndices[index++] = i;
             }
         }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java
index 9b814f5..16b54f1 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java
@@ -20,10 +20,7 @@
 import java.util.Collections;
 import java.util.List;
 
-import static android.os.Build.VERSION_CODES.GINGERBREAD;
-import static android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH;
-import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR2;
-import static android.os.Build.VERSION_CODES.KITKAT;
+import static android.os.Build.VERSION_CODES.*;
 
 /**
  * Various helper methods to simulate older versions of platform.
@@ -39,13 +36,16 @@
     private static final List<String> sDefaultResourceDir =
             Collections.singletonList(DEFAULT_RESOURCE_DIR);
 
+    private static final int WHITE = 0xFFFFFFFF;
+    private static final int BLACK = 0xFF000000;
+
     public static boolean showOnScreenNavBar(int platformVersion) {
         return platformVersion == 0 || platformVersion >= ICE_CREAM_SANDWICH;
     }
 
     public static int getStatusBarColor(int platformVersion) {
         // return white for froyo and earlier; black otherwise.
-        return platformVersion == 0 || platformVersion >= GINGERBREAD ? 0xFF000000 : 0xFFFFFFFF;
+        return platformVersion == 0 || platformVersion >= GINGERBREAD ? BLACK : WHITE;
     }
 
     public static List<String> getResourceDirs(int platformVersion) {
@@ -70,4 +70,49 @@
 
         return Collections.unmodifiableList(list);
     }
+
+    public static String getTime(int platformVersion) {
+        if (platformVersion == 0) {
+            // TODO: revisit when the version is selected.
+            return "4:57";
+        }
+        if (platformVersion < GINGERBREAD) {
+            return "2:20";
+        }
+        if (platformVersion < ICE_CREAM_SANDWICH) {
+            return "2:30";
+        }
+        if (platformVersion < JELLY_BEAN) {
+            return "4:00";
+        }
+        if (platformVersion < KITKAT) {
+            return "4:30";
+        }
+        if (platformVersion <= KITKAT_WATCH) {
+            return "4:40";
+        }
+        // Should never happen.
+        return "4:04";
+    }
+
+    public static int getTimeColor(int platformVersion) {
+        if (platformVersion == 0 || platformVersion >= KITKAT ||
+                platformVersion > FROYO && platformVersion < HONEYCOMB) {
+            // Gingerbread and KitKat onwards.
+            return WHITE;
+        }
+        // Black for froyo.
+        if (platformVersion < GINGERBREAD) {
+            return BLACK;
+        } else if (platformVersion < KITKAT) {
+            // Honeycomb to JB-mr2: Holo blue light.
+            return 0xff33b5e5;
+        }
+        // Should never happen.
+        return WHITE;
+    }
+
+    public static String getWifiIconType(int platformVersion) {
+        return platformVersion == 0 ? "xml" : "png";
+    }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
index bed232ab..13ddf07 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
@@ -127,24 +127,25 @@
         }
     }
 
-    protected TextView setText(int index, String stringReference) {
+    protected TextView setText(int index, String string, boolean reference) {
         View child = getChildAt(index);
         if (child instanceof TextView) {
             TextView textView = (TextView) child;
-            setText(textView, stringReference);
+            setText(textView, string, reference);
             return textView;
         }
 
         return null;
     }
 
-    private void setText(TextView textView, String stringReference) {
-        ResourceValue value = getResourceValue(stringReference);
-        if (value != null) {
-            textView.setText(value.getValue());
-        } else {
-            textView.setText(stringReference);
+    private void setText(TextView textView, String string, boolean reference) {
+        if (reference) {
+            ResourceValue value = getResourceValue(string);
+            if (value != null) {
+                string = value.getValue();
+            }
         }
+        textView.setText(string);
     }
 
     protected void setStyle(String themeEntryName) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
index 1795db9..c7c62d6 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
@@ -16,22 +16,38 @@
 
 package com.android.layoutlib.bridge.bars;
 
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
+import com.android.layoutlib.bridge.impl.ParserFactory;
 import com.android.resources.Density;
 
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.content.Context;
+import android.graphics.drawable.Drawable;
 import android.view.Gravity;
+import android.view.View;
+import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import java.io.IOException;
+import java.io.InputStream;
+
 public class StatusBar extends CustomBar {
 
+    private final Context mContext;
+    private final int mSimulatedPlatformVersion;
+
     public StatusBar(Context context, Density density, int direction, boolean RtlEnabled,
             int simulatedPlatformVersion) throws XmlPullParserException {
         // FIXME: if direction is RTL but it's not enabled in application manifest, mirror this bar.
         super(context, LinearLayout.HORIZONTAL, "/bars/status_bar.xml", "status_bar.xml",
                 simulatedPlatformVersion);
+        mContext = context;
+        mSimulatedPlatformVersion = simulatedPlatformVersion;
 
         // FIXME: use FILL_H?
         setGravity(Gravity.START | Gravity.TOP | Gravity.RIGHT);
@@ -41,8 +57,44 @@
         // created for them.
         // We do know the order though.
         // 0 is the spacer
-        loadIcon(1, "stat_sys_wifi_signal_4_fully.png", density);
+        loadIcon(1, "stat_sys_wifi_signal_4_fully."
+                        + Config.getWifiIconType(simulatedPlatformVersion), density);
         loadIcon(2, "stat_sys_battery_100.png", density);
+        setText(3, Config.getTime(simulatedPlatformVersion), false)
+                .setTextColor(Config.getTimeColor(simulatedPlatformVersion));
+    }
+
+    @Override
+    protected void loadIcon(int index, String iconName, Density density) {
+        if (!iconName.endsWith(".xml")) {
+            super.loadIcon(index, iconName, density);
+            return;
+        }
+        View child = getChildAt(index);
+        if (child instanceof ImageView) {
+            ImageView imageView = (ImageView) child;
+            // The xml is stored only in xhdpi.
+            IconLoader iconLoader = new IconLoader(iconName, Density.XHIGH,
+                    mSimulatedPlatformVersion, null);
+            InputStream stream = iconLoader.getIcon();
+
+            if (stream != null) {
+                try {
+                    BridgeXmlBlockParser parser = new BridgeXmlBlockParser(
+                            ParserFactory.create(stream, null), (BridgeContext) mContext, true);
+                    Drawable drawable = Drawable.createFromXml(mContext.getResources(), parser);
+                    if (drawable != null) {
+                        imageView.setImageDrawable(drawable);
+                    }
+                } catch (XmlPullParserException e) {
+                    Bridge.getLog().error(LayoutLog.TAG_BROKEN, "Unable to draw wifi icon", e,
+                            null);
+                } catch (IOException e) {
+                    Bridge.getLog().error(LayoutLog.TAG_BROKEN, "Unable to draw wifi icon", e,
+                            null);
+                }
+            }
+        }
     }
 
     @Override
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java
index ff952bd..10f1383 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java
@@ -34,7 +34,7 @@
         // Cannot access the inside items through id because no R.id values have been
         // created for them.
         // We do know the order though.
-        mTextView = setText(0, label);
+        mTextView = setText(0, label, true);
 
         setStyle("windowTitleBackgroundStyle");
     }
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 3c37b94..ac2a176 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -21,7 +21,7 @@
 import android.net.IpConfiguration.ProxySettings;
 import android.net.IpConfiguration.IpAssignment;
 import android.net.ProxyInfo;
-import android.net.LinkProperties;
+import android.net.StaticIpConfiguration;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -1096,13 +1096,13 @@
     }
 
     /** @hide */
-    public LinkProperties getLinkProperties() {
-        return mIpConfiguration.linkProperties;
+    public StaticIpConfiguration getStaticIpConfiguration() {
+        return mIpConfiguration.getStaticIpConfiguration();
     }
 
     /** @hide */
-    public void setLinkProperties(LinkProperties linkProperties) {
-        mIpConfiguration.linkProperties = linkProperties;
+    public void setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration) {
+        mIpConfiguration.setStaticIpConfiguration(staticIpConfiguration);
     }
 
     /** @hide */
@@ -1126,9 +1126,19 @@
     }
 
     /** @hide */
+    public ProxyInfo getHttpProxy() {
+        return mIpConfiguration.httpProxy;
+    }
+
+    /** @hide */
+    public void setHttpProxy(ProxyInfo httpProxy) {
+        mIpConfiguration.httpProxy = httpProxy;
+    }
+
+    /** @hide */
     public void setProxy(ProxySettings settings, ProxyInfo proxy) {
         mIpConfiguration.proxySettings = settings;
-        mIpConfiguration.linkProperties.setHttpProxy(proxy);
+        mIpConfiguration.httpProxy = proxy;
     }
 
     /** Implement the Parcelable interface {@hide} */