Merge "ActionBarOverlay needs to be focusable" into lmp-dev
diff --git a/Android.mk b/Android.mk
index 4a97c28..b419231 100644
--- a/Android.mk
+++ b/Android.mk
@@ -350,8 +350,8 @@
 	media/java/android/media/tv/ITvInputServiceCallback.aidl \
 	media/java/android/media/tv/ITvInputSession.aidl \
 	media/java/android/media/tv/ITvInputSessionCallback.aidl \
-	telecomm/java/com/android/internal/telecomm/IVideoCallCallback.aidl \
-	telecomm/java/com/android/internal/telecomm/IVideoCallProvider.aidl \
+	telecomm/java/com/android/internal/telecomm/IVideoCallback.aidl \
+	telecomm/java/com/android/internal/telecomm/IVideoProvider.aidl \
 	telecomm/java/com/android/internal/telecomm/IConnectionService.aidl \
 	telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl \
 	telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl \
diff --git a/api/current.txt b/api/current.txt
index e8d1369..584246b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -114,7 +114,6 @@
     field public static final java.lang.String RECEIVE_SMS = "android.permission.RECEIVE_SMS";
     field public static final java.lang.String RECEIVE_WAP_PUSH = "android.permission.RECEIVE_WAP_PUSH";
     field public static final java.lang.String RECORD_AUDIO = "android.permission.RECORD_AUDIO";
-    field public static final java.lang.String RECOVERY = "android.permission.RECOVERY";
     field public static final java.lang.String REORDER_TASKS = "android.permission.REORDER_TASKS";
     field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
     field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
@@ -465,7 +464,6 @@
     field public static final int contentInsetLeft = 16843861; // 0x1010455
     field public static final int contentInsetRight = 16843862; // 0x1010456
     field public static final int contentInsetStart = 16843859; // 0x1010453
-    field public static final int contentRatingSystemXml = 16843955; // 0x10104b3
     field public static final int controlX1 = 16843798; // 0x1010416
     field public static final int controlX2 = 16843800; // 0x1010418
     field public static final int controlY1 = 16843799; // 0x1010417
@@ -1356,6 +1354,7 @@
     field public static final int trimPathEnd = 16843811; // 0x1010423
     field public static final int trimPathOffset = 16843812; // 0x1010424
     field public static final int trimPathStart = 16843810; // 0x1010422
+    field public static final int tvContentRatingDescription = 16843955; // 0x10104b3
     field public static final int type = 16843169; // 0x10101a1
     field public static final int typeface = 16842902; // 0x1010096
     field public static final int uiOptions = 16843672; // 0x1010398
@@ -3438,7 +3437,6 @@
     method public void onAttachFragment(android.app.Fragment);
     method public void onAttachedToWindow();
     method public void onBackPressed();
-    method public void onBackgroundMediaPlayingChanged(boolean);
     method protected void onChildTitleChanged(android.app.Activity, java.lang.CharSequence);
     method public void onConfigurationChanged(android.content.res.Configuration);
     method public void onContentChanged();
@@ -3495,13 +3493,13 @@
     method public boolean onSearchRequested();
     method protected void onStart();
     method protected void onStop();
-    method public void onStopMediaPlaying();
     method protected void onTitleChanged(java.lang.CharSequence, int);
     method public boolean onTouchEvent(android.view.MotionEvent);
     method public boolean onTrackballEvent(android.view.MotionEvent);
     method public void onTrimMemory(int);
     method public void onUserInteraction();
     method protected void onUserLeaveHint();
+    method public void onVisibleBehindCancelled();
     method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
     method public void onWindowFocusChanged(boolean);
     method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
@@ -3513,6 +3511,7 @@
     method public void registerForContextMenu(android.view.View);
     method public final deprecated void removeDialog(int);
     method public void reportFullyDrawn();
+    method public boolean requestVisibleBehind(boolean);
     method public final boolean requestWindowFeature(int);
     method public final void runOnUiThread(java.lang.Runnable);
     method public void setActionBar(android.widget.Toolbar);
@@ -3531,7 +3530,6 @@
     method public void setImmersive(boolean);
     method public void setIntent(android.content.Intent);
     method public final void setMediaController(android.media.session.MediaController);
-    method public boolean setMediaPlaying(boolean);
     method public final void setProgress(int);
     method public final void setProgressBarIndeterminate(boolean);
     method public final void setProgressBarIndeterminateVisibility(boolean);
@@ -3772,20 +3770,11 @@
     method public void update(android.app.ActivityOptions);
   }
 
-  public class AlarmClockInfo implements android.os.Parcelable {
-    ctor public AlarmClockInfo(long, android.app.PendingIntent);
-    method public int describeContents();
-    method public android.app.PendingIntent getShowIntent();
-    method public long getTriggerTime();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator CREATOR;
-  }
-
   public class AlarmManager {
     method public void cancel(android.app.PendingIntent);
-    method public android.app.AlarmClockInfo getNextAlarmClock();
+    method public android.app.AlarmManager.AlarmClockInfo getNextAlarmClock();
     method public void set(int, long, android.app.PendingIntent);
-    method public void setAlarmClock(android.app.AlarmClockInfo, android.app.PendingIntent);
+    method public void setAlarmClock(android.app.AlarmManager.AlarmClockInfo, android.app.PendingIntent);
     method public void setExact(int, long, android.app.PendingIntent);
     method public void setInexactRepeating(int, long, long, android.app.PendingIntent);
     method public void setRepeating(int, long, long, android.app.PendingIntent);
@@ -3804,6 +3793,15 @@
     field public static final int RTC_WAKEUP = 0; // 0x0
   }
 
+  public static final class AlarmManager.AlarmClockInfo implements android.os.Parcelable {
+    ctor public AlarmManager.AlarmClockInfo(long, android.app.PendingIntent);
+    method public int describeContents();
+    method public android.app.PendingIntent getShowIntent();
+    method public long getTriggerTime();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
   public class AlertDialog extends android.app.Dialog implements android.content.DialogInterface {
     ctor protected AlertDialog(android.content.Context);
     ctor protected AlertDialog(android.content.Context, int);
@@ -5238,8 +5236,8 @@
     field public static java.lang.String ACTION_EXIT_CAR_MODE;
     field public static java.lang.String ACTION_EXIT_DESK_MODE;
     field public static final int DISABLE_CAR_MODE_GO_HOME = 1; // 0x1
+    field public static final int ENABLE_CAR_MODE_ALLOW_SLEEP = 2; // 0x2
     field public static final int ENABLE_CAR_MODE_GO_CAR_HOME = 1; // 0x1
-    field public static final int ENABLE_CAR_MODE_NO_WAKE_LOCK = 2; // 0x2
     field public static final int MODE_NIGHT_AUTO = 0; // 0x0
     field public static final int MODE_NIGHT_NO = 1; // 0x1
     field public static final int MODE_NIGHT_YES = 2; // 0x2
@@ -13588,7 +13586,7 @@
 
   public class InputMethodService extends android.inputmethodservice.AbstractInputMethodService {
     ctor public InputMethodService();
-    method public boolean enableHardwareAcceleration();
+    method public deprecated boolean enableHardwareAcceleration();
     method public int getBackDisposition();
     method public int getCandidatesHiddenVisibility();
     method public android.view.inputmethod.InputBinding getCurrentInputBinding();
@@ -15762,11 +15760,12 @@
   }
 
   public class Ringtone {
-    method public int getStreamType();
+    method public deprecated int getStreamType();
     method public java.lang.String getTitle(android.content.Context);
     method public boolean isPlaying();
     method public void play();
-    method public void setStreamType(int);
+    method public void setAudioAttributes(android.media.AudioAttributes) throws java.lang.IllegalArgumentException;
+    method public deprecated void setStreamType(int);
     method public void stop();
   }
 
@@ -16718,6 +16717,7 @@
     method public void onPlaybackStateChanged(android.media.session.PlaybackState);
     method public void onQueueChanged(java.util.List<android.media.session.MediaSession.Track>);
     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);
   }
@@ -22810,7 +22810,6 @@
     field public static final deprecated int FULL_WAKE_LOCK = 26; // 0x1a
     field public static final int ON_AFTER_RELEASE = 536870912; // 0x20000000
     field public static final int PARTIAL_WAKE_LOCK = 1; // 0x1
-    field public static final java.lang.String REBOOT_RECOVERY = "recovery";
     field public static final deprecated int SCREEN_BRIGHT_WAKE_LOCK = 10; // 0xa
     field public static final deprecated int SCREEN_DIM_WAKE_LOCK = 6; // 0x6
   }
@@ -25886,8 +25885,10 @@
     field public static final java.lang.String ACTION_SHOW_REGULATORY_INFO = "android.settings.SHOW_REGULATORY_INFO";
     field public static final java.lang.String ACTION_SOUND_SETTINGS = "android.settings.SOUND_SETTINGS";
     field public static final java.lang.String ACTION_SYNC_SETTINGS = "android.settings.SYNC_SETTINGS";
+    field public static final java.lang.String ACTION_USAGE_ACCESS_SETTINGS = "android.settings.USAGE_ACCESS_SETTINGS";
     field public static final java.lang.String ACTION_USER_DICTIONARY_SETTINGS = "android.settings.USER_DICTIONARY_SETTINGS";
     field public static final java.lang.String ACTION_VOICE_CONTROL_AIRPLANE_MODE = "android.settings.VOICE_CONTROL_AIRPLANE_MODE";
+    field public static final java.lang.String ACTION_VOICE_INPUT_SETTINGS = "android.settings.VOICE_INPUT_SETTINGS";
     field public static final java.lang.String ACTION_WIFI_IP_SETTINGS = "android.settings.WIFI_IP_SETTINGS";
     field public static final java.lang.String ACTION_WIFI_SETTINGS = "android.settings.WIFI_SETTINGS";
     field public static final java.lang.String ACTION_WIRELESS_SETTINGS = "android.settings.WIRELESS_SETTINGS";
@@ -28812,70 +28813,7 @@
 
 package android.telecomm {
 
-  public final class Call {
-    method public void addListener(android.telecomm.Call.Listener);
-    method public void answer(int);
-    method public void conference(android.telecomm.Call);
-    method public void disconnect();
-    method public java.util.List<java.lang.String> getCannedTextResponses();
-    method public java.util.List<android.telecomm.Call> getChildren();
-    method public java.util.List<android.telecomm.Call> getConferenceableCalls();
-    method public android.telecomm.Call.Details getDetails();
-    method public android.telecomm.Call getParent();
-    method public java.lang.String getRemainingPostDialSequence();
-    method public int getState();
-    method public android.telecomm.InCallService.VideoCall getVideoCall();
-    method public void hold();
-    method public void phoneAccountClicked();
-    method public void phoneAccountSelected(android.telecomm.PhoneAccountHandle);
-    method public void playDtmfTone(char);
-    method public void postDialContinue(boolean);
-    method public void reject(boolean, java.lang.String);
-    method public void removeListener(android.telecomm.Call.Listener);
-    method public void splitFromConference();
-    method public void stopDtmfTone();
-    method public void swapWithBackgroundCall();
-    method public void unhold();
-    field public static final int STATE_ACTIVE = 4; // 0x4
-    field public static final int STATE_CONNECTING = 9; // 0x9
-    field public static final int STATE_DIALING = 1; // 0x1
-    field public static final int STATE_DISCONNECTED = 7; // 0x7
-    field public static final int STATE_HOLDING = 3; // 0x3
-    field public static final int STATE_NEW = 0; // 0x0
-    field public static final int STATE_PRE_DIAL_WAIT = 8; // 0x8
-    field public static final int STATE_RINGING = 2; // 0x2
-  }
-
-  public static class Call.Details {
-    method public android.telecomm.PhoneAccountHandle getAccountHandle();
-    method public int getCallCapabilities();
-    method public java.lang.String getCallerDisplayName();
-    method public int getCallerDisplayNamePresentation();
-    method public long getConnectTimeMillis();
-    method public int getDisconnectCauseCode();
-    method public java.lang.String getDisconnectCauseMsg();
-    method public android.telecomm.GatewayInfo getGatewayInfo();
-    method public android.net.Uri getHandle();
-    method public int getHandlePresentation();
-    method public android.telecomm.StatusHints getStatusHints();
-    method public int getVideoState();
-  }
-
-  public static abstract class Call.Listener {
-    ctor public Call.Listener();
-    method public void onCallDestroyed(android.telecomm.Call);
-    method public void onCannedTextResponsesLoaded(android.telecomm.Call, java.util.List<java.lang.String>);
-    method public void onChildrenChanged(android.telecomm.Call, java.util.List<android.telecomm.Call>);
-    method public void onConferenceableCallsChanged(android.telecomm.Call, java.util.List<android.telecomm.Call>);
-    method public void onDetailsChanged(android.telecomm.Call, android.telecomm.Call.Details);
-    method public void onParentChanged(android.telecomm.Call, android.telecomm.Call);
-    method public void onPostDialWait(android.telecomm.Call, java.lang.String);
-    method public void onStartActivity(android.telecomm.Call, android.app.PendingIntent);
-    method public void onStateChanged(android.telecomm.Call, int);
-    method public void onVideoCallChanged(android.telecomm.Call, android.telecomm.InCallService.VideoCall);
-  }
-
-  public final class CallAudioState implements android.os.Parcelable {
+  public final class AudioState 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;
@@ -28890,8 +28828,8 @@
     field public final int supportedRouteMask;
   }
 
-  public final class CallCameraCapabilities implements android.os.Parcelable {
-    ctor public CallCameraCapabilities(boolean, float, int, int);
+  public final class CameraCapabilities implements android.os.Parcelable {
+    ctor public CameraCapabilities(boolean, float, int, int);
     method public int describeContents();
     method public int getHeight();
     method public float getMaxZoom();
@@ -28901,55 +28839,18 @@
     field public static final android.os.Parcelable.Creator CREATOR;
   }
 
-  public final class CallCapabilities {
-    method public static java.lang.String toString(int);
-    field public static final int ADD_CALL = 16; // 0x10
-    field public static final int ALL = 3327; // 0xcff
-    field public static final int GENERIC_CONFERENCE = 128; // 0x80
-    field public static final int HOLD = 1; // 0x1
-    field public static final int MERGE_CALLS = 4; // 0x4
-    field public static final int MUTE = 64; // 0x40
-    field public static final int RESPOND_VIA_TEXT = 32; // 0x20
-    field public static final int SUPPORTS_VT_LOCAL = 256; // 0x100
-    field public static final int SUPPORTS_VT_REMOTE = 512; // 0x200
-    field public static final int SUPPORT_HOLD = 2; // 0x2
-    field public static final int SWAP_CALLS = 8; // 0x8
-    field public static final int VoLTE = 1024; // 0x400
-    field public static final int VoWIFI = 2048; // 0x800
-  }
-
-  public class CallPropertyPresentation {
-    ctor public CallPropertyPresentation();
-    field public static final int ALLOWED = 1; // 0x1
-    field public static final int PAYPHONE = 4; // 0x4
-    field public static final int RESTRICTED = 2; // 0x2
-    field public static final int UNKNOWN = 3; // 0x3
-  }
-
-  public final class CallState extends java.lang.Enum {
-    method public static android.telecomm.CallState valueOf(java.lang.String);
-    method public static final android.telecomm.CallState[] values();
-    enum_constant public static final android.telecomm.CallState ACTIVE;
-    enum_constant public static final android.telecomm.CallState CONNECTING;
-    enum_constant public static final android.telecomm.CallState DIALING;
-    enum_constant public static final android.telecomm.CallState DISCONNECTED;
-    enum_constant public static final android.telecomm.CallState NEW;
-    enum_constant public static final android.telecomm.CallState ON_HOLD;
-    enum_constant public static final android.telecomm.CallState PRE_DIAL_WAIT;
-    enum_constant public static final android.telecomm.CallState RINGING;
-  }
-
   public abstract class Connection {
     ctor public Connection();
+    method public static android.telecomm.Connection createCanceledConnection();
+    method public static android.telecomm.Connection createFailedConnection(int, java.lang.String);
     method public final void destroy();
     method public final boolean getAudioModeIsVoip();
-    method public final android.telecomm.CallAudioState getCallAudioState();
+    method public final android.telecomm.AudioState getAudioState();
     method public final int getCallCapabilities();
     method public final java.lang.String getCallerDisplayName();
     method public final int getCallerDisplayNamePresentation();
-    method public static android.telecomm.Connection getCanceledConnection();
     method public final java.util.List<android.telecomm.Connection> getChildConnections();
-    method public static android.telecomm.Connection getFailedConnection(int, java.lang.String);
+    method public final java.util.List<android.telecomm.Connection> getConferenceableConnections();
     method public final int getFailureCode();
     method public final java.lang.String getFailureMessage();
     method public final android.net.Uri getHandle();
@@ -28957,7 +28858,7 @@
     method public final android.telecomm.Connection getParentConnection();
     method public final int getState();
     method public final android.telecomm.StatusHints getStatusHints();
-    method public final android.telecomm.ConnectionService.VideoCallProvider getVideoCallProvider();
+    method public final android.telecomm.Connection.VideoProvider getVideoProvider();
     method public final int getVideoState();
     method public final boolean isConferenceConnection();
     method public final boolean isRequestingRingback();
@@ -28972,10 +28873,9 @@
     method public void onPostDialContinue(boolean);
     method public void onReject();
     method public void onSeparate();
-    method public void onSetAudioState(android.telecomm.CallAudioState);
+    method public void onSetAudioState(android.telecomm.AudioState);
     method public void onSetState(int);
     method public void onStopDtmfTone();
-    method public void onSwapWithBackgroundCall();
     method public void onUnhold();
     method public final void setActive();
     method public final void setAudioModeIsVoip(boolean);
@@ -28994,31 +28894,55 @@
     method public final void setPostDialWait(java.lang.String);
     method public final void setRequestingRingback(boolean);
     method public final void setRinging();
-    method public final void setSignal(android.os.Bundle);
     method public final void setStatusHints(android.telecomm.StatusHints);
-    method public final void setVideoCallProvider(android.telecomm.ConnectionService.VideoCallProvider);
+    method public final void setVideoProvider(android.telecomm.Connection.VideoProvider);
     method public final void setVideoState(int);
     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
+    field public static final int STATE_RINGING = 2; // 0x2
   }
 
-  public final class Connection.State {
-    field public static final int ACTIVE = 4; // 0x4
-    field public static final int CANCELED = 8; // 0x8
-    field public static final int DIALING = 3; // 0x3
-    field public static final int DISCONNECTED = 6; // 0x6
-    field public static final int FAILED = 7; // 0x7
-    field public static final int HOLDING = 5; // 0x5
-    field public static final int INITIALIZING = 0; // 0x0
-    field public static final int NEW = 1; // 0x1
-    field public static final int RINGING = 2; // 0x2
+  public static abstract class Connection.VideoProvider {
+    ctor public Connection.VideoProvider();
+    method public void changeCallDataUsage(int);
+    method public void changeCameraCapabilities(android.telecomm.CameraCapabilities);
+    method public void changePeerDimensions(int, int);
+    method public void handleCallSessionEvent(int);
+    method public abstract void onRequestCallDataUsage();
+    method public abstract void onRequestCameraCapabilities();
+    method public abstract void onSendSessionModifyRequest(android.telecomm.VideoProfile);
+    method public abstract void onSendSessionModifyResponse(android.telecomm.VideoProfile);
+    method public abstract void onSetCamera(java.lang.String);
+    method public abstract void onSetDeviceOrientation(int);
+    method public abstract void onSetDisplaySurface(android.view.Surface);
+    method public abstract void onSetPauseImage(java.lang.String);
+    method public abstract void onSetPreviewSurface(android.view.Surface);
+    method public abstract void onSetZoom(float);
+    method public void receiveSessionModifyRequest(android.telecomm.VideoProfile);
+    method public void receiveSessionModifyResponse(int, android.telecomm.VideoProfile, android.telecomm.VideoProfile);
+    field public static final int SESSION_EVENT_CAMERA_FAILURE = 5; // 0x5
+    field public static final int SESSION_EVENT_CAMERA_READY = 6; // 0x6
+    field public static final int SESSION_EVENT_RX_PAUSE = 1; // 0x1
+    field public static final int SESSION_EVENT_RX_RESUME = 2; // 0x2
+    field public static final int SESSION_EVENT_TX_START = 3; // 0x3
+    field public static final int SESSION_EVENT_TX_STOP = 4; // 0x4
+    field public static final int SESSION_MODIFY_REQUEST_FAIL = 2; // 0x2
+    field public static final int SESSION_MODIFY_REQUEST_INVALID = 3; // 0x3
+    field public static final int SESSION_MODIFY_REQUEST_SUCCESS = 1; // 0x1
   }
 
   public final class ConnectionRequest implements android.os.Parcelable {
-    ctor public ConnectionRequest(android.telecomm.PhoneAccountHandle, java.lang.String, android.net.Uri, int, android.os.Bundle, int);
+    ctor public ConnectionRequest(android.telecomm.PhoneAccountHandle, android.net.Uri, int, android.os.Bundle, int);
     method public int describeContents();
     method public android.telecomm.PhoneAccountHandle getAccountHandle();
-    method public java.lang.String getCallId();
     method public android.os.Bundle getExtras();
     method public android.net.Uri getHandle();
     method public int getHandlePresentation();
@@ -29041,32 +28965,6 @@
     field public static final java.lang.String SERVICE_INTERFACE = "android.telecomm.ConnectionService";
   }
 
-  public static abstract interface ConnectionService.CreateConnectionResponse {
-    method public abstract void onCancel(android.telecomm.ConnectionRequest);
-    method public abstract void onFailure(android.telecomm.ConnectionRequest, int, java.lang.String);
-    method public abstract void onSuccess(android.telecomm.ConnectionRequest, CONNECTION);
-  }
-
-  public static abstract class ConnectionService.VideoCallProvider {
-    ctor public ConnectionService.VideoCallProvider();
-    method public void changeCallDataUsage(int);
-    method public void changeCameraCapabilities(android.telecomm.CallCameraCapabilities);
-    method public void changePeerDimensions(int, int);
-    method public void handleCallSessionEvent(int);
-    method public void onRequestCallDataUsage();
-    method public void onRequestCameraCapabilities();
-    method public void onSendSessionModifyRequest(android.telecomm.VideoCallProfile);
-    method public void onSendSessionModifyResponse(android.telecomm.VideoCallProfile);
-    method public void onSetCamera(java.lang.String);
-    method public void onSetDeviceOrientation(int);
-    method public void onSetDisplaySurface(android.view.Surface);
-    method public void onSetPauseImage(java.lang.String);
-    method public void onSetPreviewSurface(android.view.Surface);
-    method public void onSetZoom(float);
-    method public void receiveSessionModifyRequest(android.telecomm.VideoCallProfile);
-    method public void receiveSessionModifyResponse(int, android.telecomm.VideoCallProfile, android.telecomm.VideoCallProfile);
-  }
-
   public class GatewayInfo implements android.os.Parcelable {
     method public int describeContents();
     method public android.net.Uri getGatewayHandle();
@@ -29077,87 +28975,8 @@
     field public static final android.os.Parcelable.Creator CREATOR;
   }
 
-  public final class InCallAdapter {
-    method public void answerCall(java.lang.String, int);
-    method public void disconnectCall(java.lang.String);
-    method public void holdCall(java.lang.String);
-    method public void mute(boolean);
-    method public void phoneAccountClicked(java.lang.String);
-    method public void phoneAccountSelected(java.lang.String, android.telecomm.PhoneAccountHandle);
-    method public void playDtmfTone(java.lang.String, char);
-    method public void postDialContinue(java.lang.String, boolean);
-    method public void rejectCall(java.lang.String, boolean, java.lang.String);
-    method public void setAudioRoute(int);
-    method public void stopDtmfTone(java.lang.String);
-    method public void swapWithBackgroundCall(java.lang.String);
-    method public void turnProximitySensorOff(boolean);
-    method public void turnProximitySensorOn();
-    method public void unholdCall(java.lang.String);
-  }
-
-  public abstract class InCallService extends android.app.Service {
-    ctor public InCallService();
-    method public android.telecomm.Phone getPhone();
-    method public android.os.IBinder onBind(android.content.Intent);
-    method public void onPhoneCreated(android.telecomm.Phone);
-    method public void onPhoneDestroyed(android.telecomm.Phone);
-  }
-
-  public static abstract class InCallService.VideoCall {
-    ctor public InCallService.VideoCall();
-    method public abstract void requestCallDataUsage();
-    method public abstract void requestCameraCapabilities();
-    method public abstract void sendSessionModifyRequest(android.telecomm.VideoCallProfile);
-    method public abstract void sendSessionModifyResponse(android.telecomm.VideoCallProfile);
-    method public abstract void setCamera(java.lang.String);
-    method public abstract void setDeviceOrientation(int);
-    method public abstract void setDisplaySurface(android.view.Surface);
-    method public abstract void setPauseImage(java.lang.String);
-    method public abstract void setPreviewSurface(android.view.Surface);
-    method public abstract void setVideoCallListener(android.telecomm.InCallService.VideoCall.Listener);
-    method public abstract void setZoom(float);
-    field public static final int SESSION_EVENT_CAMERA_FAILURE = 5; // 0x5
-    field public static final int SESSION_EVENT_CAMERA_READY = 6; // 0x6
-    field public static final int SESSION_EVENT_RX_PAUSE = 1; // 0x1
-    field public static final int SESSION_EVENT_RX_RESUME = 2; // 0x2
-    field public static final int SESSION_EVENT_TX_START = 3; // 0x3
-    field public static final int SESSION_EVENT_TX_STOP = 4; // 0x4
-    field public static final int SESSION_MODIFY_REQUEST_FAIL = 2; // 0x2
-    field public static final int SESSION_MODIFY_REQUEST_INVALID = 3; // 0x3
-    field public static final int SESSION_MODIFY_REQUEST_SUCCESS = 1; // 0x1
-  }
-
-  public static abstract class InCallService.VideoCall.Listener {
-    ctor public InCallService.VideoCall.Listener();
-    method public abstract void onCallDataUsageChanged(int);
-    method public abstract void onCallSessionEvent(int);
-    method public abstract void onCameraCapabilitiesChanged(android.telecomm.CallCameraCapabilities);
-    method public abstract void onPeerDimensionsChanged(int, int);
-    method public abstract void onSessionModifyRequestReceived(android.telecomm.VideoCallProfile);
-    method public abstract void onSessionModifyResponseReceived(int, android.telecomm.VideoCallProfile, android.telecomm.VideoCallProfile);
-  }
-
-  public final class Phone {
-    method public final void addListener(android.telecomm.Phone.Listener);
-    method public final android.telecomm.CallAudioState getAudioState();
-    method public final java.util.List<android.telecomm.Call> getCalls();
-    method public final void removeListener(android.telecomm.Phone.Listener);
-    method public final void setAudioRoute(int);
-    method public final void setMuted(boolean);
-    method public final void setProximitySensorOff(boolean);
-    method public final void setProximitySensorOn();
-  }
-
-  public static abstract class Phone.Listener {
-    ctor public Phone.Listener();
-    method public void onAudioStateChanged(android.telecomm.Phone, android.telecomm.CallAudioState);
-    method public void onBringToForeground(android.telecomm.Phone, boolean);
-    method public void onCallAdded(android.telecomm.Phone, android.telecomm.Call);
-    method public void onCallRemoved(android.telecomm.Phone, android.telecomm.Call);
-  }
-
   public class PhoneAccount implements android.os.Parcelable {
-    ctor public PhoneAccount(android.telecomm.PhoneAccountHandle, android.net.Uri, java.lang.String, int, int, java.lang.CharSequence, java.lang.CharSequence);
+    method public static android.telecomm.PhoneAccount.Builder builder();
     method public int describeContents();
     method public android.telecomm.PhoneAccountHandle getAccountHandle();
     method public int getCapabilities();
@@ -29174,6 +28993,17 @@
     field public static final android.os.Parcelable.Creator CREATOR;
   }
 
+  public static class PhoneAccount.Builder {
+    method public android.telecomm.PhoneAccount build();
+    method public android.telecomm.PhoneAccount.Builder withAccountHandle(android.telecomm.PhoneAccountHandle);
+    method public android.telecomm.PhoneAccount.Builder withCapabilities(int);
+    method public android.telecomm.PhoneAccount.Builder withHandle(android.net.Uri);
+    method public android.telecomm.PhoneAccount.Builder withIconResId(int);
+    method public android.telecomm.PhoneAccount.Builder withLabel(java.lang.CharSequence);
+    method public android.telecomm.PhoneAccount.Builder withShortDescription(java.lang.CharSequence);
+    method public android.telecomm.PhoneAccount.Builder withSubscriptionNumber(java.lang.String);
+  }
+
   public class PhoneAccountHandle implements android.os.Parcelable {
     ctor public PhoneAccountHandle(android.content.ComponentName, java.lang.String);
     method public int describeContents();
@@ -29183,6 +29013,31 @@
     field public static final android.os.Parcelable.Creator CREATOR;
   }
 
+  public final class PhoneCapabilities {
+    method public static java.lang.String toString(int);
+    field public static final int ADD_CALL = 16; // 0x10
+    field public static final int ALL = 3327; // 0xcff
+    field public static final int GENERIC_CONFERENCE = 128; // 0x80
+    field public static final int HOLD = 1; // 0x1
+    field public static final int MERGE_CALLS = 4; // 0x4
+    field public static final int MUTE = 64; // 0x40
+    field public static final int RESPOND_VIA_TEXT = 32; // 0x20
+    field public static final int SUPPORTS_VT_LOCAL = 256; // 0x100
+    field public static final int SUPPORTS_VT_REMOTE = 512; // 0x200
+    field public static final int SUPPORT_HOLD = 2; // 0x2
+    field public static final int SWAP_CALLS = 8; // 0x8
+    field public static final int VoLTE = 1024; // 0x400
+    field public static final int VoWIFI = 2048; // 0x800
+  }
+
+  public class PropertyPresentation {
+    ctor public PropertyPresentation();
+    field public static final int ALLOWED = 1; // 0x1
+    field public static final int PAYPHONE = 4; // 0x4
+    field public static final int RESTRICTED = 2; // 0x2
+    field public static final int UNKNOWN = 3; // 0x3
+  }
+
   public final class RemoteConnection {
     method public void abort();
     method public void addListener(android.telecomm.RemoteConnection.Listener);
@@ -29209,9 +29064,8 @@
     method public void postDialContinue(boolean);
     method public void reject();
     method public void removeListener(android.telecomm.RemoteConnection.Listener);
-    method public void setAudioState(android.telecomm.CallAudioState);
+    method public void setAudioState(android.telecomm.AudioState);
     method public void stopDtmfTone();
-    method public void swapWithBackgroundCall();
     method public void unhold();
   }
 
@@ -29239,18 +29093,13 @@
     method public abstract void onResult(IN, OUT...);
   }
 
-  public abstract interface SimpleResponse {
-    method public abstract void onError(IN);
-    method public abstract void onResult(IN, OUT);
-  }
-
   public final class StatusHints implements android.os.Parcelable {
     ctor public StatusHints(android.content.ComponentName, java.lang.CharSequence, int, android.os.Bundle);
     method public int describeContents();
     method public android.content.ComponentName getComponentName();
     method public android.os.Bundle getExtras();
     method public android.graphics.drawable.Drawable getIcon(android.content.Context);
-    method public int getIconId();
+    method public int getIconResId();
     method public java.lang.CharSequence getLabel();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
@@ -29278,23 +29127,9 @@
     field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.intent.extra.START_CALL_WITH_VIDEO_STATE";
   }
 
-  public class VideoCallImpl extends android.telecomm.InCallService.VideoCall {
-    method public void requestCallDataUsage();
-    method public void requestCameraCapabilities();
-    method public void sendSessionModifyRequest(android.telecomm.VideoCallProfile);
-    method public void sendSessionModifyResponse(android.telecomm.VideoCallProfile);
-    method public void setCamera(java.lang.String);
-    method public void setDeviceOrientation(int);
-    method public void setDisplaySurface(android.view.Surface);
-    method public void setPauseImage(java.lang.String);
-    method public void setPreviewSurface(android.view.Surface);
-    method public void setVideoCallListener(android.telecomm.InCallService.VideoCall.Listener);
-    method public void setZoom(float);
-  }
-
-  public class VideoCallProfile implements android.os.Parcelable {
-    ctor public VideoCallProfile(int);
-    ctor public VideoCallProfile(int, int);
+  public class VideoProfile implements android.os.Parcelable {
+    ctor public VideoProfile(int);
+    ctor public VideoProfile(int, int);
     method public int describeContents();
     method public int getQuality();
     method public int getVideoState();
@@ -29306,8 +29141,8 @@
     field public static final int QUALITY_MEDIUM = 2; // 0x2
   }
 
-  public static class VideoCallProfile.VideoState {
-    ctor public VideoCallProfile.VideoState();
+  public static class VideoProfile.VideoState {
+    ctor public VideoProfile.VideoState();
     method public static boolean isAudioOnly(int);
     method public static boolean isBidirectional(int);
     method public static boolean isPaused(int);
@@ -30813,6 +30648,7 @@
   public static class InputFilter.LengthFilter implements android.text.InputFilter {
     ctor public InputFilter.LengthFilter(int);
     method public java.lang.CharSequence filter(java.lang.CharSequence, int, int, android.text.Spanned, int, int);
+    method public int getMax();
   }
 
   public abstract interface InputType {
@@ -32621,6 +32457,7 @@
     method public void setTo(android.util.DisplayMetrics);
     method public void setToDefaults();
     field public static final int DENSITY_400 = 400; // 0x190
+    field public static final int DENSITY_560 = 560; // 0x230
     field public static final int DENSITY_DEFAULT = 160; // 0xa0
     field public static final int DENSITY_HIGH = 240; // 0xf0
     field public static final int DENSITY_LOW = 120; // 0x78
@@ -36046,6 +35883,7 @@
     method public android.view.accessibility.AccessibilityNodeInfo getLabelFor();
     method public android.view.accessibility.AccessibilityNodeInfo getLabeledBy();
     method public int getLiveRegion();
+    method public int getMaxTextLength();
     method public int getMovementGranularities();
     method public java.lang.CharSequence getPackageName();
     method public android.view.accessibility.AccessibilityNodeInfo getParent();
@@ -36109,6 +35947,7 @@
     method public void setLabeledBy(android.view.View, int);
     method public void setLiveRegion(int);
     method public void setLongClickable(boolean);
+    method public void setMaxTextLength(int);
     method public void setMovementGranularities(int);
     method public void setMultiLine(boolean);
     method public void setPackageName(java.lang.CharSequence);
diff --git a/cmds/media/src/com/android/commands/media/Media.java b/cmds/media/src/com/android/commands/media/Media.java
index d9faf4c..b13b009 100644
--- a/cmds/media/src/com/android/commands/media/Media.java
+++ b/cmds/media/src/com/android/commands/media/Media.java
@@ -178,6 +178,13 @@
         public ControllerMonitor(ISessionController controller) {
             mController = controller;
         }
+
+        @Override
+        public void onSessionDestroyed() {
+            System.out.println("onSessionDestroyed. Enter q to quit.");
+
+        }
+
         @Override
         public void onEvent(String event, Bundle extras) {
             System.out.println("onSessionEvent event=" + event + ", extras=" + extras);
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index c5e91e3..15152e5 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -1703,6 +1703,10 @@
             throw new IllegalArgumentException("Missing ABI argument");
         }
 
+        if ("-".equals(abi)) {
+            return abi;
+        }
+
         final String[] supportedAbis = Build.SUPPORTED_ABIS;
         for (String supportedAbi : supportedAbis) {
             if (supportedAbi.equals(abi)) {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index fcfeddd..21c8b75 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -31,6 +31,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentCallbacks2;
 import android.content.ComponentName;
@@ -747,8 +748,8 @@
         }
     };
 
-    // Most recent call to setMediaPlaying().
-    boolean mMediaPlaying;
+    // Most recent call to requestVisibleBehind().
+    boolean mVisibleBehind;
 
     ArrayMap<String, LoaderManagerImpl> mAllLoaderManagers;
     LoaderManagerImpl mLoaderManager;
@@ -5314,6 +5315,7 @@
      *
      * @hide
      */
+    @SystemApi
     public void convertFromTranslucent() {
         try {
             mTranslucentCallback = null;
@@ -5350,6 +5352,7 @@
      *
      * @hide
      */
+    @SystemApi
     public boolean convertToTranslucent(TranslucentConversionListener callback,
             ActivityOptions options) {
         boolean drawComplete;
@@ -5406,12 +5409,13 @@
     }
 
     /**
-     * Activities that want to show media behind a translucent activity above them must call this
-     * method anytime before a return from {@link #onPause()}. If this call is successful
-     * then the activity should continue to play media when {@link #onPause()} is called, but must
-     * stop playing and release resources prior to or within the call to
-     * {@link #onStopMediaPlaying()}. If this call returns false the activity must stop
-     * playing and release resources immediately.
+     * Activities that want to remain visible behind a translucent activity above them must call
+     * this method anytime before a return from {@link #onPause()}. If this call is successful
+     * then the activity will remain visible when {@link #onPause()} is called, and can continue to
+     * play media in the background, but it must stop playing and release resources prior to or
+     * within the call to {@link #onVisibleBehindCancelled()}. If this call returns false, the 
+     * activity will not be visible in the background, and must release any media resources 
+     * immediately.
      *
      * <p>Only fullscreen opaque activities may make this call. I.e. this call is a nop
      * for dialog and translucent activities.
@@ -5419,85 +5423,86 @@
      * <p>False will be returned any time this method is call between the return of onPause and
      *      the next call to onResume.
      *
-     * @param playing true to notify the system that media is starting or continuing playing,
-     *                false to indicate that media has stopped or is stopping. Resources must
-     *                be released when passing false to this method.
-     * @return the resulting play state. If true the activity may continue playing media beyond
-     *      {@link #onPause()}, if false then the caller must stop playing and immediately
-     *      release all media resources. Returning false may occur in lieu of a call to
-     *      onReleaseMediaResources() so the return value must be checked.
+     * @param visible true to notify the system that the activity wishes to be visible behind other
+     *                translucent activities, false to indicate otherwise. Resources must be
+     *                released when passing false to this method.
+     * @return the resulting visibiity state. If true the activity may remain visible beyond
+     *      {@link #onPause()}. If false then the activity may not count on being visible behind
+     *      other translucent activities, and must stop any media playback and release resources.
+     *      Returning false may occur in lieu of a call to onVisibleBehindCancelled() so the return
+     *      value must be checked.
      *
-     * @see #isBackgroundMediaPlaying()
-     * @see #onStopMediaPlaying()
-     * @see #onBackgroundMediaPlayingChanged(boolean)
+     * @see #onVisibleBehindCancelled()
+     * @see #onBackgroundVisibleBehindChanged(boolean)
      */
-    public boolean setMediaPlaying(boolean playing) {
+    public boolean requestVisibleBehind(boolean visible) {
         if (!mResumed) {
-            // Do not permit paused or stopped activities to start playing.
-            playing = false;
+            // Do not permit paused or stopped activities to do this.
+            visible = false;
         }
         try {
-            mMediaPlaying = ActivityManagerNative.getDefault().setMediaPlaying(mToken, playing) &&
-                    playing;
+            mVisibleBehind = ActivityManagerNative.getDefault()
+                    .requestVisibleBehind(mToken, visible) && visible;
         } catch (RemoteException e) {
-            mMediaPlaying = false;
+            mVisibleBehind = false;
         }
-        return mMediaPlaying;
+        return mVisibleBehind;
     }
 
     /**
-     * Called when a translucent activity over playing media is becoming opaque or another
-     * activity is being launched. Activities that call {@link #setMediaPlaying(boolean)}
-     * must implement this method to at the minimum call
-     * <code>super.onStopMediaPlayback()</code>.
+     * Called when a translucent activity over this activity is becoming opaque or another
+     * activity is being launched. Activities that override this method must call
+     * <code>super.onVisibleBehindCancelled()</code> or a SuperNotCalledException will be thrown.
      *
-     * <p>When this method is called the activity has 500 msec to release the media resources.
+     * <p>When this method is called the activity has 500 msec to release any resources it may be
+     * using while visible in the background.
      * If the activity has not returned from this method in 500 msec the system will destroy
-     * the activity and kill the process in order to recover the media resources for another
+     * the activity and kill the process in order to recover the resources for another
      * process. Otherwise {@link #onStop()} will be called following return.
      *
-     * @see #setMediaPlaying(boolean)
-     * @see #isBackgroundMediaPlaying()
-     * @see #onBackgroundMediaPlayingChanged(boolean)
+     * @see #requestVisibleBehind(boolean)
+     * @see #onBackgroundVisibleBehindChanged(boolean)
      */
-    public void onStopMediaPlaying() {
+    public void onVisibleBehindCancelled() {
         mCalled = true;
     }
 
     /**
-     * Translucent activities may call this to determine if there is an activity below it that
-     * is playing media.
+     * Translucent activities may call this to determine if there is an activity below them that
+     * is currently set to be visible in the background.
      *
-     * @return true if media is playing according to the most recent call to
-     * {@link #setMediaPlaying(boolean)}, false otherwise.
+     * @return true if an activity below is set to visible according to the most recent call to
+     * {@link #requestVisibleBehind(boolean)}, false otherwise.
      *
-     * @see #setMediaPlaying(boolean)
-     * @see #onStopMediaPlaying()
-     * @see #onBackgroundMediaPlayingChanged(boolean)
+     * @see #requestVisibleBehind(boolean)
+     * @see #onVisibleBehindCancelled()
+     * @see #onBackgroundVisibleBehindChanged(boolean)
      * @hide
      */
-    public boolean isBackgroundMediaPlaying() {
+    @SystemApi
+    public boolean isBackgroundVisibleBehind() {
         try {
-            return ActivityManagerNative.getDefault().isBackgroundMediaPlaying(mToken);
+            return ActivityManagerNative.getDefault().isBackgroundVisibleBehind(mToken);
         } catch (RemoteException e) {
         }
         return false;
     }
 
     /**
-     * The topmost foreground activity will receive this call when an activity below it either
-     * starts or stops playing media.
+     * The topmost foreground activity will receive this call when the background visibility state
+     * of the activity below it changes.
      *
-     * This call may be a consequence of {@link #setMediaPlaying(boolean)} or might be
+     * This call may be a consequence of {@link #requestVisibleBehind(boolean)} or might be
      * due to a background activity finishing itself.
      *
-     * @param playing true if media playback is starting, false if it is stopping.
+     * @param visible true if a background activity is visible, false otherwise.
      *
-     * @see #setMediaPlaying(boolean)
-     * @see #isBackgroundMediaPlaying()
-     * @see #onStopMediaPlaying()
+     * @see #requestVisibleBehind(boolean)
+     * @see #onVisibleBehindCancelled()
+     * @hide
      */
-    public void onBackgroundMediaPlayingChanged(boolean playing) {
+    @SystemApi
+    public void onBackgroundVisibleBehindChanged(boolean visible) {
     }
 
     /**
@@ -6114,6 +6119,7 @@
      *
      * @hide
      */
+    @SystemApi
     public interface TranslucentConversionListener {
         /**
          * Callback made following {@link Activity#convertToTranslucent} once all visible Activities
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 311a8f55..31cb4d6 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1942,9 +1942,9 @@
             return true;
         }
 
-        case DISMISS_KEYGUARD_ON_NEXT_ACTIVITY_TRANSACTION: {
+        case KEYGUARD_WAITING_FOR_ACTIVITY_DRAWN_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
-            dismissKeyguardOnNextActivity();
+            keyguardWaitingForActivityDrawn();
             reply.writeNoException();
             return true;
         }
@@ -2197,29 +2197,29 @@
             return true;
         }
 
-        case SET_MEDIA_PLAYING_TRANSACTION: {
+        case REQUEST_VISIBLE_BEHIND_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder token = data.readStrongBinder();
             boolean enable = data.readInt() > 0;
-            boolean success = setMediaPlaying(token, enable);
+            boolean success = requestVisibleBehind(token, enable);
             reply.writeNoException();
             reply.writeInt(success ? 1 : 0);
             return true;
         }
 
-        case IS_BG_MEDIA_PLAYING_TRANSACTION: {
+        case IS_BACKGROUND_VISIBLE_BEHIND_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder token = data.readStrongBinder();
-            final boolean enabled = isBackgroundMediaPlaying(token);
+            final boolean enabled = isBackgroundVisibleBehind(token);
             reply.writeNoException();
             reply.writeInt(enabled ? 1 : 0);
             return true;
         }
 
-        case MEDIA_RESOURCES_RELEASED_TRANSACTION: {
+        case BACKGROUND_RESOURCES_RELEASED_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder token = data.readStrongBinder();
-            mediaResourcesReleased(token);
+            backgroundResourcesReleased(token);
             reply.writeNoException();
             return true;
         }
@@ -4738,11 +4738,11 @@
         reply.recycle();
     }
 
-    public void dismissKeyguardOnNextActivity() throws RemoteException {
+    public void keyguardWaitingForActivityDrawn() throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(DISMISS_KEYGUARD_ON_NEXT_ACTIVITY_TRANSACTION, data, reply, 0);
+        mRemote.transact(KEYGUARD_WAITING_FOR_ACTIVITY_DRAWN_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
         reply.recycle();
@@ -5101,13 +5101,13 @@
     }
 
     @Override
-    public boolean setMediaPlaying(IBinder token, boolean playing) throws RemoteException {
+    public boolean requestVisibleBehind(IBinder token, boolean visible) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(token);
-        data.writeInt(playing ? 1 : 0);
-        mRemote.transact(SET_MEDIA_PLAYING_TRANSACTION, data, reply, 0);
+        data.writeInt(visible ? 1 : 0);
+        mRemote.transact(REQUEST_VISIBLE_BEHIND_TRANSACTION, data, reply, 0);
         reply.readException();
         boolean success = reply.readInt() > 0;
         data.recycle();
@@ -5116,26 +5116,27 @@
     }
 
     @Override
-    public boolean isBackgroundMediaPlaying(IBinder token) throws RemoteException {
+    public boolean isBackgroundVisibleBehind(IBinder token) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(token);
-        mRemote.transact(IS_BG_MEDIA_PLAYING_TRANSACTION, data, reply, 0);
+        mRemote.transact(IS_BACKGROUND_VISIBLE_BEHIND_TRANSACTION, data, reply, 0);
         reply.readException();
-        final boolean playing = reply.readInt() > 0;
+        final boolean visible = reply.readInt() > 0;
         data.recycle();
         reply.recycle();
-        return playing;
+        return visible;
     }
 
     @Override
-    public void mediaResourcesReleased(IBinder token) throws RemoteException {
+    public void backgroundResourcesReleased(IBinder token) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(token);
-        mRemote.transact(MEDIA_RESOURCES_RELEASED_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
+        mRemote.transact(BACKGROUND_RESOURCES_RELEASED_TRANSACTION, data, reply,
+                IBinder.FLAG_ONEWAY);
         reply.readException();
         data.recycle();
         reply.recycle();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3a764fa..1b82d8e 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1155,13 +1155,13 @@
         }
 
         @Override
-        public void scheduleStopMediaPlaying(IBinder token) {
-            sendMessage(H.STOP_MEDIA_PLAYING, token);
+        public void scheduleCancelVisibleBehind(IBinder token) {
+            sendMessage(H.CANCEL_VISIBLE_BEHIND, token);
         }
 
         @Override
-        public void scheduleBackgroundMediaPlayingChanged(IBinder token, boolean playing) {
-            sendMessage(H.BACKGROUND_MEDIA_PLAYING_CHANGED, token, playing ? 1 : 0);
+        public void scheduleBackgroundVisibleBehindChanged(IBinder token, boolean visible) {
+            sendMessage(H.BACKGROUND_VISIBLE_BEHIND_CHANGED, token, visible ? 1 : 0);
         }
 
         public void scheduleEnterAnimationComplete(IBinder token) {
@@ -1217,8 +1217,8 @@
         public static final int TRANSLUCENT_CONVERSION_COMPLETE = 144;
         public static final int INSTALL_PROVIDER        = 145;
         public static final int ON_NEW_ACTIVITY_OPTIONS = 146;
-        public static final int STOP_MEDIA_PLAYING = 147;
-        public static final int BACKGROUND_MEDIA_PLAYING_CHANGED = 148;
+        public static final int CANCEL_VISIBLE_BEHIND = 147;
+        public static final int BACKGROUND_VISIBLE_BEHIND_CHANGED = 148;
         public static final int ENTER_ANIMATION_COMPLETE = 149;
 
         String codeToString(int code) {
@@ -1270,8 +1270,8 @@
                     case TRANSLUCENT_CONVERSION_COMPLETE: return "TRANSLUCENT_CONVERSION_COMPLETE";
                     case INSTALL_PROVIDER: return "INSTALL_PROVIDER";
                     case ON_NEW_ACTIVITY_OPTIONS: return "ON_NEW_ACTIVITY_OPTIONS";
-                    case STOP_MEDIA_PLAYING: return "STOP_MEDIA_PLAYING";
-                    case BACKGROUND_MEDIA_PLAYING_CHANGED: return "BACKGROUND_MEDIA_PLAYING_CHANGED";
+                    case CANCEL_VISIBLE_BEHIND: return "CANCEL_VISIBLE_BEHIND";
+                    case BACKGROUND_VISIBLE_BEHIND_CHANGED: return "BACKGROUND_VISIBLE_BEHIND_CHANGED";
                     case ENTER_ANIMATION_COMPLETE: return "ENTER_ANIMATION_COMPLETE";
                 }
             }
@@ -1491,11 +1491,11 @@
                     Pair<IBinder, ActivityOptions> pair = (Pair<IBinder, ActivityOptions>) msg.obj;
                     onNewActivityOptions(pair.first, pair.second);
                     break;
-                case STOP_MEDIA_PLAYING:
-                    handleStopMediaPlaying((IBinder) msg.obj);
+                case CANCEL_VISIBLE_BEHIND:
+                    handleCancelVisibleBehind((IBinder) msg.obj);
                     break;
-                case BACKGROUND_MEDIA_PLAYING_CHANGED:
-                    handleOnBackgroundMediaPlayingChanged((IBinder) msg.obj, msg.arg1 > 0);
+                case BACKGROUND_VISIBLE_BEHIND_CHANGED:
+                    handleOnBackgroundVisibleBehindChanged((IBinder) msg.obj, msg.arg1 > 0);
                     break;
                 case ENTER_ANIMATION_COMPLETE:
                     handleEnterAnimationComplete((IBinder) msg.obj);
@@ -2488,31 +2488,31 @@
         }
     }
 
-    public void handleStopMediaPlaying(IBinder token) {
+    public void handleCancelVisibleBehind(IBinder token) {
         ActivityClientRecord r = mActivities.get(token);
         if (r != null) {
             final Activity activity = r.activity;
-            if (activity.mMediaPlaying) {
+            if (activity.mVisibleBehind) {
                 activity.mCalled = false;
-                activity.onStopMediaPlaying();
+                activity.onVisibleBehindCancelled();
                 // Tick, tick, tick. The activity has 500 msec to return or it will be destroyed.
                 if (!activity.mCalled) {
                     throw new SuperNotCalledException("Activity " + activity.getLocalClassName() +
-                            " did not call through to super.onStopMediaPlayback()");
+                            " did not call through to super.onVisibleBehindCancelled()");
                 }
-                activity.mMediaPlaying = false;
+                activity.mVisibleBehind = false;
             }
         }
         try {
-            ActivityManagerNative.getDefault().mediaResourcesReleased(token);
+            ActivityManagerNative.getDefault().backgroundResourcesReleased(token);
         } catch (RemoteException e) {
         }
     }
 
-    public void handleOnBackgroundMediaPlayingChanged(IBinder token, boolean playing) {
+    public void handleOnBackgroundVisibleBehindChanged(IBinder token, boolean visible) {
         ActivityClientRecord r = mActivities.get(token);
         if (r != null) {
-            r.activity.onBackgroundMediaPlayingChanged(playing);
+            r.activity.onBackgroundVisibleBehindChanged(visible);
         }
     }
 
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index f7c0d23..7d2f677 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -239,7 +239,7 @@
         return mWindow;
     }
 
-    protected ViewGroup getDecor() {
+    public ViewGroup getDecor() {
         return (mWindow == null) ? null : (ViewGroup) mWindow.getDecorView();
     }
 
diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java
index 4f3b02c..613e248 100644
--- a/core/java/android/app/ActivityTransitionState.java
+++ b/core/java/android/app/ActivityTransitionState.java
@@ -17,9 +17,11 @@
 
 import android.os.Bundle;
 import android.os.ResultReceiver;
+import android.transition.Transition;
 import android.util.ArrayMap;
 import android.util.SparseArray;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.Window;
 
 import java.lang.ref.WeakReference;
@@ -245,13 +247,23 @@
         } else {
             if (!mHasExited) {
                 mHasExited = true;
+                Transition enterViewsTransition = null;
+                ViewGroup decor = null;
                 if (mEnterTransitionCoordinator != null) {
+                    enterViewsTransition = mEnterTransitionCoordinator.getEnterViewsTransition();
+                    decor = mEnterTransitionCoordinator.getDecor();
                     mEnterTransitionCoordinator.cancelEnter();
                     mEnterTransitionCoordinator = null;
+                    if (enterViewsTransition != null && decor != null) {
+                        enterViewsTransition.pause(decor);
+                    }
                 }
 
                 ExitTransitionCoordinator exitCoordinator =
                         new ExitTransitionCoordinator(activity, mEnteringNames, null, null, true);
+                if (enterViewsTransition != null && decor != null) {
+                    enterViewsTransition.resume(decor);
+                }
                 exitCoordinator.startExit(activity.mResultCode, activity.mResultData);
             }
             return true;
diff --git a/core/java/android/app/AlarmClockInfo.java b/core/java/android/app/AlarmClockInfo.java
deleted file mode 100644
index 0ccaf02..0000000
--- a/core/java/android/app/AlarmClockInfo.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.app;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * An immutable description of an alarm clock.
- *
- * @see AlarmManager#setAlarmClock
- * @see AlarmManager#getNextAlarmClock
- */
-public class AlarmClockInfo implements Parcelable {
-
-    private final long mTriggerTime;
-    private final PendingIntent mShowIntent;
-
-    /**
-     * Creates a new alarm clock description.
-     *
-     * @param triggerTime time at which the underlying alarm is triggered in wall time milliseconds
-     *                    since the epoch
-     * @param showIntent an intent that can be used to show or edit details of
-     *                        the alarm clock.
-     */
-    public AlarmClockInfo(long triggerTime, PendingIntent showIntent) {
-        mTriggerTime = triggerTime;
-        mShowIntent = showIntent;
-    }
-
-    /**
-     * Use the {@link #CREATOR}
-     * @hide
-     */
-    AlarmClockInfo(Parcel in) {
-        mTriggerTime = in.readLong();
-        mShowIntent = in.readParcelable(PendingIntent.class.getClassLoader());
-    }
-
-    /**
-     * Returns the time at which the alarm is going to trigger.
-     *
-     * This value is UTC wall clock time in milliseconds, as returned by
-     * {@link System#currentTimeMillis()} for example.
-     */
-    public long getTriggerTime() {
-        return mTriggerTime;
-    }
-
-    /**
-     * Returns an intent intent that can be used to show or edit details of the alarm clock in
-     * the application that scheduled it.
-     *
-     * <p class="note">Beware that any application can retrieve and send this intent, potentially
-     * with additional fields filled in. See
-     * {@link PendingIntent#send(android.content.Context, int, android.content.Intent)
-     * PendingIntent.send()} and {@link android.content.Intent#fillIn Intent.fillIn()}
-     * for details.
-     */
-    public PendingIntent getShowIntent() {
-        return mShowIntent;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeLong(mTriggerTime);
-        dest.writeParcelable(mShowIntent, flags);
-    }
-
-    public static final Creator<AlarmClockInfo> CREATOR = new Creator<AlarmClockInfo>() {
-        @Override
-        public AlarmClockInfo createFromParcel(Parcel in) {
-            return new AlarmClockInfo(in);
-        }
-
-        @Override
-        public AlarmClockInfo[] newArray(int size) {
-            return new AlarmClockInfo[size];
-        }
-    };
-}
diff --git a/core/java/android/app/AlarmClockInfo.aidl b/core/java/android/app/AlarmManager.aidl
similarity index 93%
rename from core/java/android/app/AlarmClockInfo.aidl
rename to core/java/android/app/AlarmManager.aidl
index 58a3644..c9547b2 100644
--- a/core/java/android/app/AlarmClockInfo.aidl
+++ b/core/java/android/app/AlarmManager.aidl
@@ -16,4 +16,4 @@
 
 package android.app;
 
-parcelable AlarmClockInfo;
+parcelable AlarmManager.AlarmClockInfo;
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index fa2d64c..a64e0ed 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -20,9 +20,12 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.Build;
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.WorkSource;
+import android.os.Parcelable.Creator;
 
 /**
  * This class provides access to the system alarm services.  These allow you
@@ -579,4 +582,85 @@
             return null;
         }
     }
+
+    /**
+     * An immutable description of an alarm clock.
+     *
+     * @see AlarmManager#setAlarmClock
+     * @see AlarmManager#getNextAlarmClock
+     */
+    public static final class AlarmClockInfo implements Parcelable {
+
+        private final long mTriggerTime;
+        private final PendingIntent mShowIntent;
+
+        /**
+         * Creates a new alarm clock description.
+         *
+         * @param triggerTime time at which the underlying alarm is triggered in wall time 
+         *                    milliseconds since the epoch
+         * @param showIntent an intent that can be used to show or edit details of
+         *                        the alarm clock.
+         */
+        public AlarmClockInfo(long triggerTime, PendingIntent showIntent) {
+            mTriggerTime = triggerTime;
+            mShowIntent = showIntent;
+        }
+
+        /**
+         * Use the {@link #CREATOR}
+         * @hide
+         */
+        AlarmClockInfo(Parcel in) {
+            mTriggerTime = in.readLong();
+            mShowIntent = in.readParcelable(PendingIntent.class.getClassLoader());
+        }
+
+        /**
+         * Returns the time at which the alarm is going to trigger.
+         *
+         * This value is UTC wall clock time in milliseconds, as returned by
+         * {@link System#currentTimeMillis()} for example.
+         */
+        public long getTriggerTime() {
+            return mTriggerTime;
+        }
+
+        /**
+         * Returns an intent intent that can be used to show or edit details of the alarm clock in
+         * the application that scheduled it.
+         *
+         * <p class="note">Beware that any application can retrieve and send this intent, 
+         * potentially with additional fields filled in. See
+         * {@link PendingIntent#send(android.content.Context, int, android.content.Intent)
+         * PendingIntent.send()} and {@link android.content.Intent#fillIn Intent.fillIn()}
+         * for details.
+         */
+        public PendingIntent getShowIntent() {
+            return mShowIntent;
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeLong(mTriggerTime);
+            dest.writeParcelable(mShowIntent, flags);
+        }
+
+        public static final Creator<AlarmClockInfo> CREATOR = new Creator<AlarmClockInfo>() {
+            @Override
+            public AlarmClockInfo createFromParcel(Parcel in) {
+                return new AlarmClockInfo(in);
+            }
+
+            @Override
+            public AlarmClockInfo[] newArray(int size) {
+                return new AlarmClockInfo[size];
+            }
+        };
+    }
 }
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index a52186a..a6b3608 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -451,8 +451,8 @@
             null, //VIBRATE
             null, //READ_CONTACTS
             null, //WRITE_CONTACTS
-            null, //READ_CALL_LOG
-            null, //WRITE_CALL_LOG
+            UserManager.DISALLOW_OUTGOING_CALLS, //READ_CALL_LOG
+            UserManager.DISALLOW_OUTGOING_CALLS, //WRITE_CALL_LOG
             null, //READ_CALENDAR
             null, //WRITE_CALENDAR
             UserManager.DISALLOW_SHARE_LOCATION, //WIFI_SCAN
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index e9d4bd9..52b69e1 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -648,21 +648,21 @@
             return true;
         }
 
-        case STOP_MEDIA_PLAYING_TRANSACTION:
+        case CANCEL_VISIBLE_BEHIND_TRANSACTION:
         {
             data.enforceInterface(IApplicationThread.descriptor);
             IBinder token = data.readStrongBinder();
-            scheduleStopMediaPlaying(token);
+            scheduleCancelVisibleBehind(token);
             reply.writeNoException();
             return true;
         }
 
-        case BACKGROUND_MEDIA_PLAYING_CHANGED_TRANSACTION:
+        case BACKGROUND_VISIBLE_BEHIND_CHANGED_TRANSACTION:
         {
             data.enforceInterface(IApplicationThread.descriptor);
             IBinder token = data.readStrongBinder();
             boolean enabled = data.readInt() > 0;
-            scheduleBackgroundMediaPlayingChanged(token, enabled);
+            scheduleBackgroundVisibleBehindChanged(token, enabled);
             reply.writeNoException();
             return true;
         }
@@ -1334,21 +1334,23 @@
     }
 
     @Override
-    public void scheduleStopMediaPlaying(IBinder token) throws RemoteException {
+    public void scheduleCancelVisibleBehind(IBinder token) throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         data.writeStrongBinder(token);
-        mRemote.transact(STOP_MEDIA_PLAYING_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
+        mRemote.transact(CANCEL_VISIBLE_BEHIND_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
         data.recycle();
     }
 
     @Override
-    public void scheduleBackgroundMediaPlayingChanged(IBinder token, boolean enabled) throws RemoteException {
+    public void scheduleBackgroundVisibleBehindChanged(IBinder token, boolean enabled)
+            throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         data.writeStrongBinder(token);
         data.writeInt(enabled ? 1 : 0);
-        mRemote.transact(BACKGROUND_MEDIA_PLAYING_CHANGED_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
+        mRemote.transact(BACKGROUND_VISIBLE_BEHIND_CHANGED_TRANSACTION, data, null,
+                IBinder.FLAG_ONEWAY);
         data.recycle();
     }
 
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index 54c5bc4..75ecbd9 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -59,6 +59,7 @@
     private boolean mIsViewsTransitionComplete;
     private boolean mIsSharedElementTransitionComplete;
     private ArrayList<Matrix> mSharedElementParentMatrices;
+    private Transition mEnterViewsTransition;
 
     public EnterTransitionCoordinator(Activity activity, ResultReceiver resultReceiver,
             ArrayList<String> sharedElementNames, boolean isReturning) {
@@ -104,6 +105,10 @@
         triggerViewsReady(mapNamedElements(accepted, localNames));
     }
 
+    public Transition getEnterViewsTransition() {
+        return mEnterViewsTransition;
+    }
+
     @Override
     protected void viewsReady(ArrayMap<String, View> sharedElements) {
         super.viewsReady(sharedElements);
@@ -399,10 +404,17 @@
                 viewTransitionComplete();
             } else {
                 viewsTransition.forceVisibility(View.INVISIBLE, true);
-                setTransitionAlpha(mTransitioningViews, 1);
                 viewsTransition.addListener(new ContinueTransitionListener() {
                     @Override
+                    public void onTransitionStart(Transition transition) {
+                        mEnterViewsTransition = transition;
+                        setTransitionAlpha(mTransitioningViews, 1);
+                        super.onTransitionStart(transition);
+                    }
+
+                    @Override
                     public void onTransitionEnd(Transition transition) {
+                        mEnterViewsTransition = null;
                         transition.removeListener(this);
                         viewTransitionComplete();
                         super.onTransitionEnd(transition);
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 772e132..2dbc4ea 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -383,7 +383,7 @@
 
     public void showBootMessage(CharSequence msg, boolean always) throws RemoteException;
 
-    public void dismissKeyguardOnNextActivity() throws RemoteException;
+    public void keyguardWaitingForActivityDrawn() throws RemoteException;
 
     public boolean targetTaskAffinityMatchesActivity(IBinder token, String destAffinity)
             throws RemoteException;
@@ -443,9 +443,9 @@
     public void setTaskDescription(IBinder token, ActivityManager.TaskDescription values)
             throws RemoteException;
 
-    public boolean setMediaPlaying(IBinder token, boolean playing) throws RemoteException;
-    public boolean isBackgroundMediaPlaying(IBinder token) throws RemoteException;
-    public void mediaResourcesReleased(IBinder token) throws RemoteException;
+    public boolean requestVisibleBehind(IBinder token, boolean visible) throws RemoteException;
+    public boolean isBackgroundVisibleBehind(IBinder token) throws RemoteException;
+    public void backgroundResourcesReleased(IBinder token) throws RemoteException;
 
     public void notifyLaunchTaskBehindComplete(IBinder token) throws RemoteException;
     public void notifyEnterAnimationComplete(IBinder token) throws RemoteException;
@@ -688,7 +688,6 @@
     int UPDATE_PERSISTENT_CONFIGURATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+135;
     int GET_PROCESS_PSS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+136;
     int SHOW_BOOT_MESSAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+137;
-    int DISMISS_KEYGUARD_ON_NEXT_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+138;
     int KILL_ALL_BACKGROUND_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+139;
     int GET_CONTENT_PROVIDER_EXTERNAL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+140;
     int REMOVE_CONTENT_PROVIDER_EXTERNAL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+141;
@@ -754,10 +753,11 @@
     int STOP_LOCK_TASK_BY_CURRENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+222;
     int FINISH_VOICE_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+223;
     int IS_TOP_OF_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+224;
-    int SET_MEDIA_PLAYING_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+225;
-    int IS_BG_MEDIA_PLAYING_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+226;
-    int MEDIA_RESOURCES_RELEASED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+227;
+    int REQUEST_VISIBLE_BEHIND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+225;
+    int IS_BACKGROUND_VISIBLE_BEHIND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+226;
+    int BACKGROUND_RESOURCES_RELEASED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+227;
     int NOTIFY_LAUNCH_TASK_BEHIND_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+228;
     int START_ACTIVITY_FROM_RECENTS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 229;
     int NOTIFY_ENTER_ANIMATION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+230;
+    int KEYGUARD_WAITING_FOR_ACTIVITY_DRAWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+231;
 }
diff --git a/core/java/android/app/IAlarmManager.aidl b/core/java/android/app/IAlarmManager.aidl
index fb33706..194082e 100644
--- a/core/java/android/app/IAlarmManager.aidl
+++ b/core/java/android/app/IAlarmManager.aidl
@@ -16,7 +16,7 @@
 */
 package android.app;
 
-import android.app.AlarmClockInfo;
+import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.os.WorkSource;
 
@@ -29,11 +29,11 @@
 	/** windowLength == 0 means exact; windowLength < 0 means the let the OS decide */
     void set(int type, long triggerAtTime, long windowLength,
             long interval, in PendingIntent operation, in WorkSource workSource,
-            in AlarmClockInfo alarmClock);
+            in AlarmManager.AlarmClockInfo alarmClock);
     boolean setTime(long millis);
     void setTimeZone(String zone);
     void remove(in PendingIntent operation);
-    AlarmClockInfo getNextAlarmClock(int userId);
+    AlarmManager.AlarmClockInfo getNextAlarmClock(int userId);
 }
 
 
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 4a1fda4..01b6fdf 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -145,8 +145,8 @@
     void setProcessState(int state) throws RemoteException;
     void scheduleInstallProvider(ProviderInfo provider) throws RemoteException;
     void updateTimePrefs(boolean is24Hour) throws RemoteException;
-    void scheduleStopMediaPlaying(IBinder token) throws RemoteException;
-    void scheduleBackgroundMediaPlayingChanged(IBinder token, boolean enabled) throws RemoteException;
+    void scheduleCancelVisibleBehind(IBinder token) throws RemoteException;
+    void scheduleBackgroundVisibleBehindChanged(IBinder token, boolean enabled) throws RemoteException;
     void scheduleEnterAnimationComplete(IBinder token) throws RemoteException;
 
     String descriptor = "android.app.IApplicationThread";
@@ -202,7 +202,7 @@
     int SET_PROCESS_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+49;
     int SCHEDULE_INSTALL_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+50;
     int UPDATE_TIME_PREFS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+51;
-    int STOP_MEDIA_PLAYING_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+52;
-    int BACKGROUND_MEDIA_PLAYING_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+53;
+    int CANCEL_VISIBLE_BEHIND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+52;
+    int BACKGROUND_VISIBLE_BEHIND_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+53;
     int ENTER_ANIMATION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+54;
 }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 90b8b86..5f58839 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -279,6 +279,7 @@
      *
      * @deprecated Use {@link #audioAttributes} instead.
      */
+    @Deprecated
     public static final int STREAM_DEFAULT = -1;
 
     /**
@@ -288,6 +289,7 @@
      *
      * @deprecated Use {@link #audioAttributes} instead.
      */
+    @Deprecated
     public int audioStreamType = STREAM_DEFAULT;
 
     /**
@@ -2193,6 +2195,7 @@
          * @deprecated use {@link #setSound(Uri, AudioAttributes)} instead.
          * @see Notification#sound
          */
+        @Deprecated
         public Builder setSound(Uri sound, int streamType) {
             mSound = sound;
             mAudioStreamType = streamType;
@@ -2574,9 +2577,21 @@
         }
 
         private RemoteViews applyStandardTemplate(int resId, boolean fitIn1U) {
+            final boolean largeFontScale
+                    = mContext.getResources().getConfiguration().fontScale >= 1.25f;
+
             Bitmap profileIcon = getProfileBadge();
             RemoteViews contentView = new BuilderRemoteViews(mContext.getPackageName(),
                     mOriginatingUserId, resId);
+
+            if (largeFontScale) {
+                // Make a little extra room for the bigger text.
+                final int margin = (int) mContext.getResources()
+                        .getDimensionPixelSize(R.dimen.notification_large_font_vert_pad);
+                contentView.setViewPadding(R.id.line1, 0, margin, 0, 0);
+                contentView.setViewPadding(R.id.line3, 0, 0, 0, margin);
+            }
+
             boolean showLine3 = false;
             boolean showLine2 = false;
 
@@ -3218,7 +3233,7 @@
         }
 
         private int getBigTextLayoutResource() {
-            return R.layout.notification_template_material_big_text;
+            return getBigBaseLayoutResource();
         }
 
         private int getInboxLayoutResource() {
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
index f79eb04..0a255f7 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -125,15 +125,15 @@
     public static final int ENABLE_CAR_MODE_GO_CAR_HOME = 0x0001;
 
     /**
-     * Flag for use with {@link #enableCarMode(int)}: do not hold full wake lock
-     * while in car mode. By default, when this flag is not set, the system may hold
-     * a full wake lock to keep the screen turned on while in car mode.
-     * Setting this flag disables such behavior and the screen may be turned off if
-     * there is no other user activity and no other full wake lock held.
+     * Flag for use with {@link #enableCarMode(int)}: allow sleep mode while in car mode.
+     * By default, when this flag is not set, the system may hold a full wake lock to keep the
+     * screen turned on and prevent the system from entering sleep mode while in car mode.
+     * Setting this flag disables such behavior and the system may enter sleep mode
+     * if there is no other user activity and no other wake lock held.
      * Setting this flag can be relevant for a car dock application that does not require the
      * screen kept on.
      */
-    public static final int ENABLE_CAR_MODE_NO_WAKE_LOCK = 0x0002;
+    public static final int ENABLE_CAR_MODE_ALLOW_SLEEP = 0x0002;
 
     /**
      * Force device into car mode, like it had been placed in the car dock.
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 42b8dbf..f0b609a 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1428,6 +1428,9 @@
                 if (VDBG) Log.d(TAG, "onBluetoothServiceDown: " + mService);
                 synchronized (mManagerCallback) {
                     mService = null;
+                    mLeScanClients.clear();
+                    if (sBluetoothLeAdvertiser != null) sBluetoothLeAdvertiser.cleanup();
+                    if (sBluetoothLeScanner != null) sBluetoothLeScanner.cleanup();
                     for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){
                         try {
                             if (cb != null) {
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index 5a39dd6..c8df60e 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -519,6 +519,7 @@
      * @param characteristic The local characteristic that has been updated
      * @param confirm true to request confirmation from the client (indication),
      *                false to send a notification
+     * @throws IllegalArgumentException
      * @return true, if the notification has been triggered successfully
      */
     public boolean notifyCharacteristicChanged(BluetoothDevice device,
@@ -529,6 +530,11 @@
         BluetoothGattService service = characteristic.getService();
         if (service == null) return false;
 
+        if (characteristic.getValue() == null) {
+            throw new IllegalArgumentException("Chracteristic value is empty. Use "
+                    + "BluetoothGattCharacteristic#setvalue to update");
+        }
+
         try {
             mService.sendNotification(mServerIf, device.getAddress(),
                     service.getType(), service.getInstanceId(),
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index 331ebfc..f6315ac 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -175,6 +175,15 @@
         }
     }
 
+    /**
+     * Cleans up advertise clients. Should be called when bluetooth is down.
+     *
+     * @hide
+     */
+    public void cleanup() {
+        mLeAdvertisers.clear();
+    }
+
     // Compute the size of the advertise data.
     private int totalBytes(AdvertiseData data) {
         if (data == null) {
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index 7c3cbc6..988cea5 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -209,6 +209,15 @@
     }
 
     /**
+     * Cleans up scan clients. Should be called when bluetooth is down.
+     *
+     * @hide
+     */
+    public void cleanup() {
+        mLeScanClients.clear();
+    }
+
+    /**
      * Bluetooth GATT interface callbacks
      */
     private static class BleScanCallbackWrapper extends BluetoothGattCallbackWrapper {
diff --git a/core/java/android/bluetooth/le/ScanRecord.java b/core/java/android/bluetooth/le/ScanRecord.java
index e7f33ff1..2f3d06f 100644
--- a/core/java/android/bluetooth/le/ScanRecord.java
+++ b/core/java/android/bluetooth/le/ScanRecord.java
@@ -257,9 +257,11 @@
             }
             return new ScanRecord(serviceUuids, manufacturerData, serviceData,
                     advertiseFlag, txPowerLevel, localName, scanRecord);
-        } catch (IndexOutOfBoundsException e) {
+        } catch (Exception e) {
             Log.e(TAG, "unable to parse scan record: " + Arrays.toString(scanRecord));
-            return null;
+            // As the record is invalid, ignore all the parsed results for this packet
+            // and return an empty record with raw scanRecord bytes in results
+            return new ScanRecord(null, null, null, -1, Integer.MIN_VALUE, null, scanRecord);
         }
     }
 
diff --git a/core/java/android/bluetooth/le/Utils.java b/core/java/android/bluetooth/le/Utils.java
index 8598dd7..ccdae69 100644
--- a/core/java/android/bluetooth/le/Utils.java
+++ b/core/java/android/bluetooth/le/Utils.java
@@ -44,7 +44,7 @@
         StringBuilder buffer = new StringBuilder();
         buffer.append('{');
         for (int i = 0; i < array.size(); ++i) {
-            buffer.append(array.keyAt(i)).append("=").append(array.valueAt(i));
+            buffer.append(array.keyAt(i)).append("=").append(Arrays.toString(array.valueAt(i)));
         }
         buffer.append('}');
         return buffer.toString();
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 974ff13..abe4f0a 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3874,15 +3874,15 @@
     /**
      * By default a document created by {@link #FLAG_ACTIVITY_NEW_DOCUMENT} will
      * have its entry in recent tasks removed when the user closes it (with back
-     * or however else it may finish()).  If you would like to instead allow the
+     * or however else it may finish()). If you would like to instead allow the
      * document to be kept in recents so that it can be re-launched, you can use
-     * this flag.  When set and the task's activity is finished, the recents entry
-     * will remain in the interface for the user to re-launch it, like a recents
-     * entry for a top-level application.
-     *
-     * <p>The receiving activity can override this request with
-     * {@link android.R.styleable#AndroidManifestActivity_autoRemoveFromRecents}
-     * or by explcitly calling {@link android.app.Activity#finishAndRemoveTask()
+     * this flag. When set and the task's activity is finished, the recents
+     * entry will remain in the interface for the user to re-launch it, like a
+     * recents entry for a top-level application.
+     * <p>
+     * The receiving activity can override this request with
+     * {@link android.R.attr#autoRemoveFromRecents} or by explcitly calling
+     * {@link android.app.Activity#finishAndRemoveTask()
      * Activity.finishAndRemoveTask()}.
      */
     public static final int FLAG_ACTIVITY_RETAIN_IN_RECENTS = 0x00002000;
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index cd4a7a0..e3c5449 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -1184,13 +1184,9 @@
      * {@link #MATCH_CATEGORY_MASK} and {@link #MATCH_ADJUSTMENT_MASK}),
      * or one of the error codes {@link #NO_MATCH_TYPE} if the type didn't match,
      * {@link #NO_MATCH_DATA} if the scheme/path didn't match,
-     * {@link #NO_MATCH_ACTION if the action didn't match, or
+     * {@link #NO_MATCH_ACTION} if the action didn't match, or
      * {@link #NO_MATCH_CATEGORY} if one or more categories didn't match.
      *
-     * @return How well the filter matches.  Negative if it doesn't match,
-     *         zero or positive positive value if it does with a higher
-     *         value representing a better match.
-     *
      * @see #match(String, String, String, android.net.Uri , Set, String)
      */
     public final int match(ContentResolver resolver, Intent intent,
@@ -1218,7 +1214,7 @@
      * {@link #MATCH_CATEGORY_MASK} and {@link #MATCH_ADJUSTMENT_MASK}),
      * or one of the error codes {@link #NO_MATCH_TYPE} if the type didn't match,
      * {@link #NO_MATCH_DATA} if the scheme/path didn't match,
-     * {@link #NO_MATCH_ACTION if the action didn't match, or
+     * {@link #NO_MATCH_ACTION} if the action didn't match, or
      * {@link #NO_MATCH_CATEGORY} if one or more categories didn't match.
      *
      * @see #matchData
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index db87cf7..44bf35d 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -4256,6 +4256,16 @@
         public ArraySet<String> mUpgradeKeySets;
         public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping;
 
+        /**
+         * The install time abi override for this package, if any.
+         *
+         * TODO: This seems like a horrible place to put the abiOverride because
+         * this isn't something the packageParser parsers. However, this fits in with
+         * the rest of the PackageManager where package scanning randomly pushes
+         * and prods fields out of {@code this.applicationInfo}.
+         */
+        public String cpuAbiOverride;
+
         public Package(String packageName) {
             this.packageName = packageName;
             applicationInfo.packageName = packageName;
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index af574db..4e7da48 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -70,7 +70,7 @@
 
     /**
      * Additional flag for {@link #protectionLevel}, corresponding
-     * to the <code>development</code> value of
+     * to the <code>appop</code> value of
      * {@link android.R.attr#protectionLevel}.
      */
     public static final int PROTECTION_FLAG_APPOP = 0x40;
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 8423d09..ba811b7 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -640,10 +640,13 @@
      * You can call this to try to enable hardware accelerated drawing for
      * your IME. This must be set before {@link #onCreate}, so you
      * will typically call it in your constructor.  It is not always possible
-     * to use hardware acclerated drawing in an IME (for example on low-end
+     * to use hardware accelerated drawing in an IME (for example on low-end
      * devices that do not have the resources to support this), so the call
      * returns true if it succeeds otherwise false if you will need to draw
      * in software.  You must be able to handle either case.
+     *
+     * @deprecated Starting in API 21, hardware acceleration is always enabled
+     *             on capable devices.
      */
     public boolean enableHardwareAcceleration() {
         if (mWindow != null) {
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index 129248c..a4ec80c 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -49,9 +49,8 @@
 public final class RouteInfo implements Parcelable {
     /**
      * The IP destination address for this route.
-     * TODO: Make this an IpPrefix.
      */
-    private final LinkAddress mDestination;
+    private final IpPrefix mDestination;
 
     /**
      * The gateway address for this route.
@@ -81,26 +80,15 @@
      * @param gateway the IP address to route packets through
      * @param iface the interface name to send packets on
      *
-     * TODO: Convert to use IpPrefix.
-     *
      * @hide
      */
     public RouteInfo(IpPrefix destination, InetAddress gateway, String iface) {
-        this(destination == null ? null :
-                new LinkAddress(destination.getAddress(), destination.getPrefixLength()),
-                gateway, iface);
-    }
-
-    /**
-     * @hide
-     */
-    public RouteInfo(LinkAddress destination, InetAddress gateway, String iface) {
         if (destination == null) {
             if (gateway != null) {
                 if (gateway instanceof Inet4Address) {
-                    destination = new LinkAddress(Inet4Address.ANY, 0);
+                    destination = new IpPrefix(Inet4Address.ANY, 0);
                 } else {
-                    destination = new LinkAddress(Inet6Address.ANY, 0);
+                    destination = new IpPrefix(Inet6Address.ANY, 0);
                 }
             } else {
                 // no destination, no gateway. invalid.
@@ -108,6 +96,9 @@
                                                    destination);
             }
         }
+        // TODO: set mGateway to null if there is no gateway. This is more correct, saves space, and
+        // matches the documented behaviour. Before we can do this we need to fix all callers (e.g.,
+        // ConnectivityService) to stop doing things like r.getGateway().equals(), ... .
         if (gateway == null) {
             if (destination.getAddress() instanceof Inet4Address) {
                 gateway = Inet4Address.ANY;
@@ -117,20 +108,28 @@
         }
         mHasGateway = (!gateway.isAnyLocalAddress());
 
-        mDestination = new LinkAddress(NetworkUtils.getNetworkPart(destination.getAddress(),
-                destination.getPrefixLength()), destination.getPrefixLength());
         if ((destination.getAddress() instanceof Inet4Address &&
                  (gateway instanceof Inet4Address == false)) ||
                 (destination.getAddress() instanceof Inet6Address &&
                  (gateway instanceof Inet6Address == false))) {
             throw new IllegalArgumentException("address family mismatch in RouteInfo constructor");
         }
-        mGateway = gateway;
-        mInterface = iface;
+        mDestination = destination;  // IpPrefix objects are immutable.
+        mGateway = gateway;          // InetAddress objects are immutable.
+        mInterface = iface;          // Strings are immutable.
         mIsHost = isHost();
     }
 
     /**
+     * @hide
+     */
+    public RouteInfo(LinkAddress destination, InetAddress gateway, String iface) {
+        this(destination == null ? null :
+                new IpPrefix(destination.getAddress(), destination.getPrefixLength()),
+                gateway, iface);
+    }
+
+    /**
      * Constructs a {@code RouteInfo} object.
      *
      * If destination is null, then gateway must be specified and the
@@ -164,7 +163,7 @@
      * @hide
      */
     public RouteInfo(InetAddress gateway) {
-        this((LinkAddress) null, gateway, null);
+        this((IpPrefix) null, gateway, null);
     }
 
     /**
@@ -200,9 +199,9 @@
         if (host == null) return null;
 
         if (host instanceof Inet4Address) {
-            return new RouteInfo(new LinkAddress(host, 32), gateway, iface);
+            return new RouteInfo(new IpPrefix(host, 32), gateway, iface);
         } else {
-            return new RouteInfo(new LinkAddress(host, 128), gateway, iface);
+            return new RouteInfo(new IpPrefix(host, 128), gateway, iface);
         }
     }
 
@@ -219,7 +218,7 @@
      * @return {@link IpPrefix} specifying the destination.  This is never {@code null}.
      */
     public IpPrefix getDestination() {
-        return new IpPrefix(mDestination.getAddress(), mDestination.getPrefixLength());
+        return mDestination;
     }
 
     /**
@@ -227,7 +226,7 @@
      * @hide
      */
     public LinkAddress getDestinationLinkAddress() {
-        return mDestination;
+        return new LinkAddress(mDestination.getAddress(), mDestination.getPrefixLength());
     }
 
     /**
@@ -363,7 +362,7 @@
 
         RouteInfo target = (RouteInfo) obj;
 
-        return Objects.equals(mDestination, target.getDestinationLinkAddress()) &&
+        return Objects.equals(mDestination, target.getDestination()) &&
                 Objects.equals(mGateway, target.getGateway()) &&
                 Objects.equals(mInterface, target.getInterface());
     }
@@ -388,16 +387,9 @@
      * Implement the Parcelable interface
      */
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeByteArray(mDestination.getAddress().getAddress());
-        dest.writeInt(mDestination.getPrefixLength());
-
-        if (mGateway == null) {
-            dest.writeByte((byte) 0);
-        } else {
-            dest.writeByte((byte) 1);
-            dest.writeByteArray(mGateway.getAddress());
-        }
-
+        dest.writeParcelable(mDestination, flags);
+        byte[] gatewayBytes = (mGateway == null) ? null : mGateway.getAddress();
+        dest.writeByteArray(gatewayBytes);
         dest.writeString(mInterface);
     }
 
@@ -407,33 +399,16 @@
     public static final Creator<RouteInfo> CREATOR =
         new Creator<RouteInfo>() {
         public RouteInfo createFromParcel(Parcel in) {
-            InetAddress destAddr = null;
-            int prefix = 0;
+            IpPrefix dest = in.readParcelable(null);
+
             InetAddress gateway = null;
-
             byte[] addr = in.createByteArray();
-            prefix = in.readInt();
-
             try {
-                destAddr = InetAddress.getByAddress(addr);
+                gateway = InetAddress.getByAddress(addr);
             } catch (UnknownHostException e) {}
 
-            if (in.readByte() == 1) {
-                addr = in.createByteArray();
-
-                try {
-                    gateway = InetAddress.getByAddress(addr);
-                } catch (UnknownHostException e) {}
-            }
-
             String iface = in.readString();
 
-            LinkAddress dest = null;
-
-            if (destAddr != null) {
-                dest = new LinkAddress(destAddr, prefix);
-            }
-
             return new RouteInfo(dest, gateway, iface);
         }
 
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index a1c2aa1..645d510 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -614,7 +614,7 @@
      * Flatten an ArrayMap into the parcel at the current dataPosition(),
      * growing dataCapacity() if needed.  The Map keys must be String objects.
      */
-    /* package */ void writeArrayMapInternal(ArrayMap<String,Object> val) {
+    /* package */ void writeArrayMapInternal(ArrayMap<String, Object> val) {
         if (val == null) {
             writeInt(-1);
             return;
@@ -629,7 +629,7 @@
         int startPos;
         for (int i=0; i<N; i++) {
             if (DEBUG_ARRAY_MAP) startPos = dataPosition();
-            writeValue(val.keyAt(i));
+            writeString(val.keyAt(i));
             writeValue(val.valueAt(i));
             if (DEBUG_ARRAY_MAP) Log.d(TAG, "  Write #" + i + " "
                     + (dataPosition()-startPos) + " bytes: key=0x"
@@ -639,6 +639,13 @@
     }
 
     /**
+     * @hide For testing only.
+     */
+    public void writeArrayMap(ArrayMap<String, Object> val) {
+        writeArrayMapInternal(val);
+    }
+
+    /**
      * Flatten a Bundle into the parcel at the current dataPosition(),
      * growing dataCapacity() if needed.
      */
@@ -2411,7 +2418,7 @@
         int startPos;
         while (N > 0) {
             if (DEBUG_ARRAY_MAP) startPos = dataPosition();
-            Object key = readValue(loader);
+            String key = readString();
             Object value = readValue(loader);
             if (DEBUG_ARRAY_MAP) Log.d(TAG, "  Read #" + (N-1) + " "
                     + (dataPosition()-startPos) + " bytes: key=0x"
@@ -2419,6 +2426,7 @@
             outVal.append(key, value);
             N--;
         }
+        outVal.validate();
     }
 
     /* package */ void readArrayMapSafelyInternal(ArrayMap outVal, int N,
@@ -2429,7 +2437,7 @@
             Log.d(TAG, "Reading safely " + N + " ArrayMap entries", here);
         }
         while (N > 0) {
-            Object key = readValue(loader);
+            String key = readString();
             if (DEBUG_ARRAY_MAP) Log.d(TAG, "  Read safe #" + (N-1) + ": key=0x"
                     + (key != null ? key.hashCode() : 0) + " " + key);
             Object value = readValue(loader);
@@ -2438,6 +2446,17 @@
         }
     }
 
+    /**
+     * @hide For testing only.
+     */
+    public void readArrayMap(ArrayMap outVal, ClassLoader loader) {
+        final int N = readInt();
+        if (N < 0) {
+            return;
+        }
+        readArrayMapInternal(outVal, N, loader);
+    }
+
     private void readListInternal(List outVal, int N,
         ClassLoader loader) {
         while (N > 0) {
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 6334f76..f381fdf 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -298,10 +298,10 @@
     public static final int USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS = 1 << 0;
 
     /**
-     * Go to sleep reason code: Going to sleep due by user request.
+     * Go to sleep reason code: Going to sleep due by application request.
      * @hide
      */
-    public static final int GO_TO_SLEEP_REASON_USER = 0;
+    public static final int GO_TO_SLEEP_REASON_APPLICATION = 0;
 
     /**
      * Go to sleep reason code: Going to sleep due by request of the
@@ -317,6 +317,24 @@
     public static final int GO_TO_SLEEP_REASON_TIMEOUT = 2;
 
     /**
+     * Go to sleep reason code: Going to sleep due to the lid switch being closed.
+     * @hide
+     */
+    public static final int GO_TO_SLEEP_REASON_LID_SWITCH = 3;
+
+    /**
+     * Go to sleep reason code: Going to sleep due to the power button being pressed.
+     * @hide
+     */
+    public static final int GO_TO_SLEEP_REASON_POWER_BUTTON = 4;
+
+    /**
+     * Go to sleep reason code: Going to sleep due to HDMI.
+     * @hide
+     */
+    public static final int GO_TO_SLEEP_REASON_HDMI = 5;
+
+    /**
      * The value to pass as the 'reason' argument to reboot() to
      * reboot into recovery mode (for applying system updates, doing
      * factory resets, etc.).
@@ -325,6 +343,7 @@
      * permission (in addition to
      * {@link android.Manifest.permission#REBOOT}).
      * </p>
+     * @hide
      */
     public static final String REBOOT_RECOVERY = "recovery";
     
@@ -513,7 +532,7 @@
      * @see #wakeUp
      */
     public void goToSleep(long time) {
-        goToSleep(time, GO_TO_SLEEP_REASON_USER, 0);
+        goToSleep(time, GO_TO_SLEEP_REASON_APPLICATION, 0);
     }
 
     /**
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 7aee455..7a46e40 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -432,7 +432,7 @@
 
         // Having written the command file, go ahead and reboot
         PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
-        pm.reboot("recovery");
+        pm.reboot(PowerManager.REBOOT_RECOVERY);
 
         throw new IOException("Reboot failed (no permissions?)");
     }
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 3087506..f9e7b78 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -696,6 +696,26 @@
     }
 
     /**
+     * Checks whether it's possible to add more users. Caller must hold the MANAGE_USERS
+     * permission.
+     *
+     * @return true if more users can be added, false if limit has been reached.
+     * @hide
+     */
+    public boolean canAddMoreUsers() {
+        final List<UserInfo> users = getUsers(true);
+        final int totalUserCount = users.size();
+        int aliveUserCount = 0;
+        for (int i = 0; i < totalUserCount; i++) {
+            UserInfo user = users.get(i);
+            if (!user.isGuest()) {
+                aliveUserCount++;
+            }
+        }
+        return aliveUserCount < getMaxSupportedUsers();
+    }
+
+    /**
      * Returns list of the profiles of userHandle including
      * userHandle itself.
      * Note that it this returns both enabled and not enabled profiles. See
diff --git a/core/java/android/preference/PreferenceFragment.java b/core/java/android/preference/PreferenceFragment.java
index acd7942..e95e6e2 100644
--- a/core/java/android/preference/PreferenceFragment.java
+++ b/core/java/android/preference/PreferenceFragment.java
@@ -258,6 +258,7 @@
      */
     public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
         if (mPreferenceManager.setPreferences(preferenceScreen) && preferenceScreen != null) {
+            onUnbindPreferences();
             mHavePrefs = true;
             if (mInitDone) {
                 postBindPreferences();
@@ -350,6 +351,10 @@
     }
 
     /** @hide */
+    protected void onUnbindPreferences() {
+    }
+
+    /** @hide */
     public ListView getListView() {
         ensureList();
         return mList;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 55ba9e9..8886559 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -170,6 +170,20 @@
             "android.settings.ACCESSIBILITY_SETTINGS";
 
     /**
+     * Activity Action: Show settings to control access to usage information.
+     * <p>
+     * In some cases, a matching Activity may not exist, so ensure you
+     * safeguard against this.
+     * <p>
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_USAGE_ACCESS_SETTINGS =
+            "android.settings.USAGE_ACCESS_SETTINGS";
+
+    /**
      * Activity Action: Show settings to allow configuration of security and
      * location privacy.
      * <p>
@@ -372,6 +386,21 @@
      * Output: Nothing.
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_VOICE_INPUT_SETTINGS =
+            "android.settings.VOICE_INPUT_SETTINGS";
+
+    /**
+     * Activity Action: Show settings to configure input methods, in particular
+     * allowing the user to enable input methods.
+     * <p>
+     * In some cases, a matching Activity may not exist, so ensure you
+     * safeguard against this.
+     * <p>
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_INPUT_METHOD_SETTINGS =
             "android.settings.INPUT_METHOD_SETTINGS";
 
@@ -2335,16 +2364,6 @@
         public static final String VIBRATE_WHEN_RINGING = "vibrate_when_ringing";
 
         /**
-         * Whether automatic routing of system audio to USB audio peripheral is disabled.
-         * The value is boolean (1 or 0), where 1 means automatic routing is disabled,
-         * and 0 means automatic routing is enabled.
-         *
-         * @hide
-         */
-        public static final String USB_AUDIO_AUTOMATIC_ROUTING_DISABLED =
-                "usb_audio_automatic_routing_disabled";
-
-        /**
          * Whether the audible DTMF tones are played by the dialer when dialing. The value is
          * boolean (1 or 0).
          */
@@ -4716,6 +4735,16 @@
         public static final String TV_INPUT_CUSTOM_LABELS = "tv_input_custom_labels";
 
         /**
+         * Whether automatic routing of system audio to USB audio peripheral is disabled.
+         * The value is boolean (1 or 0), where 1 means automatic routing is disabled,
+         * and 0 means automatic routing is enabled.
+         *
+         * @hide
+         */
+        public static final String USB_AUDIO_AUTOMATIC_ROUTING_DISABLED =
+                "usb_audio_automatic_routing_disabled";
+
+        /**
          * This are the settings to be backed up.
          *
          * NOTE: Settings are backed up and restored in the order they appear
@@ -6343,7 +6372,7 @@
 
         /**
          * Milliseconds to wait before bouncing Wi-Fi after settings is restored. Note that after
-         * the caller is done with this, they should call {@link ContentResolver#delete(Uri)} to
+         * the caller is done with this, they should call {@link ContentResolver#delete} to
          * clean up any value that they may have written.
          *
          * @hide
diff --git a/core/java/android/service/persistentdata/PersistentDataBlockManager.java b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
index 42a2e57..0ffdf68 100644
--- a/core/java/android/service/persistentdata/PersistentDataBlockManager.java
+++ b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
@@ -16,6 +16,7 @@
 
 package android.service.persistentdata;
 
+import android.annotation.SystemApi;
 import android.os.RemoteException;
 import android.util.Slog;
 
@@ -30,12 +31,14 @@
  * {@link PersistentDataBlockManager#getDataBlockSize()}.
  *
  * Clients can query the maximum size for a block via
+ * {@link PersistentDataBlockManager#getMaximumDataBlockSize()}
  *
  * Clients can read the currently written block by invoking
  * {@link PersistentDataBlockManager#read()}.
  *
  * @hide
  */
+@SystemApi
 public class PersistentDataBlockManager {
     private static final String TAG = PersistentDataBlockManager.class.getSimpleName();
     private IPersistentDataBlockService sService;
diff --git a/core/java/android/service/voice/VoiceInteractionServiceInfo.java b/core/java/android/service/voice/VoiceInteractionServiceInfo.java
index bacda04..e6e9413 100644
--- a/core/java/android/service/voice/VoiceInteractionServiceInfo.java
+++ b/core/java/android/service/voice/VoiceInteractionServiceInfo.java
@@ -99,6 +99,11 @@
                 mParseError = "No sessionService specified";
                 return;
             }
+            /* Not yet time
+            if (mRecognitionService == null) {
+                mParseError = "No recogitionService specified";
+                return;
+            } */
         } catch (XmlPullParserException e) {
             mParseError = "Error parsing voice interation service meta-data: " + e;
             Log.w(TAG, "error parsing voice interaction service meta-data", e);
diff --git a/core/java/android/text/InputFilter.java b/core/java/android/text/InputFilter.java
index 8d4b08e..bff09a2 100644
--- a/core/java/android/text/InputFilter.java
+++ b/core/java/android/text/InputFilter.java
@@ -75,14 +75,15 @@
      * greater than the specified length.
      */
     public static class LengthFilter implements InputFilter {
+        private final int mMax;
+
         public LengthFilter(int max) {
             mMax = max;
         }
 
-        public CharSequence filter(CharSequence source, int start, int end,
-                                   Spanned dest, int dstart, int dend) {
+        public CharSequence filter(CharSequence source, int start, int end, Spanned dest,
+                int dstart, int dend) {
             int keep = mMax - (dest.length() - (dend - dstart));
-
             if (keep <= 0) {
                 return "";
             } else if (keep >= end - start) {
@@ -99,6 +100,11 @@
             }
         }
 
-        private int mMax;
+        /**
+         * @return the maximum length enforced by this input filter
+         */
+        public int getMax() {
+            return mMax;
+        }
     }
 }
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index a36f06c7..7dce348 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -273,16 +273,22 @@
                 // Draw all leading margin spans.  Adjust left or right according
                 // to the paragraph direction of the line.
                 final int length = spans.length;
+                boolean useFirstLineMargin = isFirstParaLine;
+                for (int n = 0; n < length; n++) {
+                    if (spans[n] instanceof LeadingMarginSpan2) {
+                        int count = ((LeadingMarginSpan2) spans[n]).getLeadingMarginLineCount();
+                        int startLine = getLineForOffset(sp.getSpanStart(spans[n]));
+                        // if there is more than one LeadingMarginSpan2, use
+                        // the count that is greatest
+                        if (i < startLine + count) {
+                            useFirstLineMargin = true;
+                            break;
+                        }
+                    }
+                }
                 for (int n = 0; n < length; n++) {
                     if (spans[n] instanceof LeadingMarginSpan) {
                         LeadingMarginSpan margin = (LeadingMarginSpan) spans[n];
-                        boolean useFirstLineMargin = isFirstParaLine;
-                        if (margin instanceof LeadingMarginSpan2) {
-                            int count = ((LeadingMarginSpan2) margin).getLeadingMarginLineCount();
-                            int startLine = getLineForOffset(sp.getSpanStart(margin));
-                            useFirstLineMargin = i < startLine + count;
-                        }
-
                         if (dir == DIR_RIGHT_TO_LEFT) {
                             margin.drawLeadingMargin(canvas, paint, right, dir, ltop,
                                                      lbaseline, lbottom, buf,
@@ -1535,15 +1541,18 @@
         boolean isFirstParaLine = lineStart == 0 ||
             spanned.charAt(lineStart - 1) == '\n';
 
+        boolean useFirstLineMargin = isFirstParaLine;
+        for (int i = 0; i < spans.length; i++) {
+            if (spans[i] instanceof LeadingMarginSpan2) {
+                int spStart = spanned.getSpanStart(spans[i]);
+                int spanLine = getLineForOffset(spStart);
+                int count = ((LeadingMarginSpan2) spans[i]).getLeadingMarginLineCount();
+                // if there is more than one LeadingMarginSpan2, use the count that is greatest
+                useFirstLineMargin |= line < spanLine + count;
+            }
+        }
         for (int i = 0; i < spans.length; i++) {
             LeadingMarginSpan span = spans[i];
-            boolean useFirstLineMargin = isFirstParaLine;
-            if (span instanceof LeadingMarginSpan2) {
-                int spStart = spanned.getSpanStart(span);
-                int spanLine = getLineForOffset(spStart);
-                int count = ((LeadingMarginSpan2)span).getLeadingMarginLineCount();
-                useFirstLineMargin = line < spanLine + count;
-            }
             margin += span.getLeadingMargin(useFirstLineMargin);
         }
 
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 4144a75..aecf488 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -201,13 +201,12 @@
                     restWidth -= sp[i].getLeadingMargin(false);
 
                     // LeadingMarginSpan2 is odd.  The count affects all
-                    // leading margin spans, not just this particular one,
-                    // and start from the top of the span, not the top of the
-                    // paragraph.
+                    // leading margin spans, not just this particular one
                     if (lms instanceof LeadingMarginSpan2) {
                         LeadingMarginSpan2 lms2 = (LeadingMarginSpan2) lms;
                         int lmsFirstLine = getLineForOffset(spanned.getSpanStart(lms2));
-                        firstWidthLineLimit = lmsFirstLine + lms2.getLeadingMarginLineCount();
+                        firstWidthLineLimit = Math.max(firstWidthLineLimit,
+                                lmsFirstLine + lms2.getLeadingMarginLineCount());
                     }
                 }
 
diff --git a/core/java/android/text/style/LeadingMarginSpan.java b/core/java/android/text/style/LeadingMarginSpan.java
index 2f429ff..96a7cd9 100644
--- a/core/java/android/text/style/LeadingMarginSpan.java
+++ b/core/java/android/text/style/LeadingMarginSpan.java
@@ -28,6 +28,9 @@
  * margin spans on a single paragraph; they will be rendered in order, each
  * adding its margin to the ones before it. The leading margin is on the right
  * for lines in a right-to-left paragraph.
+ * <p>
+ * LeadingMarginSpans should be attached from the first character to the last
+ * character of a single paragraph.
  */
 public interface LeadingMarginSpan
 extends ParagraphStyle
@@ -69,18 +72,22 @@
 
 
     /**
-     * An extended version of {@link LeadingMarginSpan}, which allows
-     * the implementor to specify the number of lines of text to which
-     * this object is attached that the "first line of paragraph" margin
-     * width will be applied to.
+     * An extended version of {@link LeadingMarginSpan}, which allows the
+     * implementor to specify the number of lines of the paragraph to which
+     * this object is attached that the "first line of paragraph" margin width
+     * will be applied to.
+     * <p>
+     * There should only be one LeadingMarginSpan2 per paragraph. The leading
+     * margin line count affects all LeadingMarginSpans in the paragraph,
+     * adjusting the number of lines to which the first line margin is applied.
+     * <p>
+     * As with LeadingMarginSpans, LeadingMarginSpan2s should be attached from
+     * the beginning to the end of a paragraph.
      */
     public interface LeadingMarginSpan2 extends LeadingMarginSpan, WrapTogetherSpan {
         /**
-         * Returns the number of lines of text to which this object is
+         * Returns the number of lines of the paragraph to which this object is
          * attached that the "first line" margin will apply to.
-         * Note that if this returns N, the first N lines of the region,
-         * not the first N lines of each paragraph, will be given the
-         * special margin width.
          */
         public int getLeadingMarginLineCount();
     };
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index 9a0b7fc..3889cb6 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -410,7 +410,7 @@
 
     /**
      * Add a new value to the array map.
-     * @param key The key under which to store the value.  <b>Must not be null.</b>  If
+     * @param key The key under which to store the value.  If
      * this key already exists in the array, its value will be replaced.
      * @param value The value to store for the given key.
      * @return Returns the old value that was stored for the given key, or null if there
@@ -496,6 +496,44 @@
     }
 
     /**
+     * The use of the {@link #append} function can result in invalid array maps, in particular
+     * an array map where the same key appears multiple times.  This function verifies that
+     * the array map is valid, throwing IllegalArgumentException if a problem is found.  The
+     * main use for this method is validating an array map after unpacking from an IPC, to
+     * protect against malicious callers.
+     * @hide
+     */
+    public void validate() {
+        final int N = mSize;
+        if (N <= 1) {
+            // There can't be dups.
+            return;
+        }
+        int basehash = mHashes[0];
+        int basei = 0;
+        for (int i=1; i<N; i++) {
+            int hash = mHashes[i];
+            if (hash != basehash) {
+                basehash = hash;
+                basei = i;
+                continue;
+            }
+            // We are in a run of entries with the same hash code.  Go backwards through
+            // the array to see if any keys are the same.
+            final Object cur = mArray[i<<1];
+            for (int j=i-1; j>=basei; j--) {
+                final Object prev = mArray[j<<1];
+                if (cur == prev) {
+                    throw new IllegalArgumentException("Duplicate key in ArrayMap: " + cur);
+                }
+                if (cur != null && prev != null && cur.equals(prev)) {
+                    throw new IllegalArgumentException("Duplicate key in ArrayMap: " + cur);
+                }
+            }
+        }
+    }
+
+    /**
      * Perform a {@link #put(Object, Object)} of all key/value pairs in <var>array</var>
      * @param array The array whose contents are to be retrieved.
      */
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index 3f10b92..946a3f7 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -68,7 +68,7 @@
 
     /**
      * Intermediate density for screens that sit somewhere between
-     * {@link #DENSITY_XHIGH} (320dpi) and {@link #DENSITY_XXHIGH} (480 dpi).
+     * {@link #DENSITY_XHIGH} (320 dpi) and {@link #DENSITY_XXHIGH} (480 dpi).
      * This is not a density that applications should target, instead relying
      * on the system to scale their {@link #DENSITY_XXHIGH} assets for them.
      */
@@ -80,6 +80,14 @@
     public static final int DENSITY_XXHIGH = 480;
 
     /**
+     * Intermediate density for screens that sit somewhere between
+     * {@link #DENSITY_XXHIGH} (480 dpi) and {@link #DENSITY_XXXHIGH} (560 dpi).
+     * This is not a density that applications should target, instead relying
+     * on the system to scale their {@link #DENSITY_XXXHIGH} assets for them.
+     */
+    public static final int DENSITY_560 = 560;
+
+    /**
      * Standard quantized DPI for extra-extra-extra-high-density screens.  Applications
      * should not generally worry about this density; relying on XHIGH graphics
      * being scaled up to it should be sufficient for almost all cases.  A typical
diff --git a/core/java/android/view/GhostView.java b/core/java/android/view/GhostView.java
index a79838f..3cbaf60 100644
--- a/core/java/android/view/GhostView.java
+++ b/core/java/android/view/GhostView.java
@@ -17,6 +17,7 @@
 
 import android.graphics.Canvas;
 import android.graphics.Matrix;
+import android.widget.FrameLayout;
 
 /**
  * This view draws another View in an Overlay without changing the parent. It will not be drawn
@@ -28,17 +29,13 @@
  */
 public class GhostView extends View {
     private final View mView;
+    private int mReferences;
 
-    private GhostView(View view, ViewGroup host, Matrix matrix) {
+    private GhostView(View view) {
         super(view.getContext());
         mView = view;
         mView.mGhostView = this;
-        mRenderNode.setAnimationMatrix(matrix);
         final ViewGroup parent = (ViewGroup) mView.getParent();
-        setLeft(0);
-        setTop(0);
-        setRight(host.getWidth());
-        setBottom(host.getHeight());
         setGhostedVisibility(View.INVISIBLE);
         parent.mRecreateDisplayList = true;
         parent.getDisplayList();
@@ -100,10 +97,13 @@
         ViewGroupOverlay overlay = viewGroup.getOverlay();
         ViewOverlay.OverlayViewGroup overlayViewGroup = overlay.mOverlayViewGroup;
         GhostView ghostView = view.mGhostView;
+        int previousRefCount = 0;
         if (ghostView != null) {
-            ViewGroup oldParent = (ViewGroup) ghostView.getParent();
-            if (oldParent != overlayViewGroup) {
-                oldParent.removeView(ghostView);
+            View oldParent = (View) ghostView.getParent();
+            ViewGroup oldGrandParent = (ViewGroup) oldParent.getParent();
+            if (oldGrandParent != overlayViewGroup) {
+                previousRefCount = ghostView.mReferences;
+                oldGrandParent.removeView(oldParent);
                 ghostView = null;
             }
         }
@@ -112,9 +112,19 @@
                 matrix = new Matrix();
                 calculateMatrix(view, viewGroup, matrix);
             }
-            ghostView = new GhostView(view, (ViewGroup) overlayViewGroup.mHostView, matrix);
-            overlay.add(ghostView);
+            ghostView = new GhostView(view);
+            ghostView.setMatrix(matrix);
+            FrameLayout parent = new FrameLayout(view.getContext());
+            parent.setClipChildren(false);
+            copySize(viewGroup, parent);
+            copySize(viewGroup, ghostView);
+            parent.addView(ghostView);
+            overlay.add(parent);
+            ghostView.mReferences = previousRefCount;
+        } else if (matrix != null) {
+            ghostView.setMatrix(matrix);
         }
+        ghostView.mReferences++;
         return ghostView;
     }
 
@@ -125,12 +135,23 @@
     public static void removeGhost(View view) {
         GhostView ghostView = view.mGhostView;
         if (ghostView != null) {
-            ViewGroup parent = (ViewGroup) ghostView.getParent();
-            parent.removeView(ghostView);
+            ghostView.mReferences--;
+            if (ghostView.mReferences == 0) {
+                ViewGroup parent = (ViewGroup) ghostView.getParent();
+                ViewGroup grandParent = (ViewGroup) parent.getParent();
+                grandParent.removeView(parent);
+            }
         }
     }
 
     public static GhostView getGhost(View view) {
         return view.mGhostView;
     }
+
+    private static void copySize(View from, View to) {
+        to.setLeft(0);
+        to.setTop(0);
+        to.setRight(from.getWidth());
+        to.setBottom(from.getHeight());
+    }
 }
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 83767cb..7deb9c8 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -121,7 +121,8 @@
     boolean isKeyguardSecure();
     boolean inKeyguardRestrictedInputMode();
     void dismissKeyguard();
-    void keyguardGoingAway();
+    void keyguardGoingAway(boolean disableWindowAnimations,
+            boolean keyguardGoingToNotificationShade);
 
     void closeSystemDialogs(String reason);
 
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 0b15ba7..4d9a8cc 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -1107,8 +1107,7 @@
 
                     exportUnrolledArray(context, out, property, array, valuePrefix, suffix);
 
-                    // Probably want to return here, same as for fields.
-                    return;
+                    continue;
                 } else if (!returnType.isPrimitive()) {
                     if (property.deepExport()) {
                         dumpViewProperties(context, methodValue, out, prefix + property.prefix());
@@ -1187,8 +1186,7 @@
 
                     exportUnrolledArray(context, out, property, array, valuePrefix, suffix);
 
-                    // We exit here!
-                    return;
+                    continue;
                 } else if (!type.isPrimitive()) {
                     if (property.deepExport()) {
                         dumpViewProperties(context, field.get(view), out, prefix +
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index b6c650d..053fdd0 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -737,13 +737,14 @@
     /**
      * Create and return an animation to re-display a force hidden window.
      */
-    public Animation createForceHideEnterAnimation(boolean onWallpaper);
+    public Animation createForceHideEnterAnimation(boolean onWallpaper,
+            boolean goingToNotificationShade);
 
     /**
      * Create and return an animation to let the wallpaper disappear after being shown on a force
      * hiding window.
      */
-    public Animation createForceHideWallpaperExitAnimation();
+    public Animation createForceHideWallpaperExitAnimation(boolean goingToNotificationShade);
 
     /**
      * Called from the input reader thread before a key is enqueued.
@@ -1014,6 +1015,11 @@
     public void dismissKeyguardLw();
 
     /**
+     * Notifies the keyguard that the activity has drawn it was waiting for.
+     */
+    public void notifyActivityDrawnForKeyguardLw();
+
+    /**
      * Ask the policy whether the Keyguard has drawn. If the Keyguard is disabled, this method
      * returns true as soon as we know that Keyguard is disabled.
      *
diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java
index 4f34231..ca6437a 100644
--- a/core/java/android/view/accessibility/AccessibilityCache.java
+++ b/core/java/android/view/accessibility/AccessibilityCache.java
@@ -36,7 +36,7 @@
 
     private static final boolean DEBUG = false;
 
-    private static final boolean CHECK_INTEGRITY = Build.IS_DEBUGGABLE;
+    private static final boolean CHECK_INTEGRITY = "eng".equals(Build.TYPE);
 
     private final Object mLock = new Object();
 
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 1bf4639..3987fbc 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -562,6 +562,7 @@
     private LongArray mChildNodeIds;
     private ArrayList<AccessibilityAction> mActions;
 
+    private int mMaxTextLength = -1;
     private int mMovementGranularities;
 
     private int mTextSelectionStart = UNDEFINED_SELECTION_INDEX;
@@ -1045,6 +1046,36 @@
     }
 
     /**
+     * Sets the maximum text length, or -1 for no limit.
+     * <p>
+     * Typically used to indicate that an editable text field has a limit on
+     * the number of characters entered.
+     * <p>
+     * <strong>Note:</strong> Cannot be called from an
+     * {@link android.accessibilityservice.AccessibilityService}.
+     * This class is made immutable before being delivered to an AccessibilityService.
+     *
+     * @param max The maximum text length.
+     * @see #getMaxTextLength()
+     *
+     * @throws IllegalStateException If called from an AccessibilityService.
+     */
+    public void setMaxTextLength(int max) {
+        enforceNotSealed();
+        mMaxTextLength = max;
+    }
+
+    /**
+     * Returns the maximum text length for this node.
+     *
+     * @return The maximum text length, or -1 for no limit.
+     * @see #setMaxTextLength(int)
+     */
+    public int getMaxTextLength() {
+        return mMaxTextLength;
+    }
+
+    /**
      * Sets the movement granularities for traversing the text of this node.
      * <p>
      *   <strong>Note:</strong> Cannot be called from an
@@ -2469,8 +2500,8 @@
             parcel.writeInt(0);
         }
 
+        parcel.writeInt(mMaxTextLength);
         parcel.writeInt(mMovementGranularities);
-
         parcel.writeInt(mBooleanProperties);
 
         parcel.writeCharSequence(mPackageName);
@@ -2562,6 +2593,7 @@
         }
 
         mBooleanProperties = other.mBooleanProperties;
+        mMaxTextLength = other.mMaxTextLength;
         mMovementGranularities = other.mMovementGranularities;
 
         final LongArray otherChildNodeIds = other.mChildNodeIds;
@@ -2636,8 +2668,8 @@
             }
         }
 
+        mMaxTextLength = parcel.readInt();
         mMovementGranularities = parcel.readInt();
-
         mBooleanProperties = parcel.readInt();
 
         mPackageName = parcel.readCharSequence();
@@ -2695,6 +2727,7 @@
         mLabeledById = ROOT_NODE_ID;
         mWindowId = UNDEFINED_ITEM_ID;
         mConnectionId = UNDEFINED_CONNECTION_ID;
+        mMaxTextLength = -1;
         mMovementGranularities = 0;
         if (mChildNodeIds != null) {
             mChildNodeIds.clear();
@@ -2911,6 +2944,7 @@
         builder.append("; className: ").append(mClassName);
         builder.append("; text: ").append(mText);
         builder.append("; error: ").append(mError);
+        builder.append("; maxTextLength: ").append(mMaxTextLength);
         builder.append("; contentDescription: ").append(mContentDescription);
         builder.append("; viewIdResName: ").append(mViewIdResourceName);
 
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 623b5f9..eec3570 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1655,7 +1655,12 @@
             final boolean isImmediate = (mCursorAnchorInfoMonitorMode &
                     CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0;
             if (!isImmediate && Objects.equals(mCursorAnchorInfo, cursorAnchorInfo)) {
-                Log.w(TAG, "Ignoring redundant updateCursorAnchorInfo: info=" + cursorAnchorInfo);
+                // TODO: Consider always emitting this message once we have addressed redundant
+                // calls of this method from android.widget.Editor.
+                if (DEBUG) {
+                    Log.w(TAG, "Ignoring redundant updateCursorAnchorInfo: info="
+                            + cursorAnchorInfo);
+                }
                 return;
             }
             if (DEBUG) Log.v(TAG, "updateCursorAnchorInfo: " + cursorAnchorInfo);
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index e07a6e3..1b0cb3d 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1730,9 +1730,12 @@
      * <ul>
      * <li> This method can be used to allow JavaScript to control the host
      * application. This is a powerful feature, but also presents a security
-     * risk for applications targeted to API level
-     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} or below, because
-     * JavaScript could use reflection to access an
+     * risk for apps targeting {@link android.os.Build.VERSION_CODES#JELLY_BEAN} or earlier.
+     * Apps that target a version later than {@link android.os.Build.VERSION_CODES#JELLY_BEAN}
+     * are still vulnerable if the app runs on a device running Android earlier than 4.2.
+     * The most secure way to use this method is to target {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
+     * and to ensure the method is called only when running on Android 4.2 or later.
+     * With these older versions, JavaScript could use reflection to access an
      * injected object's public fields. Use of this method in a WebView
      * containing untrusted content could allow an attacker to manipulate the
      * host application in unintended ways, executing Java code with the
@@ -1740,7 +1743,8 @@
      * method in a WebView which could contain untrusted content.</li>
      * <li> JavaScript interacts with Java object on a private, background
      * thread of this WebView. Care is therefore required to maintain thread
-     * safety.</li>
+     * safety.
+     * </li>
      * <li> The Java object's fields are not accessible.</li>
      * <li> For applications targeted to API level {@link android.os.Build.VERSION_CODES#L}
      * and above, methods of injected Java objects are enumerable from
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 23894ee..c7ffedc 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -29,6 +29,7 @@
 import android.os.ServiceManager;
 import android.os.StrictMode;
 import android.os.SystemProperties;
+import android.os.Trace;
 import android.text.TextUtils;
 import android.util.AndroidRuntimeException;
 import android.util.Log;
@@ -71,38 +72,55 @@
     private static WebViewFactoryProvider sProviderInstance;
     private static final Object sProviderLock = new Object();
     private static boolean sAddressSpaceReserved = false;
+    private static PackageInfo sPackageInfo;
 
     public static String getWebViewPackageName() {
         return AppGlobals.getInitialApplication().getString(
                 com.android.internal.R.string.config_webViewPackageName);
     }
 
+    public static PackageInfo getLoadedPackageInfo() {
+        return sPackageInfo;
+    }
+
     static WebViewFactoryProvider getProvider() {
         synchronized (sProviderLock) {
             // For now the main purpose of this function (and the factory abstraction) is to keep
             // us honest and minimize usage of WebView internals when binding the proxy.
             if (sProviderInstance != null) return sProviderInstance;
 
-            loadNativeLibrary();
-
-            Class<WebViewFactoryProvider> providerClass;
+            Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getProvider()");
             try {
-                providerClass = getFactoryClass();
-            } catch (ClassNotFoundException e) {
-                Log.e(LOGTAG, "error loading provider", e);
-                throw new AndroidRuntimeException(e);
-            }
+                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()");
+                loadNativeLibrary();
+                Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
 
-            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
-            try {
-                sProviderInstance = providerClass.newInstance();
-                if (DEBUG) Log.v(LOGTAG, "Loaded provider: " + sProviderInstance);
-                return sProviderInstance;
-            } catch (Exception e) {
-                Log.e(LOGTAG, "error instantiating provider", e);
-                throw new AndroidRuntimeException(e);
+                Class<WebViewFactoryProvider> providerClass;
+                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getFactoryClass()");
+                try {
+                    providerClass = getFactoryClass();
+                } catch (ClassNotFoundException e) {
+                    Log.e(LOGTAG, "error loading provider", e);
+                    throw new AndroidRuntimeException(e);
+                } finally {
+                    Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
+                }
+
+                StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
+                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "providerClass.newInstance()");
+                try {
+                    sProviderInstance = providerClass.newInstance();
+                    if (DEBUG) Log.v(LOGTAG, "Loaded provider: " + sProviderInstance);
+                    return sProviderInstance;
+                } catch (Exception e) {
+                    Log.e(LOGTAG, "error instantiating provider", e);
+                    throw new AndroidRuntimeException(e);
+                } finally {
+                    Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
+                    StrictMode.setThreadPolicy(oldPolicy);
+                }
             } finally {
-                StrictMode.setThreadPolicy(oldPolicy);
+                Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
             }
         }
     }
@@ -112,9 +130,9 @@
         try {
             // First fetch the package info so we can log the webview package version.
             String packageName = getWebViewPackageName();
-            PackageInfo pi = initialApplication.getPackageManager().getPackageInfo(packageName, 0);
-            Log.i(LOGTAG, "Loading " + packageName + " version " + pi.versionName +
-                          " (code " + pi.versionCode + ")");
+            sPackageInfo = initialApplication.getPackageManager().getPackageInfo(packageName, 0);
+            Log.i(LOGTAG, "Loading " + packageName + " version " + sPackageInfo.versionName +
+                          " (code " + sPackageInfo.versionCode + ")");
 
             // Construct a package context to load the Java code into the current app.
             Context webViewContext = initialApplication.createPackageContext(packageName,
@@ -122,8 +140,13 @@
             initialApplication.getAssets().addAssetPath(
                     webViewContext.getApplicationInfo().sourceDir);
             ClassLoader clazzLoader = webViewContext.getClassLoader();
-            return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY, true,
-                                                                 clazzLoader);
+            Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "Class.forName()");
+            try {
+                return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY, true,
+                                                                     clazzLoader);
+            } finally {
+                Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
+            }
         } catch (PackageManager.NameNotFoundException e) {
             // If the package doesn't exist, then try loading the null WebView instead.
             // If that succeeds, then this is a device without WebView support; if it fails then
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index ccd0480..29a6a7d 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -53,6 +53,8 @@
 
     private int mBasePadding;
     private int mCheckMarkWidth;
+    private int mCheckMarkGravity = Gravity.END;
+
     private boolean mNeedRequestlayout;
 
     private static final int[] CHECKED_STATE_SET = {
@@ -83,15 +85,17 @@
         }
 
         mCheckMarkTintMode = Drawable.parseTintMode(a.getInt(
-                R.styleable.CompoundButton_buttonTintMode, -1), mCheckMarkTintMode);
+                R.styleable.CheckedTextView_checkMarkTintMode, -1), mCheckMarkTintMode);
 
-        if (a.hasValue(R.styleable.CompoundButton_buttonTint)) {
-            mCheckMarkTintList = a.getColorStateList(R.styleable.CompoundButton_buttonTint);
+        if (a.hasValue(R.styleable.CheckedTextView_checkMarkTint)) {
+            mCheckMarkTintList = a.getColorStateList(R.styleable.CheckedTextView_checkMarkTint);
             mHasCheckMarkTint = true;
 
             applyCheckMarkTint();
         }
 
+        mCheckMarkGravity = a.getInt(R.styleable.CheckedTextView_checkMarkGravity, Gravity.END);
+
         boolean checked = a.getBoolean(R.styleable.CheckedTextView_checked, false);
         setChecked(checked);
 
@@ -293,7 +297,7 @@
     @Override
     protected void internalSetPadding(int left, int top, int right, int bottom) {
         super.internalSetPadding(left, top, right, bottom);
-        setBasePadding(isLayoutRtl());
+        setBasePadding(isCheckMarkAtStart());
     }
 
     @Override
@@ -306,7 +310,7 @@
         resetPaddingToInitialValues();
         int newPadding = (mCheckMarkDrawable != null) ?
                 mCheckMarkWidth + mBasePadding : mBasePadding;
-        if (isLayoutRtl()) {
+        if (isCheckMarkAtStart()) {
             mNeedRequestlayout |= (mPaddingLeft != newPadding);
             mPaddingLeft = newPadding;
         } else {
@@ -319,14 +323,20 @@
         }
     }
 
-    private void setBasePadding(boolean isLayoutRtl) {
-        if (isLayoutRtl) {
+    private void setBasePadding(boolean checkmarkAtStart) {
+        if (checkmarkAtStart) {
             mBasePadding = mPaddingLeft;
         } else {
             mBasePadding = mPaddingRight;
         }
     }
 
+    private boolean isCheckMarkAtStart() {
+        final int gravity = Gravity.getAbsoluteGravity(mCheckMarkGravity, getLayoutDirection());
+        final int hgrav = gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
+        return hgrav == Gravity.LEFT;
+    }
+
     @Override
     protected void onDraw(Canvas canvas) {
         super.onDraw(canvas);
@@ -347,13 +357,13 @@
                     break;
             }
             
-            final boolean isLayoutRtl = isLayoutRtl();
+            final boolean checkMarkAtStart = isCheckMarkAtStart();
             final int width = getWidth();
             final int top = y;
             final int bottom = top + height;
             final int left;
             final int right;
-            if (isLayoutRtl) {
+            if (checkMarkAtStart) {
                 left = mBasePadding;
                 right = left + mCheckMarkWidth;
             } else {
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 682f2ae..8b97329 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -833,6 +833,10 @@
     public void setChecked(boolean checked) {
         super.setChecked(checked);
 
+        // Calling the super method may result in setChecked() getting called
+        // recursively with a different value, so load the REAL value...
+        checked = isChecked();
+
         if (isAttachedToWindow() && isLaidOut()) {
             animateThumbToCheckedState(checked);
         } else {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index b162e54..a536b2d 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -8392,6 +8392,15 @@
             }
         }
 
+        // Check for known input filter types.
+        final int numFilters = mFilters.length;
+        for (int i = 0; i < numFilters; i++) {
+            final InputFilter filter = mFilters[i];
+            if (filter instanceof InputFilter.LengthFilter) {
+                info.setMaxTextLength(((InputFilter.LengthFilter) filter).getMax());
+            }
+        }
+
         if (!isSingleLine()) {
             info.setMultiLine(true);
         }
diff --git a/core/java/com/android/internal/policy/IKeyguardService.aidl b/core/java/com/android/internal/policy/IKeyguardService.aidl
index a5421f5..64f3bea 100644
--- a/core/java/com/android/internal/policy/IKeyguardService.aidl
+++ b/core/java/com/android/internal/policy/IKeyguardService.aidl
@@ -65,4 +65,10 @@
      * @param fadeoutDuration the duration of the exit animation, in milliseconds
      */
     oneway void startKeyguardExitAnimation(long startTime, long fadeoutDuration);
+
+    /**
+     * Notifies the Keyguard that the activity that was starting has now been drawn and it's safe
+     * to start the keyguard dismiss sequence.
+     */
+    oneway void onActivityDrawn();
 }
diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java
index 9e24844..254f602 100644
--- a/core/java/com/android/internal/widget/ActionBarContainer.java
+++ b/core/java/com/android/internal/widget/ActionBarContainer.java
@@ -253,7 +253,7 @@
         return null;
     }
 
-    private boolean isCollapsed(View view) {
+    private static boolean isCollapsed(View view) {
         return view == null || view.getVisibility() == GONE || view.getMeasuredHeight() == 0;
     }
 
@@ -326,35 +326,33 @@
      * projection surfaces.
      */
     private class ActionBarBackgroundDrawable extends Drawable {
-        private Drawable getDrawable() {
+        @Override
+        public void draw(Canvas canvas) {
             if (mIsSplit) {
                 if (mSplitBackground != null) {
-                    return mSplitBackground;
+                    mSplitBackground.draw(canvas);
                 }
             } else {
                 if (mBackground != null) {
-                    return mBackground;
+                    mBackground.draw(canvas);
                 }
                 if (mStackedBackground != null && mIsStacked) {
-                    return mStackedBackground;
+                    mStackedBackground.draw(canvas);
                 }
             }
-            return null;
-        }
-
-        @Override
-        public void draw(Canvas canvas) {
-            final Drawable drawable = getDrawable();
-            if (drawable != null) {
-                drawable.draw(canvas);
-            }
         }
 
         @Override
         public void getOutline(@NonNull Outline outline) {
-            final Drawable drawable = getDrawable();
-            if (drawable != null) {
-                drawable.getOutline(outline);
+            if (mIsSplit) {
+                if (mSplitBackground != null) {
+                    mSplitBackground.getOutline(outline);
+                }
+            } else {
+                // ignore the stacked background for shadow casting
+                if (mBackground != null) {
+                    mBackground.getOutline(outline);
+                }
             }
         }
 
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 7e8d828..ece3e9d 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -18,7 +18,6 @@
 
 import android.Manifest;
 import android.app.ActivityManagerNative;
-import android.app.AlarmClockInfo;
 import android.app.AlarmManager;
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.TrustManager;
@@ -1169,7 +1168,7 @@
      * @return A formatted string of the next alarm (for showing on the lock screen),
      *   or null if there is no next alarm.
      */
-    public AlarmClockInfo getNextAlarm() {
+    public AlarmManager.AlarmClockInfo getNextAlarm() {
         AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
         return alarmManager.getNextAlarmClock(UserHandle.USER_CURRENT);
     }
diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
index eaadfb2..a728455 100644
--- a/core/jni/android_hardware_camera2_DngCreator.cpp
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -428,7 +428,7 @@
 
 status_t InputStripSource::writeToStream(Output& stream, uint32_t count) {
     status_t err = OK;
-    uint32_t fullSize = mRowStride * mHeight;
+    uint32_t fullSize = mWidth * mHeight * mBytesPerSample * mSamplesPerPixel;
     jlong offset = mOffset;
 
     if (fullSize != count) {
@@ -560,7 +560,7 @@
 DirectStripSource::~DirectStripSource() {}
 
 status_t DirectStripSource::writeToStream(Output& stream, uint32_t count) {
-    uint32_t fullSize = mRowStride * mHeight;
+    uint32_t fullSize = mWidth * mHeight * mBytesPerSample * mSamplesPerPixel;
 
     if (fullSize != count) {
         ALOGE("%s: Amount to write %u doesn't match image size %u", __FUNCTION__, count,
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ff483ce..931d1c6 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1852,7 +1852,8 @@
         android:description="@string/permdesc_manageCaCertificates" />
 
     <!-- @SystemApi Allows an application to do certain operations needed for
-         interacting with the recovery (system update) system. -->
+         interacting with the recovery (system update) system.
+         @hide -->
     <permission android:name="android.permission.RECOVERY"
         android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
         android:protectionLevel="signature|system"
diff --git a/core/res/res/anim/lock_screen_behind_enter_fade_in.xml b/core/res/res/anim/lock_screen_behind_enter_fade_in.xml
new file mode 100644
index 0000000..94e40a8
--- /dev/null
+++ b/core/res/res/anim/lock_screen_behind_enter_fade_in.xml
@@ -0,0 +1,27 @@
+<?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
+  -->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+    android:background="#ff000000"
+    android:detachWallpaper="true"
+    android:shareInterpolator="false"
+    android:interpolator="@interpolator/linear"
+    android:fromAlpha="0" android:toAlpha="1"
+    android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+    android:duration="250"
+    android:startOffset="100">
+</alpha>
\ No newline at end of file
diff --git a/core/res/res/anim/lock_screen_behind_enter_wallpaper.xml b/core/res/res/anim/lock_screen_behind_enter_wallpaper.xml
index 09d8001..ce974dc 100644
--- a/core/res/res/anim/lock_screen_behind_enter_wallpaper.xml
+++ b/core/res/res/anim/lock_screen_behind_enter_wallpaper.xml
@@ -22,15 +22,8 @@
         android:fillEnabled="true" android:fillBefore="true"
         android:interpolator="@interpolator/decelerate_quint"
         android:duration="400"/>
-    <scale
-        android:fromXScale="0.94" android:toXScale="1.0"
-        android:fromYScale="0.94" android:toYScale="1.0"
-        android:pivotX="50%" android:pivotY="100%"
-        android:fillEnabled="true" android:fillBefore="true"
-        android:interpolator="@interpolator/decelerate_quint"
-        android:duration="400" />
 
-    <translate android:fromYDelta="5%" android:toYDelta="0"
+    <translate android:fromYDelta="11%" android:toYDelta="0"
         android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
         android:interpolator="@interpolator/decelerate_quint"
         android:duration="300" />
diff --git a/core/res/res/anim/wallpaper_close_enter.xml b/core/res/res/anim/wallpaper_close_enter.xml
index 981923a..a189813 100644
--- a/core/res/res/anim/wallpaper_close_enter.xml
+++ b/core/res/res/anim/wallpaper_close_enter.xml
@@ -18,15 +18,17 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:shareInterpolator="false" android:zAdjustment="top">
-    <scale android:fromXScale=".2" android:toXScale="1.0"
-            android:fromYScale=".2" android:toYScale="1.0"
-            android:pivotX="50%p" android:pivotY="50%p"
-            android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
-            android:interpolator="@interpolator/decelerate_cubic"
-            android:duration="300" />
+    android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="top">
+
     <alpha android:fromAlpha="0" android:toAlpha="1.0"
-            android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
-            android:interpolator="@interpolator/decelerate_cubic"
-            android:duration="300"/>
+        android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+        android:interpolator="@interpolator/decelerate_quart"
+        android:startOffset="300"
+        android:duration="167"/>
+
+    <translate android:fromYDelta="110%" android:toYDelta="0"
+        android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+        android:interpolator="@interpolator/decelerate_quint"
+        android:startOffset="300"
+        android:duration="417" />
 </set>
\ No newline at end of file
diff --git a/core/res/res/anim/wallpaper_close_exit.xml b/core/res/res/anim/wallpaper_close_exit.xml
index a91eb49..12b31aef 100644
--- a/core/res/res/anim/wallpaper_close_exit.xml
+++ b/core/res/res/anim/wallpaper_close_exit.xml
@@ -20,5 +20,5 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:detachWallpaper="true" android:shareInterpolator="false" android:zAdjustment="normal">
     <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
-            android:duration="300" />
+            android:duration="417" />
 </set>
\ No newline at end of file
diff --git a/core/res/res/layout/notification_material_action.xml b/core/res/res/layout/notification_material_action.xml
index 7ccaad5..8f8c4fb 100644
--- a/core/res/res/layout/notification_material_action.xml
+++ b/core/res/res/layout/notification_material_action.xml
@@ -21,11 +21,12 @@
     android:layout_width="0dp"
     android:layout_height="48dp"
     android:layout_weight="1"
+    android:layout_margin="0dp"
     android:gravity="start|center_vertical"
     android:drawablePadding="8dp"
     android:paddingStart="8dp"
     android:textColor="#555555"
-    android:textSize="14dp"
+    android:textSize="@dimen/notification_text_size"
     android:singleLine="true"
     android:ellipsize="end"
     />
diff --git a/core/res/res/layout/notification_material_action_tombstone.xml b/core/res/res/layout/notification_material_action_tombstone.xml
index 8bf456e..976448b 100644
--- a/core/res/res/layout/notification_material_action_tombstone.xml
+++ b/core/res/res/layout/notification_material_action_tombstone.xml
@@ -25,7 +25,7 @@
     android:drawablePadding="8dp"
     android:paddingStart="8dp"
     android:textColor="#555555"
-    android:textSize="14dp"
+    android:textSize="@dimen/notification_text_size"
     android:singleLine="true"
     android:ellipsize="end"
     android:alpha="0.5"
diff --git a/core/res/res/layout/notification_template_material_base.xml b/core/res/res/layout/notification_template_material_base.xml
index ab13b98..5e51db9 100644
--- a/core/res/res/layout/notification_template_material_base.xml
+++ b/core/res/res/layout/notification_template_material_base.xml
@@ -29,106 +29,27 @@
         />
     <LinearLayout
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-
-        android:layout_gravity="fill_vertical"
+        android:layout_height="match_parent"
+        android:layout_gravity="top"
+        android:layout_marginEnd="8dp"
         android:layout_marginStart="@dimen/notification_large_icon_width"
         android:minHeight="@dimen/notification_large_icon_height"
         android:orientation="vertical"
-        android:paddingEnd="8dp"
-        android:paddingTop="2dp"
-        android:paddingBottom="2dp"
-        android:gravity="top"
         >
-        <LinearLayout
-            android:id="@+id/line1"
+        <include layout="@layout/notification_template_part_line1"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:paddingTop="6dp"
-            android:layout_marginStart="8dp"
-            android:orientation="horizontal"
-            >
-            <TextView android:id="@+id/title"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Title"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:singleLine="true"
-                android:ellipsize="marquee"
-                android:fadingEdge="horizontal"
-                android:layout_weight="1"
-                />
-            <ViewStub android:id="@+id/time"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_weight="0"
-                android:visibility="gone"
-                android:layout="@layout/notification_template_part_time"
-                />
-            <ViewStub android:id="@+id/chronometer"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_weight="0"
-                android:visibility="gone"
-                android:layout="@layout/notification_template_part_chronometer"
-                />
-        </LinearLayout>
-        <TextView android:id="@+id/text2"
-            android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Line2"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="-2dp"
-            android:layout_marginBottom="-2dp"
-            android:layout_marginStart="8dp"
-            android:singleLine="true"
-            android:fadingEdge="horizontal"
-            android:ellipsize="marquee"
-            android:visibility="gone"
+            android:layout_weight="1"
             />
-        <ProgressBar
-            android:id="@android:id/progress"
-            android:layout_width="match_parent"
-            android:layout_height="12dp"
-            android:layout_marginStart="8dp"
-            android:visibility="gone"
-            style="@style/Widget.StatusBar.Material.ProgressBar"
-            />
-        <LinearLayout
-            android:id="@+id/line3"
+        <include layout="@layout/notification_template_part_line2"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:orientation="horizontal"
-            android:gravity="center_vertical"
-            android:layout_marginStart="8dp"
-            >
-            <TextView android:id="@+id/text"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:layout_gravity="center"
-                android:singleLine="true"
-                android:ellipsize="marquee"
-                android:fadingEdge="horizontal"
-                />
-            <TextView android:id="@+id/info"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Info"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center"
-                android:layout_weight="0"
-                android:singleLine="true"
-                android:gravity="center"
-                android:paddingStart="8dp"
-                />
-            <ImageView android:id="@+id/profile_icon"
-                android:layout_width="24dp"
-                android:layout_height="24dp"
-                android:layout_gravity="center"
-                android:layout_weight="0"
-                android:layout_marginStart="8dp"
-                android:scaleType="centerInside"
-                android:visibility="gone"
-                />
-        </LinearLayout>
+            android:layout_weight="1"
+            />
+        <include layout="@layout/notification_template_part_line3"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            />
     </LinearLayout>
 </FrameLayout>
diff --git a/core/res/res/layout/notification_template_material_big_base.xml b/core/res/res/layout/notification_template_material_big_base.xml
index 0564a8f..2243a09 100644
--- a/core/res/res/layout/notification_template_material_big_base.xml
+++ b/core/res/res/layout/notification_template_material_big_base.xml
@@ -30,124 +30,24 @@
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_gravity="fill_vertical"
+        android:layout_gravity="top"
+        android:layout_marginEnd="8dp"
+        android:layout_marginStart="@dimen/notification_large_icon_width"
         android:minHeight="@dimen/notification_large_icon_height"
         android:orientation="vertical"
-        android:gravity="top"
         >
-        <LinearLayout
+        <include layout="@layout/notification_template_part_line1" />
+        <include layout="@layout/notification_template_part_line2" />
+        <TextView android:id="@+id/big_text"
+            android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginStart="@dimen/notification_large_icon_width"
             android:minHeight="@dimen/notification_large_icon_height"
-            android:paddingTop="2dp"
-            android:orientation="vertical"
-            >
-            <LinearLayout
-                android:id="@+id/line1"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:paddingTop="6dp"
-                android:layout_marginEnd="8dp"
-                android:layout_marginStart="8dp"
-                android:orientation="horizontal"
-                >
-                <TextView android:id="@+id/title"
-                    android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Title"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:singleLine="true"
-                    android:ellipsize="marquee"
-                    android:fadingEdge="horizontal"
-                    android:layout_weight="1"
-                    />
-                <ViewStub android:id="@+id/time"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_weight="0"
-                    android:visibility="gone"
-                    android:layout="@layout/notification_template_part_time"
-                    />
-                <ViewStub android:id="@+id/chronometer"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_weight="0"
-                    android:visibility="gone"
-                    android:layout="@layout/notification_template_part_chronometer"
-                    />
-            </LinearLayout>
-            <TextView android:id="@+id/text2"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Line2"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="-2dp"
-                android:layout_marginBottom="-2dp"
-                android:layout_marginStart="8dp"
-                android:layout_marginEnd="8dp"
-                android:singleLine="true"
-                android:fadingEdge="horizontal"
-                android:ellipsize="marquee"
-                android:visibility="gone"
-                />
-            <TextView android:id="@+id/big_text"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginStart="8dp"
-                android:layout_marginEnd="8dp"
-                android:singleLine="false"
-                android:visibility="gone"
-                />
-            <LinearLayout
-                android:id="@+id/line3"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginStart="8dp"
-                android:layout_marginEnd="8dp"
-                android:orientation="horizontal"
-                android:gravity="center_vertical"
-                >
-                <TextView android:id="@+id/text"
-                    android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
-                    android:layout_width="0dp"
-                    android:layout_height="wrap_content"
-                    android:layout_weight="1"
-                    android:layout_gravity="center"
-                    android:singleLine="true"
-                    android:ellipsize="marquee"
-                    android:fadingEdge="horizontal"
-                    />
-                <TextView android:id="@+id/info"
-                    android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Info"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="center"
-                    android:layout_weight="0"
-                    android:singleLine="true"
-                    android:gravity="center"
-                    android:paddingStart="8dp"
-                    />
-                <ImageView android:id="@+id/profile_icon"
-                    android:layout_width="24dp"
-                    android:layout_height="24dp"
-                    android:layout_gravity="center"
-                    android:layout_weight="0"
-                    android:layout_marginStart="8dp"
-                    android:scaleType="centerInside"
-                    android:visibility="gone"
-                    />
-            </LinearLayout>
-            <ProgressBar
-                android:id="@android:id/progress"
-                android:layout_width="match_parent"
-                android:layout_height="12dp"
-                android:layout_marginBottom="8dp"
-                android:layout_marginStart="8dp"
-                android:layout_marginEnd="8dp"
-                android:visibility="gone"
-                style="@style/Widget.StatusBar.Material.ProgressBar"
-                />
-        </LinearLayout>
+            android:layout_weight="1"
+            android:singleLine="false"
+            android:visibility="gone"
+            />
+        <include layout="@layout/notification_template_part_line3" />
         <ImageView
             android:layout_width="match_parent"
             android:layout_height="1dp"
@@ -156,9 +56,10 @@
             android:background="@drawable/list_divider_holo_light" />
         <include
             layout="@layout/notification_material_action_list"
+            android:layout_marginLeft="-8dp"
+            android:layout_marginRight="-8dp"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginStart="@dimen/notification_large_icon_width"
             />
     </LinearLayout>
 </FrameLayout>
diff --git a/core/res/res/layout/notification_template_material_big_picture.xml b/core/res/res/layout/notification_template_material_big_picture.xml
index 74819fd..302e651 100644
--- a/core/res/res/layout/notification_template_material_big_picture.xml
+++ b/core/res/res/layout/notification_template_material_big_picture.xml
@@ -40,13 +40,13 @@
         />
     <include layout="@layout/notification_template_material_base"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
+        android:layout_height="64dp"
         />
   <FrameLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginTop="208dp"
-        android:paddingStart="64dp"
+        android:paddingStart="@dimen/notification_large_icon_width"
         android:layout_gravity="bottom"
         android:background="#CCEEEEEE"
         >
diff --git a/core/res/res/layout/notification_template_material_big_text.xml b/core/res/res/layout/notification_template_material_big_text.xml
deleted file mode 100644
index 1de5add..0000000
--- a/core/res/res/layout/notification_template_material_big_text.xml
+++ /dev/null
@@ -1,179 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2014 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License
-  -->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
-    android:id="@+id/status_bar_latest_event_content"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    internal:layout_minHeight="65dp"
-    internal:layout_maxHeight="unbounded"
-    >
-    <include layout="@layout/notification_template_icon_group"
-        android:layout_width="@dimen/notification_large_icon_width"
-        android:layout_height="@dimen/notification_large_icon_height"
-        />
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_gravity="fill_vertical"
-        android:layout_marginStart="@dimen/notification_large_icon_width"
-        android:orientation="vertical"
-        android:paddingTop="0dp"
-        android:paddingBottom="2dp"
-        android:gravity="top"
-        >
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:minHeight="@dimen/notification_large_icon_height"
-            android:orientation="vertical"
-            android:layout_marginStart="8dp"
-            android:layout_marginEnd="8dp"
-            android:layout_weight="1"
-            >
-            <LinearLayout
-                android:id="@+id/line1"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:paddingTop="8dp"
-                android:orientation="horizontal"
-                android:layout_gravity="top"
-                android:layout_weight="0"
-                >
-                <TextView android:id="@+id/title"
-                    android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Title"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:singleLine="true"
-                    android:ellipsize="marquee"
-                    android:fadingEdge="horizontal"
-                    android:layout_weight="1"
-                    />
-                <ViewStub android:id="@+id/time"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_weight="0"
-                    android:visibility="gone"
-                    android:layout="@layout/notification_template_part_time"
-                    />
-                <ViewStub android:id="@+id/chronometer"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_weight="0"
-                    android:visibility="gone"
-                    android:layout="@layout/notification_template_part_chronometer"
-                    />
-            </LinearLayout>
-            <TextView android:id="@+id/text2"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Line2"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="-2dp"
-                android:layout_marginBottom="-2dp"
-                android:layout_marginEnd="8dp"
-                android:singleLine="true"
-                android:fadingEdge="horizontal"
-                android:ellipsize="marquee"
-                android:layout_weight="0"
-                android:visibility="gone"
-                />
-            <ProgressBar
-                android:id="@android:id/progress"
-                android:layout_width="match_parent"
-                android:layout_height="12dp"
-                android:layout_marginBottom="8dp"
-                android:layout_marginEnd="8dp"
-                android:visibility="gone"
-                android:layout_weight="0"
-                style="@style/Widget.StatusBar.Material.ProgressBar"
-                />
-            <TextView android:id="@+id/big_text"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
-                android:layout_width="match_parent"
-                android:layout_height="0dp"
-                android:layout_marginBottom="10dp"
-                android:layout_marginEnd="8dp"
-                android:singleLine="false"
-                android:visibility="gone"
-                android:maxLines="8"
-                android:ellipsize="end"
-                android:layout_weight="1"
-                />
-        </LinearLayout>
-        <ImageView
-            android:layout_width="match_parent"
-            android:layout_height="1dip"
-            android:id="@+id/action_divider"
-            android:visibility="gone"
-            android:background="@drawable/list_divider_holo_light" />
-        <include
-            layout="@layout/notification_material_action_list"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:visibility="gone"
-            android:layout_weight="1"
-            />
-        <ImageView
-            android:layout_width="match_parent"
-            android:layout_height="1dp"
-            android:id="@+id/overflow_divider"
-            android:layout_marginBottom="8dp"
-            android:visibility="visible"
-            android:background="@drawable/list_divider_holo_light" />
-        <LinearLayout
-            android:id="@+id/line3"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginStart="8dp"
-            android:layout_marginBottom="8dp"
-            android:layout_marginEnd="8dp"
-            android:orientation="horizontal"
-            android:layout_weight="0"
-            android:gravity="center_vertical"
-            >
-            <TextView android:id="@+id/text"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:layout_gravity="center"
-                android:singleLine="true"
-                android:ellipsize="marquee"
-                android:fadingEdge="horizontal"
-                />
-            <TextView android:id="@+id/info"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Info"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center"
-                android:layout_weight="0"
-                android:singleLine="true"
-                android:gravity="center"
-                android:paddingStart="8dp"
-                />
-            <ImageView android:id="@+id/profile_icon"
-                android:layout_width="24dp"
-                android:layout_height="24dp"
-                android:layout_gravity="center"
-                android:layout_weight="0"
-                android:layout_marginStart="8dp"
-                android:scaleType="centerInside"
-                android:visibility="gone"
-                />
-        </LinearLayout>
-    </LinearLayout>
-</FrameLayout>
diff --git a/core/res/res/layout/notification_template_material_inbox.xml b/core/res/res/layout/notification_template_material_inbox.xml
index 8411ff5..6133791 100644
--- a/core/res/res/layout/notification_template_material_inbox.xml
+++ b/core/res/res/layout/notification_template_material_inbox.xml
@@ -30,175 +30,93 @@
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_gravity="fill_vertical"
+        android:layout_gravity="top"
         android:layout_marginStart="@dimen/notification_large_icon_width"
         android:minHeight="@dimen/notification_large_icon_height"
         android:orientation="vertical"
-        android:paddingTop="0dp"
-        android:paddingBottom="2dp"
-        android:gravity="top"
         >
-        <LinearLayout
+        <include layout="@layout/notification_template_part_line1" />
+        <include layout="@layout/notification_template_part_line2" />
+        <TextView android:id="@+id/inbox_text0"
+            android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
             android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:minHeight="@dimen/notification_large_icon_height"
-            android:paddingTop="2dp"
-            android:orientation="vertical"
-            >
-            <LinearLayout
-                android:id="@+id/line1"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginStart="8dp"
-                android:layout_marginEnd="8dp"
-                android:paddingTop="6dp"
-                android:orientation="horizontal"
-                android:layout_weight="0"
-                >
-                <TextView android:id="@+id/title"
-                    android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Title"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:singleLine="true"
-                    android:ellipsize="marquee"
-                    android:fadingEdge="horizontal"
-                    android:layout_weight="1"
-                    />
-                <ViewStub android:id="@+id/time"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_weight="0"
-                    android:visibility="gone"
-                    android:layout="@layout/notification_template_part_time"
-                    />
-                <ViewStub android:id="@+id/chronometer"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_weight="0"
-                    android:visibility="gone"
-                    android:layout="@layout/notification_template_part_chronometer"
-                    />
-            </LinearLayout>
-            <TextView android:id="@+id/text2"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Line2"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="-2dp"
-                android:layout_marginBottom="-2dp"
-                android:layout_marginStart="8dp"
-                android:layout_marginEnd="8dp"
-                android:singleLine="true"
-                android:fadingEdge="horizontal"
-                android:ellipsize="marquee"
-                android:visibility="gone"
-                android:layout_weight="0"
-                />
-            <ProgressBar
-                android:id="@android:id/progress"
-                android:layout_width="match_parent"
-                android:layout_height="12dp"
-                android:layout_marginStart="8dp"
-                android:layout_marginEnd="8dp"
-                android:visibility="gone"
-                android:layout_weight="0"
-                style="@style/Widget.Material.Light.ProgressBar.Horizontal"
-                />
-            <TextView android:id="@+id/inbox_text0"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
-                android:layout_width="match_parent"
-                android:layout_height="0dp"
-                android:layout_marginStart="8dp"
-                android:layout_marginEnd="8dp"
-                android:singleLine="true"
-                android:ellipsize="end"
-                android:visibility="gone"
-                android:layout_weight="1"
-                />
-            <TextView android:id="@+id/inbox_text1"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
-                android:layout_width="match_parent"
-                android:layout_height="0dp"
-                android:layout_marginStart="8dp"
-                android:layout_marginEnd="8dp"
-                android:singleLine="true"
-                android:ellipsize="end"
-                android:visibility="gone"
-                android:layout_weight="1"
-                />
-            <TextView android:id="@+id/inbox_text2"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
-                android:layout_width="match_parent"
-                android:layout_height="0dp"
-                android:layout_marginStart="8dp"
-                android:layout_marginEnd="8dp"
-                android:singleLine="true"
-                android:ellipsize="end"
-                android:visibility="gone"
-                android:layout_weight="1"
-                />
-            <TextView android:id="@+id/inbox_text3"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
-                android:layout_width="match_parent"
-                android:layout_height="0dp"
-                android:layout_marginStart="8dp"
-                android:layout_marginEnd="8dp"
-                android:singleLine="true"
-                android:ellipsize="end"
-                android:visibility="gone"
-                android:layout_weight="1"
-                />
-            <TextView android:id="@+id/inbox_text4"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
-                android:layout_width="match_parent"
-                android:layout_height="0dp"
-                android:layout_marginStart="8dp"
-                android:singleLine="true"
-                android:ellipsize="end"
-                android:visibility="gone"
-                android:layout_weight="1"
-                />
-            <TextView android:id="@+id/inbox_text5"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
-                android:layout_width="match_parent"
-                android:layout_height="0dp"
-                android:layout_marginStart="8dp"
-                android:layout_marginEnd="8dp"
-                android:singleLine="true"
-                android:ellipsize="end"
-                android:visibility="gone"
-                android:layout_weight="1"
-                />
-            <TextView android:id="@+id/inbox_text6"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
-                android:layout_width="match_parent"
-                android:layout_height="0dp"
-                android:layout_marginStart="8dp"
-                android:layout_marginEnd="8dp"
-                android:singleLine="true"
-                android:ellipsize="end"
-                android:visibility="gone"
-                android:layout_weight="1"
-                />
-            <TextView android:id="@+id/inbox_more"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
-                android:layout_width="match_parent"
-                android:layout_height="0dp"
-                android:layout_marginStart="8dp"
-                android:layout_marginEnd="8dp"
-                android:singleLine="true"
-                android:ellipsize="end"
-                android:visibility="gone"
-                android:layout_weight="1"
-                android:text="@android:string/ellipsis"
-                />
-            <FrameLayout
-                android:id="@+id/inbox_end_pad"
-                android:layout_width="match_parent"
-                android:layout_height="8dip"
-                android:visibility="gone"
-                android:layout_weight="0"
+            android:layout_height="0dp"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:visibility="gone"
+            android:layout_weight="1"
             />
-        </LinearLayout>
+        <TextView android:id="@+id/inbox_text1"
+            android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:visibility="gone"
+            android:layout_weight="1"
+            />
+        <TextView android:id="@+id/inbox_text2"
+            android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:visibility="gone"
+            android:layout_weight="1"
+            />
+        <TextView android:id="@+id/inbox_text3"
+            android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:visibility="gone"
+            android:layout_weight="1"
+            />
+        <TextView android:id="@+id/inbox_text4"
+            android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:visibility="gone"
+            android:layout_weight="1"
+            />
+        <TextView android:id="@+id/inbox_text5"
+            android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:visibility="gone"
+            android:layout_weight="1"
+            />
+        <TextView android:id="@+id/inbox_text6"
+            android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:visibility="gone"
+            android:layout_weight="1"
+            />
+        <TextView android:id="@+id/inbox_more"
+            android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:visibility="gone"
+            android:layout_weight="1"
+            android:text="@android:string/ellipsis"
+            />
+        <FrameLayout
+            android:id="@+id/inbox_end_pad"
+            android:layout_width="match_parent"
+            android:layout_height="8dip"
+            android:visibility="gone"
+            android:layout_weight="0"
+        />
         <ImageView
             android:layout_width="match_parent"
             android:layout_height="1dip"
@@ -209,6 +127,8 @@
             layout="@layout/notification_material_action_list"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:layout_marginLeft="-8dp"
+            android:layout_marginRight="-8dp"
             android:layout_weight="0"
             />
         <ImageView
@@ -217,47 +137,6 @@
             android:id="@+id/overflow_divider"
             android:visibility="visible"
             android:background="@drawable/list_divider_holo_light" />
-        <LinearLayout
-            android:id="@+id/line3"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="8dp"
-            android:layout_marginStart="8dp"
-            android:layout_marginBottom="8dp"
-            android:layout_marginEnd="8dp"
-            android:orientation="horizontal"
-            android:layout_weight="0"
-            android:gravity="center_vertical"
-            >
-            <TextView android:id="@+id/text"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:layout_gravity="center"
-                android:singleLine="true"
-                android:ellipsize="marquee"
-                android:fadingEdge="horizontal"
-                />
-            <TextView android:id="@+id/info"
-                android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Info"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center"
-                android:layout_weight="0"
-                android:singleLine="true"
-                android:gravity="center"
-                android:paddingStart="8dp"
-                />
-            <ImageView android:id="@+id/profile_icon"
-                android:layout_width="24dp"
-                android:layout_height="24dp"
-                android:layout_gravity="center"
-                android:layout_weight="0"
-                android:layout_marginStart="8dp"
-                android:scaleType="centerInside"
-                android:visibility="gone"
-                />
-        </LinearLayout>
+        <include layout="@layout/notification_template_part_line3" />
     </LinearLayout>
 </FrameLayout>
diff --git a/core/res/res/layout/notification_template_part_line1.xml b/core/res/res/layout/notification_template_part_line1.xml
new file mode 100644
index 0000000..d652959
--- /dev/null
+++ b/core/res/res/layout/notification_template_part_line1.xml
@@ -0,0 +1,49 @@
+<?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
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/line1"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:paddingTop="@dimen/notification_vert_pad"
+    android:layout_weight="0"
+    >
+    <TextView android:id="@+id/title"
+        android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:fadingEdge="horizontal"
+        android:layout_weight="1"
+        />
+    <ViewStub android:id="@+id/time"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_weight="0"
+        android:visibility="gone"
+        android:layout="@layout/notification_template_part_time"
+        />
+    <ViewStub android:id="@+id/chronometer"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_weight="0"
+        android:visibility="gone"
+        android:layout="@layout/notification_template_part_chronometer"
+        />
+</LinearLayout>
diff --git a/core/res/res/layout/notification_template_part_line2.xml b/core/res/res/layout/notification_template_part_line2.xml
new file mode 100644
index 0000000..1e19df1
--- /dev/null
+++ b/core/res/res/layout/notification_template_part_line2.xml
@@ -0,0 +1,40 @@
+<?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
+  -->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+    <TextView 
+        android:id="@+id/text2"
+        android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Line2"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="-2dp"
+        android:layout_marginBottom="-2dp"
+        android:singleLine="true"
+        android:fadingEdge="horizontal"
+        android:ellipsize="marquee"
+        android:visibility="gone"
+        android:layout_weight="0"
+        />
+    <ProgressBar
+        android:id="@android:id/progress"
+        android:layout_width="match_parent"
+        android:layout_height="8dp"
+        android:visibility="gone"
+        android:layout_weight="0"
+        style="@style/Widget.Material.Light.ProgressBar.Horizontal"
+        />
+</merge>
diff --git a/core/res/res/layout/notification_template_part_line3.xml b/core/res/res/layout/notification_template_part_line3.xml
new file mode 100644
index 0000000..2c8c704c
--- /dev/null
+++ b/core/res/res/layout/notification_template_part_line3.xml
@@ -0,0 +1,56 @@
+<?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
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/line3"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:layout_weight="0"
+    android:gravity="center_vertical"
+    android:paddingBottom="@dimen/notification_vert_pad"
+    >
+    <TextView android:id="@+id/text"
+        android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:layout_gravity="center"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:fadingEdge="horizontal"
+        />
+    <TextView android:id="@+id/info"
+        android:textAppearance="@style/TextAppearance.StatusBar.Material.EventContent.Info"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:layout_weight="0"
+        android:singleLine="true"
+        android:gravity="center"
+        android:paddingStart="8dp"
+        />
+    <ImageView android:id="@+id/profile_icon"
+        android:layout_width="24dp"
+        android:layout_height="24dp"
+        android:layout_gravity="center"
+        android:layout_weight="0"
+        android:layout_marginStart="8dp"
+        android:scaleType="centerInside"
+        android:visibility="gone"
+        />
+</LinearLayout>
diff --git a/core/res/res/layout/preference_widget_switch.xml b/core/res/res/layout/preference_widget_switch.xml
index 7395ff2..25e8aa6 100644
--- a/core/res/res/layout/preference_widget_switch.xml
+++ b/core/res/res/layout/preference_widget_switch.xml
@@ -21,4 +21,5 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:focusable="false"
+    android:clickable="false"
     android:background="@null" />
diff --git a/core/res/res/layout/select_dialog_multichoice_material.xml b/core/res/res/layout/select_dialog_multichoice_material.xml
index 8b4c59d..01e4cfa 100644
--- a/core/res/res/layout/select_dialog_multichoice_material.xml
+++ b/core/res/res/layout/select_dialog_multichoice_material.xml
@@ -26,4 +26,5 @@
     android:paddingStart="16dip"
     android:paddingEnd="16dip"
     android:checkMark="?android:attr/listChoiceIndicatorMultiple"
+    android:checkMarkGravity="start"
     android:ellipsize="marquee" />
diff --git a/core/res/res/layout/select_dialog_singlechoice_material.xml b/core/res/res/layout/select_dialog_singlechoice_material.xml
index 27a6648..0f3c277 100644
--- a/core/res/res/layout/select_dialog_singlechoice_material.xml
+++ b/core/res/res/layout/select_dialog_singlechoice_material.xml
@@ -26,4 +26,5 @@
     android:paddingStart="16dip"
     android:paddingEnd="16dip"
     android:checkMark="?android:attr/listChoiceIndicatorSingle"
+    android:checkMarkGravity="start"
     android:ellipsize="marquee" />
diff --git a/core/res/res/values-mcc206-mnc05/config.xml b/core/res/res/values-mcc206-mnc05/config.xml
new file mode 100644
index 0000000..a684aaa
--- /dev/null
+++ b/core/res/res/values-mcc206-mnc05/config.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>20610</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc206-mnc10/config.xml b/core/res/res/values-mcc206-mnc10/config.xml
new file mode 100644
index 0000000..5c96317
--- /dev/null
+++ b/core/res/res/values-mcc206-mnc10/config.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>20605</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc208-mnc10/config.xml b/core/res/res/values-mcc208-mnc10/config.xml
index 358bef6..10a6c5d 100644
--- a/core/res/res/values-mcc208-mnc10/config.xml
+++ b/core/res/res/values-mcc208-mnc10/config.xml
@@ -35,4 +35,28 @@
          note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" -->
     <string translatable="false" name="config_tether_apndata">SFR option modem,websfr,,,,,,,,,208,10,,DUN</string>
 
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>21401</item>
+        <item>21402</item>
+        <item>21403</item>
+        <item>21404</item>
+        <item>21405</item>
+        <item>21406</item>
+        <item>21407</item>
+        <item>21408</item>
+        <item>21409</item>
+        <item>21410</item>
+        <item>21411</item>
+        <item>21412</item>
+        <item>21413</item>
+        <item>21414</item>
+        <item>21415</item>
+        <item>21416</item>
+        <item>21417</item>
+        <item>21418</item>
+        <item>21419</item>
+        <item>21420</item>
+        <item>21421</item>
+    </string-array>
+
 </resources>
diff --git a/core/res/res/values-mcc208-mnc15/config.xml b/core/res/res/values-mcc208-mnc15/config.xml
new file mode 100644
index 0000000..32b951c
--- /dev/null
+++ b/core/res/res/values-mcc208-mnc15/config.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>20801</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc214-mnc01/config.xml b/core/res/res/values-mcc214-mnc01/config.xml
index 1b7c462..ecd8124 100644
--- a/core/res/res/values-mcc214-mnc01/config.xml
+++ b/core/res/res/values-mcc214-mnc01/config.xml
@@ -37,4 +37,27 @@
          note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" -->
     <string translatable="false" name="config_tether_apndata">INTERNET,airtelnet.es,,,vodafone,vodafone,,,,,214,01,1,DUN</string>
 
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>21402</item>
+        <item>21403</item>
+        <item>21404</item>
+        <item>21405</item>
+        <item>21406</item>
+        <item>21407</item>
+        <item>21408</item>
+        <item>21409</item>
+        <item>21410</item>
+        <item>21411</item>
+        <item>21412</item>
+        <item>21413</item>
+        <item>21414</item>
+        <item>21415</item>
+        <item>21416</item>
+        <item>21417</item>
+        <item>21418</item>
+        <item>21419</item>
+        <item>21420</item>
+        <item>21421</item>
+    </string-array>
+
 </resources>
diff --git a/core/res/res/values-mcc214-mnc02/config.xml b/core/res/res/values-mcc214-mnc02/config.xml
new file mode 100755
index 0000000..c83de57
--- /dev/null
+++ b/core/res/res/values-mcc214-mnc02/config.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+
+<resources>
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>21401</item>
+        <item>21402</item>
+        <item>21403</item>
+        <item>21404</item>
+        <item>21405</item>
+        <item>21406</item>
+        <item>21407</item>
+        <item>21408</item>
+        <item>21409</item>
+        <item>21410</item>
+        <item>21411</item>
+        <item>21412</item>
+        <item>21413</item>
+        <item>21414</item>
+        <item>21415</item>
+        <item>21416</item>
+        <item>21417</item>
+        <item>21418</item>
+        <item>21419</item>
+        <item>21420</item>
+        <item>21421</item>
+    </string-array>
+
+</resources>
diff --git a/core/res/res/values-mcc214-mnc04/config.xml b/core/res/res/values-mcc214-mnc04/config.xml
index 71301d5..6dfa87b 100644
--- a/core/res/res/values-mcc214-mnc04/config.xml
+++ b/core/res/res/values-mcc214-mnc04/config.xml
@@ -20,6 +20,25 @@
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- Don't use roaming icon for considered operators -->
     <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>21401</item>
+        <item>21402</item>
+        <item>21403</item>
+        <item>21405</item>
+        <item>21406</item>
         <item>21407</item>
+        <item>21408</item>
+        <item>21409</item>
+        <item>21410</item>
+        <item>21411</item>
+        <item>21412</item>
+        <item>21413</item>
+        <item>21414</item>
+        <item>21415</item>
+        <item>21416</item>
+        <item>21417</item>
+        <item>21418</item>
+        <item>21419</item>
+        <item>21420</item>
+        <item>21421</item>
     </string-array>
 </resources>
diff --git a/core/res/res/values-mcc214-mnc05/config.xml b/core/res/res/values-mcc214-mnc05/config.xml
new file mode 100755
index 0000000..9302b0c
--- /dev/null
+++ b/core/res/res/values-mcc214-mnc05/config.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>21401</item>
+        <item>21402</item>
+        <item>21403</item>
+        <item>21404</item>
+        <item>21406</item>
+        <item>21407</item>
+        <item>21408</item>
+        <item>21409</item>
+        <item>21410</item>
+        <item>21411</item>
+        <item>21412</item>
+        <item>21413</item>
+        <item>21414</item>
+        <item>21415</item>
+        <item>21416</item>
+        <item>21417</item>
+        <item>21418</item>
+        <item>21419</item>
+        <item>21420</item>
+        <item>21421</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc214-mnc06/config.xml b/core/res/res/values-mcc214-mnc06/config.xml
new file mode 100755
index 0000000..c3f2643
--- /dev/null
+++ b/core/res/res/values-mcc214-mnc06/config.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>21401</item>
+        <item>21402</item>
+        <item>21403</item>
+        <item>21404</item>
+        <item>21405</item>
+        <item>21407</item>
+        <item>21408</item>
+        <item>21409</item>
+        <item>21410</item>
+        <item>21411</item>
+        <item>21412</item>
+        <item>21413</item>
+        <item>21414</item>
+        <item>21415</item>
+        <item>21416</item>
+        <item>21417</item>
+        <item>21418</item>
+        <item>21419</item>
+        <item>21420</item>
+        <item>21421</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc214-mnc08/config.xml b/core/res/res/values-mcc214-mnc08/config.xml
new file mode 100755
index 0000000..5af6d5d
--- /dev/null
+++ b/core/res/res/values-mcc214-mnc08/config.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>21401</item>
+        <item>21402</item>
+        <item>21403</item>
+        <item>21404</item>
+        <item>21405</item>
+        <item>21406</item>
+        <item>21407</item>
+        <item>21409</item>
+        <item>21410</item>
+        <item>21411</item>
+        <item>21412</item>
+        <item>21413</item>
+        <item>21414</item>
+        <item>21415</item>
+        <item>21416</item>
+        <item>21417</item>
+        <item>21418</item>
+        <item>21419</item>
+        <item>21420</item>
+        <item>21421</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc214-mnc09/config.xml b/core/res/res/values-mcc214-mnc09/config.xml
new file mode 100755
index 0000000..d789771
--- /dev/null
+++ b/core/res/res/values-mcc214-mnc09/config.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>21401</item>
+        <item>21402</item>
+        <item>21403</item>
+        <item>21404</item>
+        <item>21405</item>
+        <item>21406</item>
+        <item>21407</item>
+        <item>21408</item>
+        <item>21410</item>
+        <item>21411</item>
+        <item>21412</item>
+        <item>21413</item>
+        <item>21414</item>
+        <item>21415</item>
+        <item>21416</item>
+        <item>21417</item>
+        <item>21418</item>
+        <item>21419</item>
+        <item>21420</item>
+        <item>21421</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc214-mnc10/config.xml b/core/res/res/values-mcc214-mnc10/config.xml
new file mode 100755
index 0000000..b66e1a2
--- /dev/null
+++ b/core/res/res/values-mcc214-mnc10/config.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>21401</item>
+        <item>21402</item>
+        <item>21403</item>
+        <item>21404</item>
+        <item>21405</item>
+        <item>21406</item>
+        <item>21407</item>
+        <item>21408</item>
+        <item>21409</item>
+        <item>21411</item>
+        <item>21412</item>
+        <item>21413</item>
+        <item>21414</item>
+        <item>21415</item>
+        <item>21416</item>
+        <item>21417</item>
+        <item>21418</item>
+        <item>21419</item>
+        <item>21420</item>
+        <item>21421</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc214-mnc11/config.xml b/core/res/res/values-mcc214-mnc11/config.xml
new file mode 100755
index 0000000..9fd06db
--- /dev/null
+++ b/core/res/res/values-mcc214-mnc11/config.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>21401</item>
+        <item>21402</item>
+        <item>21403</item>
+        <item>21404</item>
+        <item>21405</item>
+        <item>21406</item>
+        <item>21407</item>
+        <item>21408</item>
+        <item>21409</item>
+        <item>21410</item>
+        <item>21412</item>
+        <item>21413</item>
+        <item>21414</item>
+        <item>21415</item>
+        <item>21416</item>
+        <item>21417</item>
+        <item>21418</item>
+        <item>21419</item>
+        <item>21420</item>
+        <item>21421</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc214-mnc12/config.xml b/core/res/res/values-mcc214-mnc12/config.xml
new file mode 100755
index 0000000..7468238
--- /dev/null
+++ b/core/res/res/values-mcc214-mnc12/config.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>21401</item>
+        <item>21402</item>
+        <item>21403</item>
+        <item>21404</item>
+        <item>21405</item>
+        <item>21406</item>
+        <item>21407</item>
+        <item>21408</item>
+        <item>21409</item>
+        <item>21410</item>
+        <item>21411</item>
+        <item>21413</item>
+        <item>21414</item>
+        <item>21415</item>
+        <item>21416</item>
+        <item>21417</item>
+        <item>21418</item>
+        <item>21419</item>
+        <item>21420</item>
+        <item>21421</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc214-mnc13/config.xml b/core/res/res/values-mcc214-mnc13/config.xml
new file mode 100755
index 0000000..35ff4ae
--- /dev/null
+++ b/core/res/res/values-mcc214-mnc13/config.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>21401</item>
+        <item>21402</item>
+        <item>21403</item>
+        <item>21404</item>
+        <item>21405</item>
+        <item>21406</item>
+        <item>21407</item>
+        <item>21408</item>
+        <item>21409</item>
+        <item>21410</item>
+        <item>21411</item>
+        <item>21412</item>
+        <item>21414</item>
+        <item>21415</item>
+        <item>21416</item>
+        <item>21417</item>
+        <item>21418</item>
+        <item>21419</item>
+        <item>21420</item>
+        <item>21421</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc214-mnc14/config.xml b/core/res/res/values-mcc214-mnc14/config.xml
new file mode 100755
index 0000000..b6a7440
--- /dev/null
+++ b/core/res/res/values-mcc214-mnc14/config.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>21401</item>
+        <item>21402</item>
+        <item>21403</item>
+        <item>21404</item>
+        <item>21405</item>
+        <item>21406</item>
+        <item>21407</item>
+        <item>21408</item>
+        <item>21409</item>
+        <item>21410</item>
+        <item>21411</item>
+        <item>21412</item>
+        <item>21413</item>
+        <item>21415</item>
+        <item>21416</item>
+        <item>21417</item>
+        <item>21418</item>
+        <item>21419</item>
+        <item>21420</item>
+        <item>21421</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc214-mnc15/config.xml b/core/res/res/values-mcc214-mnc15/config.xml
new file mode 100755
index 0000000..8296410
--- /dev/null
+++ b/core/res/res/values-mcc214-mnc15/config.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>21401</item>
+        <item>21402</item>
+        <item>21403</item>
+        <item>21404</item>
+        <item>21405</item>
+        <item>21406</item>
+        <item>21407</item>
+        <item>21408</item>
+        <item>21409</item>
+        <item>21410</item>
+        <item>21411</item>
+        <item>21412</item>
+        <item>21413</item>
+        <item>21414</item>
+        <item>21416</item>
+        <item>21417</item>
+        <item>21418</item>
+        <item>21419</item>
+        <item>21420</item>
+        <item>21421</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc214-mnc16/config.xml b/core/res/res/values-mcc214-mnc16/config.xml
new file mode 100755
index 0000000..1aaf577
--- /dev/null
+++ b/core/res/res/values-mcc214-mnc16/config.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>21401</item>
+        <item>21402</item>
+        <item>21403</item>
+        <item>21404</item>
+        <item>21405</item>
+        <item>21406</item>
+        <item>21407</item>
+        <item>21408</item>
+        <item>21409</item>
+        <item>21410</item>
+        <item>21411</item>
+        <item>21412</item>
+        <item>21413</item>
+        <item>21414</item>
+        <item>21415</item>
+        <item>21417</item>
+        <item>21418</item>
+        <item>21419</item>
+        <item>21420</item>
+        <item>21421</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc214-mnc17/config.xml b/core/res/res/values-mcc214-mnc17/config.xml
new file mode 100755
index 0000000..be92a32
--- /dev/null
+++ b/core/res/res/values-mcc214-mnc17/config.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>21401</item>
+        <item>21402</item>
+        <item>21403</item>
+        <item>21404</item>
+        <item>21405</item>
+        <item>21406</item>
+        <item>21407</item>
+        <item>21408</item>
+        <item>21409</item>
+        <item>21410</item>
+        <item>21411</item>
+        <item>21412</item>
+        <item>21413</item>
+        <item>21414</item>
+        <item>21415</item>
+        <item>21416</item>
+        <item>21418</item>
+        <item>21419</item>
+        <item>21420</item>
+        <item>21421</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc214-mnc18/config.xml b/core/res/res/values-mcc214-mnc18/config.xml
new file mode 100755
index 0000000..078d7e2
--- /dev/null
+++ b/core/res/res/values-mcc214-mnc18/config.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>21401</item>
+        <item>21402</item>
+        <item>21403</item>
+        <item>21404</item>
+        <item>21405</item>
+        <item>21406</item>
+        <item>21407</item>
+        <item>21408</item>
+        <item>21409</item>
+        <item>21410</item>
+        <item>21411</item>
+        <item>21412</item>
+        <item>21413</item>
+        <item>21414</item>
+        <item>21415</item>
+        <item>21416</item>
+        <item>21417</item>
+        <item>21419</item>
+        <item>21420</item>
+        <item>21421</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc214-mnc19/config.xml b/core/res/res/values-mcc214-mnc19/config.xml
new file mode 100755
index 0000000..d194687
--- /dev/null
+++ b/core/res/res/values-mcc214-mnc19/config.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>21401</item>
+        <item>21402</item>
+        <item>21403</item>
+        <item>21404</item>
+        <item>21405</item>
+        <item>21406</item>
+        <item>21407</item>
+        <item>21408</item>
+        <item>21409</item>
+        <item>21410</item>
+        <item>21411</item>
+        <item>21412</item>
+        <item>21413</item>
+        <item>21414</item>
+        <item>21415</item>
+        <item>21416</item>
+        <item>21417</item>
+        <item>21418</item>
+        <item>21420</item>
+        <item>21421</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc214-mnc20/config.xml b/core/res/res/values-mcc214-mnc20/config.xml
new file mode 100755
index 0000000..6aaf970
--- /dev/null
+++ b/core/res/res/values-mcc214-mnc20/config.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>21401</item>
+        <item>21402</item>
+        <item>21403</item>
+        <item>21404</item>
+        <item>21405</item>
+        <item>21406</item>
+        <item>21407</item>
+        <item>21408</item>
+        <item>21409</item>
+        <item>21410</item>
+        <item>21411</item>
+        <item>21412</item>
+        <item>21413</item>
+        <item>21414</item>
+        <item>21415</item>
+        <item>21416</item>
+        <item>21417</item>
+        <item>21418</item>
+        <item>21419</item>
+        <item>21421</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc214-mnc21/config.xml b/core/res/res/values-mcc214-mnc21/config.xml
new file mode 100755
index 0000000..f890b14
--- /dev/null
+++ b/core/res/res/values-mcc214-mnc21/config.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>21401</item>
+        <item>21402</item>
+        <item>21403</item>
+        <item>21404</item>
+        <item>21405</item>
+        <item>21406</item>
+        <item>21407</item>
+        <item>21408</item>
+        <item>21409</item>
+        <item>21410</item>
+        <item>21411</item>
+        <item>21412</item>
+        <item>21413</item>
+        <item>21414</item>
+        <item>21415</item>
+        <item>21416</item>
+        <item>21417</item>
+        <item>21418</item>
+        <item>21419</item>
+        <item>21420</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc222-mnc10/config.xml b/core/res/res/values-mcc222-mnc10/config.xml
index 24dd71c..67467a0 100644
--- a/core/res/res/values-mcc222-mnc10/config.xml
+++ b/core/res/res/values-mcc222-mnc10/config.xml
@@ -35,4 +35,29 @@
          "name,apn,proxy,port,username,password,server,mmsc,mmsproxy,mmsport,mcc,mnc,auth,type"
          note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" -->
     <string translatable="false" name="config_tether_apndata">Tethering Internet,web.omnitel.it,,,,,,,,,222,10,,DUN</string>
+
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>21401</item>
+        <item>21402</item>
+        <item>21403</item>
+        <item>21404</item>
+        <item>21405</item>
+        <item>21406</item>
+        <item>21407</item>
+        <item>21408</item>
+        <item>21409</item>
+        <item>21410</item>
+        <item>21411</item>
+        <item>21412</item>
+        <item>21413</item>
+        <item>21414</item>
+        <item>21415</item>
+        <item>21416</item>
+        <item>21417</item>
+        <item>21418</item>
+        <item>21419</item>
+        <item>21420</item>
+        <item>21421</item>
+    </string-array>
+
 </resources>
diff --git a/core/res/res/values-mcc234-mnc10/config.xml b/core/res/res/values-mcc234-mnc10/config.xml
new file mode 100644
index 0000000..b704d3f
--- /dev/null
+++ b/core/res/res/values-mcc234-mnc10/config.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>23420</item>
+        <item>23426</item>
+        <item>23430</item>
+        <item>23431</item>
+        <item>23432</item>
+        <item>23433</item>
+        <item>23434</item>
+        <item>23486</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc234-mnc20/config.xml b/core/res/res/values-mcc234-mnc20/config.xml
index d602c9f..1ed53dc 100644
--- a/core/res/res/values-mcc234-mnc20/config.xml
+++ b/core/res/res/values-mcc234-mnc20/config.xml
@@ -24,5 +24,15 @@
     <!-- Configure mobile network MTU. Carrier specific value is set here.
     -->
     <integer name="config_mobile_mtu">1440</integer>
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>23410</item>
+        <item>23426</item>
+        <item>23430</item>
+        <item>23431</item>
+        <item>23432</item>
+        <item>23433</item>
+        <item>23434</item>
+        <item>23486</item>
+    </string-array>
 
 </resources>
diff --git a/core/res/res/values-mcc234-mnc26/config.xml b/core/res/res/values-mcc234-mnc26/config.xml
new file mode 100644
index 0000000..8d259de
--- /dev/null
+++ b/core/res/res/values-mcc234-mnc26/config.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>23410</item>
+        <item>23420</item>
+        <item>23430</item>
+        <item>23431</item>
+        <item>23432</item>
+        <item>23433</item>
+        <item>23434</item>
+        <item>23486</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc220/config.xml b/core/res/res/values-mcc302-mnc220/config.xml
new file mode 100644
index 0000000..5259152
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc220/config.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>302370</item>
+        <item>302610</item>
+        <item>302660</item>
+        <item>302720</item>
+        <item>302780</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370/config.xml b/core/res/res/values-mcc302-mnc370/config.xml
index 4fb2232..9cfe31f 100644
--- a/core/res/res/values-mcc302-mnc370/config.xml
+++ b/core/res/res/values-mcc302-mnc370/config.xml
@@ -40,4 +40,12 @@
     -->
     <integer name="config_mobile_mtu">1410</integer>
 
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>302220</item>
+        <item>302610</item>
+        <item>302660</item>
+        <item>302720</item>
+        <item>302780</item>
+    </string-array>
+
 </resources>
diff --git a/core/res/res/values-mcc302-mnc660/config.xml b/core/res/res/values-mcc302-mnc660/config.xml
index 76f7968..000f897 100644
--- a/core/res/res/values-mcc302-mnc660/config.xml
+++ b/core/res/res/values-mcc302-mnc660/config.xml
@@ -40,4 +40,12 @@
     -->
     <integer name="config_mobile_mtu">1430</integer>
 
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>302220</item>
+        <item>302370</item>
+        <item>302610</item>
+        <item>302720</item>
+        <item>302780</item>
+    </string-array>
+
 </resources>
diff --git a/core/res/res/values-mcc302-mnc720/config.xml b/core/res/res/values-mcc302-mnc720/config.xml
index 4eceffc..dfc58fe 100644
--- a/core/res/res/values-mcc302-mnc720/config.xml
+++ b/core/res/res/values-mcc302-mnc720/config.xml
@@ -40,4 +40,12 @@
     -->
     <integer name="config_mobile_mtu">1430</integer>
 
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>302220</item>
+        <item>302370</item>
+        <item>302610</item>
+        <item>302660</item>
+        <item>302780</item>
+    </string-array>
+
 </resources>
diff --git a/core/res/res/values-mcc310-mnc150/config.xml b/core/res/res/values-mcc310-mnc150/config.xml
new file mode 100644
index 0000000..f1936f4
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc150/config.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Show roaming icon though same named operators. -->
+    <string-array translatable="false" name="config_sameNamedOperatorConsideredRoaming">
+        <item>310110</item>
+        <item>310140</item>
+        <item>310400</item>
+        <item>310470</item>
+    </string-array>
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>311</item>
+        <item>312</item>
+        <item>313</item>
+        <item>314</item>
+        <item>315</item>
+        <item>316</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc170 b/core/res/res/values-mcc310-mnc170
new file mode 120000
index 0000000..cfced17
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc170
@@ -0,0 +1 @@
+./values-mcc310-mnc150
\ No newline at end of file
diff --git a/core/res/res/values-mcc310-mnc380 b/core/res/res/values-mcc310-mnc380
new file mode 120000
index 0000000..cfced17
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc380
@@ -0,0 +1 @@
+./values-mcc310-mnc150
\ No newline at end of file
diff --git a/core/res/res/values-mcc310-mnc410/config.xml b/core/res/res/values-mcc310-mnc410/config.xml
index 73aa1ce..c7ae8c8 100644
--- a/core/res/res/values-mcc310-mnc410/config.xml
+++ b/core/res/res/values-mcc310-mnc410/config.xml
@@ -24,5 +24,20 @@
     <!-- Configure mobile network MTU. Carrier specific value is set here.
     -->
     <integer name="config_mobile_mtu">1410</integer>
-
+    <!-- Show roaming icon though same named operators. -->
+    <string-array translatable="false" name="config_sameNamedOperatorConsideredRoaming">
+        <item>310110</item>
+        <item>310140</item>
+        <item>310400</item>
+        <item>310470</item>
+    </string-array>
+    <!-- BEGIN Motorola, xnk746, Feb-12-2014, IKVPREL2KK-1468 -->
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>311</item>
+        <item>312</item>
+        <item>313</item>
+        <item>314</item>
+        <item>315</item>
+        <item>316</item>
+    </string-array>
 </resources>
diff --git a/core/res/res/values-mcc340-mnc01/config.xml b/core/res/res/values-mcc340-mnc01/config.xml
index bbab4ad..bb491ed 100644
--- a/core/res/res/values-mcc340-mnc01/config.xml
+++ b/core/res/res/values-mcc340-mnc01/config.xml
@@ -35,4 +35,10 @@
          "name,apn,proxy,port,username,password,server,mmsc,mmsproxy,mmsport,mcc,mnc,auth,type"
          note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" -->
     <string translatable="false" name="config_tether_apndata">Orangeweb,orangeweb,,,orange,orange,,,,,340,01,1,DUN</string>
+
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>20801</item>
+        <item>20815</item>
+    </string-array>
+
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index e81ec69..89bda82 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3163,6 +3163,17 @@
                  result to valid color values. Saturate(S + D) -->
             <enum name="add" value="16" />
         </attr>
+        <!-- Gravity for aligning a CheckedTextView's checkmark to one side or the other. -->
+        <attr name="checkMarkGravity">
+            <!-- Push object to the left of its container, not changing its size. -->
+            <flag name="left" value="0x03" />
+            <!-- Push object to the right of its container, not changing its size. -->
+            <flag name="right" value="0x05" />
+            <!-- Push object to the beginning of its container, not changing its size. -->
+            <flag name="start" value="0x00800003" />
+            <!-- Push object to the end of its container, not changing its size. -->
+            <flag name="end" value="0x00800005" />
+        </attr>
     </declare-styleable>
     <declare-styleable name="EditText">
     </declare-styleable>
@@ -6851,9 +6862,11 @@
          its {@link android.service.voice.VoiceInteractionService#SERVICE_META_DATA} meta-data entry.
          Described here are the attributes that can be included in that tag. -->
     <declare-styleable name="VoiceInteractionService">
-        <!-- The service that hosts active voice interaction sessions. -->
+        <!-- The service that hosts active voice interaction sessions.  This is required. -->
         <attr name="sessionService" format="string" />
-        <!-- The service that provides voice recognition. -->
+        <!-- The service that provides voice recognition.  This is required.  When the user
+             selects this voice interaction service, they will also be implicitly selecting
+             the component here for their recognition service. -->
         <attr name="recognitionService" format="string" />
         <attr name="settingsActivity" />
     </declare-styleable>
@@ -7274,9 +7287,8 @@
         <!-- Component name of an activity that allows the user to modify
              the settings for this service. -->
         <attr name="settingsActivity" />
-        <!-- Component name of an xml file that describes the structure of TV content ratings that
-             this service uses. -->
-        <attr name="contentRatingSystemXml" format="reference" />
+        <!-- Reference to an XML document that describes TV content rating. -->
+        <attr name="tvContentRatingDescription" format="reference" />
     </declare-styleable>
 
     <declare-styleable name="ResolverDrawerLayout">
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index bacdc3f..9d6c36d 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -42,11 +42,6 @@
     <dimen name="status_bar_icon_size">24dip</dimen>
     <!-- Size of the giant number (unread count) in the notifications -->
     <dimen name="status_bar_content_number_size">48sp</dimen>
-    <!-- Height of the system bar (combined status & navigation); used by
-         SystemUI internally, not respected by the window manager. -->
-    <dimen name="system_bar_height">@dimen/navigation_bar_height</dimen>
-    <!-- Height of notification icons in the system bar -->
-    <dimen name="system_bar_icon_size">32dip</dimen>
     <!-- Margin at the edge of the screen to ignore touch events for in the windowshade. -->
     <dimen name="status_bar_edge_ignore">5dp</dimen>
 
@@ -220,11 +215,17 @@
     <dimen name="action_bar_stacked_tab_max_width">180dp</dimen>
 
     <!-- Size of notification text (see TextAppearance.StatusBar.EventContent) -->
-    <dimen name="notification_text_size">13dp</dimen>
+    <dimen name="notification_text_size">13sp</dimen>
     <!-- Size of notification text titles (see TextAppearance.StatusBar.EventContent.Title) -->
-    <dimen name="notification_title_text_size">16dp</dimen>
+    <dimen name="notification_title_text_size">16sp</dimen>
     <!-- Size of smaller notification text (see TextAppearance.StatusBar.EventContent.Line2, Info, Time) -->
-    <dimen name="notification_subtext_size">12dp</dimen>
+    <dimen name="notification_subtext_size">12sp</dimen>
+
+    <!-- 8dp at the top/bottom of the notification view -->
+    <dimen name="notification_vert_pad">10dp</dimen>
+
+    <!-- Replacement for @dimen/notification_vert_pad when the text is large -->
+    <dimen name="notification_large_font_vert_pad">3dp</dimen>
 
     <!-- Keyguard dimensions -->
     <!-- TEMP -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 60aacf2..e894a9c 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2267,7 +2267,7 @@
   <public type="attr" name="windowReenterTransition" />
   <public type="attr" name="windowSharedElementReturnTransition" />
   <public type="attr" name="windowSharedElementReenterTransition" />
-  <public type="attr" name="contentRatingSystemXml"/>
+  <public type="attr" name="tvContentRatingDescription"/>
   <public type="attr" name="datePickerMode"/>
   <public type="attr" name="timePickerMode"/>
   <public type="attr" name="inset" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e67eae1..74992ed 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4839,24 +4839,28 @@
     <string name="day_of_week_label_typeface">sans-serif</string>
 
     <!-- Notify use that they are in Lock-to-app -->
-    <string name="lock_to_app_toast">You are in lock-to-app mode. To exit, touch and hold the Recents button</string>
+    <string name="lock_to_app_toast">To unpin this screen, touch and hold  Back and Recents at the same time.</string>
+    <!-- Notify use that they are in Lock-to-app in accessibility mode -->
+    <string name="lock_to_app_toast_accessible">To unpin this screen, touch and hold Recents.</string>
     <!-- Notify user that they are locked in lock-to-app mode -->
-    <string name="lock_to_app_toast_locked">You are in Lock-to-App mode.</string>
+    <string name="lock_to_app_toast_locked">Screen is pinned. Unpinning isn\'t allowed by your organization.</string>
     <!-- Lock-to-app dialog title. -->
-    <string name="lock_to_app_title">Use lock-to-app?</string>
+    <string name="lock_to_app_title">Use screen pinning?</string>
     <!-- Lock-to-app dialog description. -->
-    <string name="lock_to_app_description">Lock-to-app locks the display in a single app.\n\nTo exit, touch and hold the Recents button.</string>
+    <string name="lock_to_app_description">Screen pinning locks the display in a single view.\n\nTo exit, touch and hold Back and Recents at the same time.</string>
+    <!-- Lock-to-app dialog description when in accessibility mode. -->
+    <string name="lock_to_app_description_accessible">Screen pinning locks the display in a single view.\n\nTo exit, touch and hold Recents.</string>
     <!-- Lock-to-app negative response. -->
     <string name="lock_to_app_negative">NO, THANKS</string>
     <!-- Lock-to-app positive response. -->
     <string name="lock_to_app_positive">START</string>
     <!-- Starting lock-to-app indication. -->
-    <string name="lock_to_app_start">Locked to app</string>
+    <string name="lock_to_app_start">Screen pinned</string>
     <!-- Exting lock-to-app indication. -->
-    <string name="lock_to_app_exit">No longer locked to app</string>
+    <string name="lock_to_app_exit">Screen unpinned</string>
 
     <!-- Lock-to-app checkbox for lock on exit -->
-    <string name="lock_to_app_use_screen_lock">Ask for %1$s before exiting</string>
+    <string name="lock_to_app_use_screen_lock">Ask for %1$s before unpinning</string>
 
     <!-- Lock-to-app unlock pin string -->
     <string name="lock_to_app_unlock_pin">PIN</string>
@@ -4867,35 +4871,35 @@
 
     <!-- Range specific TV content rating system strings for AM TV -->
     <string name="display_name_amtvrs" translatable="false">AM-TV-RS</string>
-    <string name="description_amtvrs">Range specific TV content rating system strings for Armenia</string>
+    <string name="description_amtvrs" translatable="false">Range specific TV content rating system strings for Armenia</string>
     <string name="display_name_amtvrs_y" translatable="false">Y</string>
     <string name="display_name_amtvrs_y7" translatable="false">Y7</string>
     <string name="display_name_amtvrs_ga" translatable="false">GA</string>
     <string name="display_name_amtvrs_tw" translatable="false">TW</string>
     <string name="display_name_amtvrs_t" translatable="false">T</string>
     <string name="display_name_amtvrs_a" translatable="false">A</string>
-    <string name="description_amtvrs_y">Suitable for ages 2–11</string>
-    <string name="description_amtvrs_y7">Suitable for ages 7–16</string>
-    <string name="description_amtvrs_ga">Suitable for general audiences</string>
-    <string name="description_amtvrs_tw">Suitable for teens ages 9 and up</string>
-    <string name="description_amtvrs_t">Suitable for teens ages 12 and up</string>
-    <string name="description_amtvrs_a">Suitable only for adults ages 18 and up</string>
+    <string name="description_amtvrs_y" translatable="false">Suitable for ages 2-11</string>
+    <string name="description_amtvrs_y7" translatable="false">Suitable for ages 7-16</string>
+    <string name="description_amtvrs_ga" translatable="false">Suitable for general audiences</string>
+    <string name="description_amtvrs_tw" translatable="false">Suitable for teens ages 9 and up</string>
+    <string name="description_amtvrs_t" translatable="false">Suitable for teens ages 12 and up</string>
+    <string name="description_amtvrs_a" translatable="false">Suitable only for adults ages 18 and up</string>
 
     <!-- Age specific TV content rating system strings for AM TV -->
     <string name="display_name_amtvas" translatable="false">AM-TV-AS</string>
-    <string name="description_amtvas">Age specific TV content rating system strings for Armenia</string>
+    <string name="description_amtvas" translatable="false">Age specific TV content rating system strings for Armenia</string>
     <string name="display_name_amtvas_ec" translatable="false">EC</string>
     <string name="display_name_amtvas_e" translatable="false">E</string>
     <string name="display_name_amtvas_e9" translatable="false">E9</string>
     <string name="display_name_amtvas_t" translatable="false">T</string>
     <string name="display_name_amtvas_m" translatable="false">M</string>
     <string name="display_name_amtvas_ao" translatable="false">AO</string>
-    <string name="description_amtvas_ec">Suitable for ages 2 and up</string>
-    <string name="description_amtvas_e">Suitable for ages 5 and up</string>
-    <string name="description_amtvas_e9">Suitable for ages 9 and up</string>
-    <string name="description_amtvas_t">Suitable for ages 12 and up</string>
-    <string name="description_amtvas_m">Suitable for ages 16 and up</string>
-    <string name="description_amtvas_ao">Suitable for ages 17 and up</string>
+    <string name="description_amtvas_ec" translatable="false">Suitable for ages 2 and up</string>
+    <string name="description_amtvas_e" translatable="false">Suitable for ages 5 and up</string>
+    <string name="description_amtvas_e9" translatable="false">Suitable for ages 9 and up</string>
+    <string name="description_amtvas_t" translatable="false">Suitable for ages 12 and up</string>
+    <string name="description_amtvas_m" translatable="false">Suitable for ages 16 and up</string>
+    <string name="description_amtvas_ao" translatable="false">Suitable for ages 17 and up</string>
 
     <!-- TV content rating system strings for AR TV -->
     <string name="display_name_artv" translatable="false">AR-TV</string>
@@ -4903,10 +4907,10 @@
     <string name="display_name_artv_13" translatable="false">Apto para mayores de 13 años</string>
     <string name="display_name_artv_16" translatable="false">Apto para mayores de 16 años</string>
     <string name="display_name_artv_18" translatable="false">Apto para mayores de 18 años</string>
-    <string name="description_artv_all">Suitable for all audiences. Programs may contain mild violence, language and mature situations</string>
-    <string name="description_artv_13">Suitable for ages 13 and up. Programs may contain mild to moderate language and mild violence and sexual references</string>
-    <string name="description_artv_16">Suitable for ages 16 and up. Programs may contain more intensive violence and coarse language, partial nudity and moderate sexual references</string>
-    <string name="description_artv_18">Suitable for mature audiences only. Programs contain strong violence, coarse language and explicit sexual references</string>
+    <string name="description_artv_all" translatable="false">Suitable for all audiences. Programs may contain mild violence, language and mature situations</string>
+    <string name="description_artv_13" translatable="false">Suitable for ages 13 and up. Programs may contain mild to moderate language and mild violence and sexual references</string>
+    <string name="description_artv_16" translatable="false">Suitable for ages 16 and up. Programs may contain more intensive violence and coarse language, partial nudity and moderate sexual references</string>
+    <string name="description_artv_18" translatable="false">Suitable for mature audiences only. Programs contain strong violence, coarse language and explicit sexual references</string>
 
     <!-- TV content rating system strings for AU TV -->
     <string name="display_name_autv" translatable="false">Australian TV Classification</string>
@@ -4917,13 +4921,13 @@
     <string name="display_name_autv_ma15" translatable="false">MA 15+</string>
     <string name="display_name_autv_r18" translatable="false">R 18+</string>
     <string name="display_name_autv_x18" translatable="false">X 18+</string>
-    <string name="description_autv_ctc">This has advertising approval, but is not yet classified</string>
-    <string name="description_autv_g">The content is very mild in impact, and suitable for everyone</string>
-    <string name="description_autv_pg">The content is mild in impact, but it may contain content that children find confusing or upsetting and may require the guidance or parents and guardians</string>
-    <string name="description_autv_m">The content is moderate in impact, and it is recommended for teenagers aged 15 years and over</string>
-    <string name="description_autv_ma15">The content is strong in impact, and it is legally restricted to persons 15 years and over</string>
-    <string name="description_autv_r18">The content is high in impact, and it is restricted to adults</string>
-    <string name="description_autv_x18">The content is restricted to adults. This classification is a special and legally restricted category which contains only sexually explicit content</string>
+    <string name="description_autv_ctc" translatable="false">This has advertising approval, but is not yet classified</string>
+    <string name="description_autv_g" translatable="false">The content is very mild in impact, and suitable for everyone</string>
+    <string name="description_autv_pg" translatable="false">The content is mild in impact, but it may contain content that children find confusing or upsetting and may require the guidance or parents and guardians</string>
+    <string name="description_autv_m" translatable="false">The content is moderate in impact, and it is recommended for teenagers aged 15 years and over</string>
+    <string name="description_autv_ma15" translatable="false">The content is strong in impact, and it is legally restricted to persons 15 years and over</string>
+    <string name="description_autv_r18" translatable="false">The content is high in impact, and it is restricted to adults</string>
+    <string name="description_autv_x18" translatable="false">The content is restricted to adults. This classification is a special and legally restricted category which contains only sexually explicit content</string>
 
     <!-- TV content rating system strings for BG TV -->
     <string name="display_name_bgtv" translatable="false">BG-TV</string>
@@ -4932,11 +4936,11 @@
     <string name="display_name_bgtv_c" translatable="false">C</string>
     <string name="display_name_bgtv_d" translatable="false">D</string>
     <string name="display_name_bgtv_x" translatable="false">X</string>
-    <string name="description_bgtv_a">Recommended to children. When the film confirms the ideals of humanism or popularizes the national and world cultures or contributes to upbringing children</string>
-    <string name="description_bgtv_b">No restrictive recommendations from the Committee. When the film is in no way contrary to the universal rules of morality in this country, has no restrictive recommendations from the Committee and does not fall in rating A</string>
-    <string name="description_bgtv_c">No persons under the age of 12 are admitted unless accompanied by an adult. When the film contains certain erotic scenes or scenes with drinking, taking drugs or stimulants or a few scenes of violence</string>
-    <string name="description_bgtv_d">No persons under the age of 16 are admitted. When the film contains quite a number of erotic scenes or scenes with drinking, taking drugs or stimulants or a considerable number of scenes showing violence</string>
-    <string name="description_bgtv_x">No persons under the age of 18 are admitted. When the film is naturalistically erotic or shows violence in an ostentatious manner</string>
+    <string name="description_bgtv_a" translatable="false">Recommended to children. When the film confirms the ideals of humanism or popularizes the national and world cultures or contributes to upbringing children</string>
+    <string name="description_bgtv_b" translatable="false">No restrictive recommendations from the Committee. When the film is in no way contrary to the universal rules of morality in this country, has no restrictive recommendations from the Committee and does not fall in rating A</string>
+    <string name="description_bgtv_c" translatable="false">No persons under the age of 12 are admitted unless accompanied by an adult. When the film contains certain erotic scenes or scenes with drinking, taking drugs or stimulants or a few scenes of violence</string>
+    <string name="description_bgtv_d" translatable="false">No persons under the age of 16 are admitted. When the film contains quite a number of erotic scenes or scenes with drinking, taking drugs or stimulants or a considerable number of scenes showing violence</string>
+    <string name="description_bgtv_x" translatable="false">No persons under the age of 18 are admitted. When the film is naturalistically erotic or shows violence in an ostentatious manner</string>
 
     <!-- TV content rating system strings for BR TV -->
     <string name="display_name_brtv" translatable="false">Brazil Content Rating</string>
@@ -4946,12 +4950,12 @@
     <string name="display_name_brtv_14" translatable="false">14 anos</string>
     <string name="display_name_brtv_16" translatable="false">16 anos</string>
     <string name="display_name_brtv_18" translatable="false">18 anos</string>
-    <string name="description_brtv_l">Content is suitable for all audiences</string>
-    <string name="description_brtv_10">Content suitable for viewers over the age of 10</string>
-    <string name="description_brtv_12">Content suitable for viewers over the age of 12</string>
-    <string name="description_brtv_14">Content suitable for viewers over the age of 14</string>
-    <string name="description_brtv_16">Content suitable for viewers over the age of 16</string>
-    <string name="description_brtv_18">Content suitable for viewers over the age of 18</string>
+    <string name="description_brtv_l" translatable="false">Content is suitable for all audiences</string>
+    <string name="description_brtv_10" translatable="false">Content suitable for viewers over the age of 10</string>
+    <string name="description_brtv_12" translatable="false">Content suitable for viewers over the age of 12</string>
+    <string name="description_brtv_14" translatable="false">Content suitable for viewers over the age of 14</string>
+    <string name="description_brtv_16" translatable="false">Content suitable for viewers over the age of 16</string>
+    <string name="description_brtv_18" translatable="false">Content suitable for viewers over the age of 18</string>
 
     <!-- TV content rating system strings for CA TV -->
     <string name="display_name_catv" translatable="false">Canadian TV Classification System</string>
@@ -4962,20 +4966,20 @@
     <string name="display_name_catv_pg" translatable="false">PG</string>
     <string name="display_name_catv_14" translatable="false">14+</string>
     <string name="display_name_catv_18" translatable="false">18+</string>
-    <string name="description_catv_exempt">Shows which are exempt from ratings (such as news and sports programming) will not display an on-screen rating at all</string>
-    <string name="description_catv_c">Programming suitable for children ages of 2–7 years. No profanity or sexual content of any level allowed. Contains little violence</string>
-    <string name="description_catv_c8">Suitable for children ages 8+. Low level violence and fantasy horror is allowed. No foul language is allowed, but occasional "socially offensive and discriminatory" language is allowed if in the context of the story. No sexual content of any level allowed</string>
-    <string name="description_catv_g">Suitable for general audiences. Programming suitable for the entire family with mild violence, and mild profanity and/or censored language</string>
-    <string name="description_catv_pg">Parental guidance. Moderate violence and moderate profanity is allowed, as is brief nudity and sexual references if important to the context of the story</string>
-    <string name="description_catv_14">Programming intended for viewers ages 14 and older. May contain strong violence and strong profanity, and depictions of sexual activity as long as they are within the context of a story</string>
-    <string name="description_catv_18">Programming intended for viewers ages 18 and older. May contain explicit violence and sexual activity</string>
+    <string name="description_catv_exempt" translatable="false">Shows which are exempt from ratings (such as news and sports programming) will not display an on-screen rating at all</string>
+    <string name="description_catv_c" translatable="false">Programming suitable for children ages of 2-7 years. No profanity or sexual content of any level allowed. Contains little violence</string>
+    <string name="description_catv_c8" translatable="false">Suitable for children ages 8+. Low level violence and fantasy horror is allowed. No foul language is allowed, but occasional "socially offensive and discriminatory" language is allowed if in the context of the story. No sexual content of any level allowed</string>
+    <string name="description_catv_g" translatable="false">Suitable for general audiences. Programming suitable for the entire family with mild violence, and mild profanity and/or censored language</string>
+    <string name="description_catv_pg" translatable="false">Parental guidance. Moderate violence and moderate profanity is allowed, as is brief nudity and sexual references if important to the context of the story</string>
+    <string name="description_catv_14" translatable="false">Programming intended for viewers ages 14 and older. May contain strong violence and strong profanity, and depictions of sexual activity as long as they are within the context of a story</string>
+    <string name="description_catv_18" translatable="false">Programming intended for viewers ages 18 and older. May contain explicit violence and sexual activity</string>
 
     <!-- TV content rating system strings for CH TV -->
     <string name="display_name_chtv" translatable="false">CH-TV</string>
     <string name="display_name_chtv_all" translatable="false">All ages</string>
     <string name="display_name_chtv_red" translatable="false">Red rectangle</string>
-    <string name="description_chtv_all">This program is suitable for all ages</string>
-    <string name="description_chtv_red">This program contains scenes that may hurt sensitive people, therefore the red symbol will be displayed</string>
+    <string name="description_chtv_all" translatable="false">This program is suitable for all ages</string>
+    <string name="description_chtv_red" translatable="false">This program contains scenes that may hurt sensitive people, therefore the red symbol will be displayed</string>
 
     <!-- TV content rating system strings for CL TV -->
     <string name="display_name_cltv" translatable="false">CL-TV</string>
@@ -4986,13 +4990,13 @@
     <string name="display_name_cltv_f" translatable="false">F</string>
     <string name="display_name_cltv_r" translatable="false">R</string>
     <string name="display_name_cltv_a" translatable="false">A</string>
-    <string name="description_cltv_i">Programs suitable for all children</string>
-    <string name="description_cltv_i7">Programs recommended for children ages 7 or older</string>
-    <string name="description_cltv_i10">Programs recommended for children ages 10 or older</string>
-    <string name="description_cltv_i12">Programs recommended for children and teens ages 12 or older</string>
-    <string name="description_cltv_f">Programs suitable for a general audience, with content appropriate for all ages</string>
-    <string name="description_cltv_r">Programs may content not suitable for children not accompanied by an adult</string>
-    <string name="description_cltv_a">Programs suitable for adult audiences only (ages 18 or older), may contain coarse language, and sexual or explicit situations</string>
+    <string name="description_cltv_i" translatable="false">Programs suitable for all children</string>
+    <string name="description_cltv_i7" translatable="false">Programs recommended for children ages 7 or older</string>
+    <string name="description_cltv_i10" translatable="false">Programs recommended for children ages 10 or older</string>
+    <string name="description_cltv_i12" translatable="false">Programs recommended for children and teens ages 12 or older</string>
+    <string name="description_cltv_f" translatable="false">Programs suitable for a general audience, with content appropriate for all ages</string>
+    <string name="description_cltv_r" translatable="false">Programs may content not suitable for children not accompanied by an adult</string>
+    <string name="description_cltv_a" translatable="false">Programs suitable for adult audiences only (ages 18 or older), may contain coarse language, and sexual or explicit situations</string>
 
     <!-- TV content rating system strings for DE TV -->
     <string name="display_name_detv" translatable="false">DE-TV</string>
@@ -5000,10 +5004,10 @@
     <string name="display_name_detv_12" translatable="false">ab 12 Jahren</string>
     <string name="display_name_detv_16" translatable="false">ab 16 Jahren</string>
     <string name="display_name_detv_18" translatable="false">ab 18 Jahren</string>
-    <string name="description_detv_all">The program is suitable for all ages</string>
-    <string name="description_detv_12">The program is not suitable for viewers under the age of 12</string>
-    <string name="description_detv_16">The program is not suitable for viewers under the age of 16</string>
-    <string name="description_detv_18">The program is not suitable for viewers under the age of 18</string>
+    <string name="description_detv_all" translatable="false">The program is suitable for all ages</string>
+    <string name="description_detv_12" translatable="false">The program is not suitable for viewers under the age of 12</string>
+    <string name="description_detv_16" translatable="false">The program is not suitable for viewers under the age of 16</string>
+    <string name="description_detv_18" translatable="false">The program is not suitable for viewers under the age of 18</string>
 
     <!-- TV content rating system strings for DK TV -->
     <string name="display_name_dktv" translatable="false">DK-TV</string>
@@ -5011,10 +5015,10 @@
     <string name="display_name_dktv_y" translatable="false">Yellow symbol</string>
     <string name="display_name_dktv_r" translatable="false">Red symbol</string>
     <string name="display_name_dktv_b" translatable="false">Blue symbol</string>
-    <string name="description_dktv_g">programs suitable for all ages</string>
-    <string name="description_dktv_y">programs suitable children accompanied by an adult</string>
-    <string name="description_dktv_r">programs containing material with more intensive content </string>
-    <string name="description_dktv_b">programs containing explicit content and strictly for adults only</string>
+    <string name="description_dktv_g" translatable="false">programs suitable for all ages</string>
+    <string name="description_dktv_y" translatable="false">programs suitable children accompanied by an adult</string>
+    <string name="description_dktv_r" translatable="false">programs containing material with more intensive content </string>
+    <string name="description_dktv_b" translatable="false">programs containing explicit content and strictly for adults only</string>
 
     <!-- TV content rating system strings for ES TV -->
     <string name="display_name_estv" translatable="false">ES-TV</string>
@@ -5025,13 +5029,13 @@
     <string name="display_name_estv_12" translatable="false">12</string>
     <string name="display_name_estv_16" translatable="false">16</string>
     <string name="display_name_estv_18" translatable="false">18</string>
-    <string name="description_estv_tp">Recommended for all ages</string>
-    <string name="description_estv_i">Specially recommended for preschoolers and kids</string>
-    <string name="description_estv_7">Recommended for people older than 7 years old</string>
-    <string name="description_estv_7i">Recommended for kids older than 7 years old</string>
-    <string name="description_estv_12">Recommended for people older than 12 years old</string>
-    <string name="description_estv_16">Recommended for people older than 16 years old</string>
-    <string name="description_estv_18">Recommended for people older than 18 years old</string>
+    <string name="description_estv_tp" translatable="false">Recommended for all ages</string>
+    <string name="description_estv_i" translatable="false">Specially recommended for preschoolers and kids</string>
+    <string name="description_estv_7" translatable="false">Recommended for people older than 7 years old</string>
+    <string name="description_estv_7i" translatable="false">Recommended for kids older than 7 years old</string>
+    <string name="description_estv_12" translatable="false">Recommended for people older than 12 years old</string>
+    <string name="description_estv_16" translatable="false">Recommended for people older than 16 years old</string>
+    <string name="description_estv_18" translatable="false">Recommended for people older than 18 years old</string>
 
     <!-- TV content rating system strings for FI TV -->
     <string name="display_name_fitv" translatable="false">FI-TV</string>
@@ -5040,11 +5044,11 @@
     <string name="display_name_fitv_k12" translatable="false">K12</string>
     <string name="display_name_fitv_k16" translatable="false">K16</string>
     <string name="display_name_fitv_k18" translatable="false">K18</string>
-    <string name="description_fitv_s">Allowed at all times</string>
-    <string name="description_fitv_k7">Not recommended for children under 7</string>
-    <string name="description_fitv_k12">Not recommended for children under 12</string>
-    <string name="description_fitv_k16">Not recommended for children under 16</string>
-    <string name="description_fitv_k18">Not recommended for children under 18</string>
+    <string name="description_fitv_s" translatable="false">Allowed at all times</string>
+    <string name="description_fitv_k7" translatable="false">Not recommended for children under 7</string>
+    <string name="description_fitv_k12" translatable="false">Not recommended for children under 12</string>
+    <string name="description_fitv_k16" translatable="false">Not recommended for children under 16</string>
+    <string name="description_fitv_k18" translatable="false">Not recommended for children under 18</string>
 
     <!-- TV content rating system strings for FR TV -->
     <string name="display_name_frtv" translatable="false">FR-TV</string>
@@ -5053,11 +5057,11 @@
     <string name="display_name_frtv_12" translatable="false">Déconseillé aux -12 ans</string>
     <string name="display_name_frtv_16" translatable="false">Déconseillé aux -16 ans</string>
     <string name="display_name_frtv_18" translatable="false">Déconseillé aux -18 ans</string>
-    <string name="description_frtv_all">Appropriate for all ages</string>
-    <string name="description_frtv_10">Not recommended for children under 10</string>
-    <string name="description_frtv_12">Not recommended for children under 12</string>
-    <string name="description_frtv_16">Not recommended for children under 16</string>
-    <string name="description_frtv_18">Not recommended for persons under 18</string>
+    <string name="description_frtv_all" translatable="false">Appropriate for all ages</string>
+    <string name="description_frtv_10" translatable="false">Not recommended for children under 10</string>
+    <string name="description_frtv_12" translatable="false">Not recommended for children under 12</string>
+    <string name="description_frtv_16" translatable="false">Not recommended for children under 16</string>
+    <string name="description_frtv_18" translatable="false">Not recommended for persons under 18</string>
 
     <!-- TV content rating system strings for GR TV -->
     <string name="display_name_grtv" translatable="false">GR-TV</string>
@@ -5066,20 +5070,20 @@
     <string name="display_name_grtv_12" translatable="false">White triangle in orange background</string>
     <string name="display_name_grtv_15" translatable="false">White square in purple background</string>
     <string name="display_name_grtv_18" translatable="false">White X in red background</string>
-    <string name="description_grtv_all">Suitable for all ages</string>
-    <string name="description_grtv_10">Parental consent suggested</string>
-    <string name="description_grtv_12">Required parental consent</string>
-    <string name="description_grtv_15">Suitable for minors over the age of 15</string>
-    <string name="description_grtv_18">Suitable only for adults profanity before midnight is punishable by fine, except when used in the context of the program</string>
+    <string name="description_grtv_all" translatable="false">Suitable for all ages</string>
+    <string name="description_grtv_10" translatable="false">Parental consent suggested</string>
+    <string name="description_grtv_12" translatable="false">Required parental consent</string>
+    <string name="description_grtv_15" translatable="false">Suitable for minors over the age of 15</string>
+    <string name="description_grtv_18" translatable="false">Suitable only for adults profanity before midnight is punishable by fine, except when used in the context of the program</string>
 
     <!-- TV content rating system strings for HK TV -->
     <string name="display_name_hktv" translatable="false">HK-TV</string>
     <string name="display_name_hktv_g" translatable="false">G</string>
     <string name="display_name_hktv_pg" translatable="false">PG</string>
     <string name="display_name_hktv_m" translatable="false">M</string>
-    <string name="description_hktv_g">For general audiences</string>
-    <string name="description_hktv_pg">Programs are unsuitable for children, parental guidance is recommended</string>
-    <string name="description_hktv_m">Programs are recommended only for adult viewers above the age of 18</string>
+    <string name="description_hktv_g" translatable="false">For general audiences</string>
+    <string name="description_hktv_pg" translatable="false">Programs are unsuitable for children, parental guidance is recommended</string>
+    <string name="description_hktv_m" translatable="false">Programs are recommended only for adult viewers above the age of 18</string>
 
     <!-- TV content rating system strings for HU TV -->
     <string name="display_name_hutv" translatable="false">HU-TV</string>
@@ -5089,12 +5093,12 @@
     <string name="display_name_hutv_12" translatable="false">12</string>
     <string name="display_name_hutv_16" translatable="false">16</string>
     <string name="display_name_hutv_18" translatable="false">18</string>
-    <string name="description_hutv_u">Programs can be viewed by any age</string>
-    <string name="description_hutv_cf">Programs recommended for children. It is an optional rating, there is no obligation for broadcasters to indicate it</string>
-    <string name="description_hutv_6">Programs not recommended for children below the age of 6, may not contain any violence or sexual content</string>
-    <string name="description_hutv_12">Programs not recommended for children below the age of 12, may contain light sexual content or explicit language</string>
-    <string name="description_hutv_16">Programs not recommended for teens and children below the age of 16, may contain more intensive violence and sexual content</string>
-    <string name="description_hutv_18">The program is recommended only for adult viewers (for ages 18 and up), may contain explicit violence and explicit sexual content</string>
+    <string name="description_hutv_u" translatable="false">Programs can be viewed by any age</string>
+    <string name="description_hutv_cf" translatable="false">Programs recommended for children. It is an optional rating, there is no obligation for broadcasters to indicate it</string>
+    <string name="description_hutv_6" translatable="false">Programs not recommended for children below the age of 6, may not contain any violence or sexual content</string>
+    <string name="description_hutv_12" translatable="false">Programs not recommended for children below the age of 12, may contain light sexual content or explicit language</string>
+    <string name="description_hutv_16" translatable="false">Programs not recommended for teens and children below the age of 16, may contain more intensive violence and sexual content</string>
+    <string name="description_hutv_18" translatable="false">The program is recommended only for adult viewers (for ages 18 and up), may contain explicit violence and explicit sexual content</string>
 
     <!-- TV content rating system strings for ID TV -->
     <string name="display_name_idtv" translatable="false">ID-TV</string>
@@ -5106,14 +5110,14 @@
     <string name="display_name_idtv_r" translatable="false">R</string>
     <string name="display_name_idtv_r_bo" translatable="false">R-BO</string>
     <string name="display_name_idtv_d" translatable="false">D</string>
-    <string name="description_idtv_p">Suitable for children from ages 2 through 11</string>
-    <string name="description_idtv_a">Suitable for teens and children from ages 7 through 16</string>
-    <string name="description_idtv_a_bo">Suitable for children ages 5 through 10, with parental guidance or permission</string>
-    <string name="description_idtv_su">Suitable for general audiences</string>
-    <string name="description_idtv_bo">Parental guidance suggested for ages 5 and under</string>
-    <string name="description_idtv_r">Suitable for teens from ages 13 through 17</string>
-    <string name="description_idtv_r_bo">Suitable for teens with parental guidance or permission</string>
-    <string name="description_idtv_d">Suitable for viewers over 18 and older only</string>
+    <string name="description_idtv_p" translatable="false">Suitable for children from ages 2 through 11</string>
+    <string name="description_idtv_a" translatable="false">Suitable for teens and children from ages 7 through 16</string>
+    <string name="description_idtv_a_bo" translatable="false">Suitable for children ages 5 through 10, with parental guidance or permission</string>
+    <string name="description_idtv_su" translatable="false">Suitable for general audiences</string>
+    <string name="description_idtv_bo" translatable="false">Parental guidance suggested for ages 5 and under</string>
+    <string name="description_idtv_r" translatable="false">Suitable for teens from ages 13 through 17</string>
+    <string name="description_idtv_r_bo" translatable="false">Suitable for teens with parental guidance or permission</string>
+    <string name="description_idtv_d" translatable="false">Suitable for viewers over 18 and older only</string>
 
     <!-- TV content rating system strings for IE TV -->
     <string name="display_name_ietv" translatable="false">RTÉ programme classifications</string>
@@ -5122,11 +5126,11 @@
     <string name="display_name_ietv_ya" translatable="false">YA</string>
     <string name="display_name_ietv_ps" translatable="false">PS</string>
     <string name="display_name_ietv_ma" translatable="false">MA</string>
-    <string name="description_ietv_ga">Suitable for all ages</string>
-    <string name="description_ietv_ch">Suitable for children ages 5 to 10, may contain comedic violence or action fantasy violence</string>
-    <string name="description_ietv_ya">Suitable for adolescent audiences, may contain thematic elements that would appeal to teenagers</string>
-    <string name="description_ietv_ps">Suitable for more mature viewers, more mature themes may be present</string>
-    <string name="description_ietv_ma">Most restrictive classification, allowing for heavy subject matter and coarse language</string>
+    <string name="description_ietv_ga" translatable="false">Suitable for all ages</string>
+    <string name="description_ietv_ch" translatable="false">Suitable for children ages 5 to 10, may contain comedic violence or action fantasy violence</string>
+    <string name="description_ietv_ya" translatable="false">Suitable for adolescent audiences, may contain thematic elements that would appeal to teenagers</string>
+    <string name="description_ietv_ps" translatable="false">Suitable for more mature viewers, more mature themes may be present</string>
+    <string name="description_ietv_ma" translatable="false">Most restrictive classification, allowing for heavy subject matter and coarse language</string>
 
     <!-- TV content rating system strings for IL TV -->
     <string name="display_name_iltv" translatable="false">IL-TV</string>
@@ -5135,11 +5139,11 @@
     <string name="display_name_iltv_15" translatable="false">15+</string>
     <string name="display_name_iltv_18" translatable="false">18+</string>
     <string name="display_name_iltv_e" translatable="false">E</string>
-    <string name="description_iltv_g">General audience; anyone, regardless of age, can view the program, usually news and children\'s programming</string>
-    <string name="description_iltv_12">Suitable for teens and children ages 12 and over, no child under 12 are permitted to view the program</string>
-    <string name="description_iltv_15">Suitable for teens ages 15 and over, no child under 15 may view the programme</string>
-    <string name="description_iltv_18">Suitable for adults only, no minors may view the programme</string>
-    <string name="description_iltv_e">Exempt from classification</string>
+    <string name="description_iltv_g" translatable="false">General audience; anyone, regardless of age, can view the program, usually news and children\'s programming</string>
+    <string name="description_iltv_12" translatable="false">Suitable for teens and children ages 12 and over, no child under 12 are permitted to view the program</string>
+    <string name="description_iltv_15" translatable="false">Suitable for teens ages 15 and over, no child under 15 may view the programme</string>
+    <string name="description_iltv_18" translatable="false">Suitable for adults only, no minors may view the programme</string>
+    <string name="description_iltv_e" translatable="false">Exempt from classification</string>
 
     <!-- TV content rating system strings for IN TV -->
     <string name="display_name_intv" translatable="false">IN-TV</string>
@@ -5147,10 +5151,10 @@
     <string name="display_name_intv_u/a" translatable="false">U/A</string>
     <string name="display_name_intv_a" translatable="false">A</string>
     <string name="display_name_intv_s" translatable="false">S</string>
-    <string name="description_intv_u">Unrestricted public exhibition</string>
-    <string name="description_intv_u/a">Unrestricted public exhibition, but with a caution regarding parental guidance to those under 12 years of age</string>
-    <string name="description_intv_a">Public exhibition restricted to adults 18 years of age and older only</string>
-    <string name="description_intv_s">Public exhibition restricted to members of any profession or any class of persons</string>
+    <string name="description_intv_u" translatable="false">Unrestricted public exhibition</string>
+    <string name="description_intv_u/a" translatable="false">Unrestricted public exhibition, but with a caution regarding parental guidance to those under 12 years of age</string>
+    <string name="description_intv_a" translatable="false">Public exhibition restricted to adults 18 years of age and older only</string>
+    <string name="description_intv_s" translatable="false">Public exhibition restricted to members of any profession or any class of persons</string>
 
     <!-- TV content rating system strings for IS TV -->
     <string name="display_name_istv" translatable="false">IS-TV</string>
@@ -5161,13 +5165,13 @@
     <string name="display_name_istv_14" translatable="false">14</string>
     <string name="display_name_istv_16" translatable="false">16</string>
     <string name="display_name_istv_18" translatable="false">18</string>
-    <string name="description_istv_l">Programs suitable for all ages</string>
-    <string name="description_istv_7">Programs suitable for ages 7 and older</string>
-    <string name="description_istv_10">Programs suitable for ages 10 and older</string>
-    <string name="description_istv_12">Programs suitable for ages 12 and older</string>
-    <string name="description_istv_14">Programs suitable for ages 14 and older</string>
-    <string name="description_istv_16">Programs suitable for ages 16 and older</string>
-    <string name="description_istv_18">Programs suitable for ages 18 and older</string>
+    <string name="description_istv_l" translatable="false">Programs suitable for all ages</string>
+    <string name="description_istv_7" translatable="false">Programs suitable for ages 7 and older</string>
+    <string name="description_istv_10" translatable="false">Programs suitable for ages 10 and older</string>
+    <string name="description_istv_12" translatable="false">Programs suitable for ages 12 and older</string>
+    <string name="description_istv_14" translatable="false">Programs suitable for ages 14 and older</string>
+    <string name="description_istv_16" translatable="false">Programs suitable for ages 16 and older</string>
+    <string name="description_istv_18" translatable="false">Programs suitable for ages 18 and older</string>
 
     <!-- TV content rating system strings for KR TV -->
     <string name="display_name_krtv" translatable="false">KR-TV</string>
@@ -5176,11 +5180,11 @@
     <string name="display_name_krtv_12" translatable="false">12세이상시청가</string>
     <string name="display_name_krtv_15" translatable="false">15세이상시청가</string>
     <string name="display_name_krtv_19" translatable="false">19세이상시청가</string>
-    <string name="description_krtv_all">Appropriate for all ages</string>
-    <string name="description_krtv_7">May contain material inappropriate for children younger than 7, and parental discretion should be used</string>
-    <string name="description_krtv_12">May deemed inappropriate for those younger than 12, and parental discretion should be used</string>
-    <string name="description_krtv_15">May be inappropriate for children under 15, and that parental discretion should be used</string>
-    <string name="description_krtv_19">For adults only</string>
+    <string name="description_krtv_all" translatable="false">Appropriate for all ages</string>
+    <string name="description_krtv_7" translatable="false">May contain material inappropriate for children younger than 7, and parental discretion should be used</string>
+    <string name="description_krtv_12" translatable="false">May deemed inappropriate for those younger than 12, and parental discretion should be used</string>
+    <string name="description_krtv_15" translatable="false">May be inappropriate for children under 15, and that parental discretion should be used</string>
+    <string name="description_krtv_19" translatable="false">For adults only</string>
 
     <!-- TV content rating system strings for MV TV -->
     <string name="display_name_mvtv" translatable="false">MV-TV</string>
@@ -5193,15 +5197,15 @@
     <string name="display_name_mvtv_18" translatable="false">18+</string>
     <string name="display_name_mvtv_21" translatable="false">21+</string>
     <string name="display_name_mvtv_x" translatable="false">X</string>
-    <string name="description_mvtv_y">Young children</string>
-    <string name="description_mvtv_g">General viewing for all ages</string>
-    <string name="description_mvtv_pg">Parental guidance is required unaccompanied children</string>
-    <string name="description_mvtv_pg-12">Parental guidance is required for children under the age of 12</string>
-    <string name="description_mvtv_12">Teens and children aged 12 and older may watch, otherwise restricted</string>
-    <string name="description_mvtv_15">Restricted to viewers aged 15 and above</string>
-    <string name="description_mvtv_18">Restricted to viewers aged 18 and above</string>
-    <string name="description_mvtv_21">Restricted to viewers aged 21 and above</string>
-    <string name="description_mvtv_x">Most restrictive classification, only adults ages 25 and above may view</string>
+    <string name="description_mvtv_y" translatable="false">Young children</string>
+    <string name="description_mvtv_g" translatable="false">General viewing for all ages</string>
+    <string name="description_mvtv_pg" translatable="false">Parental guidance is required unaccompanied children</string>
+    <string name="description_mvtv_pg-12" translatable="false">Parental guidance is required for children under the age of 12</string>
+    <string name="description_mvtv_12" translatable="false">Teens and children aged 12 and older may watch, otherwise restricted</string>
+    <string name="description_mvtv_15" translatable="false">Restricted to viewers aged 15 and above</string>
+    <string name="description_mvtv_18" translatable="false">Restricted to viewers aged 18 and above</string>
+    <string name="description_mvtv_21" translatable="false">Restricted to viewers aged 21 and above</string>
+    <string name="description_mvtv_x" translatable="false">Most restrictive classification, only adults ages 25 and above may view</string>
 
     <!-- TV content rating system strings for MX TV -->
     <string name="display_name_mxtv" translatable="false">MX-TV</string>
@@ -5211,21 +5215,21 @@
     <string name="display_name_mxtv_c" translatable="false">C</string>
     <string name="display_name_mxtv_d" translatable="false">D</string>
     <string name="display_name_mxtv_rc" translatable="false">RC</string>
-    <string name="description_mxtv_a">Appropriate for all ages, parental guidance is recommended for children under 7 years</string>
-    <string name="description_mxtv_b">Designed for ages 12 and older, may contain some sexual situations, mild violence, and mild language</string>
-    <string name="description_mxtv_b-15">Designed for ages 15 and up, slightly more intensive than the \'A\' and \'B\' ratings</string>
-    <string name="description_mxtv_c">Designed to be viewed by adults aged 18 or older only, generally more intensive content </string>
-    <string name="description_mxtv_d">Designed to be viewed only by mature adults (at least 21 years of age and over), contains extreme content matter</string>
-    <string name="description_mxtv_rc">Banned from public television in Mexico</string>
+    <string name="description_mxtv_a" translatable="false">Appropriate for all ages, parental guidance is recommended for children under 7 years</string>
+    <string name="description_mxtv_b" translatable="false">Designed for ages 12 and older, may contain some sexual situations, mild violence, and mild language</string>
+    <string name="description_mxtv_b-15" translatable="false">Designed for ages 15 and up, slightly more intensive than the \'A\' and \'B\' ratings</string>
+    <string name="description_mxtv_c" translatable="false">Designed to be viewed by adults aged 18 or older only, generally more intensive content </string>
+    <string name="description_mxtv_d" translatable="false">Designed to be viewed only by mature adults (at least 21 years of age and over), contains extreme content matter</string>
+    <string name="description_mxtv_rc" translatable="false">Banned from public television in Mexico</string>
 
     <!-- TV content rating system strings for MY TV -->
     <string name="display_name_mytv" translatable="false">MY-TV</string>
     <string name="display_name_mytv_u" translatable="false">U</string>
     <string name="display_name_mytv_p13" translatable="false">P13</string>
     <string name="display_name_mytv_18" translatable="false">18</string>
-    <string name="description_mytv_u">General viewing for all ages, can be broadcast anytime</string>
-    <string name="description_mytv_p13">For viewers ages 13 and above, children under 13 needs parental guidance, can be broadcast anytime, but some elements may only be broadcast at night</string>
-    <string name="description_mytv_18">For viewers ages 18 and above only</string>
+    <string name="description_mytv_u" translatable="false">General viewing for all ages, can be broadcast anytime</string>
+    <string name="description_mytv_p13" translatable="false">For viewers ages 13 and above, children under 13 needs parental guidance, can be broadcast anytime, but some elements may only be broadcast at night</string>
+    <string name="description_mytv_18" translatable="false">For viewers ages 18 and above only</string>
 
     <!-- TV content rating system strings for NL TV -->
     <string name="display_name_nltv" translatable="false">NICAM</string>
@@ -5240,31 +5244,31 @@
     <string name="display_name_nltv_9" translatable="false">Let op met kinderen tot 9 jaar</string>
     <string name="display_name_nltv_12" translatable="false">Let op met kinderen tot 12 jaar</string>
     <string name="display_name_nltv_16" translatable="false">Let op met kinderen tot 16 jaar</string>
-    <string name="description_nltv_v">Violence</string>
-    <string name="description_nltv_f">Scary or Disturbing Content </string>
-    <string name="description_nltv_s">Sexual Content</string>
-    <string name="description_nltv_d">Discrimination</string>
-    <string name="description_nltv_da">Drug and/or Alcohol abuse</string>
-    <string name="description_nltv_l">Bad Language</string>
-    <string name="description_nltv_al">All Ages</string>
-    <string name="description_nltv_6">Parental advisory for children under 6</string>
-    <string name="description_nltv_9">Parental advisory for children under 9</string>
-    <string name="description_nltv_12">Parental advisory for children under 12</string>
-    <string name="description_nltv_16">Parental advisory for children under 16</string>
+    <string name="description_nltv_v" translatable="false">Violence\nApplicable to NL_TV_AL, NL_TV_6, NL_TV_9, NL_TV_12, NL_TV_16</string>
+    <string name="description_nltv_f" translatable="false">Scary or Disturbing ContentViolence\nApplicable to NL_TV_AL, NL_TV_6, NL_TV_9, NL_TV_12, NL_TV_16</string>
+    <string name="description_nltv_s" translatable="false">Sexual Content\nApplicable to NL_TV_AL, NL_TV_6, NL_TV_9, NL_TV_12, NL_TV_16</string>
+    <string name="description_nltv_d" translatable="false">Discrimination\nApplicable to NL_TV_AL, NL_TV_6, NL_TV_9, NL_TV_12, NL_TV_16</string>
+    <string name="description_nltv_da" translatable="false">Drug and/or Alcohol abuse\nApplicable to NL_TV_AL, NL_TV_6, NL_TV_9, NL_TV_12, NL_TV_16</string>
+    <string name="description_nltv_l" translatable="false">Bad Language\nApplicable to NL_TV_AL, NL_TV_6, NL_TV_9, NL_TV_12, NL_TV_16</string>
+    <string name="description_nltv_al" translatable="false">All Ages</string>
+    <string name="description_nltv_6" translatable="false">Parental advisory for children under 6</string>
+    <string name="description_nltv_9" translatable="false">Parental advisory for children under 9</string>
+    <string name="description_nltv_12" translatable="false">Parental advisory for children under 12</string>
+    <string name="description_nltv_16" translatable="false">Parental advisory for children under 16</string>
 
     <!-- TV content rating system strings for NZF(Free) TV -->
     <string name="display_name_nzftv" translatable="false">NZ-Free-TV</string>
-    <string name="description_nzftv">New Zealand\'s free-to-air TV content rating system</string>
+    <string name="description_nzftv" translatable="false">TV content rating system for free-to-air channels in New Zealand</string>
     <string name="display_name_nzftv_g" translatable="false">G</string>
     <string name="display_name_nzftv_pgr" translatable="false">PGR</string>
     <string name="display_name_nzftv_ao" translatable="false">AO</string>
-    <string name="description_nzftv_g">These exclude material likely to harm children under 14 and can screen at any time. Programmes may not necessarily be designed for younger viewers, but must not contain material likely to cause them undue distress or discomfort</string>
-    <string name="description_nzftv_pgr">Programmes more suited to more mature viewers. These are not necessarily unsuitable for children, but viewer discretion is advised, and parents and guardians are encouraged to supervise younger viewers</string>
-    <string name="description_nzftv_ao">Contain material of an adult nature handled in such a way that it is unsuitable for children</string>
+    <string name="description_nzftv_g" translatable="false">These exclude material likely to harm children under 14 and can screen at any time. Programmes may not necessarily be designed for younger viewers, but must not contain material likely to cause them undue distress or discomfort</string>
+    <string name="description_nzftv_pgr" translatable="false">Programmes more suited to more mature viewers. These are not necessarily unsuitable for children, but viewer discretion is advised, and parents and guardians are encouraged to supervise younger viewers</string>
+    <string name="description_nzftv_ao" translatable="false">Contain material of an adult nature handled in such a way that it is unsuitable for children</string>
 
     <!-- TV content rating system strings for NZP(Pay) TV -->
     <string name="display_name_nzptv" translatable="false">NZ-Pay-TV</string>
-    <string name="description_nzptv">New Zealand\'s pay TV content rating system</string>
+    <string name="description_nzptv" translatable="false">TV content rating system for Pay TV channels in New Zealand</string>
     <string name="display_name_nzptv_c" translatable="false">C</string>
     <string name="display_name_nzptv_v" translatable="false">V</string>
     <string name="display_name_nzptv_l" translatable="false">L</string>
@@ -5274,46 +5278,46 @@
     <string name="display_name_nzptv_m" translatable="false">M</string>
     <string name="display_name_nzptv_16" translatable="false">16</string>
     <string name="display_name_nzptv_18" translatable="false">18</string>
-    <string name="description_nzptv_c">Content may offend</string>
-    <string name="description_nzptv_v">Violence</string>
-    <string name="description_nzptv_l">Language</string>
-    <string name="description_nzptv_s">Sexual content</string>
-    <string name="description_nzptv_g">suitable for general audiences</string>
-    <string name="description_nzptv_pg">Parental guidance recommended for under 10</string>
-    <string name="description_nzptv_m">Suitable for mature audiences 13 and up</string>
-    <string name="description_nzptv_16">Suitable for viewers 16 and up</string>
-    <string name="description_nzptv_18">Suitable for viewers 18 and up</string>
+    <string name="description_nzptv_c" translatable="false">Content may offend\nApplicable to NZ_PTV_PG, NZ_PTV_M, NZ_PTV_16, NZ_PTV_18</string>
+    <string name="description_nzptv_v" translatable="false">Violence\nApplicable to NZ_PTV_PG, NZ_PTV_M, NZ_PTV_16, NZ_PTV_18</string>
+    <string name="description_nzptv_l" translatable="false">Language\nApplicable to NZ_PTV_PG, NZ_PTV_M, NZ_PTV_16, NZ_PTV_18</string>
+    <string name="description_nzptv_s" translatable="false">Sexual content\nApplicable to NZ_PTV_PG, NZ_PTV_M, NZ_PTV_16, NZ_PTV_18</string>
+    <string name="description_nzptv_g" translatable="false">suitable for general audiences</string>
+    <string name="description_nzptv_pg" translatable="false">Parental guidance recommended for under 10</string>
+    <string name="description_nzptv_m" translatable="false">Suitable for mature audiences 13 and up</string>
+    <string name="description_nzptv_16" translatable="false">Suitable for viewers 16 and up</string>
+    <string name="description_nzptv_18" translatable="false">Suitable for viewers 18 and up</string>
 
     <!-- TV content rating system strings for PE TV -->
     <string name="display_name_petv" translatable="false">PE-TV</string>
-    <string name="description_petv">TV content rating system for some Peruvian channels in Peru</string>
+    <string name="description_petv" translatable="false">TV content rating system for some Peruvian channels in Peru</string>
     <string name="display_name_petv_a" translatable="false">Apt</string>
     <string name="display_name_petv_14" translatable="false">14</string>
     <string name="display_name_petv_18" translatable="false">18</string>
-    <string name="description_petv_a">Suitable for all audiences</string>
-    <string name="description_petv_14">Suitable for people aged 14 and above only</string>
-    <string name="description_petv_18">Suitable for people aged 18 and above only</string>
+    <string name="description_petv_a" translatable="false">Suitable for all audiences</string>
+    <string name="description_petv_14" translatable="false">Suitable for people aged 14 and above only</string>
+    <string name="description_petv_18" translatable="false">Suitable for people aged 18 and above only</string>
 
     <!-- TV content rating system strings for America TV in PE -->
     <string name="display_name_peatv" translatable="false">PE-ATV</string>
-    <string name="description_peatv">TV content rating system for America Television in Peru that uses its own rating system</string>
+    <string name="description_peatv" translatable="false">TV content rating system for America Television in Peru that uses its own rating system</string>
     <string name="display_name_peatv_gp" translatable="false">GP</string>
     <string name="display_name_peatv_pg" translatable="false">PG</string>
     <string name="display_name_peatv_14" translatable="false">TV-14</string>
     <string name="display_name_peatv_18" translatable="false">TV-18</string>
-    <string name="description_peatv_gp">General audience</string>
-    <string name="description_peatv_pg">Parental guidance required for under 6</string>
-    <string name="description_peatv_14">Suitable for people aged 14 and above only</string>
-    <string name="description_peatv_18">Suitable for people aged 18 and above only</string>
+    <string name="description_peatv_gp" translatable="false">General audience</string>
+    <string name="description_peatv_pg" translatable="false">Parental guidance required for under 6</string>
+    <string name="description_peatv_14" translatable="false">Suitable for people aged 14 and above only</string>
+    <string name="description_peatv_18" translatable="false">Suitable for people aged 18 and above only</string>
 
     <!-- TV content rating system strings for PH TV -->
     <string name="display_name_phtv" translatable="false">MTRCB</string>
     <string name="display_name_phtv_g" translatable="false">G</string>
     <string name="display_name_phtv_pg" translatable="false">PG</string>
     <string name="display_name_phtv_spg" translatable="false">SPG</string>
-    <string name="description_phtv_g">Suitable for all public viewers</string>
-    <string name="description_phtv_pg">Programmes rated PG may contain scenes or other content that are unsuitable for children without the guidance of a parent</string>
-    <string name="description_phtv_spg">Contains mature themes or moderate to intense violence, which may be deemed unfit for children to watch without strict parental supervision</string>
+    <string name="description_phtv_g" translatable="false">Suitable for all public viewers</string>
+    <string name="description_phtv_pg" translatable="false">Programmes rated PG may contain scenes or other content that are unsuitable for children without the guidance of a parent</string>
+    <string name="description_phtv_spg" translatable="false">Contains mature themes or moderate to intense violence, which may be deemed unfit for children to watch without strict parental supervision</string>
 
     <!-- TV content rating system strings for PL TV -->
     <string name="display_name_pltv" translatable="false">PL-TV</string>
@@ -5322,11 +5326,11 @@
     <string name="display_name_pltv_12" translatable="false">12</string>
     <string name="display_name_pltv_16" translatable="false">16</string>
     <string name="display_name_pltv_18" translatable="false">18</string>
-    <string name="description_pltv_g">Positive or neutral view of the world, little to no violence, non-sexual love, and no sexual content</string>
-    <string name="description_pltv_7">Age 7 and above. May additionally contain some mild language, bloodless violence, and a more negative view of the world</string>
-    <string name="description_pltv_12">Age 12 and above. May contain some foul language, some violence, and some sexual content</string>
-    <string name="description_pltv_16">Age 16 and above. Deviant social behaviour, world filled with violence and sexuality, simplified picture of adulthood, display of physical force, especially in controversial social context, immoral behaviour without ethic dilemma, putting the blame on the victim, excessive concentration on material possessions</string>
-    <string name="description_pltv_18">Age 18 and above. One-sided display of the joys of adult life without showing responsibilities, social justification of violent behaviour, excessive vulgarity, use of racial slurs and social stereotypes, explicit sexual content, praise of aggression or vulgarity</string>
+    <string name="description_pltv_g" translatable="false">Positive or neutral view of the world, little to no violence, non-sexual love, and no sexual content</string>
+    <string name="description_pltv_7" translatable="false">Age 7 and above. May additionally contain some mild language, bloodless violence, and a more negative view of the world</string>
+    <string name="description_pltv_12" translatable="false">Age 12 and above. May contain some foul language, some violence, and some sexual content</string>
+    <string name="description_pltv_16" translatable="false">Age 16 and above. Deviant social behaviour, world filled with violence and sexuality, simplified picture of adulthood, display of physical force, especially in controversial social context, immoral behaviour without ethic dilemma, putting the blame on the victim, excessive concentration on material possessions</string>
+    <string name="description_pltv_18" translatable="false">Age 18 and above. One-sided display of the joys of adult life without showing responsibilities, social justification of violent behaviour, excessive vulgarity, use of racial slurs and social stereotypes, explicit sexual content, praise of aggression or vulgarity</string>
 
     <!-- TV content rating system strings for PT TV -->
     <string name="display_name_pttv" translatable="false">PT-TV</string>
@@ -5334,10 +5338,10 @@
     <string name="display_name_pttv_10" translatable="false">10</string>
     <string name="display_name_pttv_12" translatable="false">12</string>
     <string name="display_name_pttv_16" translatable="false">16</string>
-    <string name="description_pttv_t">Suitable for all</string>
-    <string name="description_pttv_10">May not be suitable for children under 10, parental guidance advised</string>
-    <string name="description_pttv_12">May not be suitable for children under 12, parental guidance advised</string>
-    <string name="description_pttv_16">Not suitable for children under 16</string>
+    <string name="description_pttv_t" translatable="false">Suitable for all</string>
+    <string name="description_pttv_10" translatable="false">May not be suitable for children under 10, parental guidance advised</string>
+    <string name="description_pttv_12" translatable="false">May not be suitable for children under 12, parental guidance advised</string>
+    <string name="description_pttv_16" translatable="false">Not suitable for children under 16</string>
 
     <!-- TV content rating system strings for RO TV -->
     <string name="display_name_rotv" translatable="false">RO-TV</string>
@@ -5347,12 +5351,12 @@
     <string name="display_name_rotv_12" translatable="false">12</string>
     <string name="display_name_rotv_15" translatable="false">15</string>
     <string name="display_name_rotv_18" translatable="false">18</string>
-    <string name="description_rotv_y">Young Ages</string>
-    <string name="description_rotv_g">General Exhibition</string>
-    <string name="description_rotv_ap">Parental guidance is recommended for children below the age of 12</string>
-    <string name="description_rotv_12">Forbidden for children under 12 years of age</string>
-    <string name="description_rotv_15">Forbidden for children under 15 years of age</string>
-    <string name="description_rotv_18">Forbidden for children under 18 years of age</string>
+    <string name="description_rotv_y" translatable="false">Young Ages</string>
+    <string name="description_rotv_g" translatable="false">General Exhibition</string>
+    <string name="description_rotv_ap" translatable="false">Parental guidance is recommended for children below the age of 12</string>
+    <string name="description_rotv_12" translatable="false">Forbidden for children under 12 years of age</string>
+    <string name="description_rotv_15" translatable="false">Forbidden for children under 15 years of age</string>
+    <string name="description_rotv_18" translatable="false">Forbidden for children under 18 years of age</string>
 
     <!-- TV content rating system strings for RU TV -->
     <string name="display_name_rutv" translatable="false">RU-TV</string>
@@ -5361,11 +5365,11 @@
     <string name="display_name_rutv_12" translatable="false">12+</string>
     <string name="display_name_rutv_16" translatable="false">16+</string>
     <string name="display_name_rutv_18" translatable="false">18+</string>
-    <string name="description_rutv_0">Can be watched by Any Age</string>
-    <string name="description_rutv_6">Only kids the age of 6 or older can watch</string>
-    <string name="description_rutv_12">Only kids the age of 12 or older can watch</string>
-    <string name="description_rutv_16">Only teens the age of 16 or older can watch</string>
-    <string name="description_rutv_18">Restricted to children ONLY people 18 or older</string>
+    <string name="description_rutv_0" translatable="false">Can be watched by Any Age</string>
+    <string name="description_rutv_6" translatable="false">Only kids the age of 6 or older can watch</string>
+    <string name="description_rutv_12" translatable="false">Only kids the age of 12 or older can watch</string>
+    <string name="description_rutv_16" translatable="false">Only teens the age of 16 or older can watch</string>
+    <string name="description_rutv_18" translatable="false">Restricted to children ONLY people 18 or older</string>
 
     <!-- TV content rating system strings for RS TV -->
     <string name="display_name_rstv" translatable="false">RS-TV</string>
@@ -5376,27 +5380,27 @@
     <string name="display_name_rstv_16" translatable="false">16</string>
     <string name="display_name_rstv_17" translatable="false">17</string>
     <string name="display_name_rstv_18" translatable="false">18</string>
-    <string name="description_rstv_g">Program suitable for all ages</string>
-    <string name="description_rstv_12">Program not suitable for children under the age of 12 </string>
-    <string name="description_rstv_14">Program not suitable for children/teens under the age of 14</string>
-    <string name="description_rstv_15">Program not suitable for children/teens under the age of 15</string>
-    <string name="description_rstv_16">Program not suitable for children/teens under the age of 16</string>
-    <string name="description_rstv_17">Program not suitable for children/teens under the age of 17</string>
-    <string name="description_rstv_18">Program not suitable for minors under the age of 18</string>
+    <string name="description_rstv_g" translatable="false">Program suitable for all ages</string>
+    <string name="description_rstv_12" translatable="false">Program not suitable for children under the age of 12 </string>
+    <string name="description_rstv_14" translatable="false">Program not suitable for children/teens under the age of 14</string>
+    <string name="description_rstv_15" translatable="false">Program not suitable for children/teens under the age of 15</string>
+    <string name="description_rstv_16" translatable="false">Program not suitable for children/teens under the age of 16</string>
+    <string name="description_rstv_17" translatable="false">Program not suitable for children/teens under the age of 17</string>
+    <string name="description_rstv_18" translatable="false">Program not suitable for minors under the age of 18</string>
 
     <!-- TV content rating system strings for SGF(Free-to-Air) TV -->
     <string name="display_name_sgftv" translatable="false">SG-Free-TV</string>
     <string name="display_name_sgftv_pg" translatable="false">PG</string>
     <string name="display_name_sgftv_pg13" translatable="false">PG13</string>
-    <string name="description_sgftv_pg">Suitable for most but parents should guide their young</string>
-    <string name="description_sgftv_pg13">Parental Guidance Strongly Cautioned – Suitable for 13 And Above</string>
+    <string name="description_sgftv_pg" translatable="false">Suitable for most but parents should guide their young</string>
+    <string name="description_sgftv_pg13" translatable="false">Parental Guidance Strongly Cautioned - Suitable for 13 And Above</string>
 
     <!-- TV content rating system strings for SGP(Pay TV) TV -->
     <string name="display_name_sgptv" translatable="false">SG-Pay-TV</string>
     <string name="display_name_sgptv_nc16" translatable="false">NC16</string>
     <string name="display_name_sgptv_m18" translatable="false">M18</string>
-    <string name="description_sgptv_nc16">No Children Under 16</string>
-    <string name="description_sgptv_m18">Nobody under age 18 is admitted</string>
+    <string name="description_sgptv_nc16" translatable="false">No Children Under 16</string>
+    <string name="description_sgptv_m18" translatable="false">Nobody under age 18 is admitted</string>
 
     <!-- TV content rating system strings for SI TV -->
     <string name="display_name_sitv" translatable="false">SI-TV</string>
@@ -5404,10 +5408,10 @@
     <string name="display_name_sitv_12" translatable="false">+12</string>
     <string name="display_name_sitv_15" translatable="false">+15</string>
     <string name="display_name_sitv_ad" translatable="false">AD</string>
-    <string name="description_sitv_vs">Parental guidance suggested (for children under 6)</string>
-    <string name="description_sitv_12">Content suitable for teens over 12 years</string>
-    <string name="description_sitv_15">Content suitable for teens over 15 years</string>
-    <string name="description_sitv_ad">Content exclusively for adults</string>
+    <string name="description_sitv_vs" translatable="false">Parental guidance suggested (for children under 6)</string>
+    <string name="description_sitv_12" translatable="false">Content suitable for teens over 12 years</string>
+    <string name="description_sitv_15" translatable="false">Content suitable for teens over 15 years</string>
+    <string name="description_sitv_ad" translatable="false">Content exclusively for adults</string>
 
     <!-- TV content rating system strings for TH TV -->
     <string name="display_name_thtv" translatable="false">TH-TV</string>
@@ -5417,12 +5421,12 @@
     <string name="display_name_thtv_pg13" translatable="false">PG13</string>
     <string name="display_name_thtv_pg18" translatable="false">PG18</string>
     <string name="display_name_thtv_adults" translatable="false">Adults</string>
-    <string name="description_thtv_primary">Content suitable for primary school aged children</string>
-    <string name="description_thtv_children">Content suitable for children between 6–12 years old</string>
-    <string name="description_thtv_general">Content suitable for general audiences</string>
-    <string name="description_thtv_pg13">Content suitable for people aged 13 and above, but can be watched by those who are under the recommended age if parental guidance is provided</string>
-    <string name="description_thtv_pg18">Content suitable for people aged above 18 years old; those who are younger that 18 must be provided with parental guidance</string>
-    <string name="description_thtv_adults">Content unsuitable for children and youngsters</string>
+    <string name="description_thtv_primary" translatable="false">Content suitable for primary school aged children</string>
+    <string name="description_thtv_children" translatable="false">Content suitable for children between 6-12 years old</string>
+    <string name="description_thtv_general" translatable="false">Content suitable for general audiences</string>
+    <string name="description_thtv_pg13" translatable="false">Content suitable for people aged 13 and above, but can be watched by those who are under the recommended age if parental guidance is provided</string>
+    <string name="description_thtv_pg18" translatable="false">Content suitable for people aged above 18 years old; those who are younger that 18 must be provided with parental guidance</string>
+    <string name="description_thtv_adults" translatable="false">Content unsuitable for children and youngsters</string>
 
     <!-- TV content rating system strings for TR TV -->
     <string name="display_name_trtv" translatable="false">TR-TV</string>
@@ -5430,10 +5434,10 @@
     <string name="display_name_trtv_7" translatable="false">7+</string>
     <string name="display_name_trtv_13" translatable="false">13+</string>
     <string name="display_name_trtv_18" translatable="false">18+</string>
-    <string name="description_trtv_g">General audience. Suitable for all ages</string>
-    <string name="description_trtv_7">Suitable for ages 7 and over</string>
-    <string name="description_trtv_13">Suitable for ages 13 and over</string>
-    <string name="description_trtv_18">Suitable for ages 13 and over</string>
+    <string name="description_trtv_g" translatable="false">General audience. Suitable for all ages</string>
+    <string name="description_trtv_7" translatable="false">Suitable for ages 7 and over</string>
+    <string name="description_trtv_13" translatable="false">Suitable for ages 13 and over</string>
+    <string name="description_trtv_18" translatable="false">Suitable for ages 13 and over</string>
 
     <!-- TV content rating system strings for TW TV -->
     <string name="display_name_twtv" translatable="false">TW-TV</string>
@@ -5441,54 +5445,54 @@
     <string name="display_name_twtv_p" translatable="false">Protected category</string>
     <string name="display_name_twtv_pg" translatable="false">Parental guidance category</string>
     <string name="display_name_twtv_r" translatable="false">Restricted category</string>
-    <string name="description_twtv_g">For all ages</string>
-    <string name="description_twtv_p">Not suitable for children under 6 years old. People aged 6 but under 12 require guidance from accompanying adults to watch</string>
-    <string name="description_twtv_pg">Not suitable for people under 12 years of age. Parental guidance is required for people aged 12 but under 18</string>
-    <string name="description_twtv_r">For adults only and people under 18 years of age must not watch</string>
+    <string name="description_twtv_g" translatable="false">For all ages</string>
+    <string name="description_twtv_p" translatable="false">Not suitable for children under 6 years old. People aged 6 but under 12 require guidance from accompanying adults to watch</string>
+    <string name="description_twtv_pg" translatable="false">Not suitable for people under 12 years of age. Parental guidance is required for people aged 12 but under 18</string>
+    <string name="description_twtv_r" translatable="false">For adults only and people under 18 years of age must not watch</string>
 
     <!-- TV content rating system strings for UA TV -->
     <string name="display_name_uatv" translatable="false">UA-TV</string>
     <string name="display_name_uatv_green circle" translatable="false">Green Circle</string>
     <string name="display_name_uatv_yellow triangle" translatable="false">Yellow Triangle</string>
     <string name="display_name_uatv_red square" translatable="false">Red Square</string>
-    <string name="description_uatv_green circle">This program does not have age restrictions</string>
-    <string name="description_uatv_yellow triangle">Children must view this program with parents. In it program there are fragments, which unsuitable for children</string>
-    <string name="description_uatv_red square">This program is only for adult viewers. In it there are scenes with nudity, drug use, or violence</string>
+    <string name="description_uatv_green circle" translatable="false">This program does not have age restrictions</string>
+    <string name="description_uatv_yellow triangle" translatable="false">Children must view this program with parents. In it program there are fragments, which unsuitable for children</string>
+    <string name="description_uatv_red square" translatable="false">This program is only for adult viewers. In it there are scenes with nudity, drug use, or violence</string>
 
     <!-- TV content rating system strings for US TV -->
-    <string name="display_name_ustvpg" translatable="false">US-TV</string>
-    <string name="description_ustvpg">The TV Parental Guidelines</string>
-    <string name="display_name_ustvpg_d" translatable="false">D</string>
-    <string name="display_name_ustvpg_l" translatable="false">L</string>
-    <string name="display_name_ustvpg_s" translatable="false">S</string>
-    <string name="display_name_ustvpg_v" translatable="false">V</string>
-    <string name="display_name_ustvpg_fv" translatable="false">FV</string>
-    <string name="display_name_ustvpg_y" translatable="false">TV-Y</string>
-    <string name="display_name_ustvpg_y7" translatable="false">TV-Y7</string>
-    <string name="display_name_ustvpg_g" translatable="false">TV-G</string>
-    <string name="display_name_ustvpg_pg" translatable="false">TV-PG</string>
-    <string name="display_name_ustvpg_14" translatable="false">TV-14</string>
-    <string name="display_name_ustvpg_ma" translatable="false">TV-MA</string>
-    <string name="description_ustvpg_d">Suggestive dialogue (Usually means talks about sex)</string>
-    <string name="description_ustvpg_l">Coarse language</string>
-    <string name="description_ustvpg_s">Sexual content</string>
-    <string name="description_ustvpg_v">Violence</string>
-    <string name="description_ustvpg_fv">Fantasy violence (Children\'s programming only)</string>
-    <string name="description_ustvpg_y">This program is designed to be appropriate for all children</string>
-    <string name="description_ustvpg_y7">This program is designed for children age 7 and above</string>
-    <string name="description_ustvpg_g">Most parents would find this program suitable for all ages</string>
-    <string name="description_ustvpg_pg">This program contains material that parents may find unsuitable for younger children</string>
-    <string name="description_ustvpg_14">This program contains some material that many parents would find unsuitable for children under 14 years of age</string>
-    <string name="description_ustvpg_ma">This program is specifically designed to be viewed by adults and therefore may be unsuitable for children under 17</string>
+    <string name="display_name_ustv" translatable="false">US-TV</string>
+    <string name="description_ustv" translatable="false">TV content rating system for United States</string>
+    <string name="display_name_ustv_d" translatable="false">D</string>
+    <string name="display_name_ustv_l" translatable="false">L</string>
+    <string name="display_name_ustv_s" translatable="false">S</string>
+    <string name="display_name_ustv_v" translatable="false">V</string>
+    <string name="display_name_ustv_fv" translatable="false">FV</string>
+    <string name="display_name_ustv_y" translatable="false">TV-Y</string>
+    <string name="display_name_ustv_y7" translatable="false">TV-Y7</string>
+    <string name="display_name_ustv_g" translatable="false">TV-G</string>
+    <string name="display_name_ustv_pg" translatable="false">TV-PG</string>
+    <string name="display_name_ustv_14" translatable="false">TV-14</string>
+    <string name="display_name_ustv_ma" translatable="false">TV-MA</string>
+    <string name="description_ustv_d" translatable="false">Suggestive dialogue (Usually means talks about sex)\nApplicable to US_TV_PG, US_TV_14, US_TV</string>
+    <string name="description_ustv_l" translatable="false">Coarse language\nApplicable to US_TV_PG, US_TV_14</string>
+    <string name="description_ustv_s" translatable="false">Sexual content\nApplicable to US_TV_PG, US_TV_14, US_TV_MA</string>
+    <string name="description_ustv_v" translatable="false">Violence\nApplicable to US_TV_PG, US_TV_14, US_TV_MA</string>
+    <string name="description_ustv_fv" translatable="false">Fantasy violence (Children\'s programming only)\nApplicable to US_TV_Y7</string>
+    <string name="description_ustv_y" translatable="false">This program is designed to be appropriate for all children</string>
+    <string name="description_ustv_y7" translatable="false">This program is designed for children age 7 and above</string>
+    <string name="description_ustv_g" translatable="false">Most parents would find this program suitable for all ages</string>
+    <string name="description_ustv_pg" translatable="false">This program contains material that parents may find unsuitable for younger children</string>
+    <string name="description_ustv_14" translatable="false">This program contains some material that many parents would find unsuitable for children under 14 years of age</string>
+    <string name="description_ustv_ma" translatable="false">This program is specifically designed to be viewed by adults and therefore may be unsuitable for children under 17</string>
 
     <!-- TV content rating system strings for VE TV -->
     <string name="display_name_vetv" translatable="false">VE-TV</string>
     <string name="display_name_vetv_tu" translatable="false">TU</string>
     <string name="display_name_vetv_su" translatable="false">SU</string>
     <string name="display_name_vetv_a" translatable="false">A</string>
-    <string name="description_vetv_tu">For all ages</string>
-    <string name="description_vetv_su">Parental guidance for young viewers</string>
-    <string name="description_vetv_a">Mature viewers</string>
+    <string name="description_vetv_tu" translatable="false">For all ages</string>
+    <string name="description_vetv_su" translatable="false">Parental guidance for young viewers</string>
+    <string name="description_vetv_a" translatable="false">Mature viewers</string>
 
     <!-- TV content rating system strings for ZA TV -->
     <string name="display_name_zatv" translatable="false">ZA-TV</string>
@@ -5504,18 +5508,18 @@
     <string name="display_name_zatv_16" translatable="false">16</string>
     <string name="display_name_zatv_18" translatable="false">18</string>
     <string name="display_name_zatv_r18" translatable="false">R18</string>
-    <string name="description_zatv_d">Drug</string>
-    <string name="description_zatv_v">Violence</string>
-    <string name="description_zatv_n">Nudity</string>
-    <string name="description_zatv_p">Prejudice</string>
-    <string name="description_zatv_s">Sex</string>
-    <string name="description_zatv_l">Language</string>
-    <string name="description_zatv_f">This is a program/film that does not contain any obscenity, and is suitable for family viewing. A logo must be displayed in the corner of the screen for 30 seconds after each commercial break</string>
-    <string name="description_zatv_pg">Children under 6 may watch this program/film, but must be accompanied by an adult. This program contains an adult related theme, which might include very mild language, violence and sexual innuendo. A logo must be displayed in the corner of the screen for one minute after each commercial break</string>
-    <string name="description_zatv_13">Children under 13 are prohibited from watching this program/film. This program contains mild language, violence and sexual innuendo. A logo must be displayed in the corner of the screen for two minutes after each commercial break</string>
-    <string name="description_zatv_16">Children under 16 are prohibited from watching this program/film. It contains moderate violence, language, and some sexual situations. In the case of television, this program may only be broadcast after 9pm–4:30am. A logo must be displayed in the corner of the screen for five minutes after each commercial break. A full-screen warning must be issued before the start of the program. If the program is longer than an hour, a warning must be displayed every half an hour</string>
-    <string name="description_zatv_18">Children under 18 are prohibited from watching this program/film. It contains extreme violence, language and/or graphic sexual content. In the case of television, this program may only be broadcast from 10pm–4:30am. A logo must be displayed in the corner of the screen for the duration of the program. A full-screen warning must be issued before the start of the program and after each commercial break</string>
-    <string name="description_zatv_r18">This is reserved for films of an extreme sexual nature (pornography). R18 films may only be distributed in the form of video and DVD in a controlled environment (e.g. Adult Shops). No public viewing of this film may take place. R18 films may not be broadcast on television and in cinemas</string>
+    <string name="description_zatv_d" translatable="false">Drug\nApplicable to ZA_TV_F, ZA_TV_PG, ZA_TV_13, ZA_TV_16, ZA_TV_18, ZA_TV_R18</string>
+    <string name="description_zatv_v" translatable="false">Violence\nApplicable to ZA_TV_F, ZA_TV_PG, ZA_TV_13, ZA_TV_16, ZA_TV_18, ZA_TV_R18</string>
+    <string name="description_zatv_n" translatable="false">Nudity\nApplicable to ZA_TV_F, ZA_TV_PG, ZA_TV_13, ZA_TV_16, ZA_TV_18, ZA_TV_R18</string>
+    <string name="description_zatv_p" translatable="false">Prejudice\nApplicable to ZA_TV_F, ZA_TV_PG, ZA_TV_13, ZA_TV_16, ZA_TV_18, ZA_TV_R18</string>
+    <string name="description_zatv_s" translatable="false">Sex\nApplicable to ZA_TV_F, ZA_TV_PG, ZA_TV_13, ZA_TV_16, ZA_TV_18, ZA_TV_R18</string>
+    <string name="description_zatv_l" translatable="false">Language\nApplicable to ZA_TV_F, ZA_TV_PG, ZA_TV_13, ZA_TV_16, ZA_TV_18, ZA_TV_R18</string>
+    <string name="description_zatv_f" translatable="false">This is a program/film that does not contain any obscenity, and is suitable for family viewing. A logo must be displayed in the corner of the screen for 30 seconds after each commercial break</string>
+    <string name="description_zatv_pg" translatable="false">Children under 6 may watch this program/film, but must be accompanied by an adult. This program contains an adult related theme, which might include very mild language, violence and sexual innuendo. A logo must be displayed in the corner of the screen for one minute after each commercial break</string>
+    <string name="description_zatv_13" translatable="false">Children under 13 are prohibited from watching this program/film. This program contains mild language, violence and sexual innuendo. A logo must be displayed in the corner of the screen for two minutes after each commercial break</string>
+    <string name="description_zatv_16" translatable="false">Children under 16 are prohibited from watching this program/film. It contains moderate violence, language, and some sexual situations. In the case of television, this program may only be broadcast after 9pm-4:30am. A logo must be displayed in the corner of the screen for five minutes after each commercial break. A full-screen warning must be issued before the start of the program. If the program is longer than an hour, a warning must be displayed every half an hour</string>
+    <string name="description_zatv_18" translatable="false">Children under 18 are prohibited from watching this program/film. It contains extreme violence, language and/or graphic sexual content. In the case of television, this program may only be broadcast from 10pm-4:30am. A logo must be displayed in the corner of the screen for the duration of the program. A full-screen warning must be issued before the start of the program and after each commercial break</string>
+    <string name="description_zatv_r18" translatable="false">This is reserved for films of an extreme sexual nature (pornography). R18 films may only be distributed in the form of video and DVD in a controlled environment (e.g. Adult Shops). No public viewing of this film may take place. R18 films may not be broadcast on television and in cinemas</string>
 
     <!-- [CHAR_LIMIT=NONE] Battery saver: Feature description -->
     <string name="battery_saver_description">To help improve battery life, battery saver reduces your device’s performance and limits vibration and most background data. Email, messaging, and other apps that rely on syncing may not update unless you open them.\n\nBattery saver turns off automatically when your device is charging</string>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 35baf9c..8fc9bac 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1360,7 +1360,7 @@
         <item name="lightZ">800dp</item>
         <item name="lightRadius">800dp</item>
         <item name="ambientShadowAlpha">0.06</item>
-        <item name="spotShadowAlpha">0.22</item>
+        <item name="spotShadowAlpha">0.16</item>
     </style>
 
 </resources>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 97d4bf6..f028222 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -426,7 +426,6 @@
     <style name="Widget.Material.Button" parent="Widget.Button">
         <item name="background">@drawable/btn_default_material</item>
         <item name="textAppearance">?attr/textAppearanceButton</item>
-        <item name="textColor">?attr/textColorPrimary</item>
         <item name="minHeight">48dip</item>
         <item name="minWidth">88dip</item>
         <item name="stateListAnimator">@anim/button_state_list_anim_material</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 0ebf0b5..a4bec17d 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -349,6 +349,7 @@
   <java-symbol type="dimen" name="notification_text_size" />
   <java-symbol type="dimen" name="notification_title_text_size" />
   <java-symbol type="dimen" name="notification_subtext_size" />
+  <java-symbol type="dimen" name="notification_large_font_vert_pad" />
   <java-symbol type="dimen" name="immersive_mode_cling_width" />
   <java-symbol type="dimen" name="circular_display_mask_offset" />
 
@@ -609,9 +610,11 @@
   <java-symbol type="string" name="last_month" />
   <java-symbol type="string" name="launchBrowserDefault" />
   <java-symbol type="string" name="lock_to_app_toast" />
+  <java-symbol type="string" name="lock_to_app_toast_accessible" />
   <java-symbol type="string" name="lock_to_app_toast_locked" />
   <java-symbol type="string" name="lock_to_app_title" />
   <java-symbol type="string" name="lock_to_app_description" />
+  <java-symbol type="string" name="lock_to_app_description_accessible" />
   <java-symbol type="string" name="lock_to_app_negative" />
   <java-symbol type="string" name="lock_to_app_positive" />
   <java-symbol type="layout" name="lock_to_app_checkbox" />
@@ -1699,7 +1702,6 @@
   <java-symbol type="layout" name="notification_template_material_base" />
   <java-symbol type="layout" name="notification_template_material_big_base" />
   <java-symbol type="layout" name="notification_template_material_big_picture" />
-  <java-symbol type="layout" name="notification_template_material_big_text" />
   <java-symbol type="layout" name="notification_template_material_inbox" />
   <java-symbol type="layout" name="notification_template_material_media" />
   <java-symbol type="layout" name="notification_template_material_big_media" />
@@ -1721,11 +1723,11 @@
   <java-symbol type="anim" name="push_up_out" />
   <java-symbol type="anim" name="lock_screen_behind_enter" />
   <java-symbol type="anim" name="lock_screen_behind_enter_wallpaper" />
+  <java-symbol type="anim" name="lock_screen_behind_enter_fade_in" />
   <java-symbol type="anim" name="lock_screen_wallpaper_exit" />
 
   <java-symbol type="bool" name="config_alwaysUseCdmaRssi" />
   <java-symbol type="dimen" name="status_bar_icon_size" />
-  <java-symbol type="dimen" name="system_bar_icon_size" />
   <java-symbol type="drawable" name="list_selector_pressed_holo_dark" />
   <java-symbol type="drawable" name="scrubber_control_disabled_holo" />
   <java-symbol type="drawable" name="scrubber_control_selector_holo" />
@@ -1978,4 +1980,8 @@
   <java-symbol type="bool" name="config_sms_decode_gsm_8bit_data" />
   <java-symbol type="string" name="time_picker_am_label" />
   <java-symbol type="string" name="time_picker_pm_label" />
+  <java-symbol type="dimen" name="text_size_small_material" />
+  <java-symbol type="attr" name="checkMarkGravity" />
+  <java-symbol type="layout" name="select_dialog_singlechoice_material" />
+  <java-symbol type="layout" name="select_dialog_multichoice_material" />
 </resources>
diff --git a/core/res/res/xml/tv_content_rating_systems.xml b/core/res/res/xml/tv_content_rating_systems.xml
index 8e2a23c..1318274 100644
--- a/core/res/res/xml/tv_content_rating_systems.xml
+++ b/core/res/res/xml/tv_content_rating_systems.xml
@@ -1549,75 +1549,75 @@
     </rating-system-definition>
 
     <!-- TV content rating system for US TV -->
-    <rating-system-definition id="US_TVPG"
-        displayName="@string/display_name_ustvpg"
-        description="@string/description_ustvpg"
+    <rating-system-definition id="US_TV"
+        displayName="@string/display_name_ustv"
+        description="@string/description_ustv"
         country="US">
-        <sub-rating-definition id="US_TVPG_D"
-            displayName="@string/display_name_ustvpg_d"
-            description="@string/description_ustvpg_d" />
-        <sub-rating-definition id="US_TVPG_L"
-            displayName="@string/display_name_ustvpg_l"
-            description="@string/description_ustvpg_l" />
-        <sub-rating-definition id="US_TVPG_S"
-            displayName="@string/display_name_ustvpg_s"
-            description="@string/description_ustvpg_s" />
-        <sub-rating-definition id="US_TVPG_V"
-            displayName="@string/display_name_ustvpg_v"
-            description="@string/description_ustvpg_v" />
-        <sub-rating-definition id="US_TVPG_FV"
-            displayName="@string/display_name_ustvpg_fv"
-            description="@string/description_ustvpg_fv" />
+        <sub-rating-definition id="US_TV_D"
+            displayName="@string/display_name_ustv_d"
+            description="@string/description_ustv_d" />
+        <sub-rating-definition id="US_TV_L"
+            displayName="@string/display_name_ustv_l"
+            description="@string/description_ustv_l" />
+        <sub-rating-definition id="US_TV_S"
+            displayName="@string/display_name_ustv_s"
+            description="@string/description_ustv_s" />
+        <sub-rating-definition id="US_TV_V"
+            displayName="@string/display_name_ustv_v"
+            description="@string/description_ustv_v" />
+        <sub-rating-definition id="US_TV_FV"
+            displayName="@string/display_name_ustv_fv"
+            description="@string/description_ustv_fv" />
 
-        <rating-definition id="US_TVPG_TV_Y"
-            displayName="@string/display_name_ustvpg_y"
-            description="@string/description_ustvpg_y"
+        <rating-definition id="US_TV_Y"
+            displayName="@string/display_name_ustv_y"
+            description="@string/description_ustv_y"
             ageHint="0" />
-        <rating-definition id="US_TVPG_TV_Y7"
-            displayName="@string/display_name_ustvpg_y7"
-            description="@string/description_ustvpg_y7"
+        <rating-definition id="US_TV_Y7"
+            displayName="@string/display_name_ustv_y7"
+            description="@string/description_ustv_y7"
             ageHint="7">
-            <sub-rating id="US_TVPG_FV" />
+            <sub-rating id="US_TV_FV" />
         </rating-definition>
-        <rating-definition id="US_TVPG_TV_G"
-            displayName="@string/display_name_ustvpg_g"
-            description="@string/description_ustvpg_g"
+        <rating-definition id="US_TV_G"
+            displayName="@string/display_name_ustv_g"
+            description="@string/description_ustv_g"
             ageHint="0" />
-        <rating-definition id="US_TVPG_TV_PG"
-            displayName="@string/display_name_ustvpg_pg"
-            description="@string/description_ustvpg_pg"
+        <rating-definition id="US_TV_PG"
+            displayName="@string/display_name_ustv_pg"
+            description="@string/description_ustv_pg"
             ageHint="14">
-            <sub-rating id="US_TVPG_D" />
-            <sub-rating id="US_TVPG_L" />
-            <sub-rating id="US_TVPG_S" />
-            <sub-rating id="US_TVPG_V" />
+            <sub-rating id="US_TV_D" />
+            <sub-rating id="US_TV_L" />
+            <sub-rating id="US_TV_S" />
+            <sub-rating id="US_TV_V" />
         </rating-definition>
-        <rating-definition id="US_TVPG_TV_14"
-            displayName="@string/display_name_ustvpg_14"
-            description="@string/description_ustvpg_14"
+        <rating-definition id="US_TV_14"
+            displayName="@string/display_name_ustv_14"
+            description="@string/description_ustv_14"
             ageHint="14">
-            <sub-rating id="US_TVPG_D" />
-            <sub-rating id="US_TVPG_L" />
-            <sub-rating id="US_TVPG_S" />
-            <sub-rating id="US_TVPG_V" />
+            <sub-rating id="US_TV_D" />
+            <sub-rating id="US_TV_L" />
+            <sub-rating id="US_TV_S" />
+            <sub-rating id="US_TV_V" />
         </rating-definition>
-        <rating-definition id="US_TVPG_TV_MA"
-            displayName="@string/display_name_ustvpg_ma"
-            description="@string/description_ustvpg_ma"
+        <rating-definition id="US_TV_MA"
+            displayName="@string/display_name_ustv_ma"
+            description="@string/description_ustv_ma"
             ageHint="17">
-            <sub-rating id="US_TVPG_L" />
-            <sub-rating id="US_TVPG_S" />
-            <sub-rating id="US_TVPG_V" />
+            <sub-rating id="US_TV_L" />
+            <sub-rating id="US_TV_S" />
+            <sub-rating id="US_TV_V" />
         </rating-definition>
         <order>
-            <rating id="US_TVPG_TV_Y" />
-            <rating id="US_TVPG_TV_Y7" />
+            <rating id="US_TV_Y" />
+            <rating id="US_TV_Y7" />
         </order>
         <order>
-            <rating id="US_TVPG_TV_G" />
-            <rating id="US_TVPG_TV_PG" />
-            <rating id="US_TVPG_TV_14" />
-            <rating id="US_TVPG_TV_MA" />
+            <rating id="US_TV_G" />
+            <rating id="US_TV_PG" />
+            <rating id="US_TV_14" />
+            <rating id="US_TV_MA" />
         </order>
     </rating-system-definition>
 
diff --git a/core/tests/coretests/src/android/net/RouteInfoTest.java b/core/tests/coretests/src/android/net/RouteInfoTest.java
index dcacd11..0b88bc7 100644
--- a/core/tests/coretests/src/android/net/RouteInfoTest.java
+++ b/core/tests/coretests/src/android/net/RouteInfoTest.java
@@ -214,6 +214,29 @@
       assertFalse(r.isIPv6Default());
     }
 
+    public void testTruncation() {
+      LinkAddress l;
+      RouteInfo r;
+
+      l = new LinkAddress("192.0.2.5/30");
+      r = new RouteInfo(l, Address("192.0.2.1"), "wlan0");
+      assertEquals("192.0.2.4", r.getDestination().getAddress().getHostAddress());
+
+      l = new LinkAddress("2001:db8:1:f::5/63");
+      r = new RouteInfo(l, Address("2001:db8:5::1"), "wlan0");
+      assertEquals("2001:db8:1:e::", r.getDestination().getAddress().getHostAddress());
+    }
+
+    // Make sure that creating routes to multicast addresses doesn't throw an exception. Even though
+    // there's nothing we can do with them, we don't want to crash if, e.g., someone calls
+    // requestRouteToHostAddress("230.0.0.0", MOBILE_HIPRI);
+    public void testMulticastRoute() {
+      RouteInfo r;
+      r = new RouteInfo(Prefix("230.0.0.0/32"), Address("192.0.2.1"), "wlan0");
+      r = new RouteInfo(Prefix("ff02::1/128"), Address("2001:db8::1"), "wlan0");
+      // No exceptions? Good.
+    }
+
     public RouteInfo passThroughParcel(RouteInfo r) {
         Parcel p = Parcel.obtain();
         RouteInfo r2 = null;
diff --git a/docs/html/google/gcm/ccs.jd b/docs/html/google/gcm/ccs.jd
index 90d8d4c..1c7c802 100644
--- a/docs/html/google/gcm/ccs.jd
+++ b/docs/html/google/gcm/ccs.jd
@@ -40,8 +40,6 @@
 <li><a href="{@docRoot}google/gcm/gs.html">Getting Started</a></li>
 <li><a href="{@docRoot}google/gcm/server.html">Implementing GCM Server</a></li>
 <li><a href="{@docRoot}google/gcm/client.html">Implementing GCM Client</a></li>
-<li><a href="https://services.google.com/fb/forms/gcm/" class="external-link"
-target="_android">CCS and User Notifications Signup Form</a></li>
 </ol>
 
 </div>
diff --git a/docs/html/google/gcm/gs.jd b/docs/html/google/gcm/gs.jd
index 4cfe1bc..ae57b6d 100644
--- a/docs/html/google/gcm/gs.jd
+++ b/docs/html/google/gcm/gs.jd
@@ -20,7 +20,6 @@
 <ol class="toc">
 <li><a href="https://cloud.google.com/console">Google Cloud Console</a></li>
 <li><a href="https://developers.google.com/console/help/new/">Google Cloud Console Help</a></li>
-<li><a href="https://services.google.com/fb/forms/gcm/" class="external-link" target="_android">CCS and User Notifications Signup Form</a></li>
 </ol>
 
 </div>
diff --git a/docs/html/preview/api-overview.jd b/docs/html/preview/api-overview.jd
index cf594dc..beea0ca 100644
--- a/docs/html/preview/api-overview.jd
+++ b/docs/html/preview/api-overview.jd
@@ -19,6 +19,7 @@
       <li><a href="#BehaviorNotifications">If your app implements notifications...</a></li>
       <li><a href="#BehaviorMediaControl">If your app uses RemoteControlClient...</a></li>
 <li><a href="#BehaviorGetRecentTasks">If your app uses ActivityManager.getRecentTasks()...</a></li>
+<li><a href="#64BitSupport">If you are using the Android Native Development Kit (NDK)...</a></li>
     </ol>
   </li>
   <li><a href="#UI">User Interface</a>
@@ -246,6 +247,29 @@
 its own tasks, use {@code android.app.ActivityManager.getAppTasks()} instead to
 retrieve that information.</p>
 
+<h3 id="64BitSupport">If you are using the Android Native Development Kit (NDK)...</h3>
+
+<p>The L Developer Preview introduces support for 64-bit systems and other
+  preview NDK APIs. The 64-bit enhancement adds needed address space as Android
+  usage diversifies and increases performance while still supporting existing
+  32-bit apps fully. Use of OpenSSL for cryptography in the platform is also
+  faster. In addition, this release introduces new native audio and media NDK
+  APIs and native OpenGL ES (GLES) 3.1 support.</p>
+
+<p>To use this enhancement, download and install NDK Revision 10 from the
+<a href="{@docRoot}tools/sdk/ndk/index.html">Android NDK page</a>. Refer to the
+Revision 10 <a href="{@docRoot}tools/sdk/ndk/index.html#Revisions">release notes</a>
+for more information about important changes and bug fixes to the NDK.</p>
+
+<p>If you are using the NDK and want to use the features provided in the L
+  Developer Preview, download the {@code android-ndk64-r10} package for your
+  target platform. Due to a
+  <a href="https://code.google.com/p/android/issues/detail?id=73705">known issue</a>,
+  you must still download the 64-bit package even if you only want to compile
+  apps for 32-bit systems. The package also includes
+  the {@code gcc-4.9} compiler for both 32- and 64-bit apps. The L Developer
+  Preview API library is located under the {@code platforms/android-L/} API directory.</p>
+
 <h2 id="UI">User Interface</h2>
 
 <h3 id="MaterialDesign">Material design support</h3>
diff --git a/docs/html/preview/support.jd b/docs/html/preview/support.jd
index 9d7844b..3220d63 100644
--- a/docs/html/preview/support.jd
+++ b/docs/html/preview/support.jd
@@ -106,3 +106,15 @@
 <li>Deleting a Android work profile may take several minutes to complete. You
 cannot create a new Android work profile until the deletion operation is over.</li>
 </ul>
+
+<h3 id="64bitsupport">64-bit support</h3>
+<ul>
+<li><p>If you are using the NDK to compile apps for 32- or 64-bit systems and
+want to use the features provided in the L Developer Preview, download the
+{@code android-ndk64-r10} package for your target platform from the
+<a href="{@docRoot}tools/sdk/ndk/index.html">Android NDK page</a>. The
+{@code android-ndk64-r10} package contains the L Developer Preview API
+library (located under the {@code platforms/android-L/} API directory) for both
+32- and 64-bit systems. The package also includes the {@code gcc-4.9} compiler
+for both 32- and 64-bit apps.</p></li>
+</ul>
diff --git a/docs/html/training/volley/index.jd b/docs/html/training/volley/index.jd
index ba5b09f..97bddae 100644
--- a/docs/html/training/volley/index.jd
+++ b/docs/html/training/volley/index.jd
@@ -20,21 +20,6 @@
   <li>Android 1.6 (API Level 4) or higher</li>
 </ul>
 
-<h2>You should also see</h2>
-<ul>
-  <li>For a production quality app that uses Volley, see the 2013 Google I/O
-  <a href="https://github.com/google/iosched">schedule app</a>. In particular, see:
-    <ul>
-      <li><a
-      href="https://github.com/google/iosched/blob/master/android/src/main/java/com/google/android/apps/iosched/util/ImageLoader.java">
-      ImageLoader</a></li>
-      <li><a
-      href="https://github.com/google/iosched/blob/master/android/src/main/java/com/google/android/apps/iosched/util/BitmapCache.java">
-      BitmapCache</a></li>
-    </ul>
-  </li>
-</ul>
-
 </div>
 </div>
 
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 0dc903a..06586ca 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -132,6 +132,9 @@
      * @return The best matching typeface.
      */
     public static Typeface create(Typeface family, int style) {
+        if (style < 0 || style > 3) {
+            style = 0;
+        }
         long ni = 0;
         if (family != null) {
             // Return early if we're asked for the same face/style
diff --git a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
index e3c03a9..0bc4fdf 100644
--- a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
@@ -275,7 +275,7 @@
         final int res = a.getResourceId(R.styleable.AnimatedRotateDrawable_drawable, 0);
         Drawable drawable = null;
         if (res > 0) {
-            drawable = r.getDrawable(res);
+            drawable = r.getDrawable(res, theme);
         }
 
         a.recycle();
diff --git a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
index 2cb7b03..fc38e8a 100644
--- a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
@@ -427,7 +427,7 @@
 
         final Drawable dr;
         if (drawableRes != 0) {
-            dr = r.getDrawable(drawableRes);
+            dr = r.getDrawable(drawableRes, theme);
         } else {
             int type;
             while ((type = parser.next()) == XmlPullParser.TEXT) {
@@ -473,7 +473,7 @@
 
         final Drawable dr;
         if (drawableRes != 0) {
-            dr = r.getDrawable(drawableRes);
+            dr = r.getDrawable(drawableRes, theme);
         } else {
             int type;
             while ((type = parser.next()) == XmlPullParser.TEXT) {
diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java
index cef3377..5318fa7 100644
--- a/graphics/java/android/graphics/drawable/AnimationDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java
@@ -313,7 +313,7 @@
 
             Drawable dr;
             if (drawableRes != 0) {
-                dr = r.getDrawable(drawableRes);
+                dr = r.getDrawable(drawableRes, theme);
             } else {
                 while ((type=parser.next()) == XmlPullParser.TEXT) {
                     // Empty
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index f097239..ea9f732 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -157,6 +157,12 @@
     private boolean mOverrideBounds;
 
     /**
+     * Whether hotspots are being cleared. Used to prevent re-entry by
+     * animation finish listeners.
+     */
+    private boolean mClearingHotspots;
+
+    /**
      * Constructor used for drawable inflation.
      */
     RippleDrawable() {
@@ -524,6 +530,8 @@
     }
 
     private void clearHotspots() {
+        mClearingHotspots = true;
+
         final int count = mAnimatingRipplesCount;
         final Ripple[] ripples = mAnimatingRipples;
         for (int i = 0; i < count; i++) {
@@ -532,11 +540,6 @@
             final Ripple ripple = ripples[i];
             ripples[i] = null;
             ripple.cancel();
-
-            // The active ripple may also be animating. Don't cancel it twice.
-            if (mRipple == ripple) {
-                mRipple = null;
-            }
         }
 
         if (mRipple != null) {
@@ -549,6 +552,7 @@
             mBackground = null;
         }
 
+        mClearingHotspots = false;
         mAnimatingRipplesCount = 0;
         invalidateSelf();
     }
@@ -647,15 +651,17 @@
      * @param ripple the ripple to remove
      */
     void removeRipple(Ripple ripple) {
-        // Ripple ripple ripple ripple. Ripple ripple.
-        final Ripple[] ripples = mAnimatingRipples;
-        final int count = mAnimatingRipplesCount;
-        final int index = getRippleIndex(ripple);
-        if (index >= 0) {
-            System.arraycopy(ripples, index + 1, ripples, index + 1 - 1, count - (index + 1));
-            ripples[count - 1] = null;
-            mAnimatingRipplesCount--;
-            invalidateSelf();
+        if (!mClearingHotspots) {
+            // Ripple ripple ripple ripple. Ripple ripple.
+            final Ripple[] ripples = mAnimatingRipples;
+            final int count = mAnimatingRipplesCount;
+            final int index = getRippleIndex(ripple);
+            if (index >= 0) {
+                System.arraycopy(ripples, index + 1, ripples, index + 1 - 1, count - (index + 1));
+                ripples[count - 1] = null;
+                mAnimatingRipplesCount--;
+                invalidateSelf();
+            }
         }
     }
 
diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java
index 983eb3b..63b9e02 100644
--- a/graphics/java/android/graphics/drawable/RotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/RotateDrawable.java
@@ -436,7 +436,7 @@
                 com.android.internal.R.styleable.RotateDrawable_drawable, 0);
         Drawable drawable = null;
         if (res > 0) {
-            drawable = r.getDrawable(res);
+            drawable = r.getDrawable(res, theme);
         }
 
         a.recycle();
diff --git a/libs/hwui/AmbientShadow.cpp b/libs/hwui/AmbientShadow.cpp
index 181230a..9cc83ed 100644
--- a/libs/hwui/AmbientShadow.cpp
+++ b/libs/hwui/AmbientShadow.cpp
@@ -117,10 +117,13 @@
 
         // inner ring of points
         float opacity = 1.0 / (1 + rayHeight[rayIndex] * heightFactor);
+        // NOTE: Shadow alpha values are transformed when stored in alphavertices,
+        // so that they can be consumed directly by gFS_Main_ApplyVertexAlphaShadowInterp
+        float transformedOpacity = acos(1.0f - 2.0f * opacity);
         AlphaVertex::set(&shadowVertices[rays + rayIndex],
                 intersection.x,
                 intersection.y,
-                opacity);
+                transformedOpacity);
     }
 
     if (isCasterOpaque) {
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 7bd0798..5689e17 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -703,6 +703,8 @@
     propertyLightPosY = -1.0f;
     propertyLightPosZ = -1.0f;
     propertyAmbientRatio = -1.0f;
+    propertyAmbientShadowStrength = -1;
+    propertySpotShadowStrength = -1;
 }
 
 void Caches::setTempProperty(const char* name, const char* value) {
@@ -723,6 +725,14 @@
         propertyLightPosZ = fmin(fmax(atof(value), 0.0), 3000.0);
         ALOGD("lightPos Z = %.2f", propertyLightPosZ);
         return;
+    } else if (!strcmp(name, "ambientShadowStrength")) {
+        propertyAmbientShadowStrength = atoi(value);
+        ALOGD("ambient shadow strength = 0x%x out of 0xff", propertyAmbientShadowStrength);
+        return;
+    } else if (!strcmp(name, "spotShadowStrength")) {
+        propertySpotShadowStrength = atoi(value);
+        ALOGD("spot shadow strength = 0x%x out of 0xff", propertySpotShadowStrength);
+        return;
     }
     ALOGD("    failed");
 }
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index e00cb0b..0482430 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -366,6 +366,9 @@
     float propertyLightPosY;
     float propertyLightPosZ;
     float propertyAmbientRatio;
+    int propertyAmbientShadowStrength;
+    int propertySpotShadowStrength;
+
 private:
     enum OverdrawColorSet {
         kColorSet_Default = 0,
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 7123bfe..3fcfbc1 100755
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1641,9 +1641,9 @@
     mCaches.disableTexCoordsVertexArray();
 }
 
-void OpenGLRenderer::setupDrawAA(bool useShadowInterp) {
-    mDescription.isAA = true;
-    mDescription.isShadowAA = useShadowInterp;
+void OpenGLRenderer::setupDrawVertexAlpha(bool useShadowAlphaInterp) {
+    mDescription.hasVertexAlpha = true;
+    mDescription.useShadowAlphaInterp = useShadowAlphaInterp;
 }
 
 void OpenGLRenderer::setupDrawColor(int color, int alpha) {
@@ -2382,7 +2382,7 @@
 
     setupDraw();
     setupDrawNoTexture();
-    if (isAA) setupDrawAA((displayFlags & kVertexBuffer_ShadowAA));
+    if (isAA) setupDrawVertexAlpha((displayFlags & kVertexBuffer_ShadowInterp));
     setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha);
     setupDrawColorFilter(getColorFilter(paint));
     setupDrawShader(getShader(paint));
@@ -3166,14 +3166,23 @@
     SkPaint paint;
     paint.setAntiAlias(true); // want to use AlphaVertex
 
-    if (ambientShadowVertexBuffer && mAmbientShadowAlpha > 0) {
-        paint.setARGB(casterAlpha * mAmbientShadowAlpha, 0, 0, 0);
-        drawVertexBuffer(*ambientShadowVertexBuffer, &paint, kVertexBuffer_ShadowAA);
+    // The caller has made sure casterAlpha > 0.
+    float ambientShadowAlpha = mAmbientShadowAlpha;
+    if (CC_UNLIKELY(mCaches.propertyAmbientShadowStrength >= 0)) {
+        ambientShadowAlpha = mCaches.propertyAmbientShadowStrength;
+    }
+    if (ambientShadowVertexBuffer && ambientShadowAlpha > 0) {
+        paint.setARGB(casterAlpha * ambientShadowAlpha, 0, 0, 0);
+        drawVertexBuffer(*ambientShadowVertexBuffer, &paint, kVertexBuffer_ShadowInterp);
     }
 
-    if (spotShadowVertexBuffer && mSpotShadowAlpha > 0) {
-        paint.setARGB(casterAlpha * mSpotShadowAlpha, 0, 0, 0);
-        drawVertexBuffer(*spotShadowVertexBuffer, &paint, kVertexBuffer_ShadowAA);
+    float spotShadowAlpha = mSpotShadowAlpha;
+    if (CC_UNLIKELY(mCaches.propertySpotShadowStrength >= 0)) {
+        spotShadowAlpha = mCaches.propertySpotShadowStrength;
+    }
+    if (spotShadowVertexBuffer && spotShadowAlpha > 0) {
+        paint.setARGB(casterAlpha * spotShadowAlpha, 0, 0, 0);
+        drawVertexBuffer(*spotShadowVertexBuffer, &paint, kVertexBuffer_ShadowInterp);
     }
 
     return DrawGlInfo::kStatusDrew;
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 2a9badd..fc95c18 100755
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -96,7 +96,7 @@
 
 enum VertexBufferDisplayFlags {
     kVertexBuffer_Offset = 0x1,
-    kVertexBuffer_ShadowAA = 0x2,
+    kVertexBuffer_ShadowInterp = 0x2,
 };
 
 /**
@@ -847,7 +847,7 @@
     void setupDrawWithTextureAndColor(bool isAlpha8 = false);
     void setupDrawWithExternalTexture();
     void setupDrawNoTexture();
-    void setupDrawAA(bool useShadowInterp);
+    void setupDrawVertexAlpha(bool useShadowAlphaInterp);
     void setupDrawColor(int color, int alpha);
     void setupDrawColor(float r, float g, float b, float a);
     void setupDrawAlpha8Color(int color, int alpha);
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index 1d95c40..56773f4 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -71,8 +71,8 @@
 #define PROGRAM_GRADIENT_TYPE_SHIFT 33 // 2 bits for gradient type
 #define PROGRAM_MODULATE_SHIFT 35
 
-#define PROGRAM_HAS_AA_SHIFT 36
-#define PROGRAM_HAS_SHADOW_AA_SHIFT 37
+#define PROGRAM_HAS_VERTEX_ALPHA_SHIFT 36
+#define PROGRAM_USE_SHADOW_ALPHA_INTERP_SHIFT 37
 
 #define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38
 #define PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT 39
@@ -135,8 +135,8 @@
     bool hasBitmap;
     bool isBitmapNpot;
 
-    bool isAA; // drawing with a per-vertex alpha
-    bool isShadowAA; // drawing per vertex alpha with shadow interpolation
+    bool hasVertexAlpha;
+    bool useShadowAlphaInterp;
 
     bool hasGradient;
     Gradient gradientType;
@@ -176,8 +176,8 @@
 
         hasColors = false;
 
-        isAA = false;
-        isShadowAA = false;
+        hasVertexAlpha = false;
+        useShadowAlphaInterp = false;
 
         modulate = false;
 
@@ -264,8 +264,8 @@
         key |= (framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
         if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST;
         if (modulate) key |= programid(0x1) << PROGRAM_MODULATE_SHIFT;
-        if (isAA) key |= programid(0x1) << PROGRAM_HAS_AA_SHIFT;
-        if (isShadowAA) key |= programid(0x1) << PROGRAM_HAS_SHADOW_AA_SHIFT;
+        if (hasVertexAlpha) key |= programid(0x1) << PROGRAM_HAS_VERTEX_ALPHA_SHIFT;
+        if (useShadowAlphaInterp) key |= programid(0x1) << PROGRAM_USE_SHADOW_ALPHA_INTERP_SHIFT;
         if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT;
         if (hasTextureTransform) key |= programid(0x1) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT;
         if (hasGammaCorrection) key |= programid(0x1) << PROGRAM_HAS_GAMMA_CORRECTION;
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 2dd89b8..c802b18 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -46,7 +46,7 @@
         "attribute vec2 texCoords;\n";
 const char* gVS_Header_Attributes_Colors =
         "attribute vec4 colors;\n";
-const char* gVS_Header_Attributes_AAVertexShapeParameters =
+const char* gVS_Header_Attributes_VertexAlphaParameters =
         "attribute float vtxAlpha;\n";
 const char* gVS_Header_Uniforms_TextureTransform =
         "uniform mat4 mainTextureTransform;\n";
@@ -64,7 +64,7 @@
         "varying vec2 outTexCoords;\n";
 const char* gVS_Header_Varyings_HasColors =
         "varying vec4 outColors;\n";
-const char* gVS_Header_Varyings_IsAAVertexShape =
+const char* gVS_Header_Varyings_HasVertexAlpha =
         "varying float alpha;\n";
 const char* gVS_Header_Varyings_HasBitmap =
         "varying highp vec2 outBitmapTexCoords;\n";
@@ -122,9 +122,7 @@
         "    vec4 transformedPosition = projection * transform * position;\n"
         "    gl_Position = transformedPosition;\n";
 
-const char* gVS_Main_ShadowAAVertexShape =
-        "    alpha = pow(vtxAlpha, 0.667);\n";
-const char* gVS_Main_AAVertexShape =
+const char* gVS_Main_VertexAlpha =
         "    alpha = vtxAlpha;\n";
 
 const char* gVS_Main_HasRoundRectClip =
@@ -239,10 +237,10 @@
         "    fragColor = color;\n";
 const char* gFS_Main_ModulateColor =
         "    fragColor *= color.a;\n";
-const char* gFS_Main_AccountForAAVertexShape =
+const char* gFS_Main_ApplyVertexAlphaLinearInterp =
         "    fragColor *= alpha;\n";
-const char* gFS_Main_AccountForShadowAAVertexShape =
-        "    fragColor *= pow(alpha, 1.5);\n";
+const char* gFS_Main_ApplyVertexAlphaShadowInterp =
+        "    fragColor *= (1.0 - cos(alpha)) / 2.0;\n";
 
 const char* gFS_Main_FetchTexture[2] = {
         // Don't modulate
@@ -473,8 +471,8 @@
     if (description.hasTexture || description.hasExternalTexture) {
         shader.append(gVS_Header_Attributes_TexCoords);
     }
-    if (description.isAA) {
-        shader.append(gVS_Header_Attributes_AAVertexShapeParameters);
+    if (description.hasVertexAlpha) {
+        shader.append(gVS_Header_Attributes_VertexAlphaParameters);
     }
     if (description.hasColors) {
         shader.append(gVS_Header_Attributes_Colors);
@@ -497,8 +495,8 @@
     if (description.hasTexture || description.hasExternalTexture) {
         shader.append(gVS_Header_Varyings_HasTexture);
     }
-    if (description.isAA) {
-        shader.append(gVS_Header_Varyings_IsAAVertexShape);
+    if (description.hasVertexAlpha) {
+        shader.append(gVS_Header_Varyings_HasVertexAlpha);
     }
     if (description.hasColors) {
         shader.append(gVS_Header_Varyings_HasColors);
@@ -520,12 +518,8 @@
         } else if (description.hasTexture || description.hasExternalTexture) {
             shader.append(gVS_Main_OutTexCoords);
         }
-        if (description.isAA) {
-            if (description.isShadowAA) {
-                shader.append(gVS_Main_ShadowAAVertexShape);
-            } else {
-                shader.append(gVS_Main_AAVertexShape);
-            }
+        if (description.hasVertexAlpha) {
+            shader.append(gVS_Main_VertexAlpha);
         }
         if (description.hasColors) {
             shader.append(gVS_Main_OutColors);
@@ -575,8 +569,8 @@
     if (description.hasTexture || description.hasExternalTexture) {
         shader.append(gVS_Header_Varyings_HasTexture);
     }
-    if (description.isAA) {
-        shader.append(gVS_Header_Varyings_IsAAVertexShape);
+    if (description.hasVertexAlpha) {
+        shader.append(gVS_Header_Varyings_HasVertexAlpha);
     }
     if (description.hasColors) {
         shader.append(gVS_Header_Varyings_HasColors);
@@ -617,7 +611,7 @@
     }
 
     // Optimization for common cases
-    if (!description.isAA
+    if (!description.hasVertexAlpha
             && !blendFramebuffer
             && !description.hasColors
             && description.colorOp == ProgramDescription::kColorNone
@@ -759,11 +753,11 @@
         // Apply the color op if needed
         shader.append(gFS_Main_ApplyColorOp[description.colorOp]);
 
-        if (description.isAA) {
-            if (description.isShadowAA) {
-                shader.append(gFS_Main_AccountForShadowAAVertexShape);
+        if (description.hasVertexAlpha) {
+            if (description.useShadowAlphaInterp) {
+                shader.append(gFS_Main_ApplyVertexAlphaShadowInterp);
             } else {
-                shader.append(gFS_Main_AccountForAAVertexShape);
+                shader.append(gFS_Main_ApplyVertexAlphaLinearInterp);
             }
         }
 
diff --git a/libs/hwui/SpotShadow.cpp b/libs/hwui/SpotShadow.cpp
index 8c3077b..d726538 100644
--- a/libs/hwui/SpotShadow.cpp
+++ b/libs/hwui/SpotShadow.cpp
@@ -754,9 +754,13 @@
     AlphaVertex* shadowVertices =
             shadowTriangleStrip.alloc<AlphaVertex>(SHADOW_VERTEX_COUNT);
 
+    // NOTE: Shadow alpha values are transformed when stored in alphavertices,
+    // so that they can be consumed directly by gFS_Main_ApplyVertexAlphaShadowInterp
+    float transformedMaxAlpha = M_PI;
+
     // Calculate the vertices (x, y, alpha) in the shadow area.
     AlphaVertex centroidXYA;
-    AlphaVertex::set(&centroidXYA, centroid.x, centroid.y, 1.0f);
+    AlphaVertex::set(&centroidXYA, centroid.x, centroid.y, transformedMaxAlpha);
     for (int rayIndex = 0; rayIndex < rays; rayIndex++) {
         float dx = cosf(step * rayIndex);
         float dy = sinf(step * rayIndex);
@@ -770,14 +774,16 @@
         // umbra ring
         float umbraDistance = umbraDistPerRay[rayIndex];
         AlphaVertex::set(&shadowVertices[rays + rayIndex],
-                dx * umbraDistance + centroid.x, dy * umbraDistance + centroid.y, 1.0f);
+                dx * umbraDistance + centroid.x,
+                dy * umbraDistance + centroid.y,
+                transformedMaxAlpha);
 
         // occluded umbra ring
         if (hasOccludedUmbraArea) {
             float occludedUmbraDistance = occludedUmbraDistPerRay[rayIndex];
             AlphaVertex::set(&shadowVertices[2 * rays + rayIndex],
                     dx * occludedUmbraDistance + centroid.x,
-                    dy * occludedUmbraDistance + centroid.y, 1.0f);
+                    dy * occludedUmbraDistance + centroid.y, transformedMaxAlpha);
         } else {
             // Put all vertices of the occluded umbra ring at the centroid.
             shadowVertices[2 * rays + rayIndex] = centroidXYA;
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index bd50142..6a76a71 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1672,24 +1672,6 @@
 
     /**
      * @hide
-     * Checks whether any local or remote media playback is active.
-     * Local playback refers to playback for instance on the device's speakers or wired headphones.
-     * Remote playback refers to playback for instance on a wireless display mirroring the
-     *    devices's, or on a device using a Cast-like protocol.
-     * @return true if media playback, from which the device is aware, is active.
-     */
-    public boolean isLocalOrRemoteMusicActive() {
-        IAudioService service = getService();
-        try {
-            return service.isLocalOrRemoteMusicActive();
-        } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in isLocalOrRemoteMusicActive()", e);
-            return false;
-        }
-    }
-
-    /**
-     * @hide
      * Checks whether the current audio focus is exclusive.
      * @return true if the top of the audio focus stack requested focus
      *     with {@link #AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE}
diff --git a/media/java/android/media/AudioManagerInternal.java b/media/java/android/media/AudioManagerInternal.java
new file mode 100644
index 0000000..6f1bdef
--- /dev/null
+++ b/media/java/android/media/AudioManagerInternal.java
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+import com.android.server.LocalServices;
+
+/**
+ * Class for system services to access extra AudioManager functionality. The
+ * AudioService is responsible for registering an implementation with
+ * {@link LocalServices}.
+ *
+ * @hide
+ */
+public abstract class AudioManagerInternal {
+
+    public abstract void adjustStreamVolumeForUid(int streamType, int direction, int flags,
+            String callingPackage, int uid);
+
+    public abstract void setStreamVolumeForUid(int streamType, int direction, int flags,
+            String callingPackage, int uid);
+}
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index c6489a6..0af2457 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -79,6 +79,7 @@
 
 import com.android.internal.telephony.ITelephony;
 import com.android.internal.util.XmlUtils;
+import com.android.server.LocalServices;
 
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -481,11 +482,6 @@
     final RemoteCallbackList<IAudioRoutesObserver> mRoutesObservers
             = new RemoteCallbackList<IAudioRoutesObserver>();
 
-    /**
-     * A fake stream type to match the notion of remote media playback
-     */
-    public final static int STREAM_REMOTE_MUSIC = -200;
-
     // Devices for which the volume is fixed and VolumePanel slider should be disabled
     int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_HDMI |
             AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
@@ -635,6 +631,7 @@
         mMasterVolumeRamp = context.getResources().getIntArray(
                 com.android.internal.R.array.config_masterVolumeRamp);
 
+        LocalServices.addService(AudioManagerInternal.class, new AudioServiceInternal());
     }
 
     public void systemReady() {
@@ -896,27 +893,6 @@
     ///////////////////////////////////////////////////////////////////////////
     // IPC methods
     ///////////////////////////////////////////////////////////////////////////
-    /** @see AudioManager#isLocalOrRemoteMusicActive() */
-    public boolean isLocalOrRemoteMusicActive() {
-        if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)) {
-            // local / wired / BT playback active
-            if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): local");
-            return true;
-        }
-        if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC)) {
-            // remote "cast-like" playback active
-            if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): has PLAYBACK_TYPE_REMOTE");
-            return true;
-        }
-        if (AudioSystem.isStreamActiveRemotely(AudioSystem.STREAM_MUSIC, 0)) {
-            // remote submix playback active
-            if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): remote submix");
-            return true;
-        }
-        if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): no");
-        return false;
-    }
-
     /** @see AudioManager#adjustVolume(int, int) */
     public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
             String callingPackage) {
@@ -930,9 +906,8 @@
         }
         final int resolvedStream = mStreamVolumeAlias[streamType];
 
-        // Play sounds on STREAM_RING and STREAM_REMOTE_MUSIC only.
-        if ((streamType != STREAM_REMOTE_MUSIC) &&
-                (flags & AudioManager.FLAG_PLAY_SOUND) != 0 &&
+        // Play sounds on STREAM_RING only.
+        if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 &&
                 resolvedStream != AudioSystem.STREAM_RING) {
             flags &= ~AudioManager.FLAG_PLAY_SOUND;
         }
@@ -945,17 +920,17 @@
             if (DEBUG_VOL) Log.d(TAG, "Volume controller suppressed adjustment");
         }
 
-        if (streamType == STREAM_REMOTE_MUSIC) {
-            // TODO bounce it to MediaSessionService to find an appropriate
-            // session
-        } else {
-            adjustStreamVolume(streamType, direction, flags, callingPackage);
-        }
+        adjustStreamVolume(streamType, direction, flags, callingPackage);
     }
 
     /** @see AudioManager#adjustStreamVolume(int, int, int) */
     public void adjustStreamVolume(int streamType, int direction, int flags,
             String callingPackage) {
+        adjustStreamVolume(streamType, direction, flags, callingPackage, Binder.getCallingUid());
+    }
+
+    private void adjustStreamVolume(int streamType, int direction, int flags,
+            String callingPackage, int uid) {
         if (mUseFixedVolume) {
             return;
         }
@@ -984,8 +959,8 @@
             return;
         }
 
-        if (mAppOps.noteOp(STEAM_VOLUME_OPS[streamTypeAlias], Binder.getCallingUid(),
-                callingPackage) != AppOpsManager.MODE_ALLOWED) {
+        if (mAppOps.noteOp(STEAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
+                != AppOpsManager.MODE_ALLOWED) {
             return;
         }
 
@@ -1161,6 +1136,11 @@
 
     /** @see AudioManager#setStreamVolume(int, int, int) */
     public void setStreamVolume(int streamType, int index, int flags, String callingPackage) {
+        setStreamVolume(streamType, index, flags, callingPackage, Binder.getCallingUid());
+    }
+
+    private void setStreamVolume(int streamType, int index, int flags, String callingPackage,
+            int uid) {
         if (mUseFixedVolume) {
             return;
         }
@@ -1179,8 +1159,8 @@
             return;
         }
 
-        if (mAppOps.noteOp(STEAM_VOLUME_OPS[streamTypeAlias], Binder.getCallingUid(),
-                callingPackage) != AppOpsManager.MODE_ALLOWED) {
+        if (mAppOps.noteOp(STEAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
+                != AppOpsManager.MODE_ALLOWED) {
             return;
         }
 
@@ -1885,10 +1865,6 @@
                 }
             }
             int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
-            if (streamType == STREAM_REMOTE_MUSIC) {
-                // here handle remote media playback the same way as local playback
-                streamType = AudioManager.STREAM_MUSIC;
-            }
             int device = getDeviceForStream(streamType);
             int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device);
             setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true);
@@ -2973,12 +2949,6 @@
                     if (DEBUG_VOL)
                         Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active");
                     return AudioSystem.STREAM_MUSIC;
-                } else
-                    if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC))
-                    {
-                        if (DEBUG_VOL)
-                            Log.v(TAG, "getActiveStreamType: Forcing STREAM_REMOTE_MUSIC");
-                        return STREAM_REMOTE_MUSIC;
                     } else {
                         if (DEBUG_VOL)
                             Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING b/c default");
@@ -2992,19 +2962,8 @@
             break;
         case PLATFORM_TELEVISION:
             if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
-                if (isAfMusicActiveRecently(DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS)) {
-                    if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: forcing STREAM_MUSIC");
+                    // TV always defaults to STREAM_MUSIC
                     return AudioSystem.STREAM_MUSIC;
-                } else if (mMediaFocusControl.checkUpdateRemoteStateIfActive(
-                                                                        AudioSystem.STREAM_MUSIC)) {
-                    if (DEBUG_VOL)
-                        Log.v(TAG, "getActiveStreamType: Forcing STREAM_REMOTE_MUSIC");
-                    return STREAM_REMOTE_MUSIC;
-                } else {
-                    if (DEBUG_VOL) Log.v(TAG,
-                            "getActiveStreamType: using STREAM_MUSIC as default");
-                    return AudioSystem.STREAM_MUSIC;
-                }
             }
             break;
         default:
@@ -3027,12 +2986,6 @@
                 if (isAfMusicActiveRecently(DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS)) {
                     if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: forcing STREAM_MUSIC");
                     return AudioSystem.STREAM_MUSIC;
-                } else
-                    if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC))
-                    {
-                        if (DEBUG_VOL)
-                            Log.v(TAG, "getActiveStreamType: Forcing STREAM_REMOTE_MUSIC");
-                        return STREAM_REMOTE_MUSIC;
                 } else {
                     if (DEBUG_VOL) Log.v(TAG,
                             "getActiveStreamType: using STREAM_NOTIFICATION as default");
@@ -4618,8 +4571,8 @@
                 // in SettingsObserver. Here we should log that a USB device is connected
                 // and disconnected with its address (card , device) and force the
                 // connection or disconnection when the setting changes.
-                int isDisabled = Settings.System.getInt(mContentResolver,
-                        Settings.System.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED, 0);
+                int isDisabled = Settings.Secure.getInt(mContentResolver,
+                        Settings.Secure.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED, 0);
                 if (isDisabled != 0) {
                     return;
                 }
@@ -5347,6 +5300,24 @@
         }
     }
 
+    /**
+     * Interface for system components to get some extra functionality through
+     * LocalServices.
+     */
+    final class AudioServiceInternal extends AudioManagerInternal {
+        @Override
+        public void adjustStreamVolumeForUid(int streamType, int direction, int flags,
+                String callingPackage, int uid) {
+            adjustStreamVolume(streamType, direction, flags, callingPackage, uid);
+        }
+
+        @Override
+        public void setStreamVolumeForUid(int streamType, int direction, int flags,
+                String callingPackage, int uid) {
+            setStreamVolume(streamType, direction, flags, callingPackage, uid);
+        }
+    }
+
     //==========================================================================================
     // Audio policy management
     //==========================================================================================
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 7318660..6477055 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -37,8 +37,6 @@
  */
 interface IAudioService {
 
-    boolean isLocalOrRemoteMusicActive();
-
     void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
             String callingPackage);
 
diff --git a/media/java/android/media/IRingtonePlayer.aidl b/media/java/android/media/IRingtonePlayer.aidl
index 0872f1d..7c011e6 100644
--- a/media/java/android/media/IRingtonePlayer.aidl
+++ b/media/java/android/media/IRingtonePlayer.aidl
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.media.AudioAttributes;
 import android.net.Uri;
 import android.os.UserHandle;
 
@@ -24,11 +25,11 @@
  */
 interface IRingtonePlayer {
     /** Used for Ringtone.java playback */
-    void play(IBinder token, in Uri uri, int streamType);
+    void play(IBinder token, in Uri uri, in AudioAttributes aa);
     void stop(IBinder token);
     boolean isPlaying(IBinder token);
 
     /** Used for Notification sound playback. */
-    void playAsync(in Uri uri, in UserHandle user, boolean looping, int streamType);
+    void playAsync(in Uri uri, in UserHandle user, boolean looping, in AudioAttributes aa);
     void stopAsync();
 }
diff --git a/media/java/android/media/RemoteController.java b/media/java/android/media/RemoteController.java
index 0aaaf46..adc8391 100644
--- a/media/java/android/media/RemoteController.java
+++ b/media/java/android/media/RemoteController.java
@@ -793,7 +793,7 @@
         final ComponentName listenerComponent = new ComponentName(mContext,
                 mOnClientUpdateListener.getClass());
         mSessionManager.addActiveSessionsListener(mSessionListener, listenerComponent,
-                UserHandle.myUserId());
+                UserHandle.myUserId(), null);
         mSessionListener.onActiveSessionsChanged(mSessionManager
                 .getActiveSessions(listenerComponent));
         if (DEBUG) {
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index 2616b6c..a221104 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -60,7 +60,10 @@
     private Uri mUri;
     private String mTitle;
 
-    private int mStreamType = AudioManager.STREAM_RING;
+    private AudioAttributes mAudioAttributes = new AudioAttributes.Builder()
+            .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
+            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+            .build();
 
     /** {@hide} */
     public Ringtone(Context context, boolean allowRemote) {
@@ -75,22 +78,40 @@
      * Sets the stream type where this ringtone will be played.
      * 
      * @param streamType The stream, see {@link AudioManager}.
+     * @deprecated use {@link #setAudioAttributes(AudioAttributes)}
      */
+    @Deprecated
     public void setStreamType(int streamType) {
-        mStreamType = streamType;
-
-        // The stream type has to be set before the media player is prepared.
-        // Re-initialize it.
-        setUri(mUri);
+        setAudioAttributes(new AudioAttributes.Builder()
+                .setInternalLegacyStreamType(streamType)
+                .build());
     }
 
     /**
      * Gets the stream type where this ringtone will be played.
      * 
      * @return The stream type, see {@link AudioManager}.
+     * @deprecated use of stream types is deprecated, see
+     *     {@link #setAudioAttributes(AudioAttributes)}
      */
+    @Deprecated
     public int getStreamType() {
-        return mStreamType;
+        return AudioAttributes.toLegacyStreamType(mAudioAttributes);
+    }
+
+    /**
+     * Sets the {@link AudioAttributes} for this ringtone.
+     * @param attributes the non-null attributes characterizing this ringtone.
+     */
+    public void setAudioAttributes(AudioAttributes attributes)
+            throws IllegalArgumentException {
+        if (attributes == null) {
+            throw new IllegalArgumentException("Invalid null AudioAttributes for Ringtone");
+        }
+        mAudioAttributes = attributes;
+        // The audio attributes have to be set before the media player is prepared.
+        // Re-initialize it.
+        setUri(mUri);
     }
 
     /**
@@ -178,7 +199,7 @@
         mLocalPlayer = new MediaPlayer();
         try {
             mLocalPlayer.setDataSource(mContext, mUri);
-            mLocalPlayer.setAudioStreamType(mStreamType);
+            mLocalPlayer.setAudioAttributes(mAudioAttributes);
             mLocalPlayer.prepare();
 
         } catch (SecurityException e) {
@@ -214,13 +235,14 @@
         if (mLocalPlayer != null) {
             // do not play ringtones if stream volume is 0
             // (typically because ringer mode is silent).
-            if (mAudioManager.getStreamVolume(mStreamType) != 0) {
+            if (mAudioManager.getStreamVolume(
+                    AudioAttributes.toLegacyStreamType(mAudioAttributes)) != 0) {
                 mLocalPlayer.start();
             }
         } else if (mAllowRemote && (mRemotePlayer != null)) {
             final Uri canonicalUri = mUri.getCanonicalUri();
             try {
-                mRemotePlayer.play(mRemoteToken, canonicalUri, mStreamType);
+                mRemotePlayer.play(mRemoteToken, canonicalUri, mAudioAttributes);
             } catch (RemoteException e) {
                 if (!playFallbackRingtone()) {
                     Log.w(TAG, "Problem playing ringtone: " + e);
@@ -278,7 +300,8 @@
     }
 
     private boolean playFallbackRingtone() {
-        if (mAudioManager.getStreamVolume(mStreamType) != 0) {
+        if (mAudioManager.getStreamVolume(AudioAttributes.toLegacyStreamType(mAudioAttributes))
+                != 0) {
             int ringtoneType = RingtoneManager.getDefaultType(mUri);
             if (ringtoneType == -1 ||
                     RingtoneManager.getActualDefaultRingtoneUri(mContext, ringtoneType) != null) {
@@ -295,7 +318,7 @@
                                     afd.getStartOffset(),
                                     afd.getDeclaredLength());
                         }
-                        mLocalPlayer.setAudioStreamType(mStreamType);
+                        mLocalPlayer.setAudioAttributes(mAudioAttributes);
                         mLocalPlayer.prepare();
                         mLocalPlayer.start();
                         afd.close();
diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl
index 3518458..5764bd1 100644
--- a/media/java/android/media/session/ISessionController.aidl
+++ b/media/java/android/media/session/ISessionController.aidl
@@ -48,8 +48,8 @@
     PendingIntent getLaunchPendingIntent();
     long getFlags();
     ParcelableVolumeInfo getVolumeAttributes();
-    void adjustVolume(int direction, int flags);
-    void setVolumeTo(int value, int flags);
+    void adjustVolume(int direction, int flags, String packageName);
+    void setVolumeTo(int value, int flags, String packageName);
 
     IMediaRouterDelegate createMediaRouterDelegate(IMediaRouterStateCallback callback);
 
diff --git a/media/java/android/media/session/ISessionControllerCallback.aidl b/media/java/android/media/session/ISessionControllerCallback.aidl
index 78cd699..cf31767 100644
--- a/media/java/android/media/session/ISessionControllerCallback.aidl
+++ b/media/java/android/media/session/ISessionControllerCallback.aidl
@@ -27,6 +27,7 @@
  */
 oneway interface ISessionControllerCallback {
     void onEvent(String event, in Bundle extras);
+    void onSessionDestroyed();
 
     // These callbacks are for the TransportController
     void onPlaybackStateChanged(in PlaybackState state);
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index f6e189a..63c85f8 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -63,6 +63,7 @@
     private static final int MSG_UPDATE_QUEUE = 5;
     private static final int MSG_UPDATE_QUEUE_TITLE = 6;
     private static final int MSG_UPDATE_EXTRAS = 7;
+    private static final int MSG_DESTROYED = 8;
 
     private final ISessionController mSessionBinder;
 
@@ -310,7 +311,7 @@
      */
     public void setVolumeTo(int value, int flags) {
         try {
-            mSessionBinder.setVolumeTo(value, flags);
+            mSessionBinder.setVolumeTo(value, flags, mContext.getPackageName());
         } catch (RemoteException e) {
             Log.wtf(TAG, "Error calling setVolumeTo.", e);
         }
@@ -331,7 +332,7 @@
      */
     public void adjustVolume(int direction, int flags) {
         try {
-            mSessionBinder.adjustVolume(direction, flags);
+            mSessionBinder.adjustVolume(direction, flags, mContext.getPackageName());
         } catch (RemoteException e) {
             Log.wtf(TAG, "Error calling adjustVolumeBy.", e);
         }
@@ -508,6 +509,13 @@
      */
     public static abstract class Callback {
         /**
+         * Override to handle the session being destroyed. The session is no
+         * longer valid after this call and calls to it will be ignored.
+         */
+        public void onSessionDestroyed() {
+        }
+
+        /**
          * Override to handle custom events sent by the session owner without a
          * specified interface. Controllers should only handle these for
          * sessions they own.
@@ -863,6 +871,14 @@
         }
 
         @Override
+        public void onSessionDestroyed() {
+            MediaController controller = mController.get();
+            if (controller != null) {
+                controller.postMessage(MSG_DESTROYED, null, null);
+            }
+        }
+
+        @Override
         public void onEvent(String event, Bundle extras) {
             MediaController controller = mController.get();
             if (controller != null) {
@@ -955,6 +971,9 @@
                 case MSG_UPDATE_VOLUME:
                     mCallback.onVolumeInfoChanged((VolumeInfo) msg.obj);
                     break;
+                case MSG_DESTROYED:
+                    mCallback.onSessionDestroyed();
+                    break;
             }
         }
 
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 84983b9..c2fb5a3 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -23,6 +23,7 @@
 import android.media.AudioManager;
 import android.media.IRemoteVolumeController;
 import android.media.session.ISessionManager;
+import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -37,11 +38,11 @@
 
 /**
  * Provides support for interacting with {@link MediaSession media sessions}
- * that applications have published to express their ongoing media playback state.
+ * that applications have published to express their ongoing media playback
+ * state.
  * <p>
  * Use <code>Context.getSystemService(Context.MEDIA_SESSION_SERVICE)</code> to
  * get an instance of this class.
- * <p>
  *
  * @see MediaSession
  * @see MediaController
@@ -133,15 +134,17 @@
      * the calling app. You may also retrieve this list if your app is an
      * enabled notification listener using the
      * {@link NotificationListenerService} APIs, in which case you must pass the
-     * {@link ComponentName} of your enabled listener.
+     * {@link ComponentName} of your enabled listener. Updates will be posted to
+     * the thread that registered the listener.
      *
      * @param sessionListener The listener to add.
      * @param notificationListener The enabled notification listener component.
      *            May be null.
      */
-    public void addActiveSessionsListener(SessionListener sessionListener,
-            ComponentName notificationListener) {
-        addActiveSessionsListener(sessionListener, notificationListener, UserHandle.myUserId());
+    public void addActiveSessionsListener(@NonNull SessionListener sessionListener,
+            @Nullable ComponentName notificationListener) {
+        addActiveSessionsListener(sessionListener, notificationListener, UserHandle.myUserId(),
+                null);
     }
 
     /**
@@ -157,13 +160,18 @@
      * @param notificationListener The enabled notification listener component.
      *            May be null.
      * @param userId The userId to listen for changes on.
+     * @param handler The handler to post updates on.
      * @hide
      */
     public void addActiveSessionsListener(@NonNull SessionListener sessionListener,
-            @Nullable ComponentName notificationListener, int userId) {
+            @Nullable ComponentName notificationListener, int userId, @Nullable Handler handler) {
         if (sessionListener == null) {
             throw new IllegalArgumentException("listener may not be null");
         }
+        if (handler == null) {
+            handler = new Handler();
+        }
+        sessionListener.setHandler(handler);
         try {
             mService.addSessionsListener(sessionListener.mStub, notificationListener, userId);
         } catch (RemoteException e) {
@@ -253,6 +261,7 @@
      */
     public static abstract class SessionListener {
         private final Context mContext;
+        private Handler mHandler;
 
         public SessionListener(Context context) {
             mContext = context;
@@ -269,15 +278,27 @@
         public abstract void onActiveSessionsChanged(
                 @Nullable List<MediaController> controllers);
 
+        private final void setHandler(Handler handler) {
+            mHandler = handler;
+        }
+
         private final IActiveSessionsListener.Stub mStub = new IActiveSessionsListener.Stub() {
             @Override
-            public void onActiveSessionsChanged(List<MediaSession.Token> tokens) {
-                ArrayList<MediaController> controllers = new ArrayList<MediaController>();
-                int size = tokens.size();
-                for (int i = 0; i < size; i++) {
-                    controllers.add(new MediaController(mContext, tokens.get(i)));
+            public void onActiveSessionsChanged(final List<MediaSession.Token> tokens) {
+                if (mHandler != null) {
+                    mHandler.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            ArrayList<MediaController> controllers
+                                    = new ArrayList<MediaController>();
+                            int size = tokens.size();
+                            for (int i = 0; i < size; i++) {
+                                controllers.add(new MediaController(mContext, tokens.get(i)));
+                            }
+                            SessionListener.this.onActiveSessionsChanged(controllers);
+                        }
+                    });
                 }
-                SessionListener.this.onActiveSessionsChanged(controllers);
             }
         };
     }
diff --git a/media/java/android/media/tv/TvContentRating.java b/media/java/android/media/tv/TvContentRating.java
index 25252ed..405ef22 100644
--- a/media/java/android/media/tv/TvContentRating.java
+++ b/media/java/android/media/tv/TvContentRating.java
@@ -34,42 +34,87 @@
  * strings, or a TV input service defined strings.
  * TV input service defined strings are in an xml file defined in <code>&lt;{@link
  * android.R.styleable#TvInputService tv-input}&gt;</code> with the {@link
- * android.R.attr#contentRatingSystemXml contentRatingSystemXml} attribute by the TV input service.
+ * android.R.attr#tvContentRatingDescription tvContentRatingDescription} attribute by the TV input
+ * service.
  *
- * <h3> Content Rating System XML format </h3>
- * The XML file for publishing content rating system should follow the DTD bellow:
+ * <h3> Example: Rating system definition for the TV Parental Guidelines</h3>
+ * The following XML example shows how the TV Parental Guidelines in United States can be defined:
  * <p><pre class="prettyprint">
- * &lt;?xml version="1.0" encoding="UTF-8"?&gt;
- * &lt;!DOCTYPE rating-systems [
- *     &lt;!ELEMENT rating-system-definitions (rating-system-definition+)&gt;
- *     &lt;!ATTLIST rating-system-definitions
- *         version     CDATA #REQUIRED&gt;
- *     &lt;!ELEMENT rating-system-definition (
- *         (sub-rating-definition*, rating-definition, sub-rating-definition*)+, order*)&gt;
- *     &lt;!ATTLIST rating-system-definition
- *         id          ID    #REQUIRED
- *         displayName CDATA #IMPLIED
- *         description CDATA #IMPLIED
- *         country     CDATA #IMPLIED&gt;
- *     &lt;!ELEMENT sub-rating-definition EMPTY&gt;
- *     &lt;!ATTLIST sub-rating-definition
- *         id          ID    #REQUIRED
- *         displayName CDATA #IMPLIED
- *         icon        CDATA #IMPLIED
- *         description CDATA #IMPLIED&gt;
- *     &lt;!ELEMENT rating-definition (sub-rating*))&gt;
- *     &lt;!ATTLIST rating-definition
- *         id          ID    #REQUIRED
- *         displayName CDATA #IMPLIED
- *         icon        CDATA #IMPLIED
- *         description CDATA #IMPLIED&gt;
- *     &lt;!ELEMENT sub-rating EMPTY&gt;
- *     &lt;!ATTLIST sub-rating id IDREF #REQUIRED&gt;
- *     &lt;!ELEMENT order (rating, rating+)&gt;
- *     &lt;!ELEMENT rating EMPTY&gt;
- *     &lt;!ATTLIST rating id IDREF #REQUIRED&gt;
- * ]&gt;
- * </pre></p>
+ * {@literal
+ * <?xml version="1.0" encoding="UTF-8"?>
+ * <rating-system-definitions version="1.0">
+ *     <rating-system-definition id="US_TV"
+ *         displayName="US-TV"
+ *         description="The TV Parental Guidelines"
+ *         country="US">
+ *         <sub-rating-definition id="US_TV_D"
+ *             displayName="D"
+ *             description="Suggestive dialogue (Usually means talks about sex)" />
+ *         <sub-rating-definition id="US_TV_L"
+ *             displayName="L"
+ *             description="Coarse language" />
+ *         <sub-rating-definition id="US_TV_S"
+ *             displayName="S"
+ *             description="Sexual content" />
+ *         <sub-rating-definition id="US_TV_V"
+ *             displayName="V"
+ *             description="Violence" />
+ *         <sub-rating-definition id="US_TV_FV"
+ *             displayName="FV"
+ *             description="Fantasy violence (Children\'s programming only)" />
+ *
+ *         <rating-definition id="US_TV_Y"
+ *             displayName="TV-Y"
+ *             description="This program is designed to be appropriate for all children"
+ *             ageHint="0" />
+ *         <rating-definition id="US_TV_Y7"
+ *             displayName="TV-Y7"
+ *             description="This program is designed for children age 7 and above"
+ *             ageHint="7">
+ *             <sub-rating id="US_TV_FV" />
+ *         </rating-definition>
+ *         <rating-definition id="US_TV_G"
+ *             displayName="TV-G"
+ *             description="Most parents would find this program suitable for all ages"
+ *             ageHint="0" />
+ *         <rating-definition id="US_TV_PG"
+ *             displayName="TV-PG"
+ *             description="This program contains material that parents may find unsuitable for younger children"
+ *             ageHint="14">
+ *             <sub-rating id="US_TV_D" />
+ *             <sub-rating id="US_TV_L" />
+ *             <sub-rating id="US_TV_S" />
+ *             <sub-rating id="US_TV_V" />
+ *         </rating-definition>
+ *         <rating-definition id="US_TV_14"
+ *             displayName="TV-14"
+ *             description="This program contains some material that many parents would find unsuitable for children under 14 years of age"
+ *             ageHint="14">
+ *             <sub-rating id="US_TV_D" />
+ *             <sub-rating id="US_TV_L" />
+ *             <sub-rating id="US_TV_S" />
+ *             <sub-rating id="US_TV_V" />
+ *         </rating-definition>
+ *         <rating-definition id="US_TV_MA"
+ *             displayName="TV-MA"
+ *             description="This program is specifically designed to be viewed by adults and therefore may be unsuitable for children under 17"
+ *             ageHint="17">
+ *             <sub-rating id="US_TV_L" />
+ *             <sub-rating id="US_TV_S" />
+ *             <sub-rating id="US_TV_V" />
+ *         </rating-definition>
+ *         <order>
+ *             <rating id="US_TV_Y" />
+ *             <rating id="US_TV_Y7" />
+ *         </order>
+ *         <order>
+ *             <rating id="US_TV_G" />
+ *             <rating id="US_TV_PG" />
+ *             <rating id="US_TV_14" />
+ *             <rating id="US_TV_MA" />
+ *         </order>
+ *     </rating-system-definition>
+ * </rating-system-definitions>}</pre></p>
  *
  * <h3>System defined rating strings</h3>
  *
@@ -86,9 +131,9 @@
  * </table>
  *
  * <u>System defined string for {@code ratingSystem}</u>
- * <table border="0" cellspacing="0" cellpadding="0">
+ * <table border="1" cellspacing="0" cellpadding="0">
  *     <tr>
- *         <td width=10%>String value</td>
+ *         <td width="10%">String value</td>
  *         <td>Comments</td>
  *     </tr>
  *     <tr>
@@ -101,111 +146,111 @@
  *     </tr>
  *     <tr>
  *         <td>AR_TV</td>
- *         <td>TV content rating system for Argentina TV</td>
+ *         <td>TV content rating system for Argentina</td>
  *     </tr>
  *     <tr>
  *         <td>AU_TV</td>
- *         <td>TV content rating system for Australia TV</td>
+ *         <td>TV content rating system for Australia</td>
  *     </tr>
  *     <tr>
  *         <td>BG_TV</td>
- *         <td>TV content rating system for Bulgaria TV</td>
+ *         <td>TV content rating system for Bulgaria</td>
  *     </tr>
  *     <tr>
  *         <td>BR_TV</td>
- *         <td>TV content rating system for Brazil TV</td>
+ *         <td>TV content rating system for Brazil</td>
  *     </tr>
  *     <tr>
  *         <td>CA_TV</td>
- *         <td>TV content rating system for Canada TV</td>
+ *         <td>TV content rating system for Canada</td>
  *     </tr>
  *     <tr>
  *         <td>CH_TV</td>
- *         <td>TV content rating system for Switzerland TV</td>
+ *         <td>TV content rating system for Switzerland</td>
  *     </tr>
  *     <tr>
  *         <td>CL_TV</td>
- *         <td>TV content rating system for Chile TV</td>
+ *         <td>TV content rating system for Chile</td>
  *     </tr>
  *     <tr>
  *         <td>DE_TV</td>
- *         <td>TV content rating system for Germany TV</td>
+ *         <td>TV content rating system for Germany</td>
  *     </tr>
  *     <tr>
  *         <td>DK_TV</td>
- *         <td>TV content rating system for Denmark TV</td>
+ *         <td>TV content rating system for Denmark</td>
  *     </tr>
  *     <tr>
  *         <td>ES_TV</td>
- *         <td>TV content rating system for Spain TV</td>
+ *         <td>TV content rating system for Spain</td>
  *     </tr>
  *     <tr>
  *         <td>FI_TV</td>
- *         <td>TV content rating system for Finland TV</td>
+ *         <td>TV content rating system for Finland</td>
  *     </tr>
  *     <tr>
  *         <td>FR_TV</td>
- *         <td>TV content rating system for France TV</td>
+ *         <td>TV content rating system for France</td>
  *     </tr>
  *     <tr>
  *         <td>GR_TV</td>
- *         <td>TV content rating system for Greece TV</td>
+ *         <td>TV content rating system for Greece</td>
  *     </tr>
  *     <tr>
  *         <td>HK_TV</td>
- *         <td>TV content rating system for Hong Kong TV</td>
+ *         <td>TV content rating system for Hong Kong</td>
  *     </tr>
  *     <tr>
  *         <td>HU_TV</td>
- *         <td>TV content rating system for Hungary TV</td>
+ *         <td>TV content rating system for Hungary</td>
  *     </tr>
  *     <tr>
  *         <td>ID_TV</td>
- *         <td>TV content rating system for Indonesia TV</td>
+ *         <td>TV content rating system for Indonesia</td>
  *     </tr>
  *     <tr>
  *         <td>IE_TV</td>
- *         <td>TV content rating system for Ireland TV</td>
+ *         <td>TV content rating system for Ireland</td>
  *     </tr>
  *     <tr>
  *         <td>IL_TV</td>
- *         <td>TV content rating system for Israel TV</td>
+ *         <td>TV content rating system for Israel</td>
  *     </tr>
  *     <tr>
  *         <td>IN_TV</td>
- *         <td>TV content rating system for India TV</td>
+ *         <td>TV content rating system for India</td>
  *     </tr>
  *     <tr>
  *         <td>IS_TV</td>
- *         <td>TV content rating system for Iceland TV</td>
+ *         <td>TV content rating system for Iceland</td>
  *     </tr>
  *     <tr>
  *         <td>KR_TV</td>
- *         <td>TV content rating system for South Korea TV</td>
+ *         <td>TV content rating system for South Korea</td>
  *     </tr>
  *     <tr>
  *         <td>MV_TV</td>
- *         <td>TV content rating system for Maldives TV</td>
+ *         <td>TV content rating system for Maldives</td>
  *     </tr>
  *     <tr>
  *         <td>MX_TV</td>
- *         <td>TV content rating system for Mexico TV</td>
+ *         <td>TV content rating system for Mexico</td>
  *     </tr>
  *     <tr>
  *         <td>MY_TV</td>
- *         <td>TV content rating system for Malaysia TV</td>
+ *         <td>TV content rating system for Malaysia</td>
  *     </tr>
  *     <tr>
  *         <td>NL_TV</td>
- *         <td>TV content rating system for Netherlands TV</td>
+ *         <td>TV content rating system for Netherlands</td>
  *     </tr>
  *     <tr>
  *         <td>NZ_FTV</td>
- *         <td>New Zealand\'s free-to-air TV content rating system</td>
+ *         <td>TV content rating system for free-to-air channels in New Zealand</td>
  *     </tr>
  *     <tr>
  *         <td>NZ_PTV</td>
- *         <td>New Zealand\'s pay TV content rating system</td>
+ *         <td>TV content rating system for Pay TV channels in New Zealand</td>
  *     </tr>
  *     <tr>
  *         <td>PE_TV</td>
@@ -214,87 +259,89 @@
  *     <tr>
  *         <td>PE_ATV</td>
  *         <td>TV content rating system for America Television in Peru that uses its own rating
- *         </td>
+ *         system</td>
  *     </tr>
  *     <tr>
  *         <td>PH_TV</td>
- *         <td>TV content rating system for Philippines TV</td>
+ *         <td>TV content rating system for Philippines</td>
  *     </tr>
  *     <tr>
  *         <td>PL_TV</td>
- *         <td>TV content rating system for Poland TV</td>
+ *         <td>TV content rating system for Poland</td>
  *     </tr>
  *     <tr>
  *         <td>PT_TV</td>
- *         <td>TV content rating system for Portugal TV</td>
+ *         <td>TV content rating system for Portugal</td>
  *     </tr>
  *     <tr>
  *         <td>RO_TV</td>
- *         <td>TV content rating system for Romania TV</td>
+ *         <td>TV content rating system for Romania</td>
  *     </tr>
  *     <tr>
  *         <td>RU_TV</td>
- *         <td>TV content rating system for Russia TV</td>
+ *         <td>TV content rating system for Russia</td>
  *     </tr>
  *     <tr>
  *         <td>RS_TV</td>
- *         <td>TV content rating system for Serbia TV</td>
+ *         <td>TV content rating system for Serbia</td>
  *     </tr>
  *     <tr>
  *         <td>SG_FTV</td>
- *         <td>TV content rating system for Singapore TV</td>
+ *         <td>TV content rating system for Singapore</td>
  *     </tr>
  *     <tr>
  *         <td>SG_PTV</td>
- *         <td>TV content rating system for Singapore TV</td>
+ *         <td>TV content rating system for Singapore</td>
  *     </tr>
  *     <tr>
  *         <td>SI_TV</td>
- *         <td>TV content rating system for Slovenia TV</td>
+ *         <td>TV content rating system for Slovenia</td>
  *     </tr>
  *     <tr>
  *         <td>TH_TV</td>
- *         <td>TV content rating system for Thailand TV</td>
+ *         <td>TV content rating system for Thailand</td>
  *     </tr>
  *     <tr>
  *         <td>TR_TV</td>
- *         <td>TV content rating system for Turkey TV</td>
+ *         <td>TV content rating system for Turkey</td>
  *     </tr>
  *     <tr>
  *         <td>TW_TV</td>
- *         <td>TV content rating system for Taiwan TV</td>
+ *         <td>TV content rating system for Taiwan</td>
  *     </tr>
  *     <tr>
  *         <td>UA_TV</td>
- *         <td>TV content rating system for Ukraine TV</td>
+ *         <td>TV content rating system for Ukraine</td>
  *     </tr>
  *     <tr>
- *         <td>US_TVPG</td>
- *         <td>The TV Parental Guidelines</td>
+ *         <td>US_TV</td>
+ *         <td>TV content rating system for United States</td>
  *     </tr>
  *     <tr>
  *         <td>VE_TV</td>
- *         <td>TV content rating system for Venezuela TV</td>
+ *         <td>TV content rating system for Venezuela</td>
  *     </tr>
  *     <tr>
  *         <td>ZA_TV</td>
- *         <td>TV content rating system for South Africa TV</td>
+ *         <td>TV content rating system for South Africa</td>
  *     </tr>
  * </table>
  *
  * <u>System defined string for {@code rating}</u>
- * <table border="0" cellspacing="0" cellpadding="0">
+ * <table border="1" cellspacing="0" cellpadding="0">
  *     <tr>
- *         <td width=10%>String value</td>
+ *         <td width="10%">RatingSystem code</td>
+ *         <td width="10%">Rating string value</td>
  *         <td>Comments</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="6">AM_TV_RS</td>
  *         <td>AM_TV_RS_Y</td>
- *         <td>Suitable for ages 2–11</td>
+ *         <td>Suitable for ages 2-11</td>
  *     </tr>
  *     <tr>
  *         <td>AM_TV_RS_Y7</td>
- *         <td>Suitable for ages 7–16</td>
+ *         <td>Suitable for ages 7-16</td>
  *     </tr>
  *     <tr>
  *         <td>AM_TV_RS_GA</td>
@@ -313,6 +360,7 @@
  *         <td>Suitable only for adults ages 18 and up</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="6">AM_TV_AS</td>
  *         <td>AM_TV_AS_EC</td>
  *         <td>Suitable for ages 2 and up</td>
  *     </tr>
@@ -337,26 +385,28 @@
  *         <td>Suitable for ages 17 and up</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="4">AR_TV</td>
  *         <td>AR_TV_ALL</td>
  *         <td>Suitable for all audiences. Programs may contain mild violence, language and mature
- *         </td>
+ *         situations</td>
  *     </tr>
  *     <tr>
  *         <td>AR_TV_13</td>
  *         <td>Suitable for ages 13 and up. Programs may contain mild to moderate language and mild
- *         and sexual references</td>
+ *         violence and sexual references</td>
  *     </tr>
  *     <tr>
  *         <td>AR_TV_16</td>
  *         <td>Suitable for ages 16 and up. Programs may contain more intensive violence and coarse
- *         partial nudity and moderate sexual references</td>
+ *         language, partial nudity and moderate sexual references</td>
  *     </tr>
  *     <tr>
  *         <td>AR_TV_18</td>
  *         <td>Suitable for mature audiences only. Programs contain strong violence, coarse language
- *         explicit sexual references</td>
+ *         and explicit sexual references</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="7">AU_TV</td>
  *         <td>AU_TV_CTC</td>
  *         <td>This has advertising approval, but is not yet classified</td>
  *     </tr>
@@ -367,17 +417,17 @@
  *     <tr>
  *         <td>AU_TV_PG</td>
  *         <td>The content is mild in impact, but it may contain content that children find
- *         or upsetting and may require the guidance or parents and guardians</td>
+ *         confusing or upsetting and may require the guidance or parents and guardians</td>
  *     </tr>
  *     <tr>
  *         <td>AU_TV_M</td>
  *         <td>The content is moderate in impact, and it is recommended for teenagers aged 15 years
- *         over</td>
+ *         and over</td>
  *     </tr>
  *     <tr>
  *         <td>AU_TV_MA15</td>
  *         <td>The content is strong in impact, and it is legally restricted to persons 15 years and
- *         </td>
+ *         over</td>
  *     </tr>
  *     <tr>
  *         <td>AU_TV_R18</td>
@@ -386,37 +436,39 @@
  *     <tr>
  *         <td>AU_TV_X18</td>
  *         <td>The content is restricted to adults. This classification is a special and legally
- *         category which contains only sexually explicit content</td>
+ *         restricted category which contains only sexually explicit content</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="5">BG_TV</td>
  *         <td>BG_TV_A</td>
  *         <td>Recommended to children. When the film confirms the ideals of humanism or popularizes
- *         national and world cultures or contributes to upbringing children</td>
+ *         the national and world cultures or contributes to upbringing children</td>
  *     </tr>
  *     <tr>
  *         <td>BG_TV_B</td>
  *         <td>No restrictive recommendations from the Committee. When the film is in no way
- *         to the universal rules of morality in this country, has no restrictive recommendations
- *         the Committee and does not fall in rating A</td>
+ *         contrary to the universal rules of morality in this country, has no restrictive
+ *         recommendations from the Committee and does not fall in rating A</td>
  *     </tr>
  *     <tr>
  *         <td>BG_TV_C</td>
  *         <td>No persons under the age of 12 are admitted unless accompanied by an adult. When the
- *         contains certain erotic scenes or scenes with drinking, taking drugs or stimulants or a
- *         scenes of violence</td>
+ *         film contains certain erotic scenes or scenes with drinking, taking drugs or stimulants
+ *         or a few scenes of violence</td>
  *     </tr>
  *     <tr>
  *         <td>BG_TV_D</td>
  *         <td>No persons under the age of 16 are admitted. When the film contains quite a number of
- *         scenes or scenes with drinking, taking drugs or stimulants or a considerable number of
- *         showing violence</td>
+ *         erotic scenes or scenes with drinking, taking drugs or stimulants or a considerable
+ *         number of scenes showing violence</td>
  *     </tr>
  *     <tr>
  *         <td>BG_TV_X</td>
  *         <td>No persons under the age of 18 are admitted. When the film is naturalistically erotic
- *         shows violence in an ostentatious manner</td>
+ *         or shows violence in an ostentatious manner</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="6">BR_TV</td>
  *         <td>BR_TV_L</td>
  *         <td>Content is suitable for all audiences</td>
  *     </tr>
@@ -441,52 +493,55 @@
  *         <td>Content suitable for viewers over the age of 18</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="7">CA_TV</td>
  *         <td>CA_TV_EXEMPT</td>
  *         <td>Shows which are exempt from ratings (such as news and sports programming) will not
- *         an on-screen rating at all</td>
+ *         display an on-screen rating at all</td>
  *     </tr>
  *     <tr>
  *         <td>CA_TV_C</td>
- *         <td>Programming suitable for children ages of 2–7 years. No profanity or sexual content
- *         any level allowed. Contains little violence</td>
+ *         <td>Programming suitable for children ages of 2-7 years. No profanity or sexual content
+ *         of any level allowed. Contains little violence</td>
  *     </tr>
  *     <tr>
  *         <td>CA_TV_C8</td>
  *         <td>Suitable for children ages 8+. Low level violence and fantasy horror is allowed. No
- *         language is allowed, but occasional "socially offensive and discriminatory" language is
- *         if in the context of the story. No sexual content of any level allowed</td>
+ *         foul language is allowed, but occasional "socially offensive and discriminatory" language
+ *         is allowed if in the context of the story. No sexual content of any level allowed</td>
  *     </tr>
  *     <tr>
  *         <td>CA_TV_G</td>
  *         <td>Suitable for general audiences. Programming suitable for the entire family with mild
- *         and mild profanity and/or censored language</td>
+ *         violence, and mild profanity and/or censored language</td>
  *     </tr>
  *     <tr>
  *         <td>CA_TV_PG</td>
  *         <td>Parental guidance. Moderate violence and moderate profanity is allowed, as is brief
- *         and sexual references if important to the context of the story</td>
+ *         nudity and sexual references if important to the context of the story</td>
  *     </tr>
  *     <tr>
  *         <td>CA_TV_14</td>
  *         <td>Programming intended for viewers ages 14 and older. May contain strong violence and
- *         profanity, and depictions of sexual activity as long as they are within the context of a
- *         </td>
+ *         strong profanity, and depictions of sexual activity as long as they are within the
+ *         context of a story</td>
  *     </tr>
  *     <tr>
  *         <td>CA_TV_18</td>
  *         <td>Programming intended for viewers ages 18 and older. May contain explicit violence and
- *         activity</td>
+ *         sexual activity</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="2">CH_TV</td>
  *         <td>CH_TV_ALL</td>
  *         <td>This program is suitable for all ages</td>
  *     </tr>
  *     <tr>
  *         <td>CH_TV_RED</td>
  *         <td>This program contains scenes that may hurt sensitive people, therefore the red symbol
- *         be displayed</td>
+ *         will be displayed</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="7">CL_TV</td>
  *         <td>CL_TV_I</td>
  *         <td>Programs suitable for all children</td>
  *     </tr>
@@ -513,9 +568,10 @@
  *     <tr>
  *         <td>CL_TV_A</td>
  *         <td>Programs suitable for adult audiences only (ages 18 or older), may contain coarse
- *         and sexual or explicit situations</td>
+ *         language, and sexual or explicit situations</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="4">DE_TV</td>
  *         <td>DE_TV_ALL</td>
  *         <td>The program is suitable for all ages</td>
  *     </tr>
@@ -532,6 +588,7 @@
  *         <td>The program is not suitable for viewers under the age of 18</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="4">DK_TV</td>
  *         <td>DK_TV_G</td>
  *         <td>programs suitable for all ages</td>
  *     </tr>
@@ -548,6 +605,7 @@
  *         <td>programs containing explicit content and strictly for adults only</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="7">ES_TV</td>
  *         <td>ES_TV_TP</td>
  *         <td>Recommended for all ages</td>
  *     </tr>
@@ -576,6 +634,7 @@
  *         <td>Recommended for people older than 18 years old</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="5">FI_TV</td>
  *         <td>FI_TV_S</td>
  *         <td>Allowed at all times</td>
  *     </tr>
@@ -596,6 +655,7 @@
  *         <td>Not recommended for children under 18</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="5">FR_TV</td>
  *         <td>FR_TV_ALL</td>
  *         <td>Appropriate for all ages</td>
  *     </tr>
@@ -616,6 +676,7 @@
  *         <td>Not recommended for persons under 18</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="5">GR_TV</td>
  *         <td>GR_TV_all</td>
  *         <td>Suitable for all ages</td>
  *     </tr>
@@ -634,9 +695,10 @@
  *     <tr>
  *         <td>GR_TV_18</td>
  *         <td>Suitable only for adults profanity before midnight is punishable by fine, except when
- *         in the context of the program</td>
+ *         used in the context of the program</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="3">HK_TV</td>
  *         <td>HK_TV_G</td>
  *         <td>For general audiences</td>
  *     </tr>
@@ -649,35 +711,37 @@
  *         <td>Programs are recommended only for adult viewers above the age of 18</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="6">HU_TV</td>
  *         <td>HU_TV_U</td>
  *         <td>Programs can be viewed by any age</td>
  *     </tr>
  *     <tr>
  *         <td>HU_TV_CF</td>
  *         <td>Programs recommended for children. It is an optional rating, there is no obligation
- *         broadcasters to indicate it</td>
+ *         for broadcasters to indicate it</td>
  *     </tr>
  *     <tr>
  *         <td>HU_TV_6</td>
  *         <td>Programs not recommended for children below the age of 6, may not contain any
- *         or sexual content</td>
+ *         violence or sexual content</td>
  *     </tr>
  *     <tr>
  *         <td>HU_TV_12</td>
  *         <td>Programs not recommended for children below the age of 12, may contain light sexual
- *         or explicit language</td>
+ *         content or explicit language</td>
  *     </tr>
  *     <tr>
  *         <td>HU_TV_16</td>
  *         <td>Programs not recommended for teens and children below the age of 16, may contain more
- *         violence and sexual content</td>
+ *         intensive violence and sexual content</td>
  *     </tr>
  *     <tr>
  *         <td>HU_TV_18</td>
  *         <td>The program is recommended only for adult viewers (for ages 18 and up), may contain
- *         violence and explicit sexual content</td>
+ *         explicit violence and explicit sexual content</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="8">ID_TV</td>
  *         <td>ID_TV_P</td>
  *         <td>Suitable for children from ages 2 through 11</td>
  *     </tr>
@@ -710,18 +774,19 @@
  *         <td>Suitable for viewers over 18 and older only</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="5">IE_TV</td>
  *         <td>IE_TV_GA</td>
  *         <td>Suitable for all ages</td>
  *     </tr>
  *     <tr>
  *         <td>IE_TV_Ch</td>
  *         <td>Suitable for children ages 5 to 10, may contain comedic violence or action fantasy
- *         </td>
+ *         violence</td>
  *     </tr>
  *     <tr>
  *         <td>IE_TV_YA</td>
  *         <td>Suitable for adolescent audiences, may contain thematic elements that would appeal to
- *         </td>
+ *         teenagers</td>
  *     </tr>
  *     <tr>
  *         <td>IE_TV_PS</td>
@@ -730,17 +795,18 @@
  *     <tr>
  *         <td>IE_TV_MA</td>
  *         <td>Most restrictive classification, allowing for heavy subject matter and coarse
- *         </td>
+ *         language</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="5">IL_TV</td>
  *         <td>IL_TV_G</td>
  *         <td>General audience; anyone, regardless of age, can view the program, usually news and
- *         programming</td>
+ *         children's programming</td>
  *     </tr>
  *     <tr>
  *         <td>IL_TV_12</td>
  *         <td>Suitable for teens and children ages 12 and over, no child under 12 are permitted to
- *         the program</td>
+ *         view the program</td>
  *     </tr>
  *     <tr>
  *         <td>IL_TV_15</td>
@@ -755,13 +821,14 @@
  *         <td>Exempt from classification</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="4">IN_TV</td>
  *         <td>IN_TV_U</td>
  *         <td>Unrestricted public exhibition</td>
  *     </tr>
  *     <tr>
  *         <td>IN_TV_U/A</td>
  *         <td>Unrestricted public exhibition, but with a caution regarding parental guidance to
- *         under 12 years of age</td>
+ *         those under 12 years of age</td>
  *     </tr>
  *     <tr>
  *         <td>IN_TV_A</td>
@@ -773,6 +840,7 @@
  *         </td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="7">IS_TV</td>
  *         <td>IS_TV_L</td>
  *         <td>Programs suitable for all ages</td>
  *     </tr>
@@ -801,29 +869,31 @@
  *         <td>Programs suitable for ages 18 and older</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="5">KR_TV</td>
  *         <td>KR_TV_All</td>
  *         <td>Appropriate for all ages</td>
  *     </tr>
  *     <tr>
  *         <td>KR_TV_7</td>
  *         <td>May contain material inappropriate for children younger than 7, and parental
- *         should be used</td>
+ *         discretion should be used</td>
  *     </tr>
  *     <tr>
  *         <td>KR_TV_12</td>
  *         <td>May deemed inappropriate for those younger than 12, and parental discretion should be
- *         </td>
+ *         used</td>
  *     </tr>
  *     <tr>
  *         <td>KR_TV_15</td>
  *         <td>May be inappropriate for children under 15, and that parental discretion should be
- *         </td>
+ *         used</td>
  *     </tr>
  *     <tr>
  *         <td>KR_TV_19</td>
  *         <td>For adults only</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="9">MV_TV</td>
  *         <td>MV_TV_Y</td>
  *         <td>Young children</td>
  *     </tr>
@@ -860,6 +930,7 @@
  *         <td>Most restrictive classification, only adults ages 25 and above may view</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="6">MX_TV</td>
  *         <td>MX_TV_A</td>
  *         <td>Appropriate for all ages, parental guidance is recommended for children under 7 years
  *         </td>
@@ -867,41 +938,43 @@
  *     <tr>
  *         <td>MX_TV_B</td>
  *         <td>Designed for ages 12 and older, may contain some sexual situations, mild violence,
- *         mild language</td>
+ *         and mild language</td>
  *     </tr>
  *     <tr>
  *         <td>MX_TV_B-15</td>
- *         <td>Designed for ages 15 and up, slightly more intensive than the \'A\' and \'B\' ratings
+ *         <td>Designed for ages 15 and up, slightly more intensive than the 'A' and 'B' ratings
  *         </td>
  *     </tr>
  *     <tr>
  *         <td>MX_TV_C</td>
  *         <td>Designed to be viewed by adults aged 18 or older only, generally more intensive
- *         </td>
+ *         content</td>
  *     </tr>
  *     <tr>
  *         <td>MX_TV_D</td>
  *         <td>Designed to be viewed only by mature adults (at least 21 years of age and over),
- *         extreme content matter</td>
+ *         contains extreme content matter</td>
  *     </tr>
  *     <tr>
  *         <td>MX_TV_RC</td>
  *         <td>Banned from public television in Mexico</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="3">MY_TV</td>
  *         <td>MY_TV_U</td>
  *         <td>General viewing for all ages, can be broadcast anytime</td>
  *     </tr>
  *     <tr>
  *         <td>MY_TV_P13</td>
  *         <td>For viewers ages 13 and above, children under 13 needs parental guidance, can be
- *         anytime, but some elements may only be broadcast at night</td>
+ *         broadcast anytime, but some elements may only be broadcast at night</td>
  *     </tr>
  *     <tr>
  *         <td>MY_TV_18</td>
  *         <td>For viewers ages 18 and above only</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="5">NL_TV</td>
  *         <td>NL_TV_AL</td>
  *         <td>All Ages</td>
  *     </tr>
@@ -922,23 +995,25 @@
  *         <td>Parental advisory for children under 16</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="3">NZ_FTV</td>
  *         <td>NZ_FTV_G</td>
  *         <td>These exclude material likely to harm children under 14 and can screen at any time.
- *         may not necessarily be designed for younger viewers, but must not contain material likely
- *         cause them undue distress or discomfort</td>
+ *         Programmes may not necessarily be designed for younger viewers, but must not contain
+ *         material likely to cause them undue distress or discomfort</td>
  *     </tr>
  *     <tr>
  *         <td>NZ_FTV_PGR</td>
  *         <td>Programmes more suited to more mature viewers. These are not necessarily unsuitable
- *         children, but viewer discretion is advised, and parents and guardians are encouraged to
- *         younger viewers</td>
+ *         for children, but viewer discretion is advised, and parents and guardians are encouraged
+ *         to supervise younger viewers</td>
  *     </tr>
  *     <tr>
  *         <td>NZ_FTV_AO</td>
  *         <td>Contain material of an adult nature handled in such a way that it is unsuitable for
- *         </td>
+ *         children</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="5">NZ_PTV</td>
  *         <td>NZ_PTV_G</td>
  *         <td>suitable for general audiences</td>
  *     </tr>
@@ -959,6 +1034,7 @@
  *         <td>Suitable for viewers 18 and up</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="3">PE_TV</td>
  *         <td>PE_TV_A</td>
  *         <td>Suitable for all audiences</td>
  *     </tr>
@@ -971,6 +1047,7 @@
  *         <td>Suitable for people aged 18 and above only</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="4">PE_ATV</td>
  *         <td>PE_ATV_GP</td>
  *         <td>General audience</td>
  *     </tr>
@@ -987,48 +1064,52 @@
  *         <td>Suitable for people aged 18 and above only</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="3">PH_TV</td>
  *         <td>PH_TV_G</td>
  *         <td>Suitable for all public viewers</td>
  *     </tr>
  *     <tr>
  *         <td>PH_TV_PG</td>
  *         <td>Programmes rated PG may contain scenes or other content that are unsuitable for
- *         without the guidance of a parent</td>
+ *         children without the guidance of a parent</td>
  *     </tr>
  *     <tr>
  *         <td>PH_TV_SPG</td>
  *         <td>Contains mature themes or moderate to intense violence, which may be deemed unfit for
- *         to watch without strict parental supervision</td>
+ *         children to watch without strict parental supervision</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="5">PL_TV</td>
  *         <td>PL_TV_G</td>
  *         <td>Positive or neutral view of the world, little to no violence, non-sexual love, and no
- *         content</td>
+ *         sexual content</td>
  *     </tr>
  *     <tr>
  *         <td>PL_TV_7</td>
  *         <td>Age 7 and above. May additionally contain some mild language, bloodless violence, and
- *         more negative view of the world</td>
+ *         a more negative view of the world</td>
  *     </tr>
  *     <tr>
  *         <td>PL_TV_12</td>
  *         <td>Age 12 and above. May contain some foul language, some violence, and some sexual
- *         </td>
+ *         content</td>
  *     </tr>
  *     <tr>
  *         <td>PL_TV_16</td>
  *         <td>Age 16 and above. Deviant social behaviour, world filled with violence and sexuality,
- *         picture of adulthood, display of physical force, especially in controversial social
- *         immoral behaviour without ethic dilemma, putting the blame on the victim, excessive
- *         on material possessions</td>
+ *         simplified picture of adulthood, display of physical force, especially in controversial
+ *         social context, immoral behaviour without ethic dilemma, putting the blame on the victim,
+ *         excessive concentration on material possessions</td>
  *     </tr>
  *     <tr>
  *         <td>PL_TV_18</td>
  *         <td>Age 18 and above. One-sided display of the joys of adult life without showing
- *         social justification of violent behaviour, excessive vulgarity, use of racial slurs and
- *         stereotypes, explicit sexual content, praise of aggression or vulgarity</td>
+ *         responsibilities, social justification of violent behaviour, excessive vulgarity, use of
+ *         racial slurs and social stereotypes, explicit sexual content, praise of aggression or
+ *         vulgarity</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="4">PT_TV</td>
  *         <td>PT_TV_T</td>
  *         <td>Suitable for all</td>
  *     </tr>
@@ -1045,6 +1126,7 @@
  *         <td>Not suitable for children under 16</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="6">RO_TV</td>
  *         <td>RO_TV_Y</td>
  *         <td>Young Ages</td>
  *     </tr>
@@ -1069,6 +1151,7 @@
  *         <td>Forbidden for children under 18 years of age</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="5">RU_TV</td>
  *         <td>RU_TV_0</td>
  *         <td>Can be watched by Any Age</td>
  *     </tr>
@@ -1089,6 +1172,7 @@
  *         <td>Restricted to children ONLY people 18 or older</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="7">RS_TV</td>
  *         <td>RS_TV_G</td>
  *         <td>Program suitable for all ages</td>
  *     </tr>
@@ -1117,14 +1201,16 @@
  *         <td>Program not suitable for minors under the age of 18</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="2">SG_FTV</td>
  *         <td>SG_FTV_PG</td>
  *         <td>Suitable for most but parents should guide their young</td>
  *     </tr>
  *     <tr>
  *         <td>SG_FTV_PG13</td>
- *         <td>Parental Guidance Strongly Cautioned – Suitable for 13 And Above</td>
+ *         <td>Parental Guidance Strongly Cautioned - Suitable for 13 And Above</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="2">SG_PTV</td>
  *         <td>SG_PTV_NC16</td>
  *         <td>No Children Under 16</td>
  *     </tr>
@@ -1133,6 +1219,7 @@
  *         <td>Nobody under age 18 is admitted</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="4">SI_TV</td>
  *         <td>SI_TV_VS</td>
  *         <td>Parental guidance suggested (for children under 6)</td>
  *     </tr>
@@ -1149,12 +1236,13 @@
  *         <td>Content exclusively for adults</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="6">TH_TV</td>
  *         <td>TH_TV_P</td>
  *         <td>Content suitable for primary school aged children</td>
  *     </tr>
  *     <tr>
  *         <td>TH_TV_C</td>
- *         <td>Content suitable for children between 6–12 years old</td>
+ *         <td>Content suitable for children between 6-12 years old</td>
  *     </tr>
  *     <tr>
  *         <td>TH_TV_G</td>
@@ -1163,18 +1251,19 @@
  *     <tr>
  *         <td>TH_TV_PG13</td>
  *         <td>Content suitable for people aged 13 and above, but can be watched by those who are
- *         the recommended age if parental guidance is provided</td>
+ *         under the recommended age if parental guidance is provided</td>
  *     </tr>
  *     <tr>
  *         <td>TH_TV_PG18</td>
  *         <td>Content suitable for people aged above 18 years old; those who are younger that 18
- *         be provided with parental guidance</td>
+ *         must be provided with parental guidance</td>
  *     </tr>
  *     <tr>
  *         <td>TH_TV_A</td>
  *         <td>Content unsuitable for children and youngsters</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="4">TR_TV</td>
  *         <td>TR_TV_G</td>
  *         <td>General audience. Suitable for all ages</td>
  *     </tr>
@@ -1191,65 +1280,69 @@
  *         <td>Suitable for ages 13 and over</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="4">TW_TV</td>
  *         <td>TW_TV_G</td>
  *         <td>For all ages</td>
  *     </tr>
  *     <tr>
  *         <td>TW_TV_P</td>
  *         <td>Not suitable for children under 6 years old. People aged 6 but under 12 require
- *         from accompanying adults to watch</td>
+ *         guidance from accompanying adults to watch</td>
  *     </tr>
  *     <tr>
  *         <td>TW_TV_PG</td>
  *         <td>Not suitable for people under 12 years of age. Parental guidance is required for
- *         aged 12 but under 18</td>
+ *         people aged 12 but under 18</td>
  *     </tr>
  *     <tr>
  *         <td>TW_TV_R</td>
  *         <td>For adults only and people under 18 years of age must not watch</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="3">UA_TV</td>
  *         <td>UA_TV_G</td>
  *         <td>This program does not have age restrictions</td>
  *     </tr>
  *     <tr>
  *         <td>UA_TV_Y</td>
  *         <td>Children must view this program with parents. In it program there are fragments,
- *         unsuitable for children</td>
+ *         which unsuitable for children</td>
  *     </tr>
  *     <tr>
  *         <td>UA_TV_R</td>
  *         <td>This program is only for adult viewers. In it there are scenes with nudity, drug use,
- *         violence</td>
+ *         or violence</td>
  *     </tr>
  *     <tr>
- *         <td>US_TVPG_TV_Y</td>
+ *         <td valign="top" rowspan="6">US_TV</td>
+ *         <td>US_TV_Y</td>
  *         <td>This program is designed to be appropriate for all children</td>
  *     </tr>
  *     <tr>
- *         <td>US_TVPG_TV_Y7</td>
+ *         <td>US_TV_Y7</td>
  *         <td>This program is designed for children age 7 and above</td>
  *     </tr>
  *     <tr>
- *         <td>US_TVPG_TV_G</td>
+ *         <td>US_TV_G</td>
  *         <td>Most parents would find this program suitable for all ages</td>
  *     </tr>
  *     <tr>
- *         <td>US_TVPG_TV_PG</td>
+ *         <td>US_TV_PG</td>
  *         <td>This program contains material that parents may find unsuitable for younger children
  *         </td>
  *     </tr>
  *     <tr>
- *         <td>US_TVPG_TV_14</td>
+ *         <td>US_TV_14</td>
  *         <td>This program contains some material that many parents would find unsuitable for
- *         under 14 years of age</td>
+ *         children under 14 years of age</td>
  *     </tr>
  *     <tr>
- *         <td>US_TVPG_TV_MA</td>
+ *         <td>US_TV_MA</td>
  *         <td>This program is specifically designed to be viewed by adults and therefore may be
- *         for children under 17</td>
+ *         unsuitable for children under 17</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="3">VE_TV</td>
  *         <td>VE_TV_TU</td>
  *         <td>For all ages</td>
  *     </tr>
@@ -1262,139 +1355,153 @@
  *         <td>Mature viewers</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="6">ZA_TV</td>
  *         <td>ZA_TV_F</td>
  *         <td>This is a program/film that does not contain any obscenity, and is suitable for
- *         viewing. A logo must be displayed in the corner of the screen for 30 seconds after each
- *         break</td>
+ *         family viewing. A logo must be displayed in the corner of the screen for 30 seconds after
+ *         each commercial break</td>
  *     </tr>
  *     <tr>
  *         <td>ZA_TV_PG</td>
  *         <td>Children under 6 may watch this program/film, but must be accompanied by an adult.
- *         program contains an adult related theme, which might include very mild language, violence
- *         sexual innuendo. A logo must be displayed in the corner of the screen for one minute
- *         each commercial break</td>
+ *         This program contains an adult related theme, which might include very mild language,
+ *         violence and sexual innuendo. A logo must be displayed in the corner of the screen for
+ *         one minute after each commercial break</td>
  *     </tr>
  *     <tr>
  *         <td>ZA_TV_13</td>
  *         <td>Children under 13 are prohibited from watching this program/film. This program
- *         mild language, violence and sexual innuendo. A logo must be displayed in the corner of
- *         screen for two minutes after each commercial break</td>
+ *         contains mild language, violence and sexual innuendo. A logo must be displayed in the
+ *         corner of the screen for two minutes after each commercial break</td>
  *     </tr>
  *     <tr>
  *         <td>ZA_TV_16</td>
  *         <td>Children under 16 are prohibited from watching this program/film. It contains
- *         violence, language, and some sexual situations. In the case of television, this program
- *         only be broadcast after 9pm–4:30am. A logo must be displayed in the corner of the screen
- *         five minutes after each commercial break. A full-screen warning must be issued before the
- *         of the program. If the program is longer than an hour, a warning must be displayed every
- *         an hour</td>
+ *         moderate violence, language, and some sexual situations. In the case of television, this
+ *         program may only be broadcast after 9pm-4:30am. A logo must be displayed in the corner of
+ *         the screen for five minutes after each commercial break. A full-screen warning must be
+ *         issued before the start of the program. If the program is longer than an hour, a warning
+ *         must be displayed every half an hour</td>
  *     </tr>
  *     <tr>
  *         <td>ZA_TV_18</td>
  *         <td>Children under 18 are prohibited from watching this program/film. It contains extreme
- *         language and/or graphic sexual content. In the case of television, this program may only
- *         broadcast from 10pm–4:30am. A logo must be displayed in the corner of the screen for the
- *         of the program. A full-screen warning must be issued before the start of the program and
- *         each commercial break</td>
+ *         violence, language and/or graphic sexual content. In the case of television, this program
+ *         may only be broadcast from 10pm-4:30am. A logo must be displayed in the corner of the
+ *         screen for the duration of the program. A full-screen warning must be issued before the
+ *         start of the program and after each commercial break</td>
  *     </tr>
  *     <tr>
  *         <td>ZA_TV_R18</td>
  *         <td>This is reserved for films of an extreme sexual nature (pornography). R18 films may
- *         be distributed in the form of video and DVD in a controlled environment (e.g. Adult
- *         No public viewing of this film may take place. R18 films may not be broadcast on
- *         and in cinemas</td>
+ *         only be distributed in the form of video and DVD in a controlled environment (e.g. Adult
+ *         Shops). No public viewing of this film may take place. R18 films may not be broadcast on
+ *         television and in cinemas</td>
  *     </tr>
  * </table>
  *
  * <u>System defined string for {@code subRating}</u>
- * <table border="0" cellspacing="0" cellpadding="0">
+ * <table border="1" cellspacing="0" cellpadding="0">
  *     <tr>
- *         <td width=10%>String value</td>
+ *         <td width="10%">RatingSystem code</td>
+ *         <td width="10%">Rating string value</td>
  *         <td>Comments</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="6">NL_TV</td>
  *         <td>NL_TV_V</td>
- *         <td>Violence</td>
+ *         <td>Violence<br/>Applicable to NL_TV_AL, NL_TV_6, NL_TV_9, NL_TV_12, NL_TV_16</td>
  *     </tr>
  *     <tr>
  *         <td>NL_TV_F</td>
- *         <td>Scary or Disturbing Content</td>
+ *         <td>Scary or Disturbing ContentViolence<br/>Applicable to NL_TV_AL, NL_TV_6, NL_TV_9,
+ *         NL_TV_12, NL_TV_16</td>
  *     </tr>
  *     <tr>
  *         <td>NL_TV_S</td>
- *         <td>Sexual Content</td>
+ *         <td>Sexual Content<br/>Applicable to NL_TV_AL, NL_TV_6, NL_TV_9, NL_TV_12, NL_TV_16</td>
  *     </tr>
  *     <tr>
  *         <td>NL_TV_D</td>
- *         <td>Discrimination</td>
+ *         <td>Discrimination<br/>Applicable to NL_TV_AL, NL_TV_6, NL_TV_9, NL_TV_12, NL_TV_16</td>
  *     </tr>
  *     <tr>
  *         <td>NL_TV_DA</td>
- *         <td>Drug and/or Alcohol abuse</td>
+ *         <td>Drug and/or Alcohol abuse<br/>Applicable to NL_TV_AL, NL_TV_6, NL_TV_9, NL_TV_12,
+ *         NL_TV_16</td>
  *     </tr>
  *     <tr>
  *         <td>NL_TV_L</td>
- *         <td>Bad Language</td>
+ *         <td>Bad Language<br/>Applicable to NL_TV_AL, NL_TV_6, NL_TV_9, NL_TV_12, NL_TV_16</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="4">NZ_PTV</td>
  *         <td>NZ_PTV_C</td>
- *         <td>Content may offend</td>
+ *         <td>Content may offend<br/>Applicable to NZ_PTV_PG, NZ_PTV_M, NZ_PTV_16, NZ_PTV_18</td>
  *     </tr>
  *     <tr>
  *         <td>NZ_PTV_V</td>
- *         <td>Violence</td>
+ *         <td>Violence<br/>Applicable to NZ_PTV_PG, NZ_PTV_M, NZ_PTV_16, NZ_PTV_18</td>
  *     </tr>
  *     <tr>
  *         <td>NZ_PTV_L</td>
- *         <td>Language</td>
+ *         <td>Language<br/>Applicable to NZ_PTV_PG, NZ_PTV_M, NZ_PTV_16, NZ_PTV_18</td>
  *     </tr>
  *     <tr>
  *         <td>NZ_PTV_S</td>
- *         <td>Sexual content</td>
+ *         <td>Sexual content<br/>Applicable to NZ_PTV_PG, NZ_PTV_M, NZ_PTV_16, NZ_PTV_18</td>
  *     </tr>
  *     <tr>
- *         <td>US_TVPG_D</td>
- *         <td>Suggestive dialogue (Usually means talks about sex)</td>
+ *         <td valign="top" rowspan="5">US_TV</td>
+ *         <td>US_TV_D</td>
+ *         <td>Suggestive dialogue (Usually means talks about sex)<br/>Applicable to US_TV_PG,
+ *         US_TV_14, US_TV</td>
  *     </tr>
  *     <tr>
- *         <td>US_TVPG_L</td>
- *         <td>Coarse language</td>
+ *         <td>US_TV_L</td>
+ *         <td>Coarse language<br/>Applicable to US_TV_PG, US_TV_14</td>
  *     </tr>
  *     <tr>
- *         <td>US_TVPG_S</td>
- *         <td>Sexual content</td>
+ *         <td>US_TV_S</td>
+ *         <td>Sexual content<br/>Applicable to US_TV_PG, US_TV_14, US_TV_MA</td>
  *     </tr>
  *     <tr>
- *         <td>US_TVPG_V</td>
- *         <td>Violence</td>
+ *         <td>US_TV_V</td>
+ *         <td>Violence<br/>Applicable to US_TV_PG, US_TV_14, US_TV_MA</td>
  *     </tr>
  *     <tr>
- *         <td>US_TVPG_FV</td>
- *         <td>Fantasy violence (Children\'s programming only)</td>
+ *         <td>US_TV_FV</td>
+ *         <td>Fantasy violence (Children's programming only)<br/>Applicable to US_TV_Y7</td>
  *     </tr>
  *     <tr>
+ *         <td valign="top" rowspan="6">ZA_TV</td>
  *         <td>ZA_TV_D</td>
- *         <td>Drug</td>
+ *         <td>Drug<br/>Applicable to ZA_TV_F, ZA_TV_PG, ZA_TV_13, ZA_TV_16, ZA_TV_18, ZA_TV_R18
+ *         </td>
  *     </tr>
  *     <tr>
  *         <td>ZA_TV_V</td>
- *         <td>Violence</td>
+ *         <td>Violence<br/>Applicable to ZA_TV_F, ZA_TV_PG, ZA_TV_13, ZA_TV_16, ZA_TV_18, ZA_TV_R18
+ *         </td>
  *     </tr>
  *     <tr>
  *         <td>ZA_TV_N</td>
- *         <td>Nudity</td>
+ *         <td>Nudity<br/>Applicable to ZA_TV_F, ZA_TV_PG, ZA_TV_13, ZA_TV_16, ZA_TV_18, ZA_TV_R18
+ *         </td>
  *     </tr>
  *     <tr>
  *         <td>ZA_TV_P</td>
- *         <td>Prejudice</td>
+ *         <td>Prejudice<br/>Applicable to ZA_TV_F, ZA_TV_PG, ZA_TV_13, ZA_TV_16, ZA_TV_18,
+ *         ZA_TV_R18</td>
  *     </tr>
  *     <tr>
  *         <td>ZA_TV_S</td>
- *         <td>Sex</td>
+ *         <td>Sex<br/>Applicable to ZA_TV_F, ZA_TV_PG, ZA_TV_13, ZA_TV_16, ZA_TV_18, ZA_TV_R18</td>
  *     </tr>
  *     <tr>
  *         <td>ZA_TV_L</td>
- *         <td>Language</td>
+ *         <td>Language<br/>Applicable to ZA_TV_F, ZA_TV_PG, ZA_TV_13, ZA_TV_16, ZA_TV_18, ZA_TV_R18
+ *         </td>
  *     </tr>
  * </table>
  */
@@ -1480,7 +1587,7 @@
             Arrays.sort(subRatings);
             mSubRatings = subRatings;
         }
-        mHashCode = Objects.hash(mDomain, mRating, mSubRatings);
+        mHashCode = 31 * Objects.hash(mDomain, mRating) + Arrays.hashCode(mSubRatings);
     }
 
     /**
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index e975676..9a32bd6 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -153,7 +153,8 @@
     /**
      * Builds a URI that points to all channels from a given TV input.
      *
-     * @param inputId The ID of the TV input to build a channels URI for.
+     * @param inputId The ID of the TV input to build a channels URI for. If {@code null}, builds a
+     *            URI for all the TV inputs.
      */
     public static final Uri buildChannelsUriForInput(String inputId) {
         return buildChannelsUriForInput(inputId, false);
@@ -162,43 +163,46 @@
     /**
      * Builds a URI that points to all or browsable-only channels from a given TV input.
      *
-     * @param inputId The ID of the TV input to build a channels URI for.
+     * @param inputId The ID of the TV input to build a channels URI for. If {@code null}, builds a
+     *            URI for all the TV inputs.
      * @param browsableOnly If set to {@code true} the URI points to only browsable channels. If set
      *            to {@code false} the URI points to all channels regardless of whether they are
      *            browsable or not.
      * @hide
      */
+    @SystemApi
     public static final Uri buildChannelsUriForInput(String inputId, boolean browsableOnly) {
-        return Channels.CONTENT_URI.buildUpon()
-                .appendQueryParameter(PARAM_INPUT, inputId)
-                .appendQueryParameter(PARAM_BROWSABLE_ONLY, String.valueOf(browsableOnly)).build();
+        Uri.Builder builder = Channels.CONTENT_URI.buildUpon();
+        if (inputId != null) {
+            builder.appendQueryParameter(PARAM_INPUT, inputId);
+        }
+        return builder.appendQueryParameter(PARAM_BROWSABLE_ONLY, String.valueOf(browsableOnly))
+                .build();
     }
 
     /**
      * Builds a URI that points to all or browsable-only channels which have programs with the given
      * genre from the given TV input.
      *
-     * @param inputId The ID of the TV input to build a channels URI for. If null, builds a URI for
-     *            all the TV inputs.
-     * @param genre {@link Programs.Genres} to search.
+     * @param inputId The ID of the TV input to build a channels URI for. If {@code null}, builds a
+     *            URI for all the TV inputs.
+     * @param genre {@link Programs.Genres} to search. If {@code null}, builds a URI for all genres.
      * @param browsableOnly If set to {@code true} the URI points to only browsable channels. If set
      *            to {@code false} the URI points to all channels regardless of whether they are
      *            browsable or not.
      * @hide
      */
-    public static final Uri buildChannelsUriForCanonicalGenre(String inputId, String genre,
+    @SystemApi
+    public static final Uri buildChannelsUriForInput(String inputId, String genre,
             boolean browsableOnly) {
+        if (genre == null) {
+            return buildChannelsUriForInput(inputId, browsableOnly);
+        }
         if (!Programs.Genres.isCanonical(genre)) {
             throw new IllegalArgumentException("Not a canonical genre: '" + genre + "'");
         }
-
-        Uri uri;
-        if (inputId == null) {
-            uri = Channels.CONTENT_URI;
-        } else {
-            uri = buildChannelsUriForInput(inputId, browsableOnly);
-        }
-        return uri.buildUpon().appendQueryParameter(PARAM_CANONICAL_GENRE, genre).build();
+        return buildChannelsUriForInput(inputId, browsableOnly).buildUpon()
+                .appendQueryParameter(PARAM_CANONICAL_GENRE, genre).build();
     }
 
     /**
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index e735e4e..6ed7580 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -38,7 +38,6 @@
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.util.Pair;
 import android.util.SparseIntArray;
 import android.util.Xml;
 
@@ -47,9 +46,11 @@
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.List;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
 
 /**
  * This class is used to specify meta information of a TV input.
@@ -245,17 +246,17 @@
                 Log.d(TAG, "Settings activity loaded. [" + input.mSettingsActivity + "] for "
                         + si.name);
             }
-            int contentRatingSystemXml = sa.getResourceId(
-                    com.android.internal.R.styleable.TvInputService_contentRatingSystemXml, -1);
-            if (contentRatingSystemXml != -1) {
+            int tvContentRatingDescription = sa.getResourceId(
+                    com.android.internal.R.styleable.TvInputService_tvContentRatingDescription, -1);
+            if (tvContentRatingDescription != -1) {
                 input.mRatingSystemXmlUri = new Uri.Builder()
                         .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
                         .authority(si.packageName)
-                        .appendPath(Integer.toString(contentRatingSystemXml))
+                        .appendPath(Integer.toString(tvContentRatingDescription))
                         .build();
                 if (DEBUG) {
-                    Log.d(TAG, "Content rating xml loaded. [" + contentRatingSystemXml + "] for "
-                            + si.name);
+                    Log.d(TAG, "Content rating xml loaded. [" + tvContentRatingDescription
+                            + "] for " + si.name);
                 }
             }
             sa.recycle();
@@ -405,7 +406,7 @@
      */
     @SystemApi
     public boolean isHidden(Context context) {
-        return TvInputSettings.isHidden(context, mId, UserHandle.USER_CURRENT);
+        return TvInputSettings.isHidden(context, mId, UserHandle.myUserId());
     }
 
     /**
@@ -433,7 +434,7 @@
      */
     @SystemApi
     public CharSequence loadCustomLabel(Context context) {
-        return TvInputSettings.getCustomLabel(context, mId, UserHandle.USER_CURRENT);
+        return TvInputSettings.getCustomLabel(context, mId, UserHandle.myUserId());
     }
 
     /**
@@ -601,66 +602,61 @@
         }
 
         private static String getCustomLabel(Context context, String inputId, int userId) {
-            for (Pair<String, String> pair : getCustomLabelList(context, userId)) {
-                if (pair.first.equals(inputId)) {
-                    return pair.second;
-                }
-            }
-            return null;
+            return getCustomLabels(context, userId).get(inputId);
         }
 
         /**
-         * Returns a list of TV input IDs which are marked as hidden by user in the settings.
+         * Returns a set of TV input IDs which are marked as hidden by user in the settings.
          *
          * @param context The application context
-         * @param userId The user ID for the stored hidden input list
+         * @param userId The user ID for the stored hidden input set
          * @hide
          */
         @SystemApi
-        public static List<String> getHiddenTvInputIds(Context context, int userId) {
+        public static Set<String> getHiddenTvInputIds(Context context, int userId) {
             String hiddenIdsString = Settings.Secure.getStringForUser(
                     context.getContentResolver(), Settings.Secure.TV_INPUT_HIDDEN_INPUTS, userId);
             if (TextUtils.isEmpty(hiddenIdsString)) {
-                return new ArrayList<String>();
+                return new HashSet<String>();
             }
             String[] ids = hiddenIdsString.split(TV_INPUT_SEPARATOR);
-            return new ArrayList(Arrays.asList(ids));
+            return new HashSet(Arrays.asList(ids));
         }
 
         /**
-         * Returns a list of TV input ID/custom label pairs set by the user in the settings.
+         * Returns a map of TV input ID/custom label pairs set by the user in the settings.
          *
          * @param context The application context
-         * @param userId The user ID for the stored hidden input list
+         * @param userId The user ID for the stored hidden input map
          * @hide
          */
         @SystemApi
-        public static List<Pair<String, String>> getCustomLabelList(Context context, int userId) {
+        public static Map<String, String> getCustomLabels(Context context, int userId) {
             String labelsString = Settings.Secure.getStringForUser(
                     context.getContentResolver(), Settings.Secure.TV_INPUT_CUSTOM_LABELS, userId);
-            List<Pair<String, String>> list = new ArrayList<Pair<String, String>>();
+            Map<String, String> map = new HashMap<String, String>();
             if (TextUtils.isEmpty(labelsString)) {
-                return list;
+                return map;
             }
             String[] pairs = labelsString.split(TV_INPUT_SEPARATOR);
             for (String pairString : pairs) {
                 String[] pair = pairString.split(CUSTOM_NAME_SEPARATOR);
-                list.add(new Pair<String, String>(pair[0], pair[1]));
+                map.put(pair[0], pair[1]);
             }
-            return list;
+            return map;
         }
 
         /**
-         * Stores a list of TV input IDs which are marked as hidden by user. This is expected to
+         * Stores a set of TV input IDs which are marked as hidden by user. This is expected to
          * be called from the settings app.
          *
          * @param context The application context
-         * @param hiddenInputIds A list including all the hidden TV input IDs
-         * @param userId The user ID for the stored hidden input list
+         * @param hiddenInputIds A set including all the hidden TV input IDs
+         * @param userId The user ID for the stored hidden input set
          * @hide
          */
         @SystemApi
-        public static void putHiddenTvInputList(Context context, List<String> hiddenInputIds,
+        public static void putHiddenTvInputs(Context context, Set<String> hiddenInputIds,
                 int userId) {
             StringBuilder builder = new StringBuilder();
             boolean firstItem = true;
@@ -678,30 +674,30 @@
         }
 
         /**
-         * Stores a list of TV input ID/custom label pairs set by user. This is expected to be
+         * Stores a map of TV input ID/custom label set by user. This is expected to be
          * called from the settings app.
          *
          * @param context The application context.
-         * @param customLabels A list of TV input ID/custom label pairs
-         * @param userId The user ID for the stored hidden input list
+         * @param customLabels A map of TV input ID/custom label pairs
+         * @param userId The user ID for the stored hidden input map
          * @hide
          */
         @SystemApi
-        public static void putCustomLabelList(Context context,
-                List<Pair<String, String>> customLabels, int userId) {
+        public static void putCustomLabels(Context context,
+                Map<String, String> customLabels, int userId) {
             StringBuilder builder = new StringBuilder();
             boolean firstItem = true;
-            for (Pair<String, String> pair : customLabels) {
-                ensureValidField(pair.first);
-                ensureValidField(pair.second);
+            for (Map.Entry<String, String> entry: customLabels.entrySet()) {
+                ensureValidField(entry.getKey());
+                ensureValidField(entry.getValue());
                 if (firstItem) {
                     firstItem = false;
                 } else {
                     builder.append(TV_INPUT_SEPARATOR);
                 }
-                builder.append(pair.first);
+                builder.append(entry.getKey());
                 builder.append(CUSTOM_NAME_SEPARATOR);
-                builder.append(pair.second);
+                builder.append(entry.getValue());
             }
             Settings.Secure.putStringForUser(context.getContentResolver(),
                     Settings.Secure.TV_INPUT_CUSTOM_LABELS, builder.toString(), userId);
diff --git a/media/jni/android_media_MediaCodecList.cpp b/media/jni/android_media_MediaCodecList.cpp
index ecba02a..12eb7d2 100644
--- a/media/jni/android_media_MediaCodecList.cpp
+++ b/media/jni/android_media_MediaCodecList.cpp
@@ -85,6 +85,7 @@
     sp<IMediaCodecList> mcl = getCodecList(env);
     if (mcl == NULL) {
         // Runtime exception already pending.
+        env->ReleaseStringUTFChars(name, nameStr);
         return -ENOENT;
     }
 
@@ -162,7 +163,6 @@
     }
 
     const char *typeStr = env->GetStringUTFChars(type, NULL);
-
     if (typeStr == NULL) {
         // Out of memory exception already pending.
         return NULL;
@@ -177,12 +177,12 @@
     // TODO query default-format also from codec/codec list
     const sp<MediaCodecInfo::Capabilities> &capabilities =
         info->getCapabilitiesFor(typeStr);
+    env->ReleaseStringUTFChars(type, typeStr);
+    typeStr = NULL;
     if (capabilities == NULL) {
         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
         return NULL;
     }
-    env->ReleaseStringUTFChars(type, typeStr);
-    typeStr = NULL;
 
     capabilities->getSupportedColorFormats(&colorFormats);
     capabilities->getSupportedProfileLevels(&profileLevels);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java b/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java
index 3038323..b2e38fc 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java
@@ -210,7 +210,7 @@
                     return pm.getDrawable(info.packageName, icon, info.applicationInfo);
                 }
             } else {
-                return context.getResources().getDrawable(icon);
+                return context.getDrawable(icon);
             }
         }
         return null;
@@ -218,19 +218,17 @@
 
     public static Drawable loadMimeIcon(
             Context context, String mimeType, String authority, String docId, int mode) {
-        final Resources res = context.getResources();
-
         if (Document.MIME_TYPE_DIR.equals(mimeType)) {
             // TODO: eventually move these hacky assets into that package
             if ("com.android.providers.media.documents".equals(authority)
                     && docId.startsWith("album")) {
-                return res.getDrawable(R.drawable.ic_doc_album);
+                return context.getDrawable(R.drawable.ic_doc_album);
             }
 
             if (mode == DocumentsActivity.State.MODE_GRID) {
-                return res.getDrawable(R.drawable.ic_grid_folder);
+                return context.getDrawable(R.drawable.ic_grid_folder);
             } else {
-                return res.getDrawable(R.drawable.ic_doc_folder);
+                return context.getDrawable(R.drawable.ic_doc_folder);
             }
         }
 
@@ -238,16 +236,14 @@
     }
 
     public static Drawable loadMimeIcon(Context context, String mimeType) {
-        final Resources res = context.getResources();
-
         if (Document.MIME_TYPE_DIR.equals(mimeType)) {
-            return res.getDrawable(R.drawable.ic_doc_folder);
+            return context.getDrawable(R.drawable.ic_doc_folder);
         }
 
         // Look for exact match first
         Integer resId = sMimeIcons.get(mimeType);
         if (resId != null) {
-            return res.getDrawable(resId);
+            return context.getDrawable(resId);
         }
 
         if (mimeType == null) {
@@ -258,15 +254,15 @@
         // Otherwise look for partial match
         final String typeOnly = mimeType.split("/")[0];
         if ("audio".equals(typeOnly)) {
-            return res.getDrawable(R.drawable.ic_doc_audio);
+            return context.getDrawable(R.drawable.ic_doc_audio);
         } else if ("image".equals(typeOnly)) {
-            return res.getDrawable(R.drawable.ic_doc_image);
+            return context.getDrawable(R.drawable.ic_doc_image);
         } else if ("text".equals(typeOnly)) {
-            return res.getDrawable(R.drawable.ic_doc_text);
+            return context.getDrawable(R.drawable.ic_doc_text);
         } else if ("video".equals(typeOnly)) {
-            return res.getDrawable(R.drawable.ic_doc_video);
+            return context.getDrawable(R.drawable.ic_doc_video);
         } else {
-            return res.getDrawable(R.drawable.ic_doc_generic);
+            return context.getDrawable(R.drawable.ic_doc_generic);
         }
     }
 
@@ -276,7 +272,7 @@
         final TypedValue outValue = new TypedValue();
         context.getTheme().resolveAttribute(tintAttrId, outValue, true);
 
-        final Drawable icon = res.getDrawable(drawableId);
+        final Drawable icon = context.getDrawable(drawableId);
         icon.mutate();
         icon.setTintList(res.getColorStateList(outValue.resourceId));
         return icon;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
index 82c3048..dd75dbd 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
@@ -221,8 +221,7 @@
             final DocumentStack stack = getItem(position);
             iconMime.setImageDrawable(stack.root.loadIcon(context));
 
-            final Drawable crumb = context.getResources()
-                    .getDrawable(R.drawable.ic_breadcrumb_arrow);
+            final Drawable crumb = context.getDrawable(R.drawable.ic_breadcrumb_arrow);
             crumb.setBounds(0, 0, crumb.getIntrinsicWidth(), crumb.getIntrinsicHeight());
 
             final SpannableStringBuilder builder = new SpannableStringBuilder();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
index a358798..fcfe518 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
@@ -205,7 +205,7 @@
 
     public Drawable loadIcon(Context context) {
         if (derivedIcon != 0) {
-            return context.getResources().getDrawable(derivedIcon);
+            return context.getDrawable(derivedIcon);
         } else {
             return IconUtils.loadPackageIcon(context, authority, icon);
         }
diff --git a/packages/Keyguard/res/values-h560dp/dimens.xml b/packages/Keyguard/res/values-h560dp/dimens.xml
new file mode 100644
index 0000000..1683113
--- /dev/null
+++ b/packages/Keyguard/res/values-h560dp/dimens.xml
@@ -0,0 +1,20 @@
+<?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
+  -->
+
+<resources>
+    <dimen name="widget_big_font_size">96dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/packages/Keyguard/res/values-sw600dp-land/dimens.xml b/packages/Keyguard/res/values-sw600dp-land/dimens.xml
index 13a6f62..89252cf 100644
--- a/packages/Keyguard/res/values-sw600dp-land/dimens.xml
+++ b/packages/Keyguard/res/values-sw600dp-land/dimens.xml
@@ -25,5 +25,5 @@
     <dimen name="kg_status_line_font_right_margin">16dp</dimen>
 
     <!-- Overload default clock widget parameters -->
-    <dimen name="widget_big_font_size">88dp</dimen>
+    <dimen name="widget_big_font_size">100dp</dimen>
 </resources>
\ No newline at end of file
diff --git a/packages/Keyguard/res/values-sw600dp/dimens.xml b/packages/Keyguard/res/values-sw600dp/dimens.xml
index 69bf44f..74be1ff 100644
--- a/packages/Keyguard/res/values-sw600dp/dimens.xml
+++ b/packages/Keyguard/res/values-sw600dp/dimens.xml
@@ -63,7 +63,7 @@
     <dimen name="keyguard_muliuser_selector_margin">12dp</dimen>
 
     <!-- Overload default clock widget parameters -->
-    <dimen name="widget_big_font_size">120dp</dimen>
+    <dimen name="widget_big_font_size">140dp</dimen>
     <dimen name="widget_label_font_size">16sp</dimen>
     <dimen name="bottom_text_spacing_digital">-16dp</dimen>
 
diff --git a/packages/Keyguard/res/values-sw720dp-land/dimens.xml b/packages/Keyguard/res/values-sw720dp-land/dimens.xml
index 14726ab..731bb64 100644
--- a/packages/Keyguard/res/values-sw720dp-land/dimens.xml
+++ b/packages/Keyguard/res/values-sw720dp-land/dimens.xml
@@ -26,4 +26,6 @@
 
     <!-- Horizontal padding for the widget pager -->
     <dimen name="kg_widget_pager_horizontal_padding">32dp</dimen>
+
+    <dimen name="widget_big_font_size">150dp</dimen>
 </resources>
diff --git a/packages/Keyguard/res/values-sw720dp/dimens.xml b/packages/Keyguard/res/values-sw720dp/dimens.xml
index c487072..3e89a84 100644
--- a/packages/Keyguard/res/values-sw720dp/dimens.xml
+++ b/packages/Keyguard/res/values-sw720dp/dimens.xml
@@ -61,4 +61,5 @@
     <!-- Height of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) -->
     <dimen name="keyguard_security_height">420dp</dimen>
 
+    <dimen name="widget_big_font_size">150dp</dimen>
 </resources>
diff --git a/packages/Keyguard/res/values/dimens.xml b/packages/Keyguard/res/values/dimens.xml
index e822c82..bfc0531 100644
--- a/packages/Keyguard/res/values/dimens.xml
+++ b/packages/Keyguard/res/values/dimens.xml
@@ -161,7 +161,7 @@
     <dimen name="bottom_text_spacing_digital">-10dp</dimen>
     <dimen name="label_font_size">14dp</dimen>
     <dimen name="widget_label_font_size">16sp</dimen>
-    <dimen name="widget_big_font_size">96dp</dimen>
+    <dimen name="widget_big_font_size">88dp</dimen>
     <dimen name="big_font_size">120dp</dimen>
 
     <!-- The y translation to apply at the start in appear animations. -->
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java b/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java
index 25f3383..32f7a1e 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java
@@ -36,6 +36,7 @@
 import android.provider.MediaStore;
 import android.util.Log;
 import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
 
 import com.android.keyguard.KeyguardHostView.OnDismissAction;
 
@@ -214,9 +215,9 @@
 
     private void dismissKeyguardOnNextActivity() {
         try {
-            ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
+            WindowManagerGlobal.getWindowManagerService().dismissKeyguard();
         } catch (RemoteException e) {
-            Log.w(TAG, "can't dismiss keyguard on launch");
+            Log.w(TAG, "Error dismissing keyguard", e);
         }
     }
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimpleHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimpleHostView.java
index bc159cb..f009787 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimpleHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimpleHostView.java
@@ -68,5 +68,17 @@
         public void onUserSwitchComplete(int userId) {
             getSecurityContainer().showPrimarySecurityScreen(false /* turning off */);
         }
+
+        @Override
+        public void onTrustInitiatedByUser(int userId) {
+            if (userId != mLockPatternUtils.getCurrentUser()) return;
+            if (!isAttachedToWindow()) return;
+
+            if (isVisibleToUser()) {
+                dismiss(false /* authenticated */);
+            } else {
+                // TODO: Play first half of unlock sound.
+            }
+        }
     };
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
index daba0a2..51a276e 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
@@ -16,9 +16,10 @@
 
 package com.android.keyguard;
 
-import android.app.AlarmClockInfo;
+import android.app.AlarmManager;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.provider.AlarmClock;
 import android.text.TextUtils;
@@ -26,6 +27,7 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Slog;
+import android.util.TypedValue;
 import android.view.View;
 import android.widget.GridLayout;
 import android.widget.TextClock;
@@ -115,8 +117,19 @@
         mClockView.setElegantTextHeight(false);
     }
 
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        mClockView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
+                getResources().getDimensionPixelSize(R.dimen.widget_big_font_size));
+        mDateView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
+                getResources().getDimensionPixelSize(R.dimen.widget_label_font_size));
+        mOwnerInfo.setTextSize(TypedValue.COMPLEX_UNIT_PX,
+                getResources().getDimensionPixelSize(R.dimen.widget_label_font_size));
+    }
+
     protected void refresh() {
-        AlarmClockInfo nextAlarm = mLockPatternUtils.getNextAlarm();
+        AlarmManager.AlarmClockInfo nextAlarm = mLockPatternUtils.getNextAlarm();
         Patterns.update(mContext, nextAlarm != null);
 
         mDateView.setFormat24Hour(Patterns.dateView);
@@ -128,7 +141,7 @@
         refreshAlarmStatus(nextAlarm);
     }
 
-    void refreshAlarmStatus(AlarmClockInfo nextAlarm) {
+    void refreshAlarmStatus(AlarmManager.AlarmClockInfo nextAlarm) {
         if (nextAlarm != null) {
             mAlarmStatusView.setText(formatNextAlarm(mContext, nextAlarm));
             mAlarmStatusView.setVisibility(View.VISIBLE);
@@ -137,7 +150,7 @@
         }
     }
 
-    public static String formatNextAlarm(Context context, AlarmClockInfo info) {
+    public static String formatNextAlarm(Context context, AlarmManager.AlarmClockInfo info) {
         if (info == null) {
             return "";
         }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
index d9c5a53..e35b2b2 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
@@ -237,7 +237,7 @@
     }
 
     public void startDisappearAnimation(Runnable finishRunnable) {
-        if (!mSecurityContainer.startDisappearAnimation(finishRunnable)) {
+        if (!mSecurityContainer.startDisappearAnimation(finishRunnable) && finishRunnable != null) {
             finishRunnable.run();
         }
     }
diff --git a/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
index f74843e..2e5450d 100644
--- a/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
@@ -61,4 +61,9 @@
      * Report when keyguard is actually gone
      */
     void keyguardGone();
+
+    /**
+     * Report when the UI is ready for dismissing the whole Keyguard.
+     */
+    void readyForKeyguardDone();
 }
diff --git a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
index ed17494..4ea1c77 100644
--- a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
+++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
@@ -31,6 +31,16 @@
 public class SampleTrustAgent extends TrustAgentService
         implements SharedPreferences.OnSharedPreferenceChangeListener {
 
+    /**
+     * If true, allows anyone to control this trust agent, e.g. using adb:
+     * <pre>
+     * $ adb shell am broadcast -a action.sample_trust_agent.grant_trust\
+     *  -e extra.message SampleTrust\
+     *  --el extra.duration 1000 --ez extra.init_by_user false
+     * </pre>
+     */
+    private static final boolean ALLOW_EXTERNAL_BROADCASTS = false;
+
     LocalBroadcastManager mLocalBroadcastManager;
 
     private static final String ACTION_GRANT_TRUST = "action.sample_trust_agent.grant_trust";
@@ -38,7 +48,7 @@
 
     private static final String EXTRA_MESSAGE = "extra.message";
     private static final String EXTRA_DURATION = "extra.duration";
-    private static final String EXTRA_EXTRA = "extra.extra";
+    private static final String EXTRA_INITIATED_BY_USER = "extra.init_by_user";
 
     private static final String PREFERENCE_REPORT_UNLOCK_ATTEMPTS
             = "preference.report_unlock_attempts";
@@ -50,11 +60,16 @@
     @Override
     public void onCreate() {
         super.onCreate();
+        mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
+
         IntentFilter filter = new IntentFilter();
         filter.addAction(ACTION_GRANT_TRUST);
         filter.addAction(ACTION_REVOKE_TRUST);
-        mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
         mLocalBroadcastManager.registerReceiver(mReceiver, filter);
+        if (ALLOW_EXTERNAL_BROADCASTS) {
+            registerReceiver(mReceiver, filter);
+        }
+
         setManagingTrust(getIsManagingTrust(this));
         PreferenceManager.getDefaultSharedPreferences(this)
                 .registerOnSharedPreferenceChangeListener(this);
@@ -79,6 +94,9 @@
     public void onDestroy() {
         super.onDestroy();
         mLocalBroadcastManager.unregisterReceiver(mReceiver);
+        if (ALLOW_EXTERNAL_BROADCASTS) {
+            unregisterReceiver(mReceiver);
+        }
         PreferenceManager.getDefaultSharedPreferences(this)
                 .unregisterOnSharedPreferenceChangeListener(this);
     }
@@ -91,7 +109,7 @@
                 try {
                     grantTrust(intent.getStringExtra(EXTRA_MESSAGE),
                             intent.getLongExtra(EXTRA_DURATION, 0),
-                            false /* initiatedByUser */);
+                            intent.getBooleanExtra(EXTRA_INITIATED_BY_USER, false));
                 } catch (IllegalStateException e) {
                     Toast.makeText(context,
                             "IllegalStateException: " + e.getMessage(), Toast.LENGTH_SHORT).show();
@@ -103,11 +121,11 @@
     };
 
     public static void sendGrantTrust(Context context,
-            String message, long durationMs, Bundle extra) {
+            String message, long durationMs, boolean initiatedByUser) {
         Intent intent = new Intent(ACTION_GRANT_TRUST);
         intent.putExtra(EXTRA_MESSAGE, message);
         intent.putExtra(EXTRA_DURATION, durationMs);
-        intent.putExtra(EXTRA_EXTRA, extra);
+        intent.putExtra(EXTRA_INITIATED_BY_USER, initiatedByUser);
         LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
     }
 
diff --git a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
index 2c85609..bea74ab 100644
--- a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
+++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
@@ -59,7 +59,7 @@
         int id = v.getId();
         if (id == R.id.enable_trust) {
             SampleTrustAgent.sendGrantTrust(this, "SampleTrustAgent", TRUST_DURATION_MS,
-                    null /* extra */);
+                    false /* initiatedByUser */);
         } else if (id == R.id.revoke_trust) {
             SampleTrustAgent.sendRevokeTrust(this);
         } else if (id == R.id.crash) {
diff --git a/packages/PrintSpooler/res/drawable/ic_savetopdf.xml b/packages/PrintSpooler/res/drawable/ic_savetopdf.xml
new file mode 100644
index 0000000..60ed33a
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable/ic_savetopdf.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="@drawable/ic_menu_savetopdf"
+    android:tint="@color/promoted_action_background_color" />
diff --git a/packages/PrintSpooler/res/layout/preview_page.xml b/packages/PrintSpooler/res/layout/preview_page.xml
index 509a1d2..76dd76b 100644
--- a/packages/PrintSpooler/res/layout/preview_page.xml
+++ b/packages/PrintSpooler/res/layout/preview_page.xml
@@ -31,7 +31,7 @@
     <RelativeLayout
         android:id="@+id/page_footer"
         android:layout_width="fill_parent"
-        android:layout_height="32dip"
+        android:layout_height="@dimen/preview_page_footer_height"
         android:background="@*android:color/material_grey_500"
         android:orientation="horizontal">
 
diff --git a/packages/PrintSpooler/res/layout/print_activity.xml b/packages/PrintSpooler/res/layout/print_activity.xml
index 3905646..ee5d42a 100644
--- a/packages/PrintSpooler/res/layout/print_activity.xml
+++ b/packages/PrintSpooler/res/layout/print_activity.xml
@@ -27,7 +27,6 @@
         android:id="@+id/static_content"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
-        android:padding="16dip"
         android:elevation="@dimen/preview_controls_elevation"
         android:background="?android:attr/colorPrimary">
 
@@ -35,6 +34,7 @@
             android:id="@+id/destination_spinner"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:layout_marginTop="4dip"
             android:dropDownWidth="wrap_content"
             android:minHeight="?android:attr/listPreferredItemHeightSmall">
         </Spinner>
@@ -56,7 +56,6 @@
         <TextView
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginTop="8dip"
             android:layout_marginStart="12dip"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:labelFor="@+id/copies_count_summary"
@@ -67,7 +66,6 @@
             android:id="@+id/copies_count_summary"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginTop="8dip"
             android:layout_marginStart="16dip"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textColor="?android:attr/textColorPrimary">
@@ -76,7 +74,6 @@
         <TextView
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginTop="8dip"
             android:layout_marginStart="32dip"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:labelFor="@+id/paper_size_summary"
@@ -87,7 +84,6 @@
             android:id="@+id/paper_size_summary"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginTop="8dip"
             android:layout_marginStart="16dip"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textColor="?android:attr/textColorPrimary">
diff --git a/packages/PrintSpooler/res/layout/print_activity_controls.xml b/packages/PrintSpooler/res/layout/print_activity_controls.xml
index ef6044a..31bda7e 100644
--- a/packages/PrintSpooler/res/layout/print_activity_controls.xml
+++ b/packages/PrintSpooler/res/layout/print_activity_controls.xml
@@ -267,8 +267,8 @@
              android:id="@+id/expand_collapse_icon"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
-             android:layout_marginTop="8dip"
-             android:layout_marginBottom="8dip"
+             android:layout_marginTop="4dip"
+             android:layout_marginBottom="4dip"
              android:layout_gravity="center"
              android:background="@drawable/ic_expand_more">
          </ImageView>
diff --git a/packages/PrintSpooler/res/values/constants.xml b/packages/PrintSpooler/res/values/constants.xml
index faad527..b95703b 100644
--- a/packages/PrintSpooler/res/values/constants.xml
+++ b/packages/PrintSpooler/res/values/constants.xml
@@ -45,4 +45,7 @@
     <fraction name="page_selected_alpha">100%</fraction>
     <fraction name="page_unselected_alpha">50%</fraction>
 
+    <dimen name="preview_page_footer_height">32dip</dimen>
+    <dimen name="preview_page_min_width">130dip</dimen>
+
 </resources>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
index e976936..5bcdb9f 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
@@ -96,6 +96,7 @@
     private float mUnselectedPageAlpha;
 
     private int mPreviewPageMargin;
+    private int mPreviewPageMinWidth;
     private int mPreviewListPadding;
     private int mFooterHeight;
 
@@ -141,17 +142,17 @@
         mPreviewPageMargin = mContext.getResources().getDimensionPixelSize(
                 R.dimen.preview_page_margin);
 
+        mPreviewPageMinWidth = mContext.getResources().getDimensionPixelSize(
+                R.dimen.preview_page_min_width);
+
         mPreviewListPadding = mContext.getResources().getDimensionPixelSize(
                 R.dimen.preview_list_padding);
 
         mColumnCount = mContext.getResources().getInteger(
                 R.integer.preview_page_per_row_count);
 
-        TypedValue outValue = new TypedValue();
-        mContext.getTheme().resolveAttribute(
-                com.android.internal.R.attr.listPreferredItemHeightSmall, outValue, true);
-        mFooterHeight = TypedValue.complexToDimensionPixelSize(outValue.data,
-                mContext.getResources().getDisplayMetrics());
+        mFooterHeight = mContext.getResources().getDimensionPixelSize(
+                R.dimen.preview_page_footer_height);
 
         mPreviewArea = previewArea;
 
@@ -428,8 +429,12 @@
         // Compute max page height.
         final int pageContentDesiredHeight = (int) (((float) pageContentDesiredWidth
                 / pageAspectRatio) + 0.5f);
-        final int pageContentMaxHeight = availableHeight - 2 * (mPreviewListPadding
-                + mPreviewPageMargin) - mFooterHeight;
+
+        // If the page does not fit entirely in a vertial direction,
+        // we shirk it but not less than the minimal page width.
+        final int pageContentMinHeight = (int) (mPreviewPageMinWidth / pageAspectRatio + 0.5f);
+        final int pageContentMaxHeight = Math.max(pageContentMinHeight,
+                availableHeight - 2 * (mPreviewListPadding + mPreviewPageMargin) - mFooterHeight);
 
         mPageContentHeight = Math.min(pageContentDesiredHeight, pageContentMaxHeight);
         mPageContentWidth = (int) ((mPageContentHeight * pageAspectRatio) + 0.5f);
@@ -439,10 +444,17 @@
 
         final int rowCount = mSelectedPageCount / columnCount
                 + ((mSelectedPageCount % columnCount) > 0 ? 1 : 0);
-        final int totalContentHeight = rowCount* (mPageContentHeight + mFooterHeight + 2
+        final int totalContentHeight = rowCount * (mPageContentHeight + mFooterHeight + 2
                 * mPreviewPageMargin);
-        final int verticalPadding = Math.max(mPreviewListPadding,
-                (availableHeight - totalContentHeight) / 2);
+
+        final int verticalPadding;
+        if (mPageContentHeight + mFooterHeight + mPreviewListPadding > availableHeight) {
+            verticalPadding = Math.max(mPreviewPageMargin,
+                    (availableHeight - totalContentHeight) / 2);
+        } else {
+            verticalPadding = Math.max(mPreviewListPadding,
+                    (availableHeight - totalContentHeight) / 2);
+        }
 
         mPreviewArea.setPadding(horizontalPadding, verticalPadding,
                 horizontalPadding, verticalPadding);
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index a1b1aec..6b29e5f 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -1704,7 +1704,7 @@
                 if (position == 0 && getPdfPrinter() != null) {
                     PrinterHolder printerHolder = (PrinterHolder) getItem(position);
                     title = printerHolder.printer.getName();
-                    icon = getResources().getDrawable(com.android.internal.R.drawable.ic_menu_save);
+                    icon = getResources().getDrawable(R.drawable.ic_savetopdf);
                 } else if (position == 1) {
                     title = getString(R.string.all_printers);
                 }
@@ -1712,7 +1712,7 @@
                 if (position == 1 && getPdfPrinter() != null) {
                     PrinterHolder printerHolder = (PrinterHolder) getItem(position);
                     title = printerHolder.printer.getName();
-                    icon = getResources().getDrawable(com.android.internal.R.drawable.ic_menu_save);
+                    icon = getResources().getDrawable(R.drawable.ic_savetopdf);
                 } else if (position == getCount() - 1) {
                     title = getString(R.string.all_printers);
                 } else {
diff --git a/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java b/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java
index 4d2cb6c..8365373 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java
@@ -94,7 +94,7 @@
         mMinMargins = minMargins;
         mContentRequested = false;
 
-        // If there is not provider we want immediately to switch to
+        // If there is no provider we want immediately to switch to
         // the empty state, so pages with no content appear blank.
         if (mProvider == null && getBackground() != mEmptyState) {
             setBackground(mEmptyState);
diff --git a/packages/PrintSpooler/src/com/android/printspooler/widget/PrintOptionsLayout.java b/packages/PrintSpooler/src/com/android/printspooler/widget/PrintOptionsLayout.java
index 01f4a04..71f4aa7 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/widget/PrintOptionsLayout.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/widget/PrintOptionsLayout.java
@@ -162,7 +162,7 @@
             }
 
             cellStart = getPaddingStart();
-            cellTop += cellTop + rowHeight;
+            cellTop += rowHeight;
         }
     }
 
diff --git a/packages/SystemUI/res/drawable/recents_task_view_header_bg.xml b/packages/SystemUI/res/drawable/recents_task_view_header_bg.xml
new file mode 100644
index 0000000..745af33
--- /dev/null
+++ b/packages/SystemUI/res/drawable/recents_task_view_header_bg.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="?android:attr/colorControlHighlight">
+    <item android:drawable="@android:color/transparent" />
+</ripple>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/trust_circle.xml b/packages/SystemUI/res/drawable/trust_circle.xml
index 89f4a0b..56fc62e 100644
--- a/packages/SystemUI/res/drawable/trust_circle.xml
+++ b/packages/SystemUI/res/drawable/trust_circle.xml
@@ -17,6 +17,6 @@
   -->
 
 <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="ring"
-        android:innerRadius="24dp" android:thickness="1dp">
-    <solid android:color="#66ffffff" />
+        android:innerRadius="22dp" android:thickness="2dp">
+    <solid android:color="#4cffffff" />
 </shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index fc6e9ae..8e9b501 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -27,7 +27,7 @@
         android:id="@+id/keyguard_indication_text"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginBottom="70dp"
+        android:layout_marginBottom="@dimen/keyguard_indication_margin_bottom"
         android:layout_gravity="bottom|center_horizontal"
         android:textStyle="italic"
         android:textColor="#ffffff"
diff --git a/packages/SystemUI/res/layout/keyguard_status_bar.xml b/packages/SystemUI/res/layout/keyguard_status_bar.xml
index d4b1214..fcc0f4a 100644
--- a/packages/SystemUI/res/layout/keyguard_status_bar.xml
+++ b/packages/SystemUI/res/layout/keyguard_status_bar.xml
@@ -60,7 +60,7 @@
             android:paddingEnd="@dimen/battery_level_padding_end"
             android:textColor="#ffffff"
             android:visibility="gone"
-            android:textSize="12sp"/>
+            android:textSize="@dimen/battery_level_text_size"/>
     </LinearLayout>
 
     <com.android.keyguard.CarrierText
diff --git a/packages/SystemUI/res/layout/qs_detail_header.xml b/packages/SystemUI/res/layout/qs_detail_header.xml
index fcbb32c..f3f1918 100644
--- a/packages/SystemUI/res/layout/qs_detail_header.xml
+++ b/packages/SystemUI/res/layout/qs_detail_header.xml
@@ -15,7 +15,10 @@
      limitations under the License.
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    style="@style/BrightnessDialogContainer"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_alignParentBottom="true"
+    android:padding="@dimen/qs_panel_padding"
     android:background="@drawable/btn_borderless_rect" >
 
     <TextView
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index 4a5fffe..828065b 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -17,7 +17,8 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent" 
     android:layout_height="match_parent"
-    android:focusable="true">
+    android:focusable="true"
+    android:background="#FFffffff">
     <com.android.systemui.recents.views.TaskViewThumbnail
         android:id="@+id/task_view_thumbnail"
         android:layout_width="match_parent"
@@ -26,8 +27,7 @@
         android:id="@+id/task_view_bar"
         android:layout_width="match_parent"
         android:layout_height="@dimen/recents_task_bar_height"
-        android:layout_gravity="top|center_horizontal"
-        android:background="@color/recents_task_bar_default_background_color">
+        android:layout_gravity="top|center_horizontal">
         <com.android.systemui.recents.views.FixedSizeImageView
             android:id="@+id/application_icon"
             android:layout_width="@dimen/recents_task_view_application_icon_size"
@@ -69,7 +69,6 @@
         android:layout_gravity="bottom|right"
         android:layout_marginRight="15dp"
         android:layout_marginBottom="15dp"
-        android:translationZ="50dp"
         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/split_clock_view.xml b/packages/SystemUI/res/layout/split_clock_view.xml
index d9ba35d..87b7051 100644
--- a/packages/SystemUI/res/layout/split_clock_view.xml
+++ b/packages/SystemUI/res/layout/split_clock_view.xml
@@ -34,5 +34,15 @@
         android:layout_height="wrap_content"
         android:singleLine="true"
         android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock"
+        android:textSize="@dimen/qs_time_collapsed_size"
+        />
+
+    <!-- Empty text view so we have the same height when expanded/collapsed-->
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:visibility="invisible"
+        android:singleLine="true"
+        android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock"
         />
 </com.android.systemui.statusbar.policy.SplitClockView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 4eab9c7..cc449c5 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -50,6 +50,10 @@
         android:visibility="gone"
         />
 
+    <include
+        layout="@layout/keyguard_bottom_area"
+        android:visibility="gone" />
+
     <com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer
         android:layout_width="match_parent"
         android:layout_height="match_parent"
@@ -115,10 +119,6 @@
 
     <include layout="@layout/status_bar_expanded_header" />
 
-    <include
-        layout="@layout/keyguard_bottom_area"
-        android:visibility="gone" />
-
     <com.android.systemui.statusbar.AlphaOptimizedView
         android:id="@+id/qs_navbar_scrim"
         android:layout_height="96dp"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index 21d8457..1226fc5 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -51,7 +51,7 @@
         android:layout_height="@dimen/status_bar_header_height"
         android:background="@drawable/ripple_drawable"
         android:src="@drawable/ic_settings"
-        android:contentDescription="@string/accessibility_desc_quick_settings"/>
+        android:contentDescription="@string/accessibility_desc_settings"/>
 
     <LinearLayout android:id="@+id/system_icons_super_container"
         android:layout_width="wrap_content"
@@ -72,7 +72,7 @@
             android:layout_marginStart="@dimen/header_battery_margin_expanded"
             android:paddingEnd="@dimen/battery_level_padding_end"
             android:textColor="#ffffff"
-            android:textSize="12sp"/>
+            android:textSize="@dimen/battery_level_text_size"/>
     </LinearLayout>
 
     <TextView
diff --git a/packages/SystemUI/res/layout/status_bar_toggle_slider.xml b/packages/SystemUI/res/layout/status_bar_toggle_slider.xml
index 062e6cb..a5bf68e 100644
--- a/packages/SystemUI/res/layout/status_bar_toggle_slider.xml
+++ b/packages/SystemUI/res/layout/status_bar_toggle_slider.xml
@@ -45,6 +45,7 @@
         android:paddingBottom="16dp"
         android:thumb="@drawable/ic_brightness_thumb"
         android:splitTrack="false"
+        android:contentDescription="@string/accessibility_brightness"
         />
     <TextView
         android:id="@+id/label"
diff --git a/packages/SystemUI/res/values-h560dp-xhdpi/config.xml b/packages/SystemUI/res/values-h560dp-xhdpi/config.xml
new file mode 100644
index 0000000..cf2017f
--- /dev/null
+++ b/packages/SystemUI/res/values-h560dp-xhdpi/config.xml
@@ -0,0 +1,23 @@
+<?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
+  -->
+<resources>
+    <!-- The maximum count of notifications on Keyguard. The rest will be collapsed in an overflow
+     card. -->
+    <integer name="keyguard_max_notification_count">3</integer>
+</resources>
+
diff --git a/packages/SystemUI/res/values-h560dp-xhdpi/dimens.xml b/packages/SystemUI/res/values-h560dp-xhdpi/dimens.xml
new file mode 100644
index 0000000..f6dbc3d
--- /dev/null
+++ b/packages/SystemUI/res/values-h560dp-xhdpi/dimens.xml
@@ -0,0 +1,21 @@
+<?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
+  -->
+
+<resources>
+    <fraction name="keyguard_clock_y_fraction_max">32.5%</fraction>
+    <fraction name="keyguard_clock_y_fraction_min">24%</fraction>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-h560dp-xxhdpi/config.xml b/packages/SystemUI/res/values-h560dp-xxhdpi/config.xml
new file mode 100644
index 0000000..b2231a6
--- /dev/null
+++ b/packages/SystemUI/res/values-h560dp-xxhdpi/config.xml
@@ -0,0 +1,22 @@
+<?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
+  -->
+<resources>
+    <!-- The maximum count of notifications on Keyguard. The rest will be collapsed in an overflow
+     card. -->
+    <integer name="keyguard_max_notification_count">4</integer>
+</resources>
+
diff --git a/packages/SystemUI/res/values-h560dp-xxhdpi/dimens.xml b/packages/SystemUI/res/values-h560dp-xxhdpi/dimens.xml
new file mode 100644
index 0000000..905e9e3
--- /dev/null
+++ b/packages/SystemUI/res/values-h560dp-xxhdpi/dimens.xml
@@ -0,0 +1,21 @@
+<?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
+  -->
+
+<resources>
+    <fraction name="keyguard_clock_y_fraction_max">32.5%</fraction>
+    <fraction name="keyguard_clock_y_fraction_min">19.8%</fraction>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-land/config.xml b/packages/SystemUI/res/values-land/config.xml
index 2b1a4dc..d608e25 100644
--- a/packages/SystemUI/res/values-land/config.xml
+++ b/packages/SystemUI/res/values-land/config.xml
@@ -29,5 +29,7 @@
 
     <!-- The number of columns that the top level tiles span in the QuickSettings -->
     <integer name="quick_settings_user_time_settings_tile_span">2</integer>
-</resources>
 
+    <!-- We have only space for one notification on phone landscape layouts. -->
+    <integer name="keyguard_max_notification_count">1</integer>
+</resources>
diff --git a/packages/SystemUI/res/values-sw600dp-land/dimens.xml b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
index 5367fbc..2c22cef 100644
--- a/packages/SystemUI/res/values-sw600dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
@@ -27,4 +27,6 @@
 
     <dimen name="keyguard_clock_notifications_margin_min">36dp</dimen>
     <dimen name="keyguard_clock_notifications_margin_max">36dp</dimen>
+
+    <dimen name="keyguard_indication_margin_bottom">80dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 7cdc078..9901e44 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -79,4 +79,6 @@
     <!-- The width of the region on the left/right edge of the screen for performing the camera/
      phone hints. -->
     <dimen name="edge_tap_area_width">80dp</dimen>
+
+    <dimen name="keyguard_indication_margin_bottom">90dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-sw720dp-land/config.xml b/packages/SystemUI/res/values-sw720dp-land/config.xml
new file mode 100644
index 0000000..1b50288
--- /dev/null
+++ b/packages/SystemUI/res/values-sw720dp-land/config.xml
@@ -0,0 +1,20 @@
+<?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
+  -->
+<resources>
+    <integer name="keyguard_max_notification_count">4</integer>
+</resources>
+
diff --git a/packages/SystemUI/res/values-sw720dp-land/dimens.xml b/packages/SystemUI/res/values-sw720dp-land/dimens.xml
index 2532dd6..511d45f 100644
--- a/packages/SystemUI/res/values-sw720dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp-land/dimens.xml
@@ -19,5 +19,5 @@
          min value is used when no notifications are displaying, and the max value is when the
          highest possible number of notifications are showing. -->
     <fraction name="keyguard_clock_y_fraction_max">35%</fraction>
-    <fraction name="keyguard_clock_y_fraction_min">20%</fraction>
+    <fraction name="keyguard_clock_y_fraction_min">24%</fraction>
 </resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 26e5ce3..f628039 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -147,6 +147,8 @@
     <integer name="recents_max_task_stack_view_dim">96</integer>
     <!-- The number of tasks that RecentsTaskLoader should load. -->
     <integer name="recents_max_num_tasks_to_load">50</integer>
+    <!-- The delay to enforce between each alt-tab key press. -->
+    <integer name="recents_alt_tab_key_delay">200</integer>
     <!-- Transposes the recents layout in landscape. -->
     <bool name="recents_transpose_layout_with_orientation">true</bool>
 
@@ -155,7 +157,7 @@
 
     <!-- The maximum count of notifications on Keyguard. The rest will be collapsed in an overflow
      card. -->
-    <integer name="keyguard_max_notification_count">4</integer>
+    <integer name="keyguard_max_notification_count">3</integer>
 
     <!-- Defines the implementation of the velocity tracker to be used for the panel expansion. Can
          be 'platform' or 'noisy' (i.e. for noisy touch screens). -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 3db0a2b..5415d19 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -222,6 +222,9 @@
     <!-- The amount to offset when animating into an affiliate group. -->
     <dimen name="recents_task_view_affiliate_group_enter_offset">64dp</dimen>
 
+    <!-- The alpha to apply to a task thumbnail. -->
+    <item name="recents_task_view_thumbnail_alpha" format="float" type="dimen">0.9</item>
+
     <!-- The height of a task view bar. -->
     <dimen name="recents_task_bar_height">56dp</dimen>
 
@@ -320,7 +323,7 @@
     <dimen name="volume_panel_z">3dp</dimen>
 
     <!-- Distance between notifications and header when they are considered to be colliding. -->
-    <dimen name="header_notifications_collide_distance">24dp</dimen>
+    <dimen name="header_notifications_collide_distance">48dp</dimen>
 
     <!-- Distance the user needs to drag vertically such that a swipe is accepted to unlock the
          device. -->
@@ -422,4 +425,9 @@
     <!-- The width/height of the phone/camera/unlock icon on keyguard. -->
     <dimen name="keyguard_affordance_height">56dp</dimen>
     <dimen name="keyguard_affordance_width">56dp</dimen>
+
+    <dimen name="keyguard_indication_margin_bottom">65dp</dimen>
+
+    <!-- The text size for battery level -->
+    <dimen name="battery_level_text_size">12sp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 72886c6..c24fcae 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -390,6 +390,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 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] -->
     <string name="accessibility_desc_recent_apps">Recent screens.</string>
 
@@ -416,6 +418,9 @@
     <!-- Content description of zen mode time condition minus button (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_quick_settings_less_time">Less time</string>
 
+    <!-- Content description of the display brightness slider (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_brightness">Display brightness</string>
+
     <!-- Title of dialog shown when 2G-3G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
     <string name="data_usage_disabled_dialog_3g_title">2G-3G data is off</string>
     <!-- Title of dialog shown when 4G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
@@ -643,7 +648,7 @@
     <string name="speed_bump_explanation">Less urgent notifications below</string>
 
     <!-- Shows to explain the double tap interaction with notifications: After tapping a notification on Keyguard, this will explain users to tap again to launch a notification. [CHAR LIMIT=60] -->
-    <string name="notification_tap_again">Tap again to open</string>
+    <string name="notification_tap_again">Touch again to open</string>
 
     <!-- Shows when people have pressed the unlock icon to explain how to unlock. [CHAR LIMIT=60] -->
     <string name="keyguard_unlock">Swipe up to unlock</string>
@@ -673,6 +678,12 @@
 
     <!-- Related to user switcher --><skip/>
 
+    <!-- Accessibility label for the button that opens the user switcher. -->
+    <string name="accessibility_multi_user_switch_switcher">Switch user</string>
+
+    <!-- Accessibility label for the button that opens the quick contact of the user. -->
+    <string name="accessibility_multi_user_switch_quick_contact">Show profile</string>
+
     <!-- Label for the adding a new user in the user switcher [CHAR LIMIT=35] -->
     <string name="user_add_user">Add user</string>
 
@@ -685,8 +696,8 @@
     <!-- Label for adding a new guest in the user switcher [CHAR LIMIT=35] -->
     <string name="guest_new_guest">Add guest</string>
 
-    <!-- Label for exiting guest session in the user switcher [CHAR LIMIT=35] -->
-    <string name="guest_exit_guest">Exit guest</string>
+    <!-- Label for exiting and removing the  guest session in the user switcher [CHAR LIMIT=35] -->
+    <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>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 0d3a487..27e58a4 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -108,49 +108,6 @@
     <style name="TextAppearance.StatusBar.Expanded.UserSwitcher.UserName" />
 
     <style name="TextAppearance" />
-    <style name="TextAppearance.QuickSettings" />
-
-    <style name="TextAppearance.QuickSettings.TileView">
-        <item name="android:textSize">12dp</item>
-        <item name="android:textStyle">normal</item>
-        <item name="android:textColor">#CCCCCC</item>
-        <item name="android:textAllCaps">true</item>
-        <item name="android:paddingStart">6dp</item>
-        <item name="android:paddingEnd">6dp</item>
-    </style>
-
-    <style name="TextAppearance.QuickSettings.TileView.AllInOne" parent="@style/TextAppearance.QuickSettings.TileView">
-        <item name="android:lines">2</item>
-        <item name="android:gravity">top</item>
-        <item name="android:paddingBottom">2dp</item>
-        <item name="android:paddingTop">16dp</item>
-        <item name="android:drawablePadding">8dp</item>
-    </style>
-
-    <style name="TextAppearance.QuickSettings.Clock" parent="@style/TextAppearance.QuickSettings.TileView">
-        <item name="android:textSize">20dp</item>
-        <item name="android:textColor">@android:color/holo_blue_light</item>
-    </style>
-
-    <style name="TextAppearance.QuickSettings.Date" parent="@style/TextAppearance.QuickSettings.TileView">
-        <item name="android:textSize">14dp</item>
-    </style>
-
-    <style name="TextAppearance.QuickSettings.Alarm" parent="@style/TextAppearance.QuickSettings.TileView">
-        <item name="android:textSize">14dp</item>
-        <item name="android:textColor">#ff3a3b39</item>
-    </style>
-
-    <style name="TextAppearance.QuickSettings.CaCertWarning" parent="@style/TextAppearance.QuickSettings.TileView">
-        <item name="android:textAllCaps">false</item>
-    </style>
-
-    <style name="TextAppearance.QuickSettings.TileView.User" parent="@style/TextAppearance.QuickSettings.TileView">
-        <item name="android:background">#CC000000</item>
-        <item name="android:padding">4dp</item>
-        <item name="android:singleLine">true</item>
-        <item name="android:fadingEdge">horizontal</item>
-    </style>
 
     <style name="TextAppearance.QS">
         <item name="android:textStyle">normal</item>
@@ -211,7 +168,6 @@
     <style name="BaseBrightnessDialogContainer">
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">wrap_content</item>
-        <item name="android:layout_alignParentBottom">true</item>
     </style>
 
     <style name="BrightnessDialogContainer" parent="@style/BaseBrightnessDialogContainer" />
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index b280ab7..ee699d2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -208,6 +208,12 @@
             checkPermission();
             mKeyguardViewMediator.startKeyguardExitAnimation(startTime, fadeoutDuration);
         }
+
+        @Override
+        public void onActivityDrawn() {
+            checkPermission();
+            mKeyguardViewMediator.onActivityDrawn();
+        }
     };
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 117515b..be11220 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -133,6 +133,7 @@
     private static final int KEYGUARD_TIMEOUT = 13;
     private static final int DISMISS = 17;
     private static final int START_KEYGUARD_EXIT_ANIM = 18;
+    private static final int ON_ACTIVITY_DRAWN = 19;
 
     /**
      * The default amount of time we stay awake (used for all key input)
@@ -256,6 +257,7 @@
     private boolean mWaitingUntilKeyguardVisible = false;
     private LockPatternUtils mLockPatternUtils;
     private boolean mKeyguardDonePending = false;
+    private boolean mHideAnimationRun = false;
 
     private SoundPool mLockSounds;
     private int mLockSoundId;
@@ -287,6 +289,7 @@
             // ActivityManagerService) will not reconstruct the keyguard if it is already showing.
             synchronized (KeyguardViewMediator.this) {
                 mSwitchingUser = true;
+                mKeyguardDonePending = false;
                 resetStateLocked();
                 adjustStatusBarLocked();
                 // When we switch users we want to bring the new user to the biometric unlock even
@@ -431,12 +434,23 @@
         @Override
         public void keyguardDonePending() {
             mKeyguardDonePending = true;
+            mHideAnimationRun = true;
+            mStatusBarKeyguardViewManager.startPreHideAnimation(null /* finishRunnable */);
         }
 
         @Override
         public void keyguardGone() {
             mKeyguardDisplayManager.hide();
         }
+
+        @Override
+        public void readyForKeyguardDone() {
+            if (mKeyguardDonePending) {
+                // Somebody has called keyguardDonePending before, which means that we are
+                // authenticated
+                KeyguardViewMediator.this.keyguardDone(true /* authenticated */, true /* wakeUp */);
+            }
+        }
     };
 
     public void userActivity() {
@@ -545,6 +559,7 @@
             if (DEBUG) Log.d(TAG, "onScreenTurnedOff(" + why + ")");
 
             mKeyguardDonePending = false;
+            mHideAnimationRun = false;
 
             // Lock immediately based on setting if secure (user has a pin/pattern/password).
             // This also "locks" the device when not secure to provide easy access to the
@@ -1067,6 +1082,9 @@
                     StartKeyguardExitAnimParams params = (StartKeyguardExitAnimParams) msg.obj;
                     handleStartKeyguardExitAnimation(params.startTime, params.fadeoutDuration);
                     break;
+                case ON_ACTIVITY_DRAWN:
+                    handleOnActivityDrawn();
+                    break;
             }
         }
     };
@@ -1181,6 +1199,7 @@
             mHiding = false;
             mShowing = true;
             mKeyguardDonePending = false;
+            mHideAnimationRun = false;
             updateActivityLockScreenState();
             adjustStatusBarLocked();
             userActivity();
@@ -1193,6 +1212,22 @@
         mKeyguardDisplayManager.show();
     }
 
+    private final Runnable mKeyguardGoingAwayRunnable = new Runnable() {
+        @Override
+        public void run() {
+            try {
+                // Don't actually hide the Keyguard at the moment, wait for window
+                // manager until it tells us it's safe to do so with
+                // startKeyguardExitAnimation.
+                mWM.keyguardGoingAway(
+                        mStatusBarKeyguardViewManager.shouldDisableWindowAnimationsForUnlock(),
+                        mStatusBarKeyguardViewManager.isGoingToNotificationShade());
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error while calling WindowManager", e);
+            }
+        }
+    };
+
     /**
      * Handle message sent by {@link #hideLocked()}
      * @see #HIDE
@@ -1203,19 +1238,11 @@
 
             mHiding = true;
             if (mShowing && !mOccluded) {
-                mStatusBarKeyguardViewManager.startPreHideAnimation(new Runnable() {
-                    @Override
-                    public void run() {
-                        try {
-                            // Don't actually hide the Keyguard at the moment, wait for window
-                            // manager until it tells us it's safe to do so with
-                            // startKeyguardExitAnimation.
-                            mWM.keyguardGoingAway();
-                        } catch (RemoteException e) {
-                            Log.e(TAG, "Error while calling WindowManager", e);
-                        }
-                    }
-                });
+                if (!mHideAnimationRun) {
+                    mStatusBarKeyguardViewManager.startPreHideAnimation(mKeyguardGoingAwayRunnable);
+                } else {
+                    mKeyguardGoingAwayRunnable.run();
+                }
             } else {
 
                 // Don't try to rely on WindowManager - if Keyguard wasn't showing, window
@@ -1227,6 +1254,12 @@
         }
     }
 
+    private void handleOnActivityDrawn() {
+        if (mKeyguardDonePending) {
+            mStatusBarKeyguardViewManager.onActivityDrawn();
+        }
+    }
+
     private void handleStartKeyguardExitAnimation(long startTime, long fadeoutDuration) {
         synchronized (KeyguardViewMediator.this) {
 
@@ -1244,6 +1277,7 @@
             mStatusBarKeyguardViewManager.hide(startTime, fadeoutDuration);
             mShowing = false;
             mKeyguardDonePending = false;
+            mHideAnimationRun = false;
             updateActivityLockScreenState();
             adjustStatusBarLocked();
         }
@@ -1357,6 +1391,9 @@
         mHandler.sendMessage(msg);
     }
 
+    public void onActivityDrawn() {
+        mHandler.sendEmptyMessage(ON_ACTIVITY_DRAWN);
+    }
     public ViewMediatorCallback getViewMediatorCallback() {
         return mViewMediatorCallback;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java b/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
index f8b347c..803a014 100644
--- a/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
@@ -17,6 +17,7 @@
 package com.android.systemui.media;
 
 import android.content.Context;
+import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.media.MediaPlayer;
 import android.media.MediaPlayer.OnCompletionListener;
@@ -45,11 +46,11 @@
         Context context;
         Uri uri;
         boolean looping;
-        int stream;
+        AudioAttributes attributes;
         long requestTime;
 
         public String toString() {
-            return "{ code=" + code + " looping=" + looping + " stream=" + stream
+            return "{ code=" + code + " looping=" + looping + " attributes=" + attributes
                     + " uri=" + uri + " }";
         }
     }
@@ -79,7 +80,7 @@
                     (AudioManager) mCmd.context.getSystemService(Context.AUDIO_SERVICE);
                 try {
                     MediaPlayer player = new MediaPlayer();
-                    player.setAudioStreamType(mCmd.stream);
+                    player.setAudioAttributes(mCmd.attributes);
                     player.setDataSource(mCmd.context, mCmd.uri);
                     player.setLooping(mCmd.looping);
                     player.prepare();
@@ -90,10 +91,12 @@
                                 if (mAudioManagerWithAudioFocus == null) {
                                     if (mDebug) Log.d(mTag, "requesting AudioFocus");
                                     if (mCmd.looping) {
-                                        audioManager.requestAudioFocus(null, mCmd.stream,
+                                        audioManager.requestAudioFocus(null,
+                                                AudioAttributes.toLegacyStreamType(mCmd.attributes),
                                                 AudioManager.AUDIOFOCUS_GAIN);
                                     } else {
-                                        audioManager.requestAudioFocus(null, mCmd.stream,
+                                        audioManager.requestAudioFocus(null,
+                                                AudioAttributes.toLegacyStreamType(mCmd.attributes),
                                                 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
                                     }
                                     mAudioManagerWithAudioFocus = audioManager;
@@ -280,7 +283,9 @@
      *          (see {@link MediaPlayer#setLooping(boolean)})
      * @param stream the AudioStream to use.
      *          (see {@link MediaPlayer#setAudioStreamType(int)})
+     * @deprecated use {@link #play(Context, Uri, boolean, AudioAttributes)} instead.
      */
+    @Deprecated
     public void play(Context context, Uri uri, boolean looping, int stream) {
         Command cmd = new Command();
         cmd.requestTime = SystemClock.uptimeMillis();
@@ -288,7 +293,34 @@
         cmd.context = context;
         cmd.uri = uri;
         cmd.looping = looping;
-        cmd.stream = stream;
+        cmd.attributes = new AudioAttributes.Builder().setInternalLegacyStreamType(stream).build();
+        synchronized (mCmdQueue) {
+            enqueueLocked(cmd);
+            mState = PLAY;
+        }
+    }
+
+    /**
+     * Start playing the sound.  It will actually start playing at some
+     * point in the future.  There are no guarantees about latency here.
+     * Calling this before another audio file is done playing will stop
+     * that one and start the new one.
+     *
+     * @param context Your application's context.
+     * @param uri The URI to play.  (see {@link MediaPlayer#setDataSource(Context, Uri)})
+     * @param looping Whether the audio should loop forever.
+     *          (see {@link MediaPlayer#setLooping(boolean)})
+     * @param attributes the AudioAttributes to use.
+     *          (see {@link MediaPlayer#setAudioAttributes(AudioAttributes)})
+     */
+    public void play(Context context, Uri uri, boolean looping, AudioAttributes attributes) {
+        Command cmd = new Command();
+        cmd.requestTime = SystemClock.uptimeMillis();
+        cmd.code = PLAY;
+        cmd.context = context;
+        cmd.uri = uri;
+        cmd.looping = looping;
+        cmd.attributes = attributes;
         synchronized (mCmdQueue) {
             enqueueLocked(cmd);
             mState = PLAY;
diff --git a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
index 5b4bb2c..7eed7f2 100644
--- a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.media.AudioAttributes;
 import android.media.IAudioService;
 import android.media.IRingtonePlayer;
 import android.media.Ringtone;
@@ -71,11 +72,11 @@
         private final IBinder mToken;
         private final Ringtone mRingtone;
 
-        public Client(IBinder token, Uri uri, UserHandle user, int streamType) {
+        public Client(IBinder token, Uri uri, UserHandle user, AudioAttributes aa) {
             mToken = token;
 
             mRingtone = new Ringtone(getContextForUser(user), false);
-            mRingtone.setStreamType(streamType);
+            mRingtone.setAudioAttributes(aa);
             mRingtone.setUri(uri);
         }
 
@@ -91,7 +92,7 @@
 
     private IRingtonePlayer mCallback = new IRingtonePlayer.Stub() {
         @Override
-        public void play(IBinder token, Uri uri, int streamType) throws RemoteException {
+        public void play(IBinder token, Uri uri, AudioAttributes aa) throws RemoteException {
             if (LOGD) {
                 Log.d(TAG, "play(token=" + token + ", uri=" + uri + ", uid="
                         + Binder.getCallingUid() + ")");
@@ -101,7 +102,7 @@
                 client = mClients.get(token);
                 if (client == null) {
                     final UserHandle user = Binder.getCallingUserHandle();
-                    client = new Client(token, uri, user, streamType);
+                    client = new Client(token, uri, user, aa);
                     token.linkToDeath(client, 0);
                     mClients.put(token, client);
                 }
@@ -137,13 +138,13 @@
         }
 
         @Override
-        public void playAsync(Uri uri, UserHandle user, boolean looping, int streamType) {
+        public void playAsync(Uri uri, UserHandle user, boolean looping, AudioAttributes aa) {
             if (LOGD) Log.d(TAG, "playAsync(uri=" + uri + ", user=" + user + ")");
             if (Binder.getCallingUid() != Process.SYSTEM_UID) {
                 throw new SecurityException("Async playback only available from system UID.");
             }
 
-            mAsyncPlayer.play(getContextForUser(user), uri, looping, streamType);
+            mAsyncPlayer.play(getContextForUser(user), uri, looping, aa);
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerDialogWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerDialogWarnings.java
index 79fadbd..8420dc0c 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerDialogWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerDialogWarnings.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.power;
 
-import android.app.ActivityManagerNative;
 import android.app.AlertDialog;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -26,15 +25,14 @@
 import android.media.Ringtone;
 import android.media.RingtoneManager;
 import android.net.Uri;
-import android.os.RemoteException;
 import android.os.SystemClock;
-import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Slog;
 import android.view.ContextThemeWrapper;
 import android.view.WindowManager;
 
 import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.PhoneStatusBar;
 
 import java.io.PrintWriter;
 
@@ -43,6 +41,7 @@
     private static final boolean DEBUG = PowerUI.DEBUG;
 
     private final Context mContext;
+    private final PhoneStatusBar mPhoneStatusBar;
 
     private int mBatteryLevel;
     private int mBucket;
@@ -52,8 +51,9 @@
     private AlertDialog mInvalidChargerDialog;
     private AlertDialog mLowBatteryDialog;
 
-    public PowerDialogWarnings(Context context) {
+    public PowerDialogWarnings(Context context, PhoneStatusBar phoneStatusBar) {
         mContext = new ContextThemeWrapper(context, android.R.style.Theme_DeviceDefault_Light);
+        mPhoneStatusBar = phoneStatusBar;
     }
 
     @Override
@@ -121,12 +121,7 @@
                         new DialogInterface.OnClickListener() {
                     @Override
                     public void onClick(DialogInterface dialog, int which) {
-                        try {
-                            ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
-                        } catch (RemoteException e) {
-                            // we tried
-                        }
-                        mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+                        mPhoneStatusBar.startActivity(intent, true /* dismissShade */);
                         dismissLowBatteryWarning();
                     }
                 });
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index dd923e3..d455cec 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -38,6 +38,7 @@
 import android.view.View;
 
 import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.PhoneStatusBar;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 
 import java.io.PrintWriter;
@@ -93,10 +94,10 @@
     private boolean mInvalidCharger;
     private SystemUIDialog mSaverConfirmation;
 
-    public PowerNotificationWarnings(Context context) {
+    public PowerNotificationWarnings(Context context, PhoneStatusBar phoneStatusBar) {
         mContext = context;
         mNoMan = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
-        mFallbackDialogs = new PowerDialogWarnings(context);
+        mFallbackDialogs = new PowerDialogWarnings(context, phoneStatusBar);
         mReceiver.init();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index ccef8eb..d3c7dee 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -32,6 +32,7 @@
 import android.util.Slog;
 
 import com.android.systemui.SystemUI;
+import com.android.systemui.statusbar.phone.PhoneStatusBar;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -59,7 +60,7 @@
     public void start() {
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mScreenOffTime = mPowerManager.isScreenOn() ? -1 : SystemClock.elapsedRealtime();
-        mWarnings = new PowerNotificationWarnings(mContext);
+        mWarnings = new PowerNotificationWarnings(mContext, getComponent(PhoneStatusBar.class));
 
         ContentObserver obs = new ContentObserver(mHandler) {
             @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
index 1a555f1..1df3d20 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
@@ -89,11 +89,9 @@
     protected void handleStateChanged(QSTile.State state) {
         super.handleStateChanged(state);
         final SignalState s = (SignalState) state;
-        mSignal.setImageDrawable(null);  // force refresh
         mSignal.setImageResource(s.iconId);
         if (s.overlayIconId > 0) {
             mOverlay.setVisibility(VISIBLE);
-            mOverlay.setImageDrawable(null);  // force refresh
             mOverlay.setImageResource(s.overlayIconId);
         } else {
             mOverlay.setVisibility(GONE);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index efb7a2c..354eb55 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -345,8 +345,8 @@
      * Creates the activity options for an app->recents transition.  If this method sets the static
      * screenshot, then we will use that for the transition.
      */
-    ActivityOptions getThumbnailTransitionActivityOptions(ActivityManager.RunningTaskInfo topTask) {
-
+    ActivityOptions getThumbnailTransitionActivityOptions(ActivityManager.RunningTaskInfo topTask,
+            boolean isTopTaskHome) {
         if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
             // Recycle the last screenshot
             consumeLastScreenshot();
@@ -365,7 +365,7 @@
         Bitmap firstThumbnail = mSystemServicesProxy.getTaskThumbnail(topTask.id);
         if (firstThumbnail != null) {
             // Update the destination rect
-            Rect toTaskRect = getThumbnailTransitionRect(topTask.id);
+            Rect toTaskRect = getThumbnailTransitionRect(topTask.id, isTopTaskHome);
             if (toTaskRect.width() > 0 && toTaskRect.height() > 0) {
                 // Create the new thumbnail for the animation down
                 // XXX: We should find a way to optimize this so we don't need to create a new bitmap
@@ -389,7 +389,7 @@
     }
 
     /** Returns the transition rect for the given task id. */
-    Rect getThumbnailTransitionRect(int runningTaskId) {
+    Rect getThumbnailTransitionRect(int runningTaskId, boolean isTopTaskHome) {
         // Get the stack of tasks that we are animating into
         TaskStack stack = RecentsTaskLoader.getShallowTaskStack(mSystemServicesProxy, -1);
         if (stack.getTaskCount() == 0) {
@@ -401,7 +401,8 @@
         TaskStackViewLayoutAlgorithm algo = tsv.getStackAlgorithm();
         Rect taskStackBounds = new Rect(mTaskStackBounds);
         taskStackBounds.bottom -= mSystemInsets.bottom;
-        tsv.computeRects(mWindowRect.width(), mWindowRect.height(), taskStackBounds, mTriggeredFromAltTab);
+        tsv.computeRects(mWindowRect.width(), mWindowRect.height(), taskStackBounds,
+                mTriggeredFromAltTab, isTopTaskHome);
         tsv.getScroller().setStackScrollToInitialState();
 
         // Find the running task in the TaskStack
@@ -442,7 +443,7 @@
 
         if (useThumbnailTransition) {
             // Try starting with a thumbnail transition
-            ActivityOptions opts = getThumbnailTransitionActivityOptions(topTask);
+            ActivityOptions opts = getThumbnailTransitionActivityOptions(topTask, isTopTaskHome);
             if (opts != null) {
                 if (sLastScreenshot != null) {
                     startAlternateRecentsActivity(topTask, opts, EXTRA_FROM_APP_FULL_SCREENSHOT);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 3d4d6c4..3709c43 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -39,6 +39,8 @@
             public static final boolean EnableSearchLayout = true;
             // Enables the dynamic shadows behind each task
             public static final boolean EnableShadows = true;
+            // Enables the thumbnail alpha on the front-most task
+            public static final boolean EnableThumbnailAlphaOnFrontmost = false;
             // This disables the bitmap and icon caches
             public static final boolean DisableBackgroundCache = false;
             // Enables the simulated task affiliations
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 417049c..7fafe7a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -61,6 +61,7 @@
 
     RecentsConfiguration mConfig;
     boolean mVisible;
+    long mLastTabKeyEventTime;
 
     // Top level views
     RecentsView mRecentsView;
@@ -384,7 +385,7 @@
         // Private API calls to make the shadows look better
         try {
             Utilities.setShadowProperty("ambientShadowStrength", String.valueOf(35f));
-            Utilities.setShadowProperty("ambientRatio", String.valueOf(0.5f));
+            Utilities.setShadowProperty("ambientRatio", String.valueOf(1.5f));
         } catch (IllegalAccessException e) {
             e.printStackTrace();
         } catch (InvocationTargetException e) {
@@ -512,17 +513,33 @@
 
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
-        if (keyCode == KeyEvent.KEYCODE_TAB) {
-            // Focus the next task in the stack
-            final boolean backward = event.isShiftPressed();
-            mRecentsView.focusNextTask(!backward);
-            return true;
-        } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
-            mRecentsView.focusNextTask(true);
-            return true;
-        } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
-            mRecentsView.focusNextTask(false);
-            return true;
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_TAB: {
+                boolean hasRepKeyTimeElapsed = (System.currentTimeMillis() -
+                        mLastTabKeyEventTime) > mConfig.altTabKeyDelay;
+                if (event.getRepeatCount() <= 0 || hasRepKeyTimeElapsed) {
+                    // Focus the next task in the stack
+                    final boolean backward = event.isShiftPressed();
+                    mRecentsView.focusNextTask(!backward);
+                    mLastTabKeyEventTime = System.currentTimeMillis();
+                }
+                return true;
+            }
+            case KeyEvent.KEYCODE_DPAD_UP: {
+                mRecentsView.focusNextTask(true);
+                return true;
+            }
+            case KeyEvent.KEYCODE_DPAD_DOWN: {
+                mRecentsView.focusNextTask(false);
+                return true;
+            }
+            case KeyEvent.KEYCODE_DEL:
+            case KeyEvent.KEYCODE_FORWARD_DEL: {
+                mRecentsView.dismissFocusedTask();
+                return true;
+            }
+            default:
+                break;
         }
         // Pass through the debug trigger
         mDebugTrigger.onKeyEvent(keyCode);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 65e7076..b7f6451 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -81,6 +81,7 @@
     public int taskViewRoundedCornerRadiusPx;
     public int taskViewHighlightPx;
     public int taskViewAffiliateGroupEnterOffsetPx;
+    public float taskViewThumbnailAlpha;
 
     /** Task bar colors */
     public int taskBarViewDefaultBackgroundColor;
@@ -112,6 +113,9 @@
     public boolean launchedFromHome;
     public int launchedToTaskId;
 
+    /** Misc **/
+    public int altTabKeyDelay;
+
     /** Dev options and global settings */
     public boolean lockToAppEnabled;
     public boolean developerOptionsEnabled;
@@ -214,6 +218,9 @@
         taskViewTranslationZMaxPx = res.getDimensionPixelSize(R.dimen.recents_task_view_z_max);
         taskViewAffiliateGroupEnterOffsetPx =
                 res.getDimensionPixelSize(R.dimen.recents_task_view_affiliate_group_enter_offset);
+        TypedValue thumbnailAlphaValue = new TypedValue();
+        res.getValue(R.dimen.recents_task_view_thumbnail_alpha, thumbnailAlphaValue, true);
+        taskViewThumbnailAlpha = thumbnailAlphaValue.getFloat();
 
         // Task bar colors
         taskBarViewDefaultBackgroundColor =
@@ -250,6 +257,9 @@
         // Nav bar scrim
         navBarScrimEnterDuration =
                 res.getInteger(R.integer.recents_nav_bar_scrim_enter_duration);
+
+        // Misc
+        altTabKeyDelay = res.getInteger(R.integer.recents_alt_tab_key_delay);
     }
 
     /** Updates the system insets */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java b/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java
index 4c0ff48..c87a901 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.recents.misc;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.content.Context;
 
 import java.util.ArrayList;
@@ -98,10 +100,19 @@
         }
     }
 
-    /** Convenience method to decrement this trigger as a runnable */
+    /** Convenience method to decrement this trigger as a runnable. */
     public Runnable decrementAsRunnable() {
         return mDecrementRunnable;
     }
+    /** Convenience method to decrement this trigger as a animator listener. */
+    public Animator.AnimatorListener decrementOnAnimationEnd() {
+        return new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                decrement();
+            }
+        };
+    }
 
     /** Returns the current ref count */
     public int getCount() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
index bd5df28..4c6b389 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
@@ -89,6 +89,17 @@
         return Math.abs((fgL + 0.05f) / (bgL + 0.05f));
     }
 
+    /** Returns the base color overlaid with another overlay color with a specified alpha. */
+    public static int getColorWithOverlay(int baseColor, int overlayColor, float overlayAlpha) {
+        return Color.rgb(
+            (int) (overlayAlpha * Color.red(baseColor) +
+                    (1f - overlayAlpha) * Color.red(overlayColor)),
+            (int) (overlayAlpha * Color.green(baseColor) +
+                    (1f - overlayAlpha) * Color.green(overlayColor)),
+            (int) (overlayAlpha * Color.blue(baseColor) +
+                    (1f - overlayAlpha) * Color.blue(overlayColor)));
+    }
+
     /** Sets some private shadow properties. */
     public static void setShadowProperty(String property, String value)
             throws IllegalAccessException, InvocationTargetException {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index 0269141..98bf151 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -20,6 +20,7 @@
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.misc.NamedCounter;
+import com.android.systemui.recents.misc.Utilities;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -433,10 +434,8 @@
                 float alpha = 1f;
                 for (int j = 0; j < taskCount; j++) {
                     Task t = tasksMap.get(group.mTaskKeys.get(j));
-                    t.colorPrimary = Color.rgb(
-                            (int) (alpha * Color.red(affiliationColor) + (1f - alpha) * 0xFF),
-                            (int) (alpha * Color.green(affiliationColor) + (1f - alpha) * 0xFF),
-                            (int) (alpha * Color.blue(affiliationColor) + (1f - alpha) * 0xFF));
+                    t.colorPrimary = Utilities.getColorWithOverlay(affiliationColor, Color.WHITE,
+                            alpha);
                     alpha -= alphaStep;
                 }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 34e8860..07a7e74 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -316,12 +316,11 @@
     /** Notifies each task view of the user interaction. */
     public void onUserInteraction() {
         // Get the first stack view
-        TaskStackView stackView = null;
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             View child = getChildAt(i);
             if (child != mSearchBar) {
-                stackView = (TaskStackView) child;
+                TaskStackView stackView = (TaskStackView) child;
                 stackView.onUserInteraction();
             }
         }
@@ -330,18 +329,28 @@
     /** Focuses the next task in the first stack view */
     public void focusNextTask(boolean forward) {
         // Get the first stack view
-        TaskStackView stackView = null;
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             View child = getChildAt(i);
             if (child != mSearchBar) {
-                stackView = (TaskStackView) child;
+                TaskStackView stackView = (TaskStackView) child;
+                stackView.focusNextTask(forward);
                 break;
             }
         }
+    }
 
-        if (stackView != null) {
-            stackView.focusNextTask(forward);
+    /** Dismisses the focused task. */
+    public void dismissFocusedTask() {
+        // Get the first stack view
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            if (child != mSearchBar) {
+                TaskStackView stackView = (TaskStackView) child;
+                stackView.dismissFocusedTask();
+                break;
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 46996bb..aee558f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -73,6 +73,7 @@
     boolean mStackViewsDirty = true;
     boolean mAwaitingFirstLayout = true;
     boolean mStartEnterAnimationRequestedAfterLayout;
+    boolean mStartEnterAnimationCompleted;
     ViewAnimation.TaskViewEnterContext mStartEnterAnimationContext;
     int[] mTmpVisibleRange = new int[2];
     TaskViewTransform mTmpTransform = new TaskViewTransform();
@@ -349,9 +350,10 @@
     }
 
     /** Updates the min and max virtual scroll bounds */
-    void updateMinMaxScroll(boolean boundScrollToNewMinMax, boolean launchedWithAltTab) {
+    void updateMinMaxScroll(boolean boundScrollToNewMinMax, boolean launchedWithAltTab,
+            boolean launchedFromHome) {
         // Compute the min and max scroll values
-        mLayoutAlgorithm.computeMinMaxScroll(mStack.getTasks(), launchedWithAltTab);
+        mLayoutAlgorithm.computeMinMaxScroll(mStack.getTasks(), launchedWithAltTab, launchedFromHome);
 
         // Debug logging
         if (boundScrollToNewMinMax) {
@@ -366,6 +368,9 @@
 
     /** Focuses the task at the specified index in the stack */
     void focusTask(int taskIndex, boolean scrollToNewPosition) {
+        // Return early if the task is already focused
+        if (taskIndex == mFocusedTaskIndex) return;
+
         if (0 <= taskIndex && taskIndex < mStack.getTaskCount()) {
             mFocusedTaskIndex = taskIndex;
 
@@ -390,7 +395,7 @@
 
             // Scroll the view into position (just center it in the curve)
             if (scrollToNewPosition) {
-                float newScroll = mLayoutAlgorithm.getStackScrollForTaskIndex(t) - 0.5f;
+                float newScroll = mLayoutAlgorithm.getStackScrollForTask(t) - 0.5f;
                 newScroll = mStackScroller.getBoundedStackScroll(newScroll);
                 mStackScroller.animateScroll(mStackScroller.getStackScroll(), newScroll, postScrollRunnable);
             } else {
@@ -406,14 +411,24 @@
     void focusNextTask(boolean forward) {
         // Find the next index to focus
         int numTasks = mStack.getTaskCount();
-        if (mFocusedTaskIndex < 0) {
-            mFocusedTaskIndex = numTasks - 1;
-        }
+        if (numTasks == 0) return;
+
+        int nextFocusIndex = numTasks - 1;
         if (0 <= mFocusedTaskIndex && mFocusedTaskIndex < numTasks) {
-            mFocusedTaskIndex = Math.max(0, Math.min(numTasks - 1,
+            nextFocusIndex = Math.max(0, Math.min(numTasks - 1,
                     mFocusedTaskIndex + (forward ? -1 : 1)));
         }
-        focusTask(mFocusedTaskIndex, true);
+        focusTask(nextFocusIndex, true);
+    }
+
+    /** Dismisses the focused task. */
+    public void dismissFocusedTask() {
+        // Return early if there is no focused task index
+        if (mFocusedTaskIndex < 0) return;
+
+        Task t = mStack.getTasks().get(mFocusedTaskIndex);
+        TaskView tv = getChildViewForTask(t);
+        tv.dismissTask();
     }
 
     @Override
@@ -436,12 +451,12 @@
 
     /** Computes the stack and task rects */
     public void computeRects(int windowWidth, int windowHeight, Rect taskStackBounds,
-                             boolean launchedWithAltTab) {
+            boolean launchedWithAltTab, boolean launchedFromHome) {
         // Compute the rects in the stack algorithm
         mLayoutAlgorithm.computeRects(windowWidth, windowHeight, taskStackBounds);
 
         // Update the scroll bounds
-        updateMinMaxScroll(false, launchedWithAltTab);
+        updateMinMaxScroll(false, launchedWithAltTab, launchedFromHome);
     }
 
     /**
@@ -456,7 +471,8 @@
         // Compute our stack/task rects
         Rect taskStackBounds = new Rect(mTaskStackBounds);
         taskStackBounds.bottom -= mConfig.systemInsets.bottom;
-        computeRects(width, height, taskStackBounds, mConfig.launchedWithAltTab);
+        computeRects(width, height, taskStackBounds, mConfig.launchedWithAltTab,
+                mConfig.launchedFromHome);
 
         // If this is the first layout, then scroll to the front of the stack and synchronize the
         // stack views immediately to load all the views
@@ -546,7 +562,11 @@
 
         // When Alt-Tabbing, we scroll to and focus the previous task
         if (mConfig.launchedWithAltTab) {
-            focusTask(Math.max(0, mStack.getTaskCount() - 2), false);
+            if (mConfig.launchedFromHome) {
+                focusTask(Math.max(0, mStack.getTaskCount() - 1), false);
+            } else {
+                focusTask(Math.max(0, mStack.getTaskCount() - 2), false);
+            }
         }
     }
 
@@ -590,6 +610,7 @@
             ctx.postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
                 @Override
                 public void run() {
+                    mStartEnterAnimationCompleted = true;
                     // Start dozing
                     mUIDozeTrigger.startDozing();
                 }
@@ -660,8 +681,28 @@
         // Notify the callback that we've removed the task and it can clean up after it
         mCb.onTaskViewDismissed(removedTask);
 
+        // Get the stack scroll of the task to anchor to (since we are removing something, the front
+        // most task will be our anchor task)
+        Task anchorTask = null;
+        float prevAnchorTaskScroll = 0;
+        boolean pullStackForward = stack.getTaskCount() > 0;
+        if (pullStackForward) {
+            anchorTask = mStack.getFrontMostTask();
+            prevAnchorTaskScroll = mLayoutAlgorithm.getStackScrollForTask(anchorTask);
+        }
+
         // Update the min/max scroll and animate other task views into their new positions
-        updateMinMaxScroll(true, mConfig.launchedWithAltTab);
+        updateMinMaxScroll(true, mConfig.launchedWithAltTab, mConfig.launchedFromHome);
+
+        // Offset the stack by as much as the anchor task would otherwise move back
+        if (pullStackForward) {
+            float anchorTaskScroll = mLayoutAlgorithm.getStackScrollForTask(anchorTask);
+            mStackScroller.setStackScroll(mStackScroller.getStackScroll() + (anchorTaskScroll
+                    - prevAnchorTaskScroll));
+            mStackScroller.boundScroll();
+        }
+
+        // Animate all the tasks into place
         requestSynchronizeStackViewsWithModel(200);
 
         // Update the new front most task
@@ -795,6 +836,11 @@
             tv.setNoUserInteractionState();
         }
 
+        // If we've finished the start animation, then ensure we always enable the focus animations
+        if (mStartEnterAnimationCompleted) {
+            tv.enableFocusAnimations();
+        }
+
         // Find the index where this task should be placed in the stack
         int insertIndex = -1;
         int taskIndex = mStack.indexOfTask(task);
@@ -859,11 +905,23 @@
     @Override
     public void onTaskViewDismissed(TaskView tv) {
         Task task = tv.getTask();
+        int taskIndex = mStack.indexOfTask(task);
+        boolean taskWasFocused = tv.isFocusedTask();
         // Announce for accessibility
         tv.announceForAccessibility(getContext().getString(R.string.accessibility_recents_item_dismissed,
                 tv.getTask().activityLabel));
         // Remove the task from the view
         mStack.removeTask(task);
+        // If the dismissed task was focused, then we should focus the next task in front
+        if (taskWasFocused) {
+            ArrayList<Task> tasks = mStack.getTasks();
+            int nextTaskIndex = Math.min(tasks.size() - 1, taskIndex);
+            if (nextTaskIndex >= 0) {
+                Task nextTask = tasks.get(nextTaskIndex);
+                TaskView nextTv = getChildViewForTask(nextTask);
+                nextTv.setFocusedTask();
+            }
+        }
     }
 
     @Override
@@ -876,6 +934,13 @@
         requestSynchronizeStackViewsWithModel();
     }
 
+    @Override
+    public void onTaskViewFocusChanged(TaskView tv, boolean focused) {
+        if (focused) {
+            mFocusedTaskIndex = mStack.indexOfTask(tv.getTask());
+        }
+    }
+
     /**** TaskStackViewScroller.TaskStackViewScrollerCallbacks ****/
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
index 6c8de72..667faa7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
@@ -91,7 +91,8 @@
 
     /** Computes the minimum and maximum scroll progress values.  This method may be called before
      * the RecentsConfiguration is set, so we need to pass in the alt-tab state. */
-    void computeMinMaxScroll(ArrayList<Task> tasks, boolean launchedWithAltTab) {
+    void computeMinMaxScroll(ArrayList<Task> tasks, boolean launchedWithAltTab,
+            boolean launchedFromHome) {
         // Clear the progress map
         mTaskProgressMap.clear();
 
@@ -101,10 +102,16 @@
             return;
         }
 
+        // Note that we should account for the scale difference of the offsets at the screen bottom
         int taskHeight = mTaskRect.height();
         float pAtBottomOfStackRect = screenYToCurveProgress(mStackVisibleRect.bottom);
-        float pWithinAffiliateOffset = pAtBottomOfStackRect -
-                screenYToCurveProgress(mStackVisibleRect.bottom - mWithinAffiliationOffset);
+        float pWithinAffiliateTop = screenYToCurveProgress(mStackVisibleRect.bottom -
+                mWithinAffiliationOffset);
+        float scale = curveProgressToScale(pWithinAffiliateTop);
+        int scaleYOffset = (int) (((1f - scale) * taskHeight) / 2);
+        pWithinAffiliateTop = screenYToCurveProgress(mStackVisibleRect.bottom -
+                mWithinAffiliationOffset + scaleYOffset);
+        float pWithinAffiliateOffset = pAtBottomOfStackRect - pWithinAffiliateTop;
         float pBetweenAffiliateOffset = pAtBottomOfStackRect -
                 screenYToCurveProgress(mStackVisibleRect.bottom - mBetweenAffiliationOffset);
         float pTaskHeightOffset = pAtBottomOfStackRect -
@@ -133,8 +140,13 @@
         mMaxScrollP = pAtFrontMostCardTop - ((1f - pTaskHeightOffset - pNavBarOffset));
         mMinScrollP = tasks.size() == 1 ? Math.max(mMaxScrollP, 0f) : 0f;
         if (launchedWithAltTab) {
-            // Center the second most task, since that will be focused first
-            mInitialScrollP = pAtSecondFrontMostCardTop - 0.5f;
+            if (launchedFromHome) {
+                // Center the top most task, since that will be focused first
+                mInitialScrollP = pAtSecondFrontMostCardTop - 0.5f;
+            } else {
+                // Center the second top most task, since that will be focused first
+                mInitialScrollP = pAtSecondFrontMostCardTop - 0.5f;
+            }
         } else {
             mInitialScrollP = pAtFrontMostCardTop - 0.825f;
         }
@@ -190,7 +202,7 @@
     /**
      * Returns the scroll to such task top = 1f;
      */
-    float getStackScrollForTaskIndex(Task t) {
+    float getStackScrollForTask(Task t) {
         return mTaskProgressMap.get(t.key);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
index 0a12dab..2c0dc44 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
@@ -133,7 +133,7 @@
         stopBoundScrollAnimation();
 
         mScrollAnimator = ObjectAnimator.ofFloat(this, "stackScroll", curScroll, newScroll);
-        mScrollAnimator.setDuration(250);
+        mScrollAnimator.setDuration(200);
         // We would have to project the difference into the screen coords, and then use that as the
         // duration
 //        mScrollAnimator.setDuration(Utilities.calculateTranslationAnimationDuration(newScroll -
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 3b9bcc4..5914b39 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -17,7 +17,6 @@
 package com.android.systemui.recents.views;
 
 import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.content.Context;
@@ -48,12 +47,14 @@
         public void onTaskViewDismissed(TaskView tv);
         public void onTaskViewClipStateChanged(TaskView tv);
         public void onTaskViewFullScreenTransitionCompleted();
+        public void onTaskViewFocusChanged(TaskView tv, boolean focused);
     }
 
     RecentsConfiguration mConfig;
 
     float mTaskProgress;
     ObjectAnimator mTaskProgressAnimator;
+    ObjectAnimator mDimAnimator;
     float mMaxDimScale;
     int mDim;
     AccelerateInterpolator mDimInterpolator = new AccelerateInterpolator(1.25f);
@@ -62,13 +63,14 @@
     Task mTask;
     boolean mTaskDataLoaded;
     boolean mIsFocused;
+    boolean mFocusAnimationsEnabled;
     boolean mIsFullScreenView;
     boolean mClipViewInStack;
     AnimateableViewBounds mViewBounds;
     Paint mLayerPaint = new Paint();
 
     TaskViewThumbnail mThumbnailView;
-    TaskViewHeader mBarView;
+    TaskViewHeader mHeaderView;
     TaskViewFooter mFooterView;
     View mActionButtonView;
     TaskViewCallbacks mCb;
@@ -124,7 +126,7 @@
     @Override
     protected void onFinishInflate() {
         // Bind the views
-        mBarView = (TaskViewHeader) findViewById(R.id.task_view_bar);
+        mHeaderView = (TaskViewHeader) findViewById(R.id.task_view_bar);
         mThumbnailView = (TaskViewThumbnail) findViewById(R.id.task_view_thumbnail);
         mActionButtonView = findViewById(R.id.lock_to_app_fab);
         if (mFooterView != null) {
@@ -138,7 +140,7 @@
         int height = MeasureSpec.getSize(heightMeasureSpec);
 
         // Measure the bar view, thumbnail, and footer
-        mBarView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+        mHeaderView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
                 MeasureSpec.makeMeasureSpec(mConfig.taskBarHeight, MeasureSpec.EXACTLY));
         if (mFooterView != null) {
             mFooterView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
@@ -218,11 +220,12 @@
 
     /** Prepares this task view for the enter-recents animations.  This is called earlier in the
      * first layout because the actual animation into recents may take a long time. */
-    public void prepareEnterRecentsAnimation(boolean isTaskViewLaunchTargetTask,
+    void prepareEnterRecentsAnimation(boolean isTaskViewLaunchTargetTask,
                                              boolean occludesLaunchTarget, int offscreenY) {
+        int initialDim = getDim();
         if (mConfig.launchedFromAppWithScreenshot) {
             if (isTaskViewLaunchTargetTask) {
-                mBarView.prepareEnterRecentsAnimation();
+                mHeaderView.prepareEnterRecentsAnimation();
                 // Hide the footer during the transition in, and animate it out afterwards?
                 if (mFooterView != null) {
                     mFooterView.animateFooterVisibility(false, 0);
@@ -234,11 +237,11 @@
         } else if (mConfig.launchedFromAppWithThumbnail) {
             if (isTaskViewLaunchTargetTask) {
                 // Hide the front most task bar view so we can animate it in
-                mBarView.prepareEnterRecentsAnimation();
+                mHeaderView.prepareEnterRecentsAnimation();
                 // Hide the action button if it exists
                 mActionButtonView.setAlpha(0f);
                 // Set the dim to 0 so we can animate it in
-                setDim(0);
+                initialDim = 0;
             } else if (occludesLaunchTarget) {
                 // Move the task view off screen (below) so we can animate it in
                 setTranslationY(offscreenY);
@@ -253,11 +256,16 @@
             setScaleX(1f);
             setScaleY(1f);
         }
+        // Apply the current dim
+        setDim(initialDim);
+        // Prepare the thumbnail view alpha
+        mThumbnailView.prepareEnterRecentsAnimation(isTaskViewLaunchTargetTask);
     }
 
     /** Animates this task view as it enters recents */
-    public void startEnterRecentsAnimation(final ViewAnimation.TaskViewEnterContext ctx) {
+    void startEnterRecentsAnimation(final ViewAnimation.TaskViewEnterContext ctx) {
         final TaskViewTransform transform = ctx.currentTaskTransform;
+        int startDelay = 0;
 
         if (mConfig.launchedFromAppWithScreenshot) {
             if (mTask.isLaunchTarget) {
@@ -269,6 +277,7 @@
                 float scaledWindowInsetTop = (int) (taskScale * windowInsetTop);
                 float scaledTranslationY = taskRect.top + transform.translationY -
                         (scaledWindowInsetTop + scaledYOffset);
+                startDelay = mConfig.taskViewEnterFromHomeDelay;
 
                 // Animate the top clip
                 mViewBounds.animateClipTop(windowInsetTop, duration,
@@ -276,7 +285,7 @@
                     @Override
                     public void onAnimationUpdate(ValueAnimator animation) {
                         int y = (Integer) animation.getAnimatedValue();
-                        mBarView.setTranslationY(y);
+                        mHeaderView.setTranslationY(y);
                     }
                 });
                 // Animate the bottom or right clip
@@ -287,7 +296,7 @@
                     mViewBounds.animateClipBottom(getMeasuredHeight() - (windowInsetTop + size), duration);
                 }
                 // Animate the task bar of the first task view
-                mBarView.startEnterRecentsAnimation(0, null);
+                mHeaderView.startEnterRecentsAnimation(0, null);
                 animate()
                         .scaleX(taskScale)
                         .scaleY(taskScale)
@@ -304,9 +313,9 @@
                                 mViewBounds.setClipBottom(0);
                                 mViewBounds.setClipRight(0);
                                 // Reset the bar translation
-                                mBarView.setTranslationY(0);
+                                mHeaderView.setTranslationY(0);
                                 // Enable the thumbnail clip
-                                mThumbnailView.enableTaskBarClip(mBarView);
+                                mThumbnailView.enableTaskBarClip(mHeaderView);
                                 // Animate the footer into view (if it is the front most task)
                                 animateFooterVisibility(true, mConfig.taskBarEnterAnimDuration);
 
@@ -324,7 +333,7 @@
                         .start();
             } else {
                 // Otherwise, just enable the thumbnail clip
-                mThumbnailView.enableTaskBarClip(mBarView);
+                mThumbnailView.enableTaskBarClip(mHeaderView);
 
                 // Animate the footer into view
                 animateFooterVisibility(true, 0);
@@ -334,22 +343,26 @@
         } else if (mConfig.launchedFromAppWithThumbnail) {
             if (mTask.isLaunchTarget) {
                 // Animate the task bar of the first task view
-                mBarView.startEnterRecentsAnimation(mConfig.taskBarEnterAnimDelay,
-                        mThumbnailView.enableTaskBarClipAsRunnable(mBarView));
-
-                // Animate the dim into view as well
-                ObjectAnimator anim = ObjectAnimator.ofInt(this, "dim", getDimFromTaskProgress());
-                anim.setStartDelay(mConfig.taskBarEnterAnimDelay);
-                anim.setDuration(mConfig.taskBarEnterAnimDuration);
-                anim.setInterpolator(mConfig.fastOutLinearInInterpolator);
-                anim.addListener(new AnimatorListenerAdapter() {
-                    @Override
-                    public void onAnimationEnd(Animator animation) {
-                        // Decrement the post animation trigger
-                        ctx.postAnimationTrigger.decrement();
-                    }
-                });
-                anim.start();
+                mHeaderView.startEnterRecentsAnimation(mConfig.taskBarEnterAnimDelay,
+                        mThumbnailView.enableTaskBarClipAsRunnable(mHeaderView));
+                // Animate the dim/overlay
+                if (Constants.DebugFlags.App.EnableThumbnailAlphaOnFrontmost) {
+                    // Animate the thumbnail alpha before the dim animation (to prevent updating the
+                    // hardware layer)
+                    mThumbnailView.startEnterRecentsAnimation(mConfig.taskBarEnterAnimDelay,
+                            new Runnable() {
+                                @Override
+                                public void run() {
+                                    animateDimToProgress(0, mConfig.taskBarEnterAnimDuration,
+                                            ctx.postAnimationTrigger.decrementOnAnimationEnd());
+                                }
+                            });
+                } else {
+                    // Immediately start the dim animation
+                    animateDimToProgress(mConfig.taskBarEnterAnimDelay,
+                            mConfig.taskBarEnterAnimDuration,
+                            ctx.postAnimationTrigger.decrementOnAnimationEnd());
+                }
                 ctx.postAnimationTrigger.increment();
 
                 // Animate the footer into view
@@ -364,7 +377,7 @@
                         .start();
             } else {
                 // Enable the task bar clip
-                mThumbnailView.enableTaskBarClip(mBarView);
+                mThumbnailView.enableTaskBarClip(mHeaderView);
                 // Animate the task up if it was occluding the launch target
                 if (ctx.currentTaskOccludesLaunchTarget) {
                     setTranslationY(transform.translationY + mConfig.taskViewAffiliateGroupEnterOffsetPx);
@@ -378,7 +391,7 @@
                             .withEndAction(new Runnable() {
                                 @Override
                                 public void run() {
-                                    mThumbnailView.enableTaskBarClip(mBarView);
+                                    mThumbnailView.enableTaskBarClip(mHeaderView);
                                     // Decrement the post animation trigger
                                     ctx.postAnimationTrigger.decrement();
                                 }
@@ -387,6 +400,7 @@
                     ctx.postAnimationTrigger.increment();
                 }
             }
+            startDelay = mConfig.taskBarEnterAnimDelay;
 
         } else if (mConfig.launchedFromHome) {
             // Animate the tasks up
@@ -407,7 +421,7 @@
                     .withEndAction(new Runnable() {
                         @Override
                         public void run() {
-                            mThumbnailView.enableTaskBarClip(mBarView);
+                            mThumbnailView.enableTaskBarClip(mHeaderView);
                             // Decrement the post animation trigger
                             ctx.postAnimationTrigger.decrement();
                         }
@@ -417,18 +431,28 @@
 
             // Animate the footer into view
             animateFooterVisibility(true, mConfig.taskViewEnterFromHomeDuration);
+            startDelay = delay;
 
         } else {
             // Otherwise, just enable the thumbnail clip
-            mThumbnailView.enableTaskBarClip(mBarView);
+            mThumbnailView.enableTaskBarClip(mHeaderView);
 
             // Animate the footer into view
             animateFooterVisibility(true, 0);
         }
+
+        // Enable the focus animations from this point onwards so that they aren't affected by the
+        // window transitions
+        postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                enableFocusAnimations();
+            }
+        }, (startDelay / 2));
     }
 
     /** Animates this task view as it leaves recents by pressing home. */
-    public void startExitToHomeAnimation(ViewAnimation.TaskViewExitContext ctx) {
+    void startExitToHomeAnimation(ViewAnimation.TaskViewExitContext ctx) {
         animate()
                 .translationY(ctx.offscreenTranslationY)
                 .setStartDelay(0)
@@ -441,11 +465,13 @@
     }
 
     /** Animates this task view as it exits recents */
-    public void startLaunchTaskAnimation(final Runnable r, boolean isLaunchingTask,
-                                         boolean occludesLaunchTarget) {
+    void startLaunchTaskAnimation(final Runnable r, boolean isLaunchingTask,
+            boolean occludesLaunchTarget) {
         if (isLaunchingTask) {
-            // Disable the thumbnail clip and animate the bar out
-            mBarView.startLaunchTaskAnimation(mThumbnailView.disableTaskBarClipAsRunnable(), r);
+            // Disable the thumbnail clip and animate the bar out for the window animation out
+            mHeaderView.startLaunchTaskAnimation(mThumbnailView.disableTaskBarClipAsRunnable(), r);
+            // Animate the thumbnail alpha back into full opacity for the window animation out
+            mThumbnailView.startLaunchTaskAnimation();
 
             // Animate the dim
             if (mDim > 0) {
@@ -464,7 +490,7 @@
                     .start();
         } else {
             // Hide the dismiss button
-            mBarView.startLaunchTaskDismissAnimation();
+            mHeaderView.startLaunchTaskDismissAnimation();
             // If this is another view in the task grouping and is in front of the launch task,
             // animate it away first
             if (occludesLaunchTarget) {
@@ -480,7 +506,7 @@
     }
 
     /** Animates the deletion of this task view */
-    public void startDeleteTaskAnimation(final Runnable r) {
+    void startDeleteTaskAnimation(final Runnable r) {
         // Disabling clipping with the stack while the view is animating away
         setClipViewInStack(false);
 
@@ -508,19 +534,33 @@
     }
 
     /** Animates this task view if the user does not interact with the stack after a certain time. */
-    public void startNoUserInteractionAnimation() {
-        mBarView.startNoUserInteractionAnimation();
+    void startNoUserInteractionAnimation() {
+        mHeaderView.startNoUserInteractionAnimation();
     }
 
     /** Mark this task view that the user does has not interacted with the stack after a certain time. */
-    public void setNoUserInteractionState() {
-        mBarView.setNoUserInteractionState();
+    void setNoUserInteractionState() {
+        mHeaderView.setNoUserInteractionState();
+    }
+
+    /** Dismisses this task. */
+    void dismissTask() {
+        // Animate out the view and call the callback
+        final TaskView tv = this;
+        startDeleteTaskAnimation(new Runnable() {
+            @Override
+            public void run() {
+                mCb.onTaskViewDismissed(tv);
+            }
+        });
+        // Hide the footer
+        animateFooterVisibility(false, mConfig.taskViewRemoveAnimDuration);
     }
 
     /** Sets whether this task view is full screen or not. */
     void setIsFullScreen(boolean isFullscreen) {
         mIsFullScreenView = isFullscreen;
-        mBarView.setIsFullscreen(isFullscreen);
+        mHeaderView.setIsFullscreen(isFullscreen);
         if (isFullscreen) {
             // If we are full screen, then disable the bottom outline clip for the footer
             mViewBounds.setOutlineClipBottom(0);
@@ -583,10 +623,18 @@
     /** Returns the current dim. */
     public void setDim(int dim) {
         mDim = dim;
-        int inverse = 255 - mDim;
-        mDimColorFilter.setColor(Color.argb(0xFF, inverse, inverse, inverse));
-        mLayerPaint.setColorFilter(mDimColorFilter);
-        setLayerType(LAYER_TYPE_HARDWARE, mLayerPaint);
+        // 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 (mDimAnimator != null) {
+                mDimAnimator.removeAllListeners();
+                mDimAnimator.cancel();
+            }
+
+            int inverse = 255 - mDim;
+            mDimColorFilter.setColor(Color.argb(0xFF, inverse, inverse, inverse));
+            mLayerPaint.setColorFilter(mDimColorFilter);
+            setLayerType(LAYER_TYPE_HARDWARE, mLayerPaint);
+        }
     }
 
     /** Returns the current dim. */
@@ -594,6 +642,21 @@
         return mDim;
     }
 
+    /** Animates the dim to the task progress. */
+    void animateDimToProgress(int delay, int duration, Animator.AnimatorListener postAnimRunnable) {
+        // Animate the dim into view as well
+        int toDim = getDimFromTaskProgress();
+        if (toDim != getDim()) {
+            ObjectAnimator anim = ObjectAnimator.ofInt(TaskView.this, "dim", toDim);
+            anim.setStartDelay(delay);
+            anim.setDuration(duration);
+            if (postAnimRunnable != null) {
+                anim.addListener(postAnimRunnable);
+            }
+            anim.start();
+        }
+    }
+
     /** Compute the dim as a function of the scale of this view. */
     int getDimFromTaskProgress() {
         float dim = mMaxDimScale * mDimInterpolator.getInterpolation(1f - mTaskProgress);
@@ -614,6 +677,14 @@
      */
     public void setFocusedTask() {
         mIsFocused = true;
+        if (mFocusAnimationsEnabled) {
+            // Focus the header bar
+            mHeaderView.onTaskViewFocusChanged(true);
+        }
+        // Update the thumbnail alpha with the focus
+        mThumbnailView.onFocusChanged(true);
+        // Call the callback
+        mCb.onTaskViewFocusChanged(this, true);
         // Workaround, we don't always want it focusable in touch mode, but we want the first task
         // to be focused after the enter-recents animation, which can be triggered from either touch
         // or keyboard
@@ -631,6 +702,14 @@
         super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
         if (!gainFocus) {
             mIsFocused = false;
+            if (mFocusAnimationsEnabled) {
+                // Un-focus the header bar
+                mHeaderView.onTaskViewFocusChanged(false);
+            }
+            // Update the thumbnail alpha with the focus
+            mThumbnailView.onFocusChanged(false);
+            // Call the callback
+            mCb.onTaskViewFocusChanged(this, false);
             invalidate();
         }
     }
@@ -642,6 +721,16 @@
         return mIsFocused || isFocused();
     }
 
+    /** Enables all focus animations. */
+    void enableFocusAnimations() {
+        boolean wasFocusAnimationsEnabled = mFocusAnimationsEnabled;
+        mFocusAnimationsEnabled = true;
+        if (mIsFocused && !wasFocusAnimationsEnabled) {
+            // Re-notify the header if we were focused and animations were not previously enabled
+            mHeaderView.onTaskViewFocusChanged(true);
+        }
+    }
+
     /**** TaskCallbacks Implementation ****/
 
     /** Binds this task view to the task */
@@ -662,24 +751,24 @@
 
     @Override
     public void onTaskDataLoaded() {
-        if (mThumbnailView != null && mBarView != null) {
+        if (mThumbnailView != null && mHeaderView != null) {
             // Bind each of the views to the new task data
             if (mIsFullScreenView) {
                 mThumbnailView.bindToScreenshot(AlternateRecentsComponent.getLastScreenshot());
             } else {
                 mThumbnailView.rebindToTask(mTask);
             }
-            mBarView.rebindToTask(mTask);
+            mHeaderView.rebindToTask(mTask);
             // Rebind any listeners
-            mBarView.mApplicationIcon.setOnClickListener(this);
-            mBarView.mDismissButton.setOnClickListener(this);
+            mHeaderView.mApplicationIcon.setOnClickListener(this);
+            mHeaderView.mDismissButton.setOnClickListener(this);
             if (mFooterView != null) {
                 mFooterView.setOnClickListener(this);
             }
             mActionButtonView.setOnClickListener(this);
             if (Constants.DebugFlags.App.EnableDevAppInfoOnLongPress) {
                 if (mConfig.developerOptionsEnabled) {
-                    mBarView.mApplicationIcon.setOnLongClickListener(this);
+                    mHeaderView.mApplicationIcon.setOnLongClickListener(this);
                 }
             }
         }
@@ -688,20 +777,20 @@
 
     @Override
     public void onTaskDataUnloaded() {
-        if (mThumbnailView != null && mBarView != null) {
+        if (mThumbnailView != null && mHeaderView != null) {
             // Unbind each of the views from the task data and remove the task callback
             mTask.setCallbacks(null);
             mThumbnailView.unbindFromTask();
-            mBarView.unbindFromTask();
+            mHeaderView.unbindFromTask();
             // Unbind any listeners
-            mBarView.mApplicationIcon.setOnClickListener(null);
-            mBarView.mDismissButton.setOnClickListener(null);
+            mHeaderView.mApplicationIcon.setOnClickListener(null);
+            mHeaderView.mDismissButton.setOnClickListener(null);
             if (mFooterView != null) {
                 mFooterView.setOnClickListener(null);
             }
             mActionButtonView.setOnClickListener(null);
             if (Constants.DebugFlags.App.EnableDevAppInfoOnLongPress) {
-                mBarView.mApplicationIcon.setOnLongClickListener(null);
+                mHeaderView.mApplicationIcon.setOnLongClickListener(null);
             }
         }
         mTaskDataLoaded = false;
@@ -734,18 +823,10 @@
         postDelayed(new Runnable() {
             @Override
             public void run() {
-                if (Constants.DebugFlags.App.EnableTaskFiltering && v == mBarView.mApplicationIcon) {
+                if (Constants.DebugFlags.App.EnableTaskFiltering && v == mHeaderView.mApplicationIcon) {
                     mCb.onTaskViewAppIconClicked(tv);
-                } else if (v == mBarView.mDismissButton) {
-                    // Animate out the view and call the callback
-                    startDeleteTaskAnimation(new Runnable() {
-                        @Override
-                        public void run() {
-                            mCb.onTaskViewDismissed(tv);
-                        }
-                    });
-                    // Hide the footer
-                    tv.animateFooterVisibility(false, mConfig.taskViewRemoveAnimDuration);
+                } else if (v == mHeaderView.mDismissButton) {
+                    dismissTask();
                 } else {
                     mCb.onTaskViewClicked(tv, tv.getTask(),
                             (v == mFooterView || v == mActionButtonView));
@@ -758,7 +839,7 @@
 
     @Override
     public boolean onLongClick(View v) {
-        if (v == mBarView.mApplicationIcon) {
+        if (v == mHeaderView.mApplicationIcon) {
             mCb.onTaskViewAppInfoClicked(this);
             return true;
         }
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 03fc16e..4b09549 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -16,9 +16,16 @@
 
 package com.android.systemui.recents.views;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ArgbEvaluator;
+import android.animation.ValueAnimator;
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Outline;
 import android.graphics.Paint;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
@@ -28,12 +35,14 @@
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewOutlineProvider;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.TextView;
 import com.android.systemui.R;
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.misc.Utilities;
 import com.android.systemui.recents.model.Task;
 
 
@@ -46,10 +55,15 @@
     ImageView mApplicationIcon;
     TextView mActivityDescription;
 
+    RippleDrawable mBackground;
+    ColorDrawable mBackgroundColor;
     Drawable mLightDismissDrawable;
     Drawable mDarkDismissDrawable;
+    ValueAnimator mBackgroundColorAnimator;
 
     boolean mIsFullscreen;
+    boolean mCurrentPrimaryColorIsDark;
+    int mCurrentPrimaryColor;
 
     static Paint sHighlightPaint;
 
@@ -69,6 +83,13 @@
         super(context, attrs, defStyleAttr, defStyleRes);
         mConfig = RecentsConfiguration.getInstance();
         setWillNotDraw(false);
+        setClipToOutline(true);
+        setOutlineProvider(new ViewOutlineProvider() {
+            @Override
+            public void getOutline(View view, Outline outline) {
+                outline.setRect(0, 0, getMeasuredWidth(), getMeasuredHeight());
+            }
+        });
 
         // Load the dismiss resources
         Resources res = context.getResources();
@@ -107,6 +128,15 @@
                 mApplicationIcon.setBackground(null);
             }
         }
+
+        mBackgroundColor = new ColorDrawable(0);
+        // Copy the ripple drawable since we are going to be manipulating it
+        mBackground = (RippleDrawable)
+                getResources().getDrawable(R.drawable.recents_task_view_header_bg);
+        mBackground = (RippleDrawable) mBackground.mutate().getConstantState().newDrawable();
+        mBackground.setColor(ColorStateList.valueOf(0));
+        mBackground.setDrawableByLayerId(mBackground.getId(0), mBackgroundColor);
+        setBackground(mBackground);
     }
 
     @Override
@@ -130,6 +160,12 @@
         return false;
     }
 
+    /** Returns the secondary color for a primary color. */
+    int getSecondaryColor(int primaryColor, boolean useLightOverlayColor) {
+        int overlayColor = useLightOverlayColor ? Color.WHITE : Color.BLACK;
+        return Utilities.getColorWithOverlay(primaryColor, overlayColor, 0.8f);
+    }
+
     /** Binds the bar view to the task */
     void rebindToTask(Task t) {
         // If an activity icon is defined, then we use that as the primary icon to show in the bar,
@@ -147,8 +183,10 @@
         int existingBgColor = (getBackground() instanceof ColorDrawable) ?
                 ((ColorDrawable) getBackground()).getColor() : 0;
         if (existingBgColor != t.colorPrimary) {
-            setBackgroundColor(t.colorPrimary);
+            mBackgroundColor.setColor(t.colorPrimary);
         }
+        mCurrentPrimaryColor = t.colorPrimary;
+        mCurrentPrimaryColorIsDark = t.useLightOnPrimaryColor;
         mActivityDescription.setTextColor(t.useLightOnPrimaryColor ?
                 mConfig.taskBarViewLightTextColor : mConfig.taskBarViewDarkTextColor);
         mDismissButton.setImageDrawable(t.useLightOnPrimaryColor ?
@@ -165,12 +203,12 @@
 
     /** Prepares this task view for the enter-recents animations.  This is called earlier in the
      * first layout because the actual animation into recents may take a long time. */
-    public void prepareEnterRecentsAnimation() {
+    void prepareEnterRecentsAnimation() {
         setVisibility(View.INVISIBLE);
     }
 
     /** Animates this task bar as it enters recents */
-    public void startEnterRecentsAnimation(int delay, Runnable postAnimRunnable) {
+    void startEnterRecentsAnimation(int delay, Runnable postAnimRunnable) {
         // Animate the task bar of the first task view
         setVisibility(View.VISIBLE);
         setTranslationY(-getMeasuredHeight());
@@ -184,7 +222,7 @@
     }
 
     /** Animates this task bar as it exits recents */
-    public void startLaunchTaskAnimation(Runnable preAnimRunnable, final Runnable postAnimRunnable) {
+    void startLaunchTaskAnimation(Runnable preAnimRunnable, final Runnable postAnimRunnable) {
         // Animate the task bar out of the first task view
         animate()
                 .translationY(-getMeasuredHeight())
@@ -202,7 +240,7 @@
     }
 
     /** Animates this task bar dismiss button when launching a task. */
-    public void startLaunchTaskDismissAnimation() {
+    void startLaunchTaskDismissAnimation() {
         if (mDismissButton.getVisibility() == View.VISIBLE) {
             mDismissButton.animate().cancel();
             mDismissButton.animate()
@@ -216,7 +254,7 @@
     }
 
     /** Animates this task bar if the user does not interact with the stack after a certain time. */
-    public void startNoUserInteractionAnimation() {
+    void startNoUserInteractionAnimation() {
         mDismissButton.setVisibility(View.VISIBLE);
         mDismissButton.setAlpha(0f);
         mDismissButton.animate()
@@ -229,11 +267,78 @@
     }
 
     /** Mark this task view that the user does has not interacted with the stack after a certain time. */
-    public void setNoUserInteractionState() {
+    void setNoUserInteractionState() {
         if (mDismissButton.getVisibility() != View.VISIBLE) {
             mDismissButton.animate().cancel();
             mDismissButton.setVisibility(View.VISIBLE);
             mDismissButton.setAlpha(1f);
         }
     }
+
+    /** 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 (focused) {
+            int secondaryColor = getSecondaryColor(mCurrentPrimaryColor, mCurrentPrimaryColorIsDark);
+            int[][] states = new int[][] {
+                    new int[] { android.R.attr.state_enabled },
+                    new int[] { android.R.attr.state_pressed }
+            };
+            int[] newStates = new int[]{
+                    android.R.attr.state_enabled,
+                    android.R.attr.state_pressed
+            };
+            int[] colors = new int[] {
+                    secondaryColor,
+                    secondaryColor
+            };
+            mBackground.setColor(new ColorStateList(states, colors));
+            mBackground.setState(newStates);
+            // Pulse the background color
+            int currentColor = mBackgroundColor.getColor();
+            int lightPrimaryColor = getSecondaryColor(mCurrentPrimaryColor, mCurrentPrimaryColorIsDark);
+            mBackgroundColorAnimator = ValueAnimator.ofObject(new ArgbEvaluator(), lightPrimaryColor,
+                    currentColor);
+            mBackgroundColorAnimator.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationStart(Animator animation) {
+                    mBackground.setState(new int[] {});
+                }
+            });
+            mBackgroundColorAnimator.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();
+        } else {
+            if (isRunning) {
+                // Restore the background color
+                int currentColor = mBackgroundColor.getColor();
+                mBackgroundColorAnimator = ValueAnimator.ofObject(new ArgbEvaluator(), currentColor,
+                        mCurrentPrimaryColor);
+                mBackgroundColorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+                    @Override
+                    public void onAnimationUpdate(ValueAnimator animation) {
+                        mBackgroundColor.setColor((Integer) animation.getAnimatedValue());
+                    }
+                });
+                mBackgroundColorAnimator.setRepeatCount(0);
+                mBackgroundColorAnimator.setDuration(150);
+                mBackgroundColorAnimator.start();
+            } else {
+                mBackground.setState(new int[] {});
+            }
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index f836aa3..f223bf3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -21,12 +21,15 @@
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.View;
+import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.model.Task;
 
 
 /** The task thumbnail view */
 public class TaskViewThumbnail extends FixedSizeImageView {
 
+    RecentsConfiguration mConfig;
+
     // Task bar clipping
     Rect mClipRect = new Rect();
 
@@ -44,9 +47,15 @@
 
     public TaskViewThumbnail(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
+        mConfig = RecentsConfiguration.getInstance();
         setScaleType(ScaleType.FIT_XY);
     }
 
+    @Override
+    protected void onFinishInflate() {
+        setAlpha(0.9f);
+    }
+
     /** Updates the clip rect based on the given task bar. */
     void enableTaskBarClip(View taskBar) {
         int top = (int) Math.max(0, taskBar.getTranslationY() +
@@ -101,4 +110,51 @@
     void unbindFromTask() {
         setImageDrawable(null);
     }
+
+    /** Handles focus changes. */
+    void onFocusChanged(boolean focused) {
+        if (focused) {
+            if (Float.compare(getAlpha(), 1f) != 0) {
+                startFadeAnimation(1f, 0, 150, null);
+            }
+        } else {
+            if (Float.compare(getAlpha(), mConfig.taskViewThumbnailAlpha) != 0) {
+                startFadeAnimation(mConfig.taskViewThumbnailAlpha, 0, 150, null);
+            }
+        }
+    }
+
+    /** Prepares for the enter recents animation. */
+    void prepareEnterRecentsAnimation(boolean isTaskViewLaunchTargetTask) {
+        if (isTaskViewLaunchTargetTask) {
+            setAlpha(1f);
+        } else {
+            setAlpha(mConfig.taskViewThumbnailAlpha);
+        }
+    }
+
+    /** Animates this task thumbnail as it enters recents */
+    void startEnterRecentsAnimation(int delay, Runnable postAnimRunnable) {
+        startFadeAnimation(mConfig.taskViewThumbnailAlpha, delay,
+                mConfig.taskBarEnterAnimDuration, postAnimRunnable);
+    }
+
+    /** Animates this task thumbnail as it exits recents */
+    void startLaunchTaskAnimation() {
+        startFadeAnimation(1f, 0, mConfig.taskBarExitAnimDuration, null);
+    }
+
+    /** Animates the thumbnail alpha. */
+    void startFadeAnimation(float finalAlpha, int delay, int duration, Runnable postAnimRunnable) {
+        if (postAnimRunnable != null) {
+            animate().withEndAction(postAnimRunnable);
+        }
+        animate()
+                .alpha(finalAlpha)
+                .setStartDelay(delay)
+                .setInterpolator(mConfig.fastOutSlowInInterpolator)
+                .setDuration(duration)
+                .withLayer()
+                .start();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java b/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
index acfeb4f..35b574b 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
@@ -79,8 +79,9 @@
     public void setMirror(ToggleSlider toggleSlider) {
         mMirror = toggleSlider;
         if (mMirror != null) {
-            mMirror.mToggle.setChecked(mToggle.isChecked());
-            mMirror.mSlider.setProgress(mSlider.getProgress());
+            mMirror.setChecked(mToggle.isChecked());
+            mMirror.setMax(mSlider.getMax());
+            mMirror.setValue(mSlider.getProgress());
         }
     }
 
@@ -110,10 +111,16 @@
 
     public void setMax(int max) {
         mSlider.setMax(max);
+        if (mMirror != null) {
+            mMirror.setMax(max);
+        }
     }
 
     public void setValue(int value) {
         mSlider.setProgress(value);
+        if (mMirror != null) {
+            mMirror.setValue(value);
+        }
     }
 
     private final OnCheckedChangeListener mCheckListener = new OnCheckedChangeListener() {
@@ -141,7 +148,7 @@
             }
 
             if (mMirror != null) {
-                mMirror.mSlider.setProgress(progress);
+                mMirror.setValue(progress);
             }
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index c23a4cd..8c5151b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -42,6 +42,7 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.os.AsyncTask;
 import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
@@ -89,6 +90,7 @@
 import com.android.systemui.SystemUI;
 import com.android.systemui.statusbar.NotificationData.Entry;
 import com.android.systemui.statusbar.phone.KeyguardTouchDelegate;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.policy.HeadsUpNotificationView;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 
@@ -130,9 +132,6 @@
     public static final int EXPANDED_LEAVE_ALONE = -10000;
     public static final int EXPANDED_FULL_OPEN = -10001;
 
-    /** If true, delays dismissing the Keyguard until the ActivityManager calls back. */
-    protected static final boolean DELAY_DISMISS_TO_ACTIVITY_LAUNCH = false;
-
     protected CommandQueue mCommandQueue;
     protected IStatusBarService mBarService;
     protected H mHandler = createHandler();
@@ -156,6 +155,8 @@
 
     protected int mLayoutDirection = -1; // invalid
     private Locale mLocale;
+    private float mFontScale;
+
     protected boolean mUseHeadsUp = false;
     protected boolean mHeadsUpTicker = false;
     protected boolean mDisableNotificationAlerts = false;
@@ -163,6 +164,7 @@
     protected DevicePolicyManager mDevicePolicyManager;
     protected IDreamManager mDreamManager;
     PowerManager mPowerManager;
+    protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
     protected int mRowMinHeight;
     protected int mRowMaxHeight;
 
@@ -252,27 +254,33 @@
             }
             final boolean isActivity = pendingIntent.isActivity();
             if (isActivity) {
+                final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
                 dismissKeyguardThenExecute(new OnDismissAction() {
                     @Override
                     public boolean onDismiss() {
-                        try {
-                            // The intent we are sending is for the application, which
-                            // won't have permission to immediately start an activity after
-                            // the user switches to home.  We know it is safe to do at this
-                            // point, so make sure new activity switches are now allowed.
-                            ActivityManagerNative.getDefault().resumeAppSwitches();
-                        } catch (RemoteException e) {
+                        if (keyguardShowing) {
+                            try {
+                                ActivityManagerNative.getDefault()
+                                        .keyguardWaitingForActivityDrawn();
+                                // The intent we are sending is for the application, which
+                                // won't have permission to immediately start an activity after
+                                // the user switches to home.  We know it is safe to do at this
+                                // point, so make sure new activity switches are now allowed.
+                                ActivityManagerNative.getDefault().resumeAppSwitches();
+                            } catch (RemoteException e) {
+                            }
                         }
 
                         boolean handled = superOnClickHandler(view, pendingIntent, fillInIntent);
+                        overrideActivityPendingAppTransition(keyguardShowing);
 
                         // close the shade if it was open
                         if (handled) {
-                            animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
+                            animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
                             visibilityChanged(false);
                         }
                         // Wait for activity start.
-                        return handled && DELAY_DISMISS_TO_ACTIVITY_LAUNCH;
+                        return handled;
                     }
                 });
                 return true;
@@ -419,8 +427,10 @@
         mRecents = getComponent(RecentsComponent.class);
         mRecents.setCallback(this);
 
-        mLocale = mContext.getResources().getConfiguration().locale;
+        final Configuration currentConfig = mContext.getResources().getConfiguration();
+        mLocale = currentConfig.locale;
         mLayoutDirection = TextUtils.getLayoutDirectionFromLocale(mLocale);
+        mFontScale = currentConfig.fontScale;
 
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
 
@@ -527,7 +537,9 @@
     protected void onConfigurationChanged(Configuration newConfig) {
         final Locale locale = mContext.getResources().getConfiguration().locale;
         final int ld = TextUtils.getLayoutDirectionFromLocale(locale);
-        if (! locale.equals(mLocale) || ld != mLayoutDirection) {
+        final float fontScale = newConfig.fontScale;
+
+        if (! locale.equals(mLocale) || ld != mLayoutDirection || fontScale != mFontScale) {
             if (DEBUG) {
                 Log.v(TAG, String.format(
                         "config changed locale/LD: %s (%d) -> %s (%d)", mLocale, mLayoutDirection,
@@ -1064,7 +1076,7 @@
                             startAppNotificationSettingsActivity(pkg, appUidF);
                             animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
                             visibilityChanged(false);
-                            return DELAY_DISMISS_TO_ACTIVITY_LAUNCH;
+                            return true;
                         }
                     });
                 }
@@ -1208,8 +1220,6 @@
 
         row.setClearable(sbn.isClearable());
 
-        row.setDrawingCacheEnabled(true);
-
         if (MULTIUSER_DEBUG) {
             TextView debug = (TextView) row.findViewById(R.id.debug_info);
             if (debug != null) {
@@ -1254,54 +1264,74 @@
         }
 
         public void onClick(final View v) {
+            final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
             dismissKeyguardThenExecute(new OnDismissAction() {
                 public boolean onDismiss() {
-                    try {
-                        // The intent we are sending is for the application, which
-                        // won't have permission to immediately start an activity after
-                        // the user switches to home.  We know it is safe to do at this
-                        // point, so make sure new activity switches are now allowed.
-                        ActivityManagerNative.getDefault().resumeAppSwitches();
-                    } catch (RemoteException e) {
+                    if (mIsHeadsUp) {
+                        mHeadsUpNotificationView.clear();
                     }
+                    AsyncTask.execute(new Runnable() {
+                        @Override
+                        public void run() {
+                            if (keyguardShowing) {
+                                try {
+                                    ActivityManagerNative.getDefault()
+                                            .keyguardWaitingForActivityDrawn();
+                                    // The intent we are sending is for the application, which
+                                    // won't have permission to immediately start an activity after
+                                    // the user switches to home.  We know it is safe to do at this
+                                    // point, so make sure new activity switches are now allowed.
+                                    ActivityManagerNative.getDefault().resumeAppSwitches();
+                                } catch (RemoteException e) {
+                                }
+                            }
 
-                    boolean sent = false;
-                    if (mIntent != null) {
-                        int[] pos = new int[2];
-                        v.getLocationOnScreen(pos);
-                        Intent overlay = new Intent();
-                        overlay.setSourceBounds(new Rect(pos[0], pos[1],
-                                pos[0] + v.getWidth(), pos[1] + v.getHeight()));
-                        try {
-                            mIntent.send(mContext, 0, overlay);
-                            sent = true;
-                        } catch (PendingIntent.CanceledException e) {
-                            // the stack trace isn't very helpful here.
-                            // Just log the exception message.
-                            Log.w(TAG, "Sending contentIntent failed: " + e);
-                        }
-                    }
+                            if (mIntent != null) {
+                                try {
+                                    mIntent.send();
+                                } catch (PendingIntent.CanceledException e) {
+                                    // the stack trace isn't very helpful here.
+                                    // Just log the exception message.
+                                    Log.w(TAG, "Sending contentIntent failed: " + e);
 
-                    try {
-                        if (mIsHeadsUp) {
-                            mHeadsUpNotificationView.clear();
+                                    // TODO: Dismiss Keyguard.
+                                }
+                                if (mIntent.isActivity()) {
+                                    overrideActivityPendingAppTransition(keyguardShowing);
+                                }
+                            }
+
+                            try {
+                                mBarService.onNotificationClick(mNotificationKey);
+                            } catch (RemoteException ex) {
+                                // system process is dead if we're here.
+                            }
                         }
-                        mBarService.onNotificationClick(mNotificationKey);
-                    } catch (RemoteException ex) {
-                        // system process is dead if we're here.
-                    }
+                    });
 
                     // close the shade if it was open
-                    animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
+                    animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
                     visibilityChanged(false);
 
-                    boolean waitForActivityLaunch = sent && mIntent.isActivity();
-                    return waitForActivityLaunch && DELAY_DISMISS_TO_ACTIVITY_LAUNCH;
+                    return mIntent != null && mIntent.isActivity();
                 }
             });
         }
     }
 
+    public void animateCollapsePanels(int flags, boolean force) {
+    }
+
+    public void overrideActivityPendingAppTransition(boolean keyguardShowing) {
+        if (keyguardShowing) {
+            try {
+                mWindowManagerService.overridePendingAppTransition(null, 0, 0, null);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Error overriding app transition: " + e);
+            }
+        }
+    }
+
     /**
      * The LEDs are turned o)ff when the notification panel is shown, even just a little bit.
      * This was added last-minute and is inconsistent with the way the rest of the notifications
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index a275572..43b7707 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -152,6 +152,11 @@
         logExpansionEvent(true, wasExpanded);
     }
 
+    public void resetUserExpansion() {
+        mHasUserChangedExpansion = false;
+        mUserExpanded = false;
+    }
+
     public boolean isUserLocked() {
         return mUserLocked;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index df64edf..5b0bf03 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -256,7 +256,9 @@
     }
 
     public void reset() {
-        mOnHeightChangedListener.onReset(this);
+        if (mOnHeightChangedListener != null) {
+            mOnHeightChangedListener.onReset(this);
+        }
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
index 5bc7e5a..23810f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
@@ -24,5 +24,5 @@
  * Keyguard.
  */
 public interface ActivityStarter {
-    public void startActivity(Intent intent);
+    public void startActivity(Intent intent, boolean dismissShade);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index e11f20f..b8ac3e7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -24,15 +24,18 @@
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.MediaStore;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.TypedValue;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityManager;
 import android.widget.FrameLayout;
+import android.widget.TextView;
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
@@ -62,7 +65,7 @@
     private KeyguardAffordanceView mCameraImageView;
     private KeyguardAffordanceView mPhoneImageView;
     private KeyguardAffordanceView mLockIcon;
-    private View mIndicationText;
+    private TextView mIndicationText;
     private ViewGroup mPreviewContainer;
 
     private View mPhonePreview;
@@ -101,7 +104,7 @@
         mCameraImageView = (KeyguardAffordanceView) findViewById(R.id.camera_button);
         mPhoneImageView = (KeyguardAffordanceView) findViewById(R.id.phone_button);
         mLockIcon = (KeyguardAffordanceView) findViewById(R.id.lock_icon);
-        mIndicationText = findViewById(R.id.keyguard_indication_text);
+        mIndicationText = (TextView) findViewById(R.id.keyguard_indication_text);
         watchForCameraPolicyChanges();
         watchForAccessibilityChanges();
         updateCameraVisibility();
@@ -116,6 +119,23 @@
         mLockIcon.setOnClickListener(this);
     }
 
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        int indicationBottomMargin = getResources().getDimensionPixelSize(
+                R.dimen.keyguard_indication_margin_bottom);
+        MarginLayoutParams mlp = (MarginLayoutParams) mIndicationText.getLayoutParams();
+        if (mlp.bottomMargin != indicationBottomMargin) {
+            mlp.bottomMargin = indicationBottomMargin;
+            mIndicationText.setLayoutParams(mlp);
+        }
+
+        // Respect font size setting.
+        mIndicationText.setTextSize(TypedValue.COMPLEX_UNIT_PX,
+                getResources().getDimensionPixelSize(
+                        com.android.internal.R.dimen.text_size_small_material));
+    }
+
     public void setActivityStarter(ActivityStarter activityStarter) {
         mActivityStarter = activityStarter;
     }
@@ -221,12 +241,12 @@
                 !mPreviewInflater.wouldLaunchResolverActivity(intent)) {
             mContext.startActivityAsUser(intent, UserHandle.CURRENT);
         } else {
-            mActivityStarter.startActivity(intent);
+            mActivityStarter.startActivity(intent, false /* dismissShade */);
         }
     }
 
     public void launchPhone() {
-        mActivityStarter.startActivity(PHONE_INTENT);
+        mActivityStarter.startActivity(PHONE_INTENT, false /* dismissShade */);
     }
 
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index db42b9d..fc737bee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -98,7 +98,7 @@
     public void startPreHideAnimation(Runnable runnable) {
         if (mKeyguardView != null) {
             mKeyguardView.startDisappearAnimation(runnable);
-        } else {
+        } else if (runnable != null) {
             runnable.run();
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index b66c310..5e5c3aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -18,8 +18,10 @@
 
 import android.animation.LayoutTransition;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
+import android.util.TypedValue;
 import android.view.View;
 import android.view.ViewTreeObserver;
 import android.view.animation.AnimationUtils;
@@ -43,6 +45,7 @@
     private boolean mKeyguardUserSwitcherShowing;
     private boolean mBatteryListening;
 
+    private TextView mCarrierLabel;
     private View mSystemIconsSuperContainer;
     private MultiUserSwitch mMultiUserSwitch;
     private ImageView mMultiUserAvatar;
@@ -65,12 +68,25 @@
         mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch);
         mMultiUserAvatar = (ImageView) findViewById(R.id.multi_user_avatar);
         mBatteryLevel = (TextView) findViewById(R.id.battery_level);
+        mCarrierLabel = (TextView) findViewById(R.id.keyguard_carrier_text);
         loadDimens();
         mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(getContext(),
                 android.R.interpolator.fast_out_slow_in);
         updateUserSwitcher();
     }
 
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+
+        // Respect font size setting.
+        mCarrierLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX,
+                getResources().getDimensionPixelSize(
+                        com.android.internal.R.dimen.text_size_small_material));
+        mBatteryLevel.setTextSize(TypedValue.COMPLEX_UNIT_PX,
+                getResources().getDimensionPixelSize(R.dimen.battery_level_text_size));
+    }
+
     private void loadDimens() {
         mSystemIconsSwitcherHiddenExpandedMargin = getResources().getDimensionPixelSize(
                 R.dimen.system_icons_switcher_hidden_expanded_margin);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index 47325c8..d7144da 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -21,10 +21,13 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.ContactsContract;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
 import android.widget.FrameLayout;
 
+import com.android.systemui.R;
 import com.android.systemui.qs.QSPanel;
 import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
 
@@ -36,9 +39,11 @@
     private QSPanel mQsPanel;
     private KeyguardUserSwitcher mKeyguardUserSwitcher;
     private boolean mKeyguardMode;
+    final UserManager mUserManager;
 
     public MultiUserSwitch(Context context, AttributeSet attrs) {
         super(context, attrs);
+        mUserManager = UserManager.get(getContext());
     }
 
     @Override
@@ -80,6 +85,22 @@
     }
 
     @Override
+    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+        super.onPopulateAccessibilityEvent(event);
+
+        if (isClickable()) {
+            final UserManager um = UserManager.get(getContext());
+            String text = mContext.getString(um.isUserSwitcherEnabled()
+                    ? R.string.accessibility_multi_user_switch_switcher
+                    : R.string.accessibility_multi_user_switch_quick_contact);
+            if (!TextUtils.isEmpty(text)) {
+                event.getText().add(text);
+            }
+        }
+
+    }
+
+    @Override
     public boolean hasOverlappingRendering() {
         return false;
     }
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 acdc6bc..42ae0c9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -24,6 +24,7 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.util.AttributeSet;
+import android.util.MathUtils;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
@@ -104,7 +105,6 @@
     private boolean mQsFullyExpanded;
     private boolean mKeyguardShowing;
     private boolean mDozing;
-    private boolean mKeyguardStatusBarTransparent;
     private int mStatusBarState;
     private float mInitialHeightOnTouch;
     private float mInitialTouchX;
@@ -117,6 +117,7 @@
     private int mQsPeekHeight;
     private boolean mStackScrollerOverscrolling;
     private boolean mQsExpansionFromOverscroll;
+    private float mLastOverscroll;
     private boolean mQsExpansionEnabled = true;
     private ValueAnimator mQsExpansionAnimator;
     private FlingAnimationUtils mFlingAnimationUtils;
@@ -273,11 +274,10 @@
                 requestScrollerTopPaddingUpdate(false /* animate */);
             }
         } else {
-            if (!mStackScrollerOverscrolling) {
-                setQsExpansion(mQsMinExpansionHeight);
-            }
+            setQsExpansion(mQsMinExpansionHeight + mLastOverscroll);
             positionClockAndNotifications();
             mNotificationStackScroller.setStackHeight(getExpandedHeight());
+            updateHeader();
         }
         mNotificationStackScroller.updateIsSmallScreen(
                 mHeader.getCollapsedHeight() + mQsPeekHeight);
@@ -414,12 +414,12 @@
     }
 
     @Override
-    public void fling(float vel, boolean always) {
+    public void fling(float vel, boolean expand) {
         GestureRecorder gr = ((PhoneStatusBarView) mBar).mBar.getGestureRecorder();
         if (gr != null) {
             gr.tag("fling " + ((vel > 0) ? "open" : "closed"), "notifications,v=" + vel);
         }
-        super.fling(vel, always);
+        super.fling(vel, expand);
     }
 
     @Override
@@ -552,8 +552,8 @@
     }
 
     private float getQsExpansionFraction() {
-        return (mQsExpansionHeight - mQsMinExpansionHeight)
-                / (getTempQsMaxExpansion() - mQsMinExpansionHeight);
+        return Math.min(1f, (mQsExpansionHeight - mQsMinExpansionHeight)
+                / (getTempQsMaxExpansion() - mQsMinExpansionHeight));
     }
 
     @Override
@@ -602,6 +602,10 @@
                 && event.getY(event.getActionIndex()) < mStatusBarMinHeight) {
             mTwoFingerQsExpand = true;
             requestPanelHeightUpdate();
+
+            // Normally, we start listening when the panel is expanded, but here we need to start
+            // earlier so the state is already up to date when dragging down.
+            setListening(true);
         }
         super.onTouchEvent(event);
         return true;
@@ -621,6 +625,11 @@
             mInitialHeightOnTouch = mQsExpansionHeight;
             mInitialTouchY = event.getX();
             mInitialTouchX = event.getY();
+
+            // If we interrupt an expansion gesture here, make sure to update the state correctly.
+            if (mIsExpanding) {
+                onExpandingFinished();
+            }
         }
     }
 
@@ -718,6 +727,7 @@
         float rounded = amount >= 1f ? amount : 0f;
         mStackScrollerOverscrolling = rounded != 0f && isRubberbanded;
         mQsExpansionFromOverscroll = rounded != 0f;
+        mLastOverscroll = rounded;
         updateQsState();
         setQsExpansion(mQsMinExpansionHeight + rounded);
     }
@@ -984,15 +994,7 @@
         requestScrollerTopPaddingUpdate(false /* animate */);
         updateNotificationScrim(height);
         if (mKeyguardShowing) {
-            float alpha = getQsExpansionFraction();
-            alpha *= 2;
-            alpha = Math.min(1, alpha);
-            alpha = 1 - alpha;
-            mKeyguardStatusBarTransparent = alpha == 0f;
-            updateKeyguardStatusBarVisibility();
-            if (!mKeyguardStatusBarTransparent) {
-                mKeyguardStatusBar.setAlpha(alpha);
-            }
+            updateHeaderKeyguard();
         }
         if (mStatusBarState == StatusBarState.SHADE && mQsExpanded
                 && !mStackScrollerOverscrolling && mQsScrimEnabled) {
@@ -1025,7 +1027,9 @@
     }
 
     private float calculateQsTopPadding() {
-        if (mKeyguardShowing) {
+        // We can only do the smoother transition on Keyguard when we also are not collapsing from a
+        // scrolled quick settings.
+        if (mKeyguardShowing && mScrollYOverride == -1) {
             return interpolate(getQsExpansionFraction(),
                     mNotificationStackScroller.getIntrinsicPadding() - mNotificationTopPadding,
                     mQsMaxExpansionHeight);
@@ -1081,6 +1085,7 @@
             }
             return;
         }
+        mScrollView.setBlockFlinging(true);
         ValueAnimator animator = ValueAnimator.ofFloat(mQsExpansionHeight, target);
         mFlingAnimationUtils.apply(animator, mQsExpansionHeight, target, vel);
         animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@@ -1092,6 +1097,7 @@
         animator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
+                mScrollView.setBlockFlinging(false);
                 mScrollYOverride = -1;
                 mQsExpansionAnimator = null;
                 if (onFinishRunnable != null) {
@@ -1339,27 +1345,25 @@
     }
 
     private void updateHeaderKeyguard() {
-        float alpha;
+        float alphaNotifications;
         if (mStatusBar.getBarState() == StatusBarState.KEYGUARD) {
 
             // When on Keyguard, we hide the header as soon as the top card of the notification
             // stack scroller is close enough (collision distance) to the bottom of the header.
-            alpha = getNotificationsTopY()
+            alphaNotifications = getNotificationsTopY()
                     /
-                    (mQsMinExpansionHeight + mNotificationsHeaderCollideDistance);
-
+                    (mKeyguardStatusBar.getHeight() + mNotificationsHeaderCollideDistance);
         } else {
 
             // In SHADE_LOCKED, the top card is already really close to the header. Hide it as
             // soon as we start translating the stack.
-            alpha = getNotificationsTopY() / mQsMinExpansionHeight;
+            alphaNotifications = getNotificationsTopY() / mKeyguardStatusBar.getHeight();
         }
-        alpha = Math.max(0, Math.min(alpha, 1));
-        alpha = (float) Math.pow(alpha, 0.75);
-        if (!mQsExpanded) {
-            mKeyguardStatusBar.setAlpha(alpha);
-        }
-        mKeyguardBottomArea.setAlpha(alpha);
+        alphaNotifications = MathUtils.constrain(alphaNotifications, 0, 1);
+        alphaNotifications = (float) Math.pow(alphaNotifications, 0.75);
+        float alphaQsExpansion = 1 - Math.min(1, getQsExpansionFraction() * 2);
+        mKeyguardStatusBar.setAlpha(Math.min(alphaNotifications, alphaQsExpansion));
+        mKeyguardBottomArea.setAlpha(Math.min(1 - getQsExpansionFraction(), alphaNotifications));
         setQsTranslation(mQsExpansionHeight);
     }
 
@@ -1703,8 +1707,7 @@
     }
 
     private void updateKeyguardStatusBarVisibility() {
-        mKeyguardStatusBar.setVisibility(mKeyguardShowing && !mKeyguardStatusBarTransparent
-                && !mDozing ? VISIBLE : INVISIBLE);
+        mKeyguardStatusBar.setVisibility(mKeyguardShowing && !mDozing ? VISIBLE : INVISIBLE);
     }
 
     public void setDozing(boolean dozing) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java
index ee6b1a9..53361dc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java
@@ -33,6 +33,7 @@
     private boolean mHandlingTouchEvent;
     private float mLastX;
     private float mLastY;
+    private boolean mBlockFlinging;
 
     public ObservableScrollView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -109,6 +110,17 @@
                         maxOverScrollX, maxOverScrollY, isTouchEvent);
     }
 
+    public void setBlockFlinging(boolean blockFlinging) {
+        mBlockFlinging = blockFlinging;
+    }
+
+    @Override
+    public void fling(int velocityY) {
+        if (!mBlockFlinging) {
+            super.fling(velocityY);
+        }
+    }
+
     @Override
     protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
         super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index 59f94f2..f74d2f4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -140,7 +140,7 @@
         mPanelHolder.setSelectedPanel(mTouchingPanel);
         for (PanelView pv : mPanels) {
             if (pv != panel) {
-                pv.collapse();
+                pv.collapse(false /* delayed */);
             }
         }
     }
@@ -191,7 +191,7 @@
         boolean waiting = false;
         for (PanelView pv : mPanels) {
             if (animate && !pv.isFullyCollapsed()) {
-                pv.collapse();
+                pv.collapse(true /* delayed */);
                 waiting = true;
             } else {
                 pv.resetViews();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 469a831..c8e943e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -99,6 +99,7 @@
     };
 
     protected void onExpandingFinished() {
+        mClosing = false;
         mBar.onExpandingFinished();
     }
 
@@ -150,7 +151,7 @@
                     postOnAnimation(new Runnable() {
                         @Override
                         public void run() {
-                            collapse();
+                            collapse(false /* delayed */);
                         }
                     });
                 }
@@ -651,7 +652,7 @@
         mBar = panelBar;
     }
 
-    public void collapse() {
+    public void collapse(boolean delayed) {
         if (DEBUG) logf("collapse: " + this);
         if (mPeekPending || mPeekAnimator != null) {
             mCollapseAfterPeek = true;
@@ -668,7 +669,16 @@
             }
             mClosing = true;
             notifyExpandingStarted();
-            fling(0, false /* expand */);
+            if (delayed) {
+                postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        fling(0, false /* expand */);
+                    }
+                }, 120);
+            } else {
+                fling(0, false /* expand */);
+            }
         }
     }
 
@@ -856,7 +866,7 @@
     private final Runnable mPostCollapseRunnable = new Runnable() {
         @Override
         public void run() {
-            collapse();
+            collapse(false /* delayed */);
         }
     };
     private boolean onMiddleClicked() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index caecf1d..7a9cbef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -91,6 +91,8 @@
 import android.view.ViewStub;
 import android.view.ViewTreeObserver;
 import android.view.WindowManager;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
 import android.view.animation.AccelerateDecelerateInterpolator;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.Animation;
@@ -113,7 +115,6 @@
 import com.android.systemui.doze.DozeService;
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.qs.QSPanel;
-import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.ActivatableNotificationView;
 import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.CommandQueue;
@@ -138,6 +139,7 @@
 import com.android.systemui.statusbar.policy.FlashlightController;
 import com.android.systemui.statusbar.policy.HeadsUpNotificationView;
 import com.android.systemui.statusbar.policy.HotspotControllerImpl;
+import com.android.systemui.statusbar.policy.KeyButtonView;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
 import com.android.systemui.statusbar.policy.LocationControllerImpl;
@@ -211,6 +213,9 @@
     public static final int FADE_KEYGUARD_START_DELAY = 100;
     public static final int FADE_KEYGUARD_DURATION = 300;
 
+    /** Allow some time inbetween the long press for back and recents. */
+    private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200;
+
     PhoneStatusBarPolicy mIconPolicy;
 
     // These are no longer handled by the policy, because we need custom strategies for them
@@ -323,7 +328,7 @@
     VelocityTracker mVelocityTracker;
 
     int[] mAbsPos = new int[2];
-    Runnable mPostCollapseCleanup = null;
+    ArrayList<Runnable> mPostCollapseRunnables = new ArrayList<>();
 
     // for disabling the status bar
     int mDisabled = 0;
@@ -395,7 +400,6 @@
     private int mNavigationBarMode;
     private Boolean mScreenOn;
 
-    private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
     private ViewMediatorCallback mKeyguardViewMediatorCallback;
     private ScrimController mScrimController;
 
@@ -575,6 +579,7 @@
 
         mDozeServiceHost = new DozeServiceHost();
         putComponent(DozeService.Host.class, mDozeServiceHost);
+        putComponent(PhoneStatusBar.class, this);
 
         setControllerUsers();
     }
@@ -887,14 +892,14 @@
             return;
         }
 
-        mPostCollapseCleanup = new Runnable() {
+        addPostCollapseAction(new Runnable() {
             @Override
             public void run() {
                 try {
                     mBarService.onClearAllNotifications(mCurrentUserId);
                 } catch (Exception ex) { }
             }
-        };
+        });
 
         performDismissAllAnimations(viewsToHide);
 
@@ -1055,10 +1060,13 @@
         }
     };
 
-    private View.OnLongClickListener mLockToAppClickListener = new View.OnLongClickListener() {
+    private long mLastLockToAppLongPress;
+    private AccessibilityManager mAccessibilityManager;
+    private View.OnLongClickListener mLongPressBackRecentsListener =
+            new View.OnLongClickListener() {
         @Override
         public boolean onLongClick(View v) {
-            toggleLockedApp();
+            handleLongPressBackRecents(v);
             return true;
         }
     };
@@ -1107,7 +1115,9 @@
         mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
         mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPreloadOnTouchListener);
         mNavigationBarView.getRecentsButton().setLongClickable(true);
-        mNavigationBarView.getRecentsButton().setOnLongClickListener(mLockToAppClickListener);
+        mNavigationBarView.getRecentsButton().setOnLongClickListener(mLongPressBackRecentsListener);
+        mNavigationBarView.getBackButton().setLongClickable(true);
+        mNavigationBarView.getBackButton().setOnLongClickListener(mLongPressBackRecentsListener);
         mNavigationBarView.getHomeButton().setOnTouchListener(mHomeActionListener);
         updateSearchPanel();
     }
@@ -1366,6 +1376,17 @@
     private void updateNotificationShade() {
         if (mStackScroller == null) return;
 
+        // Do not modify the notifications during collapse.
+        if (isCollapsing()) {
+            addPostCollapseAction(new Runnable() {
+                @Override
+                public void run() {
+                    updateNotificationShade();
+                }
+            });
+            return;
+        }
+
         ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications();
         ArrayList<ExpandableNotificationRow> toShow = new ArrayList<>(activeNotifications.size());
         final int N = activeNotifications.size();
@@ -2004,8 +2025,8 @@
     }
 
     @Override
-    public void startActivity(Intent intent) {
-        startActivityDismissingKeyguard(intent, false);
+    public void startActivity(Intent intent, boolean dismissShade) {
+        startActivityDismissingKeyguard(intent, false, dismissShade);
     }
 
     public ScrimController getScrimController() {
@@ -2016,6 +2037,14 @@
         mStatusBarWindowManager.setQsExpanded(expanded);
     }
 
+    public boolean isGoingToNotificationShade() {
+        return mLeaveOpenOnKeyguardHide;
+    }
+
+    public boolean isQsExpanded() {
+        return mNotificationPanel.isQsExpanded();
+    }
+
     /**
      * All changes to the status bar and notifications funnel through here and are batched.
      */
@@ -2126,10 +2155,7 @@
     public void animateCollapsePanels(int flags, boolean force) {
         if (!force &&
                 (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)) {
-            if (mPostCollapseCleanup != null) {
-                mPostCollapseCleanup.run();
-                mPostCollapseCleanup = null;
-            }
+            runPostCollapseRunnables();
             return;
         }
         if (SPEW) {
@@ -2159,6 +2185,14 @@
         }
     }
 
+    private void runPostCollapseRunnables() {
+        int size = mPostCollapseRunnables.size();
+        for (int i = 0; i < size; i++) {
+            mPostCollapseRunnables.get(i).run();
+        }
+        mPostCollapseRunnables.clear();
+    }
+
     public ViewPropertyAnimator setVisibilityWhenDone(
             final ViewPropertyAnimator a, final View v, final int vis) {
         a.setListener(new AnimatorListenerAdapter() {
@@ -2270,11 +2304,7 @@
         // Close any "App info" popups that might have snuck on-screen
         dismissPopups();
 
-        if (mPostCollapseCleanup != null) {
-            mPostCollapseCleanup.run();
-            mPostCollapseCleanup = null;
-        }
-
+        runPostCollapseRunnables();
         setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
         showBouncer();
         disable(mDisabledUnmodified, true /* animate */);
@@ -2874,7 +2904,8 @@
         }
     }
 
-    public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned) {
+    public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
+            final boolean dismissShade) {
         if (onlyProvisioned && !isDeviceProvisioned()) return;
 
         final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
@@ -2884,32 +2915,27 @@
                 AsyncTask.execute(new Runnable() {
                     public void run() {
                         try {
+                            if (keyguardShowing) {
+                                ActivityManagerNative.getDefault()
+                                        .keyguardWaitingForActivityDrawn();
+                            }
                             intent.setFlags(
                                     Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
                             mContext.startActivityAsUser(
                                     intent, new UserHandle(UserHandle.USER_CURRENT));
-                            if (keyguardShowing) {
-                                mWindowManagerService.overridePendingAppTransition(
-                                        null, 0, 0, null);
-                            }
+                            overrideActivityPendingAppTransition(keyguardShowing);
                         } catch (RemoteException e) {
                         }
                     }
                 });
-                animateCollapsePanels();
-
-                return DELAY_DISMISS_TO_ACTIVITY_LAUNCH;
+                if (dismissShade) {
+                    animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
+                }
+                return true;
             }
         });
     }
 
-    private View.OnClickListener mClockClickListener = new View.OnClickListener() {
-        public void onClick(View v) {
-            startActivityDismissingKeyguard(
-                    new Intent(Intent.ACTION_QUICK_CLOCK), true); // have fun, everyone
-        }
-    };
-
     private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         public void onReceive(Context context, Intent intent) {
             if (DEBUG) Log.v(TAG, "onReceive: " + intent);
@@ -2928,6 +2954,7 @@
                 notifyHeadsUpScreenOn(false);
                 finishBarAnimations();
                 stopNotificationLogging();
+                resetUserExpandedStates();
             }
             else if (Intent.ACTION_SCREEN_ON.equals(action)) {
                 mScreenOn = true;
@@ -2956,6 +2983,17 @@
         }
     };
 
+    private void resetUserExpandedStates() {
+        ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications();
+        final int notificationCount = activeNotifications.size();
+        for (int i = 0; i < notificationCount; i++) {
+            NotificationData.Entry entry = activeNotifications.get(i);
+            if (entry.row != null) {
+                entry.row.resetUserExpansion();
+            }
+        }
+    }
+
     @Override
     protected void dismissKeyguardThenExecute(final OnDismissAction action) {
         if (mStatusBarKeyguardViewManager.isShowing()) {
@@ -3208,19 +3246,7 @@
     }
 
     private void handleStartSettingsActivity(Intent intent, boolean onlyProvisioned) {
-        if (onlyProvisioned && !isDeviceProvisioned()) return;
-        try {
-            // Dismiss the lock screen when Settings starts.
-            ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
-        } catch (RemoteException e) {
-        }
-        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
-        mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
-        animateCollapsePanels();
-    }
-
-    public void startSettingsActivity(String action) {
-        postStartSettingsActivity(new Intent(action), 0);
+        startActivityDismissingKeyguard(intent, onlyProvisioned, true /* dismissShade */);
     }
 
     private static class FastColorDrawable extends Drawable {
@@ -3363,6 +3389,14 @@
         }
     }
 
+    public boolean isCollapsing() {
+        return mNotificationPanel.isCollapsing();
+    }
+
+    public void addPostCollapseAction(Runnable r) {
+        mPostCollapseRunnables.add(r);
+    }
+
     public boolean isInLaunchTransition() {
         return mNotificationPanel.isLaunchTransitionRunning()
                 || mNotificationPanel.isLaunchTransitionFinished();
@@ -3603,10 +3637,7 @@
     }
 
     public void onTrackingStarted() {
-        if (mPostCollapseCleanup != null) {
-            mPostCollapseCleanup.run();
-            mPostCollapseCleanup = null;
-        }
+        runPostCollapseRunnables();
     }
 
     public void onUnlockHintStarted() {
@@ -3753,15 +3784,58 @@
         mStackScroller.setAnimationsEnabled(true);
     }
 
-    public void toggleLockedApp() {
-        Log.d(TAG, "Trying to toggle lock-to-app");
+    /**
+     * This handles long-press of both back and recents.  They are
+     * handled together to capture them both being long-pressed
+     * at the same time to exit screen pinning (lock task).
+     *
+     * When accessibility mode is on, only a long-press from recents
+     * is required to exit.
+     *
+     * In all other circumstances we try to pass through long-press events
+     * for Back, so that apps can still use it.  Which can be from two things.
+     * 1) Not currently in screen pinning (lock task).
+     * 2) Back is long-pressed without recents.
+     */
+    private void handleLongPressBackRecents(View v) {
         try {
+            boolean sendBackLongPress = false;
             IActivityManager activityManager = ActivityManagerNative.getDefault();
-            if (activityManager.isInLockTaskMode()) {
-                activityManager.stopLockTaskModeOnCurrent();
+            if (mAccessibilityManager == null) {
+                mAccessibilityManager = (AccessibilityManager)
+                        mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
+            }
+            boolean isAccessiblityEnabled = mAccessibilityManager.isEnabled();
+            if (activityManager.isInLockTaskMode() && !isAccessiblityEnabled) {
+                long time = System.currentTimeMillis();
+                // If we recently long-pressed the other button then they were
+                // long-pressed 'together'
+                if ((time - mLastLockToAppLongPress) < LOCK_TO_APP_GESTURE_TOLERENCE) {
+                    activityManager.stopLockTaskModeOnCurrent();
+                } else if ((v.getId() == R.id.back)
+                        && !mNavigationBarView.getRecentsButton().isPressed()) {
+                    // If we aren't pressing recents right now then they presses
+                    // won't be together, so send the standard long-press action.
+                    sendBackLongPress = true;
+                }
+                mLastLockToAppLongPress = time;
+            } else {
+                // If this is back still need to handle sending the long-press event.
+                if (v.getId() == R.id.back) {
+                    sendBackLongPress = true;
+                } else if (isAccessiblityEnabled && activityManager.isInLockTaskMode()) {
+                    // When in accessibility mode a long press that is recents (not back)
+                    // should stop lock task.
+                    activityManager.stopLockTaskModeOnCurrent();
+                }
+            }
+            if (sendBackLongPress) {
+                KeyButtonView keyButtonView = (KeyButtonView) v;
+                keyButtonView.sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.FLAG_LONG_PRESS);
+                keyButtonView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
             }
         } catch (RemoteException e) {
-            Log.d(TAG, "Unable to toggle Lock-to-app", e);
+            Log.d(TAG, "Unable to reach activity manager", e);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index 0c62fd3..39b2022 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -16,7 +16,7 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.app.AlarmClockInfo;
+import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
@@ -24,6 +24,7 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
+import android.util.TypedValue;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewOutlineProvider;
@@ -54,7 +55,7 @@
     private View mSystemIconsSuperContainer;
     private View mDateGroup;
     private View mClock;
-    private View mTime;
+    private TextView mTime;
     private View mAmPm;
     private MultiUserSwitch mMultiUserSwitch;
     private ImageView mMultiUserAvatar;
@@ -73,7 +74,7 @@
 
     private boolean mShowEmergencyCallsOnly;
     private boolean mAlarmShowing;
-    private AlarmClockInfo mNextAlarm;
+    private AlarmManager.AlarmClockInfo mNextAlarm;
 
     private int mCollapsedHeight;
     private int mExpandedHeight;
@@ -86,6 +87,9 @@
     private int mMultiUserSwitchWidthCollapsed;
     private int mMultiUserSwitchWidthExpanded;
 
+    private int mClockCollapsedSize;
+    private int mClockExpandedSize;
+
     /**
      * In collapsed QS, the clock and avatar are scaled down a bit post-layout to allow for a nice
      * transition. These values determine that factor.
@@ -121,7 +125,7 @@
         mSystemIconsSuperContainer.setOnClickListener(this);
         mDateGroup = findViewById(R.id.date_group);
         mClock = findViewById(R.id.clock);
-        mTime = findViewById(R.id.time_view);
+        mTime = (TextView) findViewById(R.id.time_view);
         mAmPm = findViewById(R.id.am_pm_view);
         mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch);
         mMultiUserAvatar = (ImageView) findViewById(R.id.multi_user_avatar);
@@ -152,8 +156,6 @@
                 boolean rtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
                 mTime.setPivotX(rtl ? mTime.getWidth() : 0);
                 mTime.setPivotY(mTime.getBaseline());
-                mAmPm.setPivotX(rtl ? mAmPm.getWidth() : 0);
-                mAmPm.setPivotY(mAmPm.getBaseline());
                 updateAmPmTranslation();
             }
         });
@@ -206,9 +208,10 @@
         mAvatarCollapsedScaleFactor =
                 getResources().getDimensionPixelSize(R.dimen.multi_user_avatar_collapsed_size)
                 / (float) mMultiUserAvatar.getLayoutParams().width;
-        mClockCollapsedScaleFactor =
-                (float) getResources().getDimensionPixelSize(R.dimen.qs_time_collapsed_size)
-                / (float) getResources().getDimensionPixelSize(R.dimen.qs_time_expanded_size);
+        mClockCollapsedSize = getResources().getDimensionPixelSize(R.dimen.qs_time_collapsed_size);
+        mClockExpandedSize = getResources().getDimensionPixelSize(R.dimen.qs_time_expanded_size);
+        mClockCollapsedScaleFactor = (float) mClockCollapsedSize / (float) mClockExpandedSize;
+
     }
 
     public void setActivityStarter(ActivityStarter activityStarter) {
@@ -333,17 +336,14 @@
     }
 
     private void updateClockScale() {
-        mAmPm.setScaleX(mClockCollapsedScaleFactor);
-        mAmPm.setScaleY(mClockCollapsedScaleFactor);
-        mTime.setScaleX(getTimeScale());
-        mTime.setScaleY(getTimeScale());
+        mTime.setTextSize(TypedValue.COMPLEX_UNIT_PX, mExpanded
+                ? mClockExpandedSize
+                : mClockCollapsedSize);
+        mTime.setScaleX(1f);
+        mTime.setScaleY(1f);
         updateAmPmTranslation();
     }
 
-    private float getTimeScale() {
-        return !mExpanded ? mClockCollapsedScaleFactor : 1f;
-    }
-
     private void updateAmPmTranslation() {
         boolean rtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
         mAmPm.setTranslationX((rtl ? 1 : -1) * mTime.getWidth() * (1 - mTime.getScaleX()));
@@ -360,13 +360,13 @@
     }
 
     @Override
-    public void onNextAlarmChanged(AlarmClockInfo nextAlarm) {
+    public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
         mNextAlarm = nextAlarm;
         if (nextAlarm != null) {
             mAlarmStatus.setText(KeyguardStatusView.formatNextAlarm(getContext(), nextAlarm));
         }
         mAlarmShowing = nextAlarm != null;
-        updateVisibilities();
+        updateEverything();
         requestCaptureValues();
     }
 
@@ -483,17 +483,19 @@
         } else if (v == mAlarmStatus && mNextAlarm != null) {
             PendingIntent showIntent = mNextAlarm.getShowIntent();
             if (showIntent != null && showIntent.isActivity()) {
-                mActivityStarter.startActivity(showIntent.getIntent());
+                mActivityStarter.startActivity(showIntent.getIntent(), true /* dismissShade */);
             }
         }
     }
 
     private void startSettingsActivity() {
-        mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS));
+        mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS),
+                true /* dismissShade */);
     }
 
     private void startBatteryActivity() {
-        mActivityStarter.startActivity(new Intent(Intent.ACTION_POWER_USAGE_SUMMARY));
+        mActivityStarter.startActivity(new Intent(Intent.ACTION_POWER_USAGE_SUMMARY),
+                true /* dismissShade */);
     }
 
     public void setQSPanel(QSPanel qsp) {
@@ -510,10 +512,13 @@
     }
 
     public void setShowEmergencyCallsOnly(boolean show) {
-        mShowEmergencyCallsOnly = show;
-        if (mExpanded) {
-            updateVisibilities();
-            requestCaptureValues();
+        boolean changed = show != mShowEmergencyCallsOnly;
+        if (changed) {
+            mShowEmergencyCallsOnly = show;
+            if (mExpanded) {
+                updateEverything();
+                requestCaptureValues();
+            }
         }
     }
 
@@ -524,8 +529,8 @@
     }
 
     private void captureLayoutValues(LayoutValues target) {
-        target.timeScale = mTime.getScaleX();
-        target.clockY = mClock.getTop();
+        target.timeScale = mExpanded ? 1f : mClockCollapsedScaleFactor;
+        target.clockY = mClock.getBottom();
         target.dateY = mDateGroup.getTop();
         target.emergencyCallsOnlyAlpha = getAlphaForVisibility(mEmergencyCallsOnly);
         target.alarmStatusAlpha = getAlphaForVisibility(mAlarmStatus);
@@ -550,7 +555,7 @@
     }
 
     private void applyAlpha(View v, float alpha) {
-        if (v == null) {
+        if (v == null || v.getVisibility() == View.GONE) {
             return;
         }
         if (alpha == 0f) {
@@ -564,7 +569,7 @@
     private void applyLayoutValues(LayoutValues values) {
         mTime.setScaleX(values.timeScale);
         mTime.setScaleY(values.timeScale);
-        mClock.setY(values.clockY);
+        mClock.setY(values.clockY - mClock.getHeight());
         mDateGroup.setY(values.dateY);
         mAlarmStatus.setY(values.dateY - mAlarmStatus.getPaddingTop());
         mMultiUserAvatar.setScaleX(values.avatarScale);
@@ -593,6 +598,10 @@
         applyAlpha(mBatteryLevel, values.batteryLevelAlpha);
         applyAlpha(mSettingsButton, values.settingsAlpha);
         applyAlpha(mSignalCluster, values.signalClusterAlpha);
+        if (!mExpanded) {
+            mTime.setScaleX(1f);
+            mTime.setScaleY(1f);
+        }
         updateAmPmTranslation();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 68dd4f9..f427ec4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -188,6 +188,7 @@
                             @Override
                             public void run() {
                                 mStatusBarWindowManager.setKeyguardOccluded(true);
+                                reset();
                             }
                         });
                 return;
@@ -206,12 +207,13 @@
      * Starts the animation before we dismiss Keyguard, i.e. an disappearing animation on the
      * security view of the bouncer.
      *
-     * @param finishRunnable the runnable to be run after the animation finished
+     * @param finishRunnable the runnable to be run after the animation finished, or {@code null} if
+     *                       no action should be run
      */
     public void startPreHideAnimation(Runnable finishRunnable) {
         if (mBouncer.isShowing()) {
             mBouncer.startPreHideAnimation(finishRunnable);
-        } else {
+        } else if (finishRunnable != null) {
             finishRunnable.run();
         }
     }
@@ -362,4 +364,25 @@
     public boolean interceptMediaKey(KeyEvent event) {
         return mBouncer.interceptMediaKey(event);
     }
+
+    public void onActivityDrawn() {
+        if (mPhoneStatusBar.isCollapsing()) {
+            mPhoneStatusBar.addPostCollapseAction(new Runnable() {
+                @Override
+                public void run() {
+                    mViewMediatorCallback.readyForKeyguardDone();
+                }
+            });
+        } else {
+            mViewMediatorCallback.readyForKeyguardDone();
+        }
+    }
+
+    public boolean shouldDisableWindowAnimationsForUnlock() {
+        return mPhoneStatusBar.isInLaunchTransition();
+    }
+
+    public boolean isGoingToNotificationShade() {
+        return mPhoneStatusBar.isGoingToNotificationShade();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 2c5bcb79..04ee294 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -28,7 +28,6 @@
 import android.view.ViewRootImpl;
 import android.widget.FrameLayout;
 
-import com.android.systemui.ExpandHelper;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.DragDownHelper;
@@ -130,7 +129,7 @@
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
         boolean handled = false;
-        if (mService.getBarState() == StatusBarState.KEYGUARD) {
+        if (mService.getBarState() == StatusBarState.KEYGUARD && !mService.isQsExpanded()) {
             handled = mDragDownHelper.onTouchEvent(ev);
         }
         if (!handled) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 330b599..e9581fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -56,12 +56,12 @@
         public void run() {
             if (isPressed()) {
                 // Log.d("KeyButtonView", "longpressed: " + this);
-                if (mCode != 0) {
-                    sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.FLAG_LONG_PRESS);
-                    sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
-                } else {
+                if (isLongClickable()) {
                     // Just an old-fashioned ImageView
                     performLongClick();
+                } else {
+                    sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.FLAG_LONG_PRESS);
+                    sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
                 }
             }
         }
@@ -216,7 +216,7 @@
         return true;
     }
 
-    void sendEvent(int action, int flags) {
+    public void sendEvent(int action, int flags) {
         sendEvent(action, flags, SystemClock.uptimeMillis());
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmController.java
index ca71521..8f1f7c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmController.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.statusbar.policy;
 
-import android.app.AlarmClockInfo;
 import android.app.AlarmManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -33,7 +32,7 @@
     private final ArrayList<NextAlarmChangeCallback> mChangeCallbacks = new ArrayList<>();
 
     private AlarmManager mAlarmManager;
-    private AlarmClockInfo mNextAlarm;
+    private AlarmManager.AlarmClockInfo mNextAlarm;
 
     public NextAlarmController(Context context) {
         mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
@@ -79,6 +78,6 @@
     }
 
     public interface NextAlarmChangeCallback {
-        void onNextAlarmChanged(AlarmClockInfo nextAlarm);
+        void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm);
     }
 }
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 a1993f7..47e3e73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -113,6 +113,7 @@
      *
      * @param forcePictureLoadForId forces the picture of the given user to be reloaded.
      */
+    @SuppressWarnings("unchecked")
     private void refreshUsers(int forcePictureLoadForId) {
 
         SparseArray<Bitmap> bitmaps = new SparseArray<>(mUsers.size());
@@ -170,7 +171,7 @@
                 boolean canCreateGuest = (currentUserCanCreateUsers || anyoneCanCreateUsers)
                         && guestRecord == null;
                 boolean canCreateUser = (currentUserCanCreateUsers || anyoneCanCreateUsers)
-                        && records.size() < UserManager.getMaxSupportedUsers();
+                        && mUserManager.canAddMoreUsers();
                 boolean createIsRestricted = !addUsersWhenLocked;
 
                 if (!mSimpleUserSwitcher) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
index 9d3dec8..b33e502 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.statusbar.policy;
 
-import android.app.AlarmClockInfo;
 import android.app.AlarmManager;
 import android.app.INotificationManager;
 import android.content.BroadcastReceiver;
@@ -146,7 +145,7 @@
 
     @Override
     public long getNextAlarm() {
-        final AlarmClockInfo info = mAlarmManager.getNextAlarmClock(mUserId);
+        final AlarmManager.AlarmClockInfo info = mAlarmManager.getNextAlarmClock(mUserId);
         return info != null ? info.getTriggerTime() : 0;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index d25dda1..8e5077c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -211,6 +211,15 @@
     public NotificationStackScrollLayout(Context context, AttributeSet attrs, int defStyleAttr,
             int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
+        int minHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height);
+        int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_max_height);
+        mExpandHelper = new ExpandHelper(getContext(), this,
+                minHeight, maxHeight);
+        mExpandHelper.setEventSource(this);
+        mExpandHelper.setScrollAdapter(this);
+
+        mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, getContext());
+        mSwipeHelper.setLongPressListener(mLongPressListener);
         initView(context);
         if (DEBUG) {
             setWillNotDraw(false);
@@ -248,10 +257,6 @@
         mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
         mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
         mOverflingDistance = configuration.getScaledOverflingDistance();
-        float densityScale = getResources().getDisplayMetrics().density;
-        float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop();
-        mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, getContext());
-        mSwipeHelper.setLongPressListener(mLongPressListener);
 
         mSidePaddings = context.getResources()
                 .getDimensionPixelSize(R.dimen.notification_side_padding);
@@ -266,12 +271,6 @@
         mPaddingBetweenElementsNormal = context.getResources()
                 .getDimensionPixelSize(R.dimen.notification_padding);
         updatePadding(mAmbientState.isDimmed());
-        int minHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height);
-        int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_max_height);
-        mExpandHelper = new ExpandHelper(getContext(), this,
-                minHeight, maxHeight);
-        mExpandHelper.setEventSource(this);
-        mExpandHelper.setScrollAdapter(this);
         mMinTopOverScrollToEscape = getResources().getDimensionPixelSize(
                 R.dimen.min_top_overscroll_to_qs);
         mNotificationTopPadding = getResources().getDimensionPixelSize(
@@ -281,7 +280,7 @@
     }
 
     private void updatePadding(boolean dimmed) {
-        mPaddingBetweenElements = dimmed
+        mPaddingBetweenElements = dimmed && mStackScrollAlgorithm.shouldScaleDimmed()
                 ? mPaddingBetweenElementsDimmed
                 : mPaddingBetweenElementsNormal;
         mBottomStackSlowDownHeight = mStackScrollAlgorithm.getBottomStackSlowDownLength();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index f984339b3..fc2be1a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.stack;
 
 import android.content.Context;
+import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
@@ -73,6 +74,7 @@
     private int mCollapseSecondCardPadding;
     private boolean mIsSmallScreen;
     private int mMaxNotificationHeight;
+    private boolean mScaleDimmed;
 
     public StackScrollAlgorithm(Context context) {
         initConstants(context);
@@ -80,7 +82,7 @@
     }
 
     private void updatePadding(boolean dimmed) {
-        mPaddingBetweenElements = dimmed
+        mPaddingBetweenElements = dimmed && mScaleDimmed
                 ? mPaddingBetweenElementsDimmed
                 : mPaddingBetweenElementsNormal;
         mTopStackTotalSize = mTopStackSlowDownLength + mPaddingBetweenElements
@@ -125,8 +127,13 @@
                 R.dimen.notification_material_rounded_rect_radius);
         mCollapseSecondCardPadding = context.getResources().getDimensionPixelSize(
                 R.dimen.notification_collapse_second_card_padding);
+        mScaleDimmed = context.getResources().getDisplayMetrics().densityDpi
+                >= DisplayMetrics.DENSITY_XXHIGH;
     }
 
+    public boolean shouldScaleDimmed() {
+        return mScaleDimmed;
+    }
 
     public void getStackScrollState(AmbientState ambientState, StackScrollState resultState) {
         // The state of the local variables are saved in an algorithmState to easily subdivide it
@@ -271,7 +278,7 @@
             childViewState.dark = dark;
             childViewState.hideSensitive = hideSensitive;
             boolean isActivatedChild = activatedChild == child;
-            childViewState.scale = !dimmed || isActivatedChild
+            childViewState.scale = !mScaleDimmed || !dimmed || isActivatedChild
                     ? 1.0f
                     : DIMMED_SCALE;
             if (dimmed && activatedChild != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index 5233da2..b05c242 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -112,7 +112,8 @@
 
     // Pseudo stream type for master volume
     private static final int STREAM_MASTER = -100;
-    // Pseudo stream type for remote volume is defined in AudioService.STREAM_REMOTE_MUSIC
+    // Pseudo stream type for remote volume
+    private static final int STREAM_REMOTE_MUSIC = -200;
 
     private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
             .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
@@ -192,7 +193,7 @@
                 R.drawable.ic_audio_vol,
                 R.drawable.ic_audio_vol_mute,
                 false),
-        RemoteStream(AudioService.STREAM_REMOTE_MUSIC,
+        RemoteStream(STREAM_REMOTE_MUSIC,
                 R.string.volume_icon_description_media, //FIXME should have its own description
                 R.drawable.ic_media_route_on_holo_dark,
                 R.drawable.ic_media_route_disabled_holo_dark,
@@ -521,7 +522,7 @@
     private boolean isMuted(int streamType) {
         if (streamType == STREAM_MASTER) {
             return mAudioManager.isMasterMute();
-        } else if (streamType == AudioService.STREAM_REMOTE_MUSIC) {
+        } else if (streamType == STREAM_REMOTE_MUSIC) {
             // TODO do we need to support a distinct mute property for remote?
             return false;
         } else {
@@ -532,7 +533,7 @@
     private int getStreamMaxVolume(int streamType) {
         if (streamType == STREAM_MASTER) {
             return mAudioManager.getMasterMaxVolume();
-        } else if (streamType == AudioService.STREAM_REMOTE_MUSIC) {
+        } else if (streamType == STREAM_REMOTE_MUSIC) {
             if (mStreamControls != null) {
                 StreamControl sc = mStreamControls.get(streamType);
                 if (sc != null && sc.controller != null) {
@@ -549,7 +550,7 @@
     private int getStreamVolume(int streamType) {
         if (streamType == STREAM_MASTER) {
             return mAudioManager.getMasterVolume();
-        } else if (streamType == AudioService.STREAM_REMOTE_MUSIC) {
+        } else if (streamType == STREAM_REMOTE_MUSIC) {
             if (mStreamControls != null) {
                 StreamControl sc = mStreamControls.get(streamType);
                 if (sc != null && sc.controller != null) {
@@ -564,7 +565,7 @@
     }
 
     private void setStreamVolume(StreamControl sc, int index, int flags) {
-        if (sc.streamType == AudioService.STREAM_REMOTE_MUSIC) {
+        if (sc.streamType == STREAM_REMOTE_MUSIC) {
             if (sc.controller != null) {
                 sc.controller.setVolumeTo(index, flags);
             } else {
@@ -690,7 +691,7 @@
     private void updateSliderEnabled(final StreamControl sc, boolean muted, boolean fixedVolume) {
         final boolean wasEnabled = sc.seekbarView.isEnabled();
         final boolean isRinger = isNotificationOrRing(sc.streamType);
-        if (sc.streamType == AudioService.STREAM_REMOTE_MUSIC) {
+        if (sc.streamType == STREAM_REMOTE_MUSIC) {
             // never disable touch interactions for remote playback, the muting is not tied to
             // the state of the phone.
             sc.seekbarView.setEnabled(!fixedVolume);
@@ -805,7 +806,7 @@
 
     public void postRemoteSliderVisibility(boolean visible) {
         obtainMessage(MSG_SLIDER_VISIBILITY_CHANGED,
-                AudioService.STREAM_REMOTE_MUSIC, visible ? 1 : 0).sendToTarget();
+                STREAM_REMOTE_MUSIC, visible ? 1 : 0).sendToTarget();
     }
 
     /**
@@ -980,7 +981,7 @@
                 break;
             }
 
-            case AudioService.STREAM_REMOTE_MUSIC: {
+            case STREAM_REMOTE_MUSIC: {
                 if (controller == null && sc != null) {
                     // If we weren't passed one try using the last one set.
                     controller = sc.controller;
@@ -1003,7 +1004,7 @@
         }
 
         if (sc != null) {
-            if (streamType == AudioService.STREAM_REMOTE_MUSIC && controller != sc.controller) {
+            if (streamType == STREAM_REMOTE_MUSIC && controller != sc.controller) {
                 if (sc.controller != null) {
                     sc.controller.removeCallback(mMediaControllerCb);
                 }
@@ -1021,7 +1022,7 @@
         }
 
         if (!isShowing()) {
-            int stream = (streamType == AudioService.STREAM_REMOTE_MUSIC) ? -1 : streamType;
+            int stream = (streamType == STREAM_REMOTE_MUSIC) ? -1 : streamType;
             // when the stream is for remote playback, use -1 to reset the stream type evaluation
             mAudioManager.forceVolumeControlStream(stream);
             mDialog.show();
@@ -1031,7 +1032,7 @@
         }
 
         // Do a little vibrate if applicable (only when going into vibrate mode)
-        if ((streamType != AudioService.STREAM_REMOTE_MUSIC) &&
+        if ((streamType != STREAM_REMOTE_MUSIC) &&
                 ((flags & AudioManager.FLAG_VIBRATE) != 0) &&
                 mAudioManager.isStreamAffectedByRingerMode(streamType) &&
                 mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE) {
@@ -1094,10 +1095,10 @@
 
         if (((flags & AudioManager.FLAG_SHOW_UI) != 0) || isShowing()) {
             synchronized (this) {
-                if (mActiveStreamType != AudioService.STREAM_REMOTE_MUSIC) {
-                    reorderSliders(AudioService.STREAM_REMOTE_MUSIC);
+                if (mActiveStreamType != STREAM_REMOTE_MUSIC) {
+                    reorderSliders(STREAM_REMOTE_MUSIC);
                 }
-                onShowVolumeChanged(AudioService.STREAM_REMOTE_MUSIC, flags, controller);
+                onShowVolumeChanged(STREAM_REMOTE_MUSIC, flags, controller);
             }
         } else {
             if (LOGD) Log.d(mTag, "not calling onShowVolumeChanged(), no FLAG_SHOW_UI or no UI");
@@ -1111,9 +1112,9 @@
     protected void onRemoteVolumeUpdateIfShown() {
         if (LOGD) Log.d(mTag, "onRemoteVolumeUpdateIfShown()");
         if (isShowing()
-                && (mActiveStreamType == AudioService.STREAM_REMOTE_MUSIC)
+                && (mActiveStreamType == STREAM_REMOTE_MUSIC)
                 && (mStreamControls != null)) {
-            onShowVolumeChanged(AudioService.STREAM_REMOTE_MUSIC, 0, null);
+            onShowVolumeChanged(STREAM_REMOTE_MUSIC, 0, null);
         }
     }
 
@@ -1122,7 +1123,7 @@
      */
     private void clearRemoteStreamController() {
         if (mStreamControls != null) {
-            StreamControl sc = mStreamControls.get(AudioService.STREAM_REMOTE_MUSIC);
+            StreamControl sc = mStreamControls.get(STREAM_REMOTE_MUSIC);
             if (sc != null) {
                 if (sc.controller != null) {
                     sc.controller.removeCallback(mMediaControllerCb);
@@ -1133,10 +1134,10 @@
     }
 
     /**
-     * Handler for MSG_SLIDER_VISIBILITY_CHANGED
-     * Hide or show a slider
-     * @param streamType can be a valid stream type value, or VolumePanel.STREAM_MASTER,
-     *                   or AudioService.STREAM_REMOTE_MUSIC
+     * Handler for MSG_SLIDER_VISIBILITY_CHANGED Hide or show a slider
+     *
+     * @param streamType can be a valid stream type value, or
+     *            VolumePanel.STREAM_MASTER, or VolumePanel.STREAM_REMOTE_MUSIC
      * @param visible
      */
     synchronized protected void onSliderVisibilityChanged(int streamType, int visible) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
index 04a3b88..0586a83 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -1,6 +1,5 @@
 package com.android.systemui.volume;
 
-import android.app.ActivityManagerNative;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
@@ -18,10 +17,12 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Log;
+import android.view.WindowManagerGlobal;
 
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
 import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.statusbar.phone.PhoneStatusBar;
 import com.android.systemui.statusbar.policy.ZenModeController;
 import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
 
@@ -138,22 +139,8 @@
     private final Runnable mStartZenSettings = new Runnable() {
         @Override
         public void run() {
-            AsyncTask.execute(new Runnable() {
-                @Override
-                public void run() {
-                    try {
-                        // Dismiss the lock screen when Settings starts.
-                        ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
-                    } catch (RemoteException e) {
-                    }
-                    final Intent intent = ZenModePanel.ZEN_SETTINGS;
-                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
-                    mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
-
-                    // dismiss shade if showing
-                    mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
-                }
-            });
+            getComponent(PhoneStatusBar.class).startActivityDismissingKeyguard(
+                    ZenModePanel.ZEN_SETTINGS, true /* onlyProvisioned */, true /* dismissShade */);
             mPanel.postDismiss(mDismissDelay);
         }
     };
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index ca260ec..3f7c72e 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -845,16 +845,16 @@
                 break;
             case SHORT_PRESS_POWER_GO_TO_SLEEP:
                 mPowerManager.goToSleep(eventTime,
-                        PowerManager.GO_TO_SLEEP_REASON_USER, 0);
+                        PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
                 break;
             case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
                 mPowerManager.goToSleep(eventTime,
-                        PowerManager.GO_TO_SLEEP_REASON_USER,
+                        PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
                         PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
                 break;
             case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
                 mPowerManager.goToSleep(eventTime,
-                        PowerManager.GO_TO_SLEEP_REASON_USER,
+                        PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
                         PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
                 launchHomeFromHotKey();
                 break;
@@ -2064,8 +2064,11 @@
     }
 
     @Override
-    public Animation createForceHideEnterAnimation(boolean onWallpaper) {
-        if (onWallpaper) {
+    public Animation createForceHideEnterAnimation(boolean onWallpaper,
+            boolean goingToNotificationShade) {
+        if (goingToNotificationShade) {
+            return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in);
+        } else if (onWallpaper) {
             Animation a = AnimationUtils.loadAnimation(mContext,
                     R.anim.lock_screen_behind_enter_wallpaper);
             AnimationSet set = (AnimationSet) a;
@@ -2073,7 +2076,6 @@
             // TODO: Use XML interpolators when we have log interpolators available in XML.
             set.getAnimations().get(0).setInterpolator(mLogDecelerateInterpolator);
             set.getAnimations().get(1).setInterpolator(mLogDecelerateInterpolator);
-            set.getAnimations().get(2).setInterpolator(mLogDecelerateInterpolator);
             return set;
         } else {
             Animation a = AnimationUtils.loadAnimation(mContext,
@@ -2088,8 +2090,12 @@
 
 
     @Override
-    public Animation createForceHideWallpaperExitAnimation() {
-        return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit);
+    public Animation createForceHideWallpaperExitAnimation(boolean goingToNotificationShade) {
+        if (goingToNotificationShade) {
+            return null;
+        } else {
+            return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit);
+        }
     }
 
     private static void awakenDreams() {
@@ -4290,7 +4296,8 @@
                         }
                         if ((mEndcallBehavior
                                 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
-                            mPowerManager.goToSleep(event.getEventTime());
+                            mPowerManager.goToSleep(event.getEventTime(),
+                                    PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
                             isWakeKey = false;
                         }
                     }
@@ -4347,7 +4354,8 @@
                 if (!mPowerManager.isInteractive()) {
                     useHapticFeedback = false; // suppress feedback if already non-interactive
                 }
-                mPowerManager.goToSleep(event.getEventTime());
+                mPowerManager.goToSleep(event.getEventTime(),
+                        PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
                 isWakeKey = false;
                 break;
             }
@@ -4766,13 +4774,19 @@
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    if (mKeyguardDelegate.isDismissable()) {
-                        // Can we just finish the keyguard straight away?
-                        mKeyguardDelegate.keyguardDone(false, true);
-                    } else {
-                        // ask the keyguard to prompt the user to authenticate if necessary
-                        mKeyguardDelegate.dismiss();
-                    }
+                    // ask the keyguard to prompt the user to authenticate if necessary
+                    mKeyguardDelegate.dismiss();
+                }
+            });
+        }
+    }
+
+    public void notifyActivityDrawnForKeyguardLw() {
+        if (mKeyguardDelegate != null) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mKeyguardDelegate.onActivityDrawn();
                 }
             });
         }
@@ -5246,7 +5260,7 @@
     private void applyLidSwitchState() {
         if (mLidState == LID_CLOSED && mLidControlsSleep) {
             mPowerManager.goToSleep(SystemClock.uptimeMillis(),
-                    PowerManager.GO_TO_SLEEP_REASON_USER,
+                    PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
                     PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
         }
 
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
index 63a5850..aac02ad 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
@@ -334,4 +334,9 @@
         mKeyguardState.bootCompleted = true;
     }
 
+    public void onActivityDrawn() {
+        if (mKeyguardService != null) {
+            mKeyguardService.onActivityDrawn();
+        }
+    }
 }
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java
index 5096bd3..2778b15 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java
@@ -198,6 +198,14 @@
         }
     }
 
+    public void onActivityDrawn() {
+        try {
+            mService.onActivityDrawn();
+        } catch (RemoteException e) {
+            Slog.w(TAG , "Remote Exception", e);
+        }
+    }
+
     public void showAssistant() {
         // Not used by PhoneWindowManager
     }
diff --git a/rs/java/android/renderscript/Allocation.java b/rs/java/android/renderscript/Allocation.java
index ac76ddf..7db85f2 100644
--- a/rs/java/android/renderscript/Allocation.java
+++ b/rs/java/android/renderscript/Allocation.java
@@ -1341,9 +1341,13 @@
      * @param dimX The new size of the allocation.
      *
      * @deprecated RenderScript objects should be immutable once created.  The
-     * replacement is to create a new allocation and copy the contents.
+     * replacement is to create a new allocation and copy the contents. This
+     * function will throw an exception if API 21 or higher is used.
      */
     public synchronized void resize(int dimX) {
+        if (mRS.getApplicationContext().getApplicationInfo().targetSdkVersion >= 21) {
+            throw new RSRuntimeException("Resize is not allowed in API 21+.");
+        }
         if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
             throw new RSInvalidStateException("Resize only support for 1D allocations at this time.");
         }
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 21e56702..e9419ad 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -19,7 +19,6 @@
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
-import android.app.AlarmClockInfo;
 import android.app.AlarmManager;
 import android.app.IAlarmManager;
 import android.app.PendingIntent;
@@ -129,14 +128,17 @@
     long mStartCurrentDelayTime;
     long mNextNonWakeupDeliveryTime;
 
-    private final SparseArray<AlarmClockInfo> mNextAlarmClockForUser = new SparseArray<>();
-    private final SparseArray<AlarmClockInfo> mTmpSparseAlarmClockArray = new SparseArray<>();
+    private final SparseArray<AlarmManager.AlarmClockInfo> mNextAlarmClockForUser =
+            new SparseArray<>();
+    private final SparseArray<AlarmManager.AlarmClockInfo> mTmpSparseAlarmClockArray =
+            new SparseArray<>();
     private final SparseBooleanArray mPendingSendNextAlarmClockChangedForUser =
             new SparseBooleanArray();
     private boolean mNextAlarmClockMayChange;
 
     // May only use on mHandler's thread, locking not required.
-    private final SparseArray<AlarmClockInfo> mHandlerSparseAlarmClockArray = new SparseArray<>();
+    private final SparseArray<AlarmManager.AlarmClockInfo> mHandlerSparseAlarmClockArray =
+            new SparseArray<>();
 
     class WakeupEvent {
         public long when;
@@ -619,7 +621,7 @@
 
     void setImpl(int type, long triggerAtTime, long windowLength, long interval,
             PendingIntent operation, boolean isStandalone, WorkSource workSource,
-            AlarmClockInfo alarmClock) {
+            AlarmManager.AlarmClockInfo alarmClock) {
         if (operation == null) {
             Slog.w(TAG, "set/setRepeating ignored because there is no intent");
             return;
@@ -672,7 +674,8 @@
 
     private void setImplLocked(int type, long when, long whenElapsed, long windowLength,
             long maxWhen, long interval, PendingIntent operation, boolean isStandalone,
-            boolean doValidate, WorkSource workSource, AlarmClockInfo alarmClock, int userId) {
+            boolean doValidate, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock,
+            int userId) {
         Alarm a = new Alarm(type, when, whenElapsed, windowLength, maxWhen, interval,
                 operation, workSource, alarmClock, userId);
         removeLocked(operation);
@@ -714,7 +717,8 @@
     private final IBinder mService = new IAlarmManager.Stub() {
         @Override
         public void set(int type, long triggerAtTime, long windowLength, long interval,
-                PendingIntent operation, WorkSource workSource, AlarmClockInfo alarmClock) {
+                PendingIntent operation, WorkSource workSource,
+                AlarmManager.AlarmClockInfo alarmClock) {
             if (workSource != null) {
                 getContext().enforceCallingPermission(
                         android.Manifest.permission.UPDATE_DEVICE_STATS,
@@ -762,7 +766,7 @@
         }
 
         @Override
-        public AlarmClockInfo getNextAlarmClock(int userId) {
+        public AlarmManager.AlarmClockInfo getNextAlarmClock(int userId) {
             userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
                     Binder.getCallingUid(), userId, false /* allowAll */, false /* requireFull */,
                     "getNextAlarmClock", null);
@@ -1009,7 +1013,7 @@
         return null;
     }
 
-    private AlarmClockInfo getNextAlarmClockImpl(int userId) {
+    private AlarmManager.AlarmClockInfo getNextAlarmClockImpl(int userId) {
         synchronized (mLock) {
             return mNextAlarmClockForUser.get(userId);
         }
@@ -1024,7 +1028,7 @@
         }
         mNextAlarmClockMayChange = false;
 
-        SparseArray<AlarmClockInfo> nextForUser = mTmpSparseAlarmClockArray;
+        SparseArray<AlarmManager.AlarmClockInfo> nextForUser = mTmpSparseAlarmClockArray;
         nextForUser.clear();
 
         final int N = mAlarmBatches.size();
@@ -1054,9 +1058,9 @@
         // Update mNextAlarmForUser with new values.
         final int NN = nextForUser.size();
         for (int i = 0; i < NN; i++) {
-            AlarmClockInfo newAlarm = nextForUser.valueAt(i);
+            AlarmManager.AlarmClockInfo newAlarm = nextForUser.valueAt(i);
             int userId = nextForUser.keyAt(i);
-            AlarmClockInfo currentAlarm = mNextAlarmClockForUser.get(userId);
+            AlarmManager.AlarmClockInfo currentAlarm = mNextAlarmClockForUser.get(userId);
             if (!newAlarm.equals(currentAlarm)) {
                 updateNextAlarmInfoForUserLocked(userId, newAlarm);
             }
@@ -1072,7 +1076,8 @@
         }
     }
 
-    private void updateNextAlarmInfoForUserLocked(int userId, AlarmClockInfo alarmClock) {
+    private void updateNextAlarmInfoForUserLocked(int userId,
+            AlarmManager.AlarmClockInfo alarmClock) {
         if (alarmClock != null) {
             if (DEBUG_ALARM_CLOCK) {
                 Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): " +
@@ -1100,7 +1105,7 @@
      * @see AlarmHandler#SEND_NEXT_ALARM_CLOCK_CHANGED
      */
     private void sendNextAlarmClockChanged() {
-        SparseArray<AlarmClockInfo> pendingUsers = mHandlerSparseAlarmClockArray;
+        SparseArray<AlarmManager.AlarmClockInfo> pendingUsers = mHandlerSparseAlarmClockArray;
         pendingUsers.clear();
 
         synchronized (mLock) {
@@ -1115,7 +1120,7 @@
         final int N = pendingUsers.size();
         for (int i = 0; i < N; i++) {
             int userId = pendingUsers.keyAt(i);
-            AlarmClockInfo alarmClock = pendingUsers.valueAt(i);
+            AlarmManager.AlarmClockInfo alarmClock = pendingUsers.valueAt(i);
             Settings.System.putStringForUser(getContext().getContentResolver(),
                     Settings.System.NEXT_ALARM_FORMATTED,
                     formatNextAlarm(getContext(), alarmClock),
@@ -1129,7 +1134,7 @@
     /**
      * Formats an alarm like platform/packages/apps/DeskClock used to.
      */
-    private static String formatNextAlarm(final Context context, AlarmClockInfo info) {
+    private static String formatNextAlarm(final Context context, AlarmManager.AlarmClockInfo info) {
         String skeleton = DateFormat.is24HourFormat(context) ? "EHm" : "Ehma";
         String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
         return (info == null) ? "" :
@@ -1414,12 +1419,12 @@
         public long whenElapsed;    // 'when' in the elapsed time base
         public long maxWhen;        // also in the elapsed time base
         public long repeatInterval;
-        public final AlarmClockInfo alarmClock;
+        public final AlarmManager.AlarmClockInfo alarmClock;
         public final int userId;
 
         public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
-                long _interval, PendingIntent _op, WorkSource _ws, AlarmClockInfo _info,
-                int _userId) {
+                long _interval, PendingIntent _op, WorkSource _ws,
+                AlarmManager.AlarmClockInfo _info, int _userId) {
             type = _type;
             wakeup = _type == AlarmManager.ELAPSED_REALTIME_WAKEUP
                     || _type == AlarmManager.RTC_WAKEUP;
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index b229c4f3..dd5a7ea 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -372,6 +372,11 @@
      */
     private static final int EVENT_EXPIRE_NET_TRANSITION_WAKELOCK = 24;
 
+    /**
+     * Used internally to indicate the system is ready.
+     */
+    private static final int EVENT_SYSTEM_READY = 25;
+
 
     /** Handler used for internal events. */
     final private InternalHandler mHandler;
@@ -1437,6 +1442,8 @@
             final IntentFilter filter = new IntentFilter(Intent.ACTION_USER_PRESENT);
             mContext.registerReceiver(mUserPresentReceiver, filter);
         }
+
+        mHandler.sendMessage(mHandler.obtainMessage(EVENT_SYSTEM_READY));
     }
 
     private BroadcastReceiver mUserPresentReceiver = new BroadcastReceiver() {
@@ -2270,6 +2277,12 @@
                     handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.arg1);
                     break;
                 }
+                case EVENT_SYSTEM_READY: {
+                    for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
+                        nai.networkMonitor.systemReady = true;
+                    }
+                    break;
+                }
             }
         }
     }
@@ -4108,6 +4121,9 @@
             new NetworkInfo(networkInfo), new LinkProperties(linkProperties),
             new NetworkCapabilities(networkCapabilities), currentScore, mContext, mTrackerHandler,
             networkMisc);
+        synchronized (this) {
+            nai.networkMonitor.systemReady = mSystemReady;
+        }
         if (VDBG) log("registerNetworkAgent " + nai);
         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));
     }
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 4c6b772..6ab52c6 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -479,7 +479,7 @@
         // keep screen on when charging and in car mode
         boolean keepScreenOn = mCharging &&
                 ((mCarModeEnabled && mCarModeKeepsScreenOn &&
-                  (mCarModeEnableFlags & UiModeManager.ENABLE_CAR_MODE_NO_WAKE_LOCK) == 0) ||
+                  (mCarModeEnableFlags & UiModeManager.ENABLE_CAR_MODE_ALLOW_SLEEP) == 0) ||
                  (mCurUiMode == Configuration.UI_MODE_TYPE_DESK && mDeskModeKeepsScreenOn));
         if (keepScreenOn != mWakeLock.isHeld()) {
             if (keepScreenOn) {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index d6e51f3..0bdb964 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -24,6 +24,7 @@
 import java.util.Iterator;
 import java.util.List;
 
+import android.os.DeadObjectException;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.SystemProperties;
@@ -1424,6 +1425,9 @@
                     app.repProcState);
             r.postNotification();
             created = true;
+        } catch (DeadObjectException e) {
+            Slog.w(TAG, "Application dead when creating service " + r);
+            mAm.appDiedLocked(app);
         } finally {
             if (!created) {
                 app.services.remove(r);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 6054401..ad2704a 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4201,6 +4201,10 @@
         }
     }
 
+    final void appDiedLocked(ProcessRecord app) {
+       appDiedLocked(app, app.pid, app.thread);
+    }
+
     final void appDiedLocked(ProcessRecord app, int pid,
             IApplicationThread thread) {
 
@@ -5639,17 +5643,13 @@
     }
 
     @Override
-    public void dismissKeyguardOnNextActivity() {
-        enforceNotIsolatedCaller("dismissKeyguardOnNextActivity");
+    public void keyguardWaitingForActivityDrawn() {
+        enforceNotIsolatedCaller("keyguardWaitingForActivityDrawn");
         final long token = Binder.clearCallingIdentity();
         try {
             synchronized (this) {
                 if (DEBUG_LOCKSCREEN) logLockScreen("");
-                if (mLockScreenShown) {
-                    mLockScreenShown = false;
-                    comeOutOfSleepIfNeededLocked();
-                }
-                mStackSupervisor.setDismissKeyguard(true);
+                mWindowManager.keyguardWaitingForActivityDrawn();
             }
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -5794,13 +5794,13 @@
     }
 
     @Override
-    public final void mediaResourcesReleased(IBinder token) {
+    public final void backgroundResourcesReleased(IBinder token) {
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized (this) {
                 ActivityStack stack = ActivityRecord.getStackLocked(token);
                 if (stack != null) {
-                    stack.mediaResourcesReleased(token);
+                    stack.backgroundResourcesReleased(token);
                 }
             }
         } finally {
@@ -8478,7 +8478,7 @@
                                 "Existing provider " + cpr.name.flattenToShortString()
                                 + " is crashing; detaching " + r);
                         boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);
-                        appDiedLocked(cpr.proc, cpr.proc.pid, cpr.proc.thread);
+                        appDiedLocked(cpr.proc);
                         if (!lastRef) {
                             // This wasn't the last ref our process had on
                             // the provider...  we have now been killed, bail.
@@ -8928,7 +8928,7 @@
                     + ") early provider death");
             final long ident = Binder.clearCallingIdentity();
             try {
-                appDiedLocked(proc, proc.pid, proc.thread);
+                appDiedLocked(proc);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -9263,8 +9263,7 @@
     void logLockScreen(String msg) {
         if (DEBUG_LOCKSCREEN) Slog.d(TAG, Debug.getCallers(2) + ":" + msg +
                 " mLockScreenShown=" + mLockScreenShown + " mWentToSleep=" +
-                mWentToSleep + " mSleeping=" + mSleeping + " mDismissKeyguardOnNextActivity=" +
-                mStackSupervisor.mDismissKeyguardOnNextActivity);
+                mWentToSleep + " mSleeping=" + mSleeping);
     }
 
     private void comeOutOfSleepIfNeededLocked() {
@@ -9663,7 +9662,7 @@
                 }
                 if (r.changeWindowTranslucency(true)) {
                     mWindowManager.setAppFullscreen(token, true);
-                    r.task.stack.releaseMediaResources();
+                    r.task.stack.releaseBackgroundResources();
                     mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
                     return true;
                 }
@@ -9704,13 +9703,13 @@
     }
 
     @Override
-    public boolean setMediaPlaying(IBinder token, boolean playing) {
+    public boolean requestVisibleBehind(IBinder token, boolean visible) {
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized (this) {
                 final ActivityRecord r = ActivityRecord.isInStackLocked(token);
                 if (r != null) {
-                    return mStackSupervisor.setMediaPlayingLocked(r, playing);
+                    return mStackSupervisor.requestVisibleBehindLocked(r, visible);
                 }
             }
             return false;
@@ -9720,15 +9719,15 @@
     }
 
     @Override
-    public boolean isBackgroundMediaPlaying(IBinder token) {
+    public boolean isBackgroundVisibleBehind(IBinder token) {
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized (this) {
                 final ActivityStack stack = ActivityRecord.getStackLocked(token);
-                final boolean playing = stack == null ? false : stack.isMediaPlaying();
-                if (ActivityStackSupervisor.DEBUG_MEDIA_VISIBILITY) Slog.d(TAG,
-                        "isBackgroundMediaPlaying: stack=" + stack + " playing=" + playing);
-                return playing;
+                final boolean visible = stack == null ? false : stack.hasVisibleBehindActivity();
+                if (ActivityStackSupervisor.DEBUG_VISIBLE_BEHIND) Slog.d(TAG,
+                        "isBackgroundVisibleBehind: stack=" + stack + " visible=" + visible);
+                return visible;
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 4653742..e309a03 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -46,7 +46,6 @@
 import com.android.server.Watchdog;
 import com.android.server.am.ActivityManagerService.ItemMatcher;
 import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
-import com.android.server.am.ActivityStackSupervisor.ActivityDisplay;
 import com.android.server.wm.AppTransition;
 import com.android.server.wm.TaskGroup;
 import com.android.server.wm.WindowManagerService;
@@ -249,7 +248,7 @@
     static final int STOP_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 4;
     static final int DESTROY_ACTIVITIES_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 5;
     static final int TRANSLUCENT_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 6;
-    static final int STOP_MEDIA_PLAYING_TIMEOUT_MSG =
+    static final int RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG =
             ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 7;
 
     static class ScheduleDestroyArgs {
@@ -325,10 +324,10 @@
                         notifyActivityDrawnLocked(null);
                     }
                 } break;
-                case STOP_MEDIA_PLAYING_TIMEOUT_MSG: {
+                case RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG: {
                     synchronized (mService) {
-                        final ActivityRecord r = getMediaPlayer();
-                        Slog.e(TAG, "Timeout waiting for stopMediaPlaying player=" + r);
+                        final ActivityRecord r = getVisibleBehindActivity();
+                        Slog.e(TAG, "Timeout waiting for cancelVisibleBehind player=" + r);
                         if (r != null) {
                             mService.killAppAtUsersRequest(r.app, null);
                         }
@@ -935,8 +934,8 @@
             mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
             r.stopped = true;
             r.state = ActivityState.STOPPED;
-            if (mActivityContainer.mActivityDisplay.mMediaPlayingActivity == r) {
-                mStackSupervisor.setMediaPlayingLocked(r, false);
+            if (mActivityContainer.mActivityDisplay.mVisibleBehindActivity == r) {
+                mStackSupervisor.requestVisibleBehindLocked(r, false);
             }
             if (r.finishing) {
                 r.clearOptionsLocked();
@@ -975,8 +974,8 @@
                     // the current instance before starting the new one.
                     if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
                     destroyActivityLocked(prev, true, "pause-config");
-                } else if (!isMediaPlaying()) {
-                    // If we were playing then resumeTopActivities will release resources before
+                } else if (!hasVisibleBehindActivity()) {
+                    // If we were visible then resumeTopActivities will release resources before
                     // stopping.
                     mStackSupervisor.mStoppingActivities.add(prev);
                     if (mStackSupervisor.mStoppingActivities.size() > 3 ||
@@ -1059,7 +1058,7 @@
 
         if (next.nowVisible) {
             // We won't get a call to reportActivityVisibleLocked() so dismiss lockscreen now.
-            mStackSupervisor.dismissKeyguard();
+            mStackSupervisor.notifyActivityDrawnForKeyguard();
         }
 
         // schedule an idle timeout in case the app doesn't do it for us.
@@ -1333,8 +1332,8 @@
                                 case PAUSED:
                                     // This case created for transitioning activities from
                                     // translucent to opaque {@link Activity#convertToOpaque}.
-                                    if (getMediaPlayer() == r) {
-                                        releaseMediaResources();
+                                    if (getVisibleBehindActivity() == r) {
+                                        releaseBackgroundResources();
                                     } else {
                                         if (!mStackSupervisor.mStoppingActivities.contains(r)) {
                                             mStackSupervisor.mStoppingActivities.add(r);
@@ -2937,8 +2936,8 @@
 
         // Get rid of any pending idle timeouts.
         removeTimeoutsForActivityLocked(r);
-        if (getMediaPlayer() == r) {
-            mStackSupervisor.setMediaPlayingLocked(r, false);
+        if (getVisibleBehindActivity() == r) {
+            mStackSupervisor.requestVisibleBehindLocked(r, false);
         }
     }
 
@@ -3160,47 +3159,48 @@
         }
     }
 
-    void releaseMediaResources() {
-        if (isMediaPlaying() && !mHandler.hasMessages(STOP_MEDIA_PLAYING_TIMEOUT_MSG)) {
-            final ActivityRecord r = getMediaPlayer();
-            if (DEBUG_STATES) Slog.d(TAG, "releaseMediaResources activtyDisplay=" +
-                    mActivityContainer.mActivityDisplay + " mediaPlayer=" + r + " app=" + r.app +
+    void releaseBackgroundResources() {
+        if (hasVisibleBehindActivity() &&
+                !mHandler.hasMessages(RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG)) {
+            final ActivityRecord r = getVisibleBehindActivity();
+            if (DEBUG_STATES) Slog.d(TAG, "releaseBackgroundResources activtyDisplay=" +
+                    mActivityContainer.mActivityDisplay + " visibleBehind=" + r + " app=" + r.app +
                     " thread=" + r.app.thread);
             if (r != null && r.app != null && r.app.thread != null) {
                 try {
-                    r.app.thread.scheduleStopMediaPlaying(r.appToken);
+                    r.app.thread.scheduleCancelVisibleBehind(r.appToken);
                 } catch (RemoteException e) {
                 }
-                mHandler.sendEmptyMessageDelayed(STOP_MEDIA_PLAYING_TIMEOUT_MSG, 500);
+                mHandler.sendEmptyMessageDelayed(RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG, 500);
             } else {
-                Slog.e(TAG, "releaseMediaResources: activity " + r + " no longer running");
-                mediaResourcesReleased(r.appToken);
+                Slog.e(TAG, "releaseBackgroundResources: activity " + r + " no longer running");
+                backgroundResourcesReleased(r.appToken);
             }
         }
     }
 
-    final void mediaResourcesReleased(IBinder token) {
-        mHandler.removeMessages(STOP_MEDIA_PLAYING_TIMEOUT_MSG);
-        final ActivityRecord r = getMediaPlayer();
+    final void backgroundResourcesReleased(IBinder token) {
+        mHandler.removeMessages(RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG);
+        final ActivityRecord r = getVisibleBehindActivity();
         if (r != null) {
             mStackSupervisor.mStoppingActivities.add(r);
-            setMediaPlayer(null);
+            setVisibleBehindActivity(null);
         }
         mStackSupervisor.resumeTopActivitiesLocked();
     }
 
-    boolean isMediaPlaying() {
-        return isAttached() && mActivityContainer.mActivityDisplay.isMediaPlaying();
+    boolean hasVisibleBehindActivity() {
+        return isAttached() && mActivityContainer.mActivityDisplay.hasVisibleBehindActivity();
     }
 
-    void setMediaPlayer(ActivityRecord r) {
+    void setVisibleBehindActivity(ActivityRecord r) {
         if (isAttached()) {
-            mActivityContainer.mActivityDisplay.setMediaPlaying(r);
+            mActivityContainer.mActivityDisplay.setVisibleBehindActivity(r);
         }
     }
 
-    ActivityRecord getMediaPlayer() {
-        return isAttached() ? mActivityContainer.mActivityDisplay.mMediaPlayingActivity : null;
+    ActivityRecord getVisibleBehindActivity() {
+        return isAttached() ? mActivityContainer.mActivityDisplay.mVisibleBehindActivity : null;
     }
 
     private void removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list,
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 3d23cb7..1107139 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -115,7 +115,7 @@
     static final boolean DEBUG_APP = DEBUG || false;
     static final boolean DEBUG_CONTAINERS = DEBUG || false;
     static final boolean DEBUG_IDLE = DEBUG || false;
-    static final boolean DEBUG_MEDIA_VISIBILITY = DEBUG || false;
+    static final boolean DEBUG_VISIBLE_BEHIND = DEBUG || false;
     static final boolean DEBUG_SAVED_STATE = DEBUG || false;
     static final boolean DEBUG_SCREENSHOTS = DEBUG || false;
     static final boolean DEBUG_STATES = DEBUG || false;
@@ -167,9 +167,6 @@
     WindowManagerService mWindowManager;
     DisplayManager mDisplayManager;
 
-    /** Dismiss the keyguard after the next activity is displayed? */
-    boolean mDismissKeyguardOnNextActivity = false;
-
     /** Identifier counter for all ActivityStacks */
     private int mLastStackId = HOME_STACK_ID;
 
@@ -363,12 +360,9 @@
         }
     }
 
-    void dismissKeyguard() {
+    void notifyActivityDrawnForKeyguard() {
         if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
-        if (mDismissKeyguardOnNextActivity) {
-            mDismissKeyguardOnNextActivity = false;
-            mWindowManager.dismissKeyguard();
-        }
+        mWindowManager.notifyActivityDrawnForKeyguard();
     }
 
     ActivityStack getFocusedStack() {
@@ -439,9 +433,8 @@
         return mService.startHomeActivityLocked(mCurrentUser);
     }
 
-    void setDismissKeyguard(boolean dismiss) {
-        if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen(" dismiss=" + dismiss);
-        mDismissKeyguardOnNextActivity = dismiss;
+    void keyguardWaitingForActivityDrawn() {
+        mWindowManager.keyguardWaitingForActivityDrawn();
     }
 
     TaskRecord anyTaskForIdLocked(int id) {
@@ -660,7 +653,7 @@
             w.thisTime = w.totalTime;
         }
         mService.notifyAll();
-        dismissKeyguard();
+        notifyActivityDrawnForKeyguard();
     }
 
     void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
@@ -1165,7 +1158,7 @@
                 Slog.e(TAG, "Second failure launching "
                       + r.intent.getComponent().flattenToShortString()
                       + ", giving up", e);
-                mService.appDiedLocked(app, app.pid, app.thread);
+                mService.appDiedLocked(app);
                 stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
                         "2nd-crash", false);
                 return false;
@@ -1371,7 +1364,6 @@
                     resultRecord, resultWho, requestCode,
                     Activity.RESULT_CANCELED, null);
             }
-            setDismissKeyguard(false);
             ActivityOptions.abort(options);
             return err;
         }
@@ -1386,7 +1378,6 @@
                     resultRecord, resultWho, requestCode,
                     Activity.RESULT_CANCELED, null);
             }
-            setDismissKeyguard(false);
             String msg;
             if (!aInfo.exported) {
                 msg = "Permission Denial: starting " + intent.toString()
@@ -1425,7 +1416,6 @@
             }
             // We pretend to the caller that it was really started, but
             // they will just get a cancel result.
-            setDismissKeyguard(false);
             ActivityOptions.abort(options);
             return ActivityManager.START_SUCCESS;
         }
@@ -1444,7 +1434,6 @@
                 PendingActivityLaunch pal =
                         new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
                 mPendingActivityLaunches.add(pal);
-                setDismissKeyguard(false);
                 ActivityOptions.abort(options);
                 return ActivityManager.START_SWITCHES_CANCELED;
             }
@@ -1466,12 +1455,12 @@
         err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
                 startFlags, true, options);
 
-        if (allPausedActivitiesComplete()) {
+        if (err < 0) {
             // If someone asked to have the keyguard dismissed on the next
             // activity start, but we are not actually doing an activity
             // switch...  just dismiss the keyguard now, because we
             // probably want to see whatever is behind it.
-            dismissKeyguard();
+            notifyActivityDrawnForKeyguard();
         }
         return err;
     }
@@ -1554,6 +1543,7 @@
         final Intent intent = r.intent;
         final int callingUid = r.launchedFromUid;
 
+        final boolean launchSingleTop = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP;
         final boolean launchSingleInstance = r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE;
         final boolean launchSingleTask = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK;
 
@@ -1809,8 +1799,7 @@
                         // If the top activity in the task is the root
                         // activity, deliver this new intent to it if it
                         // desires.
-                        if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
-                                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
+                        if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0 || launchSingleTop)
                                 && intentActivity.realActivity.equals(r.realActivity)) {
                             ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
                                     intentActivity.task);
@@ -1874,7 +1863,7 @@
                 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
                     if (top.app != null && top.app.thread != null) {
                         if ((launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
-                            || launchSingleInstance || launchSingleTask) {
+                            || launchSingleTop || launchSingleTask) {
                             ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
                                     top.task);
                             // For paranoia, make sure we have correctly
@@ -2651,21 +2640,21 @@
         }
     }
 
-    boolean setMediaPlayingLocked(ActivityRecord r, boolean playing) {
+    boolean requestVisibleBehindLocked(ActivityRecord r, boolean visible) {
         final ActivityStack stack = r.task.stack;
         if (stack == null) {
-            if (DEBUG_MEDIA_VISIBILITY) Slog.d(TAG, "setMediaPlaying: r=" + r + " playing=" +
-                    playing + " stack is null");
+            if (DEBUG_VISIBLE_BEHIND) Slog.d(TAG, "requestVisibleBehind: r=" + r + " visible=" +
+                    visible + " stack is null");
             return false;
         }
-        final boolean isPlaying = stack.isMediaPlaying();
-        if (DEBUG_MEDIA_VISIBILITY) Slog.d(TAG, "setMediaPlayer: r=" + r + " playing=" +
-                playing + " isPlaying=" + isPlaying);
+        final boolean isVisible = stack.hasVisibleBehindActivity();
+        if (DEBUG_VISIBLE_BEHIND) Slog.d(TAG, "requestVisibleBehind r=" + r + " visible=" +
+                visible + " isVisible=" + isVisible);
 
         final ActivityRecord top = topRunningActivityLocked();
-        if (top == null || top == r || (playing == isPlaying)) {
-            if (DEBUG_MEDIA_VISIBILITY) Slog.d(TAG, "setMediaPlaying: quick return");
-            stack.setMediaPlayer(playing ? r : null);
+        if (top == null || top == r || (visible == isVisible)) {
+            if (DEBUG_VISIBLE_BEHIND) Slog.d(TAG, "requestVisibleBehind: quick return");
+            stack.setVisibleBehindActivity(visible ? r : null);
             return true;
         }
 
@@ -2673,14 +2662,14 @@
         if (top.fullscreen || top.state != ActivityState.RESUMED || top.app == null ||
                 top.app.thread == null) {
             // Can't carry out this request.
-            if (DEBUG_MEDIA_VISIBILITY) Slog.d(TAG, "setMediaPlaying: returning top.fullscreen=" +
-                    top.fullscreen+ " top.state=" + top.state + " top.app=" + top.app +
+            if (DEBUG_VISIBLE_BEHIND) Slog.d(TAG, "requestVisibleBehind: returning top.fullscreen="
+                    + top.fullscreen+ " top.state=" + top.state + " top.app=" + top.app +
                     " top.app.thread=" + top.app.thread);
             return false;
         }
 
-        stack.setMediaPlayer(playing ? r : null);
-        if (!playing) {
+        stack.setVisibleBehindActivity(visible ? r : null);
+        if (!visible) {
             // Make the activity immediately above r opaque.
             final ActivityRecord next = stack.findNextTranslucentActivity(r);
             if (next != null) {
@@ -2688,7 +2677,7 @@
             }
         }
         try {
-            top.app.thread.scheduleBackgroundMediaPlayingChanged(top.appToken, playing);
+            top.app.thread.scheduleBackgroundVisibleBehindChanged(top.appToken, visible);
         } catch (RemoteException e) {
         }
         return true;
@@ -2852,8 +2841,6 @@
     }
 
     public void dump(PrintWriter pw, String prefix) {
-        pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity=");
-                pw.println(mDismissKeyguardOnNextActivity);
         pw.print(prefix); pw.print("mFocusedStack=" + mFocusedStack);
                 pw.print(" mLastFocusedStack="); pw.println(mLastFocusedStack);
         pw.print(prefix); pw.println("mSleepTimeout=" + mSleepTimeout);
@@ -3715,7 +3702,7 @@
          * stacks, bottommost behind. Accessed directly by ActivityManager package classes */
         final ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
 
-        ActivityRecord mMediaPlayingActivity;
+        ActivityRecord mVisibleBehindActivity;
 
         ActivityDisplay() {
         }
@@ -3748,12 +3735,12 @@
             bounds.y = mDisplayInfo.appHeight;
         }
 
-        void setMediaPlaying(ActivityRecord r) {
-            mMediaPlayingActivity = r;
+        void setVisibleBehindActivity(ActivityRecord r) {
+            mVisibleBehindActivity = r;
         }
 
-        boolean isMediaPlaying() {
-            return mMediaPlayingActivity != null;
+        boolean hasVisibleBehindActivity() {
+            return mVisibleBehindActivity != null;
         }
 
         @Override
diff --git a/services/core/java/com/android/server/am/LockTaskNotify.java b/services/core/java/com/android/server/am/LockTaskNotify.java
index 6f9b23d..cf65243 100644
--- a/services/core/java/com/android/server/am/LockTaskNotify.java
+++ b/services/core/java/com/android/server/am/LockTaskNotify.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.os.Handler;
 import android.os.Message;
+import android.view.accessibility.AccessibilityManager;
 import android.widget.Toast;
 
 import com.android.internal.R;
@@ -32,9 +33,12 @@
 
     private final Context mContext;
     private final H mHandler;
+    private AccessibilityManager mAccessibilityManager;
 
     public LockTaskNotify(Context context) {
         mContext = context;
+        mAccessibilityManager = (AccessibilityManager)
+                mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
         mHandler = new H();
     }
 
@@ -45,6 +49,9 @@
     public void handleShowToast(boolean isLocked) {
         String text = mContext.getString(isLocked
                 ? R.string.lock_to_app_toast_locked : R.string.lock_to_app_toast);
+        if (!isLocked && mAccessibilityManager.isEnabled()) {
+            text = mContext.getString(R.string.lock_to_app_toast_accessible);
+        }
         Toast.makeText(mContext, text, Toast.LENGTH_LONG).show();
     }
 
diff --git a/services/core/java/com/android/server/am/LockToAppRequestDialog.java b/services/core/java/com/android/server/am/LockToAppRequestDialog.java
index 0847b52..12dcf7e 100644
--- a/services/core/java/com/android/server/am/LockToAppRequestDialog.java
+++ b/services/core/java/com/android/server/am/LockToAppRequestDialog.java
@@ -13,6 +13,7 @@
 import android.provider.Settings.SettingNotFoundException;
 import android.util.Slog;
 import android.view.WindowManager;
+import android.view.accessibility.AccessibilityManager;
 import android.widget.CheckBox;
 
 import com.android.internal.R;
@@ -33,8 +34,12 @@
 
     private ILockSettings mLockSettingsService;
 
+    private AccessibilityManager mAccessibilityService;
+
     public LockToAppRequestDialog(Context context, ActivityManagerService activityManagerService) {
         mContext = context;
+        mAccessibilityService = (AccessibilityManager)
+                mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
         mService = activityManagerService;
     }
 
@@ -78,7 +83,9 @@
         final int unlockStringId = getLockString(task.userId);
 
         final Resources r = Resources.getSystem();
-        final String description= r.getString(R.string.lock_to_app_description);
+        final String description= r.getString(mAccessibilityService.isEnabled()
+                ? R.string.lock_to_app_description_accessible
+                : R.string.lock_to_app_description);
         AlertDialog.Builder builder = new AlertDialog.Builder(mContext)
                         .setTitle(r.getString(R.string.lock_to_app_title))
                         .setMessage(description)
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index ae5eda3..5057994 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -217,6 +217,8 @@
     private String mServer;
     private boolean mIsCaptivePortalCheckEnabled = false;
 
+    public boolean systemReady = false;
+
     private State mDefaultState = new DefaultState();
     private State mOfflineState = new OfflineState();
     private State mValidatedState = new ValidatedState();
@@ -709,6 +711,8 @@
             return;
         }
 
+        if (systemReady == false) return;
+
         Intent latencyBroadcast = new Intent(ACTION_NETWORK_CONDITIONS_MEASURED);
         switch (mNetworkAgentInfo.networkInfo.getType()) {
             case ConnectivityManager.TYPE_WIFI:
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index 72ac29a..e39f0b1 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -265,7 +265,7 @@
                     mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE
                             | DisplayDeviceInfo.FLAG_NEVER_BLANK;
                 }
-                if ((mInfo.flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
+                if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
                     mInfo.flags &= ~DisplayDeviceInfo.FLAG_NEVER_BLANK;
                 } else {
                     mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY;
diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java
index 591cf25..2407253 100644
--- a/services/core/java/com/android/server/hdmi/Constants.java
+++ b/services/core/java/com/android/server/hdmi/Constants.java
@@ -258,6 +258,12 @@
     static final int MHL_RAP_ACTION_CONTENT_ON = 0x10;
     static final int MHL_RAP_ACTION_CONTENT_OFF = 0x11;
 
+    // MHL RAPK messages.
+    static final int MHL_RAPK_NO_ERROR = 0x00;
+    static final int MHL_RAPK_UNRECOGNIZED_ACTION = 0x01;
+    static final int MHL_RAPK_UNSUPPORTED_ACTION = 0x02;
+    static final int MHL_RAPK_RESPONDER_BUSY = 0x03;
+
     static final int MHL_INVALID_ADOPTER_ID = -1;
     static final int MHL_INVALID_DEVICE_ID = -1;
 
diff --git a/services/core/java/com/android/server/hdmi/DeviceSelectAction.java b/services/core/java/com/android/server/hdmi/DeviceSelectAction.java
index ed37ead..d155e84 100644
--- a/services/core/java/com/android/server/hdmi/DeviceSelectAction.java
+++ b/services/core/java/com/android/server/hdmi/DeviceSelectAction.java
@@ -23,7 +23,6 @@
 import android.os.RemoteException;
 import android.util.Slog;
 
-import com.android.server.hdmi.HdmiCecLocalDevice.ActiveSource;
 import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
 
 /**
@@ -42,9 +41,6 @@
     // Time in milliseconds we wait for the device power status to turn to 'On'.
     private static final int TIMEOUT_POWER_ON_MS = 5 * 1000;
 
-    // Time in milliseconds we wait for <Active Source>.
-    private static final int TIMEOUT_ACTIVE_SOURCE_MS = 20 * 1000;
-
     // The number of times we try to wake up the target device before we give up
     // and just send <Set Stream Path>.
     private static final int LOOP_COUNTER_MAX = 20;
@@ -62,11 +58,6 @@
     // maximum 100 seconds (20 * 5) before we give up and just send <Set Stream Path>.
     private static final int STATE_WAIT_FOR_DEVICE_POWER_ON = 3;
 
-    // State in which we wait for the <Active Source> in response to the command
-    // <Set Stream Path> we have sent. We wait as much as TIMEOUT_ACTIVE_SOURCE_MS
-    // before we give up and mark the action as failure.
-    private static final int STATE_WAIT_FOR_ACTIVE_SOURCE = 4;
-
     private final HdmiDeviceInfo mTarget;
     private final IHdmiControlCallback mCallback;
     private final HdmiCecMessage mGivePowerStatus;
@@ -129,16 +120,6 @@
                     return handleReportPowerStatus(params[0]);
                 }
                 return false;
-            case STATE_WAIT_FOR_ACTIVE_SOURCE:
-                if (opcode == Constants.MESSAGE_ACTIVE_SOURCE) {
-                    int physicalAddress = HdmiUtils.twoBytesToInt(params);
-                    ActiveSourceHandler
-                            .create((HdmiCecLocalDeviceTv) localDevice(), mCallback)
-                            .process(ActiveSource.of(cmd.getSource(), physicalAddress));
-                    finish();
-                    return true;
-                }
-                return false;
             default:
                 break;
         }
@@ -189,8 +170,8 @@
     private void sendSetStreamPath() {
         sendCommand(HdmiCecMessageBuilder.buildSetStreamPath(
                 getSourceAddress(), mTarget.getPhysicalAddress()));
-        mState = STATE_WAIT_FOR_ACTIVE_SOURCE;
-        addTimer(mState, TIMEOUT_ACTIVE_SOURCE_MS);
+        invokeCallback(HdmiControlManager.RESULT_SUCCESS);
+        finish();
     }
 
     @Override
@@ -213,10 +194,6 @@
                 mPowerStatusCounter++;
                 queryDevicePowerStatus();
                 break;
-            case STATE_WAIT_FOR_ACTIVE_SOURCE:
-                invokeCallback(HdmiControlManager.RESULT_TIMEOUT);
-                finish();
-                break;
         }
     }
 
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 0e57afd..2818ea7 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -198,6 +198,10 @@
     @GuardedBy("mLock")
     private boolean mProhibitMode;
 
+    // Set to true while the input change by MHL is allowed.
+    @GuardedBy("mLock")
+    private boolean mMhlInputChangeEnabled;
+
     // List of listeners registered by callers that want to get notified of
     // system audio mode changes.
     private final ArrayList<IHdmiSystemAudioModeChangeListener>
@@ -269,6 +273,7 @@
         mPowerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON;
         mProhibitMode = false;
         mHdmiControlEnabled = readBooleanSetting(Global.HDMI_CONTROL_ENABLED, true);
+        mMhlInputChangeEnabled = readBooleanSetting(Global.MHL_INPUT_SWITCHING_ENABLED, true);
 
         mCecController = HdmiCecController.create(this);
         if (mCecController != null) {
@@ -353,10 +358,12 @@
                     // No need to propagate to HAL.
                     break;
                 case Global.MHL_INPUT_SWITCHING_ENABLED:
-                    setOption(OPTION_MHL_INPUT_SWITCHING, toInt(enabled));
+                    setMhlInputChangeEnabled(enabled);
                     break;
                 case Global.MHL_POWER_CHARGE_ENABLED:
-                    setOption(OPTION_MHL_POWER_CHARGE, toInt(enabled));
+                    if (mMhlController != null) {
+                        mMhlController.setOption(OPTION_MHL_POWER_CHARGE, toInt(enabled));
+                    }
                     break;
             }
         }
@@ -1578,7 +1585,7 @@
         assertRunOnServiceThread();
         mStandbyMessageReceived = true;
         PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
-        pm.goToSleep(SystemClock.uptimeMillis());
+        pm.goToSleep(SystemClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_HDMI, 0);
         // PowerManger will send the broadcast Intent.ACTION_SCREEN_OFF and after this gets
         // the intent, the sequence will continue at onStandby().
     }
@@ -1741,4 +1748,20 @@
         assertRunOnServiceThread();
         mActivePortId = portId;
     }
+
+    void setMhlInputChangeEnabled(boolean enabled) {
+        if (mMhlController != null) {
+            mMhlController.setOption(OPTION_MHL_INPUT_SWITCHING, toInt(enabled));
+        }
+
+        synchronized (mLock) {
+            mMhlInputChangeEnabled = enabled;
+        }
+    }
+
+    boolean isMhlInputChangeEnabled() {
+        synchronized (mLock) {
+            return mMhlInputChangeEnabled;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java
index 058a23e..753ae39 100644
--- a/services/core/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/core/java/com/android/server/location/GpsLocationProvider.java
@@ -221,6 +221,14 @@
     private static final int GPS_GEOFENCE_ERROR_INVALID_TRANSITION = -103;
     private static final int GPS_GEOFENCE_ERROR_GENERIC = -149;
 
+    // Value of batterySaverGpsMode such that GPS isn't affected by battery saver mode.
+    private static final int BATTERY_SAVER_MODE_NO_CHANGE = 0;
+    // Value of batterySaverGpsMode such that GPS is disabled when battery saver mode
+    // is enabled and the screen is off.
+    private static final int BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF = 1;
+    // Secure setting for GPS behavior when battery saver mode is on.
+    private static final String BATTERY_SAVER_GPS_MODE = "batterySaverGpsMode";
+
     /** simpler wrapper for ProviderRequest + Worksource */
     private static class GpsRequest {
         public ProviderRequest request;
@@ -308,6 +316,13 @@
 
     private int mPositionMode;
 
+    // Current request from underlying location clients.
+    private ProviderRequest mProviderRequest = null;
+    // Current list of underlying location clients.
+    private WorkSource mWorkSource = null;
+    // True if gps should be disabled (used to support battery saver mode in settings).
+    private boolean mDisableGps = false;
+
     // properties loaded from PROPERTIES_FILE
     private Properties mProperties;
     private String mSuplServerHost;
@@ -352,6 +367,7 @@
     // Alarms
     private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
     private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT";
+    private final PowerManager mPowerManager;
     private final AlarmManager mAlarmManager;
     private final PendingIntent mWakeupIntent;
     private final PendingIntent mTimeoutIntent;
@@ -441,23 +457,27 @@
                 checkSmsSuplInit(intent);
             } else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) {
                 checkWapSuplInit(intent);
-             } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
-                 int networkState;
-                 if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false)) {
-                     networkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
-                 } else {
-                     networkState = LocationProvider.AVAILABLE;
-                 }
+            } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
+                int networkState;
+                if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false)) {
+                    networkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
+                } else {
+                    networkState = LocationProvider.AVAILABLE;
+                }
 
-                 // retrieve NetworkInfo result for this UID
-                 NetworkInfo info =
-                         intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
-                 ConnectivityManager connManager = (ConnectivityManager)
-                         mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
-                 info = connManager.getNetworkInfo(info.getType());
+                // retrieve NetworkInfo result for this UID
+                NetworkInfo info =
+                        intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
+                ConnectivityManager connManager = (ConnectivityManager)
+                        mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+                info = connManager.getNetworkInfo(info.getType());
 
-                 updateNetworkState(networkState, info);
-             }
+                updateNetworkState(networkState, info);
+            } else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)
+                    || Intent.ACTION_SCREEN_OFF.equals(action)
+                    || Intent.ACTION_SCREEN_ON.equals(action)) {
+                updateLowPowerMode();
+            }
         }
     };
 
@@ -474,6 +494,22 @@
         native_agps_ni_message(supl_init,supl_init.length);
     }
 
+    private void updateLowPowerMode() {
+        final boolean disableGps;
+        switch (Settings.Secure.getInt(mContext.getContentResolver(), BATTERY_SAVER_GPS_MODE,
+                BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF)) {
+            case BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF:
+                disableGps = mPowerManager.isPowerSaveMode() && !mPowerManager.isInteractive();
+                break;
+            default:
+                disableGps = false;
+        }
+        if (disableGps != mDisableGps) {
+            mDisableGps = disableGps;
+            updateRequirements();
+        }
+    }
+
     public static boolean isSupported() {
         return native_is_supported();
     }
@@ -526,8 +562,8 @@
         mLocation.setExtras(mLocationExtras);
 
         // Create a wake lock
-        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
+        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
         mWakeLock.setReferenceCounted(true);
 
         mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
@@ -604,6 +640,9 @@
         intentFilter.addAction(ALARM_WAKEUP);
         intentFilter.addAction(ALARM_TIMEOUT);
         intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+        intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
+        intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
+        intentFilter.addAction(Intent.ACTION_SCREEN_ON);
         mContext.registerReceiver(mBroadcastReciever, intentFilter, null, mHandler);
     }
 
@@ -888,31 +927,43 @@
     }
 
     private void handleSetRequest(ProviderRequest request, WorkSource source) {
+        mProviderRequest = request;
+        mWorkSource = source;
+        updateRequirements();
+    }
+
+    // Called when the requirements for GPS may have changed
+    private void updateRequirements() {
+        if (mProviderRequest == null || mWorkSource == null) {
+            return;
+        }
+
         boolean singleShot = false;
 
         // see if the request is for a single update
-        if (request.locationRequests != null && request.locationRequests.size() > 0) {
+        if (mProviderRequest.locationRequests != null
+                && mProviderRequest.locationRequests.size() > 0) {
             // if any request has zero or more than one updates
             // requested, then this is not single-shot mode
             singleShot = true;
 
-            for (LocationRequest lr : request.locationRequests) {
+            for (LocationRequest lr : mProviderRequest.locationRequests) {
                 if (lr.getNumUpdates() != 1) {
                     singleShot = false;
                 }
             }
         }
 
-        if (DEBUG) Log.d(TAG, "setRequest " + request);
-        if (request.reportLocation) {
+        if (DEBUG) Log.d(TAG, "setRequest " + mProviderRequest);
+        if (mProviderRequest.reportLocation && !mDisableGps) {
             // update client uids
-            updateClientUids(source);
+            updateClientUids(mWorkSource);
 
-            mFixInterval = (int) request.interval;
+            mFixInterval = (int) mProviderRequest.interval;
 
             // check for overflow
-            if (mFixInterval != request.interval) {
-                Log.w(TAG, "interval overflow: " + request.interval);
+            if (mFixInterval != mProviderRequest.interval) {
+                Log.w(TAG, "interval overflow: " + mProviderRequest.interval);
                 mFixInterval = Integer.MAX_VALUE;
             }
 
@@ -1321,6 +1372,7 @@
         switch (status) {
             case GPS_REQUEST_AGPS_DATA_CONN:
                 if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN");
+                Log.v(TAG, "Received SUPL IP addr[]: " + ipaddr);
                 // Set mAGpsDataConnectionState before calling startUsingNetworkFeature
                 //  to avoid a race condition with handleUpdateNetworkState()
                 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
@@ -1329,6 +1381,7 @@
                 if (ipaddr != null) {
                     try {
                         mAGpsDataConnectionIpAddr = InetAddress.getByAddress(ipaddr);
+                        Log.v(TAG, "IP address converted to: " + mAGpsDataConnectionIpAddr);
                     } catch (UnknownHostException e) {
                         Log.e(TAG, "Bad IP Address: " + ipaddr, e);
                         mAGpsDataConnectionIpAddr = null;
@@ -1375,6 +1428,8 @@
             case GPS_AGPS_DATA_CONN_FAILED:
                 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
                 break;
+            default:
+                Log.d(TAG, "Received Unknown AGPS status: " + status);
         }
     }
 
@@ -1909,6 +1964,7 @@
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         StringBuilder s = new StringBuilder();
         s.append("  mFixInterval=").append(mFixInterval).append("\n");
+        s.append("  mDisableGps (battery saver mode)=").append(mDisableGps).append("\n");
         s.append("  mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities)).append(" (");
         if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHED ");
         if (hasCapability(GPS_CAPABILITY_MSB)) s.append("MSB ");
@@ -2000,3 +2056,4 @@
     private native boolean native_start_navigation_message_collection();
     private native boolean native_stop_navigation_message_collection();
 }
+
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index e549ead..f820a3c 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -22,6 +22,7 @@
 import android.content.Intent;
 import android.content.pm.ParceledListSlice;
 import android.media.AudioManager;
+import android.media.AudioManagerInternal;
 import android.media.MediaMetadata;
 import android.media.Rating;
 import android.media.VolumeProvider;
@@ -52,6 +53,8 @@
 import android.util.Slog;
 import android.view.KeyEvent;
 
+import com.android.server.LocalServices;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.UUID;
@@ -111,6 +114,7 @@
     // Volume handling fields
     private AudioAttributes mAudioAttrs;
     private AudioManager mAudioManager;
+    private AudioManagerInternal mAudioManagerInternal;
     private int mVolumeType = MediaSession.PLAYBACK_TYPE_LOCAL;
     private int mVolumeControlType = VolumeProvider.VOLUME_CONTROL_ABSOLUTE;
     private int mMaxVolume = 0;
@@ -134,6 +138,7 @@
         mService = service;
         mHandler = new MessageHandler(handler.getLooper());
         mAudioManager = (AudioManager) service.getContext().getSystemService(Context.AUDIO_SERVICE);
+        mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
         mAudioAttrs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build();
     }
 
@@ -227,7 +232,7 @@
      *
      * @param direction The direction to adjust volume in.
      */
-    public void adjustVolume(int direction, int flags) {
+    public void adjustVolume(int direction, int flags, String packageName, int uid) {
         if (isPlaybackActive(false)) {
             flags &= ~AudioManager.FLAG_PLAY_SOUND;
         }
@@ -238,7 +243,8 @@
         }
         if (mVolumeType == MediaSession.PLAYBACK_TYPE_LOCAL) {
             int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
-            mAudioManager.adjustStreamVolume(stream, direction, flags);
+            mAudioManagerInternal.adjustStreamVolumeForUid(stream, direction, flags, packageName,
+                    uid);
         } else {
             if (mVolumeControlType == VolumeProvider.VOLUME_CONTROL_FIXED) {
                 // Nothing to do, the volume cannot be changed
@@ -262,10 +268,10 @@
         }
     }
 
-    public void setVolumeTo(int value, int flags) {
+    public void setVolumeTo(int value, int flags, String packageName, int uid) {
         if (mVolumeType == MediaSession.PLAYBACK_TYPE_LOCAL) {
             int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
-            mAudioManager.setStreamVolume(stream, value, flags);
+            mAudioManagerInternal.setStreamVolumeForUid(stream, value, flags, packageName, uid);
         } else {
             if (mVolumeControlType != VolumeProvider.VOLUME_CONTROL_ABSOLUTE) {
                 // Nothing to do. The volume can't be set directly.
@@ -397,6 +403,7 @@
                 return;
             }
             mDestroyed = true;
+            mHandler.post(MessageHandler.MSG_DESTROYED);
         }
     }
 
@@ -575,6 +582,29 @@
         }
     }
 
+    private void pushSessionDestroyed() {
+        synchronized (mLock) {
+            // This is the only method that may be (and can only be) called
+            // after the session is destroyed.
+            if (!mDestroyed) {
+                return;
+            }
+            for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) {
+                ISessionControllerCallback cb = mControllerCallbacks.get(i);
+                try {
+                    cb.onSessionDestroyed();
+                } catch (DeadObjectException e) {
+                    Log.w(TAG, "Removing dead callback in pushEvent.", e);
+                    mControllerCallbacks.remove(i);
+                } catch (RemoteException e) {
+                    Log.w(TAG, "unexpected exception in pushEvent.", e);
+                }
+            }
+            // After notifying clear all listeners
+            mControllerCallbacks.clear();
+        }
+    }
+
     private PlaybackState getStateWithUpdatedPosition() {
         PlaybackState state = mPlaybackState;
         long duration = -1;
@@ -919,6 +949,16 @@
         @Override
         public void registerCallbackListener(ISessionControllerCallback cb) {
             synchronized (mLock) {
+                // If this session is already destroyed tell the caller and
+                // don't add them.
+                if (mDestroyed) {
+                    try {
+                        cb.onSessionDestroyed();
+                    } catch (Exception e) {
+                        // ignored
+                    }
+                    return;
+                }
                 if (getControllerCbIndexForCb(cb) < 0) {
                     mControllerCallbacks.add(cb);
                     if (DEBUG) {
@@ -984,20 +1024,22 @@
         }
 
         @Override
-        public void adjustVolume(int direction, int flags) {
+        public void adjustVolume(int direction, int flags, String packageName) {
+            int uid = Binder.getCallingUid();
             final long token = Binder.clearCallingIdentity();
             try {
-                MediaSessionRecord.this.adjustVolume(direction, flags);
+                MediaSessionRecord.this.adjustVolume(direction, flags, packageName, uid);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
         }
 
         @Override
-        public void setVolumeTo(int value, int flags) {
+        public void setVolumeTo(int value, int flags, String packageName) {
+            int uid = Binder.getCallingUid();
             final long token = Binder.clearCallingIdentity();
             try {
-                MediaSessionRecord.this.setVolumeTo(value, flags);
+                MediaSessionRecord.this.setVolumeTo(value, flags, packageName, uid);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -1123,6 +1165,7 @@
         private static final int MSG_SEND_EVENT = 6;
         private static final int MSG_UPDATE_SESSION_STATE = 7;
         private static final int MSG_UPDATE_VOLUME = 8;
+        private static final int MSG_DESTROYED = 9;
 
         public MessageHandler(Looper looper) {
             super(looper);
@@ -1154,6 +1197,8 @@
                 case MSG_UPDATE_VOLUME:
                     pushVolumeUpdate();
                     break;
+                case MSG_DESTROYED:
+                    pushSessionDestroyed();
             }
         }
 
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 0514f48..1221aa4 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -812,7 +812,8 @@
                     Log.e(TAG, "Error adjusting default volume.", e);
                 }
             } else {
-                session.adjustVolume(direction, flags);
+                session.adjustVolume(direction, flags, getContext().getPackageName(),
+                        UserHandle.myUserId());
                 if (session.getPlaybackType() == MediaSession.PLAYBACK_TYPE_REMOTE
                         && mRvc != null) {
                     try {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 3eb2b7e..d6afe68 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1761,26 +1761,27 @@
             if (hasValidSound) {
                 boolean looping =
                         (notification.flags & Notification.FLAG_INSISTENT) != 0;
-                int audioStreamType;
-                if (notification.audioStreamType >= 0) {
-                    audioStreamType = notification.audioStreamType;
+                AudioAttributes audioAttributes;
+                if (notification.audioAttributes != null) {
+                    audioAttributes = notification.audioAttributes;
                 } else {
-                    audioStreamType = DEFAULT_STREAM_TYPE;
+                    audioAttributes = Notification.AUDIO_ATTRIBUTES_DEFAULT;
                 }
                 mSoundNotification = record;
                 // do not play notifications if stream volume is 0 (typically because
                 // ringer mode is silent) or if there is a user of exclusive audio focus
-                if ((mAudioManager.getStreamVolume(audioStreamType) != 0)
-                        && !mAudioManager.isAudioFocusExclusive()) {
+                if ((mAudioManager.getStreamVolume(
+                        AudioAttributes.toLegacyStreamType(audioAttributes)) != 0)
+                            && !mAudioManager.isAudioFocusExclusive()) {
                     final long identity = Binder.clearCallingIdentity();
                     try {
                         final IRingtonePlayer player =
                                 mAudioManager.getRingtonePlayer();
                         if (player != null) {
                             if (DBG) Slog.v(TAG, "Playing sound " + soundUri
-                                    + " on stream " + audioStreamType);
+                                    + " with attributes " + audioAttributes);
                             player.playAsync(soundUri, record.sbn.getUser(), looping,
-                                    audioStreamType);
+                                    audioAttributes);
                             buzzBeepBlinked = true;
                         }
                     } catch (RemoteException e) {
@@ -2424,8 +2425,9 @@
                 // pulse repeatedly
                 mNotificationLight.setFlashing(ledARGB, Light.LIGHT_FLASH_TIMED,
                         ledOnMS, ledOffMS);
-                mStatusBar.notificationLightPulse(ledARGB, ledOnMS, ledOffMS);
             }
+            // let SystemUI make an independent decision
+            mStatusBar.notificationLightPulse(ledARGB, ledOnMS, ledOffMS);
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 6be6b60..89bd1d4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -253,6 +253,10 @@
     // package apks to install directory.
     private static final String INSTALL_PACKAGE_SUFFIX = "-";
 
+    // Special value for {@code PackageParser.Package#cpuAbiOverride} to indicate
+    // that the cpuAbiOverride must be clear.
+    private static final String CLEAR_ABI_OVERRIDE = "-";
+
     static final int SCAN_MONITOR = 1<<0;
     static final int SCAN_NO_DEX = 1<<1;
     static final int SCAN_FORCE_DEX = 1<<2;
@@ -3195,7 +3199,7 @@
         if (fromSource != null) {
             packageNames = fromSource.get(targetUserId);
         }
-        if (packageNames.contains(intent.getPackage())) {
+        if (packageNames != null && packageNames.contains(intent.getPackage())) {
             return true;
         }
         // We need the package name, so we try to resolve with the loosest flags possible
@@ -4093,8 +4097,7 @@
                 continue;
             }
             try {
-                scanPackageLI(file, flags | PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime,
-                        null, null);
+                scanPackageLI(file, flags | PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime, null);
             } catch (PackageManagerException e) {
                 Slog.w(TAG, "Failed to parse " + file + ": " + e.getMessage());
 
@@ -4175,7 +4178,7 @@
      *  Returns null in case of errors and the error code is stored in mLastScanError
      */
     private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanMode,
-            long currentTime, UserHandle user, String abiOverride) throws PackageManagerException {
+            long currentTime, UserHandle user) throws PackageManagerException {
         if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile);
         parseFlags |= mDefParseFlags;
         PackageParser pp = new PackageParser();
@@ -4371,7 +4374,7 @@
 
         // Note that we invoke the following method only if we are about to unpack an application
         PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanMode
-                | SCAN_UPDATE_SIGNATURE, currentTime, user, abiOverride);
+                | SCAN_UPDATE_SIGNATURE, currentTime, user);
 
         /*
          * If the system app should be overridden by a previously installed
@@ -4998,8 +5001,26 @@
         return res;
     }
 
+    /**
+     * Derive the value of the {@code cpuAbiOverride} based on the provided
+     * value and an optional stored value from the package settings.
+     */
+    private static String deriveAbiOverride(String abiOverride, PackageSetting settings) {
+        String cpuAbiOverride = null;
+
+        if (CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
+            cpuAbiOverride = null;
+        } else if (abiOverride != null) {
+            cpuAbiOverride = abiOverride;
+        } else if (settings != null) {
+            cpuAbiOverride = settings.cpuAbiOverrideString;
+        }
+
+        return cpuAbiOverride;
+    }
+
     private PackageParser.Package scanPackageLI(PackageParser.Package pkg, int parseFlags,
-            int scanMode, long currentTime, UserHandle user, String abiOverride)
+            int scanMode, long currentTime, UserHandle user)
             throws PackageManagerException {
         final File scanFile = new File(pkg.codePath);
         if (pkg.applicationInfo.getCodePath() == null ||
@@ -5155,7 +5176,7 @@
                 Slog.w(TAG, "Package " + pkg.packageName
                         + " was transferred to another, but its .apk remains");
             }
-            
+
             // Just create the setting, don't add it yet. For already existing packages
             // the PkgSetting exists already and doesn't have to be created.
             pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,
@@ -5435,14 +5456,8 @@
 
         final String path = scanFile.getPath();
         final String codePath = pkg.applicationInfo.getCodePath();
+        final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, pkgSetting);
         if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
-            // For the case where we had previously uninstalled an update, get rid
-            // of any native binaries we might have unpackaged. Note that this assumes
-            // that system app updates were not installed via ASEC.
-            //
-            // TODO(multiArch): Is this cleanup really necessary ?
-            NativeLibraryHelper.removeNativeBinariesFromDirLI(
-                    new File(codePath, LIB_DIR_NAME), false /* delete dirs */);
             setBundledAppAbisAndRoots(pkg, pkgSetting);
 
             // If we haven't found any native libraries for the app, check if it has
@@ -5497,7 +5512,7 @@
                     // Warn if we've set an abiOverride for multi-lib packages..
                     // By definition, we need to copy both 32 and 64 bit libraries for
                     // such packages.
-                    if (abiOverride != null) {
+                    if (pkg.cpuAbiOverride != null && !CLEAR_ABI_OVERRIDE.equals(pkg.cpuAbiOverride)) {
                         Slog.w(TAG, "Ignoring abiOverride for multi arch application.");
                     }
 
@@ -5540,15 +5555,15 @@
                         }
                     }
                 } else {
-                    String[] abiList = (abiOverride != null) ?
-                            new String[] { abiOverride } : Build.SUPPORTED_ABIS;
+                    String[] abiList = (cpuAbiOverride != null) ?
+                            new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS;
 
                     // Enable gross and lame hacks for apps that are built with old
                     // SDK tools. We must scan their APKs for renderscript bitcode and
                     // not launch them if it's present. Don't bother checking on devices
                     // that don't have 64 bit support.
                     boolean needsRenderScriptOverride = false;
-                    if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && abiOverride == null &&
+                    if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null &&
                             NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
                         abiList = Build.SUPPORTED_32_BIT_ABIS;
                         needsRenderScriptOverride = true;
@@ -5569,8 +5584,8 @@
 
                     if (copyRet >= 0) {
                         pkg.applicationInfo.primaryCpuAbi = abiList[copyRet];
-                    } else if (copyRet == PackageManager.NO_NATIVE_LIBRARIES && abiOverride != null) {
-                        pkg.applicationInfo.primaryCpuAbi = abiOverride;
+                    } else if (copyRet == PackageManager.NO_NATIVE_LIBRARIES && cpuAbiOverride != null) {
+                        pkg.applicationInfo.primaryCpuAbi = cpuAbiOverride;
                     } else if (needsRenderScriptOverride) {
                         pkg.applicationInfo.primaryCpuAbi = abiList[0];
                     }
@@ -5615,6 +5630,10 @@
 
         pkgSetting.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi;
         pkgSetting.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi;
+        pkgSetting.cpuAbiOverrideString = cpuAbiOverride;
+        // Copy the derived override back to the parsed package, so that we can
+        // update the package settings accordingly.
+        pkg.cpuAbiOverride = cpuAbiOverride;
 
         Slog.d(TAG, "Resolved nativeLibraryRoot for " + pkg.applicationInfo.packageName
                 + " to root=" + pkg.applicationInfo.nativeLibraryRootDir + ", isa="
@@ -6241,7 +6260,7 @@
         }
     }
 
-    private static String calculateApkRoot(final String codePathString) {
+    private static String calculateBundledApkRoot(final String codePathString) {
         final File codePath = new File(codePathString);
         final File codeRoot;
         if (FileUtils.contains(Environment.getRootDirectory(), codePath)) {
@@ -6281,14 +6300,9 @@
         final ApplicationInfo info = pkg.applicationInfo;
         final String codePath = pkg.codePath;
         final File codeFile = new File(codePath);
-        // If "/system/lib64/apkname" exists, assume that is the per-package
-        // native library directory to use; otherwise use "/system/lib/apkname".
-        final String apkRoot = calculateApkRoot(info.sourceDir);
-
         final boolean bundledApp = isSystemApp(info) && !isUpdatedSystemApp(info);
         final boolean asecApp = isForwardLocked(info) || isExternal(info);
 
-
         info.nativeLibraryRootDir = null;
         info.nativeLibraryRootRequiresIsa = false;
         info.nativeLibraryDir = null;
@@ -6297,6 +6311,9 @@
         if (isApkFile(codeFile)) {
             // Monolithic install
             if (bundledApp) {
+                // If "/system/lib64/apkname" exists, assume that is the per-package
+                // native library directory to use; otherwise use "/system/lib/apkname".
+                final String apkRoot = calculateBundledApkRoot(info.sourceDir);
                 final boolean is64Bit = VMRuntime.is64BitInstructionSet(
                         getPrimaryInstructionSet(info));
 
@@ -6352,7 +6369,7 @@
 
         // If "/system/lib64/apkname" exists, assume that is the per-package
         // native library directory to use; otherwise use "/system/lib/apkname".
-        final String apkRoot = calculateApkRoot(pkg.applicationInfo.sourceDir);
+        final String apkRoot = calculateBundledApkRoot(pkg.applicationInfo.sourceDir);
         setBundledAppAbi(pkg, apkRoot, apkName);
         // pkgSetting might be null during rescan following uninstall of updates
         // to a bundled app, so accommodate that possibility.  The settings in
@@ -9278,7 +9295,7 @@
                     // Warn if we've set an abiOverride for multi-lib packages..
                     // By definition, we need to copy both 32 and 64 bit libraries for
                     // such packages.
-                    if (abiOverride != null) {
+                    if (abiOverride != null &&  !CLEAR_ABI_OVERRIDE.equals(abiOverride)) {
                         Slog.w(TAG, "Ignoring abiOverride for multi arch application.");
                     }
 
@@ -9295,10 +9312,11 @@
                         maybeThrowExceptionForMultiArchCopy("Failure copying 64 bit native libraries", copyRet);
                     }
                 } else {
-                    String[] abiList = (abiOverride != null) ?
-                            new String[] { abiOverride } : Build.SUPPORTED_ABIS;
+                    final String cpuAbiOverride = deriveAbiOverride(this.abiOverride, null /* package setting */);
+                    String[] abiList = (cpuAbiOverride != null) ?
+                            new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS;
 
-                    if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && abiOverride == null &&
+                    if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null &&
                             NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
                         abiList = Build.SUPPORTED_32_BIT_ABIS;
                     }
@@ -9566,7 +9584,7 @@
 
             final String newCachePath = imcs.copyPackageToContainer(
                     originFile.getAbsolutePath(), cid, getEncryptKey(), isExternal(),
-                    isFwdLocked(), abiOverride);
+                    isFwdLocked(), deriveAbiOverride(abiOverride, null /* settings */));
 
             if (newCachePath != null) {
                 setCachePath(newCachePath);
@@ -9917,7 +9935,7 @@
      */
     private void installNewPackageLI(PackageParser.Package pkg,
             int parseFlags, int scanMode, UserHandle user,
-            String installerPackageName, PackageInstalledInfo res, String abiOverride) {
+            String installerPackageName, PackageInstalledInfo res) {
         // Remember this for later, in case we need to rollback this install
         String pkgName = pkg.packageName;
 
@@ -9944,7 +9962,7 @@
 
         try {
             PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode,
-                    System.currentTimeMillis(), user, abiOverride);
+                    System.currentTimeMillis(), user);
 
             updateSettingsLI(newPackage, installerPackageName, null, null, res);
             // delete the partially installed application. the data directory will have to be
@@ -9980,7 +9998,7 @@
 
     private void replacePackageLI(PackageParser.Package pkg,
             int parseFlags, int scanMode, UserHandle user,
-            String installerPackageName, PackageInstalledInfo res, String abiOverride) {
+            String installerPackageName, PackageInstalledInfo res) {
         PackageParser.Package oldPackage;
         String pkgName = pkg.packageName;
         int[] allUsers;
@@ -10019,19 +10037,17 @@
         boolean sysPkg = (isSystemApp(oldPackage));
         if (sysPkg) {
             replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode,
-                    user, allUsers, perUserInstalled, installerPackageName, res,
-                    abiOverride);
+                    user, allUsers, perUserInstalled, installerPackageName, res);
         } else {
             replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode,
-                    user, allUsers, perUserInstalled, installerPackageName, res,
-                    abiOverride);
+                    user, allUsers, perUserInstalled, installerPackageName, res);
         }
     }
 
     private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
             PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user,
             int[] allUsers, boolean[] perUserInstalled,
-            String installerPackageName, PackageInstalledInfo res, String abiOverride) {
+            String installerPackageName, PackageInstalledInfo res) {
         String pkgName = deletedPackage.packageName;
         boolean deletedPkg = true;
         boolean updatedSettings = false;
@@ -10056,7 +10072,7 @@
             deleteCodeCacheDirsLI(pkgName);
             try {
                 final PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags,
-                        scanMode | SCAN_UPDATE_TIME, System.currentTimeMillis(), user, abiOverride);
+                        scanMode | SCAN_UPDATE_TIME, System.currentTimeMillis(), user);
                 updateSettingsLI(newPackage, installerPackageName, allUsers, perUserInstalled, res);
                 updatedSettings = true;
             } catch (PackageManagerException e) {
@@ -10089,8 +10105,7 @@
                 int oldScanMode = (oldOnSd ? 0 : SCAN_MONITOR) | SCAN_UPDATE_SIGNATURE
                         | SCAN_UPDATE_TIME;
                 try {
-                    scanPackageLI(restoreFile, oldParseFlags, oldScanMode, origUpdateTime, null,
-                            null);
+                    scanPackageLI(restoreFile, oldParseFlags, oldScanMode, origUpdateTime, null);
                 } catch (PackageManagerException e) {
                     Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade: "
                             + e.getMessage());
@@ -10112,7 +10127,7 @@
     private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
             PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user,
             int[] allUsers, boolean[] perUserInstalled,
-            String installerPackageName, PackageInstalledInfo res, String abiOverride) {
+            String installerPackageName, PackageInstalledInfo res) {
         if (DEBUG_INSTALL) Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg
                 + ", old=" + deletedPackage);
         boolean updatedSettings = false;
@@ -10172,7 +10187,7 @@
 
         PackageParser.Package newPackage = null;
         try {
-            newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0, user, abiOverride);
+            newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0, user);
             if (newPackage.mExtras != null) {
                 final PackageSetting newPkgSetting = (PackageSetting) newPackage.mExtras;
                 newPkgSetting.firstInstallTime = oldPkgSetting.firstInstallTime;
@@ -10204,8 +10219,7 @@
             }
             // Add back the old system package
             try {
-                scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0, user,
-                        null);
+                scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0, user);
             } catch (PackageManagerException e) {
                 Slog.e(TAG, "Failed to restore original package: " + e.getMessage());
             }
@@ -10336,6 +10350,9 @@
             return;
         }
 
+        // Mark that we have an install time CPU ABI override.
+        pkg.cpuAbiOverride = args.abiOverride;
+
         String pkgName = res.name = pkg.packageName;
         if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
             if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
@@ -10454,10 +10471,10 @@
 
         if (replace) {
             replacePackageLI(pkg, parseFlags, scanMode, args.user,
-                    installerPackageName, res, args.abiOverride);
+                    installerPackageName, res);
         } else {
             installNewPackageLI(pkg, parseFlags, scanMode | SCAN_DELETE_DATA_ON_FAILURES, args.user,
-                    installerPackageName, res, args.abiOverride);
+                    installerPackageName, res);
         }
         synchronized (mPackages) {
             final PackageSetting ps = mSettings.mPackages.get(pkgName);
@@ -10893,8 +10910,7 @@
 
         final PackageParser.Package newPkg;
         try {
-            newPkg = scanPackageLI(disabledPs.codePath, parseFlags, SCAN_MONITOR | SCAN_NO_PATHS, 0,
-                    null, null);
+            newPkg = scanPackageLI(disabledPs.codePath, parseFlags, SCAN_MONITOR | SCAN_NO_PATHS, 0, null);
         } catch (PackageManagerException e) {
             Slog.w(TAG, "Failed to restore system package:" + newPs.name + ": " + e.getMessage());
             return false;
@@ -12852,7 +12868,7 @@
                 synchronized (mInstallLock) {
                     PackageParser.Package pkg = null;
                     try {
-                        pkg = scanPackageLI(new File(codePath), parseFlags, 0, 0, null, null);
+                        pkg = scanPackageLI(new File(codePath), parseFlags, 0, 0, null);
                     } catch (PackageManagerException e) {
                         Slog.w(TAG, "Failed to scan " + codePath + ": " + e.getMessage());
                     }
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index a6571cf..696aa34 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -31,9 +31,11 @@
 
     PackageSetting(String name, String realName, File codePath, File resourcePath,
             String legacyNativeLibraryPathString, String primaryCpuAbiString,
-            String secondaryCpuAbiString, int pVersionCode, int pkgFlags) {
+            String secondaryCpuAbiString, String cpuAbiOverrideString,
+            int pVersionCode, int pkgFlags) {
         super(name, realName, codePath, resourcePath, legacyNativeLibraryPathString,
-                primaryCpuAbiString, secondaryCpuAbiString, pVersionCode, pkgFlags);
+                primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
+                pVersionCode, pkgFlags);
     }
 
     /**
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index e29332c..bf13fd9 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -64,8 +64,25 @@
     @Deprecated
     String legacyNativeLibraryPathString;
 
+    /**
+     * The primary CPU abi for this package. This value is regenerated at every
+     * boot scan.
+     */
     String primaryCpuAbiString;
+
+    /**
+     * The secondary CPU abi for this package. This value is regenerated at every
+     * boot scan.
+     */
     String secondaryCpuAbiString;
+
+    /**
+     * The install time CPU override, if any. This value is written at install time
+     * and doesn't change during the life of an install. If non-null,
+     * {@code primaryCpuAbiString} will contain the same value.
+     */
+    String cpuAbiOverrideString;
+
     long timeStamp;
     long firstInstallTime;
     long lastUpdateTime;
@@ -94,12 +111,13 @@
     String installerPackageName;
     PackageSettingBase(String name, String realName, File codePath, File resourcePath,
             String legacyNativeLibraryPathString, String primaryCpuAbiString,
-            String secondaryCpuAbiString, int pVersionCode, int pkgFlags) {
+            String secondaryCpuAbiString, String cpuAbiOverrideString,
+            int pVersionCode, int pkgFlags) {
         super(pkgFlags);
         this.name = name;
         this.realName = realName;
         init(codePath, resourcePath, legacyNativeLibraryPathString, primaryCpuAbiString,
-                secondaryCpuAbiString, pVersionCode);
+                secondaryCpuAbiString, cpuAbiOverrideString, pVersionCode);
     }
 
     /**
@@ -118,6 +136,7 @@
         legacyNativeLibraryPathString = base.legacyNativeLibraryPathString;
         primaryCpuAbiString = base.primaryCpuAbiString;
         secondaryCpuAbiString = base.secondaryCpuAbiString;
+        cpuAbiOverrideString = base.cpuAbiOverrideString;
         timeStamp = base.timeStamp;
         firstInstallTime = base.firstInstallTime;
         lastUpdateTime = base.lastUpdateTime;
@@ -145,7 +164,8 @@
     }
 
     void init(File codePath, File resourcePath, String legacyNativeLibraryPathString,
-              String primaryCpuAbiString, String secondaryCpuAbiString, int pVersionCode) {
+              String primaryCpuAbiString, String secondaryCpuAbiString,
+              String cpuAbiOverrideString, int pVersionCode) {
         this.codePath = codePath;
         this.codePathString = codePath.toString();
         this.resourcePath = resourcePath;
@@ -153,6 +173,7 @@
         this.legacyNativeLibraryPathString = legacyNativeLibraryPathString;
         this.primaryCpuAbiString = primaryCpuAbiString;
         this.secondaryCpuAbiString = secondaryCpuAbiString;
+        this.cpuAbiOverrideString = cpuAbiOverrideString;
         this.versionCode = pVersionCode;
     }
 
@@ -185,6 +206,7 @@
 
         primaryCpuAbiString = base.primaryCpuAbiString;
         secondaryCpuAbiString = base.secondaryCpuAbiString;
+        cpuAbiOverrideString = base.cpuAbiOverrideString;
         timeStamp = base.timeStamp;
         firstInstallTime = base.firstInstallTime;
         lastUpdateTime = base.lastUpdateTime;
diff --git a/services/core/java/com/android/server/pm/PendingPackage.java b/services/core/java/com/android/server/pm/PendingPackage.java
index 85be651..5d30e76 100644
--- a/services/core/java/com/android/server/pm/PendingPackage.java
+++ b/services/core/java/com/android/server/pm/PendingPackage.java
@@ -22,10 +22,12 @@
     final int sharedId;
 
     PendingPackage(String name, String realName, File codePath, File resourcePath,
-            String nativeLibrary32PathString, String nativeLibrary64PathString,
-            String requiredCpuAbiString, int sharedId, int pVersionCode, int pkgFlags) {
-        super(name, realName, codePath, resourcePath, nativeLibrary32PathString, nativeLibrary64PathString,
-                requiredCpuAbiString, pVersionCode, pkgFlags);
+            String legacyNativeLibraryPathString, String primaryCpuAbiString,
+            String secondaryCpuAbiString, String cpuAbiOverrideString, int sharedId,
+            int pVersionCode, int pkgFlags) {
+        super(name, realName, codePath, resourcePath, legacyNativeLibraryPathString,
+                primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
+                pVersionCode, pkgFlags);
         this.sharedId = sharedId;
     }
 }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index cd2aa22..c346f71 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -325,8 +325,8 @@
 
     PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage,
             String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
-            String legacyNativeLibraryPathString, String primaryCpuAbi, String secondaryCpuAbi, int pkgFlags,
-            UserHandle user, boolean add) {
+            String legacyNativeLibraryPathString, String primaryCpuAbi, String secondaryCpuAbi,
+            int pkgFlags, UserHandle user, boolean add) {
         final String name = pkg.packageName;
         PackageSetting p = getPackageLPw(name, origPackage, realName, sharedUser, codePath,
                 resourcePath, legacyNativeLibraryPathString, primaryCpuAbi, secondaryCpuAbi,
@@ -417,7 +417,8 @@
         }
         PackageSetting ret = addPackageLPw(name, p.realName, p.codePath, p.resourcePath,
                 p.legacyNativeLibraryPathString, p.primaryCpuAbiString,
-                p.secondaryCpuAbiString, p.appId, p.versionCode, p.pkgFlags);
+                p.secondaryCpuAbiString, p.secondaryCpuAbiString,
+                p.appId, p.versionCode, p.pkgFlags);
         mDisabledSysPackages.remove(name);
         return ret;
     }
@@ -432,7 +433,7 @@
 
     PackageSetting addPackageLPw(String name, String realName, File codePath, File resourcePath,
             String legacyNativeLibraryPathString, String primaryCpuAbiString, String secondaryCpuAbiString,
-            int uid, int vc, int pkgFlags) {
+            String cpuAbiOverrideString, int uid, int vc, int pkgFlags) {
         PackageSetting p = mPackages.get(name);
         if (p != null) {
             if (p.appId == uid) {
@@ -443,7 +444,8 @@
             return null;
         }
         p = new PackageSetting(name, realName, codePath, resourcePath,
-                legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString, vc, pkgFlags);
+                legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString,
+                cpuAbiOverrideString, vc, pkgFlags);
         p.appId = uid;
         if (addUserIdLPw(uid, p, name)) {
             mPackages.put(name, p);
@@ -512,11 +514,13 @@
     private PackageSetting getPackageLPw(String name, PackageSetting origPackage,
             String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
             String legacyNativeLibraryPathString, String primaryCpuAbiString, String secondaryCpuAbiString,
-            int vc, int pkgFlags, UserHandle installUser, boolean add, boolean allowInstall) {
+            int vc, int pkgFlags, UserHandle installUser, boolean add,
+            boolean allowInstall) {
         PackageSetting p = mPackages.get(name);
         if (p != null) {
             p.primaryCpuAbiString = primaryCpuAbiString;
             p.secondaryCpuAbiString = secondaryCpuAbiString;
+
             if (!p.codePath.equals(codePath)) {
                 // Check to see if its a disabled system app
                 if ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
@@ -560,7 +564,8 @@
             if (origPackage != null) {
                 // We are consuming the data from an existing package.
                 p = new PackageSetting(origPackage.name, name, codePath, resourcePath,
-                        legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString, vc, pkgFlags);
+                        legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString,
+                        null /* cpuAbiOverrideString */, vc, pkgFlags);
                 if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package "
                         + name + " is adopting original package " + origPackage.name);
                 // Note that we will retain the new package's signature so
@@ -577,7 +582,8 @@
                 p.setTimeStamp(codePath.lastModified());
             } else {
                 p = new PackageSetting(name, realName, codePath, resourcePath,
-                        legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString, vc, pkgFlags);
+                        legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString,
+                        null /* cpuAbiOverrideString */, vc, pkgFlags);
                 p.setTimeStamp(codePath.lastModified());
                 p.sharedUser = sharedUser;
                 // If this is not a system app, it starts out stopped.
@@ -720,6 +726,7 @@
         // Update the required Cpu Abi
         p.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi;
         p.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi;
+        p.cpuAbiOverrideString = pkg.cpuAbiOverride;
         // Update version code if needed
         if (pkg.mVersionCode != p.versionCode) {
             p.versionCode = pkg.mVersionCode;
@@ -1888,6 +1895,9 @@
         if (pkg.secondaryCpuAbiString != null) {
             serializer.attribute(null, "secondaryCpuAbi", pkg.secondaryCpuAbiString);
         }
+        if (pkg.cpuAbiOverrideString != null) {
+            serializer.attribute(null, "cpuAbiOverride", pkg.cpuAbiOverrideString);
+        }
 
         if (pkg.sharedUser == null) {
             serializer.attribute(null, "userId", Integer.toString(pkg.appId));
@@ -1938,6 +1948,9 @@
         if (pkg.secondaryCpuAbiString != null) {
             serializer.attribute(null, "secondaryCpuAbi", pkg.secondaryCpuAbiString);
         }
+        if (pkg.cpuAbiOverrideString != null) {
+            serializer.attribute(null, "cpuAbiOverride", pkg.cpuAbiOverrideString);
+        }
 
         serializer.attribute(null, "flags", Integer.toString(pkg.pkgFlags));
         serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp));
@@ -2248,8 +2261,8 @@
                 PackageSetting p = getPackageLPw(pp.name, null, pp.realName,
                         (SharedUserSetting) idObj, pp.codePath, pp.resourcePath,
                         pp.legacyNativeLibraryPathString, pp.primaryCpuAbiString,
-                        pp.secondaryCpuAbiString, pp.versionCode, pp.pkgFlags,
-                        null, true /* add */, false /* allowInstall */);
+                        pp.secondaryCpuAbiString, pp.versionCode, pp.pkgFlags, null,
+                        true /* add */, false /* allowInstall */);
                 if (p == null) {
                     PackageManagerService.reportSettingsProblem(Log.WARN,
                             "Unable to create application package for " + pp.name);
@@ -2673,6 +2686,7 @@
 
         String primaryCpuAbiStr = parser.getAttributeValue(null, "primaryCpuAbi");
         String secondaryCpuAbiStr = parser.getAttributeValue(null, "secondaryCpuAbi");
+        String cpuAbiOverrideStr = parser.getAttributeValue(null, "cpuAbiOverride");
 
         if (primaryCpuAbiStr == null && legacyCpuAbiStr != null) {
             primaryCpuAbiStr = legacyCpuAbiStr;
@@ -2698,7 +2712,7 @@
         }
         PackageSetting ps = new PackageSetting(name, realName, codePathFile,
                 new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiStr,
-                secondaryCpuAbiStr, versionCode, pkgFlags);
+                secondaryCpuAbiStr, cpuAbiOverrideStr, versionCode, pkgFlags);
         String timeStampStr = parser.getAttributeValue(null, "ft");
         if (timeStampStr != null) {
             try {
@@ -2768,6 +2782,7 @@
         String legacyNativeLibraryPathStr = null;
         String primaryCpuAbiString = null;
         String secondaryCpuAbiString = null;
+        String cpuAbiOverrideString = null;
         String systemStr = null;
         String installerPackageName = null;
         String uidError = null;
@@ -2792,6 +2807,7 @@
             legacyNativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath");
             primaryCpuAbiString = parser.getAttributeValue(null, "primaryCpuAbi");
             secondaryCpuAbiString = parser.getAttributeValue(null, "secondaryCpuAbi");
+            cpuAbiOverrideString = parser.getAttributeValue(null, "cpuAbiOverride");
 
             if (primaryCpuAbiString == null && legacyCpuAbiString != null) {
                 primaryCpuAbiString = legacyCpuAbiString;
@@ -2874,7 +2890,7 @@
             } else if (userId > 0) {
                 packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr),
                         new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiString,
-                        secondaryCpuAbiString, userId, versionCode, pkgFlags);
+                        secondaryCpuAbiString, cpuAbiOverrideString, userId, versionCode, pkgFlags);
                 if (PackageManagerService.DEBUG_SETTINGS)
                     Log.i(PackageManagerService.TAG, "Reading package " + name + ": userId="
                             + userId + " pkg=" + packageSetting);
@@ -2892,7 +2908,8 @@
                 if (userId > 0) {
                     packageSetting = new PendingPackage(name.intern(), realName, new File(
                             codePathStr), new File(resourcePathStr), legacyNativeLibraryPathStr,
-                            primaryCpuAbiString, legacyCpuAbiString, userId, versionCode, pkgFlags);
+                            primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
+                            userId, versionCode, pkgFlags);
                     packageSetting.setTimeStamp(timeStamp);
                     packageSetting.firstInstallTime = firstInstallTime;
                     packageSetting.lastUpdateTime = lastUpdateTime;
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 33ecc4d..ad87993 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -125,6 +125,10 @@
     // Number of attempts before jumping to the next BACKOFF_TIMES slot
     private static final int BACKOFF_INC_INTERVAL = 5;
 
+    // Maximum number of managed profiles permitted is 1. This cannot be increased
+    // without first making sure that the rest of the framework is prepared for it.
+    private static final int MAX_MANAGED_PROFILES = 1;
+
     // Amount of time to force the user to wait before entering the PIN again, after failing
     // BACKOFF_INC_INTERVAL times.
     private static final int[] BACKOFF_TIMES = { 0, 30*1000, 60*1000, 5*60*1000, 30*60*1000 };
@@ -510,7 +514,8 @@
         // Skip over users being removed
         for (int i = 0; i < totalUserCount; i++) {
             UserInfo user = mUsers.valueAt(i);
-            if (!mRemovingUserIds.get(user.id)) {
+            if (!mRemovingUserIds.get(user.id)
+                    && !user.isGuest()) {
                 aliveUserCount++;
             }
         }
@@ -1093,6 +1098,7 @@
             Log.w(LOG_TAG, "Cannot add user. DISALLOW_ADD_USER is enabled.");
             return null;
         }
+        final boolean isGuest = (flags & UserInfo.FLAG_GUEST) != 0;
         final long ident = Binder.clearCallingIdentity();
         UserInfo userInfo = null;
         try {
@@ -1103,7 +1109,21 @@
                         parent = getUserInfoLocked(parentId);
                         if (parent == null) return null;
                     }
-                    if (isUserLimitReachedLocked()) return null;
+                    // If we're not adding a guest user and the limit has been reached,
+                    // cannot add a user.
+                    if (!isGuest && isUserLimitReachedLocked()) {
+                        return null;
+                    }
+                    // If we're adding a guest and there already exists one, bail.
+                    if (isGuest && numberOfUsersOfTypeLocked(UserInfo.FLAG_GUEST, true) > 0) {
+                        return null;
+                    }
+                    // Limit number of managed profiles that can be created
+                    if ((flags & UserInfo.FLAG_MANAGED_PROFILE) != 0
+                            && numberOfUsersOfTypeLocked(UserInfo.FLAG_MANAGED_PROFILE, true)
+                                >= MAX_MANAGED_PROFILES) {
+                        return null;
+                    }
                     int userId = getNextAvailableIdLocked();
                     userInfo = new UserInfo(userId, name, null, flags);
                     File userPath = new File(mBaseUserPath, Integer.toString(userId));
@@ -1142,6 +1162,19 @@
         return userInfo;
     }
 
+    private int numberOfUsersOfTypeLocked(int flags, boolean excludeDying) {
+        int count = 0;
+        for (int i = mUsers.size() - 1; i >= 0; i--) {
+            UserInfo user = mUsers.valueAt(i);
+            if (!excludeDying || !mRemovingUserIds.get(user.id)) {
+                if ((user.flags & flags) != 0) {
+                    count++;
+                }
+            }
+        }
+        return count;
+    }
+
     /**
      * Removes a user and all data directories created for that user. This method should be called
      * after the user's processes have been terminated.
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 14cbd66..39c6e0e 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -771,7 +771,7 @@
                 notifyAcquire = true;
             }
 
-            applyWakeLockFlagsOnAcquireLocked(wakeLock);
+            applyWakeLockFlagsOnAcquireLocked(wakeLock, uid);
             mDirty |= DIRTY_WAKE_LOCKS;
             updatePowerStateLocked();
             if (notifyAcquire) {
@@ -796,10 +796,10 @@
         return false;
     }
 
-    private void applyWakeLockFlagsOnAcquireLocked(WakeLock wakeLock) {
+    private void applyWakeLockFlagsOnAcquireLocked(WakeLock wakeLock, int uid) {
         if ((wakeLock.mFlags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0
                 && isScreenLock(wakeLock)) {
-            wakeUpNoUpdateLocked(SystemClock.uptimeMillis());
+            wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), uid);
         }
     }
 
@@ -994,17 +994,17 @@
         return false;
     }
 
-    private void wakeUpInternal(long eventTime) {
+    private void wakeUpInternal(long eventTime, int uid) {
         synchronized (mLock) {
-            if (wakeUpNoUpdateLocked(eventTime)) {
+            if (wakeUpNoUpdateLocked(eventTime, uid)) {
                 updatePowerStateLocked();
             }
         }
     }
 
-    private boolean wakeUpNoUpdateLocked(long eventTime) {
+    private boolean wakeUpNoUpdateLocked(long eventTime, int uid) {
         if (DEBUG_SPEW) {
-            Slog.d(TAG, "wakeUpNoUpdateLocked: eventTime=" + eventTime);
+            Slog.d(TAG, "wakeUpNoUpdateLocked: eventTime=" + eventTime + ", uid=" + uid);
         }
 
         if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE
@@ -1014,13 +1014,13 @@
 
         switch (mWakefulness) {
             case WAKEFULNESS_ASLEEP:
-                Slog.i(TAG, "Waking up from sleep...");
+                Slog.i(TAG, "Waking up from sleep (uid " + uid +")...");
                 break;
             case WAKEFULNESS_DREAMING:
-                Slog.i(TAG, "Waking up from dream...");
+                Slog.i(TAG, "Waking up from dream (uid " + uid +")...");
                 break;
             case WAKEFULNESS_DOZING:
-                Slog.i(TAG, "Waking up from dozing...");
+                Slog.i(TAG, "Waking up from dozing (uid " + uid +")...");
                 break;
         }
 
@@ -1030,13 +1030,13 @@
         setInteractiveStateLocked(true, 0);
 
         userActivityNoUpdateLocked(
-                eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
+                eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, uid);
         return true;
     }
 
-    private void goToSleepInternal(long eventTime, int reason, int flags) {
+    private void goToSleepInternal(long eventTime, int reason, int flags, int uid) {
         synchronized (mLock) {
-            if (goToSleepNoUpdateLocked(eventTime, reason, flags)) {
+            if (goToSleepNoUpdateLocked(eventTime, reason, flags, uid)) {
                 updatePowerStateLocked();
             }
         }
@@ -1045,10 +1045,10 @@
     // This method is called goToSleep for historical reasons but we actually start
     // dozing before really going to sleep.
     @SuppressWarnings("deprecation")
-    private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags) {
+    private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) {
         if (DEBUG_SPEW) {
             Slog.d(TAG, "goToSleepNoUpdateLocked: eventTime=" + eventTime
-                    + ", reason=" + reason + ", flags=" + flags);
+                    + ", reason=" + reason + ", flags=" + flags + ", uid=" + uid);
         }
 
         if (eventTime < mLastWakeTime
@@ -1060,14 +1060,24 @@
 
         switch (reason) {
             case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
-                Slog.i(TAG, "Going to sleep due to device administration policy...");
+                Slog.i(TAG, "Going to sleep due to device administration policy "
+                        + "(uid " + uid +")...");
                 break;
             case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
-                Slog.i(TAG, "Going to sleep due to screen timeout...");
+                Slog.i(TAG, "Going to sleep due to screen timeout (uid " + uid +")...");
+                break;
+            case PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH:
+                Slog.i(TAG, "Going to sleep due to lid switch (uid " + uid +")...");
+                break;
+            case PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON:
+                Slog.i(TAG, "Going to sleep due to power button (uid " + uid +")...");
+                break;
+            case PowerManager.GO_TO_SLEEP_REASON_HDMI:
+                Slog.i(TAG, "Going to sleep due to HDMI standby (uid " + uid +")...");
                 break;
             default:
-                Slog.i(TAG, "Going to sleep by user request...");
-                reason = PowerManager.GO_TO_SLEEP_REASON_USER;
+                Slog.i(TAG, "Going to sleep by application request (uid " + uid +")...");
+                reason = PowerManager.GO_TO_SLEEP_REASON_APPLICATION;
                 break;
         }
 
@@ -1094,22 +1104,22 @@
 
         // Skip dozing if requested.
         if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) {
-            reallyGoToSleepNoUpdateLocked(eventTime);
+            reallyGoToSleepNoUpdateLocked(eventTime, uid);
         }
         return true;
     }
 
-    private void napInternal(long eventTime) {
+    private void napInternal(long eventTime, int uid) {
         synchronized (mLock) {
-            if (napNoUpdateLocked(eventTime)) {
+            if (napNoUpdateLocked(eventTime, uid)) {
                 updatePowerStateLocked();
             }
         }
     }
 
-    private boolean napNoUpdateLocked(long eventTime) {
+    private boolean napNoUpdateLocked(long eventTime, int uid) {
         if (DEBUG_SPEW) {
-            Slog.d(TAG, "napNoUpdateLocked: eventTime=" + eventTime);
+            Slog.d(TAG, "napNoUpdateLocked: eventTime=" + eventTime + ", uid=" + uid);
         }
 
         if (eventTime < mLastWakeTime || mWakefulness != WAKEFULNESS_AWAKE
@@ -1117,7 +1127,7 @@
             return false;
         }
 
-        Slog.i(TAG, "Nap time...");
+        Slog.i(TAG, "Nap time (uid " + uid +")...");
 
         mDirty |= DIRTY_WAKEFULNESS;
         mWakefulness = WAKEFULNESS_DREAMING;
@@ -1127,9 +1137,10 @@
     }
 
     // Done dozing, drop everything and go to sleep.
-    private boolean reallyGoToSleepNoUpdateLocked(long eventTime) {
+    private boolean reallyGoToSleepNoUpdateLocked(long eventTime, int uid) {
         if (DEBUG_SPEW) {
-            Slog.d(TAG, "reallyGoToSleepNoUpdateLocked: eventTime=" + eventTime);
+            Slog.d(TAG, "reallyGoToSleepNoUpdateLocked: eventTime=" + eventTime
+                    + ", uid=" + uid);
         }
 
         if (eventTime < mLastWakeTime || mWakefulness == WAKEFULNESS_ASLEEP
@@ -1137,7 +1148,7 @@
             return false;
         }
 
-        Slog.i(TAG, "Sleeping...");
+        Slog.i(TAG, "Sleeping (uid " + uid +")...");
 
         mDirty |= DIRTY_WAKEFULNESS;
         mWakefulness = WAKEFULNESS_ASLEEP;
@@ -1251,7 +1262,7 @@
                 final long now = SystemClock.uptimeMillis();
                 if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType,
                         dockedOnWirelessCharger)) {
-                    wakeUpNoUpdateLocked(now);
+                    wakeUpNoUpdateLocked(now, Process.SYSTEM_UID);
                 }
                 userActivityNoUpdateLocked(
                         now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
@@ -1509,10 +1520,10 @@
                 }
                 final long time = SystemClock.uptimeMillis();
                 if (shouldNapAtBedTimeLocked()) {
-                    changed = napNoUpdateLocked(time);
+                    changed = napNoUpdateLocked(time, Process.SYSTEM_UID);
                 } else {
                     changed = goToSleepNoUpdateLocked(time,
-                            PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0);
+                            PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);
                 }
             }
         }
@@ -1659,10 +1670,10 @@
                 // Dream has ended or will be stopped.  Update the power state.
                 if (isItBedTimeYetLocked()) {
                     goToSleepNoUpdateLocked(SystemClock.uptimeMillis(),
-                            PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0);
+                            PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);
                     updatePowerStateLocked();
                 } else {
-                    wakeUpNoUpdateLocked(SystemClock.uptimeMillis());
+                    wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), Process.SYSTEM_UID);
                     updatePowerStateLocked();
                 }
             } else if (wakefulness == WAKEFULNESS_DOZING) {
@@ -1671,7 +1682,7 @@
                 }
 
                 // Doze has ended or will be stopped.  Update the power state.
-                reallyGoToSleepNoUpdateLocked(SystemClock.uptimeMillis());
+                reallyGoToSleepNoUpdateLocked(SystemClock.uptimeMillis(), Process.SYSTEM_UID);
                 updatePowerStateLocked();
             }
         }
@@ -2852,9 +2863,10 @@
             mContext.enforceCallingOrSelfPermission(
                     android.Manifest.permission.DEVICE_POWER, null);
 
+            final int uid = Binder.getCallingUid();
             final long ident = Binder.clearCallingIdentity();
             try {
-                wakeUpInternal(eventTime);
+                wakeUpInternal(eventTime, uid);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -2869,9 +2881,10 @@
             mContext.enforceCallingOrSelfPermission(
                     android.Manifest.permission.DEVICE_POWER, null);
 
+            final int uid = Binder.getCallingUid();
             final long ident = Binder.clearCallingIdentity();
             try {
-                goToSleepInternal(eventTime, reason, flags);
+                goToSleepInternal(eventTime, reason, flags, uid);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -2886,9 +2899,10 @@
             mContext.enforceCallingOrSelfPermission(
                     android.Manifest.permission.DEVICE_POWER, null);
 
+            final int uid = Binder.getCallingUid();
             final long ident = Binder.clearCallingIdentity();
             try {
-                napInternal(eventTime);
+                napInternal(eventTime, uid);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
diff --git a/services/core/java/com/android/server/trust/TrustArchive.java b/services/core/java/com/android/server/trust/TrustArchive.java
index d4ed86d..7253716 100644
--- a/services/core/java/com/android/server/trust/TrustArchive.java
+++ b/services/core/java/com/android/server/trust/TrustArchive.java
@@ -129,8 +129,8 @@
             }
             switch (ev.type) {
                 case TYPE_GRANT_TRUST:
-                    writer.printf(", message=\"%s\", duration=%s",
-                            ev.message, formatDuration(ev.duration));
+                    writer.printf(", message=\"%s\", duration=%s, initiatedByUser=%d",
+                            ev.message, formatDuration(ev.duration), ev.userInitiated ? 1 : 0);
                     break;
                 case TYPE_MANAGING_TRUST:
                     writer.printf(", managingTrust=" + ev.managingTrust);
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index badead6..490536e 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -93,7 +93,7 @@
 
     private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<AgentInfo>();
     private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<ITrustListener>();
-    private final DevicePolicyReceiver mDevicePolicyReceiver = new DevicePolicyReceiver();
+    private final Receiver mReceiver = new Receiver();
     private final SparseBooleanArray mUserHasAuthenticatedSinceBoot = new SparseBooleanArray();
     /* package */ final TrustArchive mArchive = new TrustArchive();
     private final Context mContext;
@@ -115,7 +115,7 @@
     public void onBootPhase(int phase) {
         if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY && !isSafeMode()) {
             mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
-            mDevicePolicyReceiver.register(mContext);
+            mReceiver.register(mContext);
             refreshAgentList();
         }
     }
@@ -373,7 +373,13 @@
             }
         }
 
-        if (successful && !mUserHasAuthenticatedSinceBoot.get(userId)) {
+        if (successful) {
+            updateUserHasAuthenticated(userId);
+        }
+    }
+
+    private void updateUserHasAuthenticated(int userId) {
+        if (!mUserHasAuthenticatedSinceBoot.get(userId)) {
             mUserHasAuthenticatedSinceBoot.put(userId, true);
             updateTrust(userId, false);
         }
@@ -597,7 +603,7 @@
         }
     };
 
-    private class DevicePolicyReceiver extends BroadcastReceiver {
+    private class Receiver extends BroadcastReceiver {
 
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -605,14 +611,18 @@
                     intent.getAction())) {
                 refreshAgentList();
                 updateDevicePolicyFeatures(getSendingUserId());
+            } else if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {
+                updateUserHasAuthenticated(getSendingUserId());
             }
         }
 
         public void register(Context context) {
+            IntentFilter filter = new IntentFilter();
+            filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
+            filter.addAction(Intent.ACTION_USER_PRESENT);
             context.registerReceiverAsUser(this,
                     UserHandle.ALL,
-                    new IntentFilter(
-                            DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
+                    filter,
                     null /* permission */,
                     null /* scheduler */);
         }
diff --git a/services/core/java/com/android/server/tv/PersistentDataStore.java b/services/core/java/com/android/server/tv/PersistentDataStore.java
index 852e640..05a2bde 100644
--- a/services/core/java/com/android/server/tv/PersistentDataStore.java
+++ b/services/core/java/com/android/server/tv/PersistentDataStore.java
@@ -20,6 +20,7 @@
 import android.content.Intent;
 import android.media.tv.TvContentRating;
 import android.media.tv.TvInputManager;
+import android.os.Environment;
 import android.os.Handler;
 import android.os.UserHandle;
 import android.text.TextUtils;
@@ -81,8 +82,13 @@
 
     public PersistentDataStore(Context context, int userId) {
         mContext = context;
-        mAtomicFile = new AtomicFile(new File("/data/system/tv/" + userId
-                + "/tv-input-manager-state.xml"));
+        File userDir = Environment.getUserSystemDirectory(userId);
+        if (!userDir.exists()) {
+            if (!userDir.mkdirs()) {
+                throw new IllegalStateException("User dir cannot be created: " + userDir);
+            }
+        }
+        mAtomicFile = new AtomicFile(new File(userDir, "tv-input-manager-state.xml"));
     }
 
     public boolean isParentalControlsEnabled() {
@@ -91,6 +97,7 @@
     }
 
     public void setParentalControlsEnabled(boolean enabled) {
+        loadIfNeeded();
         if (mParentalControlsEnabled != enabled) {
             mParentalControlsEnabled = enabled;
             mParentalControlsEnabledChanged = true;
@@ -114,6 +121,7 @@
     }
 
     public void addBlockedRating(TvContentRating rating) {
+        loadIfNeeded();
         if (rating != null && !mBlockedRatings.contains(rating)) {
             mBlockedRatings.add(rating);
             mBlockedRatingsChanged = true;
@@ -122,6 +130,7 @@
     }
 
     public void removeBlockedRating(TvContentRating rating) {
+        loadIfNeeded();
         if (rating != null && mBlockedRatings.contains(rating)) {
             mBlockedRatings.remove(rating);
             mBlockedRatingsChanged = true;
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index c916507..78ea6c9 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -55,6 +55,7 @@
 import android.view.KeyEvent;
 import android.view.Surface;
 
+import com.android.internal.os.SomeArgs;
 import com.android.server.SystemService;
 
 import java.util.ArrayList;
@@ -877,7 +878,7 @@
         public void onHardwareDeviceRemoved(TvInputHardwareInfo info);
         public void onHdmiDeviceAdded(HdmiDeviceInfo device);
         public void onHdmiDeviceRemoved(HdmiDeviceInfo device);
-        public void onHdmiDeviceUpdated(HdmiDeviceInfo device);
+        public void onHdmiDeviceUpdated(String inputId, HdmiDeviceInfo device);
     }
 
     private class ListenerHandler extends Handler {
@@ -918,8 +919,11 @@
                     break;
                 }
                 case HDMI_DEVICE_UPDATED: {
-                    HdmiDeviceInfo info = (HdmiDeviceInfo) msg.obj;
-                    mListener.onHdmiDeviceUpdated(info);
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    String inputId = (String) args.arg1;
+                    HdmiDeviceInfo info = (HdmiDeviceInfo) args.arg2;
+                    args.recycle();
+                    mListener.onHdmiDeviceUpdated(inputId, info);
                 }
                 default: {
                     Slog.w(TAG, "Unhandled message: " + msg);
@@ -956,6 +960,7 @@
         public void onStatusChanged(HdmiDeviceInfo deviceInfo, int status) {
             synchronized (mLock) {
                 int messageType = 0;
+                Object obj = null;
                 switch (status) {
                     case HdmiControlManager.DEVICE_EVENT_ADD_DEVICE: {
                         if (!mHdmiDeviceList.contains(deviceInfo)) {
@@ -965,6 +970,7 @@
                             return;
                         }
                         messageType = ListenerHandler.HDMI_DEVICE_ADDED;
+                        obj = deviceInfo;
                         break;
                     }
                     case HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE: {
@@ -973,6 +979,7 @@
                             return;
                         }
                         messageType = ListenerHandler.HDMI_DEVICE_REMOVED;
+                        obj = deviceInfo;
                         break;
                     }
                     case HdmiControlManager.DEVICE_EVENT_UPDATE_DEVICE: {
@@ -982,11 +989,16 @@
                         }
                         mHdmiDeviceList.add(deviceInfo);
                         messageType = ListenerHandler.HDMI_DEVICE_UPDATED;
+                        String inputId = mHdmiInputIdMap.get(deviceInfo.getLogicalAddress());
+                        SomeArgs args = SomeArgs.obtain();
+                        args.arg1 = inputId;
+                        args.arg2 = deviceInfo;
+                        obj = args;
                         break;
                     }
                 }
 
-                Message msg = mHandler.obtainMessage(messageType, 0, 0, deviceInfo);
+                Message msg = mHandler.obtainMessage(messageType, 0, 0, obj);
                 if (findHardwareInfoForHdmiPortLocked(deviceInfo.getPortId()) != null) {
                     msg.sendToTarget();
                 } else {
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index dc5bc84..3b5e79d 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -17,6 +17,7 @@
 package com.android.server.tv;
 
 import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED;
+import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED_STANDBY;
 import static android.media.tv.TvInputManager.INPUT_STATE_DISCONNECTED;
 
 import android.app.ActivityManager;
@@ -36,6 +37,7 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.graphics.Rect;
+import android.hardware.hdmi.HdmiControlManager;
 import android.hardware.hdmi.HdmiDeviceInfo;
 import android.media.tv.ITvInputClient;
 import android.media.tv.ITvInputHardware;
@@ -212,8 +214,6 @@
 
     private void buildTvInputListLocked(int userId) {
         UserState userState = getUserStateLocked(userId);
-
-        Map<String, TvInputState> inputMap = new HashMap<String, TvInputState>();
         userState.packageSet.clear();
 
         if (DEBUG) Slog.d(TAG, "buildTvInputList");
@@ -229,41 +229,42 @@
                         + android.Manifest.permission.BIND_TV_INPUT);
                 continue;
             }
-            try {
-                inputList.clear();
-                ComponentName component = new ComponentName(si.packageName, si.name);
-                if (hasHardwarePermission(pm, component)) {
-                    ServiceState serviceState = userState.serviceStateMap.get(component);
-                    if (serviceState == null) {
-                        // We see this hardware TV input service for the first time; we need to
-                        // prepare the ServiceState object so that we can connect to the service and
-                        // let it add TvInputInfo objects to mInputList if there's any.
-                        serviceState = new ServiceState(component, userId);
-                        userState.serviceStateMap.put(component, serviceState);
-                    } else {
-                        inputList.addAll(serviceState.mInputList);
-                    }
+
+            ComponentName component = new ComponentName(si.packageName, si.name);
+            if (hasHardwarePermission(pm, component)) {
+                ServiceState serviceState = userState.serviceStateMap.get(component);
+                if (serviceState == null) {
+                    // We see this hardware TV input service for the first time; we need to
+                    // prepare the ServiceState object so that we can connect to the service and
+                    // let it add TvInputInfo objects to mInputList if there's any.
+                    serviceState = new ServiceState(component, userId);
+                    userState.serviceStateMap.put(component, serviceState);
                 } else {
+                    inputList.addAll(serviceState.mInputList);
+                }
+            } else {
+                try {
                     inputList.add(TvInputInfo.createTvInputInfo(mContext, ri));
+                } catch (XmlPullParserException | IOException e) {
+                    Slog.e(TAG, "Failed to load TV input " + si.name, e);
+                    continue;
                 }
-
-                for (TvInputInfo info : inputList) {
-                    if (DEBUG) Slog.d(TAG, "add " + info.getId());
-                    TvInputState state = userState.inputMap.get(info.getId());
-                    if (state == null) {
-                        state = new TvInputState();
-                    }
-                    state.mInfo = info;
-                    inputMap.put(info.getId(), state);
-                }
-
-                // Reconnect the service if existing input is updated.
-                updateServiceConnectionLocked(component, userId);
-
-                userState.packageSet.add(si.packageName);
-            } catch (IOException | XmlPullParserException e) {
-                Slog.e(TAG, "Can't load TV input " + si.name, e);
             }
+
+            // Reconnect the service if existing input is updated.
+            updateServiceConnectionLocked(component, userId);
+            userState.packageSet.add(si.packageName);
+        }
+
+        Map<String, TvInputState> inputMap = new HashMap<String, TvInputState>();
+        for (TvInputInfo info : inputList) {
+            if (DEBUG) Slog.d(TAG, "add " + info.getId());
+            TvInputState state = userState.inputMap.get(info.getId());
+            if (state == null) {
+                state = new TvInputState();
+            }
+            state.mInfo = info;
+            inputMap.put(info.getId(), state);
         }
 
         for (String inputId : inputMap.keySet()) {
@@ -338,7 +339,6 @@
                         Slog.e(TAG, "error in unregisterCallback", e);
                     }
                 }
-                serviceState.mClientTokens.clear();
                 mContext.unbindService(serviceState.mConnection);
             }
             userState.serviceStateMap.clear();
@@ -401,9 +401,7 @@
     }
 
     private static boolean shouldMaintainConnection(ServiceState serviceState) {
-        return !serviceState.mClientTokens.isEmpty()
-                || !serviceState.mSessionTokens.isEmpty()
-                || serviceState.mIsHardware;
+        return !serviceState.mSessionTokens.isEmpty() || serviceState.mIsHardware;
         // TODO: Find a way to maintain connection only when necessary.
     }
 
@@ -996,12 +994,13 @@
         }
 
         private void ensureParentalControlsPermission() {
-            if (mContext.checkCallingPermission(
-                    android.Manifest.permission.MODIFY_PARENTAL_CONTROLS)
-                    != PackageManager.PERMISSION_GRANTED) {
-                throw new SecurityException(
-                        "The caller does not have parental controls permission");
-            }
+            // STOPSHIP: Uncomment when b/16984416 is resolved.
+            //if (mContext.checkCallingPermission(
+            //        android.Manifest.permission.MODIFY_PARENTAL_CONTROLS)
+            //        != PackageManager.PERMISSION_GRANTED) {
+            //    throw new SecurityException(
+            //            "The caller does not have parental controls permission");
+            //}
         }
 
         @Override
@@ -1610,13 +1609,6 @@
 
                         pw.increaseIndent();
 
-                        pw.println("mClientTokens:");
-                        pw.increaseIndent();
-                        for (IBinder token : service.mClientTokens) {
-                            pw.println("" + token);
-                        }
-                        pw.decreaseIndent();
-
                         pw.println("mSessionTokens:");
                         pw.increaseIndent();
                         for (IBinder token : service.mSessionTokens) {
@@ -1753,7 +1745,6 @@
     }
 
     private final class ServiceState {
-        private final List<IBinder> mClientTokens = new ArrayList<IBinder>();
         private final List<IBinder> mSessionTokens = new ArrayList<IBinder>();
         private final ServiceConnection mConnection;
         private final ComponentName mComponent;
@@ -1808,7 +1799,7 @@
                 // If there are any other sessions based on this session, they should be released.
                 UserState userState = getUserStateLocked(mUserId);
                 for (SessionState sessionState : userState.sessionStateMap.values()) {
-                    if (mSession != null && mSession == sessionState.mHardwareSessionToken) {
+                    if (mSessionToken == sessionState.mHardwareSessionToken) {
                         try {
                             sessionState.mSession.release();
                         } catch (RemoteException e) {
@@ -2176,8 +2167,27 @@
         }
 
         @Override
-        public void onHdmiDeviceUpdated(HdmiDeviceInfo deviceInfo) {
-            // TODO: implement here.
+        public void onHdmiDeviceUpdated(String inputId, HdmiDeviceInfo deviceInfo) {
+            synchronized (mLock) {
+                Integer state = null;
+                switch (deviceInfo.getDevicePowerStatus()) {
+                    case HdmiControlManager.POWER_STATUS_ON:
+                        state = INPUT_STATE_CONNECTED;
+                        break;
+                    case HdmiControlManager.POWER_STATUS_STANDBY:
+                    case HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON:
+                    case HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY:
+                        state = INPUT_STATE_CONNECTED_STANDBY;
+                        break;
+                    case HdmiControlManager.POWER_STATUS_UNKNOWN:
+                    default:
+                        state = null;
+                        break;
+                }
+                if (state != null) {
+                    setStateLocked(inputId, state.intValue(), mCurrentUserId);
+                }
+            }
         }
     }
 }
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 0e1340c..f6ec86d 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -159,7 +159,7 @@
     private final int mConfigShortAnimTime;
     private final Interpolator mDecelerateInterpolator;
     private final Interpolator mThumbnailFadeoutInterpolator;
-    private final Interpolator mThumbnailCubicInterpolator;
+    private final Interpolator mThumbnailFastOutSlowInInterpolator;
 
     private int mCurrentUserId = 0;
 
@@ -170,7 +170,7 @@
                 com.android.internal.R.integer.config_shortAnimTime);
         mDecelerateInterpolator = AnimationUtils.loadInterpolator(context,
                 com.android.internal.R.interpolator.decelerate_cubic);
-        mThumbnailCubicInterpolator = AnimationUtils.loadInterpolator(context,
+        mThumbnailFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
                 com.android.internal.R.interpolator.fast_out_slow_in);
         mThumbnailFadeoutInterpolator = new Interpolator() {
             @Override
@@ -635,7 +635,7 @@
         }
 
         return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight,
-                THUMBNAIL_APP_TRANSITION_DURATION, mThumbnailCubicInterpolator);
+                THUMBNAIL_APP_TRANSITION_DURATION, mThumbnailFastOutSlowInInterpolator);
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 32e8afe..4edd5cf 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -88,6 +88,8 @@
     boolean mInitialized = false;
 
     boolean mKeyguardGoingAway;
+    boolean mKeyguardGoingAwayToNotificationShade;
+    boolean mKeyguardGoingAwayDisableWindowAnimations;
 
     // forceHiding states.
     static final int KEYGUARD_NOT_SHOWN     = 0;
@@ -389,7 +391,11 @@
         if (unForceHiding != null) {
             boolean startKeyguardExit = true;
             for (int i=unForceHiding.size()-1; i>=0; i--) {
-                Animation a = mPolicy.createForceHideEnterAnimation(wallpaperInUnForceHiding);
+                Animation a = null;
+                if (!mKeyguardGoingAwayDisableWindowAnimations) {
+                    a = mPolicy.createForceHideEnterAnimation(wallpaperInUnForceHiding,
+                            mKeyguardGoingAwayToNotificationShade);
+                }
                 if (a != null) {
                     final WindowStateAnimator winAnimator = unForceHiding.get(i);
                     winAnimator.setAnimation(a);
@@ -405,9 +411,14 @@
             }
 
             // Wallpaper is going away in un-force-hide motion, animate it as well.
-            if (!wallpaperInUnForceHiding && wallpaper != null) {
-                WindowStateAnimator animator = wallpaper.mWinAnimator;
-                animator.setAnimation(mPolicy.createForceHideWallpaperExitAnimation());
+            if (!wallpaperInUnForceHiding && wallpaper != null
+                    && !mKeyguardGoingAwayDisableWindowAnimations) {
+                Animation a = mPolicy.createForceHideWallpaperExitAnimation(
+                        mKeyguardGoingAwayToNotificationShade);
+                if (a != null) {
+                    WindowStateAnimator animator = wallpaper.mWinAnimator;
+                    animator.setAnimation(a);
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e7ebae7..711cf9c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -462,6 +462,9 @@
     int mRotation = 0;
     int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
     boolean mAltOrientation = false;
+
+    private boolean mKeyguardWaitingForActivityDrawn;
+
     class RotationWatcher {
         IRotationWatcher watcher;
         IBinder.DeathRecipient deathRecipient;
@@ -2311,6 +2314,10 @@
                             + attrs.token + ".  Aborting.");
                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
+            } else if (token.appWindowToken != null) {
+                Slog.i(TAG, "Non-null appWindowToken for system window of type=" + type);
+                // app token should be null for any other window types.
+                token.appWindowToken = null;
             }
 
             win = new WindowState(this, session, client, token,
@@ -5236,17 +5243,35 @@
     }
 
     @Override
-    public void keyguardGoingAway() {
+    public void keyguardGoingAway(boolean disableWindowAnimations,
+            boolean keyguardGoingToNotificationShade) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
                 != PackageManager.PERMISSION_GRANTED) {
             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
         }
         synchronized (mWindowMap) {
             mAnimator.mKeyguardGoingAway = true;
+            mAnimator.mKeyguardGoingAwayToNotificationShade = keyguardGoingToNotificationShade;
+            mAnimator.mKeyguardGoingAwayDisableWindowAnimations = disableWindowAnimations;
             requestTraversalLocked();
         }
     }
 
+    public void keyguardWaitingForActivityDrawn() {
+        synchronized (mWindowMap) {
+            mKeyguardWaitingForActivityDrawn = true;
+        }
+    }
+
+    public void notifyActivityDrawnForKeyguard() {
+        synchronized (mWindowMap) {
+            if (mKeyguardWaitingForActivityDrawn) {
+                mPolicy.notifyActivityDrawnForKeyguardLw();
+                mKeyguardWaitingForActivityDrawn = false;
+            }
+        }
+    }
+
     void showGlobalActions() {
         mPolicy.showGlobalActions();
     }
diff --git a/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp b/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
index 2519ff8..37a3eaa 100644
--- a/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
+++ b/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
@@ -66,7 +66,12 @@
   }
 
   ALOGE("Error %d in '%s'", resultCode, methodName);
-  env->FatalError(methodName);
+  // TODO: this layer needs to be refactored to return error codes to Java
+  // raising a FatalError is harsh, and because FLP Hardware Provider is loaded inside the system
+  // service, it can cause the device to reboot, or remain in a reboot loop
+  // a simple exception is still dumped to logcat, but it is handled more gracefully
+  jclass exceptionClass = env->FindClass("java/lang/RuntimeException");
+  env->ThrowNew(exceptionClass, methodName);
 }
 
 static bool IsValidCallbackThread() {
diff --git a/services/core/jni/com_android_server_location_GpsLocationProvider.cpp b/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
index 46327d7..c398908 100644
--- a/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
@@ -28,6 +28,7 @@
 #include "android_runtime/AndroidRuntime.h"
 #include "android_runtime/Log.h"
 
+#include <arpa/inet.h>
 #include <string.h>
 #include <pthread.h>
 #include <linux/in.h>
@@ -189,8 +190,10 @@
 
     jbyte ipv4[4];
     if (net_order) {
+        ALOGV("Converting IPv4 address(net_order) %x", ip);
         memcpy(ipv4, &ip, sizeof(ipv4));
     } else {
+        ALOGV("Converting IPv4 address(host_order) %x", ip);
         //endianess transparent conversion from int to char[]
         ipv4[0] = (jbyte) (ip & 0xFF);
         ipv4[1] = (jbyte)((ip>>8) & 0xFF);
@@ -210,6 +213,7 @@
 
     size_t status_size = agps_status->size;
     if (status_size == sizeof(AGpsStatus_v3)) {
+      ALOGV("AGpsStatus is V3: %d", status_size);
       switch (agps_status->addr.ss_family)
       {
       case AF_INET:
@@ -220,6 +224,12 @@
             if (byteArray != NULL) {
                 isSupported = true;
             }
+            IF_ALOGD() {
+                // log the IP for reference in case there is a bogus value pushed by HAL
+                char str[INET_ADDRSTRLEN];
+                inet_ntop(AF_INET, &(in->sin_addr), str, INET_ADDRSTRLEN);
+                ALOGD("AGPS IP is v4: %s", str);
+            }
           }
           break;
       case AF_INET6:
@@ -232,6 +242,12 @@
             } else {
                 ALOGE("Unable to allocate byte array for IPv6 address.");
             }
+            IF_ALOGD() {
+                // log the IP for reference in case there is a bogus value pushed by HAL
+                char str[INET6_ADDRSTRLEN];
+                inet_ntop(AF_INET6, &(in6->sin6_addr), str, INET6_ADDRSTRLEN);
+                ALOGD("AGPS IP is v6: %s", str);
+            }
           }
           break;
       default:
@@ -239,14 +255,17 @@
           break;
       }
     } else if (status_size >= sizeof(AGpsStatus_v2)) {
+      ALOGV("AGpsStatus is V2+: %d", status_size);
       // for back-compatibility reasons we check in v2 that the data structure size is greater or
       // equal to the declared size in gps.h
       uint32_t ipaddr = agps_status->ipaddr;
+      ALOGV("AGPS IP is v4: %x", ipaddr);
       byteArray = convert_to_ipv4(ipaddr, false /* net_order */);
       if (ipaddr == INADDR_NONE || byteArray != NULL) {
           isSupported = true;
       }
     } else if (status_size >= sizeof(AGpsStatus_v1)) {
+        ALOGV("AGpsStatus is V1+: %d", status_size);
         // because we have to check for >= with regards to v2, we also need to relax the check here
         // and only make sure that the size is at least what we expect
         isSupported = true;
@@ -255,6 +274,8 @@
     }
 
     if (isSupported) {
+        jsize byteArrayLength = byteArray != NULL ? env->GetArrayLength(byteArray) : 0;
+        ALOGV("Passing AGPS IP addr: size %d", byteArrayLength);
         env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus, agps_status->type,
                             agps_status->status, byteArray);
 
diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
index 8aae695..c3d4ed9 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
@@ -47,7 +47,6 @@
 import static org.easymock.EasyMock.expectLastCall;
 import static org.easymock.EasyMock.isA;
 
-import android.app.AlarmClockInfo;
 import android.app.AlarmManager;
 import android.app.IAlarmManager;
 import android.app.PendingIntent;
@@ -880,7 +879,8 @@
         expectLastCall().anyTimes();
 
         mAlarmManager.set(eq(AlarmManager.ELAPSED_REALTIME), anyLong(), anyLong(), anyLong(),
-                isA(PendingIntent.class), isA(WorkSource.class), isA(AlarmClockInfo.class));
+                isA(PendingIntent.class), isA(WorkSource.class),
+                isA(AlarmManager.AlarmClockInfo.class));
         expectLastCall().atLeastOnce();
 
         mNetManager.setGlobalAlert(anyLong());
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 2e309be..6e13732 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -47,6 +47,18 @@
                 }
             }
         }, filter);
+
+        removeExistingUsers();
+    }
+
+    private void removeExistingUsers() {
+        List<UserInfo> list = mUserManager.getUsers();
+        boolean found = false;
+        for (UserInfo user : list) {
+            if (user.id != UserHandle.USER_OWNER) {
+                removeUser(user.id);
+            }
+        }
     }
 
     public void testHasPrimary() throws Exception {
@@ -95,6 +107,29 @@
         assertFalse(findUser(userInfo.id));
     }
 
+    public void testAddGuest() throws Exception {
+        UserInfo userInfo1 = mUserManager.createUser("Guest 1", UserInfo.FLAG_GUEST);
+        UserInfo userInfo2 = mUserManager.createUser("Guest 2", UserInfo.FLAG_GUEST);
+        assertNotNull(userInfo1);
+        assertNull(userInfo2);
+
+        // Cleanup
+        removeUser(userInfo1.id);
+    }
+
+    // Make sure only one managed profile can be created
+    public void testAddManagedProfile() throws Exception {
+        UserInfo userInfo1 = mUserManager.createProfileForUser("Managed 1",
+                UserInfo.FLAG_MANAGED_PROFILE, UserHandle.USER_OWNER);
+        UserInfo userInfo2 = mUserManager.createProfileForUser("Managed 2",
+                UserInfo.FLAG_MANAGED_PROFILE, UserHandle.USER_OWNER);
+        assertNotNull(userInfo1);
+        assertNull(userInfo2);
+
+        // Cleanup
+        removeUser(userInfo1.id);
+    }
+
     private boolean findUser(int id) {
         List<UserInfo> list = mUserManager.getUsers();
 
diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java
index bcbae60..5860fc7 100644
--- a/services/usb/java/com/android/server/usb/UsbHostManager.java
+++ b/services/usb/java/com/android/server/usb/UsbHostManager.java
@@ -314,14 +314,22 @@
         mConnectedUsbCard = cardsParser.getNumCardRecords() - 1;
         mConnectedUsbDeviceNum = 0;
 
-        if (!waitForAlsaFile(mConnectedUsbCard, mConnectedUsbDeviceNum, false)) {
-            return;
-        }
-
         mConnectedHasPlayback = devicesParser.hasPlaybackDevices(mConnectedUsbCard);
         mConnectedHasCapture = devicesParser.hasCaptureDevices(mConnectedUsbCard);
         mConnectedHasMIDI = devicesParser.hasMIDIDevices(mConnectedUsbCard);
 
+        // Playback device file needed/present?
+        if (mConnectedHasPlayback &&
+            !waitForAlsaFile(mConnectedUsbCard, mConnectedUsbDeviceNum, false)) {
+            return;
+        }
+
+        // Capture device file needed/present?
+        if (mConnectedHasCapture &&
+            !waitForAlsaFile(mConnectedUsbCard, mConnectedUsbDeviceNum, true)) {
+            return;
+        }
+
         if (DEBUG_AUDIO) {
             Slog.d(TAG,
                     "usb: hasPlayback:" + mConnectedHasPlayback + " hasCapture:" + mConnectedHasCapture);
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
index f0ecafe..cc0d8df 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
@@ -130,8 +130,8 @@
 
         synchronized(this) {
             SQLiteDatabase db = getWritableDatabase();
-            String soundModelClause = SoundModelContract.KEY_MODEL_UUID + "="
-                    + modelUuid.toString();
+            String soundModelClause = SoundModelContract.KEY_MODEL_UUID + "='"
+                    + modelUuid.toString() + "'";
 
             try {
                 return db.delete(SoundModelContract.TABLE, soundModelClause, null) != 0;
diff --git a/telecomm/java/android/telecomm/CallAudioState.aidl b/telecomm/java/android/telecomm/AudioState.aidl
similarity index 93%
rename from telecomm/java/android/telecomm/CallAudioState.aidl
rename to telecomm/java/android/telecomm/AudioState.aidl
index ae64567..03772b6 100644
--- a/telecomm/java/android/telecomm/CallAudioState.aidl
+++ b/telecomm/java/android/telecomm/AudioState.aidl
@@ -16,4 +16,7 @@
 
 package android.telecomm;
 
-parcelable CallAudioState;
+/**
+ * {@hide}
+ */
+parcelable AudioState;
diff --git a/telecomm/java/android/telecomm/CallAudioState.java b/telecomm/java/android/telecomm/AudioState.java
similarity index 82%
rename from telecomm/java/android/telecomm/CallAudioState.java
rename to telecomm/java/android/telecomm/AudioState.java
index d9a0090..dc28b16 100644
--- a/telecomm/java/android/telecomm/CallAudioState.java
+++ b/telecomm/java/android/telecomm/AudioState.java
@@ -24,7 +24,7 @@
 /**
  *  Encapsulates all audio states during a call.
  */
-public final class CallAudioState implements Parcelable {
+public final class AudioState implements Parcelable {
     /** Direct the audio stream through the device's earpiece. */
     public static int ROUTE_EARPIECE      = 0x00000001;
 
@@ -57,14 +57,14 @@
     public final int supportedRouteMask;
 
     /** @hide */
-    public CallAudioState(boolean isMuted, int route, int supportedRouteMask) {
+    public AudioState(boolean isMuted, int route, int supportedRouteMask) {
         this.isMuted = isMuted;
         this.route = route;
         this.supportedRouteMask = supportedRouteMask;
     }
 
     /** @hide */
-    public CallAudioState(CallAudioState state) {
+    public AudioState(AudioState state) {
         isMuted = state.isMuted;
         route = state.route;
         supportedRouteMask = state.supportedRouteMask;
@@ -75,10 +75,10 @@
         if (obj == null) {
             return false;
         }
-        if (!(obj instanceof CallAudioState)) {
+        if (!(obj instanceof AudioState)) {
             return false;
         }
-        CallAudioState state = (CallAudioState) obj;
+        AudioState state = (AudioState) obj;
         return isMuted == state.isMuted && route == state.route &&
                 supportedRouteMask == state.supportedRouteMask;
     }
@@ -86,7 +86,7 @@
     @Override
     public String toString() {
         return String.format(Locale.US,
-                "[CallAudioState isMuted: %b, route; %s, supportedRouteMask: %s]",
+                "[AudioState isMuted: %b, route; %s, supportedRouteMask: %s]",
                 isMuted, audioRouteToString(route), audioRouteToString(supportedRouteMask));
     }
 
@@ -121,22 +121,22 @@
     }
 
     /**
-     * Responsible for creating CallAudioState objects for deserialized Parcels.
+     * Responsible for creating AudioState objects for deserialized Parcels.
      */
-    public static final Parcelable.Creator<CallAudioState> CREATOR =
-            new Parcelable.Creator<CallAudioState> () {
+    public static final Parcelable.Creator<AudioState> CREATOR =
+            new Parcelable.Creator<AudioState> () {
 
         @Override
-        public CallAudioState createFromParcel(Parcel source) {
+        public AudioState createFromParcel(Parcel source) {
             boolean isMuted = source.readByte() == 0 ? false : true;
             int route = source.readInt();
             int supportedRouteMask = source.readInt();
-            return new CallAudioState(isMuted, route, supportedRouteMask);
+            return new AudioState(isMuted, route, supportedRouteMask);
         }
 
         @Override
-        public CallAudioState[] newArray(int size) {
-            return new CallAudioState[size];
+        public AudioState[] newArray(int size) {
+            return new AudioState[size];
         }
     };
 
@@ -149,7 +149,7 @@
     }
 
     /**
-     * Writes CallAudioState object into a serializeable Parcel.
+     * Writes AudioState object into a serializeable Parcel.
      */
     @Override
     public void writeToParcel(Parcel destination, int flags) {
diff --git a/telecomm/java/android/telecomm/Call.java b/telecomm/java/android/telecomm/Call.java
index 0a54c71..f988ac8 100644
--- a/telecomm/java/android/telecomm/Call.java
+++ b/telecomm/java/android/telecomm/Call.java
@@ -18,6 +18,7 @@
 
 import android.app.PendingIntent;
 import android.net.Uri;
+import android.os.Bundle;
 import android.telephony.DisconnectCause;
 
 import java.lang.String;
@@ -29,6 +30,8 @@
 
 /**
  * Represents an ongoing phone call that the in-call app should present to the user.
+ *
+ * {@hide}
  */
 public final class Call {
     /**
@@ -84,11 +87,12 @@
         private final PhoneAccountHandle mAccountHandle;
         private final int mCallCapabilities;
         private final int mDisconnectCauseCode;
-        private final String mDisconnectCauseMsg;
+        private final String mDisconnectCauseMessage;
         private final long mConnectTimeMillis;
         private final GatewayInfo mGatewayInfo;
         private final int mVideoState;
         private final StatusHints mStatusHints;
+        private final Bundle mExtras;
 
         /**
          * @return The handle (e.g., phone number) to which the {@code Call} is currently
@@ -100,7 +104,7 @@
 
         /**
          * @return The presentation requirements for the handle. See
-         * {@link android.telecomm.CallPropertyPresentation} for valid values.
+         * {@link PropertyPresentation} for valid values.
          */
         public int getHandlePresentation() {
             return mHandlePresentation;
@@ -115,7 +119,7 @@
 
         /**
          * @return The presentation requirements for the caller display name. See
-         * {@link android.telecomm.CallPropertyPresentation} for valid values.
+         * {@link PropertyPresentation} for valid values.
          */
         public int getCallerDisplayNamePresentation() {
             return mCallerDisplayNamePresentation;
@@ -131,7 +135,7 @@
 
         /**
          * @return A bitmask of the capabilities of the {@code Call}, as defined in
-         *         {@link CallCapabilities}.
+         *         {@link PhoneCapabilities}.
          */
         public int getCallCapabilities() {
             return mCallCapabilities;
@@ -149,8 +153,8 @@
          * @return For a {@link #STATE_DISCONNECTED} {@code Call}, an optional reason for
          * disconnection expressed as a free text message.
          */
-        public String getDisconnectCauseMsg() {
-            return mDisconnectCauseMsg;
+        public String getDisconnectCauseMessage() {
+            return mDisconnectCauseMessage;
         }
 
         /**
@@ -184,6 +188,13 @@
             return mStatusHints;
         }
 
+        /**
+         * @return A bundle extras to pass with the call
+         */
+        public Bundle getExtras() {
+            return mExtras;
+        }
+
         @Override
         public boolean equals(Object o) {
             if (o instanceof Details) {
@@ -197,11 +208,12 @@
                         Objects.equals(mAccountHandle, d.mAccountHandle) &&
                         Objects.equals(mCallCapabilities, d.mCallCapabilities) &&
                         Objects.equals(mDisconnectCauseCode, d.mDisconnectCauseCode) &&
-                        Objects.equals(mDisconnectCauseMsg, d.mDisconnectCauseMsg) &&
+                        Objects.equals(mDisconnectCauseMessage, d.mDisconnectCauseMessage) &&
                         Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
                         Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
                         Objects.equals(mVideoState, d.mVideoState) &&
-                        Objects.equals(mStatusHints, d.mStatusHints);
+                        Objects.equals(mStatusHints, d.mStatusHints) &&
+                        Objects.equals(mExtras, d.mExtras);
             }
             return false;
         }
@@ -216,11 +228,12 @@
                     Objects.hashCode(mAccountHandle) +
                     Objects.hashCode(mCallCapabilities) +
                     Objects.hashCode(mDisconnectCauseCode) +
-                    Objects.hashCode(mDisconnectCauseMsg) +
+                    Objects.hashCode(mDisconnectCauseMessage) +
                     Objects.hashCode(mConnectTimeMillis) +
                     Objects.hashCode(mGatewayInfo) +
                     Objects.hashCode(mVideoState) +
-                    Objects.hashCode(mStatusHints);
+                    Objects.hashCode(mStatusHints) +
+                    Objects.hashCode(mExtras);
         }
 
         /** {@hide} */
@@ -232,11 +245,12 @@
                 PhoneAccountHandle accountHandle,
                 int capabilities,
                 int disconnectCauseCode,
-                String disconnectCauseMsg,
+                String disconnectCauseMessage,
                 long connectTimeMillis,
                 GatewayInfo gatewayInfo,
                 int videoState,
-                StatusHints statusHints) {
+                StatusHints statusHints,
+                Bundle extras) {
             mHandle = handle;
             mHandlePresentation = handlePresentation;
             mCallerDisplayName = callerDisplayName;
@@ -244,11 +258,12 @@
             mAccountHandle = accountHandle;
             mCallCapabilities = capabilities;
             mDisconnectCauseCode = disconnectCauseCode;
-            mDisconnectCauseMsg = disconnectCauseMsg;
+            mDisconnectCauseMessage = disconnectCauseMessage;
             mConnectTimeMillis = connectTimeMillis;
             mGatewayInfo = gatewayInfo;
             mVideoState = videoState;
             mStatusHints = statusHints;
+            mExtras = extras;
         }
     }
 
@@ -256,8 +271,6 @@
         /**
          * Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
          *
-         * TODO: Provide previous state also?
-         *
          * @param call The {@code Call} invoking this method.
          * @param state The new state of the {@code Call}.
          */
@@ -459,8 +472,6 @@
 
     /**
      * Notifies this {@code Call} that the phone account user interface element was touched.
-     *
-     * TODO: Figure out if and how we can generalize this
      */
     public void phoneAccountClicked() {
         mInCallAdapter.phoneAccountClicked(mTelecommCallId);
@@ -495,14 +506,6 @@
     }
 
     /**
-     * Instructs this {@code Call} to swap itself with an existing background call, if one
-     * such call exists.
-     */
-    public void swapWithBackgroundCall() {
-        mInCallAdapter.swapWithBackgroundCall(mTelecommCallId);
-    }
-
-    /**
      * Obtains the parent of this {@code Call} in a conference, if any.
      *
      * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
@@ -617,7 +620,8 @@
                 parcelableCall.getConnectTimeMillis(),
                 parcelableCall.getGatewayInfo(),
                 parcelableCall.getVideoState(),
-                parcelableCall.getStatusHints());
+                parcelableCall.getStatusHints(),
+                parcelableCall.getExtras());
         boolean detailsChanged = !Objects.equals(mDetails, details);
         if (detailsChanged) {
             mDetails = details;
@@ -774,25 +778,25 @@
         }
     }
 
-    private int stateFromParcelableCallState(CallState parcelableCallState) {
+    private int stateFromParcelableCallState(int parcelableCallState) {
         switch (parcelableCallState) {
-            case NEW:
+            case CallState.NEW:
                 return STATE_NEW;
-            case CONNECTING:
+            case CallState.CONNECTING:
                 return STATE_CONNECTING;
-            case PRE_DIAL_WAIT:
+            case CallState.PRE_DIAL_WAIT:
                 return STATE_PRE_DIAL_WAIT;
-            case DIALING:
+            case CallState.DIALING:
                 return STATE_DIALING;
-            case RINGING:
+            case CallState.RINGING:
                 return STATE_RINGING;
-            case ACTIVE:
+            case CallState.ACTIVE:
                 return STATE_ACTIVE;
-            case ON_HOLD:
+            case CallState.ON_HOLD:
                 return STATE_HOLDING;
-            case DISCONNECTED:
+            case CallState.DISCONNECTED:
                 return STATE_DISCONNECTED;
-            case ABORTED:
+            case CallState.ABORTED:
                 return STATE_DISCONNECTED;
             default:
                 Log.wtf(this, "Unrecognized CallState %s", parcelableCallState);
diff --git a/telecomm/java/android/telecomm/CallState.java b/telecomm/java/android/telecomm/CallState.java
index 0ca4840..73edbe2 100644
--- a/telecomm/java/android/telecomm/CallState.java
+++ b/telecomm/java/android/telecomm/CallState.java
@@ -21,22 +21,27 @@
  * have the notion of normal transitions, due to the volatile nature of telephony systems, code
  * that uses these states should be resilient to unexpected state changes outside of what is
  * considered traditional.
+ *
+ * {@hide}
  */
-public enum CallState {
+public final class CallState {
+
+    private CallState() {}
+
     /**
      * Indicates that a call is new and not connected. This is used as the default state internally
      * within Telecomm and should not be used between Telecomm and call services. Call services are
      * not expected to ever interact with NEW calls, but {@link InCallService}s will see calls in
      * this state.
      */
-    NEW,
+    public static final int NEW = 0;
 
     /**
      * The initial state of an outgoing {@code Call}.
      * Common transitions are to {@link #DIALING} state for a successful call or
      * {@link #DISCONNECTED} if it failed.
      */
-    CONNECTING,
+    public static final int CONNECTING = 1;
 
     /**
      * Indicates that the call is about to go into the outgoing and dialing state but is waiting for
@@ -44,7 +49,7 @@
      * this is the state where the InCallUI is waiting for the user to select a
      * {@link PhoneAccount} to call from.
      */
-    PRE_DIAL_WAIT,
+    public static final int PRE_DIAL_WAIT = 2;
 
     /**
      * Indicates that a call is outgoing and in the dialing state. A call transitions to this state
@@ -52,7 +57,7 @@
      * state usually transition to {@link #ACTIVE} if the call was answered or {@link #DISCONNECTED}
      * if the call was disconnected somehow (e.g., failure or cancellation of the call by the user).
      */
-    DIALING,
+    public static final int DIALING = 3;
 
     /**
      * Indicates that a call is incoming and the user still has the option of answering, rejecting,
@@ -60,14 +65,14 @@
      * ringtone. Normal transitions are to {@link #ACTIVE} if answered or {@link #DISCONNECTED}
      * otherwise.
      */
-    RINGING,
+    public static final int RINGING = 4;
 
     /**
      * Indicates that a call is currently connected to another party and a communication channel is
      * open between them. The normal transition to this state is by the user answering a
      * {@link #DIALING} call or a {@link #RINGING} call being answered by the other party.
      */
-    ACTIVE,
+    public static final int ACTIVE = 5;
 
     /**
      * Indicates that the call is currently on hold. In this state, the call is not terminated
@@ -75,7 +80,7 @@
      * to this state is by the user putting an {@link #ACTIVE} call on hold by explicitly performing
      * an action, such as clicking the hold button.
      */
-    ON_HOLD,
+    public static final int ON_HOLD = 6;
 
     /**
      * Indicates that a call is currently disconnected. All states can transition to this state
@@ -84,12 +89,36 @@
      * the disconnection or communication was lost to the call service currently responsible for
      * this call (e.g., call service crashes).
      */
-    DISCONNECTED,
+    public static final int DISCONNECTED = 7;
 
     /**
      * Indicates that the call was attempted (mostly in the context of outgoing, at least at the
      * time of writing) but cancelled before it was successfully connected.
-     * @hide
      */
-    ABORTED;
+    public static final int ABORTED = 8;
+
+    public static String toString(int callState) {
+        switch (callState) {
+            case NEW:
+                return "NEW";
+            case CONNECTING:
+                return "CONNECTING";
+            case PRE_DIAL_WAIT:
+                return "PRE_DIAL_WAIT";
+            case DIALING:
+                return "DIALING";
+            case RINGING:
+                return "RINGING";
+            case ACTIVE:
+                return "ACTIVE";
+            case ON_HOLD:
+                return "ON_HOLD";
+            case DISCONNECTED:
+                return "DISCONNECTED";
+            case ABORTED:
+                return "ABORTED";
+            default:
+                return "UNKNOWN";
+        }
+    }
 }
diff --git a/telecomm/java/android/telecomm/CallCameraCapabilities.aidl b/telecomm/java/android/telecomm/CameraCapabilities.aidl
similarity index 92%
copy from telecomm/java/android/telecomm/CallCameraCapabilities.aidl
copy to telecomm/java/android/telecomm/CameraCapabilities.aidl
index 25b6106..08e6f43 100644
--- a/telecomm/java/android/telecomm/CallCameraCapabilities.aidl
+++ b/telecomm/java/android/telecomm/CameraCapabilities.aidl
@@ -14,7 +14,9 @@
  * limitations under the License
  */
 
-
 package android.telecomm;
 
-parcelable CallCameraCapabilities;
+/**
+ * {@hide}
+ */
+parcelable CameraCapabilities;
diff --git a/telecomm/java/android/telecomm/CallCameraCapabilities.java b/telecomm/java/android/telecomm/CameraCapabilities.java
similarity index 84%
rename from telecomm/java/android/telecomm/CallCameraCapabilities.java
rename to telecomm/java/android/telecomm/CameraCapabilities.java
index 74904e3..7c7dde1 100644
--- a/telecomm/java/android/telecomm/CallCameraCapabilities.java
+++ b/telecomm/java/android/telecomm/CameraCapabilities.java
@@ -21,9 +21,8 @@
 
 /**
  * Represents the camera capabilities important to a Video Telephony provider.
- * TODO: Add camera capabilities as required.
  */
-public final class CallCameraCapabilities implements Parcelable {
+public final class CameraCapabilities implements Parcelable {
 
     /**
      * Whether the camera supports zoom.
@@ -53,7 +52,7 @@
      * @param width The width of the camera video (in pixels).
      * @param height The height of the camera video (in pixels).
      */
-    public CallCameraCapabilities(boolean zoomSupported, float maxZoom, int width, int height) {
+    public CameraCapabilities(boolean zoomSupported, float maxZoom, int width, int height) {
         mZoomSupported = zoomSupported;
         mMaxZoom = maxZoom;
         mWidth = width;
@@ -63,8 +62,8 @@
     /**
      * Responsible for creating CallCameraCapabilities objects from deserialized Parcels.
      **/
-    public static final Parcelable.Creator<CallCameraCapabilities> CREATOR =
-            new Parcelable.Creator<CallCameraCapabilities> () {
+    public static final Parcelable.Creator<CameraCapabilities> CREATOR =
+            new Parcelable.Creator<CameraCapabilities> () {
                 /**
                  * Creates a CallCameraCapabilities instances from a parcel.
                  *
@@ -72,18 +71,18 @@
                  * @return The CallCameraCapabilities.
                  */
                 @Override
-                public CallCameraCapabilities createFromParcel(Parcel source) {
+                public CameraCapabilities createFromParcel(Parcel source) {
                     boolean supportsZoom = source.readByte() != 0;
                     float maxZoom = source.readFloat();
                     int width = source.readInt();
                     int height = source.readInt();
 
-                    return new CallCameraCapabilities(supportsZoom, maxZoom, width, height);
+                    return new CameraCapabilities(supportsZoom, maxZoom, width, height);
                 }
 
                 @Override
-                public CallCameraCapabilities[] newArray(int size) {
-                    return new CallCameraCapabilities[size];
+                public CameraCapabilities[] newArray(int size) {
+                    return new CameraCapabilities[size];
                 }
             };
 
diff --git a/telecomm/java/android/telecomm/Connection.java b/telecomm/java/android/telecomm/Connection.java
index b323646..3ecb4cb 100644
--- a/telecomm/java/android/telecomm/Connection.java
+++ b/telecomm/java/android/telecomm/Connection.java
@@ -16,11 +16,20 @@
 
 package android.telecomm;
 
+import com.android.internal.telecomm.IVideoCallback;
+import com.android.internal.telecomm.IVideoProvider;
+
 import android.app.PendingIntent;
 import android.net.Uri;
-import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.telephony.DisconnectCause;
+import android.view.Surface;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArraySet;
@@ -30,6 +39,29 @@
  */
 public abstract class Connection {
 
+    public static final int STATE_INITIALIZING = 0;
+
+    public static final int STATE_NEW = 1;
+
+    public static final int STATE_RINGING = 2;
+
+    public static final int STATE_DIALING = 3;
+
+    public static final int STATE_ACTIVE = 4;
+
+    public static final int STATE_HOLDING = 5;
+
+    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);
+
+    private static Connection sNullConnection;
+
     /** @hide */
     public abstract static class Listener {
         public void onStateChanged(Connection c, int state) {}
@@ -37,15 +69,14 @@
         public void onCallerDisplayNameChanged(
                 Connection c, String callerDisplayName, int presentation) {}
         public void onVideoStateChanged(Connection c, int videoState) {}
-        public void onSignalChanged(Connection c, Bundle details) {}
         public void onDisconnected(Connection c, int cause, String message) {}
         public void onPostDialWait(Connection c, String remaining) {}
         public void onRequestingRingback(Connection c, boolean ringback) {}
         public void onDestroyed(Connection c) {}
         public void onCallCapabilitiesChanged(Connection c, int callCapabilities) {}
         public void onParentConnectionChanged(Connection c, Connection parent) {}
-        public void onVideoCallProviderChanged(
-                Connection c, ConnectionService.VideoCallProvider videoCallProvider) {}
+        public void onVideoProviderChanged(
+                Connection c, VideoProvider videoProvider) {}
         public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {}
         public void onStatusHintsChanged(Connection c, StatusHints statusHints) {}
         public void onStartActivityFromInCall(Connection c, PendingIntent intent) {}
@@ -53,19 +84,359 @@
                 Connection c, List<Connection> conferenceableConnections) {}
     }
 
-    public final class State {
-        private State() {}
+    public static abstract class VideoProvider {
 
-        public static final int INITIALIZING = 0;
-        public static final int NEW = 1;
-        public static final int RINGING = 2;
-        public static final int DIALING = 3;
-        public static final int ACTIVE = 4;
-        public static final int HOLDING = 5;
-        public static final int DISCONNECTED = 6;
-        public static final int FAILED = 7;
-        public static final int CANCELED = 8;
+        /**
+         * Video is not being received (no protocol pause was issued).
+         */
+        public static final int SESSION_EVENT_RX_PAUSE = 1;
 
+        /**
+         * Video reception has resumed after a SESSION_EVENT_RX_PAUSE.
+         */
+        public static final int SESSION_EVENT_RX_RESUME = 2;
+
+        /**
+         * Video transmission has begun. This occurs after a negotiated start of video transmission
+         * when the underlying protocol has actually begun transmitting video to the remote party.
+         */
+        public static final int SESSION_EVENT_TX_START = 3;
+
+        /**
+         * Video transmission has stopped. This occurs after a negotiated stop of video transmission
+         * when the underlying protocol has actually stopped transmitting video to the remote party.
+         */
+        public static final int SESSION_EVENT_TX_STOP = 4;
+
+        /**
+         * A camera failure has occurred for the selected camera.  The In-Call UI can use this as a
+         * cue to inform the user the camera is not available.
+         */
+        public static final int SESSION_EVENT_CAMERA_FAILURE = 5;
+
+        /**
+         * Issued after {@code SESSION_EVENT_CAMERA_FAILURE} when the camera is once again ready for
+         * operation.  The In-Call UI can use this as a cue to inform the user that the camera has
+         * become available again.
+         */
+        public static final int SESSION_EVENT_CAMERA_READY = 6;
+
+        /**
+         * Session modify request was successful.
+         */
+        public static final int SESSION_MODIFY_REQUEST_SUCCESS = 1;
+
+        /**
+         * Session modify request failed.
+         */
+        public static final int SESSION_MODIFY_REQUEST_FAIL = 2;
+
+        /**
+         * Session modify request ignored due to invalid parameters.
+         */
+        public static final int SESSION_MODIFY_REQUEST_INVALID = 3;
+
+        private static final int MSG_SET_VIDEO_LISTENER = 1;
+        private static final int MSG_SET_CAMERA = 2;
+        private static final int MSG_SET_PREVIEW_SURFACE = 3;
+        private static final int MSG_SET_DISPLAY_SURFACE = 4;
+        private static final int MSG_SET_DEVICE_ORIENTATION = 5;
+        private static final int MSG_SET_ZOOM = 6;
+        private static final int MSG_SEND_SESSION_MODIFY_REQUEST = 7;
+        private static final int MSG_SEND_SESSION_MODIFY_RESPONSE = 8;
+        private static final int MSG_REQUEST_CAMERA_CAPABILITIES = 9;
+        private static final int MSG_REQUEST_CALL_DATA_USAGE = 10;
+        private static final int MSG_SET_PAUSE_IMAGE = 11;
+
+        private final VideoProvider.VideoProviderHandler
+                mMessageHandler = new VideoProvider.VideoProviderHandler();
+        private final VideoProvider.VideoProviderBinder mBinder;
+        private IVideoCallback mVideoListener;
+
+        /**
+         * Default handler used to consolidate binder method calls onto a single thread.
+         */
+        private final class VideoProviderHandler extends Handler {
+            @Override
+            public void handleMessage(Message msg) {
+                switch (msg.what) {
+                    case MSG_SET_VIDEO_LISTENER:
+                        mVideoListener = IVideoCallback.Stub.asInterface((IBinder) msg.obj);
+                        break;
+                    case MSG_SET_CAMERA:
+                        onSetCamera((String) msg.obj);
+                        break;
+                    case MSG_SET_PREVIEW_SURFACE:
+                        onSetPreviewSurface((Surface) msg.obj);
+                        break;
+                    case MSG_SET_DISPLAY_SURFACE:
+                        onSetDisplaySurface((Surface) msg.obj);
+                        break;
+                    case MSG_SET_DEVICE_ORIENTATION:
+                        onSetDeviceOrientation(msg.arg1);
+                        break;
+                    case MSG_SET_ZOOM:
+                        onSetZoom((Float) msg.obj);
+                        break;
+                    case MSG_SEND_SESSION_MODIFY_REQUEST:
+                        onSendSessionModifyRequest((VideoProfile) msg.obj);
+                        break;
+                    case MSG_SEND_SESSION_MODIFY_RESPONSE:
+                        onSendSessionModifyResponse((VideoProfile) msg.obj);
+                        break;
+                    case MSG_REQUEST_CAMERA_CAPABILITIES:
+                        onRequestCameraCapabilities();
+                        break;
+                    case MSG_REQUEST_CALL_DATA_USAGE:
+                        onRequestCallDataUsage();
+                        break;
+                    case MSG_SET_PAUSE_IMAGE:
+                        onSetPauseImage((String) msg.obj);
+                        break;
+                    default:
+                        break;
+                }
+            }
+        }
+
+        /**
+         * IVideoProvider stub implementation.
+         */
+        private final class VideoProviderBinder extends IVideoProvider.Stub {
+            public void setVideoListener(IBinder videoListenerBinder) {
+                mMessageHandler.obtainMessage(
+                        MSG_SET_VIDEO_LISTENER, videoListenerBinder).sendToTarget();
+            }
+
+            public void setCamera(String cameraId) {
+                mMessageHandler.obtainMessage(MSG_SET_CAMERA, cameraId).sendToTarget();
+            }
+
+            public void setPreviewSurface(Surface surface) {
+                mMessageHandler.obtainMessage(MSG_SET_PREVIEW_SURFACE, surface).sendToTarget();
+            }
+
+            public void setDisplaySurface(Surface surface) {
+                mMessageHandler.obtainMessage(MSG_SET_DISPLAY_SURFACE, surface).sendToTarget();
+            }
+
+            public void setDeviceOrientation(int rotation) {
+                mMessageHandler.obtainMessage(MSG_SET_DEVICE_ORIENTATION, rotation).sendToTarget();
+            }
+
+            public void setZoom(float value) {
+                mMessageHandler.obtainMessage(MSG_SET_ZOOM, value).sendToTarget();
+            }
+
+            public void sendSessionModifyRequest(VideoProfile requestProfile) {
+                mMessageHandler.obtainMessage(
+                        MSG_SEND_SESSION_MODIFY_REQUEST, requestProfile).sendToTarget();
+            }
+
+            public void sendSessionModifyResponse(VideoProfile responseProfile) {
+                mMessageHandler.obtainMessage(
+                        MSG_SEND_SESSION_MODIFY_RESPONSE, responseProfile).sendToTarget();
+            }
+
+            public void requestCameraCapabilities() {
+                mMessageHandler.obtainMessage(MSG_REQUEST_CAMERA_CAPABILITIES).sendToTarget();
+            }
+
+            public void requestCallDataUsage() {
+                mMessageHandler.obtainMessage(MSG_REQUEST_CALL_DATA_USAGE).sendToTarget();
+            }
+
+            public void setPauseImage(String uri) {
+                mMessageHandler.obtainMessage(MSG_SET_PAUSE_IMAGE, uri).sendToTarget();
+            }
+        }
+
+        public VideoProvider() {
+            mBinder = new VideoProvider.VideoProviderBinder();
+        }
+
+        /**
+         * Returns binder object which can be used across IPC methods.
+         * @hide
+         */
+        public final IVideoProvider getInterface() {
+            return mBinder;
+        }
+
+        /**
+         * Sets the camera to be used for video recording in a video call.
+         *
+         * @param cameraId The id of the camera.
+         */
+        public abstract void onSetCamera(String cameraId);
+
+        /**
+         * Sets the surface to be used for displaying a preview of what the user's camera is
+         * currently capturing.  When video transmission is enabled, this is the video signal which
+         * is sent to the remote device.
+         *
+         * @param surface The surface.
+         */
+        public abstract void onSetPreviewSurface(Surface surface);
+
+        /**
+         * Sets the surface to be used for displaying the video received from the remote device.
+         *
+         * @param surface The surface.
+         */
+        public abstract void onSetDisplaySurface(Surface surface);
+
+        /**
+         * Sets the device orientation, in degrees.  Assumes that a standard portrait orientation of
+         * the device is 0 degrees.
+         *
+         * @param rotation The device orientation, in degrees.
+         */
+        public abstract void onSetDeviceOrientation(int rotation);
+
+        /**
+         * Sets camera zoom ratio.
+         *
+         * @param value The camera zoom ratio.
+         */
+        public abstract void onSetZoom(float value);
+
+        /**
+         * Issues a request to modify the properties of the current session.  The request is
+         * sent to the remote device where it it handled by the In-Call UI.
+         * Some examples of session modification requests: upgrade call from audio to video,
+         * downgrade call from video to audio, pause video.
+         *
+         * @param requestProfile The requested call video properties.
+         */
+        public abstract void onSendSessionModifyRequest(VideoProfile requestProfile);
+
+        /**te
+         * Provides a response to a request to change the current call session video
+         * properties.
+         * This is in response to a request the InCall UI has received via the InCall UI.
+         *
+         * @param responseProfile The response call video properties.
+         */
+        public abstract void onSendSessionModifyResponse(VideoProfile responseProfile);
+
+        /**
+         * Issues a request to the video provider to retrieve the camera capabilities.
+         * Camera capabilities are reported back to the caller via the In-Call UI.
+         */
+        public abstract void onRequestCameraCapabilities();
+
+        /**
+         * Issues a request to the video telephony framework to retrieve the cumulative data usage
+         * for the current call.  Data usage is reported back to the caller via the
+         * InCall UI.
+         */
+        public abstract void onRequestCallDataUsage();
+
+        /**
+         * Provides the video telephony framework with the URI of an image to be displayed to remote
+         * devices when the video signal is paused.
+         *
+         * @param uri URI of image to display.
+         */
+        public abstract void onSetPauseImage(String uri);
+
+        /**
+         * Invokes callback method defined in In-Call UI.
+         *
+         * @param videoProfile The requested video call profile.
+         */
+        public void receiveSessionModifyRequest(VideoProfile videoProfile) {
+            if (mVideoListener != null) {
+                try {
+                    mVideoListener.receiveSessionModifyRequest(videoProfile);
+                } catch (RemoteException ignored) {
+                }
+            }
+        }
+
+        /**
+         * Invokes callback method defined in In-Call UI.
+         *
+         * @param status Status of the session modify request.  Valid values are
+         *               {@link VideoProvider#SESSION_MODIFY_REQUEST_SUCCESS},
+         *               {@link VideoProvider#SESSION_MODIFY_REQUEST_FAIL},
+         *               {@link VideoProvider#SESSION_MODIFY_REQUEST_INVALID}
+         * @param requestedProfile The original request which was sent to the remote device.
+         * @param responseProfile The actual profile changes made by the remote device.
+         */
+        public void receiveSessionModifyResponse(int status,
+                VideoProfile requestedProfile, VideoProfile responseProfile) {
+            if (mVideoListener != null) {
+                try {
+                    mVideoListener.receiveSessionModifyResponse(
+                            status, requestedProfile, responseProfile);
+                } catch (RemoteException ignored) {
+                }
+            }
+        }
+
+        /**
+         * Invokes callback method defined in In-Call UI.
+         *
+         * Valid values are: {@link VideoProvider#SESSION_EVENT_RX_PAUSE},
+         * {@link VideoProvider#SESSION_EVENT_RX_RESUME},
+         * {@link VideoProvider#SESSION_EVENT_TX_START},
+         * {@link VideoProvider#SESSION_EVENT_TX_STOP}
+         *
+         * @param event The event.
+         */
+        public void handleCallSessionEvent(int event) {
+            if (mVideoListener != null) {
+                try {
+                    mVideoListener.handleCallSessionEvent(event);
+                } catch (RemoteException ignored) {
+                }
+            }
+        }
+
+        /**
+         * Invokes callback method defined in In-Call UI.
+         *
+         * @param width  The updated peer video width.
+         * @param height The updated peer video height.
+         */
+        public void changePeerDimensions(int width, int height) {
+            if (mVideoListener != null) {
+                try {
+                    mVideoListener.changePeerDimensions(width, height);
+                } catch (RemoteException ignored) {
+                }
+            }
+        }
+
+        /**
+         * Invokes callback method defined in In-Call UI.
+         *
+         * @param dataUsage The updated data usage.
+         */
+        public void changeCallDataUsage(int dataUsage) {
+            if (mVideoListener != null) {
+                try {
+                    mVideoListener.changeCallDataUsage(dataUsage);
+                } catch (RemoteException ignored) {
+                }
+            }
+        }
+
+        /**
+         * Invokes callback method defined in In-Call UI.
+         *
+         * @param cameraCapabilities The changed camera capabilities.
+         */
+        public void changeCameraCapabilities(CameraCapabilities cameraCapabilities) {
+            if (mVideoListener != null) {
+                try {
+                    mVideoListener.changeCameraCapabilities(cameraCapabilities);
+                } catch (RemoteException ignored) {
+                }
+            }
+        }
     }
 
     private final Listener mConnectionDeathListener = new Listener() {
@@ -79,10 +450,14 @@
 
     private final Set<Listener> mListeners = new CopyOnWriteArraySet<>();
     private final List<Connection> mChildConnections = new ArrayList<>();
+    private final List<Connection> mUnmodifiableChildConnections =
+            Collections.unmodifiableList(mChildConnections);
     private final List<Connection> mConferenceableConnections = new ArrayList<>();
+    private final List<Connection> mUnmodifiableConferenceableConnections =
+            Collections.unmodifiableList(mConferenceableConnections);
 
-    private int mState = State.NEW;
-    private CallAudioState mCallAudioState;
+    private int mState = STATE_NEW;
+    private AudioState mAudioState;
     private Uri mHandle;
     private int mHandlePresentation;
     private String mCallerDisplayName;
@@ -90,7 +465,7 @@
     private boolean mRequestingRingback = false;
     private int mCallCapabilities;
     private Connection mParentConnection;
-    private ConnectionService.VideoCallProvider mVideoCallProvider;
+    private VideoProvider mVideoProvider;
     private boolean mAudioModeIsVoip;
     private StatusHints mStatusHints;
     private int mVideoState;
@@ -111,7 +486,7 @@
     }
 
     /**
-     * @return The {@link CallPropertyPresentation} which controls how the handle is shown.
+     * @return The {@link PropertyPresentation} which controls how the handle is shown.
      */
     public final int getHandlePresentation() {
         return mHandlePresentation;
@@ -125,7 +500,7 @@
     }
 
     /**
-     * @return The {@link CallPropertyPresentation} which controls how the caller display name is
+     * @return The {@link PropertyPresentation} which controls how the caller display name is
      *         shown.
      */
     public final int getCallerDisplayNamePresentation() {
@@ -141,10 +516,10 @@
 
     /**
      * Returns the video state of the call.
-     * Valid values: {@link android.telecomm.VideoCallProfile.VideoState#AUDIO_ONLY},
-     * {@link android.telecomm.VideoCallProfile.VideoState#BIDIRECTIONAL},
-     * {@link android.telecomm.VideoCallProfile.VideoState#TX_ENABLED},
-     * {@link android.telecomm.VideoCallProfile.VideoState#RX_ENABLED}.
+     * Valid values: {@link VideoProfile.VideoState#AUDIO_ONLY},
+     * {@link VideoProfile.VideoState#BIDIRECTIONAL},
+     * {@link VideoProfile.VideoState#TX_ENABLED},
+     * {@link VideoProfile.VideoState#RX_ENABLED}.
      *
      * @return The video state of the call.
      */
@@ -157,8 +532,8 @@
      *         being routed by the system. This is {@code null} if this Connection
      *         does not directly know about its audio state.
      */
-    public final CallAudioState getCallAudioState() {
-        return mCallAudioState;
+    public final AudioState getAudioState() {
+        return mAudioState;
     }
 
     /**
@@ -236,36 +611,36 @@
      * @param state The new audio state.
      * @hide
      */
-    final void setAudioState(CallAudioState state) {
+    final void setAudioState(AudioState state) {
         Log.d(this, "setAudioState %s", state);
-        mCallAudioState = state;
+        mAudioState = state;
         onSetAudioState(state);
     }
 
     /**
-     * @param state An integer value from {@link State}.
+     * @param state An integer value of a {@code STATE_*} constant.
      * @return A string representation of the value.
      */
     public static String stateToString(int state) {
         switch (state) {
-            case State.INITIALIZING:
-                return "INITIALIZING";
-            case State.NEW:
-                return "NEW";
-            case State.RINGING:
-                return "RINGING";
-            case State.DIALING:
-                return "DIALING";
-            case State.ACTIVE:
-                return "ACTIVE";
-            case State.HOLDING:
-                return "HOLDING";
-            case State.DISCONNECTED:
+            case STATE_INITIALIZING:
+                return "STATE_INITIALIZING";
+            case STATE_NEW:
+                return "STATE_NEW";
+            case STATE_RINGING:
+                return "STATE_RINGING";
+            case STATE_DIALING:
+                return "STATE_DIALING";
+            case STATE_ACTIVE:
+                return "STATE_ACTIVE";
+            case STATE_HOLDING:
+                return "STATE_HOLDING";
+            case STATE_DISCONNECTED:
                 return "DISCONNECTED";
-            case State.FAILED:
-                return "FAILED";
-            case State.CANCELED:
-                return "CANCELED";
+            case STATE_FAILED:
+                return "STATE_FAILED";
+            case STATE_CANCELED:
+                return "STATE_CANCELED";
             default:
                 Log.wtf(Connection.class, "Unknown state %d", state);
                 return "UNKNOWN";
@@ -297,11 +672,11 @@
     }
 
     public final List<Connection> getChildConnections() {
-        return mChildConnections;
+        return mUnmodifiableChildConnections;
     }
 
     /**
-     * Returns the connection's {@link CallCapabilities}
+     * Returns the connection's {@link PhoneCapabilities}
      */
     public final int getCallCapabilities() {
         return mCallCapabilities;
@@ -311,7 +686,7 @@
      * Sets the value of the {@link #getHandle()} property.
      *
      * @param handle The new handle.
-     * @param presentation The {@link CallPropertyPresentation} which controls how the handle is
+     * @param presentation The {@link PropertyPresentation} which controls how the handle is
      *         shown.
      */
     public final void setHandle(Uri handle, int presentation) {
@@ -327,7 +702,7 @@
      * Sets the caller display name (CNAP).
      *
      * @param callerDisplayName The new display name.
-     * @param presentation The {@link CallPropertyPresentation} which controls how the name is
+     * @param presentation The {@link PropertyPresentation} which controls how the name is
      *         shown.
      */
     public final void setCallerDisplayName(String callerDisplayName, int presentation) {
@@ -345,17 +720,17 @@
      */
     public final void setCanceled() {
         Log.d(this, "setCanceled");
-        setState(State.CANCELED);
+        setState(STATE_CANCELED);
     }
 
     /**
-     * Move the {@link Connection} to the {@link State#FAILED} state, with the given code
+     * 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 android.telephony.DisconnectCause} indicating why the connection
+     * @param code The {@link DisconnectCause} indicating why the connection
      *             failed.
      * @param message A message explaining why the {@link Connection} failed.
      */
@@ -363,15 +738,15 @@
         Log.d(this, "setFailed (%d: %s)", code, message);
         mFailureCode = code;
         mFailureMessage = message;
-        setState(State.FAILED);
+        setState(STATE_FAILED);
     }
 
     /**
      * Set the video state for the connection.
-     * Valid values: {@link android.telecomm.VideoCallProfile.VideoState#AUDIO_ONLY},
-     * {@link android.telecomm.VideoCallProfile.VideoState#BIDIRECTIONAL},
-     * {@link android.telecomm.VideoCallProfile.VideoState#TX_ENABLED},
-     * {@link android.telecomm.VideoCallProfile.VideoState#RX_ENABLED}.
+     * Valid values: {@link VideoProfile.VideoState#AUDIO_ONLY},
+     * {@link VideoProfile.VideoState#BIDIRECTIONAL},
+     * {@link VideoProfile.VideoState#TX_ENABLED},
+     * {@link VideoProfile.VideoState#RX_ENABLED}.
      *
      * @param videoState The new video state.
      */
@@ -389,68 +764,68 @@
      */
     public final void setActive() {
         setRequestingRingback(false);
-        setState(State.ACTIVE);
+        setState(STATE_ACTIVE);
     }
 
     /**
      * Sets state to ringing (e.g., an inbound ringing call).
      */
     public final void setRinging() {
-        setState(State.RINGING);
+        setState(STATE_RINGING);
     }
 
     /**
      * Sets state to initializing (this Connection is not yet ready to be used).
      */
     public final void setInitializing() {
-        setState(State.INITIALIZING);
+        setState(STATE_INITIALIZING);
     }
 
     /**
      * Sets state to initialized (the Connection has been set up and is now ready to be used).
      */
     public final void setInitialized() {
-        setState(State.NEW);
+        setState(STATE_NEW);
     }
 
     /**
      * Sets state to dialing (e.g., dialing an outbound call).
      */
     public final void setDialing() {
-        setState(State.DIALING);
+        setState(STATE_DIALING);
     }
 
     /**
      * Sets state to be on hold.
      */
     public final void setOnHold() {
-        setState(State.HOLDING);
+        setState(STATE_HOLDING);
     }
 
     /**
      * Sets the video call provider.
-     * @param videoCallProvider The video call provider.
+     * @param videoProvider The video provider.
      */
-    public final void setVideoCallProvider(ConnectionService.VideoCallProvider videoCallProvider) {
-        mVideoCallProvider = videoCallProvider;
+    public final void setVideoProvider(VideoProvider videoProvider) {
+        mVideoProvider = videoProvider;
         for (Listener l : mListeners) {
-            l.onVideoCallProviderChanged(this, videoCallProvider);
+            l.onVideoProviderChanged(this, videoProvider);
         }
     }
 
-    public final ConnectionService.VideoCallProvider getVideoCallProvider() {
-        return mVideoCallProvider;
+    public final VideoProvider getVideoProvider() {
+        return mVideoProvider;
     }
 
     /**
      * Sets state to disconnected.
      *
      * @param cause The reason for the disconnection, any of
-     *         {@link android.telephony.DisconnectCause}.
+     *         {@link DisconnectCause}.
      * @param message Optional call-service-provided message about the disconnect.
      */
     public final void setDisconnected(int cause, String message) {
-        setState(State.DISCONNECTED);
+        setState(STATE_DISCONNECTED);
         Log.d(this, "Disconnected with cause %d message %s", cause, message);
         for (Listener l : mListeners) {
             l.onDisconnected(this, cause, message);
@@ -482,7 +857,7 @@
     }
 
     /**
-     * Sets the connection's {@link CallCapabilities}.
+     * Sets the connection's {@link PhoneCapabilities}.
      *
      * @param callCapabilities The new call capabilities.
      */
@@ -510,17 +885,6 @@
     }
 
     /**
-     * Sets the current signal levels for the underlying data transport.
-     *
-     * @param details A {@link android.os.Bundle} containing details of the current level.
-     */
-    public final void setSignal(Bundle details) {
-        for (Listener l : mListeners) {
-            l.onSignalChanged(this, details);
-        }
-    }
-
-    /**
      * Requests that the framework use VOIP audio mode for this connection.
      *
      * @param isVoip True if the audio mode is VOIP.
@@ -563,6 +927,13 @@
     }
 
     /**
+     * Obtains the connections with which this connection can be conferenced.
+     */
+    public final List<Connection> getConferenceableConnections() {
+        return mUnmodifiableConferenceableConnections;
+    }
+
+    /**
      * Launches an activity for this connection on top of the in-call UI.
      *
      * @param intent The intent to use to start the activity.
@@ -577,17 +948,17 @@
     }
 
     /**
-     * Notifies this Connection that the {@link #getCallAudioState()} property has a new value.
+     * Notifies this Connection that the {@link #getAudioState()} property has a new value.
      *
      * @param state The new call audio state.
      */
-    public void onSetAudioState(CallAudioState state) {}
+    public void onSetAudioState(AudioState state) {}
 
     /**
      * Notifies this Connection of an internal state change. This method is called after the
      * state is changed.
      *
-     * @param state The new state, a {@link Connection.State} member.
+     * @param state The new state, one of the {@code STATE_*} constants.
      */
     public void onSetState(int state) {}
 
@@ -629,7 +1000,7 @@
     public void onUnhold() {}
 
     /**
-     * Notifies this Connection, which is in {@link State#RINGING}, of
+     * Notifies this Connection, which is in {@link #STATE_RINGING}, of
      * a request to accept.
      *
      * @param videoState The video state in which to answer the call.
@@ -637,7 +1008,7 @@
     public void onAnswer(int videoState) {}
 
     /**
-     * Notifies this Connection, which is in {@link State#RINGING}, of
+     * Notifies this Connection, which is in {@link #STATE_RINGING}, of
      * a request to reject.
      */
     public void onReject() {}
@@ -648,12 +1019,6 @@
     public void onPostDialContinue(boolean proceed) {}
 
     /**
-     * Swap this call with a background call. This is used for calls that don't support hold,
-     * e.g. CDMA.
-     */
-    public void onSwapWithBackgroundCall() {}
-
-    /**
      * TODO: Needs documentation.
      */
     public void onChildrenChanged(List<Connection> children) {}
@@ -673,6 +1038,38 @@
      */
     public void onConferenceWith(Connection otherConnection) {}
 
+    static String toLogSafePhoneNumber(String number) {
+        // For unknown number, log empty string.
+        if (number == null) {
+            return "";
+        }
+
+        if (PII_DEBUG) {
+            // When PII_DEBUG is true we emit PII.
+            return number;
+        }
+
+        // Do exactly same thing as Uri#toSafeString() does, which will enable us to compare
+        // sanitized phone numbers.
+        StringBuilder builder = new StringBuilder();
+        for (int i = 0; i < number.length(); i++) {
+            char c = number.charAt(i);
+            if (c == '-' || c == '@' || c == '.') {
+                builder.append(c);
+            } else {
+                builder.append('x');
+            }
+        }
+        return builder.toString();
+    }
+
+    static synchronized Connection getNullConnection() {
+        if (sNullConnection == null) {
+            sNullConnection = new Connection() {};
+        }
+        return sNullConnection;
+    }
+
     private void addChild(Connection connection) {
         Log.d(this, "adding child %s", connection);
         mChildConnections.add(connection);
@@ -686,7 +1083,7 @@
     }
 
     private void setState(int state) {
-        if (mState == State.FAILED || mState == State.CANCELED) {
+        if (mState == STATE_FAILED || mState == STATE_CANCELED) {
             Log.d(this, "Connection already %s; cannot transition out of this state.",
                     stateToString(mState));
             return;
@@ -711,7 +1108,7 @@
      * @param message A reason for why the connection failed (not intended to be shown to the user).
      * @return A {@link Connection} which indicates failure.
      */
-    public static Connection getFailedConnection(final int code, final String message) {
+    public static Connection createFailedConnection(final int code, final String message) {
         return new Connection() {{
             setFailed(code, message);
         }};
@@ -723,13 +1120,13 @@
 
     /**
      * 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
+     * {@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 {@link Connection} which indicates that the underlying call should be canceled.
      */
-    public static Connection getCanceledConnection() {
+    public static Connection createCanceledConnection() {
         return CANCELED_CONNECTION;
     }
 
diff --git a/telecomm/java/android/telecomm/ConnectionRequest.aidl b/telecomm/java/android/telecomm/ConnectionRequest.aidl
index 72e5c8c..6081c22 100644
--- a/telecomm/java/android/telecomm/ConnectionRequest.aidl
+++ b/telecomm/java/android/telecomm/ConnectionRequest.aidl
@@ -16,4 +16,7 @@
 
 package android.telecomm;
 
+/**
+ * {@hide}
+ */
 parcelable ConnectionRequest;
diff --git a/telecomm/java/android/telecomm/ConnectionRequest.java b/telecomm/java/android/telecomm/ConnectionRequest.java
index 1016091..5ea1d1a 100644
--- a/telecomm/java/android/telecomm/ConnectionRequest.java
+++ b/telecomm/java/android/telecomm/ConnectionRequest.java
@@ -20,8 +20,6 @@
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.os.ResultReceiver;
-import android.telephony.DisconnectCause;
 
 /**
  * Simple data container encapsulating a request to some entity to
@@ -30,10 +28,7 @@
 public final class ConnectionRequest implements Parcelable {
 
     // TODO: Token to limit recursive invocations
-    // TODO: Consider upgrading "mHandle" to ordered list of handles, indicating a set of phone
-    //         numbers that would satisfy the client's needs, in order of preference
     private final PhoneAccountHandle mAccountHandle;
-    private final String mCallId;
     private final Uri mHandle;
     private final int mHandlePresentation;
     private final Bundle mExtras;
@@ -41,22 +36,19 @@
 
     /**
      * @param accountHandle The accountHandle which should be used to place the call.
-     * @param callId An identifier for this call.
      * @param handle The handle (e.g., phone number) to which the {@link Connection} is to connect.
-     * @param handlePresentation The {@link CallPropertyPresentation} which controls how the handle
+     * @param handlePresentation The {@link PropertyPresentation} which controls how the handle
      *         is shown.
      * @param extras Application-specific extra data.
      * @param videoState Determines the video state for the connection.
      */
     public ConnectionRequest(
             PhoneAccountHandle accountHandle,
-            String callId,
             Uri handle,
             int handlePresentation,
             Bundle extras,
             int videoState) {
         mAccountHandle = accountHandle;
-        mCallId = callId;
         mHandle = handle;
         mHandlePresentation = handlePresentation;
         mExtras = extras;
@@ -65,7 +57,6 @@
 
     private ConnectionRequest(Parcel in) {
         mAccountHandle = in.readParcelable(getClass().getClassLoader());
-        mCallId = in.readString();
         mHandle = in.readParcelable(getClass().getClassLoader());
         mHandlePresentation = in.readInt();
         mExtras = in.readParcelable(getClass().getClassLoader());
@@ -78,17 +69,12 @@
     public PhoneAccountHandle getAccountHandle() { return mAccountHandle; }
 
     /**
-     * An identifier for this call.
-     */
-    public String getCallId() { return mCallId; }
-
-    /**
      * The handle (e.g., phone number) to which the {@link Connection} is to connect.
      */
     public Uri getHandle() { return mHandle; }
 
     /**
-     * The {@link CallPropertyPresentation} which controls how the handle is shown.
+     * The {@link PropertyPresentation} which controls how the handle is shown.
      */
     public int getHandlePresentation() { return mHandlePresentation; }
 
@@ -100,11 +86,11 @@
     public Bundle getExtras() { return mExtras; }
 
     /**
-     * Determines the video state for the connection.
-     * Valid values: {@link VideoCallProfile.VideoState#AUDIO_ONLY},
-     * {@link VideoCallProfile.VideoState#BIDIRECTIONAL},
-     * {@link VideoCallProfile.VideoState#TX_ENABLED},
-     * {@link VideoCallProfile.VideoState#RX_ENABLED}.
+     * Describes the video states supported by the client requesting the connection.
+     * Valid values: {@link VideoProfile.VideoState#AUDIO_ONLY},
+     * {@link VideoProfile.VideoState#BIDIRECTIONAL},
+     * {@link VideoProfile.VideoState#TX_ENABLED},
+     * {@link VideoProfile.VideoState#RX_ENABLED}.
      *
      * @return The video state for the connection.
      */
@@ -114,10 +100,10 @@
 
     @Override
     public String toString() {
-        return String.format("PhoneConnectionRequest %s %s",
+        return String.format("ConnectionRequest %s %s",
                 mHandle == null
                         ? Uri.EMPTY
-                        : ConnectionService.toLogSafePhoneNumber(mHandle.toString()),
+                        : Connection.toLogSafePhoneNumber(mHandle.toString()),
                 mExtras == null ? "" : mExtras);
     }
 
@@ -144,7 +130,6 @@
     @Override
     public void writeToParcel(Parcel destination, int flags) {
         destination.writeParcelable(mAccountHandle, 0);
-        destination.writeString(mCallId);
         destination.writeParcelable(mHandle, 0);
         destination.writeInt(mHandlePresentation);
         destination.writeParcelable(mExtras, 0);
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
index 80c7bbc..d5e4f1b 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -17,26 +17,20 @@
 package android.telecomm;
 
 import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
 import android.app.PendingIntent;
 import android.app.Service;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.net.Uri;
-import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
 import android.telephony.DisconnectCause;
-import android.os.RemoteException;
-import android.view.Surface;
 
 import com.android.internal.os.SomeArgs;
 import com.android.internal.telecomm.IConnectionService;
 import com.android.internal.telecomm.IConnectionServiceAdapter;
-import com.android.internal.telecomm.IVideoCallCallback;
-import com.android.internal.telecomm.IVideoCallProvider;
 import com.android.internal.telecomm.RemoteServiceCallback;
 
 import java.util.ArrayList;
@@ -51,10 +45,11 @@
  * Android device.
  */
 public abstract class ConnectionService extends Service {
+
     /**
      * The {@link Intent} that must be declared as handled by the service.
      */
-    @SdkConstant(SdkConstantType.SERVICE_ACTION)
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
     public static final String SERVICE_INTERFACE = "android.telecomm.ConnectionService";
 
     // Flag controlling whether PII is emitted into the logs
@@ -73,12 +68,9 @@
     private static final int MSG_STOP_DTMF_TONE = 11;
     private static final int MSG_CONFERENCE = 12;
     private static final int MSG_SPLIT_FROM_CONFERENCE = 13;
-    private static final int MSG_SWAP_WITH_BACKGROUND_CALL = 14;
-    private static final int MSG_ON_POST_DIAL_CONTINUE = 15;
-    private static final int MSG_ON_PHONE_ACCOUNT_CLICKED = 16;
-    private static final int MSG_REMOVE_CONNECTION_SERVICE_ADAPTER = 17;
-
-    private static Connection sNullConnection;
+    private static final int MSG_ON_POST_DIAL_CONTINUE = 14;
+    private static final int MSG_ON_PHONE_ACCOUNT_CLICKED = 15;
+    private static final int MSG_REMOVE_CONNECTION_SERVICE_ADAPTER = 16;
 
     private final Map<String, Connection> mConnectionById = new HashMap<>();
     private final Map<Connection, String> mIdByConnection = new HashMap<>();
@@ -88,37 +80,6 @@
     private final List<Runnable> mPreInitializationConnectionRequests = new ArrayList<>();
     private final ConnectionServiceAdapter mAdapter = new ConnectionServiceAdapter();
 
-    /**
-     * A callback for providing the result of creating a connection.
-     */
-    public interface CreateConnectionResponse<CONNECTION> {
-        /**
-         * Tells Telecomm that an attempt to create the connection succeeded.
-         *
-         * @param request The original request.
-         * @param connection The connection.
-         */
-        void onSuccess(ConnectionRequest request, CONNECTION connection);
-
-        /**
-         * Tells Telecomm that an attempt to create the connection failed. Telecomm will try a
-         * different service until a service cancels the process or completes it successfully.
-         *
-         * @param request The original request.
-         * @param code An integer code indicating the reason for failure.
-         * @param msg A message explaining the reason for failure.
-         */
-        void onFailure(ConnectionRequest request, int code, String msg);
-
-        /**
-         * Tells Telecomm to cancel creating the connection. Telecomm will stop trying to create
-         * the connection an no more services will be tried.
-         *
-         * @param request The original request.
-         */
-        void onCancel(ConnectionRequest request);
-    }
-
     private final IBinder mBinder = new IConnectionService.Stub() {
         @Override
         public void addConnectionServiceAdapter(IConnectionServiceAdapter adapter) {
@@ -132,11 +93,13 @@
         @Override
         public void createConnection(
                 PhoneAccountHandle connectionManagerPhoneAccount,
+                String id,
                 ConnectionRequest request,
                 boolean isIncoming) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionManagerPhoneAccount;
-            args.arg2 = request;
+            args.arg2 = id;
+            args.arg3 = request;
             args.argi1 = isIncoming ? 1 : 0;
             mHandler.obtainMessage(MSG_CREATE_CONNECTION, args).sendToTarget();
         }
@@ -175,7 +138,7 @@
         }
 
         @Override
-        public void onAudioStateChanged(String callId, CallAudioState audioState) {
+        public void onAudioStateChanged(String callId, AudioState audioState) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = callId;
             args.arg2 = audioState;
@@ -206,11 +169,6 @@
         }
 
         @Override
-        public void swapWithBackgroundCall(String callId) {
-            mHandler.obtainMessage(MSG_SWAP_WITH_BACKGROUND_CALL, callId).sendToTarget();
-        }
-
-        @Override
         public void onPostDialContinue(String callId, boolean proceed) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = callId;
@@ -240,22 +198,27 @@
                     try {
                         final PhoneAccountHandle connectionManagerPhoneAccount =
                                 (PhoneAccountHandle) args.arg1;
-                        final ConnectionRequest request = (ConnectionRequest) args.arg2;
+                        final String id = (String) args.arg2;
+                        final ConnectionRequest request = (ConnectionRequest) args.arg3;
                         final boolean isIncoming = args.argi1 == 1;
                         if (!mAreAccountsInitialized) {
-                            Log.d(this, "Enqueueing pre-init request %s", request.getCallId());
+                            Log.d(this, "Enqueueing pre-init request %s", id);
                             mPreInitializationConnectionRequests.add(new Runnable() {
                                 @Override
                                 public void run() {
                                     createConnection(
                                             connectionManagerPhoneAccount,
+                                            id,
                                             request,
                                             isIncoming);
                                 }
                             });
                         } else {
-                            Log.d(this, "Immediately processing request %s", request.getCallId());
-                            createConnection(connectionManagerPhoneAccount, request, isIncoming);
+                            createConnection(
+                                    connectionManagerPhoneAccount,
+                                    id,
+                                    request,
+                                    isIncoming);
                         }
                     } finally {
                         args.recycle();
@@ -292,7 +255,7 @@
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
                         String callId = (String) args.arg1;
-                        CallAudioState audioState = (CallAudioState) args.arg2;
+                        AudioState audioState = (AudioState) args.arg2;
                         onAudioStateChanged(callId, audioState);
                     } finally {
                         args.recycle();
@@ -319,9 +282,6 @@
                 case MSG_SPLIT_FROM_CONFERENCE:
                     splitFromConference((String) msg.obj);
                     break;
-                case MSG_SWAP_WITH_BACKGROUND_CALL:
-                    swapWithBackgroundCall((String) msg.obj);
-                    break;
                 case MSG_ON_POST_DIAL_CONTINUE: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
@@ -348,22 +308,22 @@
             String id = mIdByConnection.get(c);
             Log.d(this, "Adapter set state %s %s", id, Connection.stateToString(state));
             switch (state) {
-                case Connection.State.ACTIVE:
+                case Connection.STATE_ACTIVE:
                     mAdapter.setActive(id);
                     break;
-                case Connection.State.DIALING:
+                case Connection.STATE_DIALING:
                     mAdapter.setDialing(id);
                     break;
-                case Connection.State.DISCONNECTED:
+                case Connection.STATE_DISCONNECTED:
                     // Handled in onDisconnected()
                     break;
-                case Connection.State.HOLDING:
+                case Connection.STATE_HOLDING:
                     mAdapter.setOnHold(id);
                     break;
-                case Connection.State.NEW:
+                case Connection.STATE_NEW:
                     // Nothing to tell Telecomm
                     break;
-                case Connection.State.RINGING:
+                case Connection.STATE_RINGING:
                     mAdapter.setRinging(id);
                     break;
             }
@@ -397,11 +357,6 @@
         }
 
         @Override
-        public void onSignalChanged(Connection c, Bundle details) {
-            // TODO: Unsupported yet
-        }
-
-        @Override
         public void onDestroyed(Connection c) {
             removeConnection(c);
         }
@@ -421,11 +376,11 @@
         }
 
         @Override
-        public void onCallCapabilitiesChanged(Connection c, int callCapabilities) {
+        public void onCallCapabilitiesChanged(Connection c, int capabilities) {
             String id = mIdByConnection.get(c);
-            Log.d(this, "call capabilities: parcelableconnection: %s",
-                    CallCapabilities.toString(callCapabilities));
-            mAdapter.setCallCapabilities(id, callCapabilities);
+            Log.d(this, "capabilities: parcelableconnection: %s",
+                    PhoneCapabilities.toString(capabilities));
+            mAdapter.setCallCapabilities(id, capabilities);
         }
 
         @Override
@@ -436,9 +391,9 @@
         }
 
         @Override
-        public void onVideoCallProviderChanged(Connection c, VideoCallProvider videoCallProvider) {
+        public void onVideoProviderChanged(Connection c, Connection.VideoProvider videoProvider) {
             String id = mIdByConnection.get(c);
-            mAdapter.setVideoCallProvider(id, videoCallProvider);
+            mAdapter.setVideoProvider(id, videoProvider);
         }
 
         @Override
@@ -487,6 +442,7 @@
      */
     private void createConnection(
             final PhoneAccountHandle callManagerAccount,
+            final String callId,
             final ConnectionRequest request,
             boolean isIncoming) {
         Log.d(this, "call %s", request);
@@ -499,64 +455,79 @@
         }
 
         if (createdConnection != null) {
-            if (createdConnection.getState() == Connection.State.INITIALIZING) {
+            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:
+                            case Connection.STATE_FAILED:
                                 Log.d(this, "Connection (%s) failed (%d: %s)", request,
                                         c.getFailureCode(), c.getFailureMessage());
                                 Log.d(this, "adapter handleCreateConnectionFailed %s",
-                                        request.getCallId());
-                                mAdapter.handleCreateConnectionFailed(request, c.getFailureCode(),
+                                        callId);
+                                mAdapter.handleCreateConnectionFailed(
+                                        callId,
+                                        request,
+                                        c.getFailureCode(),
                                         c.getFailureMessage());
                                 break;
-                            case Connection.State.CANCELED:
+                            case Connection.STATE_CANCELED:
                                 Log.d(this, "adapter handleCreateConnectionCanceled %s",
-                                        request.getCallId());
-                                mAdapter.handleCreateConnectionCancelled(request);
+                                        callId);
+                                mAdapter.handleCreateConnectionCancelled(callId, request);
                                 break;
-                            case Connection.State.INITIALIZING:
-                                Log.d(this, "State changed to INITIALIZING; ignoring");
+                            case Connection.STATE_INITIALIZING:
+                                Log.d(this, "State changed to STATE_INITIALIZING; ignoring");
                                 return; // Don't want to stop listening on this state transition.
                             default:
                                 Log.d(this, "Connection created in state %s",
                                         Connection.stateToString(state));
-                                connectionCreated(request, createdConnection);
+                                connectionCreated(callId, request, createdConnection);
                                 break;
                         }
                         c.removeConnectionListener(this);
                     }
                 });
-            } else if (createdConnection.getState() == Connection.State.CANCELED) {
+            } else if (createdConnection.getState() == Connection.STATE_CANCELED) {
                 // Tell telecomm not to attempt any more services.
-                mAdapter.handleCreateConnectionCancelled(request);
-            } else if (createdConnection.getState() == Connection.State.FAILED) {
-                mAdapter.handleCreateConnectionFailed(request, createdConnection.getFailureCode(),
+                mAdapter.handleCreateConnectionCancelled(callId, request);
+            } else if (createdConnection.getState() == Connection.STATE_FAILED) {
+                mAdapter.handleCreateConnectionFailed(
+                        callId,
+                        request,
+                        createdConnection.getFailureCode(),
                         createdConnection.getFailureMessage());
             } else {
-                connectionCreated(request, createdConnection);
+                connectionCreated(callId, request, createdConnection);
             }
         } else {
             // Tell telecomm to try a different service.
-            Log.d(this, "adapter handleCreateConnectionFailed %s", request.getCallId());
-            mAdapter.handleCreateConnectionFailed(request, DisconnectCause.ERROR_UNSPECIFIED, null);
+            Log.d(this, "adapter handleCreateConnectionFailed %s", callId);
+            mAdapter.handleCreateConnectionFailed(
+                    callId,
+                    request,
+                    DisconnectCause.ERROR_UNSPECIFIED,
+                    null);
         }
     }
 
-    private void connectionCreated(ConnectionRequest request, Connection connection) {
-        addConnection(request.getCallId(), connection);
+    private void connectionCreated(
+            String callId,
+            ConnectionRequest request,
+            Connection connection) {
+        addConnection(callId, connection);
         Uri handle = connection.getHandle();
         String number = handle == null ? "null" : handle.getSchemeSpecificPart();
         Log.v(this, "connectionCreated, parcelableconnection: %s, %d, %s",
-                toLogSafePhoneNumber(number),
+                Connection.toLogSafePhoneNumber(number),
                 connection.getState(),
-                CallCapabilities.toString(connection.getCallCapabilities()));
+                PhoneCapabilities.toString(connection.getCallCapabilities()));
 
-        Log.d(this, "adapter handleCreateConnectionSuccessful %s", request.getCallId());
+        Log.d(this, "adapter handleCreateConnectionSuccessful %s", callId);
         mAdapter.handleCreateConnectionSuccessful(
+                callId,
                 request,
                 new ParcelableConnection(
                         request.getAccountHandle(),
@@ -566,8 +537,8 @@
                         connection.getHandlePresentation(),
                         connection.getCallerDisplayName(),
                         connection.getCallerDisplayNamePresentation(),
-                        connection.getVideoCallProvider() == null ?
-                                null : connection.getVideoCallProvider().getInterface(),
+                        connection.getVideoProvider() == null ?
+                                null : connection.getVideoProvider().getInterface(),
                         connection.getVideoState()));
     }
 
@@ -601,7 +572,7 @@
         findConnectionForAction(callId, "unhold").onUnhold();
     }
 
-    private void onAudioStateChanged(String callId, CallAudioState audioState) {
+    private void onAudioStateChanged(String callId, AudioState audioState) {
         Log.d(this, "onAudioStateChanged %s %s", callId, audioState);
         findConnectionForAction(callId, "onAudioStateChanged").setAudioState(audioState);
     }
@@ -620,7 +591,7 @@
         Log.d(this, "conference %s, %s", conferenceCallId, callId);
 
         Connection connection = findConnectionForAction(callId, "conference");
-        if (connection == getNullConnection()) {
+        if (connection == Connection.getNullConnection()) {
             Log.w(this, "Connection missing in conference request %s.", callId);
             return;
         }
@@ -653,7 +624,7 @@
         Log.d(this, "splitFromConference(%s)", callId);
 
         Connection connection = findConnectionForAction(callId, "splitFromConference");
-        if (connection == getNullConnection()) {
+        if (connection == Connection.getNullConnection()) {
             Log.w(this, "Connection missing in conference request %s.", callId);
             return;
         }
@@ -661,11 +632,6 @@
         // TODO: Find existing conference call and invoke split(connection).
     }
 
-    private void swapWithBackgroundCall(String callId) {
-        Log.d(this, "swapWithBackgroundCall(%s)", callId);
-        findConnectionForAction(callId, "swapWithBackgroundCall").onSwapWithBackgroundCall();
-    }
-
     private void onPostDialContinue(String callId, boolean proceed) {
         Log.d(this, "onPostDialContinue(%s)", callId);
         findConnectionForAction(callId, "stopDtmfTone").onPostDialContinue(proceed);
@@ -792,7 +758,7 @@
      *         making the connection.
      * @param request Details about the outgoing call.
      * @return The {@code Connection} object to satisfy this call, or the result of an invocation
-     *         of {@link Connection#getFailedConnection(int, String)} to not handle the call.
+     *         of {@link Connection#createFailedConnection(int, String)} to not handle the call.
      */
     public Connection onCreateOutgoingConnection(
             PhoneAccountHandle connectionManagerPhoneAccount,
@@ -805,6 +771,9 @@
      * specified connection into a conference call. The specified connection can be any connection
      * which had previously specified itself as conference-capable including both simple connections
      * and connections previously returned from this method.
+     * <p>
+     * TODO: To be refactored out with conference call re-engineering<br/>
+     * TODO: Also remove class {@link Response} once this method is removed
      *
      * @param connection The connection from which the user opted to start a conference call.
      * @param token The token to be passed into the response callback.
@@ -829,31 +798,6 @@
      */
     public void onConnectionRemoved(Connection connection) {}
 
-    static String toLogSafePhoneNumber(String number) {
-        // For unknown number, log empty string.
-        if (number == null) {
-            return "";
-        }
-
-        if (PII_DEBUG) {
-            // When PII_DEBUG is true we emit PII.
-            return number;
-        }
-
-        // Do exactly same thing as Uri#toSafeString() does, which will enable us to compare
-        // sanitized phone numbers.
-        StringBuilder builder = new StringBuilder();
-        for (int i = 0; i < number.length(); i++) {
-            char c = number.charAt(i);
-            if (c == '-' || c == '@' || c == '.') {
-                builder.append(c);
-            } else {
-                builder.append('x');
-            }
-        }
-        return builder.toString();
-    }
-
     private void onAccountsInitialized() {
         mAreAccountsInitialized = true;
         for (Runnable r : mPreInitializationConnectionRequests) {
@@ -883,346 +827,7 @@
             return mConnectionById.get(callId);
         }
         Log.w(this, "%s - Cannot find Connection %s", action, callId);
-        return getNullConnection();
+        return Connection.getNullConnection();
     }
 
-    private final static synchronized Connection getNullConnection() {
-        if (sNullConnection == null) {
-            sNullConnection = new Connection() {};
-        }
-        return sNullConnection;
-    }
-
-    /**
-     * Abstraction for a class which provides video call functionality. This class contains no base
-     * implementation for its methods. It is expected that subclasses will override these
-     * functions to provide the desired behavior if it is supported.
-     */
-    public static abstract class VideoCallProvider {
-        private static final int MSG_SET_VIDEO_CALL_LISTENER = 1;
-        private static final int MSG_SET_CAMERA = 2;
-        private static final int MSG_SET_PREVIEW_SURFACE = 3;
-        private static final int MSG_SET_DISPLAY_SURFACE = 4;
-        private static final int MSG_SET_DEVICE_ORIENTATION = 5;
-        private static final int MSG_SET_ZOOM = 6;
-        private static final int MSG_SEND_SESSION_MODIFY_REQUEST = 7;
-        private static final int MSG_SEND_SESSION_MODIFY_RESPONSE = 8;
-        private static final int MSG_REQUEST_CAMERA_CAPABILITIES = 9;
-        private static final int MSG_REQUEST_CALL_DATA_USAGE = 10;
-        private static final int MSG_SET_PAUSE_IMAGE = 11;
-
-        private final VideoCallProviderHandler mMessageHandler = new VideoCallProviderHandler();
-        private final VideoCallProviderBinder mBinder;
-        private IVideoCallCallback mVideoCallListener;
-
-        /**
-         * Default handler used to consolidate binder method calls onto a single thread.
-         */
-        private final class VideoCallProviderHandler extends Handler {
-            @Override
-            public void handleMessage(Message msg) {
-                switch (msg.what) {
-                    case MSG_SET_VIDEO_CALL_LISTENER:
-                        mVideoCallListener = IVideoCallCallback.Stub.asInterface((IBinder) msg.obj);
-                        break;
-                    case MSG_SET_CAMERA:
-                        onSetCamera((String) msg.obj);
-                        break;
-                    case MSG_SET_PREVIEW_SURFACE:
-                        onSetPreviewSurface((Surface) msg.obj);
-                        break;
-                    case MSG_SET_DISPLAY_SURFACE:
-                        onSetDisplaySurface((Surface) msg.obj);
-                        break;
-                    case MSG_SET_DEVICE_ORIENTATION:
-                        onSetDeviceOrientation(msg.arg1);
-                        break;
-                    case MSG_SET_ZOOM:
-                        onSetZoom((Float) msg.obj);
-                        break;
-                    case MSG_SEND_SESSION_MODIFY_REQUEST:
-                        onSendSessionModifyRequest((VideoCallProfile) msg.obj);
-                        break;
-                    case MSG_SEND_SESSION_MODIFY_RESPONSE:
-                        onSendSessionModifyResponse((VideoCallProfile) msg.obj);
-                        break;
-                    case MSG_REQUEST_CAMERA_CAPABILITIES:
-                        onRequestCameraCapabilities();
-                        break;
-                    case MSG_REQUEST_CALL_DATA_USAGE:
-                        onRequestCallDataUsage();
-                        break;
-                    case MSG_SET_PAUSE_IMAGE:
-                        onSetPauseImage((String) msg.obj);
-                        break;
-                    default:
-                        break;
-                }
-            }
-        }
-
-        /**
-         * IVideoCallProvider stub implementation.
-         */
-        private final class VideoCallProviderBinder extends IVideoCallProvider.Stub {
-            public void setVideoCallListener(IBinder videoCallListenerBinder) {
-                mMessageHandler.obtainMessage(
-                        MSG_SET_VIDEO_CALL_LISTENER, videoCallListenerBinder).sendToTarget();
-            }
-
-            public void setCamera(String cameraId) {
-                mMessageHandler.obtainMessage(MSG_SET_CAMERA, cameraId).sendToTarget();
-            }
-
-            public void setPreviewSurface(Surface surface) {
-                mMessageHandler.obtainMessage(MSG_SET_PREVIEW_SURFACE, surface).sendToTarget();
-            }
-
-            public void setDisplaySurface(Surface surface) {
-                mMessageHandler.obtainMessage(MSG_SET_DISPLAY_SURFACE, surface).sendToTarget();
-            }
-
-            public void setDeviceOrientation(int rotation) {
-                mMessageHandler.obtainMessage(MSG_SET_DEVICE_ORIENTATION, rotation).sendToTarget();
-            }
-
-            public void setZoom(float value) {
-                mMessageHandler.obtainMessage(MSG_SET_ZOOM, value).sendToTarget();
-            }
-
-            public void sendSessionModifyRequest(VideoCallProfile requestProfile) {
-                mMessageHandler.obtainMessage(
-                        MSG_SEND_SESSION_MODIFY_REQUEST, requestProfile).sendToTarget();
-            }
-
-            public void sendSessionModifyResponse(VideoCallProfile responseProfile) {
-                mMessageHandler.obtainMessage(
-                        MSG_SEND_SESSION_MODIFY_RESPONSE, responseProfile).sendToTarget();
-            }
-
-            public void requestCameraCapabilities() {
-                mMessageHandler.obtainMessage(MSG_REQUEST_CAMERA_CAPABILITIES).sendToTarget();
-            }
-
-            public void requestCallDataUsage() {
-                mMessageHandler.obtainMessage(MSG_REQUEST_CALL_DATA_USAGE).sendToTarget();
-            }
-
-            public void setPauseImage(String uri) {
-                mMessageHandler.obtainMessage(MSG_SET_PAUSE_IMAGE, uri).sendToTarget();
-            }
-        }
-
-        public VideoCallProvider() {
-            mBinder = new VideoCallProviderBinder();
-        }
-
-        /**
-         * Returns binder object which can be used across IPC methods.
-         * @hide
-         */
-        public final IVideoCallProvider getInterface() {
-            return mBinder;
-        }
-
-        /**
-         * Sets the camera to be used for video recording in a video call.
-         *
-         * @param cameraId The id of the camera.
-         */
-        public void onSetCamera(String cameraId) {
-            // To be implemented by subclass.
-        }
-
-        /**
-         * Sets the surface to be used for displaying a preview of what the user's camera is
-         * currently capturing.  When video transmission is enabled, this is the video signal which
-         * is sent to the remote device.
-         *
-         * @param surface The surface.
-         */
-        public void onSetPreviewSurface(Surface surface) {
-            // To be implemented by subclass.
-        }
-
-        /**
-         * Sets the surface to be used for displaying the video received from the remote device.
-         *
-         * @param surface The surface.
-         */
-        public void onSetDisplaySurface(Surface surface) {
-            // To be implemented by subclass.
-        }
-
-        /**
-         * Sets the device orientation, in degrees.  Assumes that a standard portrait orientation of
-         * the device is 0 degrees.
-         *
-         * @param rotation The device orientation, in degrees.
-         */
-        public void onSetDeviceOrientation(int rotation) {
-            // To be implemented by subclass.
-        }
-
-        /**
-         * Sets camera zoom ratio.
-         *
-         * @param value The camera zoom ratio.
-         */
-        public void onSetZoom(float value) {
-            // To be implemented by subclass.
-        }
-
-        /**
-         * Issues a request to modify the properties of the current session.  The request is sent to
-         * the remote device where it it handled by
-         * {@link InCallService.VideoCall.Listener#onSessionModifyRequestReceived}.
-         * Some examples of session modification requests: upgrade call from audio to video, downgrade
-         * call from video to audio, pause video.
-         *
-         * @param requestProfile The requested call video properties.
-         */
-        public void onSendSessionModifyRequest(VideoCallProfile requestProfile) {
-            // To be implemented by subclass.
-        }
-
-        /**
-         * Provides a response to a request to change the current call session video
-         * properties.
-         * This is in response to a request the InCall UI has received via
-         * {@link InCallService.VideoCall.Listener#onSessionModifyRequestReceived}.
-         * The response is handled on the remove device by
-         * {@link InCallService.VideoCall.Listener#onSessionModifyResponseReceived}.
-         *
-         * @param responseProfile The response call video properties.
-         */
-        public void onSendSessionModifyResponse(VideoCallProfile responseProfile) {
-            // To be implemented by subclass.
-        }
-
-        /**
-         * Issues a request to the video provider to retrieve the camera capabilities.
-         * Camera capabilities are reported back to the caller via
-         * {@link InCallService.VideoCall.Listener#onCameraCapabilitiesChanged(CallCameraCapabilities)}.
-         */
-        public void onRequestCameraCapabilities() {
-            // To be implemented by subclass.
-        }
-
-        /**
-         * Issues a request to the video telephony framework to retrieve the cumulative data usage for
-         * the current call.  Data usage is reported back to the caller via
-         * {@link InCallService.VideoCall.Listener#onCallDataUsageChanged}.
-         */
-        public void onRequestCallDataUsage() {
-            // To be implemented by subclass.
-        }
-
-        /**
-         * Provides the video telephony framework with the URI of an image to be displayed to remote
-         * devices when the video signal is paused.
-         *
-         * @param uri URI of image to display.
-         */
-        public void onSetPauseImage(String uri) {
-            // To be implemented by subclass.
-        }
-
-        /**
-         * Invokes callback method defined in {@link InCallService.VideoCall.Listener}.
-         *
-         * @param videoCallProfile The requested video call profile.
-         */
-        public void receiveSessionModifyRequest(VideoCallProfile videoCallProfile) {
-            if (mVideoCallListener != null) {
-                try {
-                    mVideoCallListener.receiveSessionModifyRequest(videoCallProfile);
-                } catch (RemoteException ignored) {
-                }
-            }
-        }
-
-        /**
-         * Invokes callback method defined in {@link InCallService.VideoCall.Listener}.
-         *
-         * @param status Status of the session modify request.  Valid values are
-         *               {@link InCallService.VideoCall#SESSION_MODIFY_REQUEST_SUCCESS},
-         *               {@link InCallService.VideoCall#SESSION_MODIFY_REQUEST_FAIL},
-         *               {@link InCallService.VideoCall#SESSION_MODIFY_REQUEST_INVALID}
-         * @param requestedProfile The original request which was sent to the remote device.
-         * @param responseProfile The actual profile changes made by the remote device.
-         */
-        public void receiveSessionModifyResponse(
-                int status, VideoCallProfile requestedProfile, VideoCallProfile responseProfile) {
-            if (mVideoCallListener != null) {
-                try {
-                    mVideoCallListener.receiveSessionModifyResponse(
-                            status, requestedProfile, responseProfile);
-                } catch (RemoteException ignored) {
-                }
-            }
-        }
-
-        /**
-         * Invokes callback method defined in {@link InCallService.VideoCall.Listener}.
-         *
-         * Valid values are: {@link InCallService.VideoCall#SESSION_EVENT_RX_PAUSE},
-         * {@link InCallService.VideoCall#SESSION_EVENT_RX_RESUME},
-         * {@link InCallService.VideoCall#SESSION_EVENT_TX_START},
-         * {@link InCallService.VideoCall#SESSION_EVENT_TX_STOP}
-         *
-         * @param event The event.
-         */
-        public void handleCallSessionEvent(int event) {
-            if (mVideoCallListener != null) {
-                try {
-                    mVideoCallListener.handleCallSessionEvent(event);
-                } catch (RemoteException ignored) {
-                }
-            }
-        }
-
-        /**
-         * Invokes callback method defined in {@link InCallService.VideoCall.Listener}.
-         *
-         * @param width  The updated peer video width.
-         * @param height The updated peer video height.
-         */
-        public void changePeerDimensions(int width, int height) {
-            if (mVideoCallListener != null) {
-                try {
-                    mVideoCallListener.changePeerDimensions(width, height);
-                } catch (RemoteException ignored) {
-                }
-            }
-        }
-
-        /**
-         * Invokes callback method defined in {@link InCallService.VideoCall.Listener}.
-         *
-         * @param dataUsage The updated data usage.
-         */
-        public void changeCallDataUsage(int dataUsage) {
-            if (mVideoCallListener != null) {
-                try {
-                    mVideoCallListener.changeCallDataUsage(dataUsage);
-                } catch (RemoteException ignored) {
-                }
-            }
-        }
-
-        /**
-         * Invokes callback method defined in {@link InCallService.VideoCall.Listener}.
-         *
-         * @param callCameraCapabilities The changed camera capabilities.
-         */
-        public void changeCameraCapabilities(CallCameraCapabilities callCameraCapabilities) {
-            if (mVideoCallListener != null) {
-                try {
-                    mVideoCallListener.changeCameraCapabilities(callCameraCapabilities);
-                } catch (RemoteException ignored) {
-                }
-            }
-        }
-    }
 }
diff --git a/telecomm/java/android/telecomm/ConnectionServiceAdapter.java b/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
index 9fd3a97..bfcb5c3 100644
--- a/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
@@ -17,18 +17,13 @@
 package android.telecomm;
 
 import android.app.PendingIntent;
-import android.content.ComponentName;
 import android.net.Uri;
-import android.os.IBinder;
 import android.os.IBinder.DeathRecipient;
 import android.os.RemoteException;
 
-import com.android.internal.telecomm.IConnectionService;
 import com.android.internal.telecomm.IConnectionServiceAdapter;
-import com.android.internal.telecomm.IVideoCallProvider;
 import com.android.internal.telecomm.RemoteServiceCallback;
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
@@ -77,28 +72,36 @@
     }
 
     void handleCreateConnectionSuccessful(
-            ConnectionRequest request, ParcelableConnection connection) {
+            String id,
+            ConnectionRequest request,
+            ParcelableConnection connection) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.handleCreateConnectionSuccessful(request, connection);
+                adapter.handleCreateConnectionSuccessful(id, request, connection);
             } catch (RemoteException e) {
             }
         }
     }
 
-    void handleCreateConnectionFailed(ConnectionRequest request, int errorCode, String errorMsg) {
+    void handleCreateConnectionFailed(
+            String id,
+            ConnectionRequest request,
+            int errorCode,
+            String errorMsg) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.handleCreateConnectionFailed(request, errorCode, errorMsg);
+                adapter.handleCreateConnectionFailed(id, request, errorCode, errorMsg);
             } catch (RemoteException e) {
             }
         }
     }
 
-    void handleCreateConnectionCancelled(ConnectionRequest request) {
+    void handleCreateConnectionCancelled(
+            String id,
+            ConnectionRequest request) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.handleCreateConnectionCancelled(request);
+                adapter.handleCreateConnectionCancelled(id, request);
             } catch (RemoteException e) {
             }
         }
@@ -275,15 +278,15 @@
      * Sets the call video provider for a call.
      *
      * @param callId The unique ID of the call to set with the given call video provider.
-     * @param videoCallProvider The call video provider instance to set on the call.
+     * @param videoProvider The call video provider instance to set on the call.
      */
-    void setVideoCallProvider(
-            String callId, ConnectionService.VideoCallProvider videoCallProvider) {
+    void setVideoProvider(
+            String callId, Connection.VideoProvider videoProvider) {
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.setVideoCallProvider(
+                adapter.setVideoProvider(
                         callId,
-                        videoCallProvider == null ? null : videoCallProvider.getInterface());
+                        videoProvider == null ? null : videoProvider.getInterface());
             } catch (RemoteException e) {
             }
         }
@@ -334,10 +337,10 @@
     /**
      * Sets the video state associated with a call.
      *
-     * Valid values: {@link android.telecomm.VideoCallProfile#VIDEO_STATE_AUDIO_ONLY},
-     * {@link android.telecomm.VideoCallProfile#VIDEO_STATE_BIDIRECTIONAL},
-     * {@link android.telecomm.VideoCallProfile#VIDEO_STATE_TX_ENABLED},
-     * {@link android.telecomm.VideoCallProfile#VIDEO_STATE_RX_ENABLED}.
+     * Valid values: {@link VideoProfile.VideoState#AUDIO_ONLY},
+     * {@link VideoProfile.VideoState#BIDIRECTIONAL},
+     * {@link VideoProfile.VideoState#TX_ENABLED},
+     * {@link VideoProfile.VideoState#RX_ENABLED}.
      *
      * @param callId The unique ID of the call to set the video state for.
      * @param videoState The video state.
diff --git a/telecomm/java/android/telecomm/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecomm/ConnectionServiceAdapterServant.java
index 1685bd7..2632924 100644
--- a/telecomm/java/android/telecomm/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecomm/ConnectionServiceAdapterServant.java
@@ -24,7 +24,7 @@
 
 import com.android.internal.os.SomeArgs;
 import com.android.internal.telecomm.IConnectionServiceAdapter;
-import com.android.internal.telecomm.IVideoCallProvider;
+import com.android.internal.telecomm.IVideoProvider;
 import com.android.internal.telecomm.RemoteServiceCallback;
 
 import java.util.List;
@@ -80,8 +80,9 @@
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
                         mDelegate.handleCreateConnectionSuccessful(
-                                (ConnectionRequest) args.arg1,
-                                (ParcelableConnection) args.arg2);
+                                (String) args.arg1,
+                                (ConnectionRequest) args.arg2,
+                                (ParcelableConnection) args.arg3);
                     } finally {
                         args.recycle();
                     }
@@ -91,16 +92,24 @@
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
                         mDelegate.handleCreateConnectionFailed(
-                                (ConnectionRequest) args.arg1,
+                                (String) args.arg1,
+                                (ConnectionRequest) args.arg2,
                                 args.argi1,
-                                (String) args.arg2);
+                                (String) args.arg3);
                     } finally {
                         args.recycle();
                     }
                     break;
                 }
                 case MSG_HANDLE_CREATE_CONNECTION_CANCELLED: {
-                    mDelegate.handleCreateConnectionCancelled((ConnectionRequest) msg.obj);
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        mDelegate.handleCreateConnectionCancelled(
+                                (String) args.arg1,
+                                (ConnectionRequest) args.arg2);
+                    } finally {
+                        args.recycle();
+                    }
                     break;
                 }
                 case MSG_SET_ACTIVE:
@@ -164,8 +173,8 @@
                 case MSG_SET_VIDEO_CALL_PROVIDER: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.setVideoCallProvider((String) args.arg1,
-                                (IVideoCallProvider) args.arg2);
+                        mDelegate.setVideoProvider((String) args.arg1,
+                                (IVideoProvider) args.arg2);
                     } finally {
                         args.recycle();
                     }
@@ -229,26 +238,38 @@
     private final IConnectionServiceAdapter mStub = new IConnectionServiceAdapter.Stub() {
         @Override
         public void handleCreateConnectionSuccessful(
-                ConnectionRequest request, ParcelableConnection connection) {
+                String id,
+                ConnectionRequest request,
+                ParcelableConnection connection) {
             SomeArgs args = SomeArgs.obtain();
-            args.arg1 = request;
-            args.arg2 = connection;
+            args.arg1 = id;
+            args.arg2 = request;
+            args.arg3 = connection;
             mHandler.obtainMessage(MSG_HANDLE_CREATE_CONNECTION_SUCCESSFUL, args).sendToTarget();
         }
 
         @Override
         public void handleCreateConnectionFailed(
-                ConnectionRequest request, int errorCode, String errorMessage) {
+                String id,
+                ConnectionRequest request,
+                int errorCode,
+                String errorMessage) {
             SomeArgs args = SomeArgs.obtain();
-            args.arg1 = request;
+            args.arg1 = id;
+            args.arg2 = request;
             args.argi1 = errorCode;
-            args.arg2 = errorMessage;
+            args.arg3 = errorMessage;
             mHandler.obtainMessage(MSG_HANDLE_CREATE_CONNECTION_FAILED, args).sendToTarget();
         }
 
         @Override
-        public void handleCreateConnectionCancelled(ConnectionRequest request) {
-            mHandler.obtainMessage(MSG_HANDLE_CREATE_CONNECTION_CANCELLED, request).sendToTarget();
+        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();
         }
 
         @Override
@@ -330,11 +351,10 @@
         }
 
         @Override
-        public void setVideoCallProvider(
-                String connectionId, IVideoCallProvider videoCallProvider) {
+        public void setVideoProvider(String connectionId, IVideoProvider videoProvider) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
-            args.arg2 = videoCallProvider;
+            args.arg2 = videoProvider;
             mHandler.obtainMessage(MSG_SET_VIDEO_CALL_PROVIDER, args).sendToTarget();
         }
 
diff --git a/telecomm/java/android/telecomm/GatewayInfo.aidl b/telecomm/java/android/telecomm/GatewayInfo.aidl
index d59e9b4..bd81014 100644
--- a/telecomm/java/android/telecomm/GatewayInfo.aidl
+++ b/telecomm/java/android/telecomm/GatewayInfo.aidl
@@ -16,4 +16,7 @@
 
 package android.telecomm;
 
+/**
+ * {@hide}
+ */
 parcelable GatewayInfo;
diff --git a/telecomm/java/android/telecomm/InCallAdapter.java b/telecomm/java/android/telecomm/InCallAdapter.java
index 08eb03a..80f7b57 100644
--- a/telecomm/java/android/telecomm/InCallAdapter.java
+++ b/telecomm/java/android/telecomm/InCallAdapter.java
@@ -28,6 +28,10 @@
  * given call IDs to execute commands such as {@link #answerCall} for incoming calls or
  * {@link #disconnectCall} for active calls the user would like to end. Some commands are only
  * appropriate for calls in certain states; please consult each method for such limitations.
+ * <p>
+ * The adapter will stop functioning when there are no more calls.
+ *
+ * {@hide}
  */
 public final class InCallAdapter {
     private final IInCallAdapter mAdapter;
@@ -115,7 +119,7 @@
     }
 
     /**
-     * Sets the audio route (speaker, bluetooth, etc...). See {@link CallAudioState}.
+     * Sets the audio route (speaker, bluetooth, etc...). See {@link AudioState}.
      *
      * @param route The audio route to use.
      */
@@ -237,19 +241,6 @@
     }
 
     /**
-     * Swap this call with a background call. This is used for calls that don't support hold,
-     * e.g. CDMA.
-     *
-     * @param callId The unique ID of the call.
-     */
-    public void swapWithBackgroundCall(String callId) {
-        try {
-            mAdapter.swapWithBackgroundCall(callId);
-        } catch (RemoteException ignored) {
-        }
-    }
-
-    /**
      * Instructs Telecomm to turn the proximity sensor on.
      */
     public void turnProximitySensorOn() {
diff --git a/telecomm/java/android/telecomm/InCallService.java b/telecomm/java/android/telecomm/InCallService.java
index b275809..de05d1c 100644
--- a/telecomm/java/android/telecomm/InCallService.java
+++ b/telecomm/java/android/telecomm/InCallService.java
@@ -35,7 +35,8 @@
  * This service is implemented by any app that wishes to provide the user-interface for managing
  * phone calls. Telecomm binds to this service while there exists a live (active or incoming) call,
  * and uses it to notify the in-call app of any live and and recently disconnected calls.
- * TODO: What happens if two or more apps on a given device implement this interface?
+ *
+ * {@hide}
  */
 public abstract class InCallService extends Service {
     private static final int MSG_SET_IN_CALL_ADAPTER = 1;
@@ -73,7 +74,7 @@
                     break;
                 }
                 case MSG_ON_AUDIO_STATE_CHANGED:
-                    mPhone.internalAudioStateChanged((CallAudioState) msg.obj);
+                    mPhone.internalAudioStateChanged((AudioState) msg.obj);
                     break;
                 case MSG_BRING_TO_FOREGROUND:
                     mPhone.internalBringToForeground(msg.arg1 == 1);
@@ -124,7 +125,7 @@
         }
 
         @Override
-        public void onAudioStateChanged(CallAudioState audioState) {
+        public void onAudioStateChanged(AudioState audioState) {
             mHandler.obtainMessage(MSG_ON_AUDIO_STATE_CHANGED, audioState).sendToTarget();
         }
 
@@ -191,56 +192,6 @@
     public static abstract class VideoCall {
 
         /**
-         * Video is not being received (no protocol pause was issued).
-         */
-        public static final int SESSION_EVENT_RX_PAUSE = 1;
-
-        /**
-         * Video reception has resumed after a SESSION_EVENT_RX_PAUSE.
-         */
-        public static final int SESSION_EVENT_RX_RESUME = 2;
-
-        /**
-         * Video transmission has begun. This occurs after a negotiated start of video transmission
-         * when the underlying protocol has actually begun transmitting video to the remote party.
-         */
-        public static final int SESSION_EVENT_TX_START = 3;
-
-        /**
-         * Video transmission has stopped. This occurs after a negotiated stop of video transmission
-         * when the underlying protocol has actually stopped transmitting video to the remote party.
-         */
-        public static final int SESSION_EVENT_TX_STOP = 4;
-
-        /**
-         * A camera failure has occurred for the selected camera.  The In-Call UI can use this as a
-         * cue to inform the user the camera is not available.
-         */
-        public static final int SESSION_EVENT_CAMERA_FAILURE = 5;
-
-        /**
-         * Issued after {@code SESSION_EVENT_CAMERA_FAILURE} when the camera is once again ready for
-         * operation.  The In-Call UI can use this as a cue to inform the user that the camera has
-         * become available again.
-         */
-        public static final int SESSION_EVENT_CAMERA_READY = 6;
-
-        /**
-         * Session modify request was successful.
-         */
-        public static final int SESSION_MODIFY_REQUEST_SUCCESS = 1;
-
-        /**
-         * Session modify request failed.
-         */
-        public static final int SESSION_MODIFY_REQUEST_FAIL = 2;
-
-        /**
-         * Session modify request ignored due to invalid parameters.
-         */
-        public static final int SESSION_MODIFY_REQUEST_INVALID = 3;
-
-        /**
          * Sets a listener to invoke callback methods in the InCallUI after performing video
          * telephony actions.
          *
@@ -295,7 +246,7 @@
          *
          * @param requestProfile The requested call video properties.
          */
-        public abstract void sendSessionModifyRequest(VideoCallProfile requestProfile);
+        public abstract void sendSessionModifyRequest(VideoProfile requestProfile);
 
         /**
          * Provides a response to a request to change the current call session video
@@ -307,12 +258,12 @@
          *
          * @param responseProfile The response call video properties.
          */
-        public abstract void sendSessionModifyResponse(VideoCallProfile responseProfile);
+        public abstract void sendSessionModifyResponse(VideoProfile responseProfile);
 
         /**
          * Issues a request to the video provider to retrieve the camera capabilities.
          * Camera capabilities are reported back to the caller via
-         * {@link VideoCall.Listener#onCameraCapabilitiesChanged(CallCameraCapabilities)}.
+         * {@link VideoCall.Listener#onCameraCapabilitiesChanged(CameraCapabilities)}.
          */
         public abstract void requestCameraCapabilities();
 
@@ -338,43 +289,44 @@
             /**
              * Called when a session modification request is received from the remote device.
              * The remote request is sent via
-             * {@link ConnectionService.VideoCallProvider#onSendSessionModifyRequest}. The InCall UI
+             * {@link Connection.VideoProvider#onSendSessionModifyRequest}. The InCall UI
              * is responsible for potentially prompting the user whether they wish to accept the new
              * call profile (e.g. prompt user if they wish to accept an upgrade from an audio to a
              * video call) and should call
-             * {@link ConnectionService.VideoCallProvider#onSendSessionModifyResponse} to indicate
+             * {@link Connection.VideoProvider#onSendSessionModifyResponse} to indicate
              * the video settings the user has agreed to.
              *
-             * @param videoCallProfile The requested video call profile.
+             * @param videoProfile The requested video call profile.
              */
-            public abstract void onSessionModifyRequestReceived(VideoCallProfile videoCallProfile);
+            public abstract void onSessionModifyRequestReceived(VideoProfile videoProfile);
 
             /**
              * Called when a response to a session modification request is received from the remote
              * device. The remote InCall UI sends the response using
-             * {@link ConnectionService.VideoCallProvider#onSendSessionModifyResponse}.
+             * {@link Connection.VideoProvider#onSendSessionModifyResponse}.
              *
              * @param status Status of the session modify request.  Valid values are
-             *               {@link VideoCall#SESSION_MODIFY_REQUEST_SUCCESS},
-             *               {@link VideoCall#SESSION_MODIFY_REQUEST_FAIL},
-             *               {@link VideoCall#SESSION_MODIFY_REQUEST_INVALID}
+             *               {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_SUCCESS},
+             *               {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_FAIL},
+             *               {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_INVALID}
              * @param requestedProfile The original request which was sent to the remote device.
              * @param responseProfile The actual profile changes made by the remote device.
              */
             public abstract void onSessionModifyResponseReceived(int status,
-                    VideoCallProfile requestedProfile, VideoCallProfile responseProfile);
+                    VideoProfile requestedProfile, VideoProfile responseProfile);
 
             /**
              * Handles events related to the current session which the client may wish to handle.
              * These are separate from requested changes to the session due to the underlying
              * protocol or connection.
              *
-             * Valid values are: {@link VideoCall#SESSION_EVENT_RX_PAUSE},
-             * {@link VideoCall#SESSION_EVENT_RX_RESUME},
-             * {@link VideoCall#SESSION_EVENT_TX_START},
-             * {@link VideoCall#SESSION_EVENT_TX_STOP},
-             * {@link VideoCall#SESSION_EVENT_CAMERA_FAILURE},
-             * {@link VideoCall#SESSION_EVENT_CAMERA_READY}
+             * Valid values are:
+             * {@link Connection.VideoProvider#SESSION_EVENT_RX_PAUSE},
+             * {@link Connection.VideoProvider#SESSION_EVENT_RX_RESUME},
+             * {@link Connection.VideoProvider#SESSION_EVENT_TX_START},
+             * {@link Connection.VideoProvider#SESSION_EVENT_TX_STOP},
+             * {@link Connection.VideoProvider#SESSION_EVENT_CAMERA_FAILURE},
+             * {@link Connection.VideoProvider#SESSION_EVENT_CAMERA_READY}
              *
              * @param event The event.
              */
@@ -399,10 +351,10 @@
             /**
              * Handles a change in camera capabilities.
              *
-             * @param callCameraCapabilities The changed camera capabilities.
+             * @param cameraCapabilities The changed camera capabilities.
              */
             public abstract void onCameraCapabilitiesChanged(
-                    CallCameraCapabilities callCameraCapabilities);
+                    CameraCapabilities cameraCapabilities);
         }
     }
 }
diff --git a/telecomm/java/android/telecomm/ParcelableCall.aidl b/telecomm/java/android/telecomm/ParcelableCall.aidl
index 8c96638..18691d2 100644
--- a/telecomm/java/android/telecomm/ParcelableCall.aidl
+++ b/telecomm/java/android/telecomm/ParcelableCall.aidl
@@ -16,4 +16,7 @@
 
 package android.telecomm;
 
+/**
+ * {@hide}
+ */
 parcelable ParcelableCall;
diff --git a/telecomm/java/android/telecomm/ParcelableCall.java b/telecomm/java/android/telecomm/ParcelableCall.java
index 360e768..8098b94 100644
--- a/telecomm/java/android/telecomm/ParcelableCall.java
+++ b/telecomm/java/android/telecomm/ParcelableCall.java
@@ -17,24 +17,25 @@
 package android.telecomm;
 
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.telephony.DisconnectCause;
 
-import com.android.internal.telecomm.IVideoCallProvider;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
+import com.android.internal.telecomm.IVideoProvider;
+
 /**
  * Information about a call that is used between InCallService and Telecomm.
  * @hide
  */
 public final class ParcelableCall implements Parcelable {
     private final String mId;
-    private final CallState mState;
+    private final int mState;
     private final int mDisconnectCauseCode;
     private final String mDisconnectCauseMsg;
     private final List<String> mCannedSmsResponses;
@@ -46,17 +47,18 @@
     private final int mCallerDisplayNamePresentation;
     private final GatewayInfo mGatewayInfo;
     private final PhoneAccountHandle mAccountHandle;
-    private final IVideoCallProvider mVideoCallProvider;
+    private final IVideoProvider mVideoCallProvider;
     private InCallService.VideoCall mVideoCall;
     private final String mParentCallId;
     private final List<String> mChildCallIds;
     private final StatusHints mStatusHints;
     private final int mVideoState;
     private final List<String> mConferenceableCallIds;
+    private final Bundle mExtras;
 
     public ParcelableCall(
             String id,
-            CallState state,
+            int state,
             int disconnectCauseCode,
             String disconnectCauseMsg,
             List<String> cannedSmsResponses,
@@ -68,12 +70,13 @@
             int callerDisplayNamePresentation,
             GatewayInfo gatewayInfo,
             PhoneAccountHandle accountHandle,
-            IVideoCallProvider videoCallProvider,
+            IVideoProvider videoCallProvider,
             String parentCallId,
             List<String> childCallIds,
             StatusHints statusHints,
             int videoState,
-            List<String> conferenceableCallIds) {
+            List<String> conferenceableCallIds,
+            Bundle extras) {
         mId = id;
         mState = state;
         mDisconnectCauseCode = disconnectCauseCode;
@@ -93,6 +96,7 @@
         mStatusHints = statusHints;
         mVideoState = videoState;
         mConferenceableCallIds = Collections.unmodifiableList(conferenceableCallIds);
+        mExtras = extras;
     }
 
     /** The unique ID of the call. */
@@ -101,7 +105,7 @@
     }
 
     /** The current state of the call. */
-    public CallState getState() {
+    public int getState() {
         return mState;
     }
 
@@ -143,7 +147,7 @@
         return mHandle;
     }
 
-    /** The {@link CallPropertyPresentation} which controls how the handle is shown. */
+    /** The {@link PropertyPresentation} which controls how the handle is shown. */
     public int getHandlePresentation() {
         return mHandlePresentation;
     }
@@ -153,7 +157,7 @@
         return mCallerDisplayName;
     }
 
-    /** The {@link CallPropertyPresentation} which controls how the caller display name is shown. */
+    /** The {@link PropertyPresentation} which controls how the caller display name is shown. */
     public int getCallerDisplayNamePresentation() {
         return mCallerDisplayNamePresentation;
     }
@@ -220,6 +224,15 @@
         return mVideoState;
     }
 
+    /**
+     * Any extras to pass with the call
+     *
+     * @return a bundle of extras
+     */
+    public Bundle getExtras() {
+        return mExtras;
+    }
+
     /** Responsible for creating ParcelableCall objects for deserialized Parcels. */
     public static final Parcelable.Creator<ParcelableCall> CREATOR =
             new Parcelable.Creator<ParcelableCall> () {
@@ -227,7 +240,7 @@
         public ParcelableCall createFromParcel(Parcel source) {
             ClassLoader classLoader = ParcelableCall.class.getClassLoader();
             String id = source.readString();
-            CallState state = CallState.valueOf(source.readString());
+            int state = source.readInt();
             int disconnectCauseCode = source.readInt();
             String disconnectCauseMsg = source.readString();
             List<String> cannedSmsResponses = new ArrayList<>();
@@ -240,8 +253,8 @@
             int callerDisplayNamePresentation = source.readInt();
             GatewayInfo gatewayInfo = source.readParcelable(classLoader);
             PhoneAccountHandle accountHandle = source.readParcelable(classLoader);
-            IVideoCallProvider videoCallProvider =
-                    IVideoCallProvider.Stub.asInterface(source.readStrongBinder());
+            IVideoProvider videoCallProvider =
+                    IVideoProvider.Stub.asInterface(source.readStrongBinder());
             String parentCallId = source.readString();
             List<String> childCallIds = new ArrayList<>();
             source.readList(childCallIds, classLoader);
@@ -249,11 +262,12 @@
             int videoState = source.readInt();
             List<String> conferenceableCallIds = new ArrayList<>();
             source.readList(conferenceableCallIds, classLoader);
+            Bundle extras = source.readParcelable(classLoader);
             return new ParcelableCall(id, state, disconnectCauseCode, disconnectCauseMsg,
                     cannedSmsResponses, capabilities, connectTimeMillis, handle, handlePresentation,
                     callerDisplayName, callerDisplayNamePresentation, gatewayInfo,
                     accountHandle, videoCallProvider, parentCallId, childCallIds, statusHints,
-                    videoState, conferenceableCallIds);
+                    videoState, conferenceableCallIds, extras);
         }
 
         @Override
@@ -272,7 +286,7 @@
     @Override
     public void writeToParcel(Parcel destination, int flags) {
         destination.writeString(mId);
-        destination.writeString(mState.name());
+        destination.writeInt(mState);
         destination.writeInt(mDisconnectCauseCode);
         destination.writeString(mDisconnectCauseMsg);
         destination.writeList(mCannedSmsResponses);
@@ -291,6 +305,7 @@
         destination.writeParcelable(mStatusHints, 0);
         destination.writeInt(mVideoState);
         destination.writeList(mConferenceableCallIds);
+        destination.writeParcelable(mExtras, 0);
     }
 
     @Override
diff --git a/telecomm/java/android/telecomm/ParcelableConnection.aidl b/telecomm/java/android/telecomm/ParcelableConnection.aidl
index e3c3bd2..143c5a6 100644
--- a/telecomm/java/android/telecomm/ParcelableConnection.aidl
+++ b/telecomm/java/android/telecomm/ParcelableConnection.aidl
@@ -16,4 +16,7 @@
 
 package android.telecomm;
 
+/**
+ * {@hide}
+ */
 parcelable ParcelableConnection;
diff --git a/telecomm/java/android/telecomm/ParcelableConnection.java b/telecomm/java/android/telecomm/ParcelableConnection.java
index 2f79004..78dd64a 100644
--- a/telecomm/java/android/telecomm/ParcelableConnection.java
+++ b/telecomm/java/android/telecomm/ParcelableConnection.java
@@ -20,7 +20,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import com.android.internal.telecomm.IVideoCallProvider;
+import com.android.internal.telecomm.IVideoProvider;
 
 /**
  * Information about a connection that is used between Telecomm and the ConnectionService.
@@ -36,7 +36,7 @@
     private int mHandlePresentation;
     private String mCallerDisplayName;
     private int mCallerDisplayNamePresentation;
-    private IVideoCallProvider mVideoCallProvider;
+    private IVideoProvider mVideoProvider;
     private int mVideoState;
 
     /** @hide */
@@ -48,7 +48,7 @@
             int handlePresentation,
             String callerDisplayName,
             int callerDisplayNamePresentation,
-            IVideoCallProvider videoCallProvider,
+            IVideoProvider videoProvider,
             int videoState) {
         mPhoneAccount = phoneAccount;
         mState = state;
@@ -57,7 +57,7 @@
         mHandlePresentation = handlePresentation;
         mCallerDisplayName = callerDisplayName;
         mCallerDisplayNamePresentation = callerDisplayNamePresentation;
-        mVideoCallProvider = videoCallProvider;
+        mVideoProvider = videoProvider;
         mVideoState = videoState;
     }
 
@@ -90,8 +90,8 @@
         return mCallerDisplayNamePresentation;
     }
 
-    public IVideoCallProvider getVideoCallProvider() {
-        return mVideoCallProvider;
+    public IVideoProvider getVideoProvider() {
+        return mVideoProvider;
     }
 
     public int getVideoState() {
@@ -106,7 +106,7 @@
                 .append(", state:")
                 .append(mState)
                 .append(", capabilities:")
-                .append(CallCapabilities.toString(mCapabilities))
+                .append(PhoneCapabilities.toString(mCapabilities))
                 .toString();
     }
 
@@ -123,8 +123,8 @@
             int handlePresentation = source.readInt();
             String callerDisplayName = source.readString();
             int callerDisplayNamePresentation = source.readInt();
-            IVideoCallProvider videoCallProvider =
-                    IVideoCallProvider.Stub.asInterface(source.readStrongBinder());
+            IVideoProvider videoCallProvider =
+                    IVideoProvider.Stub.asInterface(source.readStrongBinder());
             int videoState = source.readInt();
 
             return new ParcelableConnection(
@@ -162,7 +162,7 @@
         destination.writeString(mCallerDisplayName);
         destination.writeInt(mCallerDisplayNamePresentation);
         destination.writeStrongBinder(
-                mVideoCallProvider != null ? mVideoCallProvider.asBinder() : null);
+                mVideoProvider != null ? mVideoProvider.asBinder() : null);
         destination.writeInt(mVideoState);
     }
 }
diff --git a/telecomm/java/android/telecomm/Phone.java b/telecomm/java/android/telecomm/Phone.java
index 4ad572d..79e777a 100644
--- a/telecomm/java/android/telecomm/Phone.java
+++ b/telecomm/java/android/telecomm/Phone.java
@@ -27,6 +27,8 @@
 
 /**
  * A unified virtual device providing a means of voice (and other) communication on a device.
+ *
+ * {@hide}
  */
 public final class Phone {
 
@@ -35,9 +37,9 @@
          * Called when the audio state changes.
          *
          * @param phone The {@code Phone} calling this method.
-         * @param audioState The new {@link CallAudioState}.
+         * @param audioState The new {@link AudioState}.
          */
-        public void onAudioStateChanged(Phone phone, CallAudioState audioState) { }
+        public void onAudioStateChanged(Phone phone, AudioState audioState) { }
 
         /**
          * Called to bring the in-call screen to the foreground. The in-call experience should
@@ -85,7 +87,7 @@
 
     private final InCallAdapter mInCallAdapter;
 
-    private CallAudioState mAudioState;
+    private AudioState mAudioState;
 
     private final List<Listener> mListeners = new ArrayList<>();
 
@@ -129,10 +131,10 @@
     }
 
     /** {@hide} */
-    final void internalAudioStateChanged(CallAudioState callAudioState) {
-        if (!Objects.equals(mAudioState, callAudioState)) {
-            mAudioState = callAudioState;
-            fireAudioStateChanged(callAudioState);
+    final void internalAudioStateChanged(AudioState audioState) {
+        if (!Objects.equals(mAudioState, audioState)) {
+            mAudioState = audioState;
+            fireAudioStateChanged(audioState);
         }
     }
 
@@ -229,7 +231,7 @@
      *
      * @return An object encapsulating the audio state.
      */
-    public final CallAudioState getAudioState() {
+    public final AudioState getAudioState() {
         return mAudioState;
     }
 
@@ -247,7 +249,7 @@
         }
     }
 
-    private void fireAudioStateChanged(CallAudioState audioState) {
+    private void fireAudioStateChanged(AudioState audioState) {
         Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
         for (int i = 0; i < listeners.length; i++) {
             listeners[i].onAudioStateChanged(this, audioState);
diff --git a/telecomm/java/android/telecomm/PhoneAccount.java b/telecomm/java/android/telecomm/PhoneAccount.java
index 0fea7ba..411f48c 100644
--- a/telecomm/java/android/telecomm/PhoneAccount.java
+++ b/telecomm/java/android/telecomm/PhoneAccount.java
@@ -27,7 +27,8 @@
 import java.util.MissingResourceException;
 
 /**
- * Provides user interface description information for a {@code PhoneAccount}.
+ * Describes a distinct account, line of service or call placement method that the system
+ * can use to place phone calls.
  */
 public class PhoneAccount implements Parcelable {
 
@@ -37,9 +38,9 @@
      * will be allowed to manage phone calls including using its own proprietary phone-call
      * implementation (like VoIP calling) to make calls instead of the telephony stack.
      * <p>
-     * When a user opts to place a call using the SIM-based telephony stack, the connection-service
-     * associated with this phone-account will be attempted first if the user has explicitly
-     * selected it to be used as the default connection manager.
+     * When a user opts to place a call using the SIM-based telephony stack, the
+     * {@link ConnectionService} associated with this {@code PhoneAccount} will be attempted first
+     * if the user has explicitly selected it to be used as the default connection manager.
      * <p>
      * See {@link #getCapabilities}
      */
@@ -53,21 +54,25 @@
      * calls from or use the built-in telephony stack to place its calls.
      * <p>
      * See {@link #getCapabilities}
-     *
+     * <p>
      * {@hide}
      */
     public static final int CAPABILITY_CALL_PROVIDER = 0x2;
 
     /**
-     * Flag indicating that this {@code PhoneAccount} represents  built-in PSTN SIM
+     * Flag indicating that this {@code PhoneAccount} represents a built-in PSTN SIM
      * subscription.
      * <p>
-     * Only the android framework can set this capability on a phone account.
+     * Only the Android framework can register a {@code PhoneAccount} having this capability.
+     * <p>
+     * See {@link #getCapabilities}
      */
     public static final int CAPABILITY_SIM_SUBSCRIPTION = 0x4;
 
     /**
-     * Flag indicating that this {@code PhoneAccount} is capable of video calling.
+     * Flag indicating that this {@code PhoneAccount} is capable of placing video calls.
+     * <p>
+     * See {@link #getCapabilities}
      */
     public static final int CAPABILITY_VIDEO_CALLING = 0x8;
 
@@ -79,7 +84,65 @@
     private final CharSequence mLabel;
     private final CharSequence mShortDescription;
 
-    public PhoneAccount(
+    public static class Builder {
+        private PhoneAccountHandle mAccountHandle;
+        private Uri mHandle;
+        private String mSubscriptionNumber;
+        private int mCapabilities;
+        private int mIconResId;
+        private CharSequence mLabel;
+        private CharSequence mShortDescription;
+
+        private Builder() {}
+
+        public Builder withAccountHandle(PhoneAccountHandle value) {
+            this.mAccountHandle = value;
+            return this;
+        }
+
+        public Builder withHandle(Uri value) {
+            this.mHandle = value;
+            return this;
+        }
+
+        public Builder withSubscriptionNumber(String value) {
+            this.mSubscriptionNumber = value;
+            return this;
+        }
+
+        public Builder withCapabilities(int value) {
+            this.mCapabilities = value;
+            return this;
+        }
+
+        public Builder withIconResId(int value) {
+            this.mIconResId = value;
+            return this;
+        }
+
+        public Builder withLabel(CharSequence value) {
+            this.mLabel = value;
+            return this;
+        }
+
+        public Builder withShortDescription(CharSequence value) {
+            this.mShortDescription = value;
+            return this;
+        }
+
+        public PhoneAccount build() {
+            return new PhoneAccount(
+                    mAccountHandle,
+                    mHandle,
+                    mSubscriptionNumber,
+                    mCapabilities,
+                    mIconResId,
+                    mLabel,
+                    mShortDescription);
+        }
+    }
+
+    private PhoneAccount(
             PhoneAccountHandle account,
             Uri handle,
             String subscriptionNumber,
@@ -96,8 +159,10 @@
         mShortDescription = shortDescription;
     }
 
+    public static Builder builder() { return new Builder(); }
+
     /**
-     * The {@code PhoneAccountHandle} to which this metadata pertains.
+     * The unique identifier of this {@code PhoneAccount}.
      *
      * @return A {@code PhoneAccountHandle}.
      */
@@ -118,9 +183,15 @@
     }
 
     /**
-     * The subscription number associated with the underlying transport. This may differ from the
-     * {@link #getHandle()} number; for example, if the number used to talk to the network is not
-     * the same number that will be on the remote party's caller ID display.
+     * The raw callback number used for this {@code PhoneAccount}, as distinct from
+     * {@link #getHandle()}. For the majority of {@code PhoneAccount}s this should be registered
+     * as {@code null}.  It is used by the system for SIM-based {@code PhoneAccount} registration
+     * where {@link android.telephony.TelephonyManager#setLine1NumberForDisplay(String, String)}
+     * or {@link android.telephony.TelephonyManager#setLine1NumberForDisplay(long, String, String)}
+     * has been used to alter the callback number.
+     * <p>
+     * TODO: Should this also be a URI, for consistency? Should it be called the
+     * "subscription handle"?
      *
      * @return The subscription number, suitable for display to the user.
      */
@@ -147,7 +218,7 @@
     }
 
     /**
-     * A short paragraph describing a {@code PhoneAccount}.
+     * A short paragraph describing this {@code PhoneAccount}.
      *
      * @return A description for this {@code PhoneAccount}.
      */
@@ -183,7 +254,7 @@
             return null;
         }
         try {
-            return packageContext.getResources().getDrawable(resId);
+            return packageContext.getDrawable(resId);
         } catch (NotFoundException|MissingResourceException e) {
             Log.e(this, e, "Cannot find icon %d in package %s",
                     resId, mAccountHandle.getComponentName().getPackageName());
diff --git a/telecomm/java/android/telecomm/PhoneAccountHandle.java b/telecomm/java/android/telecomm/PhoneAccountHandle.java
index f14766c..04cd2b0 100644
--- a/telecomm/java/android/telecomm/PhoneAccountHandle.java
+++ b/telecomm/java/android/telecomm/PhoneAccountHandle.java
@@ -23,8 +23,7 @@
 import java.util.Objects;
 
 /**
- * Represents a distinct account, line of service or call placement method that
- * the system can use to place phone calls.
+ * The unique identifier for a {@link PhoneAccount}.
  */
 public class PhoneAccountHandle implements Parcelable {
     private ComponentName mComponentName;
@@ -48,10 +47,18 @@
     }
 
     /**
-     * A unique identifier for this {@code PhoneAccountHandle}, generated by and meaningful to the
-     * {@link android.telecomm.ConnectionService} that created it.
+     * A string that uniquely distinguishes this particular {@code PhoneAccountHandle} from all the
+     * others supported by the {@link ConnectionService} that created it.
+     * <p>
+     * A {@code ConnectionService} must select identifiers that are stable for the lifetime of
+     * their users' relationship with their service, across many Android devices. For example, a
+     * good set of identifiers might be the email addresses with which with users registered for
+     * their accounts with a particular service. Depending on how a service chooses to operate,
+     * a bad set of identifiers might be an increasing series of integers
+     * ({@code 0}, {@code 1}, {@code 2}, ...) that are generated locally on each phone and could
+     * collide with values generated on other phones or after a data wipe of a given phone.
      *
-     * @return A unique identifier for this {@code PhoneAccountHandle}.
+     * @return A service-specific unique identifier for this {@code PhoneAccountHandle}.
      */
     public String getId() {
         return mId;
diff --git a/telecomm/java/android/telecomm/CallCapabilities.java b/telecomm/java/android/telecomm/PhoneCapabilities.java
similarity index 92%
rename from telecomm/java/android/telecomm/CallCapabilities.java
rename to telecomm/java/android/telecomm/PhoneCapabilities.java
index e64fe80..45168d5 100644
--- a/telecomm/java/android/telecomm/CallCapabilities.java
+++ b/telecomm/java/android/telecomm/PhoneCapabilities.java
@@ -16,8 +16,12 @@
 
 package android.telecomm;
 
-/** Defines actions a call currently supports. */
-public final class CallCapabilities {
+/**
+ * Defines capabilities a phone call can support, such as conference calling and video telephony.
+ * Also defines properties of a phone call, such as whether it is using VoLTE technology.
+
+ */
+public final class PhoneCapabilities {
     /** Call can currently be put on hold or unheld. */
     public static final int HOLD               = 0x00000001;
 
@@ -98,5 +102,5 @@
         return builder.toString();
     }
 
-    private CallCapabilities() {}
+    private PhoneCapabilities() {}
 }
diff --git a/telecomm/java/android/telecomm/CallPropertyPresentation.java b/telecomm/java/android/telecomm/PropertyPresentation.java
similarity index 88%
rename from telecomm/java/android/telecomm/CallPropertyPresentation.java
rename to telecomm/java/android/telecomm/PropertyPresentation.java
index 319e565..fe97b3d 100644
--- a/telecomm/java/android/telecomm/CallPropertyPresentation.java
+++ b/telecomm/java/android/telecomm/PropertyPresentation.java
@@ -16,8 +16,10 @@
 
 package android.telecomm;
 
-/** Defines how numbers and names are displayed in caller id. */
-public class CallPropertyPresentation {
+/**
+ * Defines how properties such as phone numbers and names are displayed to the user.
+ */
+public class PropertyPresentation {
     /** Property is displayed normally. */
     public static final int ALLOWED = 1;
 
diff --git a/telecomm/java/android/telecomm/RemoteConnection.java b/telecomm/java/android/telecomm/RemoteConnection.java
index a8636d4..13b0834 100644
--- a/telecomm/java/android/telecomm/RemoteConnection.java
+++ b/telecomm/java/android/telecomm/RemoteConnection.java
@@ -16,22 +16,24 @@
 
 package android.telecomm;
 
+import com.android.internal.telecomm.IConnectionService;
+
 import android.app.PendingIntent;
 import android.net.Uri;
 import android.os.RemoteException;
 import android.telephony.DisconnectCause;
 
-import com.android.internal.telecomm.IConnectionService;
-
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
 
 /**
- * RemoteConnection object used by RemoteConnectionService.
+ * A connection provided to a {@link ConnectionService} by another {@code ConnectionService}
+ * running in a different process.
+ *
+ * @see ConnectionService#createRemoteOutgoingConnection(PhoneAccountHandle, ConnectionRequest)
+ * @see ConnectionService#createRemoteIncomingConnection(PhoneAccountHandle, ConnectionRequest)
  */
 public final class RemoteConnection {
 
@@ -100,7 +102,7 @@
          * Invoked when the post-dial sequence in the outgoing {@code Connection} has reached a
          * pause character. This causes the post-dial signals to stop pending user confirmation. An
          * implementation should present this choice to the user and invoke
-         * {@link #postDialContinue(boolean)} when the user makes the choice.
+         * {@link RemoteConnection#postDialContinue(boolean)} when the user makes the choice.
          *
          * @param connection The {@code RemoteConnection} invoking this method.
          * @param remainingPostDialSequence The post-dial characters that remain to be sent.
@@ -131,7 +133,7 @@
          *
          * @param connection The {@code RemoteConnection} invoking this method.
          * @param handle The new handle of the {@code RemoteConnection}.
-         * @param presentation The {@link CallPropertyPresentation} which controls how the
+         * @param presentation The {@link PropertyPresentation} which controls how the
          *         handle is shown.
          */
         public void onHandleChanged(RemoteConnection connection, Uri handle, int presentation) {}
@@ -142,7 +144,7 @@
          *
          * @param connection The {@code RemoteConnection} invoking this method.
          * @param callerDisplayName The new caller display name of the {@code RemoteConnection}.
-         * @param presentation The {@link CallPropertyPresentation} which controls how the
+         * @param presentation The {@link PropertyPresentation} which controls how the
          *         caller display name is shown.
          */
         public void onCallerDisplayNameChanged(
@@ -180,11 +182,10 @@
 
     private IConnectionService mConnectionService;
     private final String mConnectionId;
-    private final Set<Listener> mListeners = Collections.newSetFromMap(
-            new ConcurrentHashMap<Listener, Boolean>(2));
+    private final Set<Listener> mListeners = new HashSet<>();
     private final Set<RemoteConnection> mConferenceableConnections = new HashSet<>();
 
-    private int mState = Connection.State.NEW;
+    private int mState = Connection.STATE_NEW;
     private int mDisconnectCauseCode = DisconnectCause.NOT_VALID;
     private String mDisconnectCauseMessage;
     private boolean mRequestingRingback;
@@ -203,12 +204,14 @@
     /**
      * @hide
      */
-    RemoteConnection(IConnectionService connectionService, ConnectionRequest request) {
+    RemoteConnection(
+            String id,
+            IConnectionService connectionService,
+            ConnectionRequest request) {
+        mConnectionId = id;
         mConnectionService = connectionService;
-        mConnectionId = request == null ? "NULL" : request.getCallId();
-
         mConnected = true;
-        mState = Connection.State.INITIALIZING;
+        mState = Connection.STATE_INITIALIZING;
     }
 
     /**
@@ -219,10 +222,10 @@
      * @param failureCode
      * @param failureMessage
      */
-    private RemoteConnection(int failureCode, String failureMessage) {
-        this(null, null);
+    RemoteConnection(int failureCode, String failureMessage) {
+        this("NULL", null, null);
         mConnected = false;
-        mState = Connection.State.FAILED;
+        mState = Connection.STATE_FAILED;
         mFailureCode = failureCode;
         mFailureMessage = failureMessage;
     }
@@ -271,7 +274,7 @@
     }
 
     /**
-     * @return For a {@link Connection.State#DISCONNECTED} {@code RemoteConnection}, the
+     * @return For a {@link Connection#STATE_DISCONNECTED} {@code RemoteConnection}, the
      * disconnect cause expressed as a code chosen from among those declared in
      * {@link DisconnectCause}.
      */
@@ -280,7 +283,7 @@
     }
 
     /**
-     * @return For a {@link Connection.State#DISCONNECTED} {@code RemoteConnection}, an optional
+     * @return For a {@link Connection#STATE_DISCONNECTED} {@code RemoteConnection}, an optional
      * reason for disconnection expressed as a free text message.
      */
     public String getDisconnectCauseMessage() {
@@ -289,7 +292,7 @@
 
     /**
      * @return A bitmask of the capabilities of the {@code RemoteConnection}, as defined in
-     *         {@link CallCapabilities}.
+     *         {@link PhoneCapabilities}.
      */
     public int getCallCapabilities() {
         return mCallCapabilities;
@@ -303,7 +306,7 @@
     }
 
     /**
-     * @return The current {@link android.telecomm.StatusHints} of this {@code RemoteConnection},
+     * @return The current {@link StatusHints} of this {@code RemoteConnection},
      * or {@code null} if none have been set.
      */
     public StatusHints getStatusHints() {
@@ -320,7 +323,7 @@
 
     /**
      * @return The presentation requirements for the handle. See
-     * {@link android.telecomm.CallPropertyPresentation} for valid values.
+     * {@link PropertyPresentation} for valid values.
      */
     public int getHandlePresentation() {
         return mHandlePresentation;
@@ -335,7 +338,7 @@
 
     /**
      * @return The presentation requirements for the caller display name. See
-     * {@link android.telecomm.CallPropertyPresentation} for valid values.
+     * {@link PropertyPresentation} for valid values.
      */
     public int getCallerDisplayNamePresentation() {
         return mCallerDisplayNamePresentation;
@@ -343,7 +346,7 @@
 
     /**
      * @return The video state of the {@code RemoteConnection}. See
-     * {@link VideoCallProfile.VideoState}.
+     * {@link VideoProfile.VideoState}.
      */
     public int getVideoState() {
         return mVideoState;
@@ -385,7 +388,7 @@
     }
 
     /**
-     * Instructs this {@link Connection.State#RINGING} {@code RemoteConnection} to answer.
+     * Instructs this {@link Connection#STATE_RINGING} {@code RemoteConnection} to answer.
      * @param videoState The video state in which to answer the call.
      */
     public void answer(int videoState) {
@@ -398,7 +401,7 @@
     }
 
     /**
-     * Instructs this {@link Connection.State#RINGING} {@code RemoteConnection} to reject.
+     * Instructs this {@link Connection#STATE_RINGING} {@code RemoteConnection} to reject.
      */
     public void reject() {
         try {
@@ -422,7 +425,7 @@
     }
 
     /**
-     * Instructs this {@link Connection.State#HOLDING} call to release from hold.
+     * Instructs this {@link Connection#STATE_HOLDING} call to release from hold.
      */
     public void unhold() {
         try {
@@ -510,24 +513,11 @@
     }
 
     /**
-     * Instructs this {@code RemoteConnection} to swap itself with an existing background call,
-     * if one such call exists.
-     */
-    public void swapWithBackgroundCall() {
-        try {
-            if (mConnected) {
-                mConnectionService.swapWithBackgroundCall(mConnectionId);
-            }
-        } catch (RemoteException ignored) {
-        }
-    }
-
-    /**
      * Set the audio state of this {@code RemoteConnection}.
      *
      * @param state The audio state of this {@code RemoteConnection}.
      */
-    public void setAudioState(CallAudioState state) {
+    public void setAudioState(AudioState state) {
         try {
             if (mConnected) {
                 mConnectionService.onAudioStateChanged(mConnectionId, state);
@@ -552,8 +542,8 @@
      * @hide
      */
     void setDisconnected(int cause, String message) {
-        if (mState != Connection.State.DISCONNECTED) {
-            mState = Connection.State.DISCONNECTED;
+        if (mState != Connection.STATE_DISCONNECTED) {
+            mState = Connection.STATE_DISCONNECTED;
             mDisconnectCauseCode = cause;
             mDisconnectCauseMessage = message;
 
@@ -591,7 +581,7 @@
     void setDestroyed() {
         if (!mListeners.isEmpty()) {
             // Make sure that the listeners are notified that the call is destroyed first.
-            if (mState != Connection.State.DISCONNECTED) {
+            if (mState != Connection.STATE_DISCONNECTED) {
                 setDisconnected(DisconnectCause.ERROR_UNSPECIFIED, "Connection destroyed.");
             }
 
@@ -676,7 +666,7 @@
     }
 
     /**
-     * Create a RemoteConnection which is in the {@link Connection.State#FAILED} state. Attempting
+     * 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.
      *
      * @return a failed {@link RemoteConnection}
diff --git a/telecomm/java/android/telecomm/RemoteConnectionService.java b/telecomm/java/android/telecomm/RemoteConnectionService.java
index 95b62ba..9a1729f 100644
--- a/telecomm/java/android/telecomm/RemoteConnectionService.java
+++ b/telecomm/java/android/telecomm/RemoteConnectionService.java
@@ -11,7 +11,7 @@
  * 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
- R* limitations under the License.
+ * limitations under the License.
  */
 
 package android.telecomm;
@@ -25,7 +25,7 @@
 
 import com.android.internal.telecomm.IConnectionService;
 import com.android.internal.telecomm.IConnectionServiceAdapter;
-import com.android.internal.telecomm.IVideoCallProvider;
+import com.android.internal.telecomm.IVideoProvider;
 import com.android.internal.telecomm.RemoteServiceCallback;
 
 import java.util.HashMap;
@@ -43,14 +43,17 @@
  */
 final class RemoteConnectionService {
 
-    private static final RemoteConnection NULL_CONNECTION = new RemoteConnection(null, null);
+    private static final RemoteConnection
+            NULL_CONNECTION = new RemoteConnection("NULL", null, null);
 
     private final IConnectionServiceAdapter mServantDelegate = new IConnectionServiceAdapter() {
         @Override
-        public void handleCreateConnectionSuccessful(ConnectionRequest request,
+        public void handleCreateConnectionSuccessful(
+                String id,
+                ConnectionRequest request,
                 ParcelableConnection parcel) {
-            RemoteConnection connection = findConnectionForAction(
-                    request.getCallId(), "handleCreateConnectionSuccessful");
+            RemoteConnection connection =
+                    findConnectionForAction(id, "handleCreateConnectionSuccessful");
             if (connection != NULL_CONNECTION && mPendingConnections.contains(connection)) {
                 mPendingConnections.remove(connection);
                 connection.setState(parcel.getState());
@@ -65,37 +68,40 @@
         }
 
         @Override
-        public void handleCreateConnectionFailed(ConnectionRequest request, int errorCode,
+        public void handleCreateConnectionFailed(
+                String id,
+                ConnectionRequest request,
+                int errorCode,
                 String errorMessage) {
             // TODO: How do we propagate the failure codes?
-            findConnectionForAction(
-                    request.getCallId(), "handleCreateConnectionFailed")
+            findConnectionForAction(id, "handleCreateConnectionFailed")
                     .setDestroyed();
         }
 
         @Override
-        public void handleCreateConnectionCancelled(ConnectionRequest request) {
-            findConnectionForAction(
-                    request.getCallId(), "handleCreateConnectionCancelled")
+        public void handleCreateConnectionCancelled(
+                String id,
+                ConnectionRequest request) {
+            findConnectionForAction(id, "handleCreateConnectionCancelled")
                     .setDestroyed();
         }
 
         @Override
         public void setActive(String callId) {
             findConnectionForAction(callId, "setActive")
-                    .setState(Connection.State.ACTIVE);
+                    .setState(Connection.STATE_ACTIVE);
         }
 
         @Override
         public void setRinging(String callId) {
             findConnectionForAction(callId, "setRinging")
-                    .setState(Connection.State.RINGING);
+                    .setState(Connection.STATE_RINGING);
         }
 
         @Override
         public void setDialing(String callId) {
             findConnectionForAction(callId, "setDialing")
-                    .setState(Connection.State.DIALING);
+                    .setState(Connection.STATE_DIALING);
         }
 
         @Override
@@ -108,7 +114,7 @@
         @Override
         public void setOnHold(String callId) {
             findConnectionForAction(callId, "setOnHold")
-                    .setState(Connection.State.HOLDING);
+                    .setState(Connection.STATE_HOLDING);
         }
 
         @Override
@@ -151,8 +157,7 @@
         }
 
         @Override
-        public void setVideoCallProvider(String callId,
-                IVideoCallProvider videoCallProvider) {
+        public void setVideoProvider(String callId, IVideoProvider videoProvider) {
             // not supported for remote connections.
         }
 
@@ -244,9 +249,9 @@
             PhoneAccountHandle connectionManagerPhoneAccount,
             ConnectionRequest request,
             boolean isIncoming) {
+        final String id = UUID.randomUUID().toString();
         final ConnectionRequest newRequest = new ConnectionRequest(
                 request.getAccountHandle(),
-                UUID.randomUUID().toString(),
                 request.getHandle(),
                 request.getHandlePresentation(),
                 request.getExtras(),
@@ -256,17 +261,18 @@
                 mConnectionService.addConnectionServiceAdapter(mServant.getStub());
             }
             RemoteConnection connection =
-                    new RemoteConnection(mConnectionService, newRequest);
+                    new RemoteConnection(id, mConnectionService, newRequest);
             mPendingConnections.add(connection);
-            mConnectionById.put(newRequest.getCallId(), connection);
+            mConnectionById.put(id, connection);
             mConnectionService.createConnection(
                     connectionManagerPhoneAccount,
+                    id,
                     newRequest,
                     isIncoming);
             connection.addListener(new RemoteConnection.Listener() {
                 @Override
                 public void onDestroyed(RemoteConnection connection) {
-                    mConnectionById.remove(newRequest.getCallId());
+                    mConnectionById.remove(id);
                     if (mConnectionById.isEmpty()) {
                         try {
                             mConnectionService.removeConnectionServiceAdapter(mServant.getStub());
@@ -277,11 +283,13 @@
             });
             return connection;
         } catch (RemoteException e) {
-            return RemoteConnection.failure(DisconnectCause.ERROR_UNSPECIFIED, e.toString());
+            return RemoteConnection
+                    .failure(DisconnectCause.ERROR_UNSPECIFIED, e.toString());
         }
     }
 
-    private RemoteConnection findConnectionForAction(String callId, String action) {
+    private RemoteConnection findConnectionForAction(
+            String callId, String action) {
         if (mConnectionById.containsKey(callId)) {
             return mConnectionById.get(callId);
         }
diff --git a/telecomm/java/android/telecomm/Response.java b/telecomm/java/android/telecomm/Response.java
index 13c0702..f879756 100644
--- a/telecomm/java/android/telecomm/Response.java
+++ b/telecomm/java/android/telecomm/Response.java
@@ -17,7 +17,10 @@
 package android.telecomm;
 
 /**
- * Used to inform a client of asynchronously returned results.
+ * <strong>OBSOLETE</strong> Used to inform a client of asynchronously returned results.
+ * <p>
+ * <strong>TODO:</strong> Remove onCreateConferenceConnection() async method
+ * then delete this interface.
  */
 public interface Response<IN, OUT> {
 
diff --git a/telecomm/java/android/telecomm/SimpleResponse.java b/telecomm/java/android/telecomm/SimpleResponse.java
deleted file mode 100644
index 8e84adb..0000000
--- a/telecomm/java/android/telecomm/SimpleResponse.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telecomm;
-
-/**
- * Used to inform a client of asynchronously returned results.
- */
-public interface SimpleResponse<IN, OUT> {
-
-    /**
-     * Provide a set of results.
-     *
-     * @param request The original request.
-     * @param result The results.
-     */
-    void onResult(IN request, OUT result);
-
-    /**
-     * Indicates the inability to provide results.
-     *
-     * @param request The original request.
-     */
-    void onError(IN request);
-}
diff --git a/telecomm/java/android/telecomm/StatusHints.java b/telecomm/java/android/telecomm/StatusHints.java
index 496a38c..f7c4f2f 100644
--- a/telecomm/java/android/telecomm/StatusHints.java
+++ b/telecomm/java/android/telecomm/StatusHints.java
@@ -20,11 +20,9 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
-import android.net.Uri;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.util.DisplayMetrics;
 
 import java.util.MissingResourceException;
 import java.util.Objects;
@@ -36,13 +34,13 @@
 
     private final ComponentName mComponentName;
     private final CharSequence mLabel;
-    private final int mIconId;
+    private final int mIconResId;
     private final Bundle mExtras;
 
-    public StatusHints(ComponentName componentName, CharSequence label, int iconId, Bundle extras) {
+    public StatusHints(ComponentName componentName, CharSequence label, int iconResId, Bundle extras) {
         mComponentName = componentName;
         mLabel = label;
-        mIconId = iconId;
+        mIconResId = iconResId;
         mExtras = extras;
     }
 
@@ -61,17 +59,19 @@
     }
 
     /**
-     * @return The icon resource identifier.
+     * The icon resource ID for the icon to show.
+     *
+     * @return A resource ID.
      */
-    public int getIconId() {
-        return mIconId;
+    public int getIconResId() {
+        return mIconResId;
     }
 
     /**
      * @return An icon displayed in the in-call UI.
      */
     public Drawable getIcon(Context context) {
-        return getIcon(context, mIconId);
+        return getIcon(context, mIconResId);
     }
 
     /**
@@ -90,7 +90,7 @@
     public void writeToParcel(Parcel out, int flags) {
         out.writeParcelable(mComponentName, flags);
         out.writeCharSequence(mLabel);
-        out.writeInt(mIconId);
+        out.writeInt(mIconResId);
         out.writeParcelable(mExtras, 0);
     }
 
@@ -108,8 +108,8 @@
     private StatusHints(Parcel in) {
         mComponentName = in.readParcelable(getClass().getClassLoader());
         mLabel = in.readCharSequence();
-        mIconId = in.readInt();
-        mExtras = (Bundle) in.readParcelable(getClass().getClassLoader());
+        mIconResId = in.readInt();
+        mExtras = in.readParcelable(getClass().getClassLoader());
     }
 
     private Drawable getIcon(Context context, int resId) {
@@ -121,7 +121,7 @@
             return null;
         }
         try {
-            return packageContext.getResources().getDrawable(resId);
+            return packageContext.getDrawable(resId);
         } catch (MissingResourceException e) {
             Log.e(this, e, "Cannot find icon %d in package %s",
                     resId, mComponentName.getPackageName());
@@ -135,7 +135,7 @@
             StatusHints otherHints = (StatusHints) other;
             return Objects.equals(otherHints.getComponentName(), getComponentName()) &&
                     Objects.equals(otherHints.getLabel(), getLabel()) &&
-                    otherHints.getIconId() == getIconId() &&
+                    otherHints.getIconResId() == getIconResId() &&
                     Objects.equals(otherHints.getExtras(), getExtras());
         }
         return false;
@@ -143,7 +143,7 @@
 
     @Override
     public int hashCode() {
-        return Objects.hashCode(mComponentName) + Objects.hashCode(mLabel) + mIconId +
+        return Objects.hashCode(mComponentName) + Objects.hashCode(mLabel) + mIconResId +
                 Objects.hashCode(mExtras);
     }
 }
diff --git a/telecomm/java/android/telecomm/TelecommManager.java b/telecomm/java/android/telecomm/TelecommManager.java
index 0f31c52..5192b0f 100644
--- a/telecomm/java/android/telecomm/TelecommManager.java
+++ b/telecomm/java/android/telecomm/TelecommManager.java
@@ -72,10 +72,10 @@
      * Optional extra for {@link android.content.Intent#ACTION_CALL} containing an integer that
      * determines the desired video state for an outgoing call.
      * Valid options:
-     * {@link android.telecomm.VideoCallProfile.VideoState#AUDIO_ONLY},
-     * {@link android.telecomm.VideoCallProfile.VideoState#BIDIRECTIONAL},
-     * {@link android.telecomm.VideoCallProfile.VideoState#RX_ENABLED},
-     * {@link android.telecomm.VideoCallProfile.VideoState#TX_ENABLED}.
+     * {@link VideoProfile.VideoState#AUDIO_ONLY},
+     * {@link VideoProfile.VideoState#BIDIRECTIONAL},
+     * {@link VideoProfile.VideoState#RX_ENABLED},
+     * {@link VideoProfile.VideoState#TX_ENABLED}.
      */
     public static final String EXTRA_START_CALL_WITH_VIDEO_STATE =
             "android.intent.extra.START_CALL_WITH_VIDEO_STATE";
@@ -101,6 +101,17 @@
             "android.intent.extra.INCOMING_CALL_EXTRAS";
 
     /**
+     * Optional extra for {@link android.content.Intent#ACTION_CALL} and
+     * {@link android.content.Intent#ACTION_DIAL} {@code Intent} containing a {@link Bundle}
+     * which contains metadata about the call. This {@link Bundle} will be saved into
+     * {@code Call.Details}.
+     *
+     * @hide
+     */
+    public static final String EXTRA_OUTGOING_CALL_EXTRAS =
+            "android.intent.extra.OUTGOING_CALL_EXTRAS";
+
+    /**
      * Optional extra for {@link android.telephony.TelephonyManager#ACTION_PHONE_STATE_CHANGED}
      * containing the disconnect code.
      */
@@ -282,10 +293,10 @@
     public List<PhoneAccountHandle> getEnabledPhoneAccounts() {
         try {
             if (isServiceConnected()) {
-                return getTelecommService().getEnabledPhoneAccounts();
+                return getTelecommService().getOutgoingPhoneAccounts();
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "Error calling ITelecommService#getEnabledPhoneAccounts", e);
+            Log.e(TAG, "Error calling ITelecommService#getOutgoingPhoneAccounts", e);
         }
         return null;
     }
diff --git a/telecomm/java/android/telecomm/VideoCallImpl.java b/telecomm/java/android/telecomm/VideoCallImpl.java
index c32bcd2..c10865f 100644
--- a/telecomm/java/android/telecomm/VideoCallImpl.java
+++ b/telecomm/java/android/telecomm/VideoCallImpl.java
@@ -25,13 +25,15 @@
 import android.view.Surface;
 
 import com.android.internal.os.SomeArgs;
-import com.android.internal.telecomm.IVideoCallCallback;
-import com.android.internal.telecomm.IVideoCallProvider;
+import com.android.internal.telecomm.IVideoCallback;
+import com.android.internal.telecomm.IVideoProvider;
 
 /**
  * Implementation of a Video Call, which allows InCallUi to communicate commands to the underlying
- * {@link ConnectionService.VideoCallProvider}, and direct callbacks from the
- * {@link ConnectionService.VideoCallProvider} to the appropriate {@link VideoCall.Listener}.
+ * {@link Connection.VideoProvider}, and direct callbacks from the
+ * {@link Connection.VideoProvider} to the appropriate {@link VideoCall.Listener}.
+ *
+ * {@hide}
  */
 public class VideoCallImpl extends VideoCall {
     private static final int MSG_RECEIVE_SESSION_MODIFY_REQUEST = 1;
@@ -41,30 +43,30 @@
     private static final int MSG_CHANGE_CALL_DATA_USAGE = 5;
     private static final int MSG_CHANGE_CAMERA_CAPABILITIES = 6;
 
-    private final IVideoCallProvider mVideoCallProvider;
+    private final IVideoProvider mVideoProvider;
     private final VideoCallListenerBinder mBinder;
     private VideoCall.Listener mVideoCallListener;
 
     private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
         @Override
         public void binderDied() {
-            mVideoCallProvider.asBinder().unlinkToDeath(this, 0);
+            mVideoProvider.asBinder().unlinkToDeath(this, 0);
         }
     };
 
     /**
-     * IVideoCallCallback stub implementation.
+     * IVideoCallback stub implementation.
      */
-    private final class VideoCallListenerBinder extends IVideoCallCallback.Stub {
+    private final class VideoCallListenerBinder extends IVideoCallback.Stub {
         @Override
-        public void receiveSessionModifyRequest(VideoCallProfile videoCallProfile) {
+        public void receiveSessionModifyRequest(VideoProfile videoProfile) {
             mHandler.obtainMessage(MSG_RECEIVE_SESSION_MODIFY_REQUEST,
-                    videoCallProfile).sendToTarget();
+                    videoProfile).sendToTarget();
         }
 
         @Override
-        public void receiveSessionModifyResponse(int status, VideoCallProfile requestProfile,
-                VideoCallProfile responseProfile) {
+        public void receiveSessionModifyResponse(int status, VideoProfile requestProfile,
+                VideoProfile responseProfile) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = status;
             args.arg2 = requestProfile;
@@ -91,7 +93,7 @@
         }
 
         @Override
-        public void changeCameraCapabilities(CallCameraCapabilities cameraCapabilities) {
+        public void changeCameraCapabilities(CameraCapabilities cameraCapabilities) {
             mHandler.obtainMessage(MSG_CHANGE_CAMERA_CAPABILITIES,
                     cameraCapabilities).sendToTarget();
         }
@@ -108,14 +110,14 @@
             SomeArgs args;
             switch (msg.what) {
                 case MSG_RECEIVE_SESSION_MODIFY_REQUEST:
-                    mVideoCallListener.onSessionModifyRequestReceived((VideoCallProfile) msg.obj);
+                    mVideoCallListener.onSessionModifyRequestReceived((VideoProfile) msg.obj);
                     break;
                 case MSG_RECEIVE_SESSION_MODIFY_RESPONSE:
                     args = (SomeArgs) msg.obj;
                     try {
                         int status = (int) args.arg1;
-                        VideoCallProfile requestProfile = (VideoCallProfile) args.arg2;
-                        VideoCallProfile responseProfile = (VideoCallProfile) args.arg3;
+                        VideoProfile requestProfile = (VideoProfile) args.arg2;
+                        VideoProfile responseProfile = (VideoProfile) args.arg3;
 
                         mVideoCallListener.onSessionModifyResponseReceived(
                                 status, requestProfile, responseProfile);
@@ -141,7 +143,7 @@
                     break;
                 case MSG_CHANGE_CAMERA_CAPABILITIES:
                     mVideoCallListener.onCameraCapabilitiesChanged(
-                            (CallCameraCapabilities) msg.obj);
+                            (CameraCapabilities) msg.obj);
                     break;
                 default:
                     break;
@@ -150,12 +152,12 @@
     };
 
     /** {@hide} */
-    VideoCallImpl(IVideoCallProvider videoCallProvider) throws RemoteException {
-        mVideoCallProvider = videoCallProvider;
-        mVideoCallProvider.asBinder().linkToDeath(mDeathRecipient, 0);
+    VideoCallImpl(IVideoProvider videoProvider) throws RemoteException {
+        mVideoProvider = videoProvider;
+        mVideoProvider.asBinder().linkToDeath(mDeathRecipient, 0);
 
         mBinder = new VideoCallListenerBinder();
-        mVideoCallProvider.setVideoCallListener(mBinder);
+        mVideoProvider.setVideoListener(mBinder);
     }
 
     /** {@inheritDoc} */
@@ -166,7 +168,7 @@
     /** {@inheritDoc} */
     public void setCamera(String cameraId) {
         try {
-            mVideoCallProvider.setCamera(cameraId);
+            mVideoProvider.setCamera(cameraId);
         } catch (RemoteException e) {
         }
     }
@@ -174,7 +176,7 @@
     /** {@inheritDoc} */
     public void setPreviewSurface(Surface surface) {
         try {
-            mVideoCallProvider.setPreviewSurface(surface);
+            mVideoProvider.setPreviewSurface(surface);
         } catch (RemoteException e) {
         }
     }
@@ -182,7 +184,7 @@
     /** {@inheritDoc} */
     public void setDisplaySurface(Surface surface) {
         try {
-            mVideoCallProvider.setDisplaySurface(surface);
+            mVideoProvider.setDisplaySurface(surface);
         } catch (RemoteException e) {
         }
     }
@@ -190,7 +192,7 @@
     /** {@inheritDoc} */
     public void setDeviceOrientation(int rotation) {
         try {
-            mVideoCallProvider.setDeviceOrientation(rotation);
+            mVideoProvider.setDeviceOrientation(rotation);
         } catch (RemoteException e) {
         }
     }
@@ -198,23 +200,23 @@
     /** {@inheritDoc} */
     public void setZoom(float value) {
         try {
-            mVideoCallProvider.setZoom(value);
+            mVideoProvider.setZoom(value);
         } catch (RemoteException e) {
         }
     }
 
     /** {@inheritDoc} */
-    public void sendSessionModifyRequest(VideoCallProfile requestProfile) {
+    public void sendSessionModifyRequest(VideoProfile requestProfile) {
         try {
-            mVideoCallProvider.sendSessionModifyRequest(requestProfile);
+            mVideoProvider.sendSessionModifyRequest(requestProfile);
         } catch (RemoteException e) {
         }
     }
 
     /** {@inheritDoc} */
-    public void sendSessionModifyResponse(VideoCallProfile responseProfile) {
+    public void sendSessionModifyResponse(VideoProfile responseProfile) {
         try {
-            mVideoCallProvider.sendSessionModifyResponse(responseProfile);
+            mVideoProvider.sendSessionModifyResponse(responseProfile);
         } catch (RemoteException e) {
         }
     }
@@ -222,7 +224,7 @@
     /** {@inheritDoc} */
     public void requestCameraCapabilities() {
         try {
-            mVideoCallProvider.requestCameraCapabilities();
+            mVideoProvider.requestCameraCapabilities();
         } catch (RemoteException e) {
         }
     }
@@ -230,7 +232,7 @@
     /** {@inheritDoc} */
     public void requestCallDataUsage() {
         try {
-            mVideoCallProvider.requestCallDataUsage();
+            mVideoProvider.requestCallDataUsage();
         } catch (RemoteException e) {
         }
     }
@@ -238,7 +240,7 @@
     /** {@inheritDoc} */
     public void setPauseImage(String uri) {
         try {
-            mVideoCallProvider.setPauseImage(uri);
+            mVideoProvider.setPauseImage(uri);
         } catch (RemoteException e) {
         }
     }
diff --git a/telecomm/java/android/telecomm/VideoCallProfile.aidl b/telecomm/java/android/telecomm/VideoCallProfile.aidl
deleted file mode 100644
index adbf94d..0000000
--- a/telecomm/java/android/telecomm/VideoCallProfile.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-
-package android.telecomm;
-
-parcelable VideoCallProfile;
diff --git a/telecomm/java/android/telecomm/CallCameraCapabilities.aidl b/telecomm/java/android/telecomm/VideoProfile.aidl
similarity index 93%
rename from telecomm/java/android/telecomm/CallCameraCapabilities.aidl
rename to telecomm/java/android/telecomm/VideoProfile.aidl
index 25b6106..e756fa7 100644
--- a/telecomm/java/android/telecomm/CallCameraCapabilities.aidl
+++ b/telecomm/java/android/telecomm/VideoProfile.aidl
@@ -17,4 +17,7 @@
 
 package android.telecomm;
 
-parcelable CallCameraCapabilities;
+/**
+ * {@hide}
+ */
+parcelable VideoProfile;
diff --git a/telecomm/java/android/telecomm/VideoCallProfile.java b/telecomm/java/android/telecomm/VideoProfile.java
similarity index 81%
rename from telecomm/java/android/telecomm/VideoCallProfile.java
rename to telecomm/java/android/telecomm/VideoProfile.java
index 24c6996..b147978 100644
--- a/telecomm/java/android/telecomm/VideoCallProfile.java
+++ b/telecomm/java/android/telecomm/VideoProfile.java
@@ -22,7 +22,7 @@
 /**
  * Represents attributes of video calls.
  */
-public class VideoCallProfile implements Parcelable {
+public class VideoProfile implements Parcelable {
     /**
      * "High" video quality.
      */
@@ -48,32 +48,32 @@
     private final int mQuality;
 
     /**
-     * Creates an instance of the VideoCallProfile
+     * Creates an instance of the VideoProfile
      *
      * @param videoState The video state.
      */
-    public VideoCallProfile(int videoState) {
+    public VideoProfile(int videoState) {
         this(videoState, QUALITY_DEFAULT);
     }
 
     /**
-     * Creates an instance of the VideoCallProfile
+     * Creates an instance of the VideoProfile
      *
      * @param videoState The video state.
      * @param quality The video quality.
      */
-    public VideoCallProfile(int videoState, int quality) {
+    public VideoProfile(int videoState, int quality) {
         mVideoState = videoState;
         mQuality = quality;
     }
 
     /**
      * The video state of the call.
-     * Valid values: {@link VideoCallProfile.VideoState#AUDIO_ONLY},
-     * {@link VideoCallProfile.VideoState#BIDIRECTIONAL},
-     * {@link VideoCallProfile.VideoState#TX_ENABLED},
-     * {@link VideoCallProfile.VideoState#RX_ENABLED},
-     * {@link VideoCallProfile.VideoState#PAUSED}.
+     * Valid values: {@link VideoProfile.VideoState#AUDIO_ONLY},
+     * {@link VideoProfile.VideoState#BIDIRECTIONAL},
+     * {@link VideoProfile.VideoState#TX_ENABLED},
+     * {@link VideoProfile.VideoState#RX_ENABLED},
+     * {@link VideoProfile.VideoState#PAUSED}.
      */
     public int getVideoState() {
         return mVideoState;
@@ -81,18 +81,18 @@
 
     /**
      * The desired video quality for the call.
-     * Valid values: {@link VideoCallProfile#QUALITY_HIGH}, {@link VideoCallProfile#QUALITY_MEDIUM},
-     * {@link VideoCallProfile#QUALITY_LOW}, {@link VideoCallProfile#QUALITY_DEFAULT}.
+     * Valid values: {@link VideoProfile#QUALITY_HIGH}, {@link VideoProfile#QUALITY_MEDIUM},
+     * {@link VideoProfile#QUALITY_LOW}, {@link VideoProfile#QUALITY_DEFAULT}.
      */
     public int getQuality() {
         return mQuality;
     }
 
     /**
-     * Responsible for creating VideoCallProfile objects from deserialized Parcels.
+     * Responsible for creating VideoProfile objects from deserialized Parcels.
      **/
-    public static final Parcelable.Creator<VideoCallProfile> CREATOR =
-            new Parcelable.Creator<VideoCallProfile> () {
+    public static final Parcelable.Creator<VideoProfile> CREATOR =
+            new Parcelable.Creator<VideoProfile> () {
                 /**
                  * Creates a MediaProfile instances from a parcel.
                  *
@@ -100,17 +100,17 @@
                  * @return The MediaProfile.
                  */
                 @Override
-                public VideoCallProfile createFromParcel(Parcel source) {
+                public VideoProfile createFromParcel(Parcel source) {
                     int state = source.readInt();
                     int quality = source.readInt();
 
-                    ClassLoader classLoader = VideoCallProfile.class.getClassLoader();
-                    return new VideoCallProfile(state, quality);
+                    ClassLoader classLoader = VideoProfile.class.getClassLoader();
+                    return new VideoProfile(state, quality);
                 }
 
                 @Override
-                public VideoCallProfile[] newArray(int size) {
-                    return new VideoCallProfile[size];
+                public VideoProfile[] newArray(int size) {
+                    return new VideoProfile[size];
                 }
             };
 
diff --git a/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl b/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl
index 7abb4dd..c412424 100644
--- a/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl
@@ -17,7 +17,7 @@
 package com.android.internal.telecomm;
 
 import android.os.Bundle;
-import android.telecomm.CallAudioState;
+import android.telecomm.AudioState;
 import android.telecomm.ConnectionRequest;
 import android.telecomm.PhoneAccountHandle;
 
@@ -37,6 +37,7 @@
 
     void createConnection(
             in PhoneAccountHandle connectionManagerPhoneAccount,
+            String callId,
             in ConnectionRequest request,
             boolean isIncoming);
 
@@ -52,7 +53,7 @@
 
     void unhold(String callId);
 
-    void onAudioStateChanged(String activeCallId, in CallAudioState audioState);
+    void onAudioStateChanged(String activeCallId, in AudioState audioState);
 
     void playDtmfTone(String callId, char digit);
 
@@ -62,8 +63,6 @@
 
     void splitFromConference(String callId);
 
-    void swapWithBackgroundCall(String callId);
-
     void onPostDialContinue(String callId, boolean proceed);
 
     void onPhoneAccountClicked(String callId);
diff --git a/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl
index c6f9712..fd4e931 100644
--- a/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl
@@ -22,7 +22,7 @@
 import android.telecomm.ParcelableConnection;
 import android.telecomm.StatusHints;
 
-import com.android.internal.telecomm.IVideoCallProvider;
+import com.android.internal.telecomm.IVideoProvider;
 import com.android.internal.telecomm.RemoteServiceCallback;
 
 /**
@@ -34,12 +34,18 @@
  */
 oneway interface IConnectionServiceAdapter {
     void handleCreateConnectionSuccessful(
-            in ConnectionRequest request, in ParcelableConnection connection);
+            String callId,
+            in ConnectionRequest request,
+            in ParcelableConnection connection);
 
     void handleCreateConnectionFailed(
-            in ConnectionRequest request, int errorCode, String errorMessage);
+            String callId,
+            in ConnectionRequest request,
+            int errorCode, String errorMessage);
 
-    void handleCreateConnectionCancelled(in ConnectionRequest request);
+    void handleCreateConnectionCancelled(
+            String callId,
+            in ConnectionRequest request);
 
     void setActive(String callId);
 
@@ -65,7 +71,7 @@
 
     void queryRemoteConnectionServices(RemoteServiceCallback callback);
 
-    void setVideoCallProvider(String callId, IVideoCallProvider videoCallProvider);
+    void setVideoProvider(String callId, IVideoProvider videoProvider);
 
     void setVideoState(String callId, int videoState);
 
diff --git a/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
index 8bc950f..2ce5c6b 100644
--- a/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
@@ -16,7 +16,6 @@
 
 package com.android.internal.telecomm;
 
-import android.telecomm.CallAudioState;
 import android.telecomm.PhoneAccountHandle;
 
 /**
@@ -55,8 +54,6 @@
 
     void splitFromConference(String callId);
 
-    void swapWithBackgroundCall(String callId);
-
     void turnOnProximitySensor();
 
     void turnOffProximitySensor(boolean screenOnImmediately);
diff --git a/telecomm/java/com/android/internal/telecomm/IInCallService.aidl b/telecomm/java/com/android/internal/telecomm/IInCallService.aidl
index 8ec6196..5d4992f 100644
--- a/telecomm/java/com/android/internal/telecomm/IInCallService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IInCallService.aidl
@@ -17,7 +17,7 @@
 package com.android.internal.telecomm;
 
 import android.app.PendingIntent;
-import android.telecomm.CallAudioState;
+import android.telecomm.AudioState;
 import android.telecomm.ParcelableCall;
 
 import com.android.internal.telecomm.IInCallAdapter;
@@ -40,7 +40,7 @@
 
     void setPostDialWait(String callId, String remaining);
 
-    void onAudioStateChanged(in CallAudioState audioState);
+    void onAudioStateChanged(in AudioState audioState);
 
     void bringToForeground(boolean showDialpad);
 
diff --git a/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl b/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
index 5036948..3c1dea6 100644
--- a/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
@@ -40,9 +40,9 @@
     PhoneAccountHandle getDefaultOutgoingPhoneAccount();
 
     /**
-     * @see TelecommManager#getEnabledPhoneAccounts
+     * @see TelecommManager#getOutgoingPhoneAccounts
      */
-    List<PhoneAccountHandle> getEnabledPhoneAccounts();
+    List<PhoneAccountHandle> getOutgoingPhoneAccounts();
 
     /**
      * @see TelecommManager#getPhoneAccount
diff --git a/telecomm/java/com/android/internal/telecomm/IVideoCallCallback.aidl b/telecomm/java/com/android/internal/telecomm/IVideoCallCallback.aidl
deleted file mode 100644
index 1a8f68e..0000000
--- a/telecomm/java/com/android/internal/telecomm/IVideoCallCallback.aidl
+++ /dev/null
@@ -1,43 +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.internal.telecomm;
-
-import android.telecomm.CallCameraCapabilities;
-import android.telecomm.VideoCallProfile;
-
-/**
- * Internal definition of a callback interface, used for an InCallUi to respond to video telephony
- * changes.
- *
- * @see android.telecomm.InCallService.VideoCall.Listener
- *
- * {@hide}
- */
-oneway interface IVideoCallCallback {
-    void receiveSessionModifyRequest(in VideoCallProfile videoCallProfile);
-
-    void receiveSessionModifyResponse(int status, in VideoCallProfile requestedProfile,
-        in VideoCallProfile responseProfile);
-
-    void handleCallSessionEvent(int event);
-
-    void changePeerDimensions(int width, int height);
-
-    void changeCallDataUsage(int dataUsage);
-
-    void changeCameraCapabilities(in CallCameraCapabilities callCameraCapabilities);
-}
diff --git a/telecomm/java/com/android/internal/telecomm/IVideoCallback.aidl b/telecomm/java/com/android/internal/telecomm/IVideoCallback.aidl
new file mode 100644
index 0000000..186f083
--- /dev/null
+++ b/telecomm/java/com/android/internal/telecomm/IVideoCallback.aidl
@@ -0,0 +1,45 @@
+/*
+ * 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.internal.telecomm;
+
+import android.telecomm.CameraCapabilities;
+import android.telecomm.VideoProfile;
+
+ /**
+  * Internal definition of a callback interface, used for an InCallUi to respond to video
+  * telephony changes.
+  *
+  * @see android.telecomm.InCallService.VideoCall.Listener
+  *
+  * {@hide}
+  */
+oneway interface IVideoCallback {
+    void receiveSessionModifyRequest(in VideoProfile videoProfile);
+
+    void receiveSessionModifyResponse(
+            int status,
+            in VideoProfile requestedProfile,
+            in VideoProfile responseProfile);
+
+    void handleCallSessionEvent(int event);
+
+    void changePeerDimensions(int width, int height);
+
+    void changeCallDataUsage(int dataUsage);
+
+    void changeCameraCapabilities(in CameraCapabilities cameraCapabilities);
+}
diff --git a/telecomm/java/com/android/internal/telecomm/IVideoCallProvider.aidl b/telecomm/java/com/android/internal/telecomm/IVideoProvider.aidl
similarity index 76%
rename from telecomm/java/com/android/internal/telecomm/IVideoCallProvider.aidl
rename to telecomm/java/com/android/internal/telecomm/IVideoProvider.aidl
index c1ba749..9d3ad7f 100644
--- a/telecomm/java/com/android/internal/telecomm/IVideoCallProvider.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IVideoProvider.aidl
@@ -17,15 +17,15 @@
 package com.android.internal.telecomm;
 
 import android.view.Surface;
-import android.telecomm.VideoCallProfile;
+import android.telecomm.VideoProfile;
 
 /**
  * Internal remote interface for a video call provider.
- * @see android.telecomm.VideoCallProvider
+ * @see android.telecomm.VideoProvider
  * @hide
  */
-oneway interface IVideoCallProvider {
-    void setVideoCallListener(IBinder videoCallListenerBinder);
+oneway interface IVideoProvider {
+    void setVideoListener(IBinder videoListenerBinder);
 
     void setCamera(String cameraId);
 
@@ -37,9 +37,9 @@
 
     void setZoom(float value);
 
-    void sendSessionModifyRequest(in VideoCallProfile reqProfile);
+    void sendSessionModifyRequest(in VideoProfile reqProfile);
 
-    void sendSessionModifyResponse(in VideoCallProfile responseProfile);
+    void sendSessionModifyResponse(in VideoProfile responseProfile);
 
     void requestCameraCapabilities();
 
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index 13b39c9..72578a4 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -130,7 +130,7 @@
                 return mMcc == o.mMcc &&
                         mMnc == o.mMnc &&
                         mCi == o.mCi &&
-                        mPci == o.mCi &&
+                        mPci == o.mPci &&
                         mTac == o.mTac;
             } catch (ClassCastException e) {
                 return false;
diff --git a/telephony/java/com/android/ims/ImsCallProfile.java b/telephony/java/com/android/ims/ImsCallProfile.java
index adcb435..dcd0b79 100644
--- a/telephony/java/com/android/ims/ImsCallProfile.java
+++ b/telephony/java/com/android/ims/ImsCallProfile.java
@@ -19,7 +19,7 @@
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.telecomm.VideoCallProfile;
+import android.telecomm.VideoProfile;
 
 /**
  * Parcelable object to handle IMS call profile.
@@ -290,7 +290,7 @@
 
     /**
      * Converts from the call types defined in {@link com.android.ims.ImsCallProfile} to the
-     * video state values defined in {@link android.telecomm.VideoCallProfile}.
+     * video state values defined in {@link VideoProfile}.
      *
      * @param callType The call type.
      * @return The video state.
@@ -298,32 +298,32 @@
     public static int getVideoStateFromCallType(int callType) {
         switch (callType) {
             case CALL_TYPE_VT_NODIR:
-                return VideoCallProfile.VideoState.PAUSED |
-                        VideoCallProfile.VideoState.BIDIRECTIONAL;
+                return VideoProfile.VideoState.PAUSED |
+                        VideoProfile.VideoState.BIDIRECTIONAL;
             case CALL_TYPE_VT_TX:
-                return VideoCallProfile.VideoState.TX_ENABLED;
+                return VideoProfile.VideoState.TX_ENABLED;
             case CALL_TYPE_VT_RX:
-                return VideoCallProfile.VideoState.RX_ENABLED;
+                return VideoProfile.VideoState.RX_ENABLED;
             case CALL_TYPE_VT:
-                return VideoCallProfile.VideoState.BIDIRECTIONAL;
+                return VideoProfile.VideoState.BIDIRECTIONAL;
             case CALL_TYPE_VOICE:
-                return VideoCallProfile.VideoState.AUDIO_ONLY;
+                return VideoProfile.VideoState.AUDIO_ONLY;
             default:
-                return VideoCallProfile.VideoState.AUDIO_ONLY;
+                return VideoProfile.VideoState.AUDIO_ONLY;
         }
     }
 
     /**
-     * Converts from the video state values defined in {@link android.telecomm.VideoCallProfile}
+     * Converts from the video state values defined in {@link VideoProfile}
      * to the call types defined in {@link ImsCallProfile}.
      *
      * @param videoState The video state.
      * @return The call type.
      */
     public static int getCallTypeFromVideoState(int videoState) {
-        boolean videoTx = isVideoStateSet(videoState, VideoCallProfile.VideoState.TX_ENABLED);
-        boolean videoRx = isVideoStateSet(videoState, VideoCallProfile.VideoState.RX_ENABLED);
-        boolean isPaused = isVideoStateSet(videoState, VideoCallProfile.VideoState.PAUSED);
+        boolean videoTx = isVideoStateSet(videoState, VideoProfile.VideoState.TX_ENABLED);
+        boolean videoRx = isVideoStateSet(videoState, VideoProfile.VideoState.RX_ENABLED);
+        boolean isPaused = isVideoStateSet(videoState, VideoProfile.VideoState.PAUSED);
         if (isPaused) {
             return ImsCallProfile.CALL_TYPE_VT_NODIR;
         } else if (videoTx && !videoRx) {
diff --git a/telephony/java/com/android/ims/internal/IImsVideoCallCallback.aidl b/telephony/java/com/android/ims/internal/IImsVideoCallCallback.aidl
index 6b8ec52..67bfe41 100644
--- a/telephony/java/com/android/ims/internal/IImsVideoCallCallback.aidl
+++ b/telephony/java/com/android/ims/internal/IImsVideoCallCallback.aidl
@@ -16,8 +16,8 @@
 
 package com.android.ims.internal;
 
-import android.telecomm.CallCameraCapabilities;
-import android.telecomm.VideoCallProfile;
+import android.telecomm.CameraCapabilities;
+import android.telecomm.VideoProfile;
 
 /**
  * Internal remote interface for IMS's video call provider.
@@ -32,10 +32,10 @@
  * {@hide}
  */
 oneway interface IImsVideoCallCallback {
-    void receiveSessionModifyRequest(in VideoCallProfile videoCallProfile);
+    void receiveSessionModifyRequest(in VideoProfile videoProfile);
 
-    void receiveSessionModifyResponse(int status, in VideoCallProfile requestedProfile,
-        in VideoCallProfile responseProfile);
+    void receiveSessionModifyResponse(int status, in VideoProfile requestedProfile,
+        in VideoProfile responseProfile);
 
     void handleCallSessionEvent(int event);
 
@@ -43,5 +43,5 @@
 
     void changeCallDataUsage(int dataUsage);
 
-    void changeCameraCapabilities(in CallCameraCapabilities callCameraCapabilities);
+    void changeCameraCapabilities(in CameraCapabilities cameraCapabilities);
 }
diff --git a/telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl b/telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl
index f8389ec..4db0d14 100644
--- a/telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl
+++ b/telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl
@@ -17,7 +17,7 @@
 package com.android.ims.internal;
 
 import android.view.Surface;
-import android.telecomm.VideoCallProfile;
+import android.telecomm.VideoProfile;
 
 import com.android.ims.internal.IImsVideoCallCallback;
 
@@ -52,9 +52,9 @@
 
     void setZoom(float value);
 
-    void sendSessionModifyRequest(in VideoCallProfile reqProfile);
+    void sendSessionModifyRequest(in VideoProfile reqProfile);
 
-    void sendSessionModifyResponse(in VideoCallProfile responseProfile);
+    void sendSessionModifyResponse(in VideoProfile responseProfile);
 
     void requestCameraCapabilities();
 
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 15298599..a8a9057 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -287,6 +287,7 @@
     int RIL_REQUEST_ALLOW_DATA = 123;
     int RIL_REQUEST_GET_HARDWARE_CONFIG = 124;
     int RIL_REQUEST_SIM_AUTHENTICATION = 125;
+    int RIL_REQUEST_SET_DATA_PROFILE = 128;
 
     int RIL_UNSOL_RESPONSE_BASE = 1000;
     int RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED = 1000;
diff --git a/tests/FeatureSplit/feature1/Android.mk b/tests/FeatureSplit/feature1/Android.mk
index 30598241..adfb575 100644
--- a/tests/FeatureSplit/feature1/Android.mk
+++ b/tests/FeatureSplit/feature1/Android.mk
@@ -26,7 +26,6 @@
 localRStamp := $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),,COMMON)/src/R.stamp
 $(localRStamp): $(featureOfApk)
 
-$(info $(localRStamp))
 LOCAL_AAPT_FLAGS := --feature-of $(featureOfApk)
 
 include $(BUILD_PACKAGE)
diff --git a/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/AppListFragment.java b/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/AppListFragment.java
index c0f3a7f..526ea5d 100644
--- a/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/AppListFragment.java
+++ b/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/AppListFragment.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 The Android Open Source Project
+ * 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.
diff --git a/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/BrowserListFragment.java b/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/BrowserListFragment.java
index 3fc468d..2fc77dc 100644
--- a/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/BrowserListFragment.java
+++ b/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/BrowserListFragment.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 The Android Open Source Project
+ * 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.
diff --git a/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/MainActivity.java b/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/MainActivity.java
index ed91aad..4c28234 100644
--- a/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/MainActivity.java
+++ b/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/MainActivity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 The Android Open Source Project
+ * 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.
diff --git a/tools/aapt/ApkBuilder.cpp b/tools/aapt/ApkBuilder.cpp
index 12f6040..01e02e2 100644
--- a/tools/aapt/ApkBuilder.cpp
+++ b/tools/aapt/ApkBuilder.cpp
@@ -85,11 +85,24 @@
         if (mName.size() > 0) {
             mName.append(",");
             mDirName.append("_");
+            mPackageSafeName.append(".");
         }
 
         String8 configStr = iter->toString();
+        String8 packageConfigStr(configStr);
+        size_t len = packageConfigStr.length();
+        if (len > 0) {
+            char* buf = packageConfigStr.lockBuffer(len);
+            for (char* end = buf + len; buf < end; ++buf) {
+                if (*buf == '-') {
+                    *buf = '_';
+                }
+            }
+            packageConfigStr.unlockBuffer(len);
+        }
         mName.append(configStr);
         mDirName.append(configStr);
+        mPackageSafeName.append(packageConfigStr);
     }
 }
 
diff --git a/tools/aapt/ApkBuilder.h b/tools/aapt/ApkBuilder.h
index db23c84..0d7f06b 100644
--- a/tools/aapt/ApkBuilder.h
+++ b/tools/aapt/ApkBuilder.h
@@ -95,6 +95,10 @@
         return mDirName;
     }
 
+    const android::String8& getPackageSafeName() const {
+        return mPackageSafeName;
+    }
+
     bool isBase() const {
         return mIsBase;
     }
@@ -111,6 +115,7 @@
     const bool mIsBase;
     String8 mName;
     String8 mDirName;
+    String8 mPackageSafeName;
     std::set<OutputEntry> mFiles;
 };
 
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 2401b3a..010d59b 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -937,8 +937,8 @@
     }
 
     // Add the 'split' attribute which describes the configurations included.
-    String8 splitName("config_");
-    splitName.append(split->getDirectorySafeName());
+    String8 splitName("config.");
+    splitName.append(split->getPackageSafeName());
     manifest->addAttribute(String16(), String16("split"), String16(splitName));
 
     // Build an empty <application> tag (required).
diff --git a/tools/layoutlib/.idea/copyright/profiles_settings.xml b/tools/layoutlib/.idea/copyright/profiles_settings.xml
index e7bedf3..20145de 100644
--- a/tools/layoutlib/.idea/copyright/profiles_settings.xml
+++ b/tools/layoutlib/.idea/copyright/profiles_settings.xml
@@ -1,3 +1,3 @@
 <component name="CopyrightManager">
-  <settings default="" />
+  <settings default="Android" />
 </component>
\ No newline at end of file
diff --git a/tools/layoutlib/bridge/resources/bars/README b/tools/layoutlib/bridge/resources/bars/README
new file mode 100644
index 0000000..c84ef80
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/README
@@ -0,0 +1,8 @@
+The directory contains the resources for StatusBar and Navigation Bar.
+
+The resources are not arranged as per the standard resources configuration.
+They are stored per API. However, to prevent duplication of resources, each API
+resource directory is used as a backup for all earlier API levels.
+
+For example, for the back icon for ICS, we search first in v18, where we don't
+find it, and then in v19.
diff --git a/tools/layoutlib/bridge/resources/bars/status_bar.xml b/tools/layoutlib/bridge/resources/bars/status_bar.xml
index 51b474d..75bfb6e 100644
--- a/tools/layoutlib/bridge/resources/bars/status_bar.xml
+++ b/tools/layoutlib/bridge/resources/bars/status_bar.xml
@@ -13,5 +13,5 @@
 			android:layout_width="wrap_content"
 			android:layout_marginLeft="3dp"
 			android:layout_marginRight="5dp"
-			android:layout_marginTop="1dp"/>
+			android:layout_marginTop="2dp"/>
 </merge>
diff --git a/tools/layoutlib/bridge/resources/bars/v11/README b/tools/layoutlib/bridge/resources/bars/v11/README
deleted file mode 100644
index ae094e2..0000000
--- a/tools/layoutlib/bridge/resources/bars/v11/README
+++ /dev/null
@@ -1 +0,0 @@
-Resources for Api level 11-20
diff --git a/tools/layoutlib/bridge/resources/bars/v18/hdpi/stat_sys_battery_100.png b/tools/layoutlib/bridge/resources/bars/v18/hdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..c920ec4
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/v18/hdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v18/hdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/v18/hdpi/stat_sys_wifi_signal_4_fully.png
new file mode 100644
index 0000000..931daed
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/v18/hdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v18/mdpi/stat_sys_battery_100.png b/tools/layoutlib/bridge/resources/bars/v18/mdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..943332e
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/v18/mdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v18/mdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/v18/mdpi/stat_sys_wifi_signal_4_fully.png
new file mode 100644
index 0000000..6e1ac91
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/v18/mdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v18/xhdpi/stat_sys_battery_100.png b/tools/layoutlib/bridge/resources/bars/v18/xhdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..36c61e1
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/v18/xhdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v18/xhdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/v18/xhdpi/stat_sys_wifi_signal_4_fully.png
new file mode 100644
index 0000000..625c61d
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/v18/xhdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v11/hdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/v19/hdpi/ic_sysbar_back.png
similarity index 100%
rename from tools/layoutlib/bridge/resources/bars/v11/hdpi/ic_sysbar_back.png
rename to tools/layoutlib/bridge/resources/bars/v19/hdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v11/hdpi/ic_sysbar_home.png b/tools/layoutlib/bridge/resources/bars/v19/hdpi/ic_sysbar_home.png
similarity index 100%
rename from tools/layoutlib/bridge/resources/bars/v11/hdpi/ic_sysbar_home.png
rename to tools/layoutlib/bridge/resources/bars/v19/hdpi/ic_sysbar_home.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v11/hdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/v19/hdpi/ic_sysbar_recent.png
similarity index 100%
rename from tools/layoutlib/bridge/resources/bars/v11/hdpi/ic_sysbar_recent.png
rename to tools/layoutlib/bridge/resources/bars/v19/hdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v19/hdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/v19/hdpi/stat_sys_wifi_signal_4_fully.png
new file mode 100644
index 0000000..6248cfd
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/v19/hdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v11/ldrtl-hdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/v19/ldrtl-hdpi/ic_sysbar_back.png
similarity index 100%
rename from tools/layoutlib/bridge/resources/bars/v11/ldrtl-hdpi/ic_sysbar_back.png
rename to tools/layoutlib/bridge/resources/bars/v19/ldrtl-hdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v11/ldrtl-hdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/v19/ldrtl-hdpi/ic_sysbar_recent.png
similarity index 100%
rename from tools/layoutlib/bridge/resources/bars/v11/ldrtl-hdpi/ic_sysbar_recent.png
rename to tools/layoutlib/bridge/resources/bars/v19/ldrtl-hdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v11/ldrtl-mdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/v19/ldrtl-mdpi/ic_sysbar_back.png
similarity index 100%
rename from tools/layoutlib/bridge/resources/bars/v11/ldrtl-mdpi/ic_sysbar_back.png
rename to tools/layoutlib/bridge/resources/bars/v19/ldrtl-mdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v11/ldrtl-mdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/v19/ldrtl-mdpi/ic_sysbar_recent.png
similarity index 100%
rename from tools/layoutlib/bridge/resources/bars/v11/ldrtl-mdpi/ic_sysbar_recent.png
rename to tools/layoutlib/bridge/resources/bars/v19/ldrtl-mdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v11/ldrtl-xhdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/v19/ldrtl-xhdpi/ic_sysbar_back.png
similarity index 100%
rename from tools/layoutlib/bridge/resources/bars/v11/ldrtl-xhdpi/ic_sysbar_back.png
rename to tools/layoutlib/bridge/resources/bars/v19/ldrtl-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v11/ldrtl-xhdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/v19/ldrtl-xhdpi/ic_sysbar_recent.png
similarity index 100%
rename from tools/layoutlib/bridge/resources/bars/v11/ldrtl-xhdpi/ic_sysbar_recent.png
rename to tools/layoutlib/bridge/resources/bars/v19/ldrtl-xhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v11/mdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/v19/mdpi/ic_sysbar_back.png
similarity index 100%
rename from tools/layoutlib/bridge/resources/bars/v11/mdpi/ic_sysbar_back.png
rename to tools/layoutlib/bridge/resources/bars/v19/mdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v11/mdpi/ic_sysbar_home.png b/tools/layoutlib/bridge/resources/bars/v19/mdpi/ic_sysbar_home.png
similarity index 100%
rename from tools/layoutlib/bridge/resources/bars/v11/mdpi/ic_sysbar_home.png
rename to tools/layoutlib/bridge/resources/bars/v19/mdpi/ic_sysbar_home.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v11/mdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/v19/mdpi/ic_sysbar_recent.png
similarity index 100%
rename from tools/layoutlib/bridge/resources/bars/v11/mdpi/ic_sysbar_recent.png
rename to tools/layoutlib/bridge/resources/bars/v19/mdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v19/mdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/v19/mdpi/stat_sys_wifi_signal_4_fully.png
new file mode 100644
index 0000000..441de0c
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/v19/mdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v11/xhdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/v19/xhdpi/ic_sysbar_back.png
similarity index 100%
rename from tools/layoutlib/bridge/resources/bars/v11/xhdpi/ic_sysbar_back.png
rename to tools/layoutlib/bridge/resources/bars/v19/xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v11/xhdpi/ic_sysbar_home.png b/tools/layoutlib/bridge/resources/bars/v19/xhdpi/ic_sysbar_home.png
similarity index 100%
rename from tools/layoutlib/bridge/resources/bars/v11/xhdpi/ic_sysbar_home.png
rename to tools/layoutlib/bridge/resources/bars/v19/xhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v11/xhdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/v19/xhdpi/ic_sysbar_recent.png
similarity index 100%
rename from tools/layoutlib/bridge/resources/bars/v11/xhdpi/ic_sysbar_recent.png
rename to tools/layoutlib/bridge/resources/bars/v19/xhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v19/xhdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/v19/xhdpi/stat_sys_wifi_signal_4_fully.png
new file mode 100644
index 0000000..459a1a2
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/v19/xhdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v19/xxhdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/v19/xxhdpi/ic_sysbar_back.png
new file mode 100644
index 0000000..79cfcee
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/v19/xxhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v19/xxhdpi/ic_sysbar_home.png b/tools/layoutlib/bridge/resources/bars/v19/xxhdpi/ic_sysbar_home.png
new file mode 100644
index 0000000..64f6a22
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/v19/xxhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v19/xxhdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/v19/xxhdpi/ic_sysbar_recent.png
new file mode 100644
index 0000000..6e0b071
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/v19/xxhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v19/xxhdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/v19/xxhdpi/stat_sys_wifi_signal_4_fully.png
new file mode 100644
index 0000000..494b005
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/v19/xxhdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v21/hdpi/stat_sys_battery_100.png b/tools/layoutlib/bridge/resources/bars/v21/hdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..f17189a
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/v21/hdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v21/hdpi/stat_sys_battery_charge_anim100.png b/tools/layoutlib/bridge/resources/bars/v21/hdpi/stat_sys_battery_charge_anim100.png
deleted file mode 100644
index 829378e..0000000
--- a/tools/layoutlib/bridge/resources/bars/v21/hdpi/stat_sys_battery_charge_anim100.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v21/hdpi/status_bar_background.9.png b/tools/layoutlib/bridge/resources/bars/v21/hdpi/status_bar_background.9.png
deleted file mode 100644
index a4be298..0000000
--- a/tools/layoutlib/bridge/resources/bars/v21/hdpi/status_bar_background.9.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v21/mdpi/stat_sys_battery_100.png b/tools/layoutlib/bridge/resources/bars/v21/mdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..2a9757d
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/v21/mdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v21/mdpi/stat_sys_battery_charge_anim100.png b/tools/layoutlib/bridge/resources/bars/v21/mdpi/stat_sys_battery_charge_anim100.png
deleted file mode 100644
index 2773a70..0000000
--- a/tools/layoutlib/bridge/resources/bars/v21/mdpi/stat_sys_battery_charge_anim100.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v21/mdpi/status_bar_background.9.png b/tools/layoutlib/bridge/resources/bars/v21/mdpi/status_bar_background.9.png
deleted file mode 100644
index eb7c1a4..0000000
--- a/tools/layoutlib/bridge/resources/bars/v21/mdpi/status_bar_background.9.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v21/xhdpi/stat_sys_battery_100.png b/tools/layoutlib/bridge/resources/bars/v21/xhdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..555bcd9
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/v21/xhdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v21/xhdpi/stat_sys_battery_charge_anim100.png b/tools/layoutlib/bridge/resources/bars/v21/xhdpi/stat_sys_battery_charge_anim100.png
deleted file mode 100644
index c7fd719..0000000
--- a/tools/layoutlib/bridge/resources/bars/v21/xhdpi/stat_sys_battery_charge_anim100.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v21/xxhdpi/stat_sys_battery_100.png b/tools/layoutlib/bridge/resources/bars/v21/xxhdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..6474aad
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/v21/xxhdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v9/hdpi/stat_sys_battery_100.png b/tools/layoutlib/bridge/resources/bars/v9/hdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..754cdf6
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/v9/hdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v9/hdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/v9/hdpi/stat_sys_wifi_signal_4_fully.png
new file mode 100644
index 0000000..b5326d2
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/v9/hdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v9/ldpi/stat_sys_battery_100.png b/tools/layoutlib/bridge/resources/bars/v9/ldpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..7023ea7
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/v9/ldpi/stat_sys_battery_100.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v9/mdpi/stat_sys_battery_100.png b/tools/layoutlib/bridge/resources/bars/v9/mdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..17a955d
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/v9/mdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/v9/mdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/v9/mdpi/stat_sys_wifi_signal_4_fully.png
new file mode 100644
index 0000000..19165ab
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/v9/mdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
index bf4e288..bd80cb8 100644
--- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
@@ -26,11 +26,12 @@
 import java.awt.Font;
 import java.awt.FontFormatException;
 import java.io.File;
+import java.io.FileNotFoundException;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Scanner;
 import java.util.Set;
 
 import static android.graphics.Typeface_Delegate.SYSTEM_FONTS;
@@ -54,14 +55,7 @@
     private static final String FONT_SUFFIX_BOLDITALIC = "BoldItalic.ttf";
     private static final String FONT_SUFFIX_BOLD = "Bold.ttf";
     private static final String FONT_SUFFIX_ITALIC = "Italic.ttf";
-
-    private static final Set<String> MISSING_FONTS =
-            Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
-                    "NotoSansHans-Regular.otf",
-                    "NotoSansHant-Regular.otf",
-                    "NotoSansJP-Regular.otf",
-                    "NotoSansKR-Regular.otf"
-            )));
+    private static final String FN_ALL_FONTS_LIST = "fontsInSdk.txt";
 
     /**
      * A class associating {@link Font} with its metadata.
@@ -80,6 +74,7 @@
     private static String sFontLocation;
     private static final List<FontFamily_Delegate> sPostInitDelegate = new
             ArrayList<FontFamily_Delegate>();
+    private static Set<String> SDK_FONTS;
 
 
     // ---- delegate data ----
@@ -113,6 +108,31 @@
 
     public static synchronized void setFontLocation(String fontLocation) {
         sFontLocation = fontLocation;
+        // init list of bundled fonts.
+        File allFonts = new File(fontLocation, FN_ALL_FONTS_LIST);
+        // Current number of fonts is 103. Use the next round number to leave scope for more fonts
+        // in the future.
+        Set<String> allFontsList = new HashSet<String>(128);
+        Scanner scanner = null;
+        try {
+            scanner = new Scanner(allFonts);
+            while (scanner.hasNext()) {
+                String name = scanner.next();
+                // Skip font configuration files.
+                if (!name.endsWith(".xml")) {
+                    allFontsList.add(name);
+                }
+            }
+        } catch (FileNotFoundException e) {
+            Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+                    "Unable to load the list of fonts. Try re-installing the SDK Platform from the SDK Manager.",
+                    e, null);
+        } finally {
+            if (scanner != null) {
+                scanner.close();
+            }
+        }
+        SDK_FONTS = Collections.unmodifiableSet(allFontsList);
         for (FontFamily_Delegate fontFamily : sPostInitDelegate) {
             fontFamily.init();
         }
@@ -225,13 +245,6 @@
     /*package*/ static boolean nAddFont(long nativeFamily, String path) {
         FontFamily_Delegate delegate = getDelegate(nativeFamily);
         if (delegate != null) {
-            // If the font to be added is known to be missing from the SDK, don't try to load it and
-            // mark the FontFamily to be not valid.
-            if (path.startsWith(SYSTEM_FONTS) &&
-                    MISSING_FONTS.contains(path.substring(SYSTEM_FONTS.length()))) {
-                return delegate.mValid = false;
-            }
-            delegate.mValid = true;
             if (sFontLocation == null) {
                 delegate.mPath.add(path);
                 return true;
@@ -259,6 +272,14 @@
     }
 
     private boolean addFont(String path) {
+        // If the font is not in the list of fonts bundled with the SDK, don't try to load it and
+        // mark the FontFamily to be not valid.
+        if (path.startsWith(SYSTEM_FONTS) &&
+                !SDK_FONTS.contains(path.substring(SYSTEM_FONTS.length()))) {
+            return mValid = false;
+        }
+        // Set valid to true, even if the font fails to load.
+        mValid = true;
         Font font = loadFont(path);
         if (font == null) {
             return false;
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 09b57fe..f8bc2ae 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -444,7 +444,8 @@
     }
 
     @Override
-    public void keyguardGoingAway() throws RemoteException {
+    public void keyguardGoingAway(boolean disableWindowAnimations,
+            boolean keyguardGoingToNotificationShade) throws RemoteException {
     }
 
     @Override
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 089cad3..9b814f5 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
@@ -16,31 +16,58 @@
 
 package com.android.layoutlib.bridge.bars;
 
+import java.util.ArrayList;
+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;
+
 /**
  * Various helper methods to simulate older versions of platform.
  */
 public class Config {
 
-    public static final String DEFAULT_RESOURCE_DIR = "/bars/v21/";
+    // each of these resource dirs must end in '/'
+    private static final String GINGERBREAD_DIR      = "/bars/v9/";
+    private static final String JELLYBEAN_DIR        = "/bars/v18/";
+    private static final String KITKAT_DIR           = "/bars/v19/";
+    private static final String DEFAULT_RESOURCE_DIR = "/bars/v21/";
+
+    private static final List<String> sDefaultResourceDir =
+            Collections.singletonList(DEFAULT_RESOURCE_DIR);
 
     public static boolean showOnScreenNavBar(int platformVersion) {
-        // return true if ICS or later.
-        return platformVersion >= 14 || platformVersion == 0;
+        return platformVersion == 0 || platformVersion >= ICE_CREAM_SANDWICH;
     }
 
     public static int getStatusBarColor(int platformVersion) {
         // return white for froyo and earlier; black otherwise.
-        return platformVersion >= 9 || platformVersion == 0 ? 0xFF000000 : 0xFFFFFFFF;
+        return platformVersion == 0 || platformVersion >= GINGERBREAD ? 0xFF000000 : 0xFFFFFFFF;
     }
 
-    public static boolean usesCustomResourceDir(int platformVersion) {
-        return platformVersion > 10 && platformVersion < 21;
-    }
-
-    public static String getResourceDir(int platformVersion) {
-        if (usesCustomResourceDir(platformVersion)) {
-            return "/bars/v11/";
+    public static List<String> getResourceDirs(int platformVersion) {
+        // Special case the most used scenario.
+        if (platformVersion == 0) {
+            return sDefaultResourceDir;
         }
-        return DEFAULT_RESOURCE_DIR;
+        List<String> list = new ArrayList<String>(4);
+        // Gingerbread - uses custom battery and wifi icons.
+        if (platformVersion <= GINGERBREAD) {
+            list.add(GINGERBREAD_DIR);
+        }
+        // ICS - JellyBean uses custom battery, wifi.
+        if (platformVersion <= JELLY_BEAN_MR2) {
+            list.add(JELLYBEAN_DIR);
+        }
+        // KitKat - uses custom wifi and nav icons.
+        if (platformVersion <= KITKAT) {
+            list.add(KITKAT_DIR);
+        }
+        list.add(DEFAULT_RESOURCE_DIR);
+
+        return Collections.unmodifiableList(list);
     }
 }
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 4da9f04..bed232ab 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
@@ -47,8 +47,6 @@
 import java.io.IOException;
 import java.io.InputStream;
 
-import static com.android.layoutlib.bridge.bars.Config.DEFAULT_RESOURCE_DIR;
-
 /**
  * Base "bar" class for the window decor around the the edited layout.
  * This is basically an horizontal layout that loads a given layout on creation (it is read
@@ -60,11 +58,6 @@
  */
 abstract class CustomBar extends LinearLayout {
 
-    // An upper-bound on the length of the path to the directory to find the icon in.
-    // This assumes that resource directory name for different api levels have same length.
-    private static final int ICON_PATH_LENGTH = DEFAULT_RESOURCE_DIR.length()
-            + LayoutDirection.RTL.getResourceValue().length() + 9;  // 9 = "-xxxhdpi/".length
-
 
     private final int mSimulatedPlatformVersion;
 
@@ -97,72 +90,6 @@
         }
     }
 
-    private InputStream getIcon(String iconName, Density[] densityInOut, LayoutDirection direction,
-            StringBuilder[] pathOut, boolean tryOtherDensities) {
-        pathOut[0] = new StringBuilder(ICON_PATH_LENGTH + iconName.length());
-
-        if (Config.usesCustomResourceDir(mSimulatedPlatformVersion)) {
-            // current density.
-            Density density = densityInOut[0];
-            InputStream stream = getIcon(iconName, Config.getResourceDir(mSimulatedPlatformVersion),
-                    densityInOut, direction, pathOut, tryOtherDensities);
-            if (stream != null) {
-                return stream;
-            }
-            // reset the density.
-            densityInOut[0] = density;
-        }
-        return getIcon(iconName, DEFAULT_RESOURCE_DIR, densityInOut, direction, pathOut,
-                tryOtherDensities);
-
-    }
-
-    private InputStream getIcon(String iconName, String dir, Density[] densityInOut,
-            LayoutDirection direction, StringBuilder[] pathOut, boolean tryOtherDensities) {
-        // current density
-        Density density = densityInOut[0];
-
-        pathOut[0].setLength(0);
-
-        // bitmap url relative to this class
-        if (direction == LayoutDirection.RTL) {
-            pathOut[0].append(dir)
-                    .append(direction.getResourceValue())
-                    .append('-')
-                    .append(density.getResourceValue())
-                    .append('/')
-                    .append(iconName);
-        } else {
-            // Since we do not have any ldltr resource, skip the check.
-            pathOut[0].append(dir)
-                    .append(density.getResourceValue())
-                    .append('/')
-                    .append(iconName);
-        }
-
-        InputStream stream = getClass().getResourceAsStream(pathOut[0].toString());
-        if (stream == null && tryOtherDensities) {
-            for (Density d : Density.values()) {
-                if (d != density) {
-                    densityInOut[0] = d;
-                    stream = getIcon(iconName, dir, densityInOut, direction, pathOut,
-                            false /*tryOtherDensities*/);
-                    if (stream != null) {
-                        return stream;
-                    }
-                }
-            }
-            // couldn't find resource with direction qualifier, try without.
-            if (direction == LayoutDirection.RTL) {
-                densityInOut[0] = density;
-                stream = getIcon(iconName, dir, densityInOut, null, pathOut,
-                        true /*tryOtherDensities*/);
-            }
-        }
-
-        return stream;
-    }
-
     protected void loadIcon(int index, String iconName, Density density) {
         loadIcon(index, iconName, density, false);
     }
@@ -172,15 +99,14 @@
         if (child instanceof ImageView) {
             ImageView imageView = (ImageView) child;
 
-            StringBuilder[] pathOut = new StringBuilder[1];
-            Density[] densityInOut = new Density[]{density};
             LayoutDirection dir = isRtl ? LayoutDirection.RTL : null;
-            InputStream stream = getIcon(iconName, densityInOut, dir, pathOut,
-                    true /*tryOtherDensities*/);
-            density = densityInOut[0];
-            String path = pathOut[0].toString();
+            IconLoader iconLoader = new IconLoader(iconName, density, mSimulatedPlatformVersion,
+                    dir);
+            InputStream stream = iconLoader.getIcon();
 
             if (stream != null) {
+                density = iconLoader.getDensity();
+                String path = iconLoader.getPath();
                 // look for a cached bitmap
                 Bitmap bitmap = Bridge.getCachedBitmap(path, true /*isFramework*/);
                 if (bitmap == null) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/IconLoader.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/IconLoader.java
new file mode 100644
index 0000000..9ab2e82
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/IconLoader.java
@@ -0,0 +1,125 @@
+/*
+ * 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.layoutlib.bridge.bars;
+
+import com.android.resources.Density;
+import com.android.resources.LayoutDirection;
+
+import java.io.InputStream;
+
+public class IconLoader {
+
+    private final String mIconName;
+    private final Density mDesiredDensity;
+    private final int mPlatformVersion;
+    private final LayoutDirection mDirection;
+
+    private Density mCurrentDensity;
+    private StringBuilder mCurrentPath;
+
+    IconLoader(String iconName, Density density, int platformVersion, LayoutDirection direction) {
+        mIconName = iconName;
+        mDesiredDensity = density;
+        mPlatformVersion = platformVersion;
+        mDirection = direction;
+        // An upper bound on the length of the path for the icon: /bars/v21/ldrtl-xxxhdpi/
+        final int iconPathLength = 24;
+        mCurrentPath = new StringBuilder(iconPathLength + iconName.length());
+    }
+
+    public InputStream getIcon() {
+        for (String resourceDir : Config.getResourceDirs(mPlatformVersion)) {
+            mCurrentDensity = null;
+            InputStream stream = getIcon(resourceDir);
+            if (stream != null) {
+                return stream;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Should only be called after {@link #getIcon()}. Returns the density of the icon, if found by
+     * {@code getIcon()}. If no icon was found, then the return value has no meaning.
+     */
+    public Density getDensity() {
+        return mCurrentDensity;
+    }
+
+    /**
+     * Should only be called after {@link #getIcon()}. Returns the path to the icon, if found by
+     * {@code getIcon()}. If no icon was found, then the return value has no meaning.
+     */
+    public String getPath() {
+        return mCurrentPath.toString();
+    }
+
+    /**
+     * Search for icon in the resource directory. This iterates over all densities.
+     * If a match is found, mCurrentDensity will be set to the icon's density.
+     */
+    private InputStream getIcon(String resourceDir) {
+        // First check for the desired density.
+        InputStream stream = getIcon(resourceDir, mDesiredDensity);
+        if (stream != null) {
+            mCurrentDensity = mDesiredDensity;
+            return stream;
+        }
+        // Didn't find in the desired density. Search in all.
+        for (Density density : Density.values()) {
+            if (density == mDesiredDensity) {
+                // Skip the desired density since it's already been checked.
+                continue;
+            }
+            stream = getIcon(resourceDir, density);
+            if (stream != null) {
+                mCurrentDensity = density;
+                return stream;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the icon for given density present in the given resource directory, taking layout
+     * direction into consideration.
+     */
+    private InputStream getIcon(String resourceDir, Density density) {
+        mCurrentPath.setLength(0);
+        // Currently we don't have any LTR only resources and hence the check is skipped. If they
+        // are ever added, change to:
+        // if (mDirection == LayoutDirection.RTL || mDirection == LayoutDirection.LTR) {
+        if (mDirection == LayoutDirection.RTL) {
+            mCurrentPath.append(resourceDir)
+                    .append(mDirection.getResourceValue())
+                    .append('-')
+                    .append(density.getResourceValue())
+                    .append('/')
+                    .append(mIconName);
+            InputStream stream = getClass().getResourceAsStream(mCurrentPath.toString());
+            if (stream != null) {
+                return stream;
+            }
+            mCurrentPath.setLength(0);
+        }
+        mCurrentPath.append(resourceDir)
+                .append(density.getResourceValue())
+                .append('/')
+                .append(mIconName);
+        return getClass().getResourceAsStream(mCurrentPath.toString());
+    }
+}
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 4cbdd4d..1795db9 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
@@ -42,7 +42,7 @@
         // We do know the order though.
         // 0 is the spacer
         loadIcon(1, "stat_sys_wifi_signal_4_fully.png", density);
-        loadIcon(2, "stat_sys_battery_charge_anim100.png", density);
+        loadIcon(2, "stat_sys_battery_100.png", density);
     }
 
     @Override